Skip to content

Commit 6e0a81a

Browse files
committed
path/filepath: use RtlIsDosDeviceName_U to detect Windows devices
RtlIsDosDeviceName_U is specifically designed to detect Windows devices. We were using GetFullPathName to do this, but it's not the right API for the job, as it is slower and allocates more memory. goos: windows goarch: amd64 pkg: path/filepath cpu: Intel(R) Core(TM) i7-10850H CPU @ 2.70GHz │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ IsLocal-12 5.685µ ± 59% 1.853µ ± 12% -67.41% (p=0.000 n=10) │ old.txt │ new.txt │ │ B/op │ B/op vs base │ IsLocal-12 496.00 ± 0% 48.00 ± 0% -90.32% (p=0.000 n=10) │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ IsLocal-12 10.000 ± 0% 6.000 ± 0% -40.00% (p=0.000 n=10) Change-Id: Ib40ad7a90ab93cf7051c8d6becbce4d287f10f4e Reviewed-on: https://go-review.googlesource.com/c/go/+/650578 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Michael Knyszek <[email protected]> Reviewed-by: Damien Neil <[email protected]>
1 parent 9ddeac3 commit 6e0a81a

File tree

4 files changed

+31
-11
lines changed

4 files changed

+31
-11
lines changed

Diff for: src/internal/filepathlite/path_windows.go

+8-11
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package filepathlite
77
import (
88
"internal/bytealg"
99
"internal/stringslite"
10+
"internal/syscall/windows"
1011
"syscall"
1112
)
1213

@@ -114,13 +115,14 @@ func isReservedName(name string) bool {
114115
return true
115116
}
116117
// The path element is a reserved name with an extension.
117-
// Some Windows versions consider this a reserved name,
118-
// while others do not. Use FullPath to see if the name is
119-
// reserved.
120-
if p, _ := syscall.FullPath(name); len(p) >= 4 && p[:4] == `\\.\` {
121-
return true
118+
// Since Windows 11, reserved names with extensions are no
119+
// longer reserved. For example, "CON.txt" is a valid file
120+
// name. Use RtlIsDosDeviceName_U to see if the name is reserved.
121+
p, err := syscall.UTF16PtrFromString(name)
122+
if err != nil {
123+
return false
122124
}
123-
return false
125+
return windows.RtlIsDosDeviceName_U(p) > 0
124126
}
125127

126128
func isReservedBaseName(name string) bool {
@@ -297,11 +299,6 @@ func cutPath(path string) (before, after string, found bool) {
297299
return path, "", false
298300
}
299301

300-
// isUNC reports whether path is a UNC path.
301-
func isUNC(path string) bool {
302-
return len(path) > 1 && IsPathSeparator(path[0]) && IsPathSeparator(path[1])
303-
}
304-
305302
// postClean adjusts the results of Clean to avoid turning a relative path
306303
// into an absolute or rooted one.
307304
func postClean(out *lazybuf) {

Diff for: src/internal/syscall/windows/syscall_windows.go

+1
Original file line numberDiff line numberDiff line change
@@ -535,3 +535,4 @@ const (
535535
//sys NtOpenFile(handle *syscall.Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, share uint32, options uint32) (ntstatus error) = ntdll.NtOpenFile
536536
//sys rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) = ntdll.RtlNtStatusToDosErrorNoTeb
537537
//sys NtSetInformationFile(handle syscall.Handle, iosb *IO_STATUS_BLOCK, inBuffer uintptr, inBufferLen uint32, class uint32) (ntstatus error) = ntdll.NtSetInformationFile
538+
//sys RtlIsDosDeviceName_U(name *uint16) (ret uint32) = ntdll.RtlIsDosDeviceName_U

Diff for: src/internal/syscall/windows/zsyscall_windows.go

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: src/path/filepath/path_test.go

+15
Original file line numberDiff line numberDiff line change
@@ -1889,3 +1889,18 @@ func TestEvalSymlinksTooManyLinks(t *testing.T) {
18891889
t.Fatal("expected error, got nil")
18901890
}
18911891
}
1892+
1893+
func BenchmarkIsLocal(b *testing.B) {
1894+
tests := islocaltests
1895+
if runtime.GOOS == "windows" {
1896+
tests = append(tests, winislocaltests...)
1897+
}
1898+
if runtime.GOOS == "plan9" {
1899+
tests = append(tests, plan9islocaltests...)
1900+
}
1901+
for b.Loop() {
1902+
for _, test := range tests {
1903+
filepath.IsLocal(test.path)
1904+
}
1905+
}
1906+
}

0 commit comments

Comments
 (0)