Linux: make Process::getPath (and dfhack.getDFPath()) not depend on cwd, for consistency with other platforms

develop
lethosor 2020-07-16 23:19:38 -04:00
parent 6cafd230c5
commit 56e43a0dde
No known key found for this signature in database
GPG Key ID: 76A269552F4F58C1
3 changed files with 59 additions and 7 deletions

@ -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

@ -23,11 +23,12 @@ distribution.
*/
#include "Internal.h"
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <unistd.h>
#include <string>
#include <vector>
@ -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()

@ -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