aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2022-04-28 13:06:31 +0100
committerJonathan Wakely <jwakely@redhat.com>2022-04-28 13:33:48 +0100
commit4e117418fb71f508c479e0144500f4da9cc92520 (patch)
treecf1ec94b493c3c0c63e162d6840f38efd65ea04a /libstdc++-v3
parentd91cb2059fb8b5a50a2aced199e987ab2cf3b629 (diff)
downloadgcc-4e117418fb71f508c479e0144500f4da9cc92520.zip
gcc-4e117418fb71f508c479e0144500f4da9cc92520.tar.gz
gcc-4e117418fb71f508c479e0144500f4da9cc92520.tar.bz2
libstdc++: Fix error reporting in filesystem::copy [PR99290]
The recursive calls to filesystem::copy should stop if any of them reports an error. libstdc++-v3/ChangeLog: PR libstdc++/99290 * src/c++17/fs_ops.cc (fs::copy): Pass error_code to directory_iterator constructor, and check on each iteration. * src/filesystem/ops.cc (fs::copy): Likewise. * testsuite/27_io/filesystem/operations/copy.cc: Check for errors during recursion. * testsuite/experimental/filesystem/operations/copy.cc: Likewise.
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/src/c++17/fs_ops.cc8
-rw-r--r--libstdc++-v3/src/filesystem/ops.cc8
-rw-r--r--libstdc++-v3/testsuite/27_io/filesystem/operations/copy.cc29
-rw-r--r--libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc29
4 files changed, 70 insertions, 4 deletions
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 4552a73..435368f 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -408,8 +408,12 @@ fs::copy(const path& from, const path& to, copy_options options,
// set an unused bit in options to disable further recursion
if (!is_set(options, copy_options::recursive))
options |= static_cast<copy_options>(4096);
- for (const directory_entry& x : directory_iterator(from))
- copy(x.path(), to/x.path().filename(), options, ec);
+ for (const directory_entry& x : directory_iterator(from, ec))
+ {
+ copy(x.path(), to/x.path().filename(), options, ec);
+ if (ec)
+ return;
+ }
}
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2683. filesystem::copy() says "no effects"
diff --git a/libstdc++-v3/src/filesystem/ops.cc b/libstdc++-v3/src/filesystem/ops.cc
index e2a2cef..98ddff5 100644
--- a/libstdc++-v3/src/filesystem/ops.cc
+++ b/libstdc++-v3/src/filesystem/ops.cc
@@ -350,8 +350,12 @@ fs::copy(const path& from, const path& to, copy_options options,
// set an unused bit in options to disable further recursion
if (!is_set(options, copy_options::recursive))
options |= static_cast<copy_options>(4096);
- for (const directory_entry& x : directory_iterator(from))
- copy(x.path(), to/x.path().filename(), options, ec);
+ for (const directory_entry& x : directory_iterator(from, ec))
+ {
+ copy(x.path(), to/x.path().filename(), options, ec);
+ if (ec)
+ return;
+ }
}
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2683. filesystem::copy() says "no effects"
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/copy.cc b/libstdc++-v3/testsuite/27_io/filesystem/operations/copy.cc
index b85628c..b936e04 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/operations/copy.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/copy.cc
@@ -193,6 +193,34 @@ test05()
VERIFY( !ec ); // Previous value should be cleared (LWG 2683)
}
+void
+test_pr99290()
+{
+ auto dir = __gnu_test::nonexistent_path();
+ auto source = dir/"source";
+ auto dest = dir/"dest";
+ create_directories(source/"emptydir");
+ create_directories(dest/"emptydir");
+ std::ofstream{source/"file"} << 'a';
+ std::ofstream{dest/"file"} << 'b';
+ // PR libstdc++/99290
+ // std::filesystem::copy does not always report errors for recursion
+ std::error_code ec;
+ copy(source, dest, ec);
+ VERIFY( ec == std::errc::file_exists );
+
+#if __cpp_exceptions
+ try {
+ copy(source, dest);
+ VERIFY( false );
+ } catch (const fs::filesystem_error& e) {
+ VERIFY( e.code() == std::errc::file_exists );
+ }
+#endif
+
+ remove_all(dir);
+}
+
int
main()
{
@@ -201,4 +229,5 @@ main()
test03();
test04();
test05();
+ test_pr99290();
}
diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc
index 319632a..5cd6b48 100644
--- a/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc
+++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc
@@ -190,6 +190,34 @@ test05()
VERIFY( !ec ); // Previous value should be cleared (LWG 2683)
}
+void
+test_pr99290()
+{
+ auto dir = __gnu_test::nonexistent_path();
+ auto source = dir/"source";
+ auto dest = dir/"dest";
+ create_directories(source/"emptydir");
+ create_directories(dest/"emptydir");
+ std::ofstream{source/"file"} << 'a';
+ std::ofstream{dest/"file"} << 'b';
+ // PR libstdc++/99290
+ // std::filesystem::copy does not always report errors for recursion
+ std::error_code ec;
+ copy(source, dest, ec);
+ VERIFY( ec == std::errc::file_exists );
+
+#if __cpp_exceptions
+ try {
+ copy(source, dest);
+ VERIFY( false );
+ } catch (const fs::filesystem_error& e) {
+ VERIFY( e.code() == std::errc::file_exists );
+ }
+#endif
+
+ remove_all(dir);
+}
+
int
main()
{
@@ -198,4 +226,5 @@ main()
test03();
test04();
test05();
+ test_pr99290();
}