From 56e43a0dde023c5a4595a22b29d800153b31e3c4 Mon Sep 17 00:00:00 2001 From: lethosor Date: Thu, 16 Jul 2020 23:19:38 -0400 Subject: [PATCH] Linux: make Process::getPath (and dfhack.getDFPath()) not depend on cwd, for consistency with other platforms --- docs/changelog.txt | 1 + library/Process-linux.cpp | 31 ++++++++++++++++++++++++------- test/core.lua | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 test/core.lua diff --git a/docs/changelog.txt b/docs/changelog.txt index 2bc506565..15a4383ca 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -39,6 +39,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ## Fixes - Fixed a segfault when attempting to start a headless session with a graphical PRINT_MODE setting - Fixed an issue with the macOS launcher failing to un-quarantine some files +- Linux: fixed ``dfhack.getDFPath()`` (Lua) and ``Process::getPath()`` (C++) to always return the DF root path, even if the working directory has changed - `labormanager`: fixed handling of new jobs in 0.47 - `embark-assistant`: fixed a couple of incursion handling bugs. - Fixed ``Units::isEggLayer``, ``Units::isGrazer``, ``Units::isMilkable``, ``Units::isTrainableHunting``, ``Units::isTrainableWar``, and ``Units::isTamable`` ignoring the unit's caste diff --git a/library/Process-linux.cpp b/library/Process-linux.cpp index a7f09a7f6..45e655948 100644 --- a/library/Process-linux.cpp +++ b/library/Process-linux.cpp @@ -23,11 +23,12 @@ distribution. */ #include "Internal.h" + #include #include -#include #include #include +#include #include #include @@ -180,12 +181,28 @@ uint32_t Process::getTickCount() string Process::getPath() { - const char * cwd_name = "/proc/self/cwd"; - char target_name[1024]; - int target_result; - target_result = readlink(cwd_name, target_name, sizeof(target_name)); - target_name[target_result] = '\0'; - return(string(target_name)); + static string cached_path; + if (cached_path.empty()) + { + const char *exe_name = "/proc/self/exe"; + char exe_path[1024]; + int length = readlink(exe_name, exe_path, sizeof(exe_path)); + if (length > 0) + { + exe_path[length] = '\0'; + string path_string = exe_path; + // DF lives in libs, so move up a folder + cached_path = path_string.substr(0, path_string.find_last_of("/", path_string.find_last_of("/") - 1)); + } + else + { + perror("readlink(/proc/self/exe) failed"); + fprintf(stderr, " length=%i\n", length); + cached_path = "."; + } + fprintf(stderr, "Resolved DF root to %s\n", cached_path.c_str()); + } + return cached_path; } int Process::getPID() diff --git a/test/core.lua b/test/core.lua new file mode 100644 index 000000000..6cde334d4 --- /dev/null +++ b/test/core.lua @@ -0,0 +1,34 @@ +local function clean_path(p) + -- todo: replace with dfhack.filesystem call? + return p:gsub('\\', '/'):gsub('//', '/'):gsub('/$', '') +end + +local fs = dfhack.filesystem +local old_cwd = clean_path(fs.getcwd()) +local function restore_cwd() + fs.chdir(old_cwd) +end + +function test.getDFPath() + expect.eq(clean_path(dfhack.getDFPath()), old_cwd) +end + +function test.getDFPath_chdir() + dfhack.with_finalize(restore_cwd, function() + fs.chdir('data') + expect.eq(clean_path(dfhack.getDFPath()), old_cwd) + expect.ne(clean_path(dfhack.getDFPath()), clean_path(fs.getcwd())) + end) +end + +function test.getHackPath() + expect.eq(clean_path(dfhack.getHackPath()), clean_path(dfhack.getDFPath() .. '/hack/')) +end + +function test.getHackPath_chdir() + dfhack.with_finalize(restore_cwd, function() + fs.chdir('hack') + expect.eq(clean_path(dfhack.getHackPath()), clean_path(old_cwd .. '/hack/')) + expect.eq(clean_path(dfhack.getHackPath()), clean_path(fs.getcwd())) + end) +end