]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Test that fs::remove and fs::remove_all do not follow symlinks
authorAdam Wood <adam.wood@mines.sdsmt.edu>
Tue, 30 Jun 2026 03:42:59 +0000 (21:42 -0600)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 30 Jun 2026 12:54:50 +0000 (13:54 +0100)
Test that fs::remove and fs::remove_all delete an initial directory
symlink instead of following it. Also test that fs::remove_all
delete symlinks inside a directory rather than following them.

libstdc++-v3/ChangeLog:

* testsuite/27_io/filesystem/operations/remove.cc: Check that
fs::remove deletes symlink instead of target.
* testsuite/27_io/filesystem/operations/remove_all.cc: Likewise.

libstdc++-v3/testsuite/27_io/filesystem/operations/remove.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/remove_all.cc

index 50b1b764716710371283463928ffd60d431c24ac..858884517dd323f4dad395c5d96f0d5d3f4f2118 100644 (file)
@@ -68,6 +68,25 @@ test01()
 
   const auto dir = __gnu_test::nonexistent_path();
   create_directories(dir/"a/b");
+
+#ifndef NO_SYMLINKS
+  create_directories(dir/"real");
+  create_directory_symlink(dir/"real", dir/"link");
+
+  ec = bad_ec;
+  n = remove(dir/"link", ec);
+  VERIFY( !ec );
+  VERIFY( exists(dir/"real") );
+  VERIFY( !exists(symlink_status(dir/"link")) );
+  VERIFY( n );
+
+  ec = bad_ec;
+  n = remove(dir/"real", ec);
+  VERIFY( !ec );
+  VERIFY( !exists(dir/"real") );
+  VERIFY( n );
+#endif
+
   ec.clear();
   n = remove(dir/"a", ec);
   VERIFY( ec );
index 16c215ce9996252d1044dfcb2134ba1f9ea3c019..f29e05086ef04255d2ce85f42dea35329f40c4d1 100644 (file)
@@ -61,7 +61,7 @@ test01()
 #endif
 
   const auto dir = __gnu_test::nonexistent_path();
-  create_directories(dir/"a/b/c");
+  create_directories(dir/"a"/"b"/"c");
   ec = bad_ec;
   n = remove_all(dir/"a", ec);
   VERIFY( !ec );
@@ -69,6 +69,44 @@ test01()
   VERIFY( exists(dir) );
   VERIFY( !exists(dir/"a") );
 
+#ifndef NO_SYMLINKS
+  // Test that remove_all does not follow an initial directory symlink.
+  create_directories(dir/"real");
+  create_directory_symlink(dir/"real", dir/"link");
+
+  ec = bad_ec;
+  n = remove_all(dir/"link", ec);
+  VERIFY( !ec );
+  VERIFY( exists(dir/"real") );
+  VERIFY( !exists(symlink_status(dir/"link")) );
+  VERIFY( n == 1 );
+
+  ec = bad_ec;
+  n = remove_all(dir/"real", ec);
+  VERIFY( !ec );
+  VERIFY( !exists(dir/"real") );
+  VERIFY( n == 1 );
+
+  // Test that remove_all does not follow symlinks inside the directory.
+  create_directories(dir/"subdir");
+  create_directories(dir/"target_dir");
+  __gnu_test::scoped_file f2(dir/"target_file");
+  create_directory_symlink(dir/"target_dir", dir/"subdir"/"link_dir");
+  create_symlink(dir/"target_file", dir/"subdir"/"link_file");
+
+  ec = bad_ec;
+  n = remove_all(dir/"subdir", ec);
+  VERIFY( !ec );
+  VERIFY( exists(dir/"target_dir") );
+  VERIFY( exists(dir/"target_file") );
+  VERIFY( !exists(dir/"subdir") );
+  VERIFY( n == 3 );
+
+  f2.path.clear();
+  remove(dir/"target_dir");
+  remove(dir/"target_file");
+#endif
+
   create_directories(dir/"a/b/c");
   __gnu_test::scoped_file a1(dir/"a/1");
   __gnu_test::scoped_file a2(dir/"a/2");