The Go Programming Language

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

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.