diff options
-rw-r--r-- | .travis.yml | 6 | ||||
-rw-r--r-- | README.md | 9 | ||||
-rw-r--r-- | doc/us/license.html | 2 | ||||
-rw-r--r-- | doc/us/manual.html | 6 | ||||
-rw-r--r-- | src/lfs.c | 151 | ||||
-rw-r--r-- | src/lfs.h | 2 | ||||
-rw-r--r-- | tests/test.lua | 13 |
7 files changed, 130 insertions, 59 deletions
diff --git a/.travis.yml b/.travis.yml index 04d46ac..38086ba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,16 +7,16 @@ env: - LUA="lua 5.2" - LUA="lua 5.3" - LUA="luajit 2.0" + - LUA="luajit 2.1" before_install: - pip install --user cpp-coveralls hererocks - hererocks env --$LUA --luarocks latest - export PATH="$PWD/env/bin:$PATH" - - luarocks install Lua-cURL --server=https://luarocks.org/dev - luarocks install lua-path - - luarocks install lua-cjson + - luarocks install dkjson - luarocks install luacov - # install luacov-coveralls, but avoids installing luafilesystem + # install luacov-coveralls, but avoid installing luafilesystem - luarocks install luacov-coveralls --server=https://luarocks.org/dev --deps-mode=none install: @@ -1,12 +1,13 @@ -[![Licence](http://img.shields.io/badge/Licence-MIT-brightgreen.svg)](LICENCE.txt) +[![License](http://img.shields.io/badge/Licence-MIT-brightgreen.svg)](LICENSE) [![Build Status](https://travis-ci.org/keplerproject/luafilesystem.svg?branch=master)](https://travis-ci.org/keplerproject/luafilesystem) [![Build status](https://ci.appveyor.com/api/projects/status/y04s4ms7u16trw8e?svg=true)](https://ci.appveyor.com/project/ignacio/luafilesystem) [![Coverage Status](https://coveralls.io/repos/keplerproject/luafilesystem/badge.png)](https://coveralls.io/r/keplerproject/luafilesystem) # LuaFileSystem - File System Library for Lua -Copyright 2003-2016 Kepler Project -http://keplerproject.github.io/luafilesystem +Copyright 2003-2017 Kepler Project + +https://keplerproject.github.io/luafilesystem # Description @@ -14,7 +15,7 @@ LuaFileSystem is a Lua library developed to complement the set of functions related to file systems offered by the standard Lua distribution. LuaFileSystem offers a portable way to access the underlying directory structure and file attributes. -LuaFileSystem is free software and uses the same license as Lua 5.1 +LuaFileSystem is free software and uses the same license as Lua 5.x (MIT). # LuaRocks Installation diff --git a/doc/us/license.html b/doc/us/license.html index 5048c11..4f828cf 100644 --- a/doc/us/license.html +++ b/doc/us/license.html @@ -84,7 +84,7 @@ Ierusalimschy, André Carregal and Tomás Guisasola. The implementation is not derived from licensed software.</p> <hr/> -<p>Copyright © 2003 Kepler Project.</p> +<p>Copyright © 2003 - 2017 Kepler Project.</p> <p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation diff --git a/doc/us/manual.html b/doc/us/manual.html index beffe03..3555e3d 100644 --- a/doc/us/manual.html +++ b/doc/us/manual.html @@ -177,7 +177,7 @@ LuaFileSystem offers the following functions: Returns <code>true</code> in case of success or <code>nil</code> plus an error string.</dd> - <dt><a name="chdir"></a><strong><code>lfs.lock_dir(path, [seconds_stale])</code></strong></dt> + <dt><a name="lock_dir"></a><strong><code>lfs.lock_dir(path, [seconds_stale])</code></strong></dt> <dd>Creates a lockfile (called lockfile.lfs) in <code>path</code> if it does not exist and returns the lock. If the lock already exists checks if it's stale, using the second parameter (default for the second @@ -187,7 +187,7 @@ LuaFileSystem offers the following functions: particular, if the lock exists and is not stale it returns the "File exists" message.</dd> - <dt><a name="getcwd"></a><strong><code>lfs.currentdir ()</code></strong></dt> + <dt><a name="currentdir"></a><strong><code>lfs.currentdir ()</code></strong></dt> <dd>Returns a string with the current working directory or <code>nil</code> plus an error string.</dd> @@ -242,6 +242,8 @@ LuaFileSystem offers the following functions: <dt><a name="symlinkattributes"></a><strong><code>lfs.symlinkattributes (filepath [, aname])</code></strong></dt> <dd>Identical to <a href="#attributes">lfs.attributes</a> except that it obtains information about the link itself (not the file it refers to). + It also adds a <strong><code>target</code></strong> field, containing + the file name that the symlink points to. On Windows this function does not yet support links, and is identical to <code>lfs.attributes</code>. </dd> @@ -1,6 +1,6 @@ /* ** LuaFileSystem -** Copyright Kepler Project 2003 - 2016 (http://keplerproject.github.io/luafilesystem) +** Copyright Kepler Project 2003 - 2017 (http://keplerproject.github.io/luafilesystem) ** ** File system manipulation library. ** This library offers these functions: @@ -41,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> -#else - #include <sys/utime.h> -#endif -#include <fcntl.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 <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> @@ -76,8 +80,10 @@ #endif -#if LUA_VERSION_NUM < 502 -# define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l)) +#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 */ @@ -85,22 +91,6 @@ #define strerror(_) "System unable to describe the error" #endif -/* Define 'getcwd' for systems that do not implement it */ -#ifdef NO_GETCWD -#define getcwd(p,s) NULL -#define getcwd_error "Function 'getcwd' not provided by system" -#else -#define getcwd_error strerror(errno) - #ifdef _WIN32 - /* MAX_PATH seems to be 260. Seems kind of small. Is there a better one? */ - #define LFS_MAXPATHLEN MAX_PATH - #else - /* For MAXPATHLEN: */ - #include <sys/param.h> - #define LFS_MAXPATHLEN MAXPATHLEN - #endif -#endif - #define DIR_METATABLE "directory metatable" typedef struct dir_data { int closed; @@ -186,18 +176,35 @@ static int change_dir (lua_State *L) { ** and a string describing the error */ static int get_dir (lua_State *L) { - char *path; - /* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */ - char buf[LFS_MAXPATHLEN]; - if ((path = getcwd(buf, LFS_MAXPATHLEN)) == NULL) { +#ifdef NO_GETCWD lua_pushnil(L); - lua_pushstring(L, getcwd_error); + lua_pushstring(L, "Function 'getcwd' not provided by system"); return 2; - } - else { - lua_pushstring(L, path); - return 1; - } +#else + char *path = NULL; + /* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */ + size_t size = LFS_MAXPATHLEN; /* initial buffer size */ + int result; + while (1) { + path = realloc(path, size); + if (!path) /* failed to allocate */ + return pusherror(L, "get_dir realloc() failed"); + if (getcwd(path, size) != NULL) { + /* success, push the path to the Lua stack */ + lua_pushstring(L, path); + result = 1; + break; + } + if (errno != ERANGE) { /* unexpected error */ + result = pusherror(L, "get_dir getcwd() failed"); + break; + } + /* ERANGE = insufficient buffer capacity, double size and retry */ + size *= 2; + } + free(path); + return result; +#endif } /* @@ -815,7 +822,8 @@ static int _file_info_ (lua_State *L, int (*st)(const char*, STAT_STRUCT*)) { /* member not found */ return luaL_error(L, "invalid attribute name '%s'", member); } - /* creates a table if none is given */ + /* creates a table if none is given, removes extra arguments */ + lua_settop(L, 2); if (!lua_istable (L, 2)) { lua_newtable (L); } @@ -838,10 +846,57 @@ 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) { + target = realloc(target, size); + if (!target) /* failed to allocate */ + return 0; + 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; } @@ -849,7 +904,7 @@ 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 (C) 2003-2016 Kepler Project"); + 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"); @@ -878,7 +933,7 @@ static const struct luaL_Reg fslib[] = { 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); @@ -1,6 +1,6 @@ /* ** LuaFileSystem -** Copyright Kepler Project 2003 - 2016 (http://keplerproject.github.io/luafilesystem) +** Copyright Kepler Project 2003 - 2017 (http://keplerproject.github.io/luafilesystem) */ /* Define 'chdir' for systems that do not implement it */ diff --git a/tests/test.lua b/tests/test.lua index 193e0bd..591ee25 100644 --- a/tests/test.lua +++ b/tests/test.lua @@ -91,6 +91,8 @@ io.flush() 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_") @@ -130,6 +132,17 @@ for key, value in pairs(attr) do "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") |