diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2019-01-17 15:32:10 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2019-01-17 15:32:10 +0000 |
commit | 16d46c7bfda76b5b3e88a2d9a809aacdc3ed8e1a (patch) | |
tree | ba4d252d5301e19425e9c6a71185ca7b60392f3c /libstdc++-v3/src | |
parent | fc6f857bd30bd678323783a595fc132769cdc659 (diff) | |
download | gcc-16d46c7bfda76b5b3e88a2d9a809aacdc3ed8e1a.zip gcc-16d46c7bfda76b5b3e88a2d9a809aacdc3ed8e1a.tar.gz gcc-16d46c7bfda76b5b3e88a2d9a809aacdc3ed8e1a.tar.bz2 |
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
Diffstat (limited to 'libstdc++-v3/src')
-rw-r--r-- | libstdc++-v3/src/c++17/fs_ops.cc | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc index c4b99fb..3ff0ded 100644 --- a/libstdc++-v3/src/c++17/fs_ops.cc +++ b/libstdc++-v3/src/c++17/fs_ops.cc @@ -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); |