diff --git a/sys/filesys_windows.go b/sys/filesys_windows.go index 769afb572..67fc4048c 100644 --- a/sys/filesys_windows.go +++ b/sys/filesys_windows.go @@ -67,11 +67,7 @@ func mkdirall(path string, perm *windows.SecurityAttributes) error { if dir.IsDir() { return nil } - return &os.PathError{ - Op: "mkdir", - Path: path, - Err: syscall.ENOTDIR, - } + return &os.PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR} } // Slow path: make sure parent exists and then call Mkdir for path. @@ -86,14 +82,14 @@ func mkdirall(path string, perm *windows.SecurityAttributes) error { } if j > 1 { - // Create parent - err = mkdirall(path[0:j-1], perm) + // Create parent. + err = mkdirall(fixRootDirectory(path[:j-1]), perm) if err != nil { return err } } - // Parent now exists; invoke os.Mkdir or mkdirWithACL and use its result. + // Parent now exists; invoke Mkdir and use its result. err = mkdirWithACL(path, perm) if err != nil { // Handle arguments like "foo/." by @@ -131,6 +127,17 @@ func mkdirWithACL(name string, sa *windows.SecurityAttributes) error { return nil } +// fixRootDirectory fixes a reference to a drive's root directory to +// have the required trailing slash. +func fixRootDirectory(p string) string { + if len(p) == len(`\\?\c:`) { + if os.IsPathSeparator(p[0]) && os.IsPathSeparator(p[1]) && p[2] == '?' && os.IsPathSeparator(p[3]) && p[5] == ':' { + return p + `\` + } + } + return p +} + func makeSecurityAttributes(sddl string) (*windows.SecurityAttributes, error) { var sa windows.SecurityAttributes sa.Length = uint32(unsafe.Sizeof(sa))