Skip to content

Fix directory iterator treating all files subsequent to a symlink as symlink on Windows #162

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 17, 2023

Conversation

Qrox
Copy link
Contributor

@Qrox Qrox commented Feb 16, 2023

According to microsoft documentation on the dwReserved0 member of _WIN32_FIND_DATAW,

If the dwFileAttributes member includes the FILE_ATTRIBUTE_REPARSE_POINT attribute, this member specifies the reparse point tag.

Otherwise, this value is undefined and should not be used.

reparse_tag_from_INFO uses dwReserved0 without checking the FILE_ATTRIBUTE_REPARSE_POINT attribute, which causes directory_iterator to use a stale dwReserved0 value for all files subsequent to a symlink, causing all of these files to be treated as symlink incorrectly.

This patch checks FILE_ATTRIBUTE_REPARSE_POINT before checking dwReserved0 to correctly get the symlink status of the files. Also replaced a hack that uses structure size to determine structure type with proper templates.

This patch is tested on CleverRaven/Cataclysm-DDA#63612 and cherrypicked from that PR.

Fix directory iterator treating all files subsequent to a symlink as symlink on Windows
@gulrak
Copy link
Owner

gulrak commented Feb 17, 2023

Thank you for the fix!

@gulrak gulrak merged commit 655b0b3 into gulrak:master Feb 17, 2023
xTVaser pushed a commit to open-goal/jak-project that referenced this pull request Jul 31, 2025
The context for this is that i was symlinking files from a mod
installation that were identical to the unmodded game, for space
considerations, because i remembered having success with that in the
past, before the project made the switch to ghc's filesystem library, it
seems. <sub>(I was also much more pressed for space back then, but well,
i thought writing a small program to check for matches and link them for
me would be a good, not-so-difficult exercise...)</sub>

However i quickly started getting weird errors that it couldn't find
GAME.CGO or KERNEL.CGO even when i hadn't touched them. Initially since
i found that it occurred only when symlinking any files that were
earlier alphabetically, i assumed it was some kind of index mismatch,
but it was actually caused by a bug in an older version of
filesystem.hpp causing the `directory_iterator` to read everything after
a symlink as also a symlink, making them fail to be read properly:
gulrak/filesystem#162

Adding `f.is_symlink()` is not as much of a change to the loop's
condition from the previous behavior as it might first appear. It seems
that even without that condition the iterator *was* reading symlinks
before, just incorrectly (and before ghc::filesystem, they were being
read just fine, iirc). With the new version, though, symlinks do have to
be accounted for explicitly.

Given that the library's major and minor version are both the same, i
don't expect there should be any breaking changes to the API, and i
didn't find any when i was testing but there might need to be more
investigation into that before merging. Also, without the added check
for `f.exists()`, the behavior is exactly the same as if, for some
reason, a fakeiso file the game needs just doesn't exist in the first
place (which has no real reason to happen in a normal installation of
the game): there's a decent chance it will either crash at some point
later during runtime, or something will happen like a level failing to
load causing Jak to trip infinitely. I thought it might be helpful to
have it fail right away in the case that, say, someone moved their
vanilla installation and staled their symlinks, but i'll defer to
maintainers' judgement on that point.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants