/* * Arguments: ..., [number] * Returns: string */ static int sys_strerror (lua_State *L) { const int err = luaL_optint(L, -1, SYS_ERRNO); #ifndef _WIN32 lua_pushstring(L, strerror(err)); #else const int flags = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM; WCHAR buf[512]; if (is_WinNT ? FormatMessageW(flags, NULL, err, 0, buf, sizeof(buf) / sizeof(buf[0]), NULL) : FormatMessageA(flags, NULL, err, 0, (char *) buf, sizeof(buf), NULL)) { char *s = filename_to_utf8(buf); if (s) { char *cp; for (cp = s; *cp != '\0'; ++cp) { if (*cp == '\r' || *cp == '\n') *cp = ' '; } lua_pushstring(L, s); free(s); return 1; } } lua_pushfstring(L, "System error %i", err); #endif return 1; }
/* * 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: ..., [number] * Returns: string */ static int sys_strerror (lua_State *L) { const int err = luaL_optint(L, -1, SYS_ERRNO); #ifndef _WIN32 #if defined(BSD) || (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) char buf[512]; if (!err) goto success; if (!strerror_r(err, buf, sizeof(buf))) { lua_pushstring(L, buf); return 1; } #endif lua_pushstring(L, strerror(err)); #else const int flags = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM; WCHAR buf[512]; if (!err) goto success; if (is_WinNT ? FormatMessageW(flags, NULL, err, 0, buf, sizeof(buf) / sizeof(buf[0]), NULL) : FormatMessageA(flags, NULL, err, 0, (char *) buf, sizeof(buf), NULL)) { char *s = filename_to_utf8(buf); if (s) { char *cp; for (cp = s; *cp != '\0'; ++cp) { if (*cp == '\r' || *cp == '\n') *cp = ' '; } lua_pushstring(L, s); free(s); return 1; } } lua_pushfstring(L, "System error %d", err); #endif return 1; success: lua_pushliteral(L, "OK"); return 1; }
/* * 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: dir_udata, directory (string) * * Returns: [filename (string), is_directory (boolean)] * | * Returns (win32): [drive_letter (string: A: .. Z:), drive_type (string)] */ static int sys_dir_next (lua_State *L) { struct dir *dp = checkudata(L, 1, DIR_TYPENAME); if (lua_gettop(L) == 2) { /* 'for' start? */ /* return generator (dir_udata) */ lua_pushvalue(L, 1); return sys_dir_open(L, 2, dp); } else { /* 'for' step */ char *filename; #ifndef _WIN32 struct dirent *entry; if (!dp->data) return 0; do { sys_vm_leave(L); entry = readdir(dp->data); sys_vm_enter(L); if (!entry) { closedir(dp->data); dp->data = NULL; return 0; } filename = entry->d_name; } while (filename[0] == '.' && (filename[1] == '\0' || (filename[1] == '.' && filename[2] == '\0'))); lua_pushstring(L, filename); lua_pushboolean(L, entry->d_type & DT_DIR); return 2; #else filename = (char *) dp->data.cFileName; if (dp->is_root) { while (++*filename <= 'Z') { const char *type; switch (GetDriveTypeA(filename)) { case DRIVE_REMOVABLE: type = "removable"; break; case DRIVE_FIXED: type = "fixed"; break; case DRIVE_REMOTE: type = "remote"; break; case DRIVE_CDROM: type = "cdrom"; break; case DRIVE_RAMDISK: type = "ramdisk"; break; default: continue; } lua_pushlstring(L, filename, 2); lua_pushstring(L, type); return 2; } return 0; } if (dp->h == INVALID_HANDLE_VALUE) return 0; for (; ; ) { int res, is_dots = 1; { char *path = filename_to_utf8(filename); if (!path) return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); if (!(path[0] == '.' && (path[1] == '\0' || (path[1] == '.' && path[2] == '\0')))) { lua_pushstring(L, path); lua_pushboolean(L, dp->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); is_dots = 0; } free(path); } sys_vm_leave(L); res = is_WinNT ? FindNextFileW(dp->h, &dp->data) : FindNextFileA(dp->h, (WIN32_FIND_DATAA *) &dp->data); sys_vm_enter(L); if (!res) { FindClose(dp->h); dp->h = INVALID_HANDLE_VALUE; return is_dots ? 0 : 2; } if (!is_dots) break; } return 2; #endif } }