mirror of
https://gcc.gnu.org/git/gcc.git
synced 2025-01-02 00:43:44 +08:00
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(). 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. From-SVN: r271755
This commit is contained in:
parent
e5ccb10ad0
commit
3cb929a32a
@ -1,5 +1,16 @@
|
||||
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.
|
||||
|
||||
* src/c++17/fs_path.cc (path::parent_path()): Create whole path at
|
||||
once instead of building it iteratively.
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user