From 3c4e563d9c140319e28c419f2710b51a2f6d6d24 Mon Sep 17 00:00:00 2001 From: NiteHawk Date: Sat, 15 Oct 2016 00:46:54 +0200 Subject: 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 --- src/lfs.c | 87 +++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/src/lfs.c b/src/lfs.c index 8154a46..25122a3 100644 --- a/src/lfs.c +++ b/src/lfs.c @@ -41,22 +41,26 @@ #include #ifdef _WIN32 -#include -#include -#include -#include -#ifdef __BORLANDC__ - #include -#else - #include -#endif -#include + #include + #include + #include + #include + #ifdef __BORLANDC__ + #include + #else + #include + #endif + #include + /* MAX_PATH seems to be 260. Seems kind of small. Is there a better one? */ + #define LFS_MAXPATHLEN MAX_PATH #else -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include /* for MAXPATHLEN */ + #define LFS_MAXPATHLEN MAXPATHLEN #endif #include @@ -85,22 +89,6 @@ #define strerror(_) "System unable to describe the error" #endif -/* Define 'getcwd' for systems that do not implement it */ -#ifdef NO_GETCWD -#define getcwd(p,s) NULL -#define getcwd_error "Function 'getcwd' not provided by system" -#else -#define getcwd_error strerror(errno) - #ifdef _WIN32 - /* MAX_PATH seems to be 260. Seems kind of small. Is there a better one? */ - #define LFS_MAXPATHLEN MAX_PATH - #else - /* For MAXPATHLEN: */ - #include - #define LFS_MAXPATHLEN MAXPATHLEN - #endif -#endif - #define DIR_METATABLE "directory metatable" typedef struct dir_data { int closed; @@ -178,18 +166,35 @@ static int change_dir (lua_State *L) { ** and a string describing the error */ static int get_dir (lua_State *L) { - char *path; - /* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */ - char buf[LFS_MAXPATHLEN]; - if ((path = getcwd(buf, LFS_MAXPATHLEN)) == NULL) { +#ifdef NO_GETCWD lua_pushnil(L); - lua_pushstring(L, getcwd_error); + lua_pushstring(L, "Function 'getcwd' not provided by system"); return 2; - } - else { - lua_pushstring(L, path); - return 1; - } +#else + char *path = NULL; + /* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */ + size_t size = LFS_MAXPATHLEN; /* initial buffer size */ + int result; + while (1) { + path = realloc(path, size); + if (!path) /* failed to allocate */ + return pusherror(L, "get_dir realloc() failed"); + if (getcwd(path, size) != NULL) { + /* success, push the path to the Lua stack */ + lua_pushstring(L, path); + result = 1; + break; + } + if (errno != ERANGE) { /* unexpected error */ + result = pusherror(L, "get_dir getcwd() failed"); + break; + } + /* ERANGE = insufficient buffer capacity, double size and retry */ + size *= 2; + } + free(path); + return result; +#endif } /* -- cgit v1.2.3