From ce7772a1c267bdba1f2c305a872fe8b088302a51 Mon Sep 17 00:00:00 2001 From: lethosor Date: Wed, 14 Oct 2020 21:22:53 -0400 Subject: [PATCH 1/4] Add Filesystem::restorecwd() This allows restoring the working directory to its original value, which may not actually be the DF root. See #1671, dfhack/scripts#152 --- docs/Lua API.rst | 4 ++++ library/Core.cpp | 5 ++++- library/LuaApi.cpp | 1 + library/include/modules/Filesystem.h | 2 ++ library/modules/Filesystem.cpp | 17 +++++++++++++++++ 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/Lua API.rst b/docs/Lua API.rst index fb67610d1..b310b449e 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -2160,6 +2160,10 @@ unless otherwise noted. Changes the current directory to ``path``. Use with caution. +* ``dfhack.filesystem.restorecwd()`` + + Restores the current working directory to what it was when DF started. + * ``dfhack.filesystem.mkdir(path)`` Creates a new directory. Returns ``false`` if unsuccessful, including if ``path`` already exists. diff --git a/library/Core.cpp b/library/Core.cpp index c6ce9ea48..ff4ccc98e 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -1618,7 +1618,10 @@ bool Core::Init() freopen("stderr.log", "w", stderr); #endif - fprintf(stderr, "DFHack build: %s\n", Version::git_description()); + Filesystem::init(); + + cerr << "DFHack build: " << Version::git_description() << "\n" + << "Starting with working directory: " << Filesystem::getcwd() << endl; // find out what we are... #ifdef LINUX_BUILD diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index c863a8d4d..d38cb31ba 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -2371,6 +2371,7 @@ static const luaL_Reg dfhack_screen_funcs[] = { static const LuaWrapper::FunctionReg dfhack_filesystem_module[] = { WRAPM(Filesystem, getcwd), + WRAPM(Filesystem, restorecwd), WRAPM(Filesystem, chdir), WRAPM(Filesystem, mkdir), WRAPM(Filesystem, mkdir_recursive), diff --git a/library/include/modules/Filesystem.h b/library/include/modules/Filesystem.h index c9218ba33..eac8a1102 100644 --- a/library/include/modules/Filesystem.h +++ b/library/include/modules/Filesystem.h @@ -146,8 +146,10 @@ enum _filetype { namespace DFHack { namespace Filesystem { + DFHACK_EXPORT void init (); DFHACK_EXPORT bool chdir (std::string path); DFHACK_EXPORT std::string getcwd (); + DFHACK_EXPORT bool restorecwd (); DFHACK_EXPORT bool mkdir (std::string path); // returns true on success or if directory already exists DFHACK_EXPORT bool mkdir_recursive (std::string path); diff --git a/library/modules/Filesystem.cpp b/library/modules/Filesystem.cpp index c0d0860ad..7738bfd5e 100644 --- a/library/modules/Filesystem.cpp +++ b/library/modules/Filesystem.cpp @@ -52,6 +52,18 @@ SOFTWARE. using namespace DFHack; +static bool initialized = false; +static std::string initial_cwd; + +void Filesystem::init () +{ + if (!initialized) + { + initialized = true; + initial_cwd = Filesystem::getcwd(); + } +} + bool Filesystem::chdir (std::string path) { return ::chdir(path.c_str()) == 0; @@ -71,6 +83,11 @@ std::string Filesystem::getcwd () return result; } +bool Filesystem::restorecwd () +{ + return Filesystem::chdir(initial_cwd); +} + bool Filesystem::mkdir (std::string path) { int fail; From 913d860ae47bd8b0e8b24db8520bc33dfd8815d4 Mon Sep 17 00:00:00 2001 From: lethosor Date: Thu, 12 Nov 2020 19:07:51 -0500 Subject: [PATCH 2/4] Use initial working directory as process path on Linux, and expose to Lua --- docs/Lua API.rst | 6 +++- library/LuaApi.cpp | 3 +- library/Process-linux.cpp | 48 ++++++++-------------------- library/include/modules/Filesystem.h | 3 +- library/modules/Filesystem.cpp | 9 +++++- 5 files changed, 30 insertions(+), 39 deletions(-) diff --git a/docs/Lua API.rst b/docs/Lua API.rst index 5939f50cb..80fd0add6 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -2160,10 +2160,14 @@ unless otherwise noted. Changes the current directory to ``path``. Use with caution. -* ``dfhack.filesystem.restorecwd()`` +* ``dfhack.filesystem.restore_cwd()`` Restores the current working directory to what it was when DF started. +* ``dfhack.filesystem.get_initial_cwd()`` + + Returns the value of the working directory when DF was started. + * ``dfhack.filesystem.mkdir(path)`` Creates a new directory. Returns ``false`` if unsuccessful, including if ``path`` already exists. diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index d38cb31ba..431ab3ae5 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -2371,7 +2371,8 @@ static const luaL_Reg dfhack_screen_funcs[] = { static const LuaWrapper::FunctionReg dfhack_filesystem_module[] = { WRAPM(Filesystem, getcwd), - WRAPM(Filesystem, restorecwd), + WRAPM(Filesystem, restore_cwd), + WRAPM(Filesystem, get_initial_cwd), WRAPM(Filesystem, chdir), WRAPM(Filesystem, mkdir), WRAPM(Filesystem, mkdir_recursive), diff --git a/library/Process-linux.cpp b/library/Process-linux.cpp index 45e655948..be3ebb5df 100644 --- a/library/Process-linux.cpp +++ b/library/Process-linux.cpp @@ -22,29 +22,28 @@ must not be misrepresented as being the original software. distribution. */ -#include "Internal.h" - +#include +#include #include #include +#include +#include +#include #include #include #include - -#include #include -#include -#include -#include -#include -using namespace std; -#include +#include "Error.h" +#include "Internal.h" +#include "md5wrapper.h" #include "MemAccess.h" #include "Memory.h" -#include "VersionInfoFactory.h" +#include "modules/Filesystem.h" #include "VersionInfo.h" -#include "Error.h" -#include +#include "VersionInfoFactory.h" + +using namespace std; using namespace DFHack; Process::Process(const VersionInfoFactory& known_versions) : identified(false), my_pe(0) @@ -181,28 +180,7 @@ uint32_t Process::getTickCount() string Process::getPath() { - 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; + return Filesystem::get_initial_cwd(); } int Process::getPID() diff --git a/library/include/modules/Filesystem.h b/library/include/modules/Filesystem.h index eac8a1102..8e7bab9b2 100644 --- a/library/include/modules/Filesystem.h +++ b/library/include/modules/Filesystem.h @@ -149,7 +149,8 @@ namespace DFHack { DFHACK_EXPORT void init (); DFHACK_EXPORT bool chdir (std::string path); DFHACK_EXPORT std::string getcwd (); - DFHACK_EXPORT bool restorecwd (); + DFHACK_EXPORT bool restore_cwd (); + DFHACK_EXPORT std::string get_initial_cwd (); DFHACK_EXPORT bool mkdir (std::string path); // returns true on success or if directory already exists DFHACK_EXPORT bool mkdir_recursive (std::string path); diff --git a/library/modules/Filesystem.cpp b/library/modules/Filesystem.cpp index 7738bfd5e..e0d0bc8c2 100644 --- a/library/modules/Filesystem.cpp +++ b/library/modules/Filesystem.cpp @@ -66,6 +66,7 @@ void Filesystem::init () bool Filesystem::chdir (std::string path) { + Filesystem::init(); return ::chdir(path.c_str()) == 0; } @@ -83,11 +84,17 @@ std::string Filesystem::getcwd () return result; } -bool Filesystem::restorecwd () +bool Filesystem::restore_cwd () { return Filesystem::chdir(initial_cwd); } +std::string Filesystem::get_initial_cwd () +{ + Filesystem::init(); + return initial_cwd; +} + bool Filesystem::mkdir (std::string path) { int fail; From b55d844164fd2bfdc9c1088e0a356cdd6a1f3bde Mon Sep 17 00:00:00 2001 From: lethosor Date: Thu, 12 Nov 2020 21:03:05 -0500 Subject: [PATCH 3/4] Add test for get_initial_cwd() --- test/core.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/core.lua b/test/core.lua index 6cde334d4..ba104c90a 100644 --- a/test/core.lua +++ b/test/core.lua @@ -13,6 +13,10 @@ function test.getDFPath() expect.eq(clean_path(dfhack.getDFPath()), old_cwd) end +function test.get_initial_cwd() + expect.eq(clean_path(dfhack.filesystem.get_initial_cwd()), clean_path(dfhack.getDFPath())) +end + function test.getDFPath_chdir() dfhack.with_finalize(restore_cwd, function() fs.chdir('data') From a5e58b766bb83b9530254cfa5b7ed6098f8247f2 Mon Sep 17 00:00:00 2001 From: lethosor Date: Thu, 12 Nov 2020 21:07:14 -0500 Subject: [PATCH 4/4] Update scripts, changelog --- docs/changelog.txt | 1 + scripts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 79179ce5e..9cbecf9ec 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -34,6 +34,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: # Future ## Fixes +- Fixed an issue on some Linux systems where DFHack installed through a package manager would attempt to write files to a non-writable folder (notably when running `exportlegends` or `gui/autogems`) - `buildingplan`: artifacts are now successfully matched when max quality is set to ``artifacts`` - `buildingplan`: no longer erroneously matches items to buildings while the game is paused - `dwarfmonitor`: fixed a crash when opening the ``prefs`` screen if units have vague preferences diff --git a/scripts b/scripts index a2b0c7c41..ccf1d035a 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit a2b0c7c41919b54933858482f1daa1dae6a6664b +Subproject commit ccf1d035a653c991b669fccc8293ecbab449548f