mirror of
https://github.com/lunarmodules/luafilesystem.git
synced 2026-07-24 12:23:08 +00:00
Merge pull request #8 from rrthomas/master
New lfs.link and other goodies
This commit is contained in:
@@ -174,7 +174,7 @@ LuaFileSystem offers the following functions:
|
|||||||
|
|
||||||
<dt><a name="chdir"></a><strong><code>lfs.lock_dir(path, [seconds_stale])</code></strong></dt>
|
<dt><a name="chdir"></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
|
<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 it
|
exist and returns the lock. If the lock already exists checks if
|
||||||
it's stale, using the second parameter (default for the second
|
it's stale, using the second parameter (default for the second
|
||||||
parameter is <code>INT_MAX</code>, which in practice means the lock will never
|
parameter is <code>INT_MAX</code>, which in practice means the lock will never
|
||||||
be stale. To free the the lock call <code>lock:free()</code>. <br/>
|
be stale. To free the the lock call <code>lock:free()</code>. <br/>
|
||||||
@@ -206,6 +206,13 @@ LuaFileSystem offers the following functions:
|
|||||||
Returns <code>true</code> if the operation was successful; in
|
Returns <code>true</code> if the operation was successful; in
|
||||||
case of error, it returns <code>nil</code> plus an error string.
|
case of error, it returns <code>nil</code> plus an error string.
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
|
<dt><a name="link"></a><strong><code>lfs.link (old, new[, symlink])</code></strong></dt>
|
||||||
|
<dd>Creates a link. The first argument is the object to link to
|
||||||
|
and the second is the name of the link. If the optional third
|
||||||
|
argument is true, the link will by a symbolic link (by default, a
|
||||||
|
hard link is created).
|
||||||
|
</dd>
|
||||||
|
|
||||||
<dt><a name="mkdir"></a><strong><code>lfs.mkdir (dirname)</code></strong></dt>
|
<dt><a name="mkdir"></a><strong><code>lfs.mkdir (dirname)</code></strong></dt>
|
||||||
<dd>Creates a new directory. The argument is the name of the new
|
<dd>Creates a new directory. The argument is the name of the new
|
||||||
@@ -221,15 +228,15 @@ LuaFileSystem offers the following functions:
|
|||||||
|
|
||||||
<dt><a name="setmode"></a><strong><code>lfs.setmode (file, mode)</code></strong></dt>
|
<dt><a name="setmode"></a><strong><code>lfs.setmode (file, mode)</code></strong></dt>
|
||||||
<dd>Sets the writing mode for a file. The mode string can be either <code>binary</code> or <code>text</code>.
|
<dd>Sets the writing mode for a file. The mode string can be either <code>binary</code> or <code>text</code>.
|
||||||
Returns the previous mode string for the file. This function is only available in Windows, so you may want to make sure that
|
Returns the previous mode string for the file. On non-Windows platforms, where the two modes are identical,
|
||||||
<code>lfs.setmode</code> exists before using it.
|
setting the mode has no effect, and the mode is always returned as <code>binary</code>.
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a name="symlinkattributes"></a><strong><code>lfs.symlinkattributes (filepath [, aname])</code></strong></dt>
|
<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
|
<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 obtains information about the link itself (not the file it refers to).
|
||||||
This function is not available in Windows so you may want to make sure that
|
On Windows this function does not yet support links, and is identical to
|
||||||
<code>lfs.symlinkattributes</code> exists before using it.
|
<code>lfs.attributes</code>.
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a name="touch"></a><strong><code>lfs.touch (filepath [, atime [, mtime]])</code></strong></dt>
|
<dt><a name="touch"></a><strong><code>lfs.touch (filepath [, atime [, mtime]])</code></strong></dt>
|
||||||
|
|||||||
2
src/.gitignore
vendored
Normal file
2
src/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*.o
|
||||||
|
*.so
|
||||||
101
src/lfs.c
101
src/lfs.c
@@ -96,16 +96,39 @@ typedef struct dir_data {
|
|||||||
#define STAT_STRUCT struct _stati64
|
#define STAT_STRUCT struct _stati64
|
||||||
#endif
|
#endif
|
||||||
#define STAT_FUNC _stati64
|
#define STAT_FUNC _stati64
|
||||||
|
#define LSTAT_FUNC STAT_FUNC
|
||||||
#else
|
#else
|
||||||
#define _O_TEXT 0
|
#define _O_TEXT 0
|
||||||
#define _O_BINARY 0
|
#define _O_BINARY 0
|
||||||
#define lfs_setmode(L,file,m) ((void)((void)file,m), \
|
#define lfs_setmode(L,file,m) 0
|
||||||
luaL_error(L, LUA_QL("setmode") " not supported on this platform"), -1)
|
|
||||||
#define STAT_STRUCT struct stat
|
#define STAT_STRUCT struct stat
|
||||||
#define STAT_FUNC stat
|
#define STAT_FUNC stat
|
||||||
#define LSTAT_FUNC lstat
|
#define LSTAT_FUNC lstat
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Utility functions
|
||||||
|
*/
|
||||||
|
static int pusherror(lua_State *L, const char *info)
|
||||||
|
{
|
||||||
|
lua_pushnil(L);
|
||||||
|
if (info==NULL)
|
||||||
|
lua_pushstring(L, strerror(errno));
|
||||||
|
else
|
||||||
|
lua_pushfstring(L, "%s: %s", info, strerror(errno));
|
||||||
|
lua_pushinteger(L, errno);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This function changes the working (current) directory
|
** This function changes the working (current) directory
|
||||||
*/
|
*/
|
||||||
@@ -280,10 +303,9 @@ static int lfs_unlock_dir(lua_State *L) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
static int lfs_g_setmode (lua_State *L, FILE *f, int arg) {
|
static int lfs_g_setmode (lua_State *L, FILE *f, int arg) {
|
||||||
static const int mode[] = {_O_TEXT, _O_BINARY};
|
static const int mode[] = {_O_BINARY, _O_TEXT};
|
||||||
static const char *const modenames[] = {"text", "binary", NULL};
|
static const char *const modenames[] = {"binary", "text", NULL};
|
||||||
int op = luaL_checkoption(L, arg, NULL, modenames);
|
int op = luaL_checkoption(L, arg, NULL, modenames);
|
||||||
int res = lfs_setmode(L, f, mode[op]);
|
int res = lfs_setmode(L, f, mode[op]);
|
||||||
if (res != -1) {
|
if (res != -1) {
|
||||||
@@ -306,13 +328,6 @@ static int lfs_g_setmode (lua_State *L, FILE *f, int arg) {
|
|||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
static int lfs_g_setmode (lua_State *L, FILE *f, int arg) {
|
|
||||||
lua_pushboolean(L, 0);
|
|
||||||
lua_pushliteral(L, "setmode not supported on this platform");
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int lfs_f_setmode(lua_State *L) {
|
static int lfs_f_setmode(lua_State *L) {
|
||||||
return lfs_g_setmode(L, check_file(L, 1, "setmode"), 2);
|
return lfs_g_setmode(L, check_file(L, 1, "setmode"), 2);
|
||||||
@@ -362,6 +377,29 @@ static int file_unlock (lua_State *L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Creates a link.
|
||||||
|
** @param #1 Object to link to.
|
||||||
|
** @param #2 Name of link.
|
||||||
|
** @param #3 True if link is symbolic (optional).
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
#else
|
||||||
|
pusherror(L, "make_link is not supported on Windows");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Creates a directory.
|
||||||
|
** @param #1 Directory path.
|
||||||
|
*/
|
||||||
static int make_dir (lua_State *L) {
|
static int make_dir (lua_State *L) {
|
||||||
const char *path = luaL_checkstring (L, 1);
|
const char *path = luaL_checkstring (L, 1);
|
||||||
int fail;
|
int fail;
|
||||||
@@ -473,21 +511,19 @@ static int dir_iter_factory (lua_State *L) {
|
|||||||
dir_data *d;
|
dir_data *d;
|
||||||
lua_pushcfunction (L, dir_iter);
|
lua_pushcfunction (L, dir_iter);
|
||||||
d = (dir_data *) lua_newuserdata (L, sizeof(dir_data));
|
d = (dir_data *) lua_newuserdata (L, sizeof(dir_data));
|
||||||
|
luaL_getmetatable (L, DIR_METATABLE);
|
||||||
|
lua_setmetatable (L, -2);
|
||||||
d->closed = 0;
|
d->closed = 0;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
d->hFile = 0L;
|
d->hFile = 0L;
|
||||||
luaL_getmetatable (L, DIR_METATABLE);
|
|
||||||
lua_setmetatable (L, -2);
|
|
||||||
if (strlen(path) > MAX_PATH-2)
|
if (strlen(path) > MAX_PATH-2)
|
||||||
luaL_error (L, "path too long: %s", path);
|
luaL_error (L, "path too long: %s", path);
|
||||||
else
|
else
|
||||||
sprintf (d->pattern, "%s/*", path);
|
sprintf (d->pattern, "%s/*", path);
|
||||||
#else
|
#else
|
||||||
luaL_getmetatable (L, DIR_METATABLE);
|
|
||||||
lua_setmetatable (L, -2);
|
|
||||||
d->dir = opendir (path);
|
d->dir = opendir (path);
|
||||||
if (d->dir == NULL)
|
if (d->dir == NULL)
|
||||||
luaL_error (L, "cannot open %s: %s", path, strerror (errno));
|
luaL_error (L, "cannot open %s: %s", path, strerror (errno));
|
||||||
#endif
|
#endif
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
@@ -498,19 +534,18 @@ static int dir_iter_factory (lua_State *L) {
|
|||||||
*/
|
*/
|
||||||
static int dir_create_meta (lua_State *L) {
|
static int dir_create_meta (lua_State *L) {
|
||||||
luaL_newmetatable (L, DIR_METATABLE);
|
luaL_newmetatable (L, DIR_METATABLE);
|
||||||
/* set its __gc field */
|
|
||||||
lua_pushstring (L, "__index");
|
/* Method table */
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
lua_pushstring (L, "next");
|
|
||||||
lua_pushcfunction (L, dir_iter);
|
lua_pushcfunction (L, dir_iter);
|
||||||
lua_settable(L, -3);
|
lua_setfield(L, -2, "next");
|
||||||
lua_pushstring (L, "close");
|
|
||||||
lua_pushcfunction (L, dir_close);
|
lua_pushcfunction (L, dir_close);
|
||||||
lua_settable(L, -3);
|
lua_setfield(L, -2, "close");
|
||||||
lua_settable (L, -3);
|
|
||||||
lua_pushstring (L, "__gc");
|
/* Metamethods */
|
||||||
|
lua_setfield(L, -2, "__index");
|
||||||
lua_pushcfunction (L, dir_close);
|
lua_pushcfunction (L, dir_close);
|
||||||
lua_settable (L, -3);
|
lua_setfield (L, -2, "__gc");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,10 +554,13 @@ static int dir_create_meta (lua_State *L) {
|
|||||||
*/
|
*/
|
||||||
static int lock_create_meta (lua_State *L) {
|
static int lock_create_meta (lua_State *L) {
|
||||||
luaL_newmetatable (L, LOCK_METATABLE);
|
luaL_newmetatable (L, LOCK_METATABLE);
|
||||||
/* set its __gc field */
|
|
||||||
|
/* Method table */
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
lua_pushcfunction(L, lfs_unlock_dir);
|
lua_pushcfunction(L, lfs_unlock_dir);
|
||||||
lua_setfield(L, -2, "free");
|
lua_setfield(L, -2, "free");
|
||||||
|
|
||||||
|
/* Metamethods */
|
||||||
lua_setfield(L, -2, "__index");
|
lua_setfield(L, -2, "__index");
|
||||||
lua_pushcfunction(L, lfs_unlock_dir);
|
lua_pushcfunction(L, lfs_unlock_dir);
|
||||||
lua_setfield(L, -2, "__gc");
|
lua_setfield(L, -2, "__gc");
|
||||||
@@ -743,17 +781,9 @@ static int file_info (lua_State *L) {
|
|||||||
/*
|
/*
|
||||||
** Get symbolic link information using lstat.
|
** Get symbolic link information using lstat.
|
||||||
*/
|
*/
|
||||||
#ifndef _WIN32
|
|
||||||
static int link_info (lua_State *L) {
|
static int link_info (lua_State *L) {
|
||||||
return _file_info_ (L, LSTAT_FUNC);
|
return _file_info_ (L, LSTAT_FUNC);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
static int link_info (lua_State *L) {
|
|
||||||
lua_pushboolean(L, 0);
|
|
||||||
lua_pushliteral(L, "symlinkattributes not supported on this platform");
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -777,6 +807,7 @@ static const struct luaL_Reg fslib[] = {
|
|||||||
{"chdir", change_dir},
|
{"chdir", change_dir},
|
||||||
{"currentdir", get_dir},
|
{"currentdir", get_dir},
|
||||||
{"dir", dir_iter_factory},
|
{"dir", dir_iter_factory},
|
||||||
|
{"link", make_link},
|
||||||
{"lock", file_lock},
|
{"lock", file_lock},
|
||||||
{"mkdir", make_dir},
|
{"mkdir", make_dir},
|
||||||
{"rmdir", remove_dir},
|
{"rmdir", remove_dir},
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/local/bin/lua5.1
|
#!/usr/bin/env lua5.1
|
||||||
|
|
||||||
local tmp = "/tmp"
|
local tmp = "/tmp"
|
||||||
local sep = "/"
|
local sep = string.match (package.config, "[^\n]+")
|
||||||
local upper = ".."
|
local upper = ".."
|
||||||
|
|
||||||
require"lfs"
|
require"lfs"
|
||||||
@@ -69,24 +69,23 @@ local new_att = assert (lfs.attributes (tmpfile))
|
|||||||
assert (new_att.access == testdate2, "could not set access time")
|
assert (new_att.access == testdate2, "could not set access time")
|
||||||
assert (new_att.modification == testdate1, "could not set modification time")
|
assert (new_att.modification == testdate1, "could not set modification time")
|
||||||
|
|
||||||
local res, err = lfs.symlinkattributes(tmpfile)
|
-- Checking link (does not work on Windows)
|
||||||
if err ~= "symlinkattributes not supported on this platform" then
|
if lfs.link (tmpfile, "_a_link_for_test_", true) then
|
||||||
-- Checking symbolic link information (does not work in Windows)
|
assert (lfs.attributes"_a_link_for_test_".mode == "file")
|
||||||
assert (os.execute ("ln -s "..tmpfile.." _a_link_for_test_"))
|
assert (lfs.symlinkattributes"_a_link_for_test_".mode == "link")
|
||||||
assert (lfs.attributes"_a_link_for_test_".mode == "file")
|
assert (lfs.link (tmpfile, "_a_hard_link_for_test_"))
|
||||||
assert (lfs.symlinkattributes"_a_link_for_test_".mode == "link")
|
assert (lfs.attributes (tmpfile, "nlink") == 2)
|
||||||
assert (os.remove"_a_link_for_test_")
|
assert (os.remove"_a_link_for_test_")
|
||||||
|
assert (os.remove"_a_hard_link_for_test_")
|
||||||
end
|
end
|
||||||
|
|
||||||
if lfs.setmode then
|
-- Checking text/binary modes (only has an effect in Windows)
|
||||||
-- Checking text/binary modes (works only in Windows)
|
local f = io.open(tmpfile, "w")
|
||||||
local f = io.open(tmpfile, "w")
|
local result, mode = lfs.setmode(f, "binary")
|
||||||
local result, mode = lfs.setmode(f, "binary")
|
assert(result) -- on non-Windows platforms, mode is always returned as "binary"
|
||||||
assert((result and mode == "text") or (not result and mode == "setmode not supported on this platform"))
|
result, mode = lfs.setmode(f, "text")
|
||||||
result, mode = lfs.setmode(f, "text")
|
assert(result and mode == "binary")
|
||||||
assert((result and mode == "binary") or (not result and mode == "setmode not supported on this platform"))
|
f:close()
|
||||||
f:close()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Restore access time to current value
|
-- Restore access time to current value
|
||||||
assert (lfs.touch (tmpfile, attrib.access, attrib.modification))
|
assert (lfs.touch (tmpfile, attrib.access, attrib.modification))
|
||||||
|
|||||||
Reference in New Issue
Block a user