os: fix os.MkdirAll with backslash path separator.
MkdirAll() need to use isSeparator().
Move primary defines of filepath.Separator/filepath.ListSeparator
to os.PathSeparator/os.PathListSeparator.
Move filepath.isSeparator() to os.IsPathSeparator().
filepath package refer them from os package.
Fixes #1831.
R=rsc, alex.brainman
CC=golang-dev
https://golang.org/cl/4535100
diff --git a/src/pkg/os/Makefile b/src/pkg/os/Makefile
index cd92840..c781df7 100644
--- a/src/pkg/os/Makefile
+++ b/src/pkg/os/Makefile
@@ -23,6 +23,7 @@
env_unix.go\
file_posix.go\
file_unix.go\
+ path_unix.go\
sys_bsd.go\
exec_posix.go\
exec_unix.go\
@@ -33,6 +34,7 @@
env_unix.go\
file_posix.go\
file_unix.go\
+ path_unix.go\
sys_bsd.go\
exec_posix.go\
exec_unix.go\
@@ -43,6 +45,7 @@
env_unix.go\
file_posix.go\
file_unix.go\
+ path_unix.go\
sys_linux.go\
exec_posix.go\
exec_unix.go\
@@ -53,6 +56,7 @@
env_windows.go\
file_posix.go\
file_windows.go\
+ path_windows.go\
sys_windows.go\
exec_posix.go\
exec_windows.go\
@@ -62,6 +66,7 @@
error_plan9.go\
env_plan9.go\
file_plan9.go\
+ path_plan9.go\
sys_plan9.go\
exec_plan9.go\
diff --git a/src/pkg/os/path.go b/src/pkg/os/path.go
index 5565aaa..7b93036 100644
--- a/src/pkg/os/path.go
+++ b/src/pkg/os/path.go
@@ -24,12 +24,12 @@
// Doesn't already exist; make sure parent does.
i := len(path)
- for i > 0 && path[i-1] == '/' { // Skip trailing slashes.
+ for i > 0 && IsPathSeparator(path[i-1]) { // Skip trailing path separator.
i--
}
j := i
- for j > 0 && path[j-1] != '/' { // Scan backward over element.
+ for j > 0 && !IsPathSeparator(path[j-1]) { // Scan backward over element.
j--
}
@@ -90,7 +90,7 @@
for {
names, err1 := fd.Readdirnames(100)
for _, name := range names {
- err1 := RemoveAll(path + "/" + name)
+ err1 := RemoveAll(path + string(PathSeparator) + name)
if err == nil {
err = err1
}
diff --git a/src/pkg/os/path_plan9.go b/src/pkg/os/path_plan9.go
new file mode 100644
index 0000000..3121b7b
--- /dev/null
+++ b/src/pkg/os/path_plan9.go
@@ -0,0 +1,15 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+const (
+ PathSeparator = '/' // OS-specific path separator
+ PathListSeparator = 0 // OS-specific path list separator
+)
+
+// IsPathSeparator returns true if c is a directory separator character.
+func IsPathSeparator(c uint8) bool {
+ return PathSeparator == c
+}
diff --git a/src/pkg/os/path_test.go b/src/pkg/os/path_test.go
index 1aabe46..d58945a 100644
--- a/src/pkg/os/path_test.go
+++ b/src/pkg/os/path_test.go
@@ -6,6 +6,7 @@
import (
. "os"
+ "path/filepath"
"testing"
"runtime"
"syscall"
@@ -44,8 +45,8 @@
if !ok {
t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err)
}
- if perr.Path != fpath {
- t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", fpath, perr.Path, fpath)
+ if filepath.Clean(perr.Path) != filepath.Clean(fpath) {
+ t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", fpath, filepath.Clean(perr.Path), filepath.Clean(fpath))
}
// Can't make subdirectory of file.
@@ -58,8 +59,16 @@
if !ok {
t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err)
}
- if perr.Path != fpath {
- t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, perr.Path, fpath)
+ if filepath.Clean(perr.Path) != filepath.Clean(fpath) {
+ t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, filepath.Clean(perr.Path), filepath.Clean(fpath))
+ }
+
+ if syscall.OS == "windows" {
+ path := `_test\_TestMkdirAll_\dir\.\dir2\`
+ err := MkdirAll(path, 0777)
+ if err != nil {
+ t.Fatalf("MkdirAll %q: %s", path, err)
+ }
}
}
diff --git a/src/pkg/os/path_unix.go b/src/pkg/os/path_unix.go
new file mode 100644
index 0000000..0d327cd
--- /dev/null
+++ b/src/pkg/os/path_unix.go
@@ -0,0 +1,15 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+const (
+ PathSeparator = '/' // OS-specific path separator
+ PathListSeparator = ':' // OS-specific path list separator
+)
+
+// IsPathSeparator returns true if c is a directory separator character.
+func IsPathSeparator(c uint8) bool {
+ return PathSeparator == c
+}
diff --git a/src/pkg/os/path_windows.go b/src/pkg/os/path_windows.go
new file mode 100644
index 0000000..8740a9e
--- /dev/null
+++ b/src/pkg/os/path_windows.go
@@ -0,0 +1,16 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+const (
+ PathSeparator = '\\' // OS-specific path separator
+ PathListSeparator = ':' // OS-specific path list separator
+)
+
+// IsPathSeparator returns true if c is a directory separator character.
+func IsPathSeparator(c uint8) bool {
+ // NOTE: Windows accept / as path separator.
+ return c == '\\' || c == '/'
+}
diff --git a/src/pkg/path/filepath/path.go b/src/pkg/path/filepath/path.go
index 6917218..147256a 100644
--- a/src/pkg/path/filepath/path.go
+++ b/src/pkg/path/filepath/path.go
@@ -15,6 +15,8 @@
)
const (
+ Separator = os.PathSeparator
+ ListSeparator = os.PathListSeparator
SeparatorString = string(Separator)
ListSeparatorString = string(ListSeparator)
)
@@ -61,20 +63,20 @@
for r < n {
switch {
- case isSeparator(path[r]):
+ case os.IsPathSeparator(path[r]):
// empty path element
r++
- case path[r] == '.' && (r+1 == n || isSeparator(path[r+1])):
+ case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
// . element
r++
- case path[r] == '.' && path[r+1] == '.' && (r+2 == n || isSeparator(path[r+2])):
+ case path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
// .. element: remove to last separator
r += 2
switch {
case w > dotdot:
// can backtrack
w--
- for w > dotdot && !isSeparator(buf[w]) {
+ for w > dotdot && !os.IsPathSeparator(buf[w]) {
w--
}
case !rooted:
@@ -97,7 +99,7 @@
w++
}
// copy element
- for ; r < n && !isSeparator(path[r]); r++ {
+ for ; r < n && !os.IsPathSeparator(path[r]); r++ {
buf[w] = path[r]
w++
}
@@ -145,7 +147,7 @@
// and file set to path.
func Split(path string) (dir, file string) {
i := len(path) - 1
- for i >= 0 && !isSeparator(path[i]) {
+ for i >= 0 && !os.IsPathSeparator(path[i]) {
i--
}
return path[:i+1], path[i+1:]
@@ -167,7 +169,7 @@
// in the final element of path; it is empty if there is
// no dot.
func Ext(path string) string {
- for i := len(path) - 1; i >= 0 && !isSeparator(path[i]); i-- {
+ for i := len(path) - 1; i >= 0 && !os.IsPathSeparator(path[i]); i-- {
if path[i] == '.' {
return path[i:]
}
@@ -339,12 +341,12 @@
return "."
}
// Strip trailing slashes.
- for len(path) > 0 && isSeparator(path[len(path)-1]) {
+ for len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) {
path = path[0 : len(path)-1]
}
// Find the last element
i := len(path) - 1
- for i >= 0 && !isSeparator(path[i]) {
+ for i >= 0 && !os.IsPathSeparator(path[i]) {
i--
}
if i >= 0 {
diff --git a/src/pkg/path/filepath/path_plan9.go b/src/pkg/path/filepath/path_plan9.go
index e400083..47990e0 100644
--- a/src/pkg/path/filepath/path_plan9.go
+++ b/src/pkg/path/filepath/path_plan9.go
@@ -6,16 +6,6 @@
import "strings"
-const (
- Separator = '/' // OS-specific path separator
- ListSeparator = 0 // OS-specific path list separator
-)
-
-// isSeparator returns true if c is a directory separator character.
-func isSeparator(c uint8) bool {
- return Separator == c
-}
-
// IsAbs returns true if the path is absolute.
func IsAbs(path string) bool {
return strings.HasPrefix(path, "/") || strings.HasPrefix(path, "#")
diff --git a/src/pkg/path/filepath/path_unix.go b/src/pkg/path/filepath/path_unix.go
index f8ac248..ea555fc 100644
--- a/src/pkg/path/filepath/path_unix.go
+++ b/src/pkg/path/filepath/path_unix.go
@@ -6,16 +6,6 @@
import "strings"
-const (
- Separator = '/' // OS-specific path separator
- ListSeparator = ':' // OS-specific path list separator
-)
-
-// isSeparator returns true if c is a directory separator character.
-func isSeparator(c uint8) bool {
- return Separator == c
-}
-
// IsAbs returns true if the path is absolute.
func IsAbs(path string) bool {
return strings.HasPrefix(path, "/")
diff --git a/src/pkg/path/filepath/path_windows.go b/src/pkg/path/filepath/path_windows.go
index dbd1c1e..35302eb 100644
--- a/src/pkg/path/filepath/path_windows.go
+++ b/src/pkg/path/filepath/path_windows.go
@@ -4,20 +4,11 @@
package filepath
-const (
- Separator = '\\' // OS-specific path separator
- ListSeparator = ':' // OS-specific path list separator
-)
-
-// isSeparator returns true if c is a directory separator character.
-func isSeparator(c uint8) bool {
- // NOTE: Windows accept / as path separator.
- return c == '\\' || c == '/'
-}
+import "os"
// IsAbs returns true if the path is absolute.
func IsAbs(path string) bool {
- return path != "" && (volumeName(path) != "" || isSeparator(path[0]))
+ return path != "" && (volumeName(path) != "" || os.IsPathSeparator(path[0]))
}
// volumeName return leading volume name.
@@ -28,7 +19,7 @@
}
// with drive letter
c := path[0]
- if len(path) > 2 && path[1] == ':' && isSeparator(path[2]) &&
+ if len(path) > 2 && path[1] == ':' && os.IsPathSeparator(path[2]) &&
('0' <= c && c <= '9' || 'a' <= c && c <= 'z' ||
'A' <= c && c <= 'Z') {
return path[0:2]