Browse Source

Windows: mkdirall volume path aware

Signed-off-by: jhowardmsft <jhoward@microsoft.com>
jhowardmsft 10 years ago
parent
commit
86d1223a29
3 changed files with 78 additions and 2 deletions
  1. 3 2
      api/common.go
  2. 11 0
      pkg/system/filesys.go
  3. 64 0
      pkg/system/filesys_windows.go

+ 3 - 2
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)

+ 11 - 0
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)
+}

+ 64 - 0
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
+}