diff options
| author | NiteHawk <n1tehawk@users.noreply.github.com> | 2016-10-15 00:46:54 +0200 |
|---|---|---|
| committer | Hisham Muhammad <hisham@gobolinux.org> | 2016-10-14 15:46:54 -0700 |
| commit | 3c4e563d9c140319e28c419f2710b51a2f6d6d24 (patch) | |
| tree | 440c52e0185f080ae4ba5af05d8dea615ba25d30 | |
| parent | 50919ed69ff64df51d8d586d00834fde3e901785 (diff) | |
| download | luafilesystem-3c4e563d9c140319e28c419f2710b51a2f6d6d24.tar.gz luafilesystem-3c4e563d9c140319e28c419f2710b51a2f6d6d24.tar.bz2 luafilesystem-3c4e563d9c140319e28c419f2710b51a2f6d6d24.zip | |
Dynamically size getcwd() buffer in get_dir function (#84)
* Dynamically size getcwd() buffer in get_dir function
This should fix issue 42.
* Fixup: Properly respect NO_GETCWD
* Fixup: Get rid of getcwd_error, handle NO_GETCWD in a single place
| -rw-r--r-- | src/lfs.c | 87 |
1 files changed, 46 insertions, 41 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; |
| @@ -178,18 +166,35 @@ static int change_dir (lua_State *L) { | |||
| 178 | ** and a string describing the error | 166 | ** and a string describing the error |
| 179 | */ | 167 | */ |
| 180 | static int get_dir (lua_State *L) { | 168 | static int get_dir (lua_State *L) { |
| 181 | char *path; | 169 | #ifdef NO_GETCWD |
| 182 | /* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */ | ||
| 183 | char buf[LFS_MAXPATHLEN]; | ||
| 184 | if ((path = getcwd(buf, LFS_MAXPATHLEN)) == NULL) { | ||
| 185 | lua_pushnil(L); | 170 | lua_pushnil(L); |
| 186 | lua_pushstring(L, getcwd_error); | 171 | lua_pushstring(L, "Function 'getcwd' not provided by system"); |
| 187 | return 2; | 172 | return 2; |
| 188 | } | 173 | #else |
| 189 | else { | 174 | char *path = NULL; |
| 190 | lua_pushstring(L, path); | 175 | /* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */ |
| 191 | return 1; | 176 | size_t size = LFS_MAXPATHLEN; /* initial buffer size */ |
| 192 | } | 177 | int result; |
| 178 | while (1) { | ||
| 179 | path = realloc(path, size); | ||
| 180 | if (!path) /* failed to allocate */ | ||
| 181 | return pusherror(L, "get_dir realloc() failed"); | ||
| 182 | if (getcwd(path, size) != NULL) { | ||
| 183 | /* success, push the path to the Lua stack */ | ||
| 184 | lua_pushstring(L, path); | ||
| 185 | result = 1; | ||
| 186 | break; | ||
| 187 | } | ||
| 188 | if (errno != ERANGE) { /* unexpected error */ | ||
| 189 | result = pusherror(L, "get_dir getcwd() failed"); | ||
| 190 | break; | ||
| 191 | } | ||
| 192 | /* ERANGE = insufficient buffer capacity, double size and retry */ | ||
| 193 | size *= 2; | ||
| 194 | } | ||
| 195 | free(path); | ||
| 196 | return result; | ||
| 197 | #endif | ||
| 193 | } | 198 | } |
| 194 | 199 | ||
| 195 | /* | 200 | /* |
