aboutsummaryrefslogtreecommitdiff
path: root/src/os
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-02-11 19:10:10 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2021-03-23 03:49:17 +0000
commitb8371d495bb291f61e4fa3ac1b84116c70ac1223 (patch)
tree85740ff86d1fa08d8a0614ece2c5de219627e171 /src/os
parentb182ba7fabcd233a03bb8169634605a7fac6a856 (diff)
downloadgo-b8371d495bb291f61e4fa3ac1b84116c70ac1223.tar.gz
go-b8371d495bb291f61e4fa3ac1b84116c70ac1223.zip
runtime: support long paths without fixup on Windows 10 >= 1607
Windows 10 >= 1607 allows CreateFile and friends to use long paths if bit 0x80 of the PEB's BitField member is set. In time this means we'll be able to entirely drop our long path hacks, which have never really worked right (see bugs below). Until that point, we'll simply have things working well on recent Windows. Updates #41734. Updates #21782. Updates #36375. Change-Id: I765de6ea4859dd4e4b8ca80af7f337994734118e Reviewed-on: https://go-review.googlesource.com/c/go/+/291291 Trust: Jason A. Donenfeld <Jason@zx2c4.com> Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/os')
-rw-r--r--src/os/export_windows_test.go1
-rw-r--r--src/os/path_windows.go7
-rw-r--r--src/os/path_windows_test.go23
3 files changed, 31 insertions, 0 deletions
diff --git a/src/os/export_windows_test.go b/src/os/export_windows_test.go
index f36fadb58b..ff4f8995f8 100644
--- a/src/os/export_windows_test.go
+++ b/src/os/export_windows_test.go
@@ -8,6 +8,7 @@ package os
var (
FixLongPath = fixLongPath
+ CanUseLongPaths = canUseLongPaths
NewConsoleFile = newConsoleFile
CommandLineToArgv = commandLineToArgv
)
diff --git a/src/os/path_windows.go b/src/os/path_windows.go
index 87b1cac531..a96245f358 100644
--- a/src/os/path_windows.go
+++ b/src/os/path_windows.go
@@ -128,6 +128,10 @@ func dirname(path string) string {
return vol + dir
}
+// This is set via go:linkname on runtime.canUseLongPaths, and is true when the OS
+// supports opting into proper long path handling without the need for fixups.
+var canUseLongPaths bool
+
// fixLongPath returns the extended-length (\\?\-prefixed) form of
// path when needed, in order to avoid the default 260 character file
// path limit imposed by Windows. If path is not easily converted to
@@ -137,6 +141,9 @@ func dirname(path string) string {
//
// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
func fixLongPath(path string) string {
+ if canUseLongPaths {
+ return path
+ }
// Do nothing (and don't allocate) if the path is "short".
// Empirically (at least on the Windows Server 2013 builder),
// the kernel is arbitrarily okay with < 248 bytes. That
diff --git a/src/os/path_windows_test.go b/src/os/path_windows_test.go
index 869db8fd6c..a23a079f77 100644
--- a/src/os/path_windows_test.go
+++ b/src/os/path_windows_test.go
@@ -12,6 +12,9 @@ import (
)
func TestFixLongPath(t *testing.T) {
+ if os.CanUseLongPaths {
+ return
+ }
// 248 is long enough to trigger the longer-than-248 checks in
// fixLongPath, but short enough not to make a path component
// longer than 255, which is illegal on Windows. (which
@@ -46,6 +49,26 @@ func TestFixLongPath(t *testing.T) {
}
}
+func TestMkdirAllLongPath(t *testing.T) {
+ tmpDir, err := os.MkdirTemp("", "TestMkdirAllLongPath")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpDir)
+ path := tmpDir
+ for i := 0; i < 100; i++ {
+ path += `\another-path-component`
+ }
+ err = os.MkdirAll(path, 0777)
+ if err != nil {
+ t.Fatalf("MkdirAll(%q) failed; %v", path, err)
+ }
+ err = os.RemoveAll(tmpDir)
+ if err != nil {
+ t.Fatalf("RemoveAll(%q) failed; %v", tmpDir, err)
+ }
+}
+
func TestMkdirAllExtendedLength(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "TestMkdirAllExtendedLength")
if err != nil {