Skip to content

Commit

Permalink
Merge pull request #162 from Qrox/patch-1
Browse files Browse the repository at this point in the history
Fix directory iterator treating all files subsequent to a symlink as symlink on Windows
  • Loading branch information
gulrak committed Feb 17, 2023
2 parents 3e5b930 + f0caeb7 commit 655b0b3
Showing 1 changed file with 24 additions and 22 deletions.
46 changes: 24 additions & 22 deletions include/ghc/filesystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2260,41 +2260,43 @@ GHC_INLINE uintmax_t hard_links_from_INFO<BY_HANDLE_FILE_INFORMATION>(const BY_H
}

template <typename INFO>
GHC_INLINE DWORD reparse_tag_from_INFO(const INFO*)
GHC_INLINE bool is_symlink_from_INFO(const path &p, const INFO* info, std::error_code& ec)
{
return 0;
if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
auto reparseData = detail::getReparseData(p, ec);
if (!ec && reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
return true;
}
}
return false;
}

template <>
GHC_INLINE DWORD reparse_tag_from_INFO(const WIN32_FIND_DATAW* info)
GHC_INLINE bool is_symlink_from_INFO(const path &, const WIN32_FIND_DATAW* info, std::error_code&)
{
return info->dwReserved0;
// dwReserved0 is undefined unless dwFileAttributes includes the
// FILE_ATTRIBUTE_REPARSE_POINT attribute according to microsoft
// documentation. In practice, dwReserved0 is not reset which
// causes it to report the incorrect symlink status.
// Note that microsoft documentation does not say whether there is
// a null value for dwReserved0, so we test for symlink directly
// instead of returning the tag which requires returning a null
// value for non-reparse-point files.
return (info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && info->dwReserved0 == IO_REPARSE_TAG_SYMLINK;
}

template <typename INFO>
GHC_INLINE file_status status_from_INFO(const path& p, const INFO* info, std::error_code& ec, uintmax_t* sz = nullptr, time_t* lwt = nullptr)
{
file_type ft = file_type::unknown;
if (sizeof(INFO) == sizeof(WIN32_FIND_DATAW)) {
if (detail::reparse_tag_from_INFO(info) == IO_REPARSE_TAG_SYMLINK) {
ft = file_type::symlink;
}
if (is_symlink_from_INFO(p, info, ec)) {
ft = file_type::symlink;
}
else {
if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
auto reparseData = detail::getReparseData(p, ec);
if (!ec && reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
ft = file_type::symlink;
}
}
else if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
ft = file_type::directory;
}
if (ft == file_type::unknown) {
if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
ft = file_type::directory;
}
else {
ft = file_type::regular;
}
else {
ft = file_type::regular;
}
perms prms = perms::owner_read | perms::group_read | perms::others_read;
if (!(info->dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
Expand Down

0 comments on commit 655b0b3

Please sign in to comment.