Copyright 2018 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+build aix darwin dragonfly freebsd linux netbsd openbsd solaris

package os

import (
	
	
	
)

func ( string) error {
fail silently to retain compatibility with previous behavior of RemoveAll. See issue 28830.
		return nil
	}
The rmdir system call does not permit removing ".", so we don't permit it either.
	if endsWithDot() {
		return &PathError{Op: "RemoveAll", Path: , Err: syscall.EINVAL}
	}
Simple case: if Remove works, we're done.
	 := Remove()
	if  == nil || IsNotExist() {
		return nil
	}
RemoveAll recurses by deleting the path base from its parent directory
	,  := splitPath()

	,  := Open()
If parent does not exist, base cannot exist. Fail silently
		return nil
	}
	if  != nil {
		return 
	}
	defer .Close()

	if  := removeAllFrom(, );  != nil {
		if ,  := .(*PathError);  {
			.Path =  + string(PathSeparator) + .Path
			 = 
		}
		return 
	}
	return nil
}

func ( *File,  string) error {
Simple case: if Unlink (aka remove) works, we're done.
	 := unix.Unlinkat(, , 0)
	if  == nil || IsNotExist() {
		return nil
	}
EISDIR means that we have a directory, and we need to remove its contents. EPERM or EACCES means that we don't have write permission on the parent directory, but this entry might still be a directory whose contents need to be removed. Otherwise just return the error.
	if  != syscall.EISDIR &&  != syscall.EPERM &&  != syscall.EACCES {
		return &PathError{Op: "unlinkat", Path: , Err: }
	}
Is this a directory we need to recurse into?
	var  syscall.Stat_t
	 := unix.Fstatat(, , &, unix.AT_SYMLINK_NOFOLLOW)
	if  != nil {
		if IsNotExist() {
			return nil
		}
		return &PathError{Op: "fstatat", Path: , Err: }
	}
Not a directory; return the error from the unix.Unlinkat.
		return &PathError{Op: "unlinkat", Path: , Err: }
	}
Remove the directory's entries.
	var  error
	for {
		const  = 1024
		var  int
Open the directory to recurse into
		,  := openFdAt(, )
		if  != nil {
			if IsNotExist() {
				return nil
			}
			 = &PathError{Op: "openfdat", Path: , Err: }
			break
		}

		for {
			 := 0

Errors other than EOF should stop us from continuing.
			if  != nil &&  != io.EOF {
				.Close()
				if IsNotExist() {
					return nil
				}
				return &PathError{Op: "readdirnames", Path: , Err: }
			}

			 = len()
			for ,  := range  {
				 := (, )
				if  != nil {
					if ,  := .(*PathError);  {
						.Path =  + string(PathSeparator) + .Path
					}
					++
					if  == nil {
						 = 
					}
				}
			}
If we can delete any entry, break to start new iteration. Otherwise, we discard current names, get next entries and try deleting them.
			if  !=  {
				break
			}
		}
Removing files from the directory may have caused the OS to reshuffle it. Simply calling Readdirnames again may skip some entries. The only reliable way to avoid this is to close and re-open the directory. See issue 20841.
		.Close()
Finish when the end of the directory is reached
		if  <  {
			break
		}
	}
Remove the directory itself.
	 := unix.Unlinkat(, , unix.AT_REMOVEDIR)
	if  == nil || IsNotExist() {
		return nil
	}

	if  != nil {
		return 
	}
	return &PathError{Op: "unlinkat", Path: , Err: }
}
openFdAt opens path relative to the directory in fd. Other than that this should act like openFileNolog. This acts like openFileNolog rather than OpenFile because we are going to (try to) remove the file. The contents of this file are not relevant for test caching.
func ( int,  string) (*File, error) {
	var  int
	for {
		var  error
		,  = unix.Openat(, , O_RDONLY|syscall.O_CLOEXEC, 0)
		if  == nil {
			break
		}
See comment in openFileNolog.
		if  == syscall.EINTR {
			continue
		}

		return nil, 
	}

	if !supportsCloseOnExec {
		syscall.CloseOnExec()
	}

	return newFile(uintptr(), , kindOpenFile), nil