aboutsummaryrefslogtreecommitdiff
path: root/src/os/dir_darwin.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/os/dir_darwin.go')
-rw-r--r--src/os/dir_darwin.go62
1 files changed, 53 insertions, 9 deletions
diff --git a/src/os/dir_darwin.go b/src/os/dir_darwin.go
index 476af6862e..deba3eb37f 100644
--- a/src/os/dir_darwin.go
+++ b/src/os/dir_darwin.go
@@ -24,11 +24,11 @@ func (d *dirInfo) close() {
d.dir = 0
}
-func (f *File) readdirnames(n int) (names []string, err error) {
+func (f *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) {
if f.dirinfo == nil {
dir, call, errno := f.pfd.OpenDir()
if errno != nil {
- return nil, &PathError{call, f.name, errno}
+ return nil, nil, nil, &PathError{Op: call, Path: f.name, Err: errno}
}
f.dirinfo = &dirInfo{
dir: dir,
@@ -42,15 +42,14 @@ func (f *File) readdirnames(n int) (names []string, err error) {
n = -1
}
- names = make([]string, 0, size)
var dirent syscall.Dirent
var entptr *syscall.Dirent
- for len(names) < size || n == -1 {
+ for len(names)+len(dirents)+len(infos) < size || n == -1 {
if errno := readdir_r(d.dir, &dirent, &entptr); errno != 0 {
if errno == syscall.EINTR {
continue
}
- return names, &PathError{"readdir", f.name, errno}
+ return names, dirents, infos, &PathError{Op: "readdir", Path: f.name, Err: errno}
}
if entptr == nil { // EOF
break
@@ -69,13 +68,58 @@ func (f *File) readdirnames(n int) (names []string, err error) {
if string(name) == "." || string(name) == ".." {
continue
}
- names = append(names, string(name))
+ if mode == readdirName {
+ names = append(names, string(name))
+ } else if mode == readdirDirEntry {
+ de, err := newUnixDirent(f.name, string(name), dtToType(dirent.Type))
+ if IsNotExist(err) {
+ // File disappeared between readdir and stat.
+ // Treat as if it didn't exist.
+ continue
+ }
+ if err != nil {
+ return nil, dirents, nil, err
+ }
+ dirents = append(dirents, de)
+ } else {
+ info, err := lstat(f.name + "/" + string(name))
+ if IsNotExist(err) {
+ // File disappeared between readdir + stat.
+ // Treat as if it didn't exist.
+ continue
+ }
+ if err != nil {
+ return nil, nil, infos, err
+ }
+ infos = append(infos, info)
+ }
runtime.KeepAlive(f)
}
- if n >= 0 && len(names) == 0 {
- return names, io.EOF
+
+ if n > 0 && len(names)+len(dirents)+len(infos) == 0 {
+ return nil, nil, nil, io.EOF
+ }
+ return names, dirents, infos, nil
+}
+
+func dtToType(typ uint8) FileMode {
+ switch typ {
+ case syscall.DT_BLK:
+ return ModeDevice
+ case syscall.DT_CHR:
+ return ModeDevice | ModeCharDevice
+ case syscall.DT_DIR:
+ return ModeDir
+ case syscall.DT_FIFO:
+ return ModeNamedPipe
+ case syscall.DT_LNK:
+ return ModeSymlink
+ case syscall.DT_REG:
+ return 0
+ case syscall.DT_SOCK:
+ return ModeSocket
}
- return names, nil
+ return ^FileMode(0)
}
// Implemented in syscall/syscall_darwin.go.