]> Cypherpunks repositories - gostls13.git/commitdiff
os: make sure Remove returns correct error on windows
authorAlex Brainman <alex.brainman@gmail.com>
Tue, 20 Dec 2011 00:52:20 +0000 (11:52 +1100)
committerAlex Brainman <alex.brainman@gmail.com>
Tue, 20 Dec 2011 00:52:20 +0000 (11:52 +1100)
R=golang-dev, bsiegert, rsc
CC=golang-dev
https://golang.org/cl/5493078

src/pkg/os/file_posix.go
src/pkg/os/file_unix.go
src/pkg/os/file_windows.go

index cbbce204dc5fe1799336916bd4f0e87dbb7bc56f..8231ef4817c96ee5ccd4edccacc184ce34700ebd 100644 (file)
@@ -24,39 +24,6 @@ func epipecheck(file *File, e error) {
        }
 }
 
-// Remove removes the named file or directory.
-func Remove(name string) error {
-       // System call interface forces us to know
-       // whether name is a file or directory.
-       // Try both: it is cheaper on average than
-       // doing a Stat plus the right one.
-       e := syscall.Unlink(name)
-       if e == nil {
-               return nil
-       }
-       e1 := syscall.Rmdir(name)
-       if e1 == nil {
-               return nil
-       }
-
-       // Both failed: figure out which error to return.
-       // OS X and Linux differ on whether unlink(dir)
-       // returns EISDIR, so can't use that.  However,
-       // both agree that rmdir(file) returns ENOTDIR,
-       // so we can use that to decide which error is real.
-       // Rmdir might also return ENOTDIR if given a bad
-       // file path, like /etc/passwd/foo, but in that case,
-       // both errors will be ENOTDIR, so it's okay to
-       // use the error from unlink.
-       // For windows syscall.ENOTDIR is set
-       // to syscall.ERROR_PATH_NOT_FOUND, hopefully it should
-       // do the trick.
-       if e1 != syscall.ENOTDIR {
-               e = e1
-       }
-       return &PathError{"remove", name, e}
-}
-
 // LinkError records an error during a link or symlink or rename
 // system call and the paths that caused it.
 type LinkError struct {
index 38664d175cc4634f8ef61854c79c6250613dfe3c..cea305abe90bf2db3f69f9fb36a188fb3de30b5b 100644 (file)
@@ -210,6 +210,36 @@ func Truncate(name string, size int64) error {
        return nil
 }
 
+// Remove removes the named file or directory.
+func Remove(name string) error {
+       // System call interface forces us to know
+       // whether name is a file or directory.
+       // Try both: it is cheaper on average than
+       // doing a Stat plus the right one.
+       e := syscall.Unlink(name)
+       if e == nil {
+               return nil
+       }
+       e1 := syscall.Rmdir(name)
+       if e1 == nil {
+               return nil
+       }
+
+       // Both failed: figure out which error to return.
+       // OS X and Linux differ on whether unlink(dir)
+       // returns EISDIR, so can't use that.  However,
+       // both agree that rmdir(file) returns ENOTDIR,
+       // so we can use that to decide which error is real.
+       // Rmdir might also return ENOTDIR if given a bad
+       // file path, like /etc/passwd/foo, but in that case,
+       // both errors will be ENOTDIR, so it's okay to
+       // use the error from unlink.
+       if e1 != syscall.ENOTDIR {
+               e = e1
+       }
+       return &PathError{"remove", name, e}
+}
+
 // basename removes trailing slashes and the leading directory name from path name
 func basename(name string) string {
        i := len(name) - 1
index bdb5d1d29c8515a26edc63723e09574d098e6a3e..4bf9c26038f5c7d7a58661627673fdd6c2102824 100644 (file)
@@ -281,6 +281,35 @@ func Truncate(name string, size int64) error {
        return nil
 }
 
+// Remove removes the named file or directory.
+func Remove(name string) error {
+       p := &syscall.StringToUTF16(name)[0]
+
+       // Go file interface forces us to know whether
+       // name is a file or directory. Try both.
+       e := syscall.DeleteFile(p)
+       if e == nil {
+               return nil
+       }
+       e1 := syscall.RemoveDirectory(p)
+       if e1 == nil {
+               return nil
+       }
+
+       // Both failed: figure out which error to return.
+       if e1 != e {
+               a, e2 := syscall.GetFileAttributes(p)
+               if e2 != nil {
+                       e = e2
+               } else {
+                       if a&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
+                               e = e1
+                       }
+               }
+       }
+       return &PathError{"remove", name, e}
+}
+
 // Pipe returns a connected pair of Files; reads from r return bytes written to w.
 // It returns the files and an error, if any.
 func Pipe() (r *File, w *File, err error) {