Source file src/os/path.go
1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package os 6 7 import ( 8 "syscall" 9 ) 10 11 // MkdirAll creates a directory named path, 12 // along with any necessary parents, and returns nil, 13 // or else returns an error. 14 // The permission bits perm (before umask) are used for all 15 // directories that MkdirAll creates. 16 // If path is already a directory, MkdirAll does nothing 17 // and returns nil. 18 func MkdirAll(path string, perm FileMode) error { 19 // Fast path: if we can tell whether path is a directory or file, stop with success or error. 20 dir, err := Stat(path) 21 if err == nil { 22 if dir.IsDir() { 23 return nil 24 } 25 return &PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR} 26 } 27 28 // Slow path: make sure parent exists and then call Mkdir for path. 29 i := len(path) 30 for i > 0 && IsPathSeparator(path[i-1]) { // Skip trailing path separator. 31 i-- 32 } 33 34 j := i 35 for j > 0 && !IsPathSeparator(path[j-1]) { // Scan backward over element. 36 j-- 37 } 38 39 if j > 1 { 40 // Create parent. 41 err = MkdirAll(fixRootDirectory(path[:j-1]), perm) 42 if err != nil { 43 return err 44 } 45 } 46 47 // Parent now exists; invoke Mkdir and use its result. 48 err = Mkdir(path, perm) 49 if err != nil { 50 // Handle arguments like "foo/." by 51 // double-checking that directory doesn't exist. 52 dir, err1 := Lstat(path) 53 if err1 == nil && dir.IsDir() { 54 return nil 55 } 56 return err 57 } 58 return nil 59 } 60 61 // RemoveAll removes path and any children it contains. 62 // It removes everything it can but returns the first error 63 // it encounters. If the path does not exist, RemoveAll 64 // returns nil (no error). 65 // If there is an error, it will be of type *PathError. 66 func RemoveAll(path string) error { 67 return removeAll(path) 68 } 69 70 // endsWithDot reports whether the final component of path is ".". 71 func endsWithDot(path string) bool { 72 if path == "." { 73 return true 74 } 75 if len(path) >= 2 && path[len(path)-1] == '.' && IsPathSeparator(path[len(path)-2]) { 76 return true 77 } 78 return false 79 } 80