From fd971faae28495ae65efc8de6a4aa68ad470e19d Mon Sep 17 00:00:00 2001 From: firewave Date: Thu, 15 Aug 2024 13:51:41 +0200 Subject: [PATCH] Path: throw from `getAbsolutePath()` if the given path does not exist --- lib/path.cpp | 9 ++++++++- lib/path.h | 7 +++++++ test/testpath.cpp | 15 ++++++++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/path.cpp b/lib/path.cpp index 073f1ab9dfb2..9430608d1da4 100644 --- a/lib/path.cpp +++ b/lib/path.cpp @@ -371,11 +371,12 @@ std::string Path::getAbsoluteFilePath(const std::string& filePath) #elif defined(__linux__) || defined(__sun) || defined(__hpux) || defined(__GNUC__) || defined(__CPPCHECK__) // simplify the path since any non-existent part has to exist even if discarded by ".." std::string spath = Path::simplifyPath(filePath); - // TODO: assert if path exists? char * absolute = realpath(spath.c_str(), nullptr); if (absolute) absolute_path = absolute; free(absolute); + if (!filePath.empty() && !spath.empty() && absolute_path.empty() && !exists(spath)) + throw std::runtime_error("path '" + filePath + "' does not exist"); #else #error Platform absolute path function needed #endif @@ -419,6 +420,12 @@ bool Path::isDirectory(const std::string &path) return file_type(path) == S_IFDIR; } +bool Path::exists(const std::string &path) +{ + const auto type = file_type(path); + return type == S_IFREG || type == S_IFDIR; +} + std::string Path::join(const std::string& path1, const std::string& path2) { if (path1.empty() || path2.empty()) return path1 + path2; diff --git a/lib/path.h b/lib/path.h index f3dd870af709..fda36c01f85a 100644 --- a/lib/path.h +++ b/lib/path.h @@ -190,6 +190,13 @@ class CPPCHECKLIB Path { */ static bool isDirectory(const std::string &path); + /** + * @brief Checks if a given path exists (i.e. is a file or directory) + * @param path Path to be checked + * @return true if given path exists + */ + static bool exists(const std::string &path); + /** * join 2 paths with '/' separators */ diff --git a/test/testpath.cpp b/test/testpath.cpp index 69608af75433..70d00e3e4cb6 100644 --- a/test/testpath.cpp +++ b/test/testpath.cpp @@ -50,6 +50,7 @@ class TestPath : public TestFixture { TEST_CASE(is_header); TEST_CASE(simplifyPath); TEST_CASE(getAbsolutePath); + TEST_CASE(exists); } void removeQuotationMarks() const { @@ -476,13 +477,25 @@ class TestPath : public TestFixture { #ifndef _WIN32 // the underlying realpath() call only returns something if the path actually exists - ASSERT_EQUALS("", Path::getAbsoluteFilePath("testabspath2.txt")); + ASSERT_THROW_EQUALS_2(Path::getAbsoluteFilePath("testabspath2.txt"), std::runtime_error, "path 'testabspath2.txt' does not exist"); #else ASSERT_EQUALS(Path::toNativeSeparators(Path::join(cwd, "testabspath2.txt")), Path::getAbsoluteFilePath("testabspath2.txt")); #endif // TODO: test with symlinks } + + void exists() const { + ScopedFile file("testpath.txt", "", "testpath"); + ScopedFile file2("testpath2.txt", ""); + ASSERT_EQUALS(true, Path::exists("testpath")); + ASSERT_EQUALS(true, Path::exists("testpath/testpath.txt")); + ASSERT_EQUALS(true, Path::exists("testpath2.txt")); + + ASSERT_EQUALS(false, Path::exists("testpath2")); + ASSERT_EQUALS(false, Path::exists("testpath/testpath2.txt")); + ASSERT_EQUALS(false, Path::exists("testpath.txt")); + } }; REGISTER_TEST(TestPath)