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

Martin Storsjö via libcxx-commits libcxx-commits at lists.llvm.org
Thu Mar 11 11:08:11 PST 2021


Author: Martin Storsjö
Date: 2021-03-11T21:07:29+02:00
New Revision: e69c65d5c45557e140b13237448581d28bbd5846

URL: https://github.com/llvm/llvm-project/commit/e69c65d5c45557e140b13237448581d28bbd5846
DIFF: https://github.com/llvm/llvm-project/commit/e69c65d5c45557e140b13237448581d28bbd5846.diff

LOG: [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 156180727d6c347eda3ba749730707acb8a48093.

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

Added: 
    

Modified: 
    libcxx/src/filesystem/directory_iterator.cpp
    libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp
    libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp
    libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp
    libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp
    libcxx/test/support/filesystem_test_helper.h

Removed: 
    


################################################################################
diff  --git a/libcxx/src/filesystem/directory_iterator.cpp b/libcxx/src/filesystem/directory_iterator.cpp
index 2721dea5c98f..bb3653076bfc 100644
--- a/libcxx/src/filesystem/directory_iterator.cpp
+++ b/libcxx/src/filesystem/directory_iterator.cpp
@@ -124,7 +124,8 @@ class __dir_stream {
       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;
     }

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
index e3759e22b0ba..a118fae4d54b 100644
--- 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_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()

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
index 48cf72a77b05..fae696613c75 100644
--- 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(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.

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
index ddffaca39335..53ca5737ba31 100644
--- 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(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.

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
index d23080a0a7d1..a116d0886dd4 100644
--- 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_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

diff  --git a/libcxx/test/support/filesystem_test_helper.h b/libcxx/test/support/filesystem_test_helper.h
index e12aa9956c0c..32d2b6ab6a86 100644
--- a/libcxx/test/support/filesystem_test_helper.h
+++ b/libcxx/test/support/filesystem_test_helper.h
@@ -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 */


        


More information about the libcxx-commits mailing list