mirror of
https://github.com/golang/go
synced 2024-11-18 12:54:44 -07:00
os, syscall: revert Yosemite readdir workaround
Reverts https://golang.org/cl/119530044 (OS X 10.10 Yosemite beta 14A299l workaround), since it was fixed in the final Yosemite release. I verified that the C program http://swtch.com/~rsc/readdirbug.c passes on Yosemite. Adds a new test to the os package too, to verify that reading a regular file as a directory fails. Fixes #9789 (ReadDir: no error if dirname is a file) Change-Id: I75286cef88fbb2ebccf045b479e33c810749dcbc Reviewed-on: https://go-review.googlesource.com/4164 Reviewed-by: Dave Cheney <dave@cheney.net>
This commit is contained in:
parent
c71b3e0e88
commit
a35181ba7f
@ -491,6 +491,30 @@ func TestReaddirStatFailures(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Readdir on a regular file should fail.
|
||||||
|
func TestReaddirOfFile(t *testing.T) {
|
||||||
|
f, err := ioutil.TempFile("", "_Go_ReaddirOfFile")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer Remove(f.Name())
|
||||||
|
f.Write([]byte("foo"))
|
||||||
|
f.Close()
|
||||||
|
reg, err := Open(f.Name())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer reg.Close()
|
||||||
|
|
||||||
|
names, err := reg.Readdirnames(-1)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Readdirnames succeeded; want non-nil error")
|
||||||
|
}
|
||||||
|
if len(names) > 0 {
|
||||||
|
t.Errorf("unexpected dir names in regular file: %q", names)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestHardLink(t *testing.T) {
|
func TestHardLink(t *testing.T) {
|
||||||
// Hardlinks are not supported under windows or Plan 9.
|
// Hardlinks are not supported under windows or Plan 9.
|
||||||
if runtime.GOOS == "plan9" {
|
if runtime.GOOS == "plan9" {
|
||||||
|
@ -68,40 +68,7 @@ func ReadDirent(fd int, buf []byte) (n int, err error) {
|
|||||||
// actual system call is getdirentries64, 64 is a good guess.
|
// actual system call is getdirentries64, 64 is a good guess.
|
||||||
// TODO(rsc): Can we use a single global basep for all calls?
|
// TODO(rsc): Can we use a single global basep for all calls?
|
||||||
var base = (*uintptr)(unsafe.Pointer(new(uint64)))
|
var base = (*uintptr)(unsafe.Pointer(new(uint64)))
|
||||||
n, err = Getdirentries(fd, buf, base)
|
return Getdirentries(fd, buf, base)
|
||||||
|
|
||||||
// On OS X 10.10 Yosemite, if you have a directory that can be returned
|
|
||||||
// in a single getdirentries64 call (for example, a directory with one file),
|
|
||||||
// and you read from the directory at EOF twice, you get EOF both times:
|
|
||||||
// fd = open("dir")
|
|
||||||
// getdirentries64(fd) // returns data
|
|
||||||
// getdirentries64(fd) // returns 0 (EOF)
|
|
||||||
// getdirentries64(fd) // returns 0 (EOF)
|
|
||||||
//
|
|
||||||
// But if you remove the file in the middle between the two calls, the
|
|
||||||
// second call returns an error instead.
|
|
||||||
// fd = open("dir")
|
|
||||||
// getdirentries64(fd) // returns data
|
|
||||||
// getdirentries64(fd) // returns 0 (EOF)
|
|
||||||
// remove("dir/file")
|
|
||||||
// getdirentries64(fd) // returns ENOENT/EINVAL
|
|
||||||
//
|
|
||||||
// Whether you get ENOENT or EINVAL depends on exactly what was
|
|
||||||
// in the directory. It is deterministic, just data-dependent.
|
|
||||||
//
|
|
||||||
// This only happens in small directories. A directory containing more data
|
|
||||||
// than fits in a 4k getdirentries64 call will return EOF correctly.
|
|
||||||
// (It's not clear if the criteria is that the directory be split across multiple
|
|
||||||
// getdirentries64 calls or that it be split across multiple file system blocks.)
|
|
||||||
//
|
|
||||||
// We could change package os to avoid the second read at EOF,
|
|
||||||
// and maybe we should, but that's a bit involved.
|
|
||||||
// For now, treat the EINVAL/ENOENT as EOF.
|
|
||||||
if runtime.GOOS == "darwin" && (err == EINVAL || err == ENOENT) {
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait status is 7 bits at bottom, either 0 (exited),
|
// Wait status is 7 bits at bottom, either 0 (exited),
|
||||||
|
Loading…
Reference in New Issue
Block a user