aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2020-04-20 22:51:39 -0300
committerHisham Muhammad <hisham@gobolinux.org>2020-04-21 13:45:50 -0300
commit94700f7c18c90455f9b627b69f93c94f773a972e (patch)
treeaa96c6cdc534cb8fcc55df7a50324a623fe0f8e5
parent53d2acc5173e20a843d26d88ffa4767b01868e02 (diff)
downloadluafilesystem-94700f7c18c90455f9b627b69f93c94f773a972e.tar.gz
luafilesystem-94700f7c18c90455f9b627b69f93c94f773a972e.tar.bz2
luafilesystem-94700f7c18c90455f9b627b69f93c94f773a972e.zip
win32: obtain symlink attributes
-rw-r--r--src/lfs.c104
1 files changed, 78 insertions, 26 deletions
diff --git a/src/lfs.c b/src/lfs.c
index ac63947..65a708f 100644
--- a/src/lfs.c
+++ b/src/lfs.c
@@ -121,7 +121,6 @@ typedef struct dir_data {
121 #define lfs_setmode(file, m) (_setmode(_fileno(file), m)) 121 #define lfs_setmode(file, m) (_setmode(_fileno(file), m))
122 #define STAT_STRUCT struct _stati64 122 #define STAT_STRUCT struct _stati64
123 #endif 123 #endif
124
125 #ifndef _S_IFLNK 124 #ifndef _S_IFLNK
126 #define _S_IFLNK 0x400 125 #define _S_IFLNK 0x400
127 #endif 126 #endif
@@ -166,6 +165,51 @@ typedef struct dir_data {
166 S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH)) 165 S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH))
167#endif 166#endif
168 167
168#ifdef _WIN32
169
170int lfs_win32_pusherror(lua_State *L)
171{
172 int en = GetLastError();
173 lua_pushnil(L);
174 if(en == ERROR_FILE_EXISTS || en == ERROR_SHARING_VIOLATION)
175 lua_pushstring(L, "File exists");
176 else
177 lua_pushstring(L, strerror(en));
178 return 2;
179}
180
181#define TICKS_PER_SECOND 10000000
182#define EPOCH_DIFFERENCE 11644473600LL
183time_t windowsToUnixTime(FILETIME ft)
184{
185 ULARGE_INTEGER uli;
186 uli.LowPart = ft.dwLowDateTime;
187 uli.HighPart = ft.dwHighDateTime;
188 return (time_t)(uli.QuadPart / TICKS_PER_SECOND - EPOCH_DIFFERENCE);
189}
190
191int lfs_win32_lstat(const char *path, STAT_STRUCT *buffer)
192{
193 WIN32_FILE_ATTRIBUTE_DATA win32buffer;
194 if (GetFileAttributesEx(path, GetFileExInfoStandard, &win32buffer)) {
195 buffer->st_mode = _S_IFLNK;
196 buffer->st_dev = 0;
197 buffer->st_ino = 0;
198 buffer->st_nlink = 0;
199 buffer->st_uid = 0;
200 buffer->st_gid = 0;
201 buffer->st_rdev = 0;
202 buffer->st_atime = windowsToUnixTime(win32buffer.ftLastAccessTime);
203 buffer->st_mtime = windowsToUnixTime(win32buffer.ftLastWriteTime);
204 buffer->st_ctime = windowsToUnixTime(win32buffer.ftCreationTime);
205 buffer->st_size = 0;
206 return 0;
207 } else {
208 return 1;
209 }
210}
211#endif
212
169/* 213/*
170** Utility functions 214** Utility functions
171*/ 215*/
@@ -335,17 +379,12 @@ static int lfs_lock_dir(lua_State *L) {
335 lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; 379 lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
336 } 380 }
337 strcpy(ln, path); strcat(ln, lockfile); 381 strcpy(ln, path); strcat(ln, lockfile);
338 if((fd = CreateFile(ln, GENERIC_WRITE, 0, NULL, CREATE_NEW, 382 fd = CreateFile(ln, GENERIC_WRITE, 0, NULL, CREATE_NEW,
339 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL)) == INVALID_HANDLE_VALUE) { 383 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
340 int en = GetLastError();
341 free(ln); lua_pushnil(L);
342 if(en == ERROR_FILE_EXISTS || en == ERROR_SHARING_VIOLATION)
343 lua_pushstring(L, "File exists");
344 else
345 lua_pushstring(L, strerror(en));
346 return 2;
347 }
348 free(ln); 384 free(ln);
385 if(fd == INVALID_HANDLE_VALUE) {
386 return lfs_win32_pusherror(L);
387 }
349 lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock)); 388 lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock));
350 lock->fd = fd; 389 lock->fd = fd;
351 luaL_getmetatable (L, LOCK_METATABLE); 390 luaL_getmetatable (L, LOCK_METATABLE);
@@ -884,35 +923,48 @@ static int file_info (lua_State *L) {
884** 0 on failure (with stack unchanged, and errno set). 923** 0 on failure (with stack unchanged, and errno set).
885*/ 924*/
886static int push_link_target(lua_State *L) { 925static int push_link_target(lua_State *L) {
887#ifdef _WIN32
888 errno = ENOSYS;
889 return 0;
890#else
891 const char *file = luaL_checkstring(L, 1); 926 const char *file = luaL_checkstring(L, 1);
927#ifdef _WIN32
928 HANDLE h = CreateFile(file, GENERIC_READ,
929 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
930 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
931 if (h == INVALID_HANDLE_VALUE) {
932 return lfs_win32_pusherror(L);
933 }
934#endif
892 char *target = NULL; 935 char *target = NULL;
893 int tsize, size = 256; /* size = initial buffer capacity */ 936 int tsize, size = 256; /* size = initial buffer capacity */
894 while (1) { 937 int ok = 0;
938 while (!ok) {
895 char* target2 = realloc(target, size); 939 char* target2 = realloc(target, size);
896 if (!target2) { /* failed to allocate */ 940 if (!target2) { /* failed to allocate */
897 free(target); 941 break;
898 return 0;
899 } 942 }
900 target = target2; 943 target = target2;
944#ifdef _WIN32
945 tsize = GetFinalPathNameByHandle(h, target, size, FILE_NAME_OPENED);
946#else
901 tsize = readlink(file, target, size); 947 tsize = readlink(file, target, size);
948#endif
902 if (tsize < 0) { /* a readlink() error occurred */ 949 if (tsize < 0) { /* a readlink() error occurred */
903 free(target); 950 break;
904 return 0; 951 }
952 if (tsize < size) {
953 ok = 1;
954 break;
905 } 955 }
906 if (tsize < size)
907 break;
908 /* possibly truncated readlink() result, double size and retry */ 956 /* possibly truncated readlink() result, double size and retry */
909 size *= 2; 957 size *= 2;
910 } 958 }
911 target[tsize] = '\0'; 959 if (ok) {
912 lua_pushlstring(L, target, tsize); 960 target[tsize] = '\0';
913 free(target); 961 lua_pushlstring(L, target, tsize);
914 return 1; 962 }
963#ifdef _WIN32
964 CloseHandle(h);
915#endif 965#endif
966 free(target);
967 return ok;
916} 968}
917 969
918/* 970/*