[gcc r17-2009] libstdc++: Test that fs::remove and fs::remove_all do not follow symlinks
Jonathan Wakely
redi@gcc.gnu.org
Tue Jun 30 12:55:19 GMT 2026
https://gcc.gnu.org/g:92bfcd8a041bdf32c2c1098ad9cc6734eaf973e7
commit r17-2009-g92bfcd8a041bdf32c2c1098ad9cc6734eaf973e7
Author: Adam Wood <adam.wood@mines.sdsmt.edu>
Date: Mon Jun 29 21:42:59 2026 -0600
libstdc++: Test that fs::remove and fs::remove_all do not follow symlinks
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.
Diff:
---
.../27_io/filesystem/operations/remove.cc | 19 ++++++++++
.../27_io/filesystem/operations/remove_all.cc | 40 +++++++++++++++++++++-
2 files changed, 58 insertions(+), 1 deletion(-)
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/remove.cc b/libstdc++-v3/testsuite/27_io/filesystem/operations/remove.cc
index 50b1b7647167..858884517dd3 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/operations/remove.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/remove.cc
@@ -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 );
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/remove_all.cc b/libstdc++-v3/testsuite/27_io/filesystem/operations/remove_all.cc
index 16c215ce9996..f29e05086ef0 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/operations/remove_all.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/remove_all.cc
@@ -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");
More information about the Libstdc++-cvs
mailing list