/* * Arguments: path (string) * Returns: [boolean] */ static int sys_rmdir (lua_State *L) { const char *path = luaL_checkstring(L, 1); int res; #ifndef _WIN32 sys_vm_leave(L); res = rmdir(path); sys_vm_enter(L); #else { void *os_path = utf8_to_filename(path); if (!os_path) return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); sys_vm_leave(L); res = is_WinNT ? !RemoveDirectoryW(os_path) : !RemoveDirectoryA(os_path); free(os_path); sys_vm_enter(L); } #endif if (!res) { lua_pushboolean(L, 1); return 1; } return sys_seterror(L, 0); }
EVQ_API int evq_add_dirwatch (struct event_queue *evq, struct event *ev, const char *path) { const DWORD flags = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SECURITY; const unsigned int filter = (ev->flags >> EVENT_EOF_SHIFT_RES) ? FILE_NOTIFY_CHANGE_LAST_WRITE : flags; HANDLE fd; ev->flags &= ~EVENT_EOF_MASK_RES; { void *os_path = utf8_to_filename(path); if (!os_path) return -1; fd = is_WinNT ? FindFirstChangeNotificationW(os_path, FALSE, filter) : FindFirstChangeNotificationA(os_path, FALSE, filter); free(os_path); } if (fd == NULL || fd == INVALID_HANDLE_VALUE) return -1; ev->fd = fd; return evq_add(evq, ev); }
/* * Arguments: path (string), [permissions (number)] * Returns: [boolean] */ static int sys_mkdir (lua_State *L) { const char *path = luaL_checkstring(L, 1); int res; #ifndef _WIN32 mode_t perm = (mode_t) lua_tointeger(L, 2); sys_vm_leave(L); res = mkdir(path, perm); sys_vm_enter(L); #else { void *os_path = utf8_to_filename(path); if (!os_path) return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); sys_vm_leave(L); res = is_WinNT ? !CreateDirectoryW(os_path, NULL) : !CreateDirectoryA(os_path, NULL); free(os_path); sys_vm_enter(L); } #endif if (!res) { lua_pushboolean(L, 1); return 1; } return sys_seterror(L, 0); }
/* * Arguments: [path (string)] * Returns: [boolean | pathname (string)] */ static int sys_curdir (lua_State *L) { const char *path = lua_tostring(L, 1); if (path) { int res; #ifndef _WIN32 res = chdir(path); #else { void *os_path = utf8_to_filename(path); if (!os_path) return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); res = is_WinNT ? !SetCurrentDirectoryW(os_path) : !SetCurrentDirectoryA(os_path); free(os_path); } #endif if (!res) { lua_pushboolean(L, 1); return 1; } } else { #ifndef _WIN32 char dir[MAX_PATHNAME]; if (getcwd(dir, MAX_PATHNAME)) { lua_pushstring(L, dir); return 1; } #else WCHAR os_dir[MAX_PATHNAME]; const int n = is_WinNT ? GetCurrentDirectoryW(MAX_PATHNAME, os_dir) : GetCurrentDirectoryA(MAX_PATHNAME, (char *) os_dir); if (n != 0 && n < MAX_PATHNAME) { void *dir = filename_to_utf8(os_dir); if (!dir) return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); lua_pushstring(L, dir); free(dir); return 1; } #endif } return sys_seterror(L, 0); }
/* * Arguments: path (string) * Returns: [total_bytes (number), available_bytes (number), * free_bytes (number)] */ static int sys_statfs (lua_State *L) { const char *path = luaL_checkstring(L, 1); int64_t ntotal, navail, nfree; int res; #ifndef _WIN32 struct statvfs buf; sys_vm_leave(L); res = statvfs(path, &buf); sys_vm_enter(L); ntotal = buf.f_blocks * buf.f_frsize; nfree = buf.f_bfree * buf.f_bsize; navail = buf.f_bavail * buf.f_bsize; #else ULARGE_INTEGER na, nt, nf; SetErrorMode(SEM_FAILCRITICALERRORS); /* for floppy disks */ { void *os_path = utf8_to_filename(path); if (!os_path) return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); sys_vm_leave(L); res = is_WinNT ? !GetDiskFreeSpaceExW(os_path, &na, &nt, &nf) : !GetDiskFreeSpaceExA(os_path, &na, &nt, &nf); free(os_path); sys_vm_enter(L); } ntotal = (int64_t) nt.QuadPart; nfree = (int64_t) nf.QuadPart; navail = (int64_t) na.QuadPart; #endif if (!res) { lua_pushnumber(L, (lua_Number) ntotal); lua_pushnumber(L, (lua_Number) navail); lua_pushnumber(L, (lua_Number) nfree); return 3; } return sys_seterror(L, 0); }
/* * Arguments: fd_udata, path (string), [permissions (number)] * Returns: [fd_udata] */ static int sys_create (lua_State *L) { fd_t fd, *fdp = checkudata(L, 1, FD_TYPENAME); const char *path = luaL_checkstring(L, 2); #ifndef _WIN32 mode_t perm = (mode_t) luaL_optinteger(L, 3, SYS_FILE_PERMISSIONS); #endif #ifndef _WIN32 sys_vm_leave(L); fd = creat(path, perm); sys_vm_enter(L); #else { const int flags = GENERIC_WRITE; const DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; const DWORD creation = CREATE_ALWAYS; const DWORD attr = FILE_ATTRIBUTE_NORMAL | SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION; void *os_path = utf8_to_filename(path); if (!os_path) return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); sys_vm_leave(L); fd = is_WinNT ? CreateFileW(os_path, flags, share, NULL, creation, attr, NULL) : CreateFileA(os_path, flags, share, NULL, creation, attr, NULL); free(os_path); sys_vm_enter(L); } #endif if (fd != (fd_t) -1) { *fdp = fd; lua_settop(L, 1); return 1; } return sys_seterror(L, 0); }
/* * Arguments: path (string) * Returns: [string] */ static int sys_realpath (lua_State *L) { const char *path = luaL_checkstring(L, 1); #ifndef _WIN32 char real[PATH_MAX]; if (realpath(path, real)) { lua_pushstring(L, real); return 1; } #else void *os_path = utf8_to_filename(path); if (!os_path) return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); { WCHAR os_real[MAX_PATHNAME]; const int n = is_WinNT ? GetFullPathNameW(os_path, MAX_PATHNAME, os_real, NULL) : GetFullPathNameA(os_path, MAX_PATHNAME, (char *) os_real, NULL); free(os_path); if (n != 0 && n < MAX_PATHNAME) { void *real = filename_to_utf8(os_real); if (!real) return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); lua_pushstring(L, real); free(real); return 1; } } #endif return sys_seterror(L, 0); }
/* * Arguments: existing_path (string), new_path (string) * Returns: [boolean] */ static int sys_rename (lua_State *L) { const char *old = luaL_checkstring(L, 1); const char *new = luaL_checkstring(L, 2); int res; #ifndef _WIN32 sys_vm_leave(L); res = rename(old, new); sys_vm_enter(L); #else { void *os_old = utf8_to_filename(old); void *os_new = utf8_to_filename(new); if (!os_old || !os_new) { free(os_old); free(os_new); return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); } sys_vm_leave(L); res = is_WinNT ? !MoveFileW(os_old, os_new) : !MoveFileA(os_old, os_new); free(os_old); free(os_new); sys_vm_enter(L); } #endif if (!res) { lua_pushboolean(L, 1); return 1; } return sys_seterror(L, 0); }
/* * Arguments: ..., directory (string) */ static int sys_dir_open (lua_State *L, const int idx, struct dir *dp) { const char *dir = luaL_checkstring(L, idx); #ifndef _WIN32 if (dp->data) closedir(dp->data); sys_vm_leave(L); dp->data = opendir(*dir == '\0' ? "/" : dir); sys_vm_enter(L); if (dp->data) return 1; #else char *filename = (char *) dp->data.cFileName; if (*dir == '\0' || (*dir == '/' && dir[1] == '\0')) { /* list drive letters */ *filename++ = 'A' - 1; *filename++ = ':'; *filename++ = '\\'; *filename = '\0'; dp->is_root = 1; return 1; } else { const int len = lua_rawlen(L, idx); /* build search path */ if (len >= MAX_PATH - 2) /* concat "\\*" */ return 0; memcpy(filename, dir, len); filename += len - 1; if (*filename != '\\' && *filename != '/') *(++filename) = '\\'; *(++filename) = '*'; *(++filename) = '\0'; if (dp->h != INVALID_HANDLE_VALUE) FindClose(dp->h); { void *os_path = utf8_to_filename((char *) dp->data.cFileName); if (!os_path) return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); sys_vm_leave(L); dp->h = is_WinNT ? FindFirstFileW(os_path, &dp->data) : FindFirstFileA(os_path, (WIN32_FIND_DATAA *) &dp->data); free(os_path); sys_vm_enter(L); } if (dp->h != INVALID_HANDLE_VALUE) { dp->is_root = 0; return 1; } } #endif return sys_seterror(L, 0); }
/* * Arguments: path (string), [more_info (boolean)] * Returns: [is_directory (boolean), is_file (boolean), * is_read (boolean), is_write (boolean), is_execute (boolean), * [is_link (boolean), size (number), * access_time (number), modify_time (number), create_time (number)]] */ static int sys_stat (lua_State *L) { const char *path = luaL_checkstring(L, 1); const int more_info = lua_toboolean(L, 2); #ifndef _WIN32 struct stat st; #else struct _stat st; #endif int res; sys_vm_leave(L); #ifndef _WIN32 res = stat(path, &st); #else { void *os_path = utf8_to_filename(path); if (!os_path) return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); res = is_WinNT ? _wstat(os_path, &st) : _stat(os_path, &st); free(os_path); } #endif sys_vm_enter(L); if (!res) { /* is directory? */ lua_pushboolean(L, #ifndef _WIN32 S_ISDIR(st.st_mode) #else st.st_mode & _S_IFDIR #endif ); /* is regular file? */ lua_pushboolean(L, #ifndef _WIN32 S_ISREG(st.st_mode) #else st.st_mode & _S_IFREG #endif ); /* can anyone read from file? */ lua_pushboolean(L, #ifndef _WIN32 st.st_mode & (S_IRUSR | S_IRGRP | S_IROTH) #else st.st_mode & _S_IREAD #endif ); /* can anyone write to file? */ lua_pushboolean(L, #ifndef _WIN32 st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH) #else st.st_mode & _S_IWRITE #endif ); /* can anyone execute the file? */ lua_pushboolean(L, #ifndef _WIN32 st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH) #else st.st_mode & _S_IEXEC #endif ); if (more_info) { /* is link? */ #ifndef _WIN32 lua_pushboolean(L, S_ISLNK(st.st_mode)); #else DWORD attr; { void *os_path = utf8_to_filename(path); if (!os_path) return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); attr = is_WinNT ? GetFileAttributesW(os_path) : GetFileAttributesA(os_path); free(os_path); } lua_pushboolean(L, attr > 0 && (attr & FILE_ATTRIBUTE_REPARSE_POINT)); #endif lua_pushnumber(L, (lua_Number) st.st_size); /* size in bytes */ lua_pushnumber(L, (lua_Number) st.st_atime); /* access time */ lua_pushnumber(L, (lua_Number) st.st_mtime); /* modification time */ lua_pushnumber(L, (lua_Number) st.st_ctime); /* creation time */ return 10; } return 5; } return sys_seterror(L, 0); }
/* * Arguments: fd_udata, path (string), [mode (string: "r", "w", "rw"), * permissions (number), options (string) ...] * Returns: [fd_udata] */ static int sys_open (lua_State *L) { fd_t fd, *fdp = checkudata(L, 1, FD_TYPENAME); const char *path = luaL_checkstring(L, 2); const char *mode = lua_tostring(L, 3); #ifndef _WIN32 mode_t perm = (mode_t) luaL_optinteger(L, 4, SYS_FILE_PERMISSIONS); #else int append = 0; #endif int flags = O_RDONLY, i; #undef OPT_START #define OPT_START 5 if (mode) { switch (mode[0]) { case 'w': flags = O_WRONLY; break; case 'r': if (mode[1] == 'w') flags = O_RDWR; } } #ifndef _WIN32 for (i = lua_gettop(L); i >= OPT_START; --i) { flags |= fdopt_flags[luaL_checkoption(L, i, NULL, fdopt_names)]; } sys_vm_leave(); fd = open(path, flags, perm); sys_vm_enter(); #else { DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE; DWORD creation = OPEN_EXISTING; DWORD attr = FILE_ATTRIBUTE_NORMAL | SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION; for (i = lua_gettop(L); i >= OPT_START; --i) { const char *opt = lua_tostring(L, i); if (opt) switch (opt[0]) { case 'a': /* append */ append = 1; break; case 'c': /* creat */ creation &= ~OPEN_EXISTING; creation |= CREATE_ALWAYS; break; case 'e': /* excl */ share = 0; break; case 'r': /* random */ attr |= FILE_FLAG_RANDOM_ACCESS; break; case 's': /* sync */ attr |= FILE_FLAG_WRITE_THROUGH; break; case 't': /* trunc */ creation &= ~OPEN_EXISTING; creation |= TRUNCATE_EXISTING; break; } } { void *os_path = utf8_to_filename(path); if (!os_path) return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); sys_vm_leave(); fd = is_WinNT ? CreateFileW(os_path, flags, share, NULL, creation, attr, NULL) : CreateFileA(os_path, flags, share, NULL, creation, attr, NULL); free(os_path); sys_vm_enter(); } } #endif if (fd != (fd_t) -1) { *fdp = fd; #ifdef _WIN32 if (append) { LONG off_hi = 0L; SetFilePointer(fd, 0L, &off_hi, SEEK_END); } #endif lua_settop(L, 1); return 1; } return sys_seterror(L, 0); }