diff --git a/.github/workflows/CI-cygwin.yml b/.github/workflows/CI-cygwin.yml index a2f27c41d..505c71686 100644 --- a/.github/workflows/CI-cygwin.yml +++ b/.github/workflows/CI-cygwin.yml @@ -23,6 +23,7 @@ jobs: - platform: 'x86_64' packages: | gcc-g++ + python3 fail-fast: false runs-on: ${{ matrix.os }} diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 32512efc3..acd5a642d 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -149,15 +149,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) bool def = false; bool maxconfigs = false; - mSettings.exename = argv[0]; -#ifdef __linux__ - // Executing cppcheck in PATH. argv[0] does not contain the path. - if (mSettings.exename.find_first_of("/\\") == std::string::npos) { - char buf[PATH_MAX] = {0}; - if (FileLister::fileExists("/proc/self/exe") && readlink("/proc/self/exe", buf, sizeof(buf)-1) > 0) - mSettings.exename = buf; - } -#endif + mSettings.exename = Path::getCurrentExecutablePath(argv[0]); for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { diff --git a/cli/main.cpp b/cli/main.cpp index 32494137a..a904893b9 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -68,18 +68,6 @@ #include #endif -#ifdef _WIN32 -#include - -static char exename[1024] = {0}; -#endif - -#if defined(__APPLE__) -#include - -static char exename[1024] = {0}; -#endif - /** * Main function of cppcheck * @@ -95,15 +83,7 @@ int main(int argc, char* argv[]) #endif CppCheckExecutor exec; -#ifdef _WIN32 - GetModuleFileNameA(nullptr, exename, sizeof(exename)/sizeof(exename[0])-1); - argv[0] = exename; -#endif -#if defined(__APPLE__) - uint32_t size = sizeof(exename); - _NSGetExecutablePath(exename, &size); - argv[0] = exename; -#endif + // *INDENT-OFF* #ifdef NDEBUG try { diff --git a/lib/library.cpp b/lib/library.cpp index 48cdec773..4c9196952 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -107,8 +107,9 @@ Library::Error Library::load(const char exename[], const char path[]) cfgfolders.emplace_back(FILESDIR "/cfg"); #endif if (exename) { - const std::string exepath(Path::fromNativeSeparators(Path::getPathFromFilename(exename))); + const std::string exepath(Path::fromNativeSeparators(Path::getPathFromFilename(Path::getCurrentExecutablePath(exename)))); cfgfolders.push_back(exepath + "cfg"); + cfgfolders.push_back(exepath + "../cfg"); cfgfolders.push_back(exepath); } diff --git a/lib/path.cpp b/lib/path.cpp index bb70ac251..0c606cc47 100644 --- a/lib/path.cpp +++ b/lib/path.cpp @@ -28,16 +28,21 @@ #include #include +#include + #ifndef _WIN32 #include #else #include +#include #endif #if defined(__CYGWIN__) #include #endif +#if defined(__APPLE__) +#include +#endif -#include /** Is the filesystem case insensitive? */ static bool caseInsensitiveFilesystem() @@ -131,6 +136,29 @@ std::string Path::getCurrentPath() return ""; } +std::string Path::getCurrentExecutablePath(const char* fallback) +{ + char buf[4096] = {}; + bool success{}; +#ifdef _WIN32 + success = (GetModuleFileNameA(nullptr, buf, sizeof(buf)) < sizeof(buf)); +#elif defined(__APPLE__) + uint32_t size = sizeof(buf); + success = (_NSGetExecutablePath(buf, &size) == 0); +#else + const char* procPath = +#ifdef __SVR4 // Solaris + "/proc/self/path/a.out"; +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) + "/proc/curproc/file"; +#else // Linux + "/proc/self/exe"; +#endif + success = (readlink(procPath, buf, sizeof(buf)) != -1); +#endif + return success ? std::string(buf) : std::string(fallback); +} + bool Path::isAbsolute(const std::string& path) { const std::string& nativePath = toNativeSeparators(path); diff --git a/lib/path.h b/lib/path.h index 4d17a593a..621360efe 100644 --- a/lib/path.h +++ b/lib/path.h @@ -104,6 +104,12 @@ public: */ static std::string getCurrentPath(); + /** + * @brief Returns the absolute path to the current executable + * @return absolute path to the current executable + */ + static std::string getCurrentExecutablePath(const char* fallback); + /** * @brief Check if given path is absolute * @param path Path to check diff --git a/test/testpath.cpp b/test/testpath.cpp index 1cf8f242c..0813c6b38 100644 --- a/test/testpath.cpp +++ b/test/testpath.cpp @@ -32,6 +32,7 @@ private: TEST_CASE(removeQuotationMarks); TEST_CASE(acceptFile); TEST_CASE(getCurrentPath); + TEST_CASE(getCurrentExecutablePath); TEST_CASE(isAbsolute); TEST_CASE(getRelative); TEST_CASE(is_c); @@ -72,6 +73,10 @@ private: ASSERT_EQUALS(true, Path::isAbsolute(Path::getCurrentPath())); } + void getCurrentExecutablePath() const { + ASSERT_EQUALS(false, Path::getCurrentExecutablePath("").empty()); + } + void isAbsolute() const { #ifdef _WIN32 ASSERT_EQUALS(true, Path::isAbsolute("C:\\foo\\bar"));