diff options
author | Cherry Zhang <cherryyz@google.com> | 2020-10-28 09:12:20 -0400 |
---|---|---|
committer | Cherry Zhang <cherryyz@google.com> | 2020-10-28 09:12:20 -0400 |
commit | a16e30d162c1c7408db7821e7b9513cefa09c6ca (patch) | |
tree | af752ba9ba44c547df39bb0af9bff79f610ba9d5 /src/os/dir_darwin.go | |
parent | 91e4d2d57bc341dd82c98247117114c851380aef (diff) | |
parent | cf6cfba4d5358404dd890f6025e573a4b2156543 (diff) | |
download | go-git-dev.link.tar.gz |
[dev.link] all: merge branch 'master' into dev.linkdev.link
Clean merge.
Change-Id: Ia7b2808bc649790198d34c226a61d9e569084dc5
Diffstat (limited to 'src/os/dir_darwin.go')
-rw-r--r-- | src/os/dir_darwin.go | 62 |
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. |