Merge pull request #78 from n1tehawk/20160716_symlink-target

Add a 'target' field for symlinkattributes.
This commit is contained in:
Hisham Muhammad
2016-07-17 22:10:31 -03:00
committed by GitHub
3 changed files with 52 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,58 @@ 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. ** 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_")