// 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
}
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
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.
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
)
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 {
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
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