mirror of
https://github.com/vxcontrol/lualibs-lfs.git
synced 2026-07-01 10:05:29 -04:00
upgraded to 1.7.0
This commit is contained in:
+1
-2
@@ -1,3 +1,2 @@
|
||||
LuaFileSystem 1.6.2 from https://github.com/keplerproject/luafilesystem.git (MIT License)
|
||||
LuaFileSystem e5f06c2 from https://github.com/keplerproject/luafilesystem (MIT License)
|
||||
|
||||
NOTE: lfs.link crashes on Windows (commented the test)
|
||||
|
||||
+240
-181
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
** LuaFileSystem
|
||||
** Copyright Kepler Project 2003 (http://www.keplerproject.org/luafilesystem)
|
||||
** Copyright Kepler Project 2003 - 2017 (http://keplerproject.github.io/luafilesystem)
|
||||
**
|
||||
** File system manipulation library.
|
||||
** This library offers these functions:
|
||||
** lfs.attributes (filepath [, attributename])
|
||||
** lfs.attributes (filepath [, attributename | attributetable])
|
||||
** lfs.chdir (path)
|
||||
** lfs.currentdir ()
|
||||
** lfs.dir (path)
|
||||
** lfs.link (old, new[, symlink])
|
||||
** lfs.lock (fh, mode)
|
||||
** lfs.lock_dir (path)
|
||||
** lfs.mkdir (path)
|
||||
** lfs.rmdir (path)
|
||||
** lfs.setmode (filepath, mode)
|
||||
** lfs.symlinkattributes (filepath [, attributename]) -- thanks to Sam Roberts
|
||||
** lfs.symlinkattributes (filepath [, attributename])
|
||||
** lfs.touch (filepath [, atime [, mtime]])
|
||||
** lfs.unlock (fh)
|
||||
**
|
||||
** $Id: lfs.c,v 1.61 2009/07/04 02:10:16 mascarenhas Exp $
|
||||
*/
|
||||
|
||||
#ifndef LFS_DO_NOT_USE_LARGE_FILE
|
||||
#ifndef _WIN32
|
||||
#ifndef _AIX
|
||||
#define _FILE_OFFSET_BITS 64 /* Linux, Solaris and HP-UX */
|
||||
@@ -27,8 +27,11 @@
|
||||
#define _LARGE_FILES 1 /* AIX */
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef LFS_DO_NOT_USE_LARGE_FILE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
@@ -38,22 +41,26 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#include <sys/locking.h>
|
||||
#ifdef __BORLANDC__
|
||||
#include <utime.h>
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#include <sys/locking.h>
|
||||
#ifdef __BORLANDC__
|
||||
#include <utime.h>
|
||||
#else
|
||||
#include <sys/utime.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
/* MAX_PATH seems to be 260. Seems kind of small. Is there a better one? */
|
||||
#define LFS_MAXPATHLEN MAX_PATH
|
||||
#else
|
||||
#include <sys/utime.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <utime.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <utime.h>
|
||||
#include <sys/param.h> /* for MAXPATHLEN */
|
||||
#define LFS_MAXPATHLEN MAXPATHLEN
|
||||
#endif
|
||||
|
||||
#include <lua.h>
|
||||
@@ -62,11 +69,21 @@
|
||||
|
||||
#include "lfs.h"
|
||||
|
||||
#define LFS_VERSION "1.6.2"
|
||||
#define LFS_VERSION "1.7.0"
|
||||
#define LFS_LIBNAME "lfs"
|
||||
|
||||
#if LUA_VERSION_NUM < 502
|
||||
# define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l))
|
||||
#if LUA_VERSION_NUM >= 503 /* Lua 5.3 */
|
||||
|
||||
#ifndef luaL_optlong
|
||||
#define luaL_optlong luaL_optinteger
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if LUA_VERSION_NUM >= 502
|
||||
# define new_lib(L, l) (luaL_newlib(L, l))
|
||||
#else
|
||||
# define new_lib(L, l) (lua_newtable(L), luaL_register(L, NULL, l))
|
||||
#endif
|
||||
|
||||
/* Define 'strerror' for systems that do not implement it */
|
||||
@@ -74,27 +91,11 @@
|
||||
#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 <sys/param.h>
|
||||
#define LFS_MAXPATHLEN MAXPATHLEN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DIR_METATABLE "directory metatable"
|
||||
typedef struct dir_data {
|
||||
int closed;
|
||||
#ifdef _WIN32
|
||||
long hFile;
|
||||
intptr_t hFile;
|
||||
char pattern[MAX_PATH+1];
|
||||
#else
|
||||
DIR *dir;
|
||||
@@ -105,10 +106,10 @@ typedef struct dir_data {
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef __BORLANDC__
|
||||
#define lfs_setmode(L,file,m) ((void)L, setmode(_fileno(file), m))
|
||||
#define lfs_setmode(file, m) (setmode(_fileno(file), m))
|
||||
#define STAT_STRUCT struct stati64
|
||||
#else
|
||||
#define lfs_setmode(L,file,m) ((void)L, _setmode(_fileno(file), m))
|
||||
#define lfs_setmode(file, m) (_setmode(_fileno(file), m))
|
||||
#define STAT_STRUCT struct _stati64
|
||||
#endif
|
||||
#define STAT_FUNC _stati64
|
||||
@@ -116,12 +117,19 @@ typedef struct dir_data {
|
||||
#else
|
||||
#define _O_TEXT 0
|
||||
#define _O_BINARY 0
|
||||
#define lfs_setmode(L,file,m) ((void)L, (void)file, (void)m, 0)
|
||||
#define lfs_setmode(file, m) ((void)file, (void)m, 0)
|
||||
#define STAT_STRUCT struct stat
|
||||
#define STAT_FUNC stat
|
||||
#define LSTAT_FUNC lstat
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define lfs_mkdir _mkdir
|
||||
#else
|
||||
#define lfs_mkdir(path) (mkdir((path), \
|
||||
S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Utility functions
|
||||
*/
|
||||
@@ -136,12 +144,13 @@ static int pusherror(lua_State *L, const char *info)
|
||||
return 3;
|
||||
}
|
||||
|
||||
static int pushresult(lua_State *L, int i, const char *info)
|
||||
{
|
||||
if (i==-1)
|
||||
return pusherror(L, info);
|
||||
lua_pushinteger(L, i);
|
||||
return 1;
|
||||
static int pushresult(lua_State *L, int res, const char *info) {
|
||||
if (res == -1) {
|
||||
return pusherror(L, info);
|
||||
} else {
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -167,33 +176,61 @@ 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) {
|
||||
char* path2 = realloc(path, size);
|
||||
if (!path2) /* failed to allocate */ {
|
||||
result = pusherror(L, "get_dir realloc() failed");
|
||||
break;
|
||||
}
|
||||
path = path2;
|
||||
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
|
||||
}
|
||||
|
||||
/*
|
||||
** Check if the given element on the stack is a file and returns it.
|
||||
*/
|
||||
static FILE *check_file (lua_State *L, int idx, const char *funcname) {
|
||||
#if LUA_VERSION_NUM == 501
|
||||
FILE **fh = (FILE **)luaL_checkudata (L, idx, "FILE*");
|
||||
if (fh == NULL) {
|
||||
luaL_error (L, "%s: not a file", funcname);
|
||||
return 0;
|
||||
} else if (*fh == NULL) {
|
||||
if (*fh == NULL) {
|
||||
luaL_error (L, "%s: closed file", funcname);
|
||||
return 0;
|
||||
} else
|
||||
return *fh;
|
||||
#elif LUA_VERSION_NUM >= 502 && LUA_VERSION_NUM <= 503
|
||||
luaL_Stream *fh = (luaL_Stream *)luaL_checkudata (L, idx, "FILE*");
|
||||
if (fh->closef == 0 || fh->f == NULL) {
|
||||
luaL_error (L, "%s: closed file", funcname);
|
||||
return 0;
|
||||
} else
|
||||
return fh->f;
|
||||
#else
|
||||
#error unsupported Lua version
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -280,8 +317,11 @@ static int lfs_lock_dir(lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
static int lfs_unlock_dir(lua_State *L) {
|
||||
lfs_Lock *lock = luaL_checkudata(L, 1, LOCK_METATABLE);
|
||||
CloseHandle(lock->fd);
|
||||
lfs_Lock *lock = (lfs_Lock *)luaL_checkudata(L, 1, LOCK_METATABLE);
|
||||
if(lock->fd != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(lock->fd);
|
||||
lock->fd=INVALID_HANDLE_VALUE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
@@ -310,7 +350,7 @@ static int lfs_lock_dir(lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
static int lfs_unlock_dir(lua_State *L) {
|
||||
lfs_Lock *lock = luaL_checkudata(L, 1, LOCK_METATABLE);
|
||||
lfs_Lock *lock = (lfs_Lock *)luaL_checkudata(L, 1, LOCK_METATABLE);
|
||||
if(lock->ln) {
|
||||
unlink(lock->ln);
|
||||
free(lock->ln);
|
||||
@@ -324,25 +364,20 @@ static int lfs_g_setmode (lua_State *L, FILE *f, int arg) {
|
||||
static const int mode[] = {_O_BINARY, _O_TEXT};
|
||||
static const char *const modenames[] = {"binary", "text", NULL};
|
||||
int op = luaL_checkoption(L, arg, NULL, modenames);
|
||||
int res = lfs_setmode(L, f, mode[op]);
|
||||
int res = lfs_setmode(f, mode[op]);
|
||||
if (res != -1) {
|
||||
int i;
|
||||
lua_pushboolean(L, 1);
|
||||
for (i = 0; modenames[i] != NULL; i++) {
|
||||
if (mode[i] == res) {
|
||||
lua_pushstring(L, modenames[i]);
|
||||
goto exit;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
lua_pushnil(L);
|
||||
exit:
|
||||
return 2;
|
||||
} else {
|
||||
int en = errno;
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "%s", strerror(en));
|
||||
lua_pushinteger(L, en);
|
||||
return 3;
|
||||
return pusherror(L, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,8 +395,8 @@ static int lfs_f_setmode(lua_State *L) {
|
||||
static int file_lock (lua_State *L) {
|
||||
FILE *fh = check_file (L, 1, "lock");
|
||||
const char *mode = luaL_checkstring (L, 2);
|
||||
const long start = luaL_optlong (L, 3, 0);
|
||||
long len = luaL_optlong (L, 4, 0);
|
||||
const long start = (long) luaL_optinteger (L, 3, 0);
|
||||
long len = (long) luaL_optinteger (L, 4, 0);
|
||||
if (_file_lock (L, fh, mode, start, len, "lock")) {
|
||||
lua_pushboolean (L, 1);
|
||||
return 1;
|
||||
@@ -381,8 +416,8 @@ static int file_lock (lua_State *L) {
|
||||
*/
|
||||
static int file_unlock (lua_State *L) {
|
||||
FILE *fh = check_file (L, 1, "unlock");
|
||||
const long start = luaL_optlong (L, 2, 0);
|
||||
long len = luaL_optlong (L, 3, 0);
|
||||
const long start = (long) luaL_optinteger (L, 2, 0);
|
||||
long len = (long) luaL_optinteger (L, 3, 0);
|
||||
if (_file_lock (L, fh, "u", start, len, "unlock")) {
|
||||
lua_pushboolean (L, 1);
|
||||
return 1;
|
||||
@@ -400,15 +435,20 @@ static int file_unlock (lua_State *L) {
|
||||
** @param #2 Name of link.
|
||||
** @param #3 True if link is symbolic (optional).
|
||||
*/
|
||||
static int make_link(lua_State *L)
|
||||
{
|
||||
static int make_link (lua_State *L) {
|
||||
#ifndef _WIN32
|
||||
const char *oldpath = luaL_checkstring(L, 1);
|
||||
const char *newpath = luaL_checkstring(L, 2);
|
||||
return pushresult(L,
|
||||
(lua_toboolean(L,3) ? symlink : link)(oldpath, newpath), NULL);
|
||||
const char *oldpath = luaL_checkstring(L, 1);
|
||||
const char *newpath = luaL_checkstring(L, 2);
|
||||
int res = (lua_toboolean(L,3) ? symlink : link)(oldpath, newpath);
|
||||
if (res == -1) {
|
||||
return pusherror(L, NULL);
|
||||
} else {
|
||||
lua_pushinteger(L, 0);
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
pusherror(L, "make_link is not supported on Windows");
|
||||
errno = ENOSYS; /* = "Function not implemented" */
|
||||
return pushresult(L, -1, "make_link is not supported on Windows");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -418,42 +458,21 @@ static int make_link(lua_State *L)
|
||||
** @param #1 Directory path.
|
||||
*/
|
||||
static int make_dir (lua_State *L) {
|
||||
const char *path = luaL_checkstring (L, 1);
|
||||
int fail;
|
||||
#ifdef _WIN32
|
||||
fail = _mkdir (path);
|
||||
#else
|
||||
fail = mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
|
||||
S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH );
|
||||
#endif
|
||||
if (fail) {
|
||||
lua_pushnil (L);
|
||||
lua_pushfstring (L, "%s", strerror(errno));
|
||||
return 2;
|
||||
}
|
||||
lua_pushboolean (L, 1);
|
||||
return 1;
|
||||
const char *path = luaL_checkstring(L, 1);
|
||||
return pushresult(L, lfs_mkdir(path), NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Removes a directory.
|
||||
** @param #1 Directory path.
|
||||
*/
|
||||
static int remove_dir (lua_State *L) {
|
||||
const char *path = luaL_checkstring (L, 1);
|
||||
int fail;
|
||||
|
||||
fail = rmdir (path);
|
||||
|
||||
if (fail) {
|
||||
lua_pushnil (L);
|
||||
lua_pushfstring (L, "%s", strerror(errno));
|
||||
return 2;
|
||||
}
|
||||
lua_pushboolean (L, 1);
|
||||
return 1;
|
||||
const char *path = luaL_checkstring(L, 1);
|
||||
return pushresult(L, rmdir(path), NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Directory iterator
|
||||
*/
|
||||
@@ -566,6 +585,7 @@ static int dir_create_meta (lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Creates lock metatable.
|
||||
*/
|
||||
@@ -636,26 +656,24 @@ static const char *mode2string (mode_t mode) {
|
||||
|
||||
|
||||
/*
|
||||
** Set access time and modification values for file
|
||||
** Set access time and modification values for a file.
|
||||
** @param #1 File path.
|
||||
** @param #2 Access time in seconds, current time is used if missing.
|
||||
** @param #3 Modification time in seconds, access time is used if missing.
|
||||
*/
|
||||
static int file_utime (lua_State *L) {
|
||||
const char *file = luaL_checkstring (L, 1);
|
||||
struct utimbuf utb, *buf;
|
||||
const char *file = luaL_checkstring(L, 1);
|
||||
struct utimbuf utb, *buf;
|
||||
|
||||
if (lua_gettop (L) == 1) /* set to current date/time */
|
||||
buf = NULL;
|
||||
else {
|
||||
utb.actime = (time_t)luaL_optnumber (L, 2, 0);
|
||||
utb.modtime = (time_t)luaL_optnumber (L, 3, utb.actime);
|
||||
buf = &utb;
|
||||
}
|
||||
if (utime (file, buf)) {
|
||||
lua_pushnil (L);
|
||||
lua_pushfstring (L, "%s", strerror (errno));
|
||||
return 2;
|
||||
}
|
||||
lua_pushboolean (L, 1);
|
||||
return 1;
|
||||
if (lua_gettop (L) == 1) /* set to current date/time */
|
||||
buf = NULL;
|
||||
else {
|
||||
utb.actime = (time_t) luaL_optnumber(L, 2, 0);
|
||||
utb.modtime = (time_t) luaL_optinteger(L, 3, utb.actime);
|
||||
buf = &utb;
|
||||
}
|
||||
|
||||
return pushresult(L, utime(file, buf), NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -665,60 +683,54 @@ static void push_st_mode (lua_State *L, STAT_STRUCT *info) {
|
||||
}
|
||||
/* device inode resides on */
|
||||
static void push_st_dev (lua_State *L, STAT_STRUCT *info) {
|
||||
lua_pushnumber (L, (lua_Number)info->st_dev);
|
||||
lua_pushinteger (L, (lua_Integer) info->st_dev);
|
||||
}
|
||||
/* inode's number */
|
||||
static void push_st_ino (lua_State *L, STAT_STRUCT *info) {
|
||||
lua_pushnumber (L, (lua_Number)info->st_ino);
|
||||
lua_pushinteger (L, (lua_Integer) info->st_ino);
|
||||
}
|
||||
/* number of hard links to the file */
|
||||
static void push_st_nlink (lua_State *L, STAT_STRUCT *info) {
|
||||
lua_pushnumber (L, (lua_Number)info->st_nlink);
|
||||
lua_pushinteger (L, (lua_Integer)info->st_nlink);
|
||||
}
|
||||
/* user-id of owner */
|
||||
static void push_st_uid (lua_State *L, STAT_STRUCT *info) {
|
||||
lua_pushnumber (L, (lua_Number)info->st_uid);
|
||||
lua_pushinteger (L, (lua_Integer)info->st_uid);
|
||||
}
|
||||
/* group-id of owner */
|
||||
static void push_st_gid (lua_State *L, STAT_STRUCT *info) {
|
||||
lua_pushnumber (L, (lua_Number)info->st_gid);
|
||||
lua_pushinteger (L, (lua_Integer)info->st_gid);
|
||||
}
|
||||
/* device type, for special file inode */
|
||||
static void push_st_rdev (lua_State *L, STAT_STRUCT *info) {
|
||||
lua_pushnumber (L, (lua_Number)info->st_rdev);
|
||||
lua_pushinteger (L, (lua_Integer) info->st_rdev);
|
||||
}
|
||||
/* time of last access */
|
||||
static void push_st_atime (lua_State *L, STAT_STRUCT *info) {
|
||||
lua_pushnumber (L, info->st_atime);
|
||||
lua_pushinteger (L, (lua_Integer) info->st_atime);
|
||||
}
|
||||
/* time of last data modification */
|
||||
static void push_st_mtime (lua_State *L, STAT_STRUCT *info) {
|
||||
lua_pushnumber (L, info->st_mtime);
|
||||
lua_pushinteger (L, (lua_Integer) info->st_mtime);
|
||||
}
|
||||
/* time of last file status change */
|
||||
static void push_st_ctime (lua_State *L, STAT_STRUCT *info) {
|
||||
lua_pushnumber (L, info->st_ctime);
|
||||
lua_pushinteger (L, (lua_Integer) info->st_ctime);
|
||||
}
|
||||
/* file size, in bytes */
|
||||
static void push_st_size (lua_State *L, STAT_STRUCT *info) {
|
||||
lua_pushnumber (L, (lua_Number)info->st_size);
|
||||
lua_pushinteger (L, (lua_Integer)info->st_size);
|
||||
}
|
||||
#ifndef _WIN32
|
||||
/* blocks allocated for file */
|
||||
static void push_st_blocks (lua_State *L, STAT_STRUCT *info) {
|
||||
lua_pushnumber (L, (lua_Number)info->st_blocks);
|
||||
lua_pushinteger (L, (lua_Integer)info->st_blocks);
|
||||
}
|
||||
/* optimal file system I/O blocksize */
|
||||
static void push_st_blksize (lua_State *L, STAT_STRUCT *info) {
|
||||
lua_pushnumber (L, (lua_Number)info->st_blksize);
|
||||
lua_pushinteger (L, (lua_Integer)info->st_blksize);
|
||||
}
|
||||
#endif
|
||||
static void push_invalid (lua_State *L, STAT_STRUCT *info) {
|
||||
luaL_error(L, "invalid attribute name");
|
||||
#ifndef _WIN32
|
||||
info->st_blksize = 0; /* never reached */
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert the inode protection mode to a permission list.
|
||||
@@ -726,7 +738,7 @@ static void push_invalid (lua_State *L, STAT_STRUCT *info) {
|
||||
|
||||
#ifdef _WIN32
|
||||
static const char *perm2string (unsigned short mode) {
|
||||
static char perms[10] = "---------\0";
|
||||
static char perms[10] = "---------";
|
||||
int i;
|
||||
for (i=0;i<9;i++) perms[i]='-';
|
||||
if (mode & _S_IREAD)
|
||||
@@ -739,7 +751,7 @@ static const char *perm2string (unsigned short mode) {
|
||||
}
|
||||
#else
|
||||
static const char *perm2string (mode_t mode) {
|
||||
static char perms[10] = "---------\0";
|
||||
static char perms[10] = "---------";
|
||||
int i;
|
||||
for (i=0;i<9;i++) perms[i]='-';
|
||||
if (mode & S_IRUSR) perms[0] = 'r';
|
||||
@@ -784,40 +796,40 @@ struct _stat_members members[] = {
|
||||
{ "blocks", push_st_blocks },
|
||||
{ "blksize", push_st_blksize },
|
||||
#endif
|
||||
{ NULL, push_invalid }
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
** Get file or symbolic link information
|
||||
*/
|
||||
static int _file_info_ (lua_State *L, int (*st)(const char*, STAT_STRUCT*)) {
|
||||
int i;
|
||||
STAT_STRUCT info;
|
||||
const char *file = luaL_checkstring (L, 1);
|
||||
int i;
|
||||
|
||||
if (st(file, &info)) {
|
||||
lua_pushnil (L);
|
||||
lua_pushfstring (L, "cannot obtain information from file `%s'", file);
|
||||
return 2;
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "cannot obtain information from file '%s': %s", file, strerror(errno));
|
||||
lua_pushinteger(L, errno);
|
||||
return 3;
|
||||
}
|
||||
if (lua_isstring (L, 2)) {
|
||||
int v;
|
||||
const char *member = lua_tostring (L, 2);
|
||||
if (strcmp (member, "mode") == 0) v = 0;
|
||||
#ifndef _WIN32
|
||||
else if (strcmp (member, "blocks") == 0) v = 11;
|
||||
else if (strcmp (member, "blksize") == 0) v = 12;
|
||||
#endif
|
||||
else /* look for member */
|
||||
for (v = 1; members[v].name; v++)
|
||||
if (*members[v].name == *member)
|
||||
break;
|
||||
/* push member value and return */
|
||||
members[v].push (L, &info);
|
||||
return 1;
|
||||
} else if (!lua_istable (L, 2))
|
||||
/* creates a table if none is given */
|
||||
for (i = 0; members[i].name; i++) {
|
||||
if (strcmp(members[i].name, member) == 0) {
|
||||
/* push member value and return */
|
||||
members[i].push (L, &info);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* member not found */
|
||||
return luaL_error(L, "invalid attribute name '%s'", member);
|
||||
}
|
||||
/* creates a table if none is given, removes extra arguments */
|
||||
lua_settop(L, 2);
|
||||
if (!lua_istable (L, 2)) {
|
||||
lua_newtable (L);
|
||||
}
|
||||
/* stores all members in table on top of the stack */
|
||||
for (i = 0; members[i].name; i++) {
|
||||
lua_pushstring (L, members[i].name);
|
||||
@@ -836,11 +848,61 @@ static int file_info (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Push the symlink target to the top of the stack.
|
||||
** Assumes the file name is at position 1 of the stack.
|
||||
** Returns 1 if successful (with the target on top of the stack),
|
||||
** 0 on failure (with stack unchanged, and errno set).
|
||||
*/
|
||||
static int push_link_target(lua_State *L) {
|
||||
#ifdef _WIN32
|
||||
errno = ENOSYS;
|
||||
return 0;
|
||||
#else
|
||||
const char *file = luaL_checkstring(L, 1);
|
||||
char *target = NULL;
|
||||
int tsize, size = 256; /* size = initial buffer capacity */
|
||||
while (1) {
|
||||
char* target2 = realloc(target, size);
|
||||
if (!target2) { /* failed to allocate */
|
||||
free(target);
|
||||
return 0;
|
||||
}
|
||||
target = target2;
|
||||
tsize = readlink(file, target, size);
|
||||
if (tsize < 0) { /* a readlink() error occurred */
|
||||
free(target);
|
||||
return 0;
|
||||
}
|
||||
if (tsize < size)
|
||||
break;
|
||||
/* possibly truncated readlink() result, double size and retry */
|
||||
size *= 2;
|
||||
}
|
||||
target[tsize] = '\0';
|
||||
lua_pushlstring(L, target, tsize);
|
||||
free(target);
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Get symbolic link information using lstat.
|
||||
*/
|
||||
static int link_info (lua_State *L) {
|
||||
return _file_info_ (L, LSTAT_FUNC);
|
||||
int ret;
|
||||
if (lua_isstring (L, 2) && (strcmp(lua_tostring(L, 2), "target") == 0)) {
|
||||
int ok = push_link_target(L);
|
||||
return ok ? 1 : pusherror(L, "could not obtain link target");
|
||||
}
|
||||
ret = _file_info_ (L, LSTAT_FUNC);
|
||||
if (ret == 1 && lua_type(L, -1) == LUA_TTABLE) {
|
||||
int ok = push_link_target(L);
|
||||
if (ok) {
|
||||
lua_setfield(L, -2, "target");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -848,15 +910,12 @@ static int link_info (lua_State *L) {
|
||||
** Assumes the table is on top of the stack.
|
||||
*/
|
||||
static void set_info (lua_State *L) {
|
||||
lua_pushliteral (L, "_COPYRIGHT");
|
||||
lua_pushliteral (L, "Copyright (C) 2003-2012 Kepler Project");
|
||||
lua_settable (L, -3);
|
||||
lua_pushliteral (L, "_DESCRIPTION");
|
||||
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");
|
||||
lua_settable (L, -3);
|
||||
lua_pushliteral (L, "_VERSION");
|
||||
lua_pushliteral (L, "LuaFileSystem "LFS_VERSION);
|
||||
lua_settable (L, -3);
|
||||
lua_pushliteral(L, "Copyright (C) 2003-2017 Kepler Project");
|
||||
lua_setfield(L, -2, "_COPYRIGHT");
|
||||
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");
|
||||
lua_setfield(L, -2, "_DESCRIPTION");
|
||||
lua_pushliteral(L, "LuaFileSystem " LFS_VERSION);
|
||||
lua_setfield(L, -2, "_VERSION");
|
||||
}
|
||||
|
||||
|
||||
@@ -877,10 +936,10 @@ static const struct luaL_Reg fslib[] = {
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
int luaopen_lfs (lua_State *L) {
|
||||
LFS_EXPORT int luaopen_lfs (lua_State *L) {
|
||||
dir_create_meta (L);
|
||||
lock_create_meta (L);
|
||||
luaL_newlib (L, fslib);
|
||||
new_lib (L, fslib);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setglobal(L, LFS_LIBNAME);
|
||||
set_info (L);
|
||||
|
||||
+24
-7
@@ -1,17 +1,34 @@
|
||||
/*
|
||||
** LuaFileSystem
|
||||
** Copyright Kepler Project 2003 (http://www.keplerproject.org/luafilesystem)
|
||||
**
|
||||
** $Id: lfs.h,v 1.5 2008/02/19 20:08:23 mascarenhas Exp $
|
||||
** Copyright Kepler Project 2003 - 2017 (http://keplerproject.github.io/luafilesystem)
|
||||
*/
|
||||
|
||||
/* Define 'chdir' for systems that do not implement it */
|
||||
#ifdef NO_CHDIR
|
||||
#define chdir(p) (-1)
|
||||
#define chdir_error "Function 'chdir' not provided by system"
|
||||
#define chdir(p) (-1)
|
||||
#define chdir_error "Function 'chdir' not provided by system"
|
||||
#else
|
||||
#define chdir_error strerror(errno)
|
||||
#define chdir_error strerror(errno)
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define chdir(p) (_chdir(p))
|
||||
#define getcwd(d, s) (_getcwd(d, s))
|
||||
#define rmdir(p) (_rmdir(p))
|
||||
#define LFS_EXPORT __declspec (dllexport)
|
||||
#ifndef fileno
|
||||
#define fileno(f) (_fileno(f))
|
||||
#endif
|
||||
#else
|
||||
#define LFS_EXPORT
|
||||
#endif
|
||||
|
||||
int luaopen_lfs (lua_State *L);
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
LFS_EXPORT int luaopen_lfs (lua_State *L);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+194
-171
@@ -1,171 +1,194 @@
|
||||
#!/usr/bin/env lua5.1
|
||||
|
||||
local tmp = "/tmp"
|
||||
local sep = string.match (package.config, "[^\n]+")
|
||||
local upper = ".."
|
||||
|
||||
local lfs = require"lfs"
|
||||
print (lfs._VERSION)
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
function attrdir (path)
|
||||
for file in lfs.dir(path) do
|
||||
if file ~= "." and file ~= ".." then
|
||||
local f = path..sep..file
|
||||
print ("\t=> "..f.." <=")
|
||||
local attr = lfs.attributes (f)
|
||||
assert (type(attr) == "table")
|
||||
if attr.mode == "directory" then
|
||||
attrdir (f)
|
||||
else
|
||||
for name, value in pairs(attr) do
|
||||
print (name, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Checking changing directories
|
||||
local current = assert (lfs.currentdir())
|
||||
local reldir = string.gsub (current, "^.*%"..sep.."([^"..sep.."])$", "%1")
|
||||
assert (lfs.chdir (upper), "could not change to upper directory")
|
||||
assert (lfs.chdir (reldir), "could not change back to current directory")
|
||||
assert (lfs.currentdir() == current, "error trying to change directories")
|
||||
assert (lfs.chdir ("this couldn't be an actual directory") == nil, "could change to a non-existent directory")
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Changing creating and removing directories
|
||||
local tmpdir = current..sep.."lfs_tmp_dir"
|
||||
local tmpfile = tmpdir..sep.."tmp_file"
|
||||
-- Test for existence of a previous lfs_tmp_dir
|
||||
-- that may have resulted from an interrupted test execution and remove it
|
||||
if lfs.chdir (tmpdir) then
|
||||
assert (lfs.chdir (upper), "could not change to upper directory")
|
||||
assert (os.remove (tmpfile), "could not remove file from previous test")
|
||||
assert (lfs.rmdir (tmpdir), "could not remove directory from previous test")
|
||||
end
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- tries to create a directory
|
||||
assert (lfs.mkdir (tmpdir), "could not make a new directory")
|
||||
local attrib, errmsg = lfs.attributes (tmpdir)
|
||||
if not attrib then
|
||||
error ("could not get attributes of file `"..tmpdir.."':\n"..errmsg)
|
||||
end
|
||||
local f = io.open(tmpfile, "w")
|
||||
f:close()
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Change access time
|
||||
local testdate = os.time({ year = 2007, day = 10, month = 2, hour=0})
|
||||
assert (lfs.touch (tmpfile, testdate))
|
||||
local new_att = assert (lfs.attributes (tmpfile))
|
||||
assert (new_att.access == testdate, "could not set access time")
|
||||
assert (new_att.modification == testdate, "could not set modification time")
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Change access and modification time
|
||||
local testdate1 = os.time({ year = 2007, day = 10, month = 2, hour=0})
|
||||
local testdate2 = os.time({ year = 2007, day = 11, month = 2, hour=0})
|
||||
|
||||
assert (lfs.touch (tmpfile, testdate2, testdate1))
|
||||
local new_att = assert (lfs.attributes (tmpfile))
|
||||
assert (new_att.access == testdate2, "could not set access time")
|
||||
assert (new_att.modification == testdate1, "could not set modification time")
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Checking link (does not work on Windows)
|
||||
local ffi = require'ffi'
|
||||
if ffi.os ~= 'Windows' then
|
||||
if lfs.link (tmpfile, "_a_link_for_test_", true) then
|
||||
assert (lfs.attributes"_a_link_for_test_".mode == "file")
|
||||
assert (lfs.symlinkattributes"_a_link_for_test_".mode == "link")
|
||||
assert (lfs.link (tmpfile, "_a_hard_link_for_test_"))
|
||||
assert (lfs.attributes (tmpfile, "nlink") == 2)
|
||||
assert (os.remove"_a_link_for_test_")
|
||||
assert (os.remove"_a_hard_link_for_test_")
|
||||
end
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
end
|
||||
|
||||
-- Checking text/binary modes (only has an effect in Windows)
|
||||
local f = io.open(tmpfile, "w")
|
||||
local result, mode = lfs.setmode(f, "binary")
|
||||
assert(result) -- on non-Windows platforms, mode is always returned as "binary"
|
||||
result, mode = lfs.setmode(f, "text")
|
||||
assert(result and mode == "binary")
|
||||
f:close()
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Restore access time to current value
|
||||
assert (lfs.touch (tmpfile, attrib.access, attrib.modification))
|
||||
new_att = assert (lfs.attributes (tmpfile))
|
||||
assert (new_att.access == attrib.access)
|
||||
assert (new_att.modification == attrib.modification)
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Remove new file and directory
|
||||
assert (os.remove (tmpfile), "could not remove new file")
|
||||
assert (lfs.rmdir (tmpdir), "could not remove new directory")
|
||||
assert (lfs.mkdir (tmpdir..sep.."lfs_tmp_dir") == nil, "could create a directory inside a non-existent one")
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Trying to get attributes of a non-existent file
|
||||
assert (lfs.attributes ("this couldn't be an actual file") == nil, "could get attributes of a non-existent file")
|
||||
assert (type(lfs.attributes (upper)) == "table", "couldn't get attributes of upper directory")
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Stressing directory iterator
|
||||
count = 0
|
||||
for i = 1, 4000 do
|
||||
for file in lfs.dir (tmp) do
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Stressing directory iterator, explicit version
|
||||
count = 0
|
||||
for i = 1, 4000 do
|
||||
local iter, dir = lfs.dir(tmp)
|
||||
local file = dir:next()
|
||||
while file do
|
||||
count = count + 1
|
||||
file = dir:next()
|
||||
end
|
||||
assert(not pcall(dir.next, dir))
|
||||
end
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- directory explicit close
|
||||
local iter, dir = lfs.dir(tmp)
|
||||
dir:close()
|
||||
assert(not pcall(dir.next, dir))
|
||||
print"Ok!"
|
||||
#!/usr/bin/env lua5.1
|
||||
|
||||
local tmp = "/tmp"
|
||||
local sep = string.match (package.config, "[^\n]+")
|
||||
local upper = ".."
|
||||
|
||||
local lfs = require"lfs"
|
||||
print (lfs._VERSION)
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
function attrdir (path)
|
||||
for file in lfs.dir(path) do
|
||||
if file ~= "." and file ~= ".." then
|
||||
local f = path..sep..file
|
||||
print ("\t=> "..f.." <=")
|
||||
local attr = lfs.attributes (f)
|
||||
assert (type(attr) == "table")
|
||||
if attr.mode == "directory" then
|
||||
attrdir (f)
|
||||
else
|
||||
for name, value in pairs(attr) do
|
||||
print (name, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Checking changing directories
|
||||
local current = assert (lfs.currentdir())
|
||||
local reldir = string.gsub (current, "^.*%"..sep.."([^"..sep.."])$", "%1")
|
||||
assert (lfs.chdir (upper), "could not change to upper directory")
|
||||
assert (lfs.chdir (reldir), "could not change back to current directory")
|
||||
assert (lfs.currentdir() == current, "error trying to change directories")
|
||||
assert (lfs.chdir ("this couldn't be an actual directory") == nil, "could change to a non-existent directory")
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Changing creating and removing directories
|
||||
local tmpdir = current..sep.."lfs_tmp_dir"
|
||||
local tmpfile = tmpdir..sep.."tmp_file"
|
||||
-- Test for existence of a previous lfs_tmp_dir
|
||||
-- that may have resulted from an interrupted test execution and remove it
|
||||
if lfs.chdir (tmpdir) then
|
||||
assert (lfs.chdir (upper), "could not change to upper directory")
|
||||
assert (os.remove (tmpfile), "could not remove file from previous test")
|
||||
assert (lfs.rmdir (tmpdir), "could not remove directory from previous test")
|
||||
end
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- tries to create a directory
|
||||
assert (lfs.mkdir (tmpdir), "could not make a new directory")
|
||||
local attrib, errmsg = lfs.attributes (tmpdir)
|
||||
if not attrib then
|
||||
error ("could not get attributes of file `"..tmpdir.."':\n"..errmsg)
|
||||
end
|
||||
local f = io.open(tmpfile, "w")
|
||||
f:close()
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Change access time
|
||||
local testdate = os.time({ year = 2007, day = 10, month = 2, hour=0})
|
||||
assert (lfs.touch (tmpfile, testdate))
|
||||
local new_att = assert (lfs.attributes (tmpfile))
|
||||
assert (new_att.access == testdate, "could not set access time")
|
||||
assert (new_att.modification == testdate, "could not set modification time")
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Change access and modification time
|
||||
local testdate1 = os.time({ year = 2007, day = 10, month = 2, hour=0})
|
||||
local testdate2 = os.time({ year = 2007, day = 11, month = 2, hour=0})
|
||||
|
||||
assert (lfs.touch (tmpfile, testdate2, testdate1))
|
||||
local new_att = assert (lfs.attributes (tmpfile))
|
||||
assert (new_att.access == testdate2, "could not set access time")
|
||||
assert (new_att.modification == testdate1, "could not set modification time")
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Checking link (does not work on Windows)
|
||||
if lfs.link (tmpfile, "_a_link_for_test_", true) then
|
||||
assert (lfs.attributes"_a_link_for_test_".mode == "file")
|
||||
assert (lfs.symlinkattributes"_a_link_for_test_".mode == "link")
|
||||
assert (lfs.symlinkattributes"_a_link_for_test_".target == tmpfile)
|
||||
assert (lfs.symlinkattributes("_a_link_for_test_", "target") == tmpfile)
|
||||
assert (lfs.link (tmpfile, "_a_hard_link_for_test_"))
|
||||
assert (lfs.attributes (tmpfile, "nlink") == 2)
|
||||
assert (os.remove"_a_link_for_test_")
|
||||
assert (os.remove"_a_hard_link_for_test_")
|
||||
end
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Checking text/binary modes (only has an effect in Windows)
|
||||
local f = io.open(tmpfile, "w")
|
||||
local result, mode = lfs.setmode(f, "binary")
|
||||
assert(result) -- on non-Windows platforms, mode is always returned as "binary"
|
||||
result, mode = lfs.setmode(f, "text")
|
||||
assert(result and mode == "binary")
|
||||
f:close()
|
||||
local ok, err = pcall(lfs.setmode, f, "binary")
|
||||
assert(not ok, "could setmode on closed file")
|
||||
assert(err:find("closed file"), "bad error message for setmode on closed file")
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Restore access time to current value
|
||||
assert (lfs.touch (tmpfile, attrib.access, attrib.modification))
|
||||
new_att = assert (lfs.attributes (tmpfile))
|
||||
assert (new_att.access == attrib.access)
|
||||
assert (new_att.modification == attrib.modification)
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Check consistency of lfs.attributes values
|
||||
local attr = lfs.attributes (tmpfile)
|
||||
for key, value in pairs(attr) do
|
||||
assert (value == lfs.attributes (tmpfile, key),
|
||||
"lfs.attributes values not consistent")
|
||||
end
|
||||
|
||||
-- Check that lfs.attributes accepts a table as second argument
|
||||
local attr2 = {}
|
||||
lfs.attributes(tmpfile, attr2)
|
||||
for key, value in pairs(attr2) do
|
||||
assert (value == lfs.attributes (tmpfile, key),
|
||||
"lfs.attributes values with table argument not consistent")
|
||||
end
|
||||
|
||||
-- Check that extra arguments are ignored
|
||||
lfs.attributes(tmpfile, attr2, nil)
|
||||
|
||||
-- Remove new file and directory
|
||||
assert (os.remove (tmpfile), "could not remove new file")
|
||||
assert (lfs.rmdir (tmpdir), "could not remove new directory")
|
||||
assert (lfs.mkdir (tmpdir..sep.."lfs_tmp_dir") == nil, "could create a directory inside a non-existent one")
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Trying to get attributes of a non-existent file
|
||||
local attr_ok, err, errno = lfs.attributes("this couldn't be an actual file")
|
||||
assert(attr_ok == nil, "could get attributes of a non-existent file")
|
||||
assert(type(err) == "string", "failed lfs.attributes did not return an error message")
|
||||
assert(type(errno) == "number", "failed lfs.attributes did not return error code")
|
||||
assert (type(lfs.attributes (upper)) == "table", "couldn't get attributes of upper directory")
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Stressing directory iterator
|
||||
count = 0
|
||||
for i = 1, 4000 do
|
||||
for file in lfs.dir (tmp) do
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- Stressing directory iterator, explicit version
|
||||
count = 0
|
||||
for i = 1, 4000 do
|
||||
local iter, dir = lfs.dir(tmp)
|
||||
local file = dir:next()
|
||||
while file do
|
||||
count = count + 1
|
||||
file = dir:next()
|
||||
end
|
||||
assert(not pcall(dir.next, dir))
|
||||
end
|
||||
|
||||
io.write(".")
|
||||
io.flush()
|
||||
|
||||
-- directory explicit close
|
||||
local iter, dir = lfs.dir(tmp)
|
||||
dir:close()
|
||||
assert(not pcall(dir.next, dir))
|
||||
print"Ok!"
|
||||
|
||||
Reference in New Issue
Block a user