]> Cypherpunks repositories - gostls13.git/commitdiff
os, syscall: revert Yosemite readdir workaround
authorBrad Fitzpatrick <bradfitz@golang.org>
Sun, 8 Feb 2015 20:19:20 +0000 (12:19 -0800)
committerBrad Fitzpatrick <bradfitz@golang.org>
Sun, 8 Feb 2015 21:04:15 +0000 (21:04 +0000)
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>
src/os/os_test.go
src/syscall/syscall_bsd.go

index d26eb9c1812f8f145d7c0fb56fbaed0f0e6e6ccb..b705e2d6d2ae5a0b5cc88e5dce6e02153eae8749 100644 (file)
@@ -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) {
        // Hardlinks are not supported under windows or Plan 9.
        if runtime.GOOS == "plan9" {
index 2556fa8746991d0311cb9702f474f482de185087..af563910b197c6284e0b8752ed4f5988d1ab29a4 100644 (file)
@@ -68,40 +68,7 @@ func ReadDirent(fd int, buf []byte) (n int, err error) {
        // actual system call is getdirentries64, 64 is a good guess.
        // TODO(rsc): Can we use a single global basep for all calls?
        var base = (*uintptr)(unsafe.Pointer(new(uint64)))
-       n, err = 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
+       return Getdirentries(fd, buf, base)
 }
 
 // Wait status is 7 bits at bottom, either 0 (exited),