diff --git a/src/libutil-tests/file-system.cc b/src/libutil-tests/file-system.cc index 3a288c110..a8c31a00e 100644 --- a/src/libutil-tests/file-system.cc +++ b/src/libutil-tests/file-system.cc @@ -203,12 +203,10 @@ TEST(isInDir, notInDir) ASSERT_EQ(p1, false); } -// XXX: hm, bug or feature? :) Looking at the implementation -// this might be problematic. TEST(isInDir, emptyDir) { auto p1 = isInDir("/zes/foo/bar", ""); - ASSERT_EQ(p1, true); + ASSERT_EQ(p1, false); } /* ---------------------------------------------------------------------------- @@ -233,14 +231,12 @@ TEST(isDirOrInDir, falseForDisjunctPaths) TEST(isDirOrInDir, relativePaths) { - ASSERT_EQ(isDirOrInDir("/foo/..", "/foo"), true); + ASSERT_EQ(isDirOrInDir("/foo/..", "/foo"), false); } -// XXX: while it is possible to use "." or ".." in the -// first argument this doesn't seem to work in the second. -TEST(isDirOrInDir, DISABLED_shouldWork) +TEST(isDirOrInDir, relativePathsTwice) { - ASSERT_EQ(isDirOrInDir("/foo/..", "/foo/."), true); + ASSERT_EQ(isDirOrInDir("/foo/..", "/foo/."), false); } /* ---------------------------------------------------------------------------- diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 13f21689d..55a7d1c9b 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -149,16 +149,18 @@ std::string_view baseNameOf(std::string_view path) } -bool isInDir(std::string_view path, std::string_view dir) +bool isInDir(const fs::path & path, const fs::path & dir) { - return path.substr(0, 1) == "/" - && path.substr(0, dir.size()) == dir - && path.size() >= dir.size() + 2 - && path[dir.size()] == '/'; + /* Note that while the standard doesn't guarantee this, the + `lexically_*` functions should do no IO and not throw. */ + auto rel = path.lexically_relative(dir); + /* Method from + https://stackoverflow.com/questions/62503197/check-if-path-contains-another-in-c++ */ + return !rel.empty() && rel.native()[0] != OS_STR('.'); } -bool isDirOrInDir(std::string_view path, std::string_view dir) +bool isDirOrInDir(const fs::path & path, const fs::path & dir) { return path == dir || isInDir(path, dir); } diff --git a/src/libutil/file-system.hh b/src/libutil/file-system.hh index 08ddbccb9..7970897ee 100644 --- a/src/libutil/file-system.hh +++ b/src/libutil/file-system.hh @@ -105,13 +105,13 @@ std::string_view baseNameOf(std::string_view path); * Check whether 'path' is a descendant of 'dir'. Both paths must be * canonicalized. */ -bool isInDir(std::string_view path, std::string_view dir); +bool isInDir(const std::filesystem::path & path, const std::filesystem::path & dir); /** * Check whether 'path' is equal to 'dir' or a descendant of * 'dir'. Both paths must be canonicalized. */ -bool isDirOrInDir(std::string_view path, std::string_view dir); +bool isDirOrInDir(const std::filesystem::path & path, const std::filesystem::path & dir); /** * Get status of `path`.