| // +build windows |
| |
| package system |
| |
| import ( |
| "os" |
| "path/filepath" |
| "regexp" |
| "strings" |
| "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 |
| } |
| |
| // IsAbs is a platform-specific wrapper for filepath.IsAbs. On Windows, |
| // golang filepath.IsAbs does not consider a path \windows\system32 as absolute |
| // as it doesn't start with a drive-letter/colon combination. However, in |
| // docker we need to verify things such as WORKDIR /windows/system32 in |
| // a Dockerfile (which gets translated to \windows\system32 when being processed |
| // by the daemon. This SHOULD be treated as absolute from a docker processing |
| // perspective. |
| func IsAbs(path string) bool { |
| if !filepath.IsAbs(path) { |
| if !strings.HasPrefix(path, string(os.PathSeparator)) { |
| return false |
| } |
| } |
| return true |
| } |