github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/os/path.go (about)

     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  }