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]