Fix filesystem::equivalent for mingw

* src/c++17/fs_ops.cc
	(equivalent(const path&, const path&, error_code&))
	[_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Use GetFileInformationByHandle to
	compare files instead of relying on incomplete info returned by stat.

From-SVN: r268036
This commit is contained in:
Jonathan Wakely 2019-01-17 15:32:10 +00:00 committed by Jonathan Wakely
parent fc6f857bd3
commit 16d46c7bfd
2 changed files with 47 additions and 0 deletions

View File

@ -1,5 +1,10 @@
2019-01-17 Jonathan Wakely <jwakely@redhat.com>
* src/c++17/fs_ops.cc
(equivalent(const path&, const path&, error_code&))
[_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Use GetFileInformationByHandle to
compare files instead of relying on incomplete info returned by stat.
PR libstdc++/88884
* src/c++17/fs_ops.cc (absolute(const path&, error_code&)): Do nothing
if the path is already absolute.

View File

@ -851,7 +851,49 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept
ec.clear();
if (is_other(s1) || is_other(s2))
return false;
#if _GLIBCXX_FILESYSTEM_IS_WINDOWS
// st_ino is not set, so can't be used to distinguish files
if (st1.st_mode != st2.st_mode || st1.st_dev != st2.st_dev)
return false;
struct auto_handle {
explicit auto_handle(const path& p_)
: handle(CreateFileW(p_.c_str(), 0,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0))
{ }
~auto_handle()
{ if (*this) CloseHandle(handle); }
explicit operator bool() const
{ return handle != INVALID_HANDLE_VALUE; }
bool get_info()
{ return GetFileInformationByHandle(handle, &info); }
HANDLE handle;
BY_HANDLE_FILE_INFORMATION info;
};
auto_handle h1(p1);
auto_handle h2(p2);
if (!h1 || !h2)
{
if (!h1 && !h2)
ec.assign((int)GetLastError(), generic_category());
return false;
}
if (!h1.get_info() || !h2.get_info())
{
ec.assign((int)GetLastError(), generic_category());
return false;
}
return h1.info.dwVolumeSerialNumber == h2.info.dwVolumeSerialNumber
&& h1.info.nFileIndexHigh == h2.info.nFileIndexHigh
&& h1.info.nFileIndexLow == h2.info.nFileIndexLow;
#else
return st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino;
#endif
}
else if (!exists(s1) && !exists(s2))
ec = std::make_error_code(std::errc::no_such_file_or_directory);