From 859ceb25d0beedbe3d048d6c48a1628af389717c Mon Sep 17 00:00:00 2001 From: NiteHawk Date: Tue, 18 Oct 2016 18:41:33 +0200 Subject: [PATCH 1/3] Implement lfs.realpath() For POSIX systems, the function is a straightforward wrapper around realpath() - see "man 3 realpath". On Windows, the CRT function `_fullpath` gets used instead, see https://msdn.microsoft.com/en-us/library/506720ff.aspx --- src/lfs.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/lfs.c b/src/lfs.c index 25122a3..37cd532 100644 --- a/src/lfs.c +++ b/src/lfs.c @@ -909,6 +909,35 @@ static int link_info (lua_State *L) { return ret; } +/* +** Retrieve canonicalized absolute pathname using realpath() +** Upon success the function returns the resolved path, otherwise the return +** values are `nil`, an error message (string) and the error number. +** +** Note that the Windows implementation differs from the POSIX function, +** for example it doesn't test if the resolved path is actually reachable. +** E.g. "C:\foo\..\bar" will happily resolve to "C:\bar", +** even if neither C:\foo nor C:\bar exist. +*/ +static int get_realpath (lua_State *L) { + const char *path = luaL_checkstring (L, 1); + char *resolved; +#ifdef _WIN32 + resolved = _fullpath(NULL, path, 0); +#else + resolved = realpath(path, NULL); +#endif + if (resolved) { + lua_pushstring(L, resolved); + free(resolved); + return 1; + } + /* an error occured */ + lua_pushnil(L); + lua_pushfstring(L, "lfs.realpath('%s') failed: %s", path, strerror(errno)); + lua_pushinteger(L, errno); + return 3; +} /* ** Assumes the table is on top of the stack. @@ -931,6 +960,7 @@ static const struct luaL_Reg fslib[] = { {"link", make_link}, {"lock", file_lock}, {"mkdir", make_dir}, + {"realpath", get_realpath}, {"rmdir", remove_dir}, {"symlinkattributes", link_info}, {"setmode", lfs_f_setmode}, From 84628e479a6dc657f7b4bc1fab0fba50196921fe Mon Sep 17 00:00:00 2001 From: NiteHawk Date: Tue, 18 Oct 2016 18:44:23 +0200 Subject: [PATCH 2/3] Add test cases for lfs.realpath() --- tests/test.lua | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/test.lua b/tests/test.lua index 10810fe..fa2cfd5 100644 --- a/tests/test.lua +++ b/tests/test.lua @@ -65,6 +65,20 @@ f:close() io.write(".") io.flush() +-- Check that realpath can resolve the parent of tmpdir (= "current") +assert(lfs.realpath(tmpdir..sep.."..") == current) + +-- Non-existent paths will error on POSIX (errno 2), but not on Windows! +local ok, err = lfs.realpath("C:\\foo\\..\\bar") +if not ok then + assert(err:match("No such file or directory")) +else + assert(ok == "C:\\bar") +end + +io.write(".") +io.flush() + -- Change access time local testdate = os.time({ year = 2007, day = 10, month = 2, hour=0}) assert (lfs.touch (tmpfile, testdate)) @@ -95,6 +109,7 @@ if lfs.link (tmpfile, "_a_link_for_test_", true) then 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 (lfs.realpath"_a_link_for_test_" == tmpfile) assert (os.remove"_a_link_for_test_") assert (os.remove"_a_hard_link_for_test_") end From 2ad5d9aae9c987250e7e98752b7bd9fa7d0e2c91 Mon Sep 17 00:00:00 2001 From: NiteHawk Date: Wed, 19 Oct 2016 13:41:24 +0200 Subject: [PATCH 3/3] Fixup: Add missing documentation line (Squash with 859ceb2) --- src/lfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lfs.c b/src/lfs.c index 37cd532..1b7b9fa 100644 --- a/src/lfs.c +++ b/src/lfs.c @@ -12,6 +12,7 @@ ** lfs.lock (fh, mode) ** lfs.lock_dir (path) ** lfs.mkdir (path) +** lfs.realpath (path) ** lfs.rmdir (path) ** lfs.setmode (filepath, mode) ** lfs.symlinkattributes (filepath [, attributename])