From 7e009bcf6f9d3673128172704cd7ff25589f18f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Sch=C3=BCmann?= Date: Sat, 22 May 2021 06:37:52 +0200 Subject: [PATCH 1/2] refs #122: added test that iterates over dead symlinks --- test/filesystem_test.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/filesystem_test.cpp b/test/filesystem_test.cpp index 4528c05..7c3cb82 100644 --- a/test/filesystem_test.cpp +++ b/test/filesystem_test.cpp @@ -1596,6 +1596,37 @@ TEST_CASE("fs.class.rec.dir.itr - class recursive_directory_iterator", "[filesys } CHECK(os.str() == "[./a,0],[./d1,0],[./d1/d2,1],[./e,0],"); } + if (is_symlink_creation_supported()) { + TemporaryDirectory t(TempOpt::change_path); + fs::create_directory("d1"); + generateFile("d1/a"); + fs::create_directory("d2"); + generateFile("d2/b"); + fs::create_directory_symlink("../d1", "d2/ds1"); + fs::create_directory_symlink("d3", "d2/ds2"); + std::multiset result; + REQUIRE_NOTHROW([&](){ + for (const auto& de : fs::recursive_directory_iterator("d2", fs::directory_options::follow_directory_symlink)) { + result.insert(de.path().generic_string()); + } + }()); + std::stringstream os; + for(const auto& p : result) { + os << p << ","; + } + CHECK(os.str() == "d2/b,d2/ds1,d2/ds1/a,d2/ds2,"); + os.str(""); + result.clear(); + REQUIRE_NOTHROW([&](){ + for (const auto& de : fs::recursive_directory_iterator("d2")) { + result.insert(de.path().generic_string()); + } + }()); + for(const auto& p : result) { + os << p << ","; + } + CHECK(os.str() == "d2/b,d2/ds1,d2/ds2,"); + } } TEST_CASE("fs.op.absolute - absolute", "[filesystem][operations][fs.op.absolute]") From 873a55addf3cda9bce6b2f81c14119120aca1d10 Mon Sep 17 00:00:00 2001 From: Steffen Schuemann Date: Sat, 22 May 2021 07:14:47 +0200 Subject: [PATCH 2/2] refs #122, fix for dead symlink iteration error --- README.md | 2 ++ include/ghc/filesystem.hpp | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7d50f40..7977f77 100644 --- a/README.md +++ b/README.md @@ -551,6 +551,8 @@ to the expected behavior. ### v1.5.5 (WIP) +* Fix for [#122](https://github.com/gulrak/filesystem/issues/122), incrementing + the `recursive_directory_iterator` will not try to enter dead symlinks. * Fix for [#119](https://github.com/gulrak/filesystem/issues/119), added missing support for char16_t and char32_t and on C++20 char8_t literals. * Pull request [#118](https://github.com/gulrak/filesystem/pull/118), when diff --git a/include/ghc/filesystem.hpp b/include/ghc/filesystem.hpp index bc55b51..9c06a74 100644 --- a/include/ghc/filesystem.hpp +++ b/include/ghc/filesystem.hpp @@ -5802,8 +5802,11 @@ GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator+ GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::increment(std::error_code& ec) noexcept { - bool isDir = (*this)->is_directory(ec); - bool isSymLink = !ec && (*this)->is_symlink(ec); + bool isSymLink = (*this)->is_symlink(ec); + bool isDir = !ec && (*this)->is_directory(ec); + if(isSymLink && detail::is_not_found_error(ec)) { + ec.clear(); + } if(!ec) { if (recursion_pending() && isDir && (!isSymLink || (options() & directory_options::follow_directory_symlink) != directory_options::none)) { _impl->_dir_iter_stack.push(directory_iterator((*this)->path(), _impl->_options, ec));