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 | /* |