...
Source file
src/os/dir_darwin.go
Documentation: os
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
58
59
60
61
62
63
64
65
66 if dirent.Ino == 0 {
67 continue
68 }
69 name := (*[len(syscall.Dirent{}.Name)]byte)(unsafe.Pointer(&dirent.Name))[:]
70 for i, c := range name {
71 if c == 0 {
72 name = name[:i]
73 break
74 }
75 }
76
77 if string(name) == "." || string(name) == ".." {
78 continue
79 }
80 if mode == readdirName {
81 names = append(names, string(name))
82 } else if mode == readdirDirEntry {
83 de, err := newUnixDirent(f.name, string(name), dtToType(dirent.Type))
84 if IsNotExist(err) {
85
86
87 continue
88 }
89 if err != nil {
90 return nil, dirents, nil, err
91 }
92 dirents = append(dirents, de)
93 } else {
94 info, err := lstat(f.name + "/" + string(name))
95 if IsNotExist(err) {
96
97
98 continue
99 }
100 if err != nil {
101 return nil, nil, infos, err
102 }
103 infos = append(infos, info)
104 }
105 runtime.KeepAlive(f)
106 }
107
108 if n > 0 && len(names)+len(dirents)+len(infos) == 0 {
109 return nil, nil, nil, io.EOF
110 }
111 return names, dirents, infos, nil
112 }
113
114 func dtToType(typ uint8) FileMode {
115 switch typ {
116 case syscall.DT_BLK:
117 return ModeDevice
118 case syscall.DT_CHR:
119 return ModeDevice | ModeCharDevice
120 case syscall.DT_DIR:
121 return ModeDir
122 case syscall.DT_FIFO:
123 return ModeNamedPipe
124 case syscall.DT_LNK:
125 return ModeSymlink
126 case syscall.DT_REG:
127 return 0
128 case syscall.DT_SOCK:
129 return ModeSocket
130 }
131 return ^FileMode(0)
132 }
133
134
135
136
137 func closedir(dir uintptr) (err error)
138
139
140 func readdir_r(dir uintptr, entry *syscall.Dirent, result **syscall.Dirent) (res syscall.Errno)
141
View as plain text