Skip to content
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

os/types_windows: fileStat.Mode() should use the reparse tag surrogate bit to identify symlinks #23684

Closed
mattico opened this issue Feb 3, 2018 · 1 comment

Comments

@mattico
Copy link

commented Feb 3, 2018

Go Version: 1.9.3 (affects 1.4+ since cf521ce)
Operating System: Windows 10 x64 build 16299 (Fall Creator's Update)
What did you do: attempt to traverse into the OneDrive folder to list files using filepath.Walk
What did you expect to see: a listing of files inside the OneDrive folder
What did you see instead: traversal stops at the OneDrive folder

I noticed that the code for fileStat.Mode() on Windows uses the presence of FILE_ATTRIBUTE_REPARSE_POINT to determine if a file is a symlink (or rather, acts like a unix symlink). While this is a common method, it is actually incorrect. Since a reparse point is simply a hook for a filesystem minifilter driver, their semantics are mostly undefined. When Microsoft added the Files On-Demand feature to OneDrive in the Fall Creator's Update, they used a reparse point which does not behave like a symlink, and thus is not readable using Readlink(). This has caused problems for users who attempt to use readlink to traverse directories that report being symlinks.

The good news is that the surrogate bit in the reparse tag specifies if "the file or directory represents another named entity in the system". That sounds like a Microsoft definition of symlink-like behavior. I made a program which verified that the surrogate bit is set on reparse points that behave like symlinks:

PATH REPARSE TAG IsReparseTagNameSurrogate
D:\symlink 10100000000000000000000000001100 true
D:\symlink_dir 10100000000000000000000000001100 true
D:\junction 10100000000000000000000000000011 true
D:\mountpoint 10100000000000000000000000000011 true
D:\OneDrive 10010000000000000111000000011010 false
D:\hardlink hard links do not use reparse points and they don't act like symlinks

Additionally, Microsoft has indicated that the IsReparseTagNameSurrogate macro is the correct way to determine if a reparse point behaves like a symlink.

TL;DR:
filestat.Mode() should read the reparse tag, and only set ModeSymlink if the surrogate bit is set in the reparse tag.

@mattico

This comment has been minimized.

Copy link
Author

commented Feb 3, 2018

Moved information to comment on related issue #22579

@mattico mattico closed this Feb 3, 2018
@golang golang locked and limited conversation to collaborators Feb 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
2 participants
You can’t perform that action at this time.