...
Run Format

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		"io"
     9		"syscall"
    10	)
    11	
    12	// MkdirAll creates a directory named path,
    13	// along with any necessary parents, and returns nil,
    14	// or else returns an error.
    15	// The permission bits perm are used for all
    16	// directories that MkdirAll creates.
    17	// If path is already a directory, MkdirAll does nothing
    18	// and returns nil.
    19	func MkdirAll(path string, perm FileMode) error {
    20		// Fast path: if we can tell whether path is a directory or file, stop with success or error.
    21		dir, err := Stat(path)
    22		if err == nil {
    23			if dir.IsDir() {
    24				return nil
    25			}
    26			return &PathError{"mkdir", path, syscall.ENOTDIR}
    27		}
    28	
    29		// Slow path: make sure parent exists and then call Mkdir for path.
    30		i := len(path)
    31		for i > 0 && IsPathSeparator(path[i-1]) { // Skip trailing path separator.
    32			i--
    33		}
    34	
    35		j := i
    36		for j > 0 && !IsPathSeparator(path[j-1]) { // Scan backward over element.
    37			j--
    38		}
    39	
    40		if j > 1 {
    41			// Create parent
    42			err = MkdirAll(path[0:j-1], perm)
    43			if err != nil {
    44				return err
    45			}
    46		}
    47	
    48		// Parent now exists; invoke Mkdir and use its result.
    49		err = Mkdir(path, perm)
    50		if err != nil {
    51			// Handle arguments like "foo/." by
    52			// double-checking that directory doesn't exist.
    53			dir, err1 := Lstat(path)
    54			if err1 == nil && dir.IsDir() {
    55				return nil
    56			}
    57			return err
    58		}
    59		return nil
    60	}
    61	
    62	// RemoveAll removes path and any children it contains.
    63	// It removes everything it can but returns the first error
    64	// it encounters. If the path does not exist, RemoveAll
    65	// returns nil (no error).
    66	func RemoveAll(path string) error {
    67		// Simple case: if Remove works, we're done.
    68		err := Remove(path)
    69		if err == nil || IsNotExist(err) {
    70			return nil
    71		}
    72	
    73		// Otherwise, is this a directory we need to recurse into?
    74		dir, serr := Lstat(path)
    75		if serr != nil {
    76			if serr, ok := serr.(*PathError); ok && (IsNotExist(serr.Err) || serr.Err == syscall.ENOTDIR) {
    77				return nil
    78			}
    79			return serr
    80		}
    81		if !dir.IsDir() {
    82			// Not a directory; return the error from Remove.
    83			return err
    84		}
    85	
    86		// Directory.
    87		fd, err := Open(path)
    88		if err != nil {
    89			if IsNotExist(err) {
    90				// Race. It was deleted between the Lstat and Open.
    91				// Return nil per RemoveAll's docs.
    92				return nil
    93			}
    94			return err
    95		}
    96	
    97		// Remove contents & return first error.
    98		err = nil
    99		for {
   100			names, err1 := fd.Readdirnames(100)
   101			for _, name := range names {
   102				err1 := RemoveAll(path + string(PathSeparator) + name)
   103				if err == nil {
   104					err = err1
   105				}
   106			}
   107			if err1 == io.EOF {
   108				break
   109			}
   110			// If Readdirnames returned an error, use it.
   111			if err == nil {
   112				err = err1
   113			}
   114			if len(names) == 0 {
   115				break
   116			}
   117		}
   118	
   119		// Close directory, because windows won't remove opened directory.
   120		fd.Close()
   121	
   122		// Remove directory.
   123		err1 := Remove(path)
   124		if err1 == nil || IsNotExist(err1) {
   125			return nil
   126		}
   127		if err == nil {
   128			err = err1
   129		}
   130		return err
   131	}
   132	

View as plain text