1
0
mirror of https://github.com/golang/go synced 2024-11-25 13:17:56 -07:00

os: make sure Remove returns correct error on windows

R=golang-dev, bsiegert, rsc
CC=golang-dev
https://golang.org/cl/5493078
This commit is contained in:
Alex Brainman 2011-12-20 11:52:20 +11:00
parent 448d89d67a
commit 796a2c19ea
3 changed files with 59 additions and 33 deletions

View 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 // LinkError records an error during a link or symlink or rename
// system call and the paths that caused it. // system call and the paths that caused it.
type LinkError struct { type LinkError struct {

View File

@ -210,6 +210,36 @@ func Truncate(name string, size int64) error {
return nil 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 // basename removes trailing slashes and the leading directory name from path name
func basename(name string) string { func basename(name string) string {
i := len(name) - 1 i := len(name) - 1

View File

@ -281,6 +281,35 @@ func Truncate(name string, size int64) error {
return nil 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. // Pipe returns a connected pair of Files; reads from r return bytes written to w.
// It returns the files and an error, if any. // It returns the files and an error, if any.
func Pipe() (r *File, w *File, err error) { func Pipe() (r *File, w *File, err error) {