aboutsummaryrefslogtreecommitdiff
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
parent4a299c53b68cc9a9bf728f46c915e5b43280d896 (diff)
downloadluafilesystem-d71c63cdb776f7d25313f8fcd14f07512ba1f83e.tar.gz
luafilesystem-d71c63cdb776f7d25313f8fcd14f07512ba1f83e.tar.bz2
luafilesystem-d71c63cdb776f7d25313f8fcd14f07512ba1f83e.zip
luafilesystem 1.6.0
-rw-r--r--README6
-rw-r--r--doc/us/index.html9
-rw-r--r--rockspecs/luafilesystem-1.6.0-1.rockspec27
-rw-r--r--src/lfs.c660
-rw-r--r--tests/test.lua81
5 files changed, 431 insertions, 352 deletions
diff --git a/README b/README
index 0103efa..6610243 100644
--- a/README
+++ b/README
@@ -22,6 +22,12 @@ Please check the documentation at doc/us/ for more information.
22History 22History
23------- 23-------
24 24
25Version 1.6.0 [26/Sep/2012]
26 * getcwd fix for Android
27 * support for Lua 5.2
28 * add lfs.link
29 * other bug fixes
30
25Version 1.5.0 [20/Oct/2009] 31Version 1.5.0 [20/Oct/2009]
26 * added explicit next and close methods to second return value of lfs.dir (the directory object), for explicit iteration or explicit closing. 32 * added explicit next and close methods to second return value of lfs.dir (the directory object), for explicit iteration or explicit closing.
27 * added directory locking via lfs.lock_dir function (see the manual). 33 * added directory locking via lfs.lock_dir function (see the manual).
diff --git a/doc/us/index.html b/doc/us/index.html
index 9798404..6d7072b 100644
--- a/doc/us/index.html
+++ b/doc/us/index.html
@@ -71,7 +71,8 @@ the underlying directory structure and file attributes.</p>
71 71
72<h2><a name="status"></a>Status</h2> 72<h2><a name="status"></a>Status</h2>
73 73
74<p>Current version is 1.5.0. It was developed for Lua 5.1.</p> 74<p>Current version is 1.6.0. It was developed for Lua 5.1 but also
75 works with Lua 5.2.</p>
75 76
76<h2><a name="download"></a>Download</h2> 77<h2><a name="download"></a>Download</h2>
77 78
@@ -82,6 +83,12 @@ page.</p>
82<h2><a name="history"></a>History</h2> 83<h2><a name="history"></a>History</h2>
83 84
84<dl class="history"> 85<dl class="history">
86 <dt><strong>Version 1.6.0</strong> [26/Sep/2012]</dt>
87 <li>getcwd fix for Android</li>
88 <li>support for Lua 5.2</li>
89 <li>add lfs.link</li>
90 <li>other bug fixes</li>
91
85 <dt><strong>Version 1.5.0</strong> [20/Oct/2009]</dt> 92 <dt><strong>Version 1.5.0</strong> [20/Oct/2009]</dt>
86 <li>Added explicit next and close methods to second return value of lfs.dir 93 <li>Added explicit next and close methods to second return value of lfs.dir
87(the directory object), for explicit iteration or explicit closing.</li> 94(the directory object), for explicit iteration or explicit closing.</li>
diff --git a/rockspecs/luafilesystem-1.6.0-1.rockspec b/rockspecs/luafilesystem-1.6.0-1.rockspec
new file mode 100644
index 0000000..82d349c
--- /dev/null
+++ b/rockspecs/luafilesystem-1.6.0-1.rockspec
@@ -0,0 +1,27 @@
1package = "LuaFileSystem"
2
3version = "1.6.0-1"
4
5source = {
6 url = "https://github.com/downloads/keplerproject/luafilesystem/luafilesystem-1.6.0.tar.gz",
7}
8
9description = {
10 summary = "File System Library for the Lua Programming Language",
11 detailed = [[
12 LuaFileSystem is a Lua library developed to complement the set of
13 functions related to file systems offered by the standard Lua
14 distribution. LuaFileSystem offers a portable way to access the
15 underlying directory structure and file attributes.
16 ]]
17}
18
19dependencies = {
20 "lua >= 5.1"
21}
22
23build = {
24 type = "builtin",
25 modules = { lfs = "src/lfs.c" },
26 copy_directories = { "doc", "tests" }
27}
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}
diff --git a/tests/test.lua b/tests/test.lua
index 20948df..4990aec 100644
--- a/tests/test.lua
+++ b/tests/test.lua
@@ -7,22 +7,25 @@ local upper = ".."
7local lfs = require"lfs" 7local lfs = require"lfs"
8print (lfs._VERSION) 8print (lfs._VERSION)
9 9
10io.write(".")
11io.flush()
12
10function attrdir (path) 13function attrdir (path)
11 for file in lfs.dir(path) do 14 for file in lfs.dir(path) do
12 if file ~= "." and file ~= ".." then 15 if file ~= "." and file ~= ".." then
13 local f = path..sep..file 16 local f = path..sep..file
14 print ("\t=> "..f.." <=") 17 print ("\t=> "..f.." <=")
15 local attr = lfs.attributes (f) 18 local attr = lfs.attributes (f)
16 assert (type(attr) == "table") 19 assert (type(attr) == "table")
17 if attr.mode == "directory" then 20 if attr.mode == "directory" then
18 attrdir (f) 21 attrdir (f)
19 else 22 else
20 for name, value in pairs(attr) do 23 for name, value in pairs(attr) do
21 print (name, value) 24 print (name, value)
22 end 25 end
23 end 26 end
24 end 27 end
25 end 28 end
26end 29end
27 30
28-- Checking changing directories 31-- Checking changing directories
@@ -33,6 +36,9 @@ assert (lfs.chdir (reldir), "could not change back to current directory")
33assert (lfs.currentdir() == current, "error trying to change directories") 36assert (lfs.currentdir() == current, "error trying to change directories")
34assert (lfs.chdir ("this couldn't be an actual directory") == nil, "could change to a non-existent directory") 37assert (lfs.chdir ("this couldn't be an actual directory") == nil, "could change to a non-existent directory")
35 38
39io.write(".")
40io.flush()
41
36-- Changing creating and removing directories 42-- Changing creating and removing directories
37local tmpdir = current..sep.."lfs_tmp_dir" 43local tmpdir = current..sep.."lfs_tmp_dir"
38local tmpfile = tmpdir..sep.."tmp_file" 44local tmpfile = tmpdir..sep.."tmp_file"
@@ -40,19 +46,25 @@ local tmpfile = tmpdir..sep.."tmp_file"
40-- that may have resulted from an interrupted test execution and remove it 46-- that may have resulted from an interrupted test execution and remove it
41if lfs.chdir (tmpdir) then 47if lfs.chdir (tmpdir) then
42 assert (lfs.chdir (upper), "could not change to upper directory") 48 assert (lfs.chdir (upper), "could not change to upper directory")
43 assert (os.remove (tmpfile), "could not remove file from previous test") 49 assert (os.remove (tmpfile), "could not remove file from previous test")
44 assert (lfs.rmdir (tmpdir), "could not remove directory from previous test") 50 assert (lfs.rmdir (tmpdir), "could not remove directory from previous test")
45end 51end
46 52
53io.write(".")
54io.flush()
55
47-- tries to create a directory 56-- tries to create a directory
48assert (lfs.mkdir (tmpdir), "could not make a new directory") 57assert (lfs.mkdir (tmpdir), "could not make a new directory")
49local attrib, errmsg = lfs.attributes (tmpdir) 58local attrib, errmsg = lfs.attributes (tmpdir)
50if not attrib then 59if not attrib then
51 error ("could not get attributes of file `"..tmpdir.."':\n"..errmsg) 60 error ("could not get attributes of file `"..tmpdir.."':\n"..errmsg)
52end 61end
53local f = io.open(tmpfile, "w") 62local f = io.open(tmpfile, "w")
54f:close() 63f:close()
55 64
65io.write(".")
66io.flush()
67
56-- Change access time 68-- Change access time
57local testdate = os.time({ year = 2007, day = 10, month = 2, hour=0}) 69local testdate = os.time({ year = 2007, day = 10, month = 2, hour=0})
58assert (lfs.touch (tmpfile, testdate)) 70assert (lfs.touch (tmpfile, testdate))
@@ -60,6 +72,9 @@ local new_att = assert (lfs.attributes (tmpfile))
60assert (new_att.access == testdate, "could not set access time") 72assert (new_att.access == testdate, "could not set access time")
61assert (new_att.modification == testdate, "could not set modification time") 73assert (new_att.modification == testdate, "could not set modification time")
62 74
75io.write(".")
76io.flush()
77
63-- Change access and modification time 78-- Change access and modification time
64local testdate1 = os.time({ year = 2007, day = 10, month = 2, hour=0}) 79local testdate1 = os.time({ year = 2007, day = 10, month = 2, hour=0})
65local testdate2 = os.time({ year = 2007, day = 11, month = 2, hour=0}) 80local testdate2 = os.time({ year = 2007, day = 11, month = 2, hour=0})
@@ -69,6 +84,9 @@ local new_att = assert (lfs.attributes (tmpfile))
69assert (new_att.access == testdate2, "could not set access time") 84assert (new_att.access == testdate2, "could not set access time")
70assert (new_att.modification == testdate1, "could not set modification time") 85assert (new_att.modification == testdate1, "could not set modification time")
71 86
87io.write(".")
88io.flush()
89
72-- Checking link (does not work on Windows) 90-- Checking link (does not work on Windows)
73if lfs.link (tmpfile, "_a_link_for_test_", true) then 91if lfs.link (tmpfile, "_a_link_for_test_", true) then
74 assert (lfs.attributes"_a_link_for_test_".mode == "file") 92 assert (lfs.attributes"_a_link_for_test_".mode == "file")
@@ -79,6 +97,9 @@ if lfs.link (tmpfile, "_a_link_for_test_", true) then
79 assert (os.remove"_a_hard_link_for_test_") 97 assert (os.remove"_a_hard_link_for_test_")
80end 98end
81 99
100io.write(".")
101io.flush()
102
82-- Checking text/binary modes (only has an effect in Windows) 103-- Checking text/binary modes (only has an effect in Windows)
83local f = io.open(tmpfile, "w") 104local f = io.open(tmpfile, "w")
84local result, mode = lfs.setmode(f, "binary") 105local result, mode = lfs.setmode(f, "binary")
@@ -86,30 +107,45 @@ assert(result) -- on non-Windows platforms, mode is always returned as "binary"
86result, mode = lfs.setmode(f, "text") 107result, mode = lfs.setmode(f, "text")
87assert(result and mode == "binary") 108assert(result and mode == "binary")
88f:close() 109f:close()
89 110
111io.write(".")
112io.flush()
113
90-- Restore access time to current value 114-- Restore access time to current value
91assert (lfs.touch (tmpfile, attrib.access, attrib.modification)) 115assert (lfs.touch (tmpfile, attrib.access, attrib.modification))
92new_att = assert (lfs.attributes (tmpfile)) 116new_att = assert (lfs.attributes (tmpfile))
93assert (new_att.access == attrib.access) 117assert (new_att.access == attrib.access)
94assert (new_att.modification == attrib.modification) 118assert (new_att.modification == attrib.modification)
95 119
120io.write(".")
121io.flush()
122
96-- Remove new file and directory 123-- Remove new file and directory
97assert (os.remove (tmpfile), "could not remove new file") 124assert (os.remove (tmpfile), "could not remove new file")
98assert (lfs.rmdir (tmpdir), "could not remove new directory") 125assert (lfs.rmdir (tmpdir), "could not remove new directory")
99assert (lfs.mkdir (tmpdir..sep.."lfs_tmp_dir") == nil, "could create a directory inside a non-existent one") 126assert (lfs.mkdir (tmpdir..sep.."lfs_tmp_dir") == nil, "could create a directory inside a non-existent one")
100 127
128io.write(".")
129io.flush()
130
101-- Trying to get attributes of a non-existent file 131-- Trying to get attributes of a non-existent file
102assert (lfs.attributes ("this couldn't be an actual file") == nil, "could get attributes of a non-existent file") 132assert (lfs.attributes ("this couldn't be an actual file") == nil, "could get attributes of a non-existent file")
103assert (type(lfs.attributes (upper)) == "table", "couldn't get attributes of upper directory") 133assert (type(lfs.attributes (upper)) == "table", "couldn't get attributes of upper directory")
104 134
135io.write(".")
136io.flush()
137
105-- Stressing directory iterator 138-- Stressing directory iterator
106count = 0 139count = 0
107for i = 1, 4000 do 140for i = 1, 4000 do
108 for file in lfs.dir (tmp) do 141 for file in lfs.dir (tmp) do
109 count = count + 1 142 count = count + 1
110 end 143 end
111end 144end
112 145
146io.write(".")
147io.flush()
148
113-- Stressing directory iterator, explicit version 149-- Stressing directory iterator, explicit version
114count = 0 150count = 0
115for i = 1, 4000 do 151for i = 1, 4000 do
@@ -122,6 +158,9 @@ for i = 1, 4000 do
122 assert(not pcall(dir.next, dir)) 158 assert(not pcall(dir.next, dir))
123end 159end
124 160
161io.write(".")
162io.flush()
163
125-- directory explicit close 164-- directory explicit close
126local iter, dir = lfs.dir(tmp) 165local iter, dir = lfs.dir(tmp)
127dir:close() 166dir:close()