aboutsummaryrefslogtreecommitdiff
path: root/src/lfs.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lfs.c139
1 files changed, 96 insertions, 43 deletions
diff --git a/src/lfs.c b/src/lfs.c
index dd0b6af..aeaa8b4 100644
--- a/src/lfs.c
+++ b/src/lfs.c
@@ -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"
105typedef struct dir_data { 93typedef 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*/
188static int get_dir (lua_State *L) { 176static 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*/
852static 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*/
843static int link_info (lua_State *L) { 884static 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