aboutsummaryrefslogtreecommitdiff
path: root/src/lfs.c
diff options
context:
space:
mode:
authorFabio Mascarenhas <mascarenhas@acm.org>2012-10-01 11:11:48 -0300
committerFabio Mascarenhas <mascarenhas@acm.org>2012-10-01 11:11:48 -0300
commitd71c63cdb776f7d25313f8fcd14f07512ba1f83e (patch)
tree41111619a268eb4d05667807baf54b6c867801d9 /src/lfs.c
parent4a299c53b68cc9a9bf728f46c915e5b43280d896 (diff)
downloadluafilesystem-d71c63cdb776f7d25313f8fcd14f07512ba1f83e.tar.gz
luafilesystem-d71c63cdb776f7d25313f8fcd14f07512ba1f83e.tar.bz2
luafilesystem-d71c63cdb776f7d25313f8fcd14f07512ba1f83e.zip
luafilesystem 1.6.0
Diffstat (limited to 'src/lfs.c')
-rw-r--r--src/lfs.c660
1 files changed, 330 insertions, 330 deletions
diff --git a/src/lfs.c b/src/lfs.c
index faba9bb..87323b3 100644
--- a/src/lfs.c
+++ b/src/lfs.c
@@ -67,21 +67,21 @@
67#if (LUA_VERSION_NUM == 502) 67#if (LUA_VERSION_NUM == 502)
68#undef luaL_register 68#undef luaL_register
69#define luaL_register(L,n,f) \ 69#define luaL_register(L,n,f) \
70 { if ((n) == NULL) luaL_setfuncs(L,f,0); else luaL_newlib(L,f); } 70 { if ((n) == NULL) luaL_setfuncs(L,f,0); else luaL_newlib(L,f); }
71 71
72#endif 72#endif
73 73
74/* Define 'strerror' for systems that do not implement it */ 74/* Define 'strerror' for systems that do not implement it */
75#ifdef NO_STRERROR 75#ifdef NO_STRERROR
76#define strerror(_) "System unable to describe the error" 76#define strerror(_) "System unable to describe the error"
77#endif 77#endif
78 78
79/* Define 'getcwd' for systems that do not implement it */ 79/* Define 'getcwd' for systems that do not implement it */
80#ifdef NO_GETCWD 80#ifdef NO_GETCWD
81#define getcwd(p,s) NULL 81#define getcwd(p,s) NULL
82#define getcwd_error "Function 'getcwd' not provided by system" 82#define getcwd_error "Function 'getcwd' not provided by system"
83#else 83#else
84#define getcwd_error strerror(errno) 84#define getcwd_error strerror(errno)
85 #ifdef _WIN32 85 #ifdef _WIN32
86 #define LFS_MAXPATHLEN MAX_PATH // MAX_PATH seems to be 260. Seems kind of small. Is there a better one? 86 #define LFS_MAXPATHLEN MAX_PATH // MAX_PATH seems to be 260. Seems kind of small. Is there a better one?
87 #else 87 #else
@@ -92,12 +92,12 @@
92 92
93#define DIR_METATABLE "directory metatable" 93#define DIR_METATABLE "directory metatable"
94typedef struct dir_data { 94typedef struct dir_data {
95 int closed; 95 int closed;
96#ifdef _WIN32 96#ifdef _WIN32
97 long hFile; 97 long hFile;
98 char pattern[MAX_PATH+1]; 98 char pattern[MAX_PATH+1];
99#else 99#else
100 DIR *dir; 100 DIR *dir;
101#endif 101#endif
102} dir_data; 102} dir_data;
103 103
@@ -127,21 +127,21 @@ typedef struct dir_data {
127*/ 127*/
128static int pusherror(lua_State *L, const char *info) 128static int pusherror(lua_State *L, const char *info)
129{ 129{
130 lua_pushnil(L); 130 lua_pushnil(L);
131 if (info==NULL) 131 if (info==NULL)
132 lua_pushstring(L, strerror(errno)); 132 lua_pushstring(L, strerror(errno));
133 else 133 else
134 lua_pushfstring(L, "%s: %s", info, strerror(errno)); 134 lua_pushfstring(L, "%s: %s", info, strerror(errno));
135 lua_pushinteger(L, errno); 135 lua_pushinteger(L, errno);
136 return 3; 136 return 3;
137} 137}
138 138
139static int pushresult(lua_State *L, int i, const char *info) 139static int pushresult(lua_State *L, int i, const char *info)
140{ 140{
141 if (i==-1) 141 if (i==-1)
142 return pusherror(L, info); 142 return pusherror(L, info);
143 lua_pushinteger(L, i); 143 lua_pushinteger(L, i);
144 return 1; 144 return 1;
145} 145}
146 146
147 147
@@ -149,16 +149,16 @@ static int pushresult(lua_State *L, int i, const char *info)
149** This function changes the working (current) directory 149** This function changes the working (current) directory
150*/ 150*/
151static int change_dir (lua_State *L) { 151static int change_dir (lua_State *L) {
152 const char *path = luaL_checkstring(L, 1); 152 const char *path = luaL_checkstring(L, 1);
153 if (chdir(path)) { 153 if (chdir(path)) {
154 lua_pushnil (L); 154 lua_pushnil (L);
155 lua_pushfstring (L,"Unable to change working directory to '%s'\n%s\n", 155 lua_pushfstring (L,"Unable to change working directory to '%s'\n%s\n",
156 path, chdir_error); 156 path, chdir_error);
157 return 2; 157 return 2;
158 } else { 158 } else {
159 lua_pushboolean (L, 1); 159 lua_pushboolean (L, 1);
160 return 1; 160 return 1;
161 } 161 }
162} 162}
163 163
164/* 164/*
@@ -169,7 +169,7 @@ static int change_dir (lua_State *L) {
169static int get_dir (lua_State *L) { 169static int get_dir (lua_State *L) {
170 char *path; 170 char *path;
171 // Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. 171 // Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead.
172 char buf[LFS_MAXPATHLEN]; 172 char buf[LFS_MAXPATHLEN];
173 if ((path = getcwd(buf, LFS_MAXPATHLEN)) == NULL) { 173 if ((path = getcwd(buf, LFS_MAXPATHLEN)) == NULL) {
174 lua_pushnil(L); 174 lua_pushnil(L);
175 lua_pushstring(L, getcwd_error); 175 lua_pushstring(L, getcwd_error);
@@ -185,15 +185,15 @@ static int get_dir (lua_State *L) {
185** Check if the given element on the stack is a file and returns it. 185** Check if the given element on the stack is a file and returns it.
186*/ 186*/
187static FILE *check_file (lua_State *L, int idx, const char *funcname) { 187static FILE *check_file (lua_State *L, int idx, const char *funcname) {
188 FILE **fh = (FILE **)luaL_checkudata (L, idx, "FILE*"); 188 FILE **fh = (FILE **)luaL_checkudata (L, idx, "FILE*");
189 if (fh == NULL) { 189 if (fh == NULL) {
190 luaL_error (L, "%s: not a file", funcname); 190 luaL_error (L, "%s: not a file", funcname);
191 return 0; 191 return 0;
192 } else if (*fh == NULL) { 192 } else if (*fh == NULL) {
193 luaL_error (L, "%s: closed file", funcname); 193 luaL_error (L, "%s: closed file", funcname);
194 return 0; 194 return 0;
195 } else 195 } else
196 return *fh; 196 return *fh;
197} 197}
198 198
199 199
@@ -201,50 +201,50 @@ static FILE *check_file (lua_State *L, int idx, const char *funcname) {
201** 201**
202*/ 202*/
203static int _file_lock (lua_State *L, FILE *fh, const char *mode, const long start, long len, const char *funcname) { 203static int _file_lock (lua_State *L, FILE *fh, const char *mode, const long start, long len, const char *funcname) {
204 int code; 204 int code;
205#ifdef _WIN32 205#ifdef _WIN32
206 /* lkmode valid values are: 206 /* lkmode valid values are:
207 LK_LOCK Locks the specified bytes. If the bytes cannot be locked, the program immediately tries again after 1 second. If, after 10 attempts, the bytes cannot be locked, the constant returns an error. 207 LK_LOCK Locks the specified bytes. If the bytes cannot be locked, the program immediately tries again after 1 second. If, after 10 attempts, the bytes cannot be locked, the constant returns an error.
208 LK_NBLCK Locks the specified bytes. If the bytes cannot be locked, the constant returns an error. 208 LK_NBLCK Locks the specified bytes. If the bytes cannot be locked, the constant returns an error.
209 LK_NBRLCK Same as _LK_NBLCK. 209 LK_NBRLCK Same as _LK_NBLCK.
210 LK_RLCK Same as _LK_LOCK. 210 LK_RLCK Same as _LK_LOCK.
211 LK_UNLCK Unlocks the specified bytes, which must have been previously locked. 211 LK_UNLCK Unlocks the specified bytes, which must have been previously locked.
212 212
213 Regions should be locked only briefly and should be unlocked before closing a file or exiting the program. 213 Regions should be locked only briefly and should be unlocked before closing a file or exiting the program.
214 214
215 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__locking.asp 215 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__locking.asp
216 */ 216 */
217 int lkmode; 217 int lkmode;
218 switch (*mode) { 218 switch (*mode) {
219 case 'r': lkmode = LK_NBLCK; break; 219 case 'r': lkmode = LK_NBLCK; break;
220 case 'w': lkmode = LK_NBLCK; break; 220 case 'w': lkmode = LK_NBLCK; break;
221 case 'u': lkmode = LK_UNLCK; break; 221 case 'u': lkmode = LK_UNLCK; break;
222 default : return luaL_error (L, "%s: invalid mode", funcname); 222 default : return luaL_error (L, "%s: invalid mode", funcname);
223 } 223 }
224 if (!len) { 224 if (!len) {
225 fseek (fh, 0L, SEEK_END); 225 fseek (fh, 0L, SEEK_END);
226 len = ftell (fh); 226 len = ftell (fh);
227 } 227 }
228 fseek (fh, start, SEEK_SET); 228 fseek (fh, start, SEEK_SET);
229#ifdef __BORLANDC__ 229#ifdef __BORLANDC__
230 code = locking (fileno(fh), lkmode, len); 230 code = locking (fileno(fh), lkmode, len);
231#else 231#else
232 code = _locking (fileno(fh), lkmode, len); 232 code = _locking (fileno(fh), lkmode, len);
233#endif 233#endif
234#else 234#else
235 struct flock f; 235 struct flock f;
236 switch (*mode) { 236 switch (*mode) {
237 case 'w': f.l_type = F_WRLCK; break; 237 case 'w': f.l_type = F_WRLCK; break;
238 case 'r': f.l_type = F_RDLCK; break; 238 case 'r': f.l_type = F_RDLCK; break;
239 case 'u': f.l_type = F_UNLCK; break; 239 case 'u': f.l_type = F_UNLCK; break;
240 default : return luaL_error (L, "%s: invalid mode", funcname); 240 default : return luaL_error (L, "%s: invalid mode", funcname);
241 } 241 }
242 f.l_whence = SEEK_SET; 242 f.l_whence = SEEK_SET;
243 f.l_start = (off_t)start; 243 f.l_start = (off_t)start;
244 f.l_len = (off_t)len; 244 f.l_len = (off_t)len;
245 code = fcntl (fileno(fh), F_SETLK, &f); 245 code = fcntl (fileno(fh), F_SETLK, &f);
246#endif 246#endif
247 return (code != -1); 247 return (code != -1);
248} 248}
249 249
250#ifdef _WIN32 250#ifdef _WIN32
@@ -258,19 +258,19 @@ static int lfs_lock_dir(lua_State *L) {
258 const char *lockfile = "/lockfile.lfs"; 258 const char *lockfile = "/lockfile.lfs";
259 const char *path = luaL_checklstring(L, 1, &pathl); 259 const char *path = luaL_checklstring(L, 1, &pathl);
260 ln = (char*)malloc(pathl + strlen(lockfile) + 1); 260 ln = (char*)malloc(pathl + strlen(lockfile) + 1);
261 if(!ln) { 261 if(!ln) {
262 lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; 262 lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
263 } 263 }
264 strcpy(ln, path); strcat(ln, lockfile); 264 strcpy(ln, path); strcat(ln, lockfile);
265 if((fd = CreateFile(ln, GENERIC_WRITE, 0, NULL, CREATE_NEW, 265 if((fd = CreateFile(ln, GENERIC_WRITE, 0, NULL, CREATE_NEW,
266 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL)) == INVALID_HANDLE_VALUE) { 266 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL)) == INVALID_HANDLE_VALUE) {
267 int en = GetLastError(); 267 int en = GetLastError();
268 free(ln); lua_pushnil(L); 268 free(ln); lua_pushnil(L);
269 if(en == ERROR_FILE_EXISTS || en == ERROR_SHARING_VIOLATION) 269 if(en == ERROR_FILE_EXISTS || en == ERROR_SHARING_VIOLATION)
270 lua_pushstring(L, "File exists"); 270 lua_pushstring(L, "File exists");
271 else 271 else
272 lua_pushstring(L, strerror(en)); 272 lua_pushstring(L, strerror(en));
273 return 2; 273 return 2;
274 } 274 }
275 free(ln); 275 free(ln);
276 lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock)); 276 lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock));
@@ -296,12 +296,12 @@ static int lfs_lock_dir(lua_State *L) {
296 const char *path = luaL_checklstring(L, 1, &pathl); 296 const char *path = luaL_checklstring(L, 1, &pathl);
297 lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock)); 297 lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock));
298 ln = (char*)malloc(pathl + strlen(lockfile) + 1); 298 ln = (char*)malloc(pathl + strlen(lockfile) + 1);
299 if(!ln) { 299 if(!ln) {
300 lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; 300 lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
301 } 301 }
302 strcpy(ln, path); strcat(ln, lockfile); 302 strcpy(ln, path); strcat(ln, lockfile);
303 if(symlink("lock", ln) == -1) { 303 if(symlink("lock", ln) == -1) {
304 free(ln); lua_pushnil(L); 304 free(ln); lua_pushnil(L);
305 lua_pushstring(L, strerror(errno)); return 2; 305 lua_pushstring(L, strerror(errno)); return 2;
306 } 306 }
307 lock->ln = ln; 307 lock->ln = ln;
@@ -358,18 +358,18 @@ static int lfs_f_setmode(lua_State *L) {
358** @param #4 Number with length (optional). 358** @param #4 Number with length (optional).
359*/ 359*/
360static int file_lock (lua_State *L) { 360static int file_lock (lua_State *L) {
361 FILE *fh = check_file (L, 1, "lock"); 361 FILE *fh = check_file (L, 1, "lock");
362 const char *mode = luaL_checkstring (L, 2); 362 const char *mode = luaL_checkstring (L, 2);
363 const long start = luaL_optlong (L, 3, 0); 363 const long start = luaL_optlong (L, 3, 0);
364 long len = luaL_optlong (L, 4, 0); 364 long len = luaL_optlong (L, 4, 0);
365 if (_file_lock (L, fh, mode, start, len, "lock")) { 365 if (_file_lock (L, fh, mode, start, len, "lock")) {
366 lua_pushboolean (L, 1); 366 lua_pushboolean (L, 1);
367 return 1; 367 return 1;
368 } else { 368 } else {
369 lua_pushnil (L); 369 lua_pushnil (L);
370 lua_pushfstring (L, "%s", strerror(errno)); 370 lua_pushfstring (L, "%s", strerror(errno));
371 return 2; 371 return 2;
372 } 372 }
373} 373}
374 374
375 375
@@ -380,17 +380,17 @@ static int file_lock (lua_State *L) {
380** @param #3 Number with length (optional). 380** @param #3 Number with length (optional).
381*/ 381*/
382static int file_unlock (lua_State *L) { 382static int file_unlock (lua_State *L) {
383 FILE *fh = check_file (L, 1, "unlock"); 383 FILE *fh = check_file (L, 1, "unlock");
384 const long start = luaL_optlong (L, 2, 0); 384 const long start = luaL_optlong (L, 2, 0);
385 long len = luaL_optlong (L, 3, 0); 385 long len = luaL_optlong (L, 3, 0);
386 if (_file_lock (L, fh, "u", start, len, "unlock")) { 386 if (_file_lock (L, fh, "u", start, len, "unlock")) {
387 lua_pushboolean (L, 1); 387 lua_pushboolean (L, 1);
388 return 1; 388 return 1;
389 } else { 389 } else {
390 lua_pushnil (L); 390 lua_pushnil (L);
391 lua_pushfstring (L, "%s", strerror(errno)); 391 lua_pushfstring (L, "%s", strerror(errno));
392 return 2; 392 return 2;
393 } 393 }
394} 394}
395 395
396 396
@@ -403,10 +403,10 @@ static int file_unlock (lua_State *L) {
403static int make_link(lua_State *L) 403static int make_link(lua_State *L)
404{ 404{
405#ifndef _WIN32 405#ifndef _WIN32
406 const char *oldpath = luaL_checkstring(L, 1); 406 const char *oldpath = luaL_checkstring(L, 1);
407 const char *newpath = luaL_checkstring(L, 2); 407 const char *newpath = luaL_checkstring(L, 2);
408 return pushresult(L, 408 return pushresult(L,
409 (lua_toboolean(L,3) ? symlink : link)(oldpath, newpath), NULL); 409 (lua_toboolean(L,3) ? symlink : link)(oldpath, newpath), NULL);
410#else 410#else
411 pusherror(L, "make_link is not supported on Windows"); 411 pusherror(L, "make_link is not supported on Windows");
412#endif 412#endif
@@ -418,21 +418,21 @@ static int make_link(lua_State *L)
418** @param #1 Directory path. 418** @param #1 Directory path.
419*/ 419*/
420static int make_dir (lua_State *L) { 420static int make_dir (lua_State *L) {
421 const char *path = luaL_checkstring (L, 1); 421 const char *path = luaL_checkstring (L, 1);
422 int fail; 422 int fail;
423#ifdef _WIN32 423#ifdef _WIN32
424 fail = _mkdir (path); 424 fail = _mkdir (path);
425#else 425#else
426 fail = mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | 426 fail = mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
427 S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH ); 427 S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH );
428#endif 428#endif
429 if (fail) { 429 if (fail) {
430 lua_pushnil (L); 430 lua_pushnil (L);
431 lua_pushfstring (L, "%s", strerror(errno)); 431 lua_pushfstring (L, "%s", strerror(errno));
432 return 2; 432 return 2;
433 } 433 }
434 lua_pushboolean (L, 1); 434 lua_pushboolean (L, 1);
435 return 1; 435 return 1;
436} 436}
437 437
438/* 438/*
@@ -440,18 +440,18 @@ static int make_dir (lua_State *L) {
440** @param #1 Directory path. 440** @param #1 Directory path.
441*/ 441*/
442static int remove_dir (lua_State *L) { 442static int remove_dir (lua_State *L) {
443 const char *path = luaL_checkstring (L, 1); 443 const char *path = luaL_checkstring (L, 1);
444 int fail; 444 int fail;
445 445
446 fail = rmdir (path); 446 fail = rmdir (path);
447 447
448 if (fail) { 448 if (fail) {
449 lua_pushnil (L); 449 lua_pushnil (L);
450 lua_pushfstring (L, "%s", strerror(errno)); 450 lua_pushfstring (L, "%s", strerror(errno));
451 return 2; 451 return 2;
452 } 452 }
453 lua_pushboolean (L, 1); 453 lua_pushboolean (L, 1);
454 return 1; 454 return 1;
455} 455}
456 456
457/* 457/*
@@ -459,44 +459,44 @@ static int remove_dir (lua_State *L) {
459*/ 459*/
460static int dir_iter (lua_State *L) { 460static int dir_iter (lua_State *L) {
461#ifdef _WIN32 461#ifdef _WIN32
462 struct _finddata_t c_file; 462 struct _finddata_t c_file;
463#else 463#else
464 struct dirent *entry; 464 struct dirent *entry;
465#endif 465#endif
466 dir_data *d = (dir_data *)luaL_checkudata (L, 1, DIR_METATABLE); 466 dir_data *d = (dir_data *)luaL_checkudata (L, 1, DIR_METATABLE);
467 luaL_argcheck (L, d->closed == 0, 1, "closed directory"); 467 luaL_argcheck (L, d->closed == 0, 1, "closed directory");
468#ifdef _WIN32 468#ifdef _WIN32
469 if (d->hFile == 0L) { /* first entry */ 469 if (d->hFile == 0L) { /* first entry */
470 if ((d->hFile = _findfirst (d->pattern, &c_file)) == -1L) { 470 if ((d->hFile = _findfirst (d->pattern, &c_file)) == -1L) {
471 lua_pushnil (L); 471 lua_pushnil (L);
472 lua_pushstring (L, strerror (errno)); 472 lua_pushstring (L, strerror (errno));
473 d->closed = 1; 473 d->closed = 1;
474 return 2; 474 return 2;
475 } else { 475 } else {
476 lua_pushstring (L, c_file.name); 476 lua_pushstring (L, c_file.name);
477 return 1; 477 return 1;
478 } 478 }
479 } else { /* next entry */ 479 } else { /* next entry */
480 if (_findnext (d->hFile, &c_file) == -1L) { 480 if (_findnext (d->hFile, &c_file) == -1L) {
481 /* no more entries => close directory */ 481 /* no more entries => close directory */
482 _findclose (d->hFile); 482 _findclose (d->hFile);
483 d->closed = 1; 483 d->closed = 1;
484 return 0; 484 return 0;
485 } else { 485 } else {
486 lua_pushstring (L, c_file.name); 486 lua_pushstring (L, c_file.name);
487 return 1; 487 return 1;
488 } 488 }
489 } 489 }
490#else 490#else
491 if ((entry = readdir (d->dir)) != NULL) { 491 if ((entry = readdir (d->dir)) != NULL) {
492 lua_pushstring (L, entry->d_name); 492 lua_pushstring (L, entry->d_name);
493 return 1; 493 return 1;
494 } else { 494 } else {
495 /* no more entries => close directory */ 495 /* no more entries => close directory */
496 closedir (d->dir); 496 closedir (d->dir);
497 d->closed = 1; 497 d->closed = 1;
498 return 0; 498 return 0;
499 } 499 }
500#endif 500#endif
501} 501}
502 502
@@ -505,18 +505,18 @@ static int dir_iter (lua_State *L) {
505** Closes directory iterators 505** Closes directory iterators
506*/ 506*/
507static int dir_close (lua_State *L) { 507static int dir_close (lua_State *L) {
508 dir_data *d = (dir_data *)lua_touserdata (L, 1); 508 dir_data *d = (dir_data *)lua_touserdata (L, 1);
509#ifdef _WIN32 509#ifdef _WIN32
510 if (!d->closed && d->hFile) { 510 if (!d->closed && d->hFile) {
511 _findclose (d->hFile); 511 _findclose (d->hFile);
512 } 512 }
513#else 513#else
514 if (!d->closed && d->dir) { 514 if (!d->closed && d->dir) {
515 closedir (d->dir); 515 closedir (d->dir);
516 } 516 }
517#endif 517#endif
518 d->closed = 1; 518 d->closed = 1;
519 return 0; 519 return 0;
520} 520}
521 521
522 522
@@ -524,25 +524,25 @@ static int dir_close (lua_State *L) {
524** Factory of directory iterators 524** Factory of directory iterators
525*/ 525*/
526static int dir_iter_factory (lua_State *L) { 526static int dir_iter_factory (lua_State *L) {
527 const char *path = luaL_checkstring (L, 1); 527 const char *path = luaL_checkstring (L, 1);
528 dir_data *d; 528 dir_data *d;
529 lua_pushcfunction (L, dir_iter); 529 lua_pushcfunction (L, dir_iter);
530 d = (dir_data *) lua_newuserdata (L, sizeof(dir_data)); 530 d = (dir_data *) lua_newuserdata (L, sizeof(dir_data));
531 luaL_getmetatable (L, DIR_METATABLE); 531 luaL_getmetatable (L, DIR_METATABLE);
532 lua_setmetatable (L, -2); 532 lua_setmetatable (L, -2);
533 d->closed = 0; 533 d->closed = 0;
534#ifdef _WIN32 534#ifdef _WIN32
535 d->hFile = 0L; 535 d->hFile = 0L;
536 if (strlen(path) > MAX_PATH-2) 536 if (strlen(path) > MAX_PATH-2)
537 luaL_error (L, "path too long: %s", path); 537 luaL_error (L, "path too long: %s", path);
538 else 538 else
539 sprintf (d->pattern, "%s/*", path); 539 sprintf (d->pattern, "%s/*", path);
540#else 540#else
541 d->dir = opendir (path); 541 d->dir = opendir (path);
542 if (d->dir == NULL) 542 if (d->dir == NULL)
543 luaL_error (L, "cannot open %s: %s", path, strerror (errno)); 543 luaL_error (L, "cannot open %s: %s", path, strerror (errno));
544#endif 544#endif
545 return 2; 545 return 2;
546} 546}
547 547
548 548
@@ -550,38 +550,38 @@ static int dir_iter_factory (lua_State *L) {
550** Creates directory metatable. 550** Creates directory metatable.
551*/ 551*/
552static int dir_create_meta (lua_State *L) { 552static int dir_create_meta (lua_State *L) {
553 luaL_newmetatable (L, DIR_METATABLE); 553 luaL_newmetatable (L, DIR_METATABLE);
554 554
555 /* Method table */ 555 /* Method table */
556 lua_newtable(L); 556 lua_newtable(L);
557 lua_pushcfunction (L, dir_iter); 557 lua_pushcfunction (L, dir_iter);
558 lua_setfield(L, -2, "next"); 558 lua_setfield(L, -2, "next");
559 lua_pushcfunction (L, dir_close); 559 lua_pushcfunction (L, dir_close);
560 lua_setfield(L, -2, "close"); 560 lua_setfield(L, -2, "close");
561 561
562 /* Metamethods */ 562 /* Metamethods */
563 lua_setfield(L, -2, "__index"); 563 lua_setfield(L, -2, "__index");
564 lua_pushcfunction (L, dir_close); 564 lua_pushcfunction (L, dir_close);
565 lua_setfield (L, -2, "__gc"); 565 lua_setfield (L, -2, "__gc");
566 return 1; 566 return 1;
567} 567}
568 568
569/* 569/*
570** Creates lock metatable. 570** Creates lock metatable.
571*/ 571*/
572static int lock_create_meta (lua_State *L) { 572static int lock_create_meta (lua_State *L) {
573 luaL_newmetatable (L, LOCK_METATABLE); 573 luaL_newmetatable (L, LOCK_METATABLE);
574 574
575 /* Method table */ 575 /* Method table */
576 lua_newtable(L); 576 lua_newtable(L);
577 lua_pushcfunction(L, lfs_unlock_dir); 577 lua_pushcfunction(L, lfs_unlock_dir);
578 lua_setfield(L, -2, "free"); 578 lua_setfield(L, -2, "free");
579 579
580 /* Metamethods */ 580 /* Metamethods */
581 lua_setfield(L, -2, "__index"); 581 lua_setfield(L, -2, "__index");
582 lua_pushcfunction(L, lfs_unlock_dir); 582 lua_pushcfunction(L, lfs_unlock_dir);
583 lua_setfield(L, -2, "__gc"); 583 lua_setfield(L, -2, "__gc");
584 return 1; 584 return 1;
585} 585}
586 586
587 587
@@ -621,17 +621,17 @@ static const char *mode2string (mode_t mode) {
621 else if ( S_ISDIR(mode) ) 621 else if ( S_ISDIR(mode) )
622 return "directory"; 622 return "directory";
623 else if ( S_ISLNK(mode) ) 623 else if ( S_ISLNK(mode) )
624 return "link"; 624 return "link";
625 else if ( S_ISSOCK(mode) ) 625 else if ( S_ISSOCK(mode) )
626 return "socket"; 626 return "socket";
627 else if ( S_ISFIFO(mode) ) 627 else if ( S_ISFIFO(mode) )
628 return "named pipe"; 628 return "named pipe";
629 else if ( S_ISCHR(mode) ) 629 else if ( S_ISCHR(mode) )
630 return "char device"; 630 return "char device";
631 else if ( S_ISBLK(mode) ) 631 else if ( S_ISBLK(mode) )
632 return "block device"; 632 return "block device";
633 else 633 else
634 return "other"; 634 return "other";
635} 635}
636 636
637 637
@@ -639,78 +639,78 @@ static const char *mode2string (mode_t mode) {
639** Set access time and modification values for file 639** Set access time and modification values for file
640*/ 640*/
641static int file_utime (lua_State *L) { 641static int file_utime (lua_State *L) {
642 const char *file = luaL_checkstring (L, 1); 642 const char *file = luaL_checkstring (L, 1);
643 struct utimbuf utb, *buf; 643 struct utimbuf utb, *buf;
644 644
645 if (lua_gettop (L) == 1) /* set to current date/time */ 645 if (lua_gettop (L) == 1) /* set to current date/time */
646 buf = NULL; 646 buf = NULL;
647 else { 647 else {
648 utb.actime = (time_t)luaL_optnumber (L, 2, 0); 648 utb.actime = (time_t)luaL_optnumber (L, 2, 0);
649 utb.modtime = (time_t)luaL_optnumber (L, 3, utb.actime); 649 utb.modtime = (time_t)luaL_optnumber (L, 3, utb.actime);
650 buf = &utb; 650 buf = &utb;
651 } 651 }
652 if (utime (file, buf)) { 652 if (utime (file, buf)) {
653 lua_pushnil (L); 653 lua_pushnil (L);
654 lua_pushfstring (L, "%s", strerror (errno)); 654 lua_pushfstring (L, "%s", strerror (errno));
655 return 2; 655 return 2;
656 } 656 }
657 lua_pushboolean (L, 1); 657 lua_pushboolean (L, 1);
658 return 1; 658 return 1;
659} 659}
660 660
661 661
662/* inode protection mode */ 662/* inode protection mode */
663static void push_st_mode (lua_State *L, STAT_STRUCT *info) { 663static void push_st_mode (lua_State *L, STAT_STRUCT *info) {
664 lua_pushstring (L, mode2string (info->st_mode)); 664 lua_pushstring (L, mode2string (info->st_mode));
665} 665}
666/* device inode resides on */ 666/* device inode resides on */
667static void push_st_dev (lua_State *L, STAT_STRUCT *info) { 667static void push_st_dev (lua_State *L, STAT_STRUCT *info) {
668 lua_pushnumber (L, (lua_Number)info->st_dev); 668 lua_pushnumber (L, (lua_Number)info->st_dev);
669} 669}
670/* inode's number */ 670/* inode's number */
671static void push_st_ino (lua_State *L, STAT_STRUCT *info) { 671static void push_st_ino (lua_State *L, STAT_STRUCT *info) {
672 lua_pushnumber (L, (lua_Number)info->st_ino); 672 lua_pushnumber (L, (lua_Number)info->st_ino);
673} 673}
674/* number of hard links to the file */ 674/* number of hard links to the file */
675static void push_st_nlink (lua_State *L, STAT_STRUCT *info) { 675static void push_st_nlink (lua_State *L, STAT_STRUCT *info) {
676 lua_pushnumber (L, (lua_Number)info->st_nlink); 676 lua_pushnumber (L, (lua_Number)info->st_nlink);
677} 677}
678/* user-id of owner */ 678/* user-id of owner */
679static void push_st_uid (lua_State *L, STAT_STRUCT *info) { 679static void push_st_uid (lua_State *L, STAT_STRUCT *info) {
680 lua_pushnumber (L, (lua_Number)info->st_uid); 680 lua_pushnumber (L, (lua_Number)info->st_uid);
681} 681}
682/* group-id of owner */ 682/* group-id of owner */
683static void push_st_gid (lua_State *L, STAT_STRUCT *info) { 683static void push_st_gid (lua_State *L, STAT_STRUCT *info) {
684 lua_pushnumber (L, (lua_Number)info->st_gid); 684 lua_pushnumber (L, (lua_Number)info->st_gid);
685} 685}
686/* device type, for special file inode */ 686/* device type, for special file inode */
687static void push_st_rdev (lua_State *L, STAT_STRUCT *info) { 687static void push_st_rdev (lua_State *L, STAT_STRUCT *info) {
688 lua_pushnumber (L, (lua_Number)info->st_rdev); 688 lua_pushnumber (L, (lua_Number)info->st_rdev);
689} 689}
690/* time of last access */ 690/* time of last access */
691static void push_st_atime (lua_State *L, STAT_STRUCT *info) { 691static void push_st_atime (lua_State *L, STAT_STRUCT *info) {
692 lua_pushnumber (L, info->st_atime); 692 lua_pushnumber (L, info->st_atime);
693} 693}
694/* time of last data modification */ 694/* time of last data modification */
695static void push_st_mtime (lua_State *L, STAT_STRUCT *info) { 695static void push_st_mtime (lua_State *L, STAT_STRUCT *info) {
696 lua_pushnumber (L, info->st_mtime); 696 lua_pushnumber (L, info->st_mtime);
697} 697}
698/* time of last file status change */ 698/* time of last file status change */
699static void push_st_ctime (lua_State *L, STAT_STRUCT *info) { 699static void push_st_ctime (lua_State *L, STAT_STRUCT *info) {
700 lua_pushnumber (L, info->st_ctime); 700 lua_pushnumber (L, info->st_ctime);
701} 701}
702/* file size, in bytes */ 702/* file size, in bytes */
703static void push_st_size (lua_State *L, STAT_STRUCT *info) { 703static void push_st_size (lua_State *L, STAT_STRUCT *info) {
704 lua_pushnumber (L, (lua_Number)info->st_size); 704 lua_pushnumber (L, (lua_Number)info->st_size);
705} 705}
706#ifndef _WIN32 706#ifndef _WIN32
707/* blocks allocated for file */ 707/* blocks allocated for file */
708static void push_st_blocks (lua_State *L, STAT_STRUCT *info) { 708static void push_st_blocks (lua_State *L, STAT_STRUCT *info) {
709 lua_pushnumber (L, (lua_Number)info->st_blocks); 709 lua_pushnumber (L, (lua_Number)info->st_blocks);
710} 710}
711/* optimal file system I/O blocksize */ 711/* optimal file system I/O blocksize */
712static void push_st_blksize (lua_State *L, STAT_STRUCT *info) { 712static void push_st_blksize (lua_State *L, STAT_STRUCT *info) {
713 lua_pushnumber (L, (lua_Number)info->st_blksize); 713 lua_pushnumber (L, (lua_Number)info->st_blksize);
714} 714}
715#endif 715#endif
716static void push_invalid (lua_State *L, STAT_STRUCT *info) { 716static void push_invalid (lua_State *L, STAT_STRUCT *info) {
@@ -763,68 +763,68 @@ static void push_st_perm (lua_State *L, STAT_STRUCT *info) {
763typedef void (*_push_function) (lua_State *L, STAT_STRUCT *info); 763typedef void (*_push_function) (lua_State *L, STAT_STRUCT *info);
764 764
765struct _stat_members { 765struct _stat_members {
766 const char *name; 766 const char *name;
767 _push_function push; 767 _push_function push;
768}; 768};
769 769
770struct _stat_members members[] = { 770struct _stat_members members[] = {
771 { "mode", push_st_mode }, 771 { "mode", push_st_mode },
772 { "dev", push_st_dev }, 772 { "dev", push_st_dev },
773 { "ino", push_st_ino }, 773 { "ino", push_st_ino },
774 { "nlink", push_st_nlink }, 774 { "nlink", push_st_nlink },
775 { "uid", push_st_uid }, 775 { "uid", push_st_uid },
776 { "gid", push_st_gid }, 776 { "gid", push_st_gid },
777 { "rdev", push_st_rdev }, 777 { "rdev", push_st_rdev },
778 { "access", push_st_atime }, 778 { "access", push_st_atime },
779 { "modification", push_st_mtime }, 779 { "modification", push_st_mtime },
780 { "change", push_st_ctime }, 780 { "change", push_st_ctime },
781 { "size", push_st_size }, 781 { "size", push_st_size },
782 { "permissions", push_st_perm }, 782 { "permissions", push_st_perm },
783#ifndef _WIN32 783#ifndef _WIN32
784 { "blocks", push_st_blocks }, 784 { "blocks", push_st_blocks },
785 { "blksize", push_st_blksize }, 785 { "blksize", push_st_blksize },
786#endif 786#endif
787 { NULL, push_invalid } 787 { NULL, push_invalid }
788}; 788};
789 789
790/* 790/*
791** Get file or symbolic link information 791** Get file or symbolic link information
792*/ 792*/
793static int _file_info_ (lua_State *L, int (*st)(const char*, STAT_STRUCT*)) { 793static int _file_info_ (lua_State *L, int (*st)(const char*, STAT_STRUCT*)) {
794 int i; 794 int i;
795 STAT_STRUCT info; 795 STAT_STRUCT info;
796 const char *file = luaL_checkstring (L, 1); 796 const char *file = luaL_checkstring (L, 1);
797 797
798 if (st(file, &info)) { 798 if (st(file, &info)) {
799 lua_pushnil (L); 799 lua_pushnil (L);
800 lua_pushfstring (L, "cannot obtain information from file `%s'", file); 800 lua_pushfstring (L, "cannot obtain information from file `%s'", file);
801 return 2; 801 return 2;
802 } 802 }
803 if (lua_isstring (L, 2)) { 803 if (lua_isstring (L, 2)) {
804 int v; 804 int v;
805 const char *member = lua_tostring (L, 2); 805 const char *member = lua_tostring (L, 2);
806 if (strcmp (member, "mode") == 0) v = 0; 806 if (strcmp (member, "mode") == 0) v = 0;
807#ifndef _WIN32 807#ifndef _WIN32
808 else if (strcmp (member, "blocks") == 0) v = 11; 808 else if (strcmp (member, "blocks") == 0) v = 11;
809 else if (strcmp (member, "blksize") == 0) v = 12; 809 else if (strcmp (member, "blksize") == 0) v = 12;
810#endif 810#endif
811 else /* look for member */ 811 else /* look for member */
812 for (v = 1; members[v].name; v++) 812 for (v = 1; members[v].name; v++)
813 if (*members[v].name == *member) 813 if (*members[v].name == *member)
814 break; 814 break;
815 /* push member value and return */ 815 /* push member value and return */
816 members[v].push (L, &info); 816 members[v].push (L, &info);
817 return 1; 817 return 1;
818 } else if (!lua_istable (L, 2)) 818 } else if (!lua_istable (L, 2))
819 /* creates a table if none is given */ 819 /* creates a table if none is given */
820 lua_newtable (L); 820 lua_newtable (L);
821 /* stores all members in table on top of the stack */ 821 /* stores all members in table on top of the stack */
822 for (i = 0; members[i].name; i++) { 822 for (i = 0; members[i].name; i++) {
823 lua_pushstring (L, members[i].name); 823 lua_pushstring (L, members[i].name);
824 members[i].push (L, &info); 824 members[i].push (L, &info);
825 lua_rawset (L, -3); 825 lua_rawset (L, -3);
826 } 826 }
827 return 1; 827 return 1;
828} 828}
829 829
830 830
@@ -832,7 +832,7 @@ static int _file_info_ (lua_State *L, int (*st)(const char*, STAT_STRUCT*)) {
832** Get file information using stat. 832** Get file information using stat.
833*/ 833*/
834static int file_info (lua_State *L) { 834static int file_info (lua_State *L) {
835 return _file_info_ (L, STAT_FUNC); 835 return _file_info_ (L, STAT_FUNC);
836} 836}
837 837
838 838
@@ -840,7 +840,7 @@ static int file_info (lua_State *L) {
840** Get symbolic link information using lstat. 840** Get symbolic link information using lstat.
841*/ 841*/
842static int link_info (lua_State *L) { 842static int link_info (lua_State *L) {
843 return _file_info_ (L, LSTAT_FUNC); 843 return _file_info_ (L, LSTAT_FUNC);
844} 844}
845 845
846 846
@@ -848,48 +848,48 @@ static int link_info (lua_State *L) {
848** Assumes the table is on top of the stack. 848** Assumes the table is on top of the stack.
849*/ 849*/
850static void set_info (lua_State *L) { 850static void set_info (lua_State *L) {
851 lua_pushliteral (L, "_COPYRIGHT"); 851 lua_pushliteral (L, "_COPYRIGHT");
852 lua_pushliteral (L, "Copyright (C) 2003-2009 Kepler Project"); 852 lua_pushliteral (L, "Copyright (C) 2003-2012 Kepler Project");
853 lua_settable (L, -3); 853 lua_settable (L, -3);
854 lua_pushliteral (L, "_DESCRIPTION"); 854 lua_pushliteral (L, "_DESCRIPTION");
855 lua_pushliteral (L, "LuaFileSystem is a Lua library developed to complement the set of functions related to file systems offered by the standard Lua distribution"); 855 lua_pushliteral (L, "LuaFileSystem is a Lua library developed to complement the set of functions related to file systems offered by the standard Lua distribution");
856 lua_settable (L, -3); 856 lua_settable (L, -3);
857 lua_pushliteral (L, "_VERSION"); 857 lua_pushliteral (L, "_VERSION");
858 lua_pushliteral (L, "LuaFileSystem 1.5.0"); 858 lua_pushliteral (L, "LuaFileSystem 1.6.0");
859 lua_settable (L, -3); 859 lua_settable (L, -3);
860} 860}
861 861
862 862
863static const struct luaL_Reg fslib[] = { 863static const struct luaL_Reg fslib[] = {
864 {"attributes", file_info}, 864 {"attributes", file_info},
865 {"chdir", change_dir}, 865 {"chdir", change_dir},
866 {"currentdir", get_dir}, 866 {"currentdir", get_dir},
867 {"dir", dir_iter_factory}, 867 {"dir", dir_iter_factory},
868 {"link", make_link}, 868 {"link", make_link},
869 {"lock", file_lock}, 869 {"lock", file_lock},
870 {"mkdir", make_dir}, 870 {"mkdir", make_dir},
871 {"rmdir", remove_dir}, 871 {"rmdir", remove_dir},
872 {"symlinkattributes", link_info}, 872 {"symlinkattributes", link_info},
873 {"setmode", lfs_f_setmode}, 873 {"setmode", lfs_f_setmode},
874 {"touch", file_utime}, 874 {"touch", file_utime},
875 {"unlock", file_unlock}, 875 {"unlock", file_unlock},
876 {"lock_dir", lfs_lock_dir}, 876 {"lock_dir", lfs_lock_dir},
877 {NULL, NULL}, 877 {NULL, NULL},
878}; 878};
879 879
880#if LUA_VERSION_NUM > 501 880#if LUA_VERSION_NUM > 501
881static void luaL_register (lua_State *L, const char *libname, const luaL_Reg *l) 881static void luaL_register (lua_State *L, const char *libname, const luaL_Reg *l)
882{ 882{
883 luaL_newlib (L, l); 883 luaL_newlib (L, l);
884 lua_pushvalue (L, -1); 884 lua_pushvalue (L, -1);
885 lua_setglobal (L, libname); 885 lua_setglobal (L, libname);
886} 886}
887#endif 887#endif
888 888
889int luaopen_lfs (lua_State *L) { 889int luaopen_lfs (lua_State *L) {
890 dir_create_meta (L); 890 dir_create_meta (L);
891 lock_create_meta (L); 891 lock_create_meta (L);
892 luaL_register (L, "lfs", fslib); 892 luaL_register (L, "lfs", fslib);
893 set_info (L); 893 set_info (L);
894 return 1; 894 return 1;
895} 895}