From 86d1223a29907ffc6afba557b5138cfad7816bb4 Mon Sep 17 00:00:00 2001 From: jhowardmsft Date: Thu, 23 Apr 2015 15:55:36 -0700 Subject: [PATCH] Windows: mkdirall volume path aware Signed-off-by: jhowardmsft --- api/common.go | 5 +-- pkg/system/filesys.go | 11 ++++++ pkg/system/filesys_windows.go | 64 +++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 pkg/system/filesys.go create mode 100644 pkg/system/filesys_windows.go diff --git a/api/common.go b/api/common.go index 4a9523cd45..743eb67091 100644 --- a/api/common.go +++ b/api/common.go @@ -3,13 +3,13 @@ package api import ( "fmt" "mime" - "os" "path/filepath" "sort" "strings" "github.com/Sirupsen/logrus" "github.com/docker/docker/api/types" + "github.com/docker/docker/pkg/system" "github.com/docker/docker/pkg/version" "github.com/docker/libtrust" ) @@ -107,7 +107,8 @@ func MatchesContentType(contentType, expectedType string) bool { // LoadOrCreateTrustKey attempts to load the libtrust key at the given path, // otherwise generates a new one func LoadOrCreateTrustKey(trustKeyPath string) (libtrust.PrivateKey, error) { - if err := os.MkdirAll(filepath.Dir(trustKeyPath), 0700); err != nil { + err := system.MkdirAll(filepath.Dir(trustKeyPath), 0700) + if err != nil { return nil, err } trustKey, err := libtrust.LoadKeyFile(trustKeyPath) diff --git a/pkg/system/filesys.go b/pkg/system/filesys.go new file mode 100644 index 0000000000..e1f70e8dac --- /dev/null +++ b/pkg/system/filesys.go @@ -0,0 +1,11 @@ +// +build !windows + +package system + +import ( + "os" +) + +func MkdirAll(path string, perm os.FileMode) error { + return os.MkdirAll(path, perm) +} diff --git a/pkg/system/filesys_windows.go b/pkg/system/filesys_windows.go new file mode 100644 index 0000000000..90b500608e --- /dev/null +++ b/pkg/system/filesys_windows.go @@ -0,0 +1,64 @@ +// +build windows + +package system + +import ( + "os" + "regexp" + "syscall" +) + +// MkdirAll implementation that is volume path aware for Windows. +func MkdirAll(path string, perm os.FileMode) error { + if re := regexp.MustCompile(`^\\\\\?\\Volume{[a-z0-9-]+}$`); re.MatchString(path) { + return nil + } + + // The rest of this method is copied from os.MkdirAll and should be kept + // as-is to ensure compatibility. + + // Fast path: if we can tell whether path is a directory or file, stop with success or error. + dir, err := os.Stat(path) + if err == nil { + if dir.IsDir() { + return nil + } + return &os.PathError{ + Op: "mkdir", + Path: path, + Err: syscall.ENOTDIR, + } + } + + // Slow path: make sure parent exists and then call Mkdir for path. + i := len(path) + for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator. + i-- + } + + j := i + for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element. + j-- + } + + if j > 1 { + // Create parent + err = MkdirAll(path[0:j-1], perm) + if err != nil { + return err + } + } + + // Parent now exists; invoke Mkdir and use its result. + err = os.Mkdir(path, perm) + if err != nil { + // Handle arguments like "foo/." by + // double-checking that directory doesn't exist. + dir, err1 := os.Lstat(path) + if err1 == nil && dir.IsDir() { + return nil + } + return err + } + return nil +}