From c8f1efebeaca041959859f2547931bcd108a35fc Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 10 Oct 2024 17:40:06 +0200 Subject: [PATCH] Use execvp in fs::RecursiveDelete() --- src/filesys.cpp | 73 ++++++++++++++++++----------------- src/unittest/test_filesys.cpp | 31 +++++++++++++++ 2 files changed, 69 insertions(+), 35 deletions(-) diff --git a/src/filesys.cpp b/src/filesys.cpp index 196aca080..b0a1f318e 100644 --- a/src/filesys.cpp +++ b/src/filesys.cpp @@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #endif + #ifdef __linux__ #include #include @@ -43,6 +44,19 @@ with this program; if not, write to the Free Software Foundation, Inc., #endif #endif +#ifdef _WIN32 +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#endif + // Error from last OS call as string #ifdef _WIN32 #define LAST_OS_ERROR() porting::ConvertError(GetLastError()) @@ -59,11 +73,6 @@ namespace fs * Windows * ***********/ -#include -#include -#include -#include - std::vector GetDirListing(const std::string &pathstring) { std::vector listing; @@ -273,12 +282,6 @@ bool CopyFileContents(const std::string &source, const std::string &target) * POSIX * *********/ -#include -#include -#include -#include -#include - std::vector GetDirListing(const std::string &pathstring) { std::vector listing; @@ -381,41 +384,41 @@ bool RecursiveDelete(const std::string &path) Execute the 'rm' command directly, by fork() and execve() */ - infostream<<"Removing \""< argv = { + "rm", "-rf", path.c_str(), - NULL + nullptr }; - verbosestream<<"Executing '"<(argv.data())); - execv(argv[0], const_cast(argv)); - - // Execv shouldn't return. Failed. + // note: use cerr because our logging won't flush in forked process + std::cerr << "exec errno: " << errno << ": " << strerror(errno) + << std::endl; _exit(1); - } - else - { + } else { // Parent - int child_status; + int status; pid_t tpid; - do{ - tpid = wait(&child_status); - }while(tpid != child_pid); - return (child_status == 0); + do + tpid = waitpid(child_pid, &status, 0); + while (tpid != child_pid); + return WIFEXITED(status) && WEXITSTATUS(status) == 0; } } diff --git a/src/unittest/test_filesys.cpp b/src/unittest/test_filesys.cpp index fd25d2de9..e24e79374 100644 --- a/src/unittest/test_filesys.cpp +++ b/src/unittest/test_filesys.cpp @@ -42,6 +42,7 @@ public: void testSafeWriteToFile(); void testCopyFileContents(); void testNonExist(); + void testRecursiveDelete(); }; static TestFileSys g_test_instance; @@ -56,6 +57,7 @@ void TestFileSys::runTests(IGameDef *gamedef) TEST(testSafeWriteToFile); TEST(testCopyFileContents); TEST(testNonExist); + TEST(testRecursiveDelete); } //////////////////////////////////////////////////////////////////////////////// @@ -338,3 +340,32 @@ void TestFileSys::testNonExist() auto ifs = open_ifstream(path.c_str(), false); UASSERT(!ifs.good()); } + +void TestFileSys::testRecursiveDelete() +{ + std::string dirs[2]; + dirs[0] = getTestTempDirectory() + DIR_DELIM "a"; + dirs[1] = dirs[0] + DIR_DELIM "b"; + + std::string files[2] = { + dirs[0] + DIR_DELIM "file1", + dirs[1] + DIR_DELIM "file2" + }; + + for (auto &it : dirs) + fs::CreateDir(it); + for (auto &it : files) + open_ofstream(it.c_str(), false).close(); + + for (auto &it : dirs) + UASSERT(fs::IsDir(it)); + for (auto &it : files) + UASSERT(fs::IsFile(it)); + + UASSERT(fs::RecursiveDelete(dirs[0])); + + for (auto &it : dirs) + UASSERT(!fs::IsDir(it)); + for (auto &it : files) + UASSERT(!fs::IsFile(it)); +}