src/pkg/os/path.go - The Go Programming Language

Golang

Source file src/pkg/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		// If path exists, 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		// Doesn't already exist; make sure parent does.
    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		// Now parent exists, try to create.
    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 {
    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			return err
    90		}
    91	
    92		// Remove contents & return first error.
    93		err = nil
    94		for {
    95			names, err1 := fd.Readdirnames(100)
    96			for _, name := range names {
    97				err1 := RemoveAll(path + string(PathSeparator) + name)
    98				if err == nil {
    99					err = err1
   100				}
   101			}
   102			if err1 == io.EOF {
   103				break
   104			}
   105			// If Readdirnames returned an error, use it.
   106			if err == nil {
   107				err = err1
   108			}
   109			if len(names) == 0 {
   110				break
   111			}
   112		}
   113	
   114		// Close directory, because windows won't remove opened directory.
   115		fd.Close()
   116	
   117		// Remove directory.
   118		err1 := Remove(path)
   119		if err == nil {
   120			err = err1
   121		}
   122		return err
   123	}