From: Jonathan Wakely <jwakely@redhat.com>
To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org
Subject: [committed] libstdc++: Fix error reporting in filesystem::copy [PR99290]
Date: Thu, 28 Apr 2022 13:34:14 +0100 [thread overview]
Message-ID: <20220428123414.2354532-1-jwakely@redhat.com> (raw)
Tested x86_64-linux, pushed to trunk. I'll backport this too.
-- >8 --
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.
---
libstdc++-v3/src/c++17/fs_ops.cc | 8 +++--
libstdc++-v3/src/filesystem/ops.cc | 8 +++--
.../27_io/filesystem/operations/copy.cc | 29 +++++++++++++++++++
.../filesystem/operations/copy.cc | 29 +++++++++++++++++++
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 4552a730bf2..435368fa5c5 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 e2a2cefdf49..98ddff5a66e 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 b85628cdf30..b936e04493b 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 319632a5a76..5cd6b483c26 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();
}
--
2.34.1
reply other threads:[~2022-04-28 12:34 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220428123414.2354532-1-jwakely@redhat.com \
--to=jwakely@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=libstdc++@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).