Browse code

Windows: mkdirall volume path aware

Signed-off-by: jhowardmsft <jhoward@microsoft.com>

jhowardmsft authored on 2015/04/24 07:55:36
Showing 3 changed files
... ...
@@ -3,13 +3,13 @@ package api
3 3
 import (
4 4
 	"fmt"
5 5
 	"mime"
6
-	"os"
7 6
 	"path/filepath"
8 7
 	"sort"
9 8
 	"strings"
10 9
 
11 10
 	"github.com/Sirupsen/logrus"
12 11
 	"github.com/docker/docker/api/types"
12
+	"github.com/docker/docker/pkg/system"
13 13
 	"github.com/docker/docker/pkg/version"
14 14
 	"github.com/docker/libtrust"
15 15
 )
... ...
@@ -107,7 +107,8 @@ func MatchesContentType(contentType, expectedType string) bool {
107 107
 // LoadOrCreateTrustKey attempts to load the libtrust key at the given path,
108 108
 // otherwise generates a new one
109 109
 func LoadOrCreateTrustKey(trustKeyPath string) (libtrust.PrivateKey, error) {
110
-	if err := os.MkdirAll(filepath.Dir(trustKeyPath), 0700); err != nil {
110
+	err := system.MkdirAll(filepath.Dir(trustKeyPath), 0700)
111
+	if err != nil {
111 112
 		return nil, err
112 113
 	}
113 114
 	trustKey, err := libtrust.LoadKeyFile(trustKeyPath)
114 115
new file mode 100644
... ...
@@ -0,0 +1,11 @@
0
+// +build !windows
1
+
2
+package system
3
+
4
+import (
5
+	"os"
6
+)
7
+
8
+func MkdirAll(path string, perm os.FileMode) error {
9
+	return os.MkdirAll(path, perm)
10
+}
0 11
new file mode 100644
... ...
@@ -0,0 +1,64 @@
0
+// +build windows
1
+
2
+package system
3
+
4
+import (
5
+	"os"
6
+	"regexp"
7
+	"syscall"
8
+)
9
+
10
+// MkdirAll implementation that is volume path aware for Windows.
11
+func MkdirAll(path string, perm os.FileMode) error {
12
+	if re := regexp.MustCompile(`^\\\\\?\\Volume{[a-z0-9-]+}$`); re.MatchString(path) {
13
+		return nil
14
+	}
15
+
16
+	// The rest of this method is copied from os.MkdirAll and should be kept
17
+	// as-is to ensure compatibility.
18
+
19
+	// Fast path: if we can tell whether path is a directory or file, stop with success or error.
20
+	dir, err := os.Stat(path)
21
+	if err == nil {
22
+		if dir.IsDir() {
23
+			return nil
24
+		}
25
+		return &os.PathError{
26
+			Op:   "mkdir",
27
+			Path: path,
28
+			Err:  syscall.ENOTDIR,
29
+		}
30
+	}
31
+
32
+	// Slow path: make sure parent exists and then call Mkdir for path.
33
+	i := len(path)
34
+	for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator.
35
+		i--
36
+	}
37
+
38
+	j := i
39
+	for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element.
40
+		j--
41
+	}
42
+
43
+	if j > 1 {
44
+		// Create parent
45
+		err = MkdirAll(path[0:j-1], perm)
46
+		if err != nil {
47
+			return err
48
+		}
49
+	}
50
+
51
+	// Parent now exists; invoke Mkdir and use its result.
52
+	err = os.Mkdir(path, perm)
53
+	if err != nil {
54
+		// Handle arguments like "foo/." by
55
+		// double-checking that directory doesn't exist.
56
+		dir, err1 := os.Lstat(path)
57
+		if err1 == nil && dir.IsDir() {
58
+			return nil
59
+		}
60
+		return err
61
+	}
62
+	return nil
63
+}