From 7a1347a1a1f6e99627a8e9bf098351c13162e5d6 Mon Sep 17 00:00:00 2001 From: Mansour Rahimi Date: Sun, 28 Jan 2018 22:19:13 +0100 Subject: [PATCH] os: make MkdirAll support path in extended-length form Calling MkdirAll on paths in extended-length form (\\?\-prefixed) failed. MkdirAll calls itself recursively with parent directory of given path in its parameter. It finds parent directory by looking for delimiter in the path, and taking the left part. When path is in extended-length form, it finds empty path at the end. Here is a sample of path in extended-length form: \\?\c:\foo\bar This change fixes that by passing trailing path separator to MkdirAll (so it works for path like \\?\c:\). Fixes #22230 Change-Id: I363660b262588c5382ea829773d3b6005ab8df3c Reviewed-on: https://go-review.googlesource.com/86295 Reviewed-by: Alex Brainman Run-TryBot: Alex Brainman TryBot-Result: Gobot Gobot --- src/os/path.go | 6 ++++-- src/os/path_windows_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/os/path.go b/src/os/path.go index eb996e5fb91..ec6a7938b2b 100644 --- a/src/os/path.go +++ b/src/os/path.go @@ -39,8 +39,10 @@ func MkdirAll(path string, perm FileMode) error { } if j > 1 { - // Create parent - err = MkdirAll(path[0:j-1], perm) + // Create parent. + // Pass trailing path separator to MkdirAll, so our + // algorithm works for paths, like \\?\c:\ + err = MkdirAll(path[0:j], perm) if err != nil { return err } diff --git a/src/os/path_windows_test.go b/src/os/path_windows_test.go index cce0bdd522d..00a3e63bf3c 100644 --- a/src/os/path_windows_test.go +++ b/src/os/path_windows_test.go @@ -5,8 +5,10 @@ package os_test import ( + "io/ioutil" "os" "strings" + "syscall" "testing" ) @@ -44,3 +46,31 @@ func TestFixLongPath(t *testing.T) { } } } + +func TestMkdirAllExtendedLength(t *testing.T) { + tmpDir, err := ioutil.TempDir("", "TestMkdirAllExtendedLength") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpDir) + + const prefix = `\\?\` + if len(tmpDir) < 4 || tmpDir[:4] != prefix { + fullPath, err := syscall.FullPath(tmpDir) + if err != nil { + t.Fatalf("FullPath(%q) fails: %v", tmpDir, err) + } + tmpDir = prefix + fullPath + } + path := tmpDir + `\dir\` + err = os.MkdirAll(path, 0777) + if err != nil { + t.Fatalf("MkdirAll(%q) failed: %v", path, err) + } + + path = path + `.\dir2` + err = os.MkdirAll(path, 0777) + if err == nil { + t.Fatalf("MkdirAll(%q) should have failed, but did not", path) + } +}