aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2019-06-14 18:11:22 +0000
committerJonathan Wakely <jwakely@redhat.com>2019-06-14 18:11:22 +0000
commit6299ac066a2543f2686b17a79322622fed675f63 (patch)
treefb37ecec7c59cb8311e146d03cba6f340e4fee48 /libstdc++-v3
parentd1d371561d2bd4619a2e55bd06d4d5d87df595a6 (diff)
PR libstdc++/88881 fix filesystem::symlink_status for Windows
The fix for PR 88881 only added a workaround to filesystem::status, but filesystem::symlink_status is also affected by the _wstat bug and needs the same workaround. The recent change to optimize path::parent_path() means that the workaround can be simplified to just use parent_path(). Backport from mainline 2019-05-29 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/88881 * src/c++17/fs_ops.cc [_GLIBCXX_FILESYSTEM_IS_WINDOWS] (status(const path&, error_code&)): Use parent_path() to remove trailing slash. (symlink_status(const path&, error_code&)): Duplicate workaround for bug in _wstat for paths with trailing slash. * testsuite/27_io/filesystem/operations/remove_all.cc: Check path with trailing slash. * testsuite/27_io/filesystem/operations/status.cc: Likewise. * testsuite/27_io/filesystem/operations/symlink_status.cc: Likewise. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gcc-9-branch@272304 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog16
-rw-r--r--libstdc++-v3/src/c++17/fs_ops.cc47
-rw-r--r--libstdc++-v3/testsuite/27_io/filesystem/operations/remove_all.cc33
-rw-r--r--libstdc++-v3/testsuite/27_io/filesystem/operations/status.cc10
-rw-r--r--libstdc++-v3/testsuite/27_io/filesystem/operations/symlink_status.cc10
5 files changed, 102 insertions, 14 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index d4cb3be5e29..78694e69b1e 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -3,6 +3,22 @@
Backport from mainline
2019-05-29 Jonathan Wakely <jwakely@redhat.com>
+ PR libstdc++/88881
+ * src/c++17/fs_ops.cc [_GLIBCXX_FILESYSTEM_IS_WINDOWS]
+ (status(const path&, error_code&)): Use parent_path() to remove
+ trailing slash.
+ (symlink_status(const path&, error_code&)): Duplicate workaround for
+ bug in _wstat for paths with trailing slash.
+ * testsuite/27_io/filesystem/operations/remove_all.cc: Check path
+ with trailing slash.
+ * testsuite/27_io/filesystem/operations/status.cc: Likewise.
+ * testsuite/27_io/filesystem/operations/symlink_status.cc: Likewise.
+
+2019-06-14 Jonathan Wakely <jwakely@redhat.com>
+
+ Backport from mainline
+ 2019-05-29 Jonathan Wakely <jwakely@redhat.com>
+
* src/c++17/fs_path.cc (path::parent_path()): Create whole path at
once instead of building it iteratively.
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 274ee7f0834..d8064819d36 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1395,23 +1395,19 @@ fs::status(const fs::path& p, error_code& ec) noexcept
#if ! defined __MINGW64_VERSION_MAJOR || __MINGW64_VERSION_MAJOR < 6
// stat() fails if there's a trailing slash (PR 88881)
path p2;
- if (p.has_relative_path())
+ if (p.has_relative_path() && !p.has_filename())
{
- wstring_view s = p.native();
- const auto len = s.find_last_not_of(L"/\\") + wstring_view::size_type(1);
- if (len != 0 && len != s.length())
+ __try
{
- __try
- {
- p2.assign(s.substr(0, len));
- }
- __catch(const bad_alloc&)
- {
- ec = std::make_error_code(std::errc::not_enough_memory);
- return status;
- }
+ p2 = p.parent_path();
str = p2.c_str();
}
+ __catch(const bad_alloc&)
+ {
+ ec = std::make_error_code(std::errc::not_enough_memory);
+ return status;
+ }
+ str = p2.c_str();
}
#endif
#endif
@@ -1440,8 +1436,31 @@ fs::file_status
fs::symlink_status(const fs::path& p, std::error_code& ec) noexcept
{
file_status status;
+ auto str = p.c_str();
+
+#if _GLIBCXX_FILESYSTEM_IS_WINDOWS
+#if ! defined __MINGW64_VERSION_MAJOR || __MINGW64_VERSION_MAJOR < 6
+ // stat() fails if there's a trailing slash (PR 88881)
+ path p2;
+ if (p.has_relative_path() && !p.has_filename())
+ {
+ __try
+ {
+ p2 = p.parent_path();
+ str = p2.c_str();
+ }
+ __catch(const bad_alloc&)
+ {
+ ec = std::make_error_code(std::errc::not_enough_memory);
+ return status;
+ }
+ str = p2.c_str();
+ }
+#endif
+#endif
+
stat_type st;
- if (posix::lstat(p.c_str(), &st))
+ if (posix::lstat(str, &st))
{
int err = errno;
ec.assign(err, std::generic_category());
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 119dd3dc783..a19bac9c5f6 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/operations/remove_all.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/remove_all.cc
@@ -108,9 +108,42 @@ test02()
VERIFY( !exists(dir) );
}
+void
+test03()
+{
+ // PR libstdc++/88881 symlink_status confused by trailing slash on Windows
+ const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
+ unsigned removed;
+ std::error_code ec = bad_ec;
+ const auto p = __gnu_test::nonexistent_path() / ""; // with trailing slash
+
+ create_directories(p);
+ removed = remove_all(p, ec);
+ VERIFY( !ec );
+ VERIFY( removed == 1 );
+ VERIFY( !exists(p) );
+ create_directories(p);
+ removed = remove_all(p);
+ VERIFY( removed == 1 );
+ VERIFY( !exists(p) );
+
+ const auto p_subs = p/"foo/bar";
+ ec = bad_ec;
+ create_directories(p_subs);
+ removed = remove_all(p, ec);
+ VERIFY( !ec );
+ VERIFY( removed == 3 );
+ VERIFY( !exists(p) );
+ create_directories(p_subs);
+ remove_all(p);
+ VERIFY( removed == 3 );
+ VERIFY( !exists(p) );
+}
+
int
main()
{
test01();
test02();
+ test03();
}
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/status.cc b/libstdc++-v3/testsuite/27_io/filesystem/operations/status.cc
index 38c0f65370c..b65a2f20906 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/operations/status.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/status.cc
@@ -93,10 +93,20 @@ test03()
fs::permissions(dir, fs::perms::owner_all, ec);
}
+void
+test04()
+{
+ // PR libstdc++/88881
+ fs::path p = "./";
+ auto st = status(p);
+ VERIFY( is_directory(st) );
+}
+
int
main()
{
test01();
test02();
test03();
+ test04();
}
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/symlink_status.cc b/libstdc++-v3/testsuite/27_io/filesystem/operations/symlink_status.cc
index 6f01419da3e..c097e4f2bf0 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/operations/symlink_status.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/symlink_status.cc
@@ -111,10 +111,20 @@ test03()
fs::permissions(dir, fs::perms::owner_all, ec);
}
+void
+test04()
+{
+ // PR libstdc++/88881
+ fs::path p = "./";
+ auto st = symlink_status(p);
+ VERIFY( is_directory(st) );
+}
+
int
main()
{
test01();
test02();
test03();
+ test04();
}