aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/os/dir.go2
-rw-r--r--src/os/file.go8
-rw-r--r--src/os/file_plan9.go4
-rw-r--r--src/os/file_unix.go30
-rw-r--r--src/os/file_windows.go4
5 files changed, 45 insertions, 3 deletions
diff --git a/src/os/dir.go b/src/os/dir.go
index 9124de29e8..dcc18e1814 100644
--- a/src/os/dir.go
+++ b/src/os/dir.go
@@ -115,7 +115,7 @@ var testingForceReadDirLstat bool
// ReadDir returns the entries it was able to read before the error,
// along with the error.
func ReadDir(name string) ([]DirEntry, error) {
- f, err := Open(name)
+ f, err := openDir(name)
if err != nil {
return nil, err
}
diff --git a/src/os/file.go b/src/os/file.go
index c0c972bbd7..fae7bf1039 100644
--- a/src/os/file.go
+++ b/src/os/file.go
@@ -380,6 +380,14 @@ func OpenFile(name string, flag int, perm FileMode) (*File, error) {
return f, nil
}
+// openDir opens a file which is assumed to be a directory. As such, it skips
+// the syscalls that make the file descriptor non-blocking as these take time
+// and will fail on file descriptors for directories.
+func openDir(name string) (*File, error) {
+ testlog.Open(name)
+ return openDirNolog(name)
+}
+
// lstat is overridden in tests.
var lstat = Lstat
diff --git a/src/os/file_plan9.go b/src/os/file_plan9.go
index 69a24316e6..477674b80a 100644
--- a/src/os/file_plan9.go
+++ b/src/os/file_plan9.go
@@ -139,6 +139,10 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
return NewFile(uintptr(fd), name), nil
}
+func openDirNolog(name string) (*File, error) {
+ return openFileNolog(name, O_RDONLY, 0)
+}
+
// Close closes the File, rendering it unusable for I/O.
// On files that support SetDeadline, any pending I/O operations will
// be canceled and return immediately with an ErrClosed error.
diff --git a/src/os/file_unix.go b/src/os/file_unix.go
index 6597186486..924ec25ed9 100644
--- a/src/os/file_unix.go
+++ b/src/os/file_unix.go
@@ -157,7 +157,7 @@ const (
kindNonBlock
// kindNoPoll means that we should not put the descriptor into
// non-blocking mode, because we know it is not a pipe or FIFO.
- // Used by openFdAt for directories.
+ // Used by openFdAt and openDirNolog for directories.
kindNoPoll
)
@@ -256,7 +256,7 @@ func epipecheck(file *File, e error) {
const DevNull = "/dev/null"
// openFileNolog is the Unix implementation of OpenFile.
-// Changes here should be reflected in openFdAt, if relevant.
+// Changes here should be reflected in openFdAt and openDirNolog, if relevant.
func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
setSticky := false
if !supportsCreateWithStickyBit && flag&O_CREATE != 0 && perm&ModeSticky != 0 {
@@ -303,6 +303,32 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
return f, nil
}
+func openDirNolog(name string) (*File, error) {
+ var r int
+ var s poll.SysFile
+ for {
+ var e error
+ r, s, e = open(name, O_RDONLY|syscall.O_CLOEXEC, 0)
+ if e == nil {
+ break
+ }
+
+ if e == syscall.EINTR {
+ continue
+ }
+
+ return nil, &PathError{Op: "open", Path: name, Err: e}
+ }
+
+ if !supportsCloseOnExec {
+ syscall.CloseOnExec(r)
+ }
+
+ f := newFile(r, name, kindNoPoll)
+ f.pfd.SysFile = s
+ return f, nil
+}
+
func (file *file) close() error {
if file == nil {
return syscall.EINVAL
diff --git a/src/os/file_windows.go b/src/os/file_windows.go
index fcdb5f2e8f..a304a5e4a7 100644
--- a/src/os/file_windows.go
+++ b/src/os/file_windows.go
@@ -119,6 +119,10 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
return newFile(r, name, "file"), nil
}
+func openDirNolog(name string) (*File, error) {
+ return openFileNolog(name, O_RDONLY, 0)
+}
+
func (file *file) close() error {
if file == nil {
return syscall.EINVAL