aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/src
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2019-01-17 15:32:10 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2019-01-17 15:32:10 +0000
commit16d46c7bfda76b5b3e88a2d9a809aacdc3ed8e1a (patch)
treeba4d252d5301e19425e9c6a71185ca7b60392f3c /libstdc++-v3/src
parentfc6f857bd30bd678323783a595fc132769cdc659 (diff)
downloadgcc-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.cc42
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);