Skip to content

Commit 86d1223

Browse files
author
jhowardmsft
committed
Windows: mkdirall volume path aware
Signed-off-by: jhowardmsft <[email protected]>
1 parent 72e9e12 commit 86d1223

3 files changed

Lines changed: 78 additions & 2 deletions

File tree

api/common.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ package api
33
import (
44
"fmt"
55
"mime"
6-
"os"
76
"path/filepath"
87
"sort"
98
"strings"
109

1110
"github.com/Sirupsen/logrus"
1211
"github.com/docker/docker/api/types"
12+
"github.com/docker/docker/pkg/system"
1313
"github.com/docker/docker/pkg/version"
1414
"github.com/docker/libtrust"
1515
)
@@ -107,7 +107,8 @@ func MatchesContentType(contentType, expectedType string) bool {
107107
// LoadOrCreateTrustKey attempts to load the libtrust key at the given path,
108108
// otherwise generates a new one
109109
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 {
111112
return nil, err
112113
}
113114
trustKey, err := libtrust.LoadKeyFile(trustKeyPath)

pkg/system/filesys.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// +build !windows
2+
3+
package system
4+
5+
import (
6+
"os"
7+
)
8+
9+
func MkdirAll(path string, perm os.FileMode) error {
10+
return os.MkdirAll(path, perm)
11+
}

pkg/system/filesys_windows.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// +build windows
2+
3+
package system
4+
5+
import (
6+
"os"
7+
"regexp"
8+
"syscall"
9+
)
10+
11+
// MkdirAll implementation that is volume path aware for Windows.
12+
func MkdirAll(path string, perm os.FileMode) error {
13+
if re := regexp.MustCompile(`^\\\\\?\\Volume{[a-z0-9-]+}$`); re.MatchString(path) {
14+
return nil
15+
}
16+
17+
// The rest of this method is copied from os.MkdirAll and should be kept
18+
// as-is to ensure compatibility.
19+
20+
// Fast path: if we can tell whether path is a directory or file, stop with success or error.
21+
dir, err := os.Stat(path)
22+
if err == nil {
23+
if dir.IsDir() {
24+
return nil
25+
}
26+
return &os.PathError{
27+
Op: "mkdir",
28+
Path: path,
29+
Err: syscall.ENOTDIR,
30+
}
31+
}
32+
33+
// Slow path: make sure parent exists and then call Mkdir for path.
34+
i := len(path)
35+
for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator.
36+
i--
37+
}
38+
39+
j := i
40+
for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element.
41+
j--
42+
}
43+
44+
if j > 1 {
45+
// Create parent
46+
err = MkdirAll(path[0:j-1], perm)
47+
if err != nil {
48+
return err
49+
}
50+
}
51+
52+
// Parent now exists; invoke Mkdir and use its result.
53+
err = os.Mkdir(path, perm)
54+
if err != nil {
55+
// Handle arguments like "foo/." by
56+
// double-checking that directory doesn't exist.
57+
dir, err1 := os.Lstat(path)
58+
if err1 == nil && dir.IsDir() {
59+
return nil
60+
}
61+
return err
62+
}
63+
return nil
64+
}

0 commit comments

Comments
 (0)