[PATCH] libstdc++: Test that fs::remove and fs::remove_all do not follow symlinks
Jonathan Wakely
jwakely@redhat.com
Tue Jun 30 12:56:01 GMT 2026
On Tue, 30 Jun 2026 at 04:51, Adam Wood <adam.wood@mines.sdsmt.edu> wrote:
>
> 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
> fs::remove deletes symlink instead of target.
> * testsuite/27_io/filesystem/operations/remove_all.cc: Likewise.
> ---
>
> Tested on x86_64-pc-linux-gnu.
>
> Tested on x86_64-w64-mingw32 with Wine 11.11. I tested with the v5 symlink
> patch.
Thanks - I've pushed this to trunk.
>
> .../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 50b1b764716..858884517dd 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 16c215ce999..f29e05086ef 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");
> --
> 2.54.0
>
More information about the Libstdc++
mailing list