aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2016-07-17 22:10:31 -0300
committerGitHub <noreply@github.com>2016-07-17 22:10:31 -0300
commit4cf702d85069db13f04b06dbe1ce4b1a0314dafc (patch)
treeffcda689b162126d3793a1f0b62ab05eec287250
parent080f74f785b2f30708ae797c15fca95a418b028a (diff)
parent32b355a9902e6ce7aae68926fc3f2d05856fc299 (diff)
downloadluafilesystem-4cf702d85069db13f04b06dbe1ce4b1a0314dafc.tar.gz
luafilesystem-4cf702d85069db13f04b06dbe1ce4b1a0314dafc.tar.bz2
luafilesystem-4cf702d85069db13f04b06dbe1ce4b1a0314dafc.zip
Merge pull request #78 from n1tehawk/20160716_symlink-target
Add a 'target' field for symlinkattributes.
-rw-r--r--doc/us/manual.html2
-rw-r--r--src/lfs.c49
-rw-r--r--tests/test.lua2
3 files changed, 52 insertions, 1 deletions
diff --git a/doc/us/manual.html b/doc/us/manual.html
index f5fbaf6..0ecb625 100644
--- a/doc/us/manual.html
+++ b/doc/us/manual.html
@@ -242,6 +242,8 @@ LuaFileSystem offers the following functions:
242 <dt><a name="symlinkattributes"></a><strong><code>lfs.symlinkattributes (filepath [, aname])</code></strong></dt> 242 <dt><a name="symlinkattributes"></a><strong><code>lfs.symlinkattributes (filepath [, aname])</code></strong></dt>
243 <dd>Identical to <a href="#attributes">lfs.attributes</a> except that 243 <dd>Identical to <a href="#attributes">lfs.attributes</a> except that
244 it obtains information about the link itself (not the file it refers to). 244 it obtains information about the link itself (not the file it refers to).
245 It also adds a <strong><code>target</code></strong> field, containing
246 the file name that the symlink points to.
245 On Windows this function does not yet support links, and is identical to 247 On Windows this function does not yet support links, and is identical to
246 <code>lfs.attributes</code>. 248 <code>lfs.attributes</code>.
247 </dd> 249 </dd>
diff --git a/src/lfs.c b/src/lfs.c
index 446373c..93c1419 100644
--- a/src/lfs.c
+++ b/src/lfs.c
@@ -850,10 +850,57 @@ static int file_info (lua_State *L) {
850 850
851 851
852/* 852/*
853** Push the symlink target to the top of the stack.
854** Assumes the file name is at position 1 of the stack.
855** Returns 1 if successful (with the target on top of the stack),
856** 0 on failure (with stack unchanged, and errno set).
857*/
858static int push_link_target(lua_State *L) {
859#ifdef _WIN32
860 errno = ENOSYS;
861 return 0;
862#else
863 const char *file = luaL_checkstring(L, 1);
864 char *target = NULL;
865 int tsize, size = 256; /* size = initial buffer capacity */
866 while (1) {
867 target = realloc(target, size);
868 if (!target) /* failed to allocate */
869 return 0;
870 tsize = readlink(file, target, size);
871 if (tsize < 0) { /* a readlink() error occurred */
872 free(target);
873 return 0;
874 }
875 if (tsize < size)
876 break;
877 /* possibly truncated readlink() result, double size and retry */
878 size *= 2;
879 }
880 target[tsize] = '\0';
881 lua_pushlstring(L, target, tsize);
882 free(target);
883 return 1;
884#endif
885}
886
887/*
853** Get symbolic link information using lstat. 888** Get symbolic link information using lstat.
854*/ 889*/
855static int link_info (lua_State *L) { 890static int link_info (lua_State *L) {
856 return _file_info_ (L, LSTAT_FUNC); 891 int ret;
892 if (lua_isstring (L, 2) && (strcmp(lua_tostring(L, 2), "target") == 0)) {
893 int ok = push_link_target(L);
894 return ok ? 1 : pusherror(L, "could not obtain link target");
895 }
896 ret = _file_info_ (L, LSTAT_FUNC);
897 if (ret == 1 && lua_type(L, -1) == LUA_TTABLE) {
898 int ok = push_link_target(L);
899 if (ok) {
900 lua_setfield(L, -2, "target");
901 }
902 }
903 return ret;
857} 904}
858 905
859 906
diff --git a/tests/test.lua b/tests/test.lua
index 2842bc0..2331eec 100644
--- a/tests/test.lua
+++ b/tests/test.lua
@@ -91,6 +91,8 @@ io.flush()
91if lfs.link (tmpfile, "_a_link_for_test_", true) then 91if lfs.link (tmpfile, "_a_link_for_test_", true) then
92 assert (lfs.attributes"_a_link_for_test_".mode == "file") 92 assert (lfs.attributes"_a_link_for_test_".mode == "file")
93 assert (lfs.symlinkattributes"_a_link_for_test_".mode == "link") 93 assert (lfs.symlinkattributes"_a_link_for_test_".mode == "link")
94 assert (lfs.symlinkattributes"_a_link_for_test_".target == tmpfile)
95 assert (lfs.symlinkattributes("_a_link_for_test_", "target") == tmpfile)
94 assert (lfs.link (tmpfile, "_a_hard_link_for_test_")) 96 assert (lfs.link (tmpfile, "_a_hard_link_for_test_"))
95 assert (lfs.attributes (tmpfile, "nlink") == 2) 97 assert (lfs.attributes (tmpfile, "nlink") == 2)
96 assert (os.remove"_a_link_for_test_") 98 assert (os.remove"_a_link_for_test_")