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  
    30  	// Extract the parent folder from path by first removing any trailing
    31  	// path separator and then scanning backward until finding a path
    32  	// separator or reaching the beginning of the string.
    33  	i := len(path) - 1
    34  	for i >= 0 && IsPathSeparator(path[i]) {
    35  		i--
    36  	}
    37  	for i >= 0 && !IsPathSeparator(path[i]) {
    38  		i--
    39  	}
    40  	if i < 0 {
    41  		i = 0
    42  	}
    43  
    44  	// If there is a parent directory, and it is not the volume name,
    45  	// recurse to ensure parent directory exists.
    46  	if parent := path[:i]; len(parent) > len(volumeName(path)) {
    47  		err = MkdirAll(parent, perm)
    48  		if err != nil {
    49  			return err
    50  		}
    51  	}
    52  
    53  	// Parent now exists; invoke Mkdir and use its result.
    54  	err = Mkdir(path, perm)
    55  	if err != nil {
    56  		// Handle arguments like "foo/." by
    57  		// double-checking that directory doesn't exist.
    58  		dir, err1 := Lstat(path)
    59  		if err1 == nil && dir.IsDir() {
    60  			return nil
    61  		}
    62  		return err
    63  	}
    64  	return nil
    65  }
    66  
    67  // RemoveAll removes path and any children it contains.
    68  // It removes everything it can but returns the first error
    69  // it encounters. If the path does not exist, RemoveAll
    70  // returns nil (no error).
    71  // If there is an error, it will be of type *PathError.
    72  func RemoveAll(path string) error {
    73  	return removeAll(path)
    74  }
    75  
    76  // endsWithDot reports whether the final component of path is ".".
    77  func endsWithDot(path string) bool {
    78  	if path == "." {
    79  		return true
    80  	}
    81  	if len(path) >= 2 && path[len(path)-1] == '.' && IsPathSeparator(path[len(path)-2]) {
    82  		return true
    83  	}
    84  	return false
    85  }
    86  

View as plain text