Skip to content

Commit 933f112

Browse files
committed
Revert "Switch to using GetFinalPathNameByHandle"
This reverts commit f05c99d.
1 parent f2749e3 commit 933f112

File tree

9 files changed

+177
-101
lines changed

9 files changed

+177
-101
lines changed

go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ go 1.23.3
55
require (
66
github.com/go-json-experiment/json v0.0.0-20241127185351-9802db03f36a
77
github.com/google/go-cmp v0.6.0
8-
golang.org/x/sys v0.27.0
98
golang.org/x/tools v0.27.0
109
gotest.tools/v3 v3.5.1
1110
)

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
66
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
77
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
88
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
9-
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
10-
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
119
golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o=
1210
golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
1311
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=

internal/vfs/os.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func (vfs *osFS) Realpath(path string) string {
8282

8383
orig := path
8484
path = filepath.FromSlash(path)
85-
path, err := realpath(path)
85+
path, err := walkSymlinks(path)
8686
if err != nil {
8787
return orig
8888
}

internal/vfs/realpath_other.go

Lines changed: 0 additions & 11 deletions
This file was deleted.

internal/vfs/realpath_windows.go

Lines changed: 0 additions & 86 deletions
This file was deleted.

internal/vfs/symlink.go

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
// Copyright 2012 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package vfs
6+
7+
import (
8+
"errors"
9+
"io/fs"
10+
"os"
11+
"path/filepath"
12+
"runtime"
13+
"syscall"
14+
)
15+
16+
// This is a copy of filepath.EvalSymlinks, but treats junctions as symlinks, matching pre-Go 1.23 behavior.
17+
18+
func volumeNameLen(path string) int {
19+
return len(filepath.VolumeName(path))
20+
}
21+
22+
func walkSymlinks(path string) (string, error) {
23+
volLen := volumeNameLen(path)
24+
pathSeparator := string(os.PathSeparator)
25+
26+
if volLen < len(path) && os.IsPathSeparator(path[volLen]) {
27+
volLen++
28+
}
29+
vol := path[:volLen]
30+
dest := vol
31+
linksWalked := 0
32+
for start, end := volLen, volLen; start < len(path); start = end { //nolint:ineffassign
33+
for start < len(path) && os.IsPathSeparator(path[start]) {
34+
start++
35+
}
36+
end = start
37+
for end < len(path) && !os.IsPathSeparator(path[end]) {
38+
end++
39+
}
40+
41+
// On Windows, "." can be a symlink.
42+
// We look it up, and use the value if it is absolute.
43+
// If not, we just return ".".
44+
isWindowsDot := runtime.GOOS == "windows" && path[volumeNameLen(path):] == "."
45+
46+
// The next path component is in path[start:end].
47+
if end == start {
48+
// No more path components.
49+
break
50+
} else if path[start:end] == "." && !isWindowsDot {
51+
// Ignore path component ".".
52+
continue
53+
} else if path[start:end] == ".." {
54+
// Back up to previous component if possible.
55+
// Note that volLen includes any leading slash.
56+
57+
// Set r to the index of the last slash in dest,
58+
// after the volume.
59+
var r int
60+
for r = len(dest) - 1; r >= volLen; r-- {
61+
if os.IsPathSeparator(dest[r]) {
62+
break
63+
}
64+
}
65+
if r < volLen || dest[r+1:] == ".." {
66+
// Either path has no slashes
67+
// (it's empty or just "C:")
68+
// or it ends in a ".." we had to keep.
69+
// Either way, keep this "..".
70+
if len(dest) > volLen {
71+
dest += pathSeparator
72+
}
73+
dest += ".."
74+
} else {
75+
// Discard everything since the last slash.
76+
dest = dest[:r]
77+
}
78+
continue
79+
}
80+
81+
// Ordinary path component. Add it to result.
82+
83+
if len(dest) > volumeNameLen(dest) && !os.IsPathSeparator(dest[len(dest)-1]) {
84+
dest += pathSeparator
85+
}
86+
87+
dest += path[start:end]
88+
89+
// Resolve symlink.
90+
91+
fi, err := os.Lstat(dest)
92+
if err != nil {
93+
return "", err
94+
}
95+
96+
if fi.Mode()&fs.ModeSymlink == 0 && !isJunction(fi) {
97+
if !fi.Mode().IsDir() && end < len(path) {
98+
return "", syscall.ENOTDIR
99+
}
100+
continue
101+
}
102+
103+
// Found symlink.
104+
105+
linksWalked++
106+
if linksWalked > 255 {
107+
return "", errors.New("EvalSymlinks: too many links")
108+
}
109+
110+
link, err := os.Readlink(dest)
111+
if err != nil {
112+
return "", err
113+
}
114+
115+
if isWindowsDot && !filepath.IsAbs(link) {
116+
// On Windows, if "." is a relative symlink,
117+
// just return ".".
118+
break
119+
}
120+
121+
path = link + path[end:]
122+
123+
v := volumeNameLen(link)
124+
if v > 0 {
125+
// Symlink to drive name is an absolute path.
126+
if v < len(link) && os.IsPathSeparator(link[v]) {
127+
v++
128+
}
129+
vol = link[:v]
130+
dest = vol
131+
end = len(vol)
132+
} else if len(link) > 0 && os.IsPathSeparator(link[0]) {
133+
// Symlink to absolute path.
134+
dest = link[:1]
135+
end = 1
136+
vol = link[:1]
137+
volLen = 1
138+
} else {
139+
// Symlink to relative path; replace last
140+
// path component in dest.
141+
var r int
142+
for r = len(dest) - 1; r >= volLen; r-- {
143+
if os.IsPathSeparator(dest[r]) {
144+
break
145+
}
146+
}
147+
if r < volLen {
148+
dest = vol
149+
} else {
150+
dest = dest[:r]
151+
}
152+
end = 0
153+
}
154+
}
155+
return filepath.Clean(dest), nil
156+
}

internal/vfs/symlink_other.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//go:build !windows
2+
3+
package vfs
4+
5+
import "os"
6+
7+
func isJunction(fi os.FileInfo) bool {
8+
return false
9+
}
File renamed without changes.

internal/vfs/symlink_windows.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package vfs
2+
3+
import (
4+
"os"
5+
"syscall"
6+
)
7+
8+
func isJunction(fi os.FileInfo) bool {
9+
sys := fi.Sys().(*syscall.Win32FileAttributeData)
10+
return sys.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 && sys.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0
11+
}

0 commit comments

Comments
 (0)