github.com/remobjects/goldbaselibrary@v0.0.0-20230924164425-d458680a936b/Source/Gold/os/removeall_noat.go (about) 1 // Copyright 2018 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 // +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris 6 7 package os 8 9 import ( 10 "io" 11 "syscall" 12 ) 13 14 func removeAll(path string) error { 15 if path == "" { 16 // fail silently to retain compatibility with previous behavior 17 // of RemoveAll. See issue 28830. 18 return nil 19 } 20 21 // The rmdir system call permits removing "." on Plan 9, 22 // so we don't permit it to remain consistent with the 23 // "at" implementation of RemoveAll. 24 if endsWithDot(path) { 25 return &PathError{"RemoveAll", path, syscall.EINVAL} 26 } 27 28 // Simple case: if Remove works, we're done. 29 err := Remove(path) 30 if err == nil || IsNotExist(err) { 31 return nil 32 } 33 34 // Otherwise, is this a directory we need to recurse into? 35 dir, serr := Lstat(path) 36 if serr != nil { 37 if serr, ok := serr.(*PathError); ok && (IsNotExist(serr.Err) || serr.Err == syscall.ENOTDIR) { 38 return nil 39 } 40 return serr 41 } 42 if !dir.IsDir() { 43 // Not a directory; return the error from Remove. 44 return err 45 } 46 47 // Remove contents & return first error. 48 err = nil 49 for { 50 fd, err := Open(path) 51 if err != nil { 52 if IsNotExist(err) { 53 // Already deleted by someone else. 54 return nil 55 } 56 return err 57 } 58 59 const reqSize = 1024 60 var names []string 61 var readErr error 62 63 for { 64 numErr := 0 65 names, readErr = fd.Readdirnames(reqSize) 66 67 for _, name := range names { 68 err1 := RemoveAll(path + string(PathSeparator) + name) 69 if err == nil { 70 err = err1 71 } 72 if err1 != nil { 73 numErr++ 74 } 75 } 76 77 // If we can delete any entry, break to start new iteration. 78 // Otherwise, we discard current names, get next entries and try deleting them. 79 if numErr != reqSize { 80 break 81 } 82 } 83 84 // Removing files from the directory may have caused 85 // the OS to reshuffle it. Simply calling Readdirnames 86 // again may skip some entries. The only reliable way 87 // to avoid this is to close and re-open the 88 // directory. See issue 20841. 89 fd.Close() 90 91 if readErr == io.EOF { 92 break 93 } 94 // If Readdirnames returned an error, use it. 95 if err == nil { 96 err = readErr 97 } 98 if len(names) == 0 { 99 break 100 } 101 102 // We don't want to re-open unnecessarily, so if we 103 // got fewer than request names from Readdirnames, try 104 // simply removing the directory now. If that 105 // succeeds, we are done. 106 if len(names) < reqSize { 107 err1 := Remove(path) 108 if err1 == nil || IsNotExist(err1) { 109 return nil 110 } 111 112 if err != nil { 113 // We got some error removing the 114 // directory contents, and since we 115 // read fewer names than we requested 116 // there probably aren't more files to 117 // remove. Don't loop around to read 118 // the directory again. We'll probably 119 // just get the same error. 120 return err 121 } 122 } 123 } 124 125 // Remove directory. 126 err1 := Remove(path) 127 err1 = removeAllTestHook(err1) 128 if err1 == nil || IsNotExist(err1) { 129 return nil 130 } 131 if err == nil { 132 err = err1 133 } 134 return err 135 }