2 Commits

Author SHA1 Message Date
Hisham
a1015fe395 Lua 5.1 compatibility 2016-06-20 20:40:01 -03:00
Hisham
2e068eb438 Add a 'target' field for symlinkattributes.
It returns the resolved path of the symlink.
2016-06-20 20:32:20 -03:00
3 changed files with 68 additions and 1 deletions

View File

@@ -242,6 +242,8 @@ LuaFileSystem offers the following functions:
<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).
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 On Windows this function does not yet support links, and is identical to
<code>lfs.attributes</code>. <code>lfs.attributes</code>.
</dd> </dd>

View File

@@ -849,11 +849,74 @@ 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;
int size, tsize;
if (lua_type(L, -1) == LUA_TTABLE) {
/* when symlinkattributes collects the whole table,
get the size from it */
lua_getfield(L, -1, "size");
int size_type = lua_type(L, -1);
if (size_type != LUA_TNUMBER) {
lua_pop(L, 1);
errno = EINVAL;
return 0;
}
size = lua_tointeger(L, -1);
lua_pop(L, 1);
} else {
/* when we are just getting 'target', we need to run
lstat ourselves to get the size */
STAT_STRUCT info;
if (LSTAT_FUNC(file, &info)) {
return 0;
}
size = info.st_size;
}
target = (char*) malloc(size + 1);
if (!target) {
return 0;
}
tsize = readlink(file, target, size);
if (tsize != size) {
free(target);
return 0;
}
target[tsize] = '\0';
lua_pushlstring(L, target, tsize);
free(target);
return 1;
#endif
}
/* /*
** Get symbolic link information using lstat. ** Get symbolic link information using lstat.
*/ */
static int link_info (lua_State *L) { 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;
} }

View File

@@ -91,6 +91,8 @@ io.flush()
if lfs.link (tmpfile, "_a_link_for_test_", true) then if lfs.link (tmpfile, "_a_link_for_test_", true) then
assert (lfs.attributes"_a_link_for_test_".mode == "file") 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_".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.link (tmpfile, "_a_hard_link_for_test_"))
assert (lfs.attributes (tmpfile, "nlink") == 2) assert (lfs.attributes (tmpfile, "nlink") == 2)
assert (os.remove"_a_link_for_test_") assert (os.remove"_a_link_for_test_")