23#ifndef LFS_DO_NOT_USE_LARGE_FILE
26#define _FILE_OFFSET_BITS 64
34#define _WIN32_WINNT 0x600
37#ifndef LFS_DO_NOT_USE_LARGE_FILE
38#define _LARGEFILE64_SOURCE
53#include <sys/locking.h>
64#define LFS_MAXPATHLEN MAX_PATH
76#define LFS_MAXPATHLEN MAXPATHLEN
79#define LFS_MAXPATHLEN _POSIX_PATH_MAX
90#define LFS_VERSION "1.8.0"
91#define LFS_LIBNAME "lfs"
93#if LUA_VERSION_NUM >= 503
96#define luaL_optlong luaL_optinteger
101#if LUA_VERSION_NUM >= 502
102#define new_lib(L, l) (luaL_newlib(L, l))
104#define new_lib(L, l) (lua_newtable(L), luaL_register(L, NULL, l))
109#define strerror(_) "System unable to describe the error"
112#define DIR_METATABLE "directory metatable"
117 char pattern[MAX_PATH + 1];
123#define LOCK_METATABLE "lock metatable"
128#define lfs_setmode(file, m) (setmode(_fileno(file), m))
129#define STAT_STRUCT struct stati64
131#define lfs_setmode(file, m) (_setmode(_fileno(file), m))
132#define STAT_STRUCT struct _stati64
136#define _S_IFLNK 0x400
140#define S_ISDIR(mode) (mode&_S_IFDIR)
143#define S_ISREG(mode) (mode&_S_IFREG)
146#define S_ISLNK(mode) (mode&_S_IFLNK)
149#define S_ISSOCK(mode) (0)
152#define S_ISFIFO(mode) (0)
155#define S_ISCHR(mode) (mode&_S_IFCHR)
158#define S_ISBLK(mode) (0)
161#define STAT_FUNC _stati64
162#define LSTAT_FUNC lfs_win32_lstat
168#define lfs_setmode(file, m) ((void)file, (void)m, 0)
169#define STAT_STRUCT struct stat
170#define STAT_FUNC stat
171#define LSTAT_FUNC lstat
176#define lfs_mkdir _mkdir
178#define lfs_mkdir(path) (mkdir((path), \
179 S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH))
186 int en = GetLastError();
188 if (en == ERROR_FILE_EXISTS || en == ERROR_SHARING_VIOLATION)
195#define TICKS_PER_SECOND 10000000
196#define EPOCH_DIFFERENCE 11644473600LL
197time_t windowsToUnixTime(FILETIME ft)
200 uli.LowPart = ft.dwLowDateTime;
201 uli.HighPart = ft.dwHighDateTime;
202 return (time_t) (uli.QuadPart / TICKS_PER_SECOND - EPOCH_DIFFERENCE);
205int lfs_win32_lstat(
const char *path,
STAT_STRUCT * buffer)
207 WIN32_FILE_ATTRIBUTE_DATA win32buffer;
208 if (GetFileAttributesEx(path, GetFileExInfoStandard, &win32buffer)) {
209 if (!(win32buffer.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
212 buffer->st_mode = _S_IFLNK;
215 buffer->st_nlink = 0;
219 buffer->st_atime = windowsToUnixTime(win32buffer.ftLastAccessTime);
220 buffer->st_mtime = windowsToUnixTime(win32buffer.ftLastWriteTime);
221 buffer->st_ctime = windowsToUnixTime(win32buffer.ftCreationTime);
291 char *path2 =
realloc(path, size);
293 result =
pusherror(L,
"get_dir realloc() failed");
297 if (getcwd(path, size) !=
NULL) {
303 if (errno != ERANGE) {
304 result =
pusherror(L,
"get_dir getcwd() failed");
320#if LUA_VERSION_NUM == 501
327#elif LUA_VERSION_NUM >= 502 && LUA_VERSION_NUM <= 504
329 if (fh->closef == 0 || fh->f ==
NULL) {
335#error unsupported Lua version
344 const long start,
long len,
const char *
funcname)
380 fseek(fh, 0L, SEEK_END);
383 fseek(fh, start, SEEK_SET);
385 code = locking(fileno(fh), lkmode, len);
387 code = _locking(fileno(fh), lkmode, len);
404 f.l_whence = SEEK_SET;
405 f.l_start = (off_t) start;
406 f.l_len = (off_t) len;
407 code = fcntl(fileno(fh), F_SETLK, &f);
422 const char *lockfile =
"/lockfile.lfs";
424 ln = (
char *)
malloc(pathl + strlen(lockfile) + 1);
431 strcat(ln, lockfile);
432 fd = CreateFile(ln, GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS,
433 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
NULL);
435 if (fd == INVALID_HANDLE_VALUE) {
436 return lfs_win32_pusherror(L);
448 if (lock->fd != INVALID_HANDLE_VALUE) {
449 CloseHandle(lock->fd);
450 lock->fd = INVALID_HANDLE_VALUE;
463 const char *lockfile =
"/lockfile.lfs";
466 ln = (
char *)
malloc(pathl + strlen(lockfile) + 1);
473 strcat(ln, lockfile);
474 if (symlink(
"lock", ln) == -1) {
501 static const char *
const modenames[] = {
"binary",
"text",
NULL };
507 for (i = 0; modenames[i] !=
NULL; i++) {
508 if (mode[i] == res) {
538 if (
_file_lock(L, fh, mode, start, len,
"lock")) {
560 if (
_file_lock(L, fh,
"u", start, len,
"unlock")) {
590 if (
STAT_FUNC(oldpath, &oldpathinfo) == 0) {
591 is_dir = S_ISDIR(oldpathinfo.st_mode) != 0;
593 if (!symbolic && is_dir) {
596 "hard links to directories are not supported on Windows");
600 int result = symbolic ? CreateSymbolicLink(newpath, oldpath, is_dir)
601 : CreateHardLink(newpath, oldpath,
NULL);
607 lua_pushstring(L, symbolic ?
"make_link CreateSymbolicLink() failed"
608 :
"make_link CreateHardLink() failed");
643 struct _finddata_t c_file;
645 struct dirent *entry;
650 if (d->hFile == 0L) {
651 if ((d->hFile = _findfirst(d->pattern, &c_file)) == -1L) {
661 if (_findnext(d->hFile, &c_file) == -1L) {
663 _findclose(d->hFile);
672 if ((entry = readdir(d->
dir)) !=
NULL) {
692 if (!d->
closed && d->hFile) {
693 _findclose(d->hFile);
719 if (strlen(path) > MAX_PATH - 2)
722 sprintf(d->pattern,
"%s/*", path);
724 d->
dir = opendir(path);
726 luaL_error(L,
"cannot open %s: %s", path, strerror(errno));
728#if LUA_VERSION_NUM >= 504
757#if LUA_VERSION_NUM >= 504
797 else if (S_ISDIR(mode))
799 else if (S_ISLNK(mode))
801 else if (S_ISSOCK(mode))
803 else if (S_ISFIFO(mode))
805 else if (S_ISCHR(mode))
806 return "char device";
807 else if (S_ISBLK(mode))
808 return "block device";
823 struct utimbuf utb, *buf;
924 static char perms[10] =
"---------";
926 for (i = 0; i < 9; i++)
928 if (mode & _S_IREAD) {
933 if (mode & _S_IWRITE) {
938 if (mode & _S_IEXEC) {
948 static char perms[10] =
"---------";
950 for (i = 0; i < 9; i++)
1017 if (st(file, &info)) {
1020 file, strerror(errno));
1034 return luaL_error(L,
"invalid attribute name '%s'", member);
1070 HANDLE h = CreateFile(file, GENERIC_READ,
1071 FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
1072 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL);
1073 if (h == INVALID_HANDLE_VALUE) {
1074 return lfs_win32_pusherror(L);
1077 char *target =
NULL;
1078 int tsize, size = 256;
1081 char *target2 =
realloc(target, size);
1087 tsize = GetFinalPathNameByHandle(h, target, size, FILE_NAME_OPENED);
1089 tsize = readlink(file, target, size);
1096 if (tsize > 4 && strncmp(target,
"\\\\?\\", 4) == 0) {
1097 memmove_s(target, tsize - 3, target + 4, tsize - 3);
1108 target[tsize] =
'\0';
1126 return ok ? 1 :
pusherror(L,
"could not obtain link target");
1147 "LuaFileSystem is a Lua library developed to complement "
1148 "the set of functions related to file systems offered by "
1149 "the standard Lua distribution");
CURL_EXTERN int void * arg
static int remove_dir(lua_State *L)
static void push_st_size(lua_State *L, STAT_STRUCT *info)
static void push_st_mode(lua_State *L, STAT_STRUCT *info)
static int _file_info_(lua_State *L, int(*st)(const char *, STAT_STRUCT *))
static void push_st_blksize(lua_State *L, STAT_STRUCT *info)
static int pusherror(lua_State *L, const char *info)
static int lfs_f_setmode(lua_State *L)
void(* _push_function)(lua_State *L, STAT_STRUCT *info)
static int file_lock(lua_State *L)
static int make_link(lua_State *L)
static int pushresult(lua_State *L, int res, const char *info)
static int change_dir(lua_State *L)
static int file_utime(lua_State *L)
static int dir_create_meta(lua_State *L)
static const struct luaL_Reg fslib[]
static void push_st_rdev(lua_State *L, STAT_STRUCT *info)
static int file_info(lua_State *L)
static FILE * check_file(lua_State *L, int idx, const char *funcname)
LFS_EXPORT int luaopen_lfs(lua_State *L)
static int lock_create_meta(lua_State *L)
static void push_st_blocks(lua_State *L, STAT_STRUCT *info)
static void push_st_perm(lua_State *L, STAT_STRUCT *info)
static void push_st_dev(lua_State *L, STAT_STRUCT *info)
static int push_link_target(lua_State *L)
static int link_info(lua_State *L)
static void set_info(lua_State *L)
static int lfs_lock_dir(lua_State *L)
static int get_dir(lua_State *L)
static void push_st_ctime(lua_State *L, STAT_STRUCT *info)
#define lfs_setmode(file, m)
static int dir_iter_factory(lua_State *L)
static const char * perm2string(mode_t mode)
static const char * mode2string(mode_t mode)
static void push_st_atime(lua_State *L, STAT_STRUCT *info)
static int dir_close(lua_State *L)
static void push_st_uid(lua_State *L, STAT_STRUCT *info)
static void push_st_mtime(lua_State *L, STAT_STRUCT *info)
static void push_st_nlink(lua_State *L, STAT_STRUCT *info)
static int lfs_unlock_dir(lua_State *L)
struct _stat_members members[]
static void push_st_ino(lua_State *L, STAT_STRUCT *info)
static int dir_iter(lua_State *L)
static int lfs_g_setmode(lua_State *L, FILE *f, int arg)
static int file_unlock(lua_State *L)
static void push_st_gid(lua_State *L, STAT_STRUCT *info)
static int make_dir(lua_State *L)
static int _file_lock(lua_State *L, FILE *fh, const char *mode, const long start, long len, const char *funcname)
LUA_API void lua_pushstring(lua_State *L, const char *s)
LUA_API int lua_setmetatable(lua_State *L, int objindex)
LUA_API void lua_pushnil(lua_State *L)
LUA_API const char * lua_pushfstring(lua_State *L, const char *fmt,...)
LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
LUA_API int lua_toboolean(lua_State *L, int idx)
LUA_API void lua_pushboolean(lua_State *L, int b)
LUA_API void lua_pushvalue(lua_State *L, int idx)
LUA_API int lua_type(lua_State *L, int idx)
LUA_API int lua_isstring(lua_State *L, int idx)
LUA_API void * lua_touserdata(lua_State *L, int idx)
LUA_API void lua_pushlstring(lua_State *L, const char *s, size_t len)
LUA_API void lua_settop(lua_State *L, int idx)
LUA_API void lua_pushinteger(lua_State *L, lua_Integer n)
LUA_API void lua_rawset(lua_State *L, int idx)
LUA_API int lua_gettop(lua_State *L)
LUALIB_API int luaL_newmetatable(lua_State *L, const char *tname)
LUALIB_API void * luaL_checkudata(lua_State *L, int ud, const char *tname)
LUALIB_API lua_Number luaL_optnumber(lua_State *L, int narg, lua_Number def)
LUALIB_API int luaL_error(lua_State *L, const char *fmt,...)
LUALIB_API lua_Integer luaL_optinteger(lua_State *L, int narg, lua_Integer def)
LUALIB_API const char * luaL_checklstring(lua_State *L, int narg, size_t *len)
LUALIB_API int luaL_checkoption(lua_State *L, int narg, const char *def, const char *const lst[])
#define luaL_getmetatable(L, n)
#define luaL_checkstring(L, n)
#define luaL_argcheck(L, cond, numarg, extramsg)
static int funcname(LexState *ls, expdesc *v)
#define lua_istable(L, n)
#define lua_pushcfunction(L, f)
#define lua_pushliteral(L, s)
#define lua_setglobal(L, s)
#define lua_tostring(L, i)
#define lua_newuserdata(L, s)