Go Version: 1.9.3 (affects 1.4+ since cf521ce64f50c4f300294d6b649f34eca87bb8a3)
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.WalkWhat 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.
Go Version: 1.9.3 (affects 1.4+ since cf521ce64f50c4f300294d6b649f34eca87bb8a3) 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 folderI 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 usingReadlink()
. 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:
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 setModeSymlink
if the surrogate bit is set in the reparse tag.