-
Notifications
You must be signed in to change notification settings - Fork 18k
path/filepath: Walk recurses on directory symlinks on Windows #17540
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
Comments
You've already know the problem and the fix looks very easy. |
I disagree about junctions; those seem like Unix mountpoints, which definitely should be descended. |
os.Readlink and os.ModeSymlink handle junctions as symlinks. |
I agree, I think we should not walk both "directory junctions" (issue #10424) and "symlinks to directories" (this issue). Otherwise how do we avoid loops? Alex |
Something like this:
should fix this issue. Alex |
@quentinmit one of the problems with junction points is if you follow them, modern Windows boxes have a directory loop out of the box if you do a filepath.Walk on C:. From an end user perspective I guess the alternatives are:
FWIW I think the latter is better library default behaviour. |
@alexbrainman I think that on the one hand your suggested patch would probably have the advantage of solving #17541 as well. On the other hand it somewhat masks the fact that according to Windows the underlying object seems to be considered both a directory and a reparse point. I wonder whether a higher level adjustment in filepath.Walk itself (and in #17541, a higher level adjustment in tar.FileInfoHeader) is better. I don't know - I think there's an argument either way. |
I imagined like this
|
I considered that too. And I am not sure which approach is better. Like you said, unlike Unix, Windows returns both "is directory" and "is symlink" for some directory elements. Perhaps that confused authors of path/filepath.Walk - I suspect they did not consider that possibility. So the question is, do we:
or
? I will let others decide here. Alex |
It is definitely unexpected that the mode would be both a directory and a symlink. It should be one or the other. That said, it's important that every directory is reachable using a walk that stops at symlinks. I don't understand the specific details here, but, for example, if the root of a mounted file system were reported as a symlink with the effect that you can't ever walk into the file system at all, that would be a problem. If we know there is a perfectly good, other, canonical name, then yes, the noncanonical one should be a symlink only, not a symlink and a directory. It also matters here whether Lstat or Stat is being called. Lstat is supposed to report symlinks. Stat is supposed to not report them, instead following down to the thing being pointed at. Walk should be able to use Lstat to avoid infinite recursion. @alexbrainman, given this, can you say a bit more about what you think should happen? Thanks. |
I do not know much about symlinks myself. Symlinks appeared in Windows Vista. Windows XP did not have symlinks, but it had "Directory Junction" - these are similar to symlinks to directories - as far as I understand they have very similar functionality, but different implementation. Symlinks and "directory junctions" can be created with mklink program that comes with Windows.
The API we use to create symlinks is CreateSymbolicLink.
I do not see how you can replace root directory with "symlink directory" or "directory junctions".
I do not understand your suggestion.
I think Stat and Lstat work as expected:
I also looked at actual Stat and Lstat implementation. So what do you think we should do here? Alex |
By the way, If I mount a NTFS drive on linux, can I see the same issue? or its driver cooks for me? |
I do not see how that is possible. See https://github.com/golang/go/blob/master/src/os/stat_linux.go#L17 for details. Each file is either symlink or directory, cannot be both. Alex |
Thank you for pointing out. So I understand that current behavior doesn't follow POSIX. http://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/stat.h.html |
This is a bit involved for the freeze. Leaving for Go 1.9. |
CL https://golang.org/cl/36854 mentions this issue. |
Relative symlinks on windows confuse filepath.Walk. This is Go issue 17540, golang/go#17540. While waiting for that to get fixed, just use absolute symlinks in windows tests.
For #17540. Change-Id: Ie01f39797526934fa553f4279cbde6c7cbf14154 Reviewed-on: https://go-review.googlesource.com/36854 Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
Relative symlinks on windows confuse filepath.Walk. This is Go issue 17540, golang/go#17540. While waiting for that to get fixed, just use absolute symlinks in windows tests.
CL https://golang.org/cl/41830 mentions this issue. |
…s on Windows" issue (see golang/go#17540) [~] command output now shows how much actual overhead is better/worse than rough estimate
In the documentation to filepath.Walk, it says "Walk does not follow symbolic links." This is not the case on Windows, and I think it's a bug.
What version of Go are you using (
go version
)?What operating system and processor architecture are you using (
go env
)?What did you do?
Run the following program:
What did you expect to see?
I expect filepath.Walk not to recurse into tmpdir/directorysymlink. So I expect to see:
When run on a non-Windows system, this is the behaviour seen.
What did you see instead?
I see two problems.
Final notes:
The text was updated successfully, but these errors were encountered: