Source file
src/os/dir_darwin.go
1
2
3
4
5 package os
6
7 import (
8 "io"
9 "runtime"
10 "syscall"
11 "unsafe"
12 )
13
14
15 type dirInfo struct {
16 dir uintptr
17 }
18
19 func (d *dirInfo) close() {
20 if d.dir == 0 {
21 return
22 }
23 closedir(d.dir)
24 d.dir = 0
25 }
26
27 func (f *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) {
28 if f.dirinfo == nil {
29 dir, call, errno := f.pfd.OpenDir()
30 if errno != nil {
31 return nil, nil, nil, &PathError{Op: call, Path: f.name, Err: errno}
32 }
33 f.dirinfo = &dirInfo{
34 dir: dir,
35 }
36 }
37 d := f.dirinfo
38
39 size := n
40 if size <= 0 {
41 size = 100
42 n = -1
43 }
44
45 var dirent syscall.Dirent
46 var entptr *syscall.Dirent
47 for len(names)+len(dirents)+len(infos) < size || n == -1 {
48 if errno := readdir_r(d.dir, &dirent, &entptr); errno != 0 {
49 if errno == syscall.EINTR {
50 continue
51 }
52 return names, dirents, infos, &PathError{Op: "readdir", Path: f.name, Err: errno}
53 }
54 if entptr == nil {
55 break
56 }
57 if dirent.Ino == 0 {
58 continue
59 }
60 name := (*[len(syscall.Dirent{}.Name)]byte)(unsafe.Pointer(&dirent.Name))[:]
61 for i, c := range name {
62 if c == 0 {
63 name = name[:i]
64 break
65 }
66 }
67
68 if string(name) == "." || string(name) == ".." {
69 continue
70 }
71 if mode == readdirName {
72 names = append(names, string(name))
73 } else if mode == readdirDirEntry {
74 de, err := newUnixDirent(f.name, string(name), dtToType(dirent.Type))
75 if IsNotExist(err) {
76
77
78 continue
79 }
80 if err != nil {
81 return nil, dirents, nil, err
82 }
83 dirents = append(dirents, de)
84 } else {
85 info, err := lstat(f.name + "/" + string(name))
86 if IsNotExist(err) {
87
88
89 continue
90 }
91 if err != nil {
92 return nil, nil, infos, err
93 }
94 infos = append(infos, info)
95 }
96 runtime.KeepAlive(f)
97 }
98
99 if n > 0 && len(names)+len(dirents)+len(infos) == 0 {
100 return nil, nil, nil, io.EOF
101 }
102 return names, dirents, infos, nil
103 }
104
105 func dtToType(typ uint8) FileMode {
106 switch typ {
107 case syscall.DT_BLK:
108 return ModeDevice
109 case syscall.DT_CHR:
110 return ModeDevice | ModeCharDevice
111 case syscall.DT_DIR:
112 return ModeDir
113 case syscall.DT_FIFO:
114 return ModeNamedPipe
115 case syscall.DT_LNK:
116 return ModeSymlink
117 case syscall.DT_REG:
118 return 0
119 case syscall.DT_SOCK:
120 return ModeSocket
121 }
122 return ^FileMode(0)
123 }
124
125
126
127
128 func closedir(dir uintptr) (err error)
129
130
131 func readdir_r(dir uintptr, entry *syscall.Dirent, result **syscall.Dirent) (res syscall.Errno)
132
View as plain text