diff --git a/src/host/path_getabsolute.c b/src/host/path_getabsolute.c old mode 100644 new mode 100755 index e8e60d35..62ec7af4 --- a/src/host/path_getabsolute.c +++ b/src/host/path_getabsolute.c @@ -8,15 +8,21 @@ #include -static void getabsolute(char* result, const char* value) +static void getabsolute(char* result, const char* value, const char* relative_to) { int i; char* ch; + char* prev; char buffer[0x4000] = { '\0' }; /* if the path is not already absolute, base it on working dir */ if (!do_isabsolute(value)) { - do_getcwd(buffer, 0x4000); + if (relative_to) { + strcpy(buffer, relative_to); + } + else { + do_getcwd(buffer, 0x4000); + } strcat(buffer, "/"); } @@ -30,10 +36,11 @@ static void getabsolute(char* result, const char* value) strcat(result, "/"); } + prev = NULL; ch = strtok(buffer, "/"); while (ch) { - /* remove ".." */ - if (strcmp(ch, "..") == 0) { + /* remove ".." where I can */ + if (strcmp(ch, "..") == 0 && (prev == NULL || (prev[0] != '$' && strcmp(prev, "..") != 0))) { i = strlen(result) - 2; while (i >= 0 && result[i] != '/') { --i; @@ -41,6 +48,7 @@ static void getabsolute(char* result, const char* value) if (i >= 0) { result[i + 1] = '\0'; } + ch = NULL; } /* allow everything except "." */ @@ -49,6 +57,7 @@ static void getabsolute(char* result, const char* value) strcat(result, "/"); } + prev = ch; ch = strtok(NULL, "/"); } @@ -62,26 +71,32 @@ static void getabsolute(char* result, const char* value) int path_getabsolute(lua_State* L) { + const char* relative_to; char buffer[0x4000]; + relative_to = NULL; + if (lua_gettop(L) > 1 && !lua_isnil(L,2)) { + relative_to = luaL_checkstring(L, 2); + } + if (lua_istable(L, 1)) { int i = 0; lua_newtable(L); lua_pushnil(L); while (lua_next(L, 1)) { - const char* value = luaL_checkstring(L, 4); - getabsolute(buffer, value); + const char* value = luaL_checkstring(L, -1); + getabsolute(buffer, value, relative_to); lua_pop(L, 1); lua_pushnumber(L, ++i); lua_pushstring(L, buffer); - lua_settable(L, 2); + lua_settable(L, -4); } return 1; } else { const char* value = luaL_checkstring(L, 1); - getabsolute(buffer, value); + getabsolute(buffer, value, relative_to); lua_pushstring(L, buffer); return 1; } diff --git a/tests/base/test_path.lua b/tests/base/test_path.lua old mode 100644 new mode 100755 index 5c5f73b6..4f31951b --- a/tests/base/test_path.lua +++ b/tests/base/test_path.lua @@ -64,6 +64,31 @@ test.isequal({ "/a/b", "/c/d" }, path.getabsolute({ "/a/b", "/c/d" })) end + function suite.getabsolute_withRelativeTo() + local relto = path.getdirectory(os.getcwd()) + local expected = relto .. "/a/b/c" + test.isequal(expected, path.getabsolute("a/b/c", relto)) + end + + function suite.getabsolute_withRelativeTo_withTrailingSlashes() + local relto = path.getdirectory(os.getcwd()) + local expected = relto .. "/a/b/c" + test.isequal(expected, path.getabsolute("a/b/c", relto .. "/")) + end + + function suite.getabsolute_acceptsTables_withRelativeTo() + local relto = path.getdirectory(os.getcwd()) + test.isequal({ relto .. "/a/b", relto .. "/c/d" }, path.getabsolute({ "a/b", "c/d" }, relto)) + end + + function suite.getabsolute_leavesDotDot_onShellVar() + test.isequal("$ORIGIN/../libs", path.getabsolute("$ORIGIN/../libs")) + end + + function suite.getabsolute_leavesDotDot2_onShellVar() + test.isequal("$ORIGIN/../../libs", path.getabsolute("$ORIGIN/../../libs")) + end + -- -- path.getbasename() tests