Browse Source

fix(fs): fix directory junction handling (fixes #9775) (#9786)

### Purpose

This fixes #9775. I also improved the comments as they were lacking.

My apologies for introducing this bug. In summary, the bug was
```
mode = mode ^ (ModeSymlink | ModeIrregular)
```
didn't correctly reset those bits. This correctly resets them:
```
mode = mode &^ ModeSymlink &^ ModeIrregular
```
Tested and working in Windows 11 version 10.0.22631.4317. I didn't test
in other versions, but I'm sure this is the only issue.
Ross Smith II 1 year ago
parent
commit
377200591e
1 changed files with 6 additions and 3 deletions
  1. 6 3
      lib/fs/basicfs_lstat_windows.go

+ 6 - 3
lib/fs/basicfs_lstat_windows.go

@@ -67,7 +67,7 @@ type dirJunctFileInfo struct {
 func (fi *dirJunctFileInfo) Mode() os.FileMode {
 	// Simulate a directory and not a symlink; also set the execute
 	// bits so the directory can be traversed Unix-side.
-	return fi.FileInfo.Mode() ^ junctionPointModeMask | os.ModeDir | 0111
+	return fi.FileInfo.Mode()&^junctionPointModeMask | os.ModeDir | 0111
 }
 
 func (fi *dirJunctFileInfo) IsDir() bool {
@@ -77,10 +77,13 @@ func (fi *dirJunctFileInfo) IsDir() bool {
 var junctionPointModeMask os.FileMode
 
 func init() {
+	// Per https://tip.golang.org/doc/go1.23#minor_library_changes
+	// In go1.22 (and go1.23 when GODEBUG=winsymlink=0) Windows' directory
+	// junctions (aka "mount points") always have ModeSymlink set.
 	junctionPointModeMask = os.ModeSymlink
 	if version.Compare(runtime.Version(), "go1.23") >= 0 {
-		// if GODEBUG=winsymlink=0, then we are in g1.22 mode so let's check for
-		// os.ModeSymlink as well, as it can't hurt.
+		// In go1.23 Windows' directory junctions always have ModeIrregular set
+		// (unless GODEBUG=winsymlink=0).
 		junctionPointModeMask |= os.ModeIrregular
 	}
 }