mirror of
https://github.com/lunarmodules/luafilesystem.git
synced 2026-07-22 02:53:06 +00:00
win32: obtain symlink attributes
This commit is contained in:
104
src/lfs.c
104
src/lfs.c
@@ -121,7 +121,6 @@ typedef struct dir_data {
|
|||||||
#define lfs_setmode(file, m) (_setmode(_fileno(file), m))
|
#define lfs_setmode(file, m) (_setmode(_fileno(file), m))
|
||||||
#define STAT_STRUCT struct _stati64
|
#define STAT_STRUCT struct _stati64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _S_IFLNK
|
#ifndef _S_IFLNK
|
||||||
#define _S_IFLNK 0x400
|
#define _S_IFLNK 0x400
|
||||||
#endif
|
#endif
|
||||||
@@ -166,6 +165,51 @@ typedef struct dir_data {
|
|||||||
S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH))
|
S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
int lfs_win32_pusherror(lua_State *L)
|
||||||
|
{
|
||||||
|
int en = GetLastError();
|
||||||
|
lua_pushnil(L);
|
||||||
|
if(en == ERROR_FILE_EXISTS || en == ERROR_SHARING_VIOLATION)
|
||||||
|
lua_pushstring(L, "File exists");
|
||||||
|
else
|
||||||
|
lua_pushstring(L, strerror(en));
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TICKS_PER_SECOND 10000000
|
||||||
|
#define EPOCH_DIFFERENCE 11644473600LL
|
||||||
|
time_t windowsToUnixTime(FILETIME ft)
|
||||||
|
{
|
||||||
|
ULARGE_INTEGER uli;
|
||||||
|
uli.LowPart = ft.dwLowDateTime;
|
||||||
|
uli.HighPart = ft.dwHighDateTime;
|
||||||
|
return (time_t)(uli.QuadPart / TICKS_PER_SECOND - EPOCH_DIFFERENCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lfs_win32_lstat(const char *path, STAT_STRUCT *buffer)
|
||||||
|
{
|
||||||
|
WIN32_FILE_ATTRIBUTE_DATA win32buffer;
|
||||||
|
if (GetFileAttributesEx(path, GetFileExInfoStandard, &win32buffer)) {
|
||||||
|
buffer->st_mode = _S_IFLNK;
|
||||||
|
buffer->st_dev = 0;
|
||||||
|
buffer->st_ino = 0;
|
||||||
|
buffer->st_nlink = 0;
|
||||||
|
buffer->st_uid = 0;
|
||||||
|
buffer->st_gid = 0;
|
||||||
|
buffer->st_rdev = 0;
|
||||||
|
buffer->st_atime = windowsToUnixTime(win32buffer.ftLastAccessTime);
|
||||||
|
buffer->st_mtime = windowsToUnixTime(win32buffer.ftLastWriteTime);
|
||||||
|
buffer->st_ctime = windowsToUnixTime(win32buffer.ftCreationTime);
|
||||||
|
buffer->st_size = 0;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Utility functions
|
** Utility functions
|
||||||
*/
|
*/
|
||||||
@@ -335,17 +379,12 @@ static int lfs_lock_dir(lua_State *L) {
|
|||||||
lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
|
lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
|
||||||
}
|
}
|
||||||
strcpy(ln, path); strcat(ln, lockfile);
|
strcpy(ln, path); strcat(ln, lockfile);
|
||||||
if((fd = CreateFile(ln, GENERIC_WRITE, 0, NULL, CREATE_NEW,
|
fd = CreateFile(ln, GENERIC_WRITE, 0, NULL, CREATE_NEW,
|
||||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL)) == INVALID_HANDLE_VALUE) {
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
|
||||||
int en = GetLastError();
|
|
||||||
free(ln); lua_pushnil(L);
|
|
||||||
if(en == ERROR_FILE_EXISTS || en == ERROR_SHARING_VIOLATION)
|
|
||||||
lua_pushstring(L, "File exists");
|
|
||||||
else
|
|
||||||
lua_pushstring(L, strerror(en));
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
free(ln);
|
free(ln);
|
||||||
|
if(fd == INVALID_HANDLE_VALUE) {
|
||||||
|
return lfs_win32_pusherror(L);
|
||||||
|
}
|
||||||
lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock));
|
lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock));
|
||||||
lock->fd = fd;
|
lock->fd = fd;
|
||||||
luaL_getmetatable (L, LOCK_METATABLE);
|
luaL_getmetatable (L, LOCK_METATABLE);
|
||||||
@@ -884,35 +923,48 @@ static int file_info (lua_State *L) {
|
|||||||
** 0 on failure (with stack unchanged, and errno set).
|
** 0 on failure (with stack unchanged, and errno set).
|
||||||
*/
|
*/
|
||||||
static int push_link_target(lua_State *L) {
|
static int push_link_target(lua_State *L) {
|
||||||
#ifdef _WIN32
|
|
||||||
errno = ENOSYS;
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
const char *file = luaL_checkstring(L, 1);
|
const char *file = luaL_checkstring(L, 1);
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE h = CreateFile(file, GENERIC_READ,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (h == INVALID_HANDLE_VALUE) {
|
||||||
|
return lfs_win32_pusherror(L);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
char *target = NULL;
|
char *target = NULL;
|
||||||
int tsize, size = 256; /* size = initial buffer capacity */
|
int tsize, size = 256; /* size = initial buffer capacity */
|
||||||
while (1) {
|
int ok = 0;
|
||||||
|
while (!ok) {
|
||||||
char* target2 = realloc(target, size);
|
char* target2 = realloc(target, size);
|
||||||
if (!target2) { /* failed to allocate */
|
if (!target2) { /* failed to allocate */
|
||||||
free(target);
|
break;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
target = target2;
|
target = target2;
|
||||||
|
#ifdef _WIN32
|
||||||
|
tsize = GetFinalPathNameByHandle(h, target, size, FILE_NAME_OPENED);
|
||||||
|
#else
|
||||||
tsize = readlink(file, target, size);
|
tsize = readlink(file, target, size);
|
||||||
|
#endif
|
||||||
if (tsize < 0) { /* a readlink() error occurred */
|
if (tsize < 0) { /* a readlink() error occurred */
|
||||||
free(target);
|
break;
|
||||||
return 0;
|
}
|
||||||
|
if (tsize < size) {
|
||||||
|
ok = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (tsize < size)
|
|
||||||
break;
|
|
||||||
/* possibly truncated readlink() result, double size and retry */
|
/* possibly truncated readlink() result, double size and retry */
|
||||||
size *= 2;
|
size *= 2;
|
||||||
}
|
}
|
||||||
target[tsize] = '\0';
|
if (ok) {
|
||||||
lua_pushlstring(L, target, tsize);
|
target[tsize] = '\0';
|
||||||
free(target);
|
lua_pushlstring(L, target, tsize);
|
||||||
return 1;
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
CloseHandle(h);
|
||||||
#endif
|
#endif
|
||||||
|
free(target);
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user