diff options
| author | Hisham <hisham@gobolinux.org> | 2016-10-19 01:35:24 -0400 |
|---|---|---|
| committer | Hisham <hisham@gobolinux.org> | 2016-10-19 01:35:24 -0400 |
| commit | 77c0e0f992329fa1812e5bb948420e9ebb1798c4 (patch) | |
| tree | f8f063e128b9dedcadacade849a03a563c4a1351 /src | |
| parent | a332bde584756b14298f51e913bdc309f87e7ff8 (diff) | |
| parent | 3c4e563d9c140319e28c419f2710b51a2f6d6d24 (diff) | |
| download | luafilesystem-1.7.tar.gz luafilesystem-1.7.tar.bz2 luafilesystem-1.7.zip | |
Merge branch 'master' into 1.71.7
Diffstat (limited to 'src')
| -rw-r--r-- | src/lfs.c | 139 |
1 files changed, 96 insertions, 43 deletions
| @@ -41,22 +41,26 @@ | |||
| 41 | #include <sys/stat.h> | 41 | #include <sys/stat.h> |
| 42 | 42 | ||
| 43 | #ifdef _WIN32 | 43 | #ifdef _WIN32 |
| 44 | #include <direct.h> | 44 | #include <direct.h> |
| 45 | #include <windows.h> | 45 | #include <windows.h> |
| 46 | #include <io.h> | 46 | #include <io.h> |
| 47 | #include <sys/locking.h> | 47 | #include <sys/locking.h> |
| 48 | #ifdef __BORLANDC__ | 48 | #ifdef __BORLANDC__ |
| 49 | #include <utime.h> | 49 | #include <utime.h> |
| 50 | #else | 50 | #else |
| 51 | #include <sys/utime.h> | 51 | #include <sys/utime.h> |
| 52 | #endif | 52 | #endif |
| 53 | #include <fcntl.h> | 53 | #include <fcntl.h> |
| 54 | /* MAX_PATH seems to be 260. Seems kind of small. Is there a better one? */ | ||
| 55 | #define LFS_MAXPATHLEN MAX_PATH | ||
| 54 | #else | 56 | #else |
| 55 | #include <unistd.h> | 57 | #include <unistd.h> |
| 56 | #include <dirent.h> | 58 | #include <dirent.h> |
| 57 | #include <fcntl.h> | 59 | #include <fcntl.h> |
| 58 | #include <sys/types.h> | 60 | #include <sys/types.h> |
| 59 | #include <utime.h> | 61 | #include <utime.h> |
| 62 | #include <sys/param.h> /* for MAXPATHLEN */ | ||
| 63 | #define LFS_MAXPATHLEN MAXPATHLEN | ||
| 60 | #endif | 64 | #endif |
| 61 | 65 | ||
| 62 | #include <lua.h> | 66 | #include <lua.h> |
| @@ -85,22 +89,6 @@ | |||
| 85 | #define strerror(_) "System unable to describe the error" | 89 | #define strerror(_) "System unable to describe the error" |
| 86 | #endif | 90 | #endif |
| 87 | 91 | ||
| 88 | /* Define 'getcwd' for systems that do not implement it */ | ||
| 89 | #ifdef NO_GETCWD | ||
| 90 | #define getcwd(p,s) NULL | ||
| 91 | #define getcwd_error "Function 'getcwd' not provided by system" | ||
| 92 | #else | ||
| 93 | #define getcwd_error strerror(errno) | ||
| 94 | #ifdef _WIN32 | ||
| 95 | /* MAX_PATH seems to be 260. Seems kind of small. Is there a better one? */ | ||
| 96 | #define LFS_MAXPATHLEN MAX_PATH | ||
| 97 | #else | ||
| 98 | /* For MAXPATHLEN: */ | ||
| 99 | #include <sys/param.h> | ||
| 100 | #define LFS_MAXPATHLEN MAXPATHLEN | ||
| 101 | #endif | ||
| 102 | #endif | ||
| 103 | |||
| 104 | #define DIR_METATABLE "directory metatable" | 92 | #define DIR_METATABLE "directory metatable" |
| 105 | typedef struct dir_data { | 93 | typedef struct dir_data { |
| 106 | int closed; | 94 | int closed; |
| @@ -186,18 +174,35 @@ static int change_dir (lua_State *L) { | |||
| 186 | ** and a string describing the error | 174 | ** and a string describing the error |
| 187 | */ | 175 | */ |
| 188 | static int get_dir (lua_State *L) { | 176 | static int get_dir (lua_State *L) { |
| 189 | char *path; | 177 | #ifdef NO_GETCWD |
| 190 | /* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */ | ||
| 191 | char buf[LFS_MAXPATHLEN]; | ||
| 192 | if ((path = getcwd(buf, LFS_MAXPATHLEN)) == NULL) { | ||
| 193 | lua_pushnil(L); | 178 | lua_pushnil(L); |
| 194 | lua_pushstring(L, getcwd_error); | 179 | lua_pushstring(L, "Function 'getcwd' not provided by system"); |
| 195 | return 2; | 180 | return 2; |
| 196 | } | 181 | #else |
| 197 | else { | 182 | char *path = NULL; |
| 198 | lua_pushstring(L, path); | 183 | /* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */ |
| 199 | return 1; | 184 | size_t size = LFS_MAXPATHLEN; /* initial buffer size */ |
| 200 | } | 185 | int result; |
| 186 | while (1) { | ||
| 187 | path = realloc(path, size); | ||
| 188 | if (!path) /* failed to allocate */ | ||
| 189 | return pusherror(L, "get_dir realloc() failed"); | ||
| 190 | if (getcwd(path, size) != NULL) { | ||
| 191 | /* success, push the path to the Lua stack */ | ||
| 192 | lua_pushstring(L, path); | ||
| 193 | result = 1; | ||
| 194 | break; | ||
| 195 | } | ||
| 196 | if (errno != ERANGE) { /* unexpected error */ | ||
| 197 | result = pusherror(L, "get_dir getcwd() failed"); | ||
| 198 | break; | ||
| 199 | } | ||
| 200 | /* ERANGE = insufficient buffer capacity, double size and retry */ | ||
| 201 | size *= 2; | ||
| 202 | } | ||
| 203 | free(path); | ||
| 204 | return result; | ||
| 205 | #endif | ||
| 201 | } | 206 | } |
| 202 | 207 | ||
| 203 | /* | 208 | /* |
| @@ -815,7 +820,8 @@ static int _file_info_ (lua_State *L, int (*st)(const char*, STAT_STRUCT*)) { | |||
| 815 | /* member not found */ | 820 | /* member not found */ |
| 816 | return luaL_error(L, "invalid attribute name '%s'", member); | 821 | return luaL_error(L, "invalid attribute name '%s'", member); |
| 817 | } | 822 | } |
| 818 | /* creates a table if none is given */ | 823 | /* creates a table if none is given, removes extra arguments */ |
| 824 | lua_settop(L, 2); | ||
| 819 | if (!lua_istable (L, 2)) { | 825 | if (!lua_istable (L, 2)) { |
| 820 | lua_newtable (L); | 826 | lua_newtable (L); |
| 821 | } | 827 | } |
| @@ -838,10 +844,57 @@ static int file_info (lua_State *L) { | |||
| 838 | 844 | ||
| 839 | 845 | ||
| 840 | /* | 846 | /* |
| 847 | ** Push the symlink target to the top of the stack. | ||
| 848 | ** Assumes the file name is at position 1 of the stack. | ||
| 849 | ** Returns 1 if successful (with the target on top of the stack), | ||
| 850 | ** 0 on failure (with stack unchanged, and errno set). | ||
| 851 | */ | ||
| 852 | static int push_link_target(lua_State *L) { | ||
| 853 | #ifdef _WIN32 | ||
| 854 | errno = ENOSYS; | ||
| 855 | return 0; | ||
| 856 | #else | ||
| 857 | const char *file = luaL_checkstring(L, 1); | ||
| 858 | char *target = NULL; | ||
| 859 | int tsize, size = 256; /* size = initial buffer capacity */ | ||
| 860 | while (1) { | ||
| 861 | target = realloc(target, size); | ||
| 862 | if (!target) /* failed to allocate */ | ||
| 863 | return 0; | ||
| 864 | tsize = readlink(file, target, size); | ||
| 865 | if (tsize < 0) { /* a readlink() error occurred */ | ||
| 866 | free(target); | ||
| 867 | return 0; | ||
| 868 | } | ||
| 869 | if (tsize < size) | ||
| 870 | break; | ||
| 871 | /* possibly truncated readlink() result, double size and retry */ | ||
| 872 | size *= 2; | ||
| 873 | } | ||
| 874 | target[tsize] = '\0'; | ||
| 875 | lua_pushlstring(L, target, tsize); | ||
| 876 | free(target); | ||
| 877 | return 1; | ||
| 878 | #endif | ||
| 879 | } | ||
| 880 | |||
| 881 | /* | ||
| 841 | ** Get symbolic link information using lstat. | 882 | ** Get symbolic link information using lstat. |
| 842 | */ | 883 | */ |
| 843 | static int link_info (lua_State *L) { | 884 | static int link_info (lua_State *L) { |
| 844 | return _file_info_ (L, LSTAT_FUNC); | 885 | int ret; |
| 886 | if (lua_isstring (L, 2) && (strcmp(lua_tostring(L, 2), "target") == 0)) { | ||
| 887 | int ok = push_link_target(L); | ||
| 888 | return ok ? 1 : pusherror(L, "could not obtain link target"); | ||
| 889 | } | ||
| 890 | ret = _file_info_ (L, LSTAT_FUNC); | ||
| 891 | if (ret == 1 && lua_type(L, -1) == LUA_TTABLE) { | ||
| 892 | int ok = push_link_target(L); | ||
| 893 | if (ok) { | ||
| 894 | lua_setfield(L, -2, "target"); | ||
| 895 | } | ||
| 896 | } | ||
| 897 | return ret; | ||
| 845 | } | 898 | } |
| 846 | 899 | ||
| 847 | 900 | ||
