diff --git a/libcxx/src/filesystem/directory_iterator.cpp b/libcxx/src/filesystem/directory_iterator.cpp --- a/libcxx/src/filesystem/directory_iterator.cpp +++ b/libcxx/src/filesystem/directory_iterator.cpp @@ -124,7 +124,8 @@ ec = detail::make_windows_error(GetLastError()); const bool ignore_permission_denied = bool(opts & directory_options::skip_permission_denied); - if (ignore_permission_denied && ec.value() == ERROR_ACCESS_DENIED) + if (ignore_permission_denied && + ec.value() == static_cast(errc::permission_denied)) ec.clear(); return; } diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp @@ -148,6 +148,23 @@ TEST_CASE(path_ctor_cannot_resolve) { using namespace fs; +#ifdef _WIN32 + // Windows doesn't support setting perms::none to trigger failures + // reading directories; test using a special inaccessible directory + // instead. + const path dir = GetWindowsInaccessibleDir(); + TEST_REQUIRE(!dir.empty()); + const path file = dir / "file"; + { + std::error_code ec = GetTestEC(); + directory_entry ent(file, ec); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + TEST_CHECK(ent.path() == file); + } + { + TEST_CHECK_NO_THROW(directory_entry(file)); + } +#else scoped_test_env env; const path dir = env.create_dir("dir"); const path file = env.create_file("dir/file", 42); @@ -179,6 +196,7 @@ TEST_CHECK_NO_THROW(directory_entry(sym_in_dir)); TEST_CHECK_NO_THROW(directory_entry(sym_out_of_dir)); } +#endif } TEST_SUITE_END() diff --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp @@ -87,6 +87,13 @@ TEST_CASE(access_denied_test_case) { using namespace fs; +#ifdef _WIN32 + // Windows doesn't support setting perms::none to trigger failures + // reading directories; test using a special inaccessible directory + // instead. + const path testDir = GetWindowsInaccessibleDir(); + TEST_REQUIRE(!testDir.empty()); +#else scoped_test_env env; path const testDir = env.make_env_path("dir1"); path const testFile = testDir / "testFile"; @@ -100,6 +107,7 @@ } // Change the permissions so we can no longer iterate permissions(testDir, perms::none); +#endif // Check that the construction fails when skip_permissions_denied is // not given. diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp @@ -88,6 +88,13 @@ TEST_CASE(access_denied_test_case) { using namespace fs; +#ifdef _WIN32 + // Windows doesn't support setting perms::none to trigger failures + // reading directories; test using a special inaccessible directory + // instead. + const path testDir = GetWindowsInaccessibleDir(); + TEST_REQUIRE(!testDir.empty()); +#else scoped_test_env env; path const testDir = env.make_env_path("dir1"); path const testFile = testDir / "testFile"; @@ -102,6 +109,7 @@ // Change the permissions so we can no longer iterate permissions(testDir, perms::none); +#endif // Check that the construction fails when skip_permissions_denied is // not given. diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp @@ -73,16 +73,24 @@ TEST_CASE(test_exists_fails) { +#ifdef _WIN32 + // Windows doesn't support setting perms::none to trigger failures + // reading directories; test using a special inaccessible directory + // instead. + const path p = GetWindowsInaccessibleDir(); + TEST_REQUIRE(!p.empty()); +#else scoped_test_env env; const path dir = env.create_dir("dir"); - const path file = env.create_file("dir/file", 42); + const path p = env.create_file("dir/file", 42); permissions(dir, perms::none); +#endif std::error_code ec; - TEST_CHECK(exists(file, ec) == false); + TEST_CHECK(exists(p, ec) == false); TEST_CHECK(ec); - TEST_CHECK_THROW(filesystem_error, exists(file)); + TEST_CHECK_THROW(filesystem_error, exists(p)); } #ifndef _WIN32 diff --git a/libcxx/test/support/filesystem_test_helper.h b/libcxx/test/support/filesystem_test_helper.h --- a/libcxx/test/support/filesystem_test_helper.h +++ b/libcxx/test/support/filesystem_test_helper.h @@ -671,4 +671,29 @@ }; +inline fs::path GetWindowsInaccessibleDir() { + // Only makes sense on windows, but the code can be compiled for + // any platform. + const fs::path dir("C:\\System Volume Information"); + std::error_code ec; + const fs::path root("C:\\"); + fs::directory_iterator it(root, ec); + if (ec) + return fs::path(); + const fs::directory_iterator endIt{}; + while (it != endIt) { + const fs::directory_entry &ent = *it; + if (ent == dir) { + // Basic sanity checks on the directory_entry + if (!ent.exists()) + return fs::path(); + if (!ent.is_directory()) + return fs::path(); + return ent; + } + ++it; + } + return fs::path(); +} + #endif /* FILESYSTEM_TEST_HELPER_HPP */