[libcxx] Test accessing a directory on windows that gives "access denied" errors

Fix handling of skip_permission_denied on windows; after converting
the return value of GetLastError() to a standard error_code, ec.value()
is in the standard errc range, not a native windows error code. This
was missed in 156180727d.

The directory "C:\System Volume Information" does seem to exist and
have these properties on most relevant contempory setups.

Differential Revision: https://reviews.llvm.org/D98166
This commit is contained in:
Martin Storsjö 2021-03-08 12:03:30 +02:00
parent cfe69c8efd
commit e69c65d5c4
6 changed files with 72 additions and 4 deletions

View File

@ -124,7 +124,8 @@ public:
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<int>(errc::permission_denied))
ec.clear();
return;
}

View File

@ -148,6 +148,23 @@ TEST_CASE(path_ctor_dne) {
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_CASE(path_ctor_cannot_resolve) {
TEST_CHECK_NO_THROW(directory_entry(sym_in_dir));
TEST_CHECK_NO_THROW(directory_entry(sym_out_of_dir));
}
#endif
}
TEST_SUITE_END()

View File

@ -87,6 +87,13 @@ TEST_CASE(test_construction_from_bad_path)
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 @@ TEST_CASE(access_denied_test_case)
}
// 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.

View File

@ -88,6 +88,13 @@ TEST_CASE(test_construction_from_bad_path)
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 @@ TEST_CASE(access_denied_test_case)
// 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.

View File

@ -73,16 +73,24 @@ TEST_CASE(test_exist_not_found)
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

View File

@ -671,4 +671,29 @@ struct ExceptionChecker {
};
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 */