diff --git a/libstdc++-v3/src/filesystem/ops.cc b/libstdc++-v3/src/filesystem/ops.cc index 98ddff5a66e..896a4918ace 100644 --- a/libstdc++-v3/src/filesystem/ops.cc +++ b/libstdc++-v3/src/filesystem/ops.cc @@ -1176,13 +1176,43 @@ fs::space(const path& p, error_code& ec) noexcept return info; } +#if _GLIBCXX_FILESYSTEM_IS_WINDOWS +static bool has_trailing_slash(const fs::path& p) +{ + wchar_t c = p.native().back(); + return c == '/' || c == L'\\'; +} +#endif + #ifdef _GLIBCXX_HAVE_SYS_STAT_H fs::file_status fs::status(const fs::path& p, error_code& ec) noexcept { file_status status; + + auto str = p.c_str(); + +#if _GLIBCXX_FILESYSTEM_IS_WINDOWS + // stat() fails if there's a trailing slash (PR 88881) + path p2; + if (p.has_relative_path() && has_trailing_slash(p)) + { + __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 + stat_type st; - if (posix::stat(p.c_str(), &st)) + if (posix::stat(str, &st)) { int err = errno; ec.assign(err, std::generic_category()); @@ -1205,8 +1235,30 @@ 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 + // stat() fails if there's a trailing slash (PR 88881) + path p2; + if (p.has_relative_path() && has_trailing_slash(p)) + { + __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 + 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/experimental/filesystem/operations/temp_directory_path.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc index 9e9cd44d460..c2945c90866 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc @@ -105,6 +105,8 @@ test03() if (!__gnu_test::permissions_are_testable()) return; + clean_env(); + auto p = __gnu_test::nonexistent_path(); create_directories(p/"tmp"); permissions(p, fs::perms::none); @@ -129,8 +131,10 @@ test03() void test04() { + clean_env(); + __gnu_test::scoped_file f; - set_env("TMPDIR", f.path.string()); + set_env("TMP", f.path.string()); std::error_code ec; auto r = fs::temp_directory_path(ec); VERIFY( ec == std::make_error_code(std::errc::not_a_directory) );