Source file
src/os/dir_plan9.go
1
2
3
4
5 package os
6
7 import (
8 "io"
9 "io/fs"
10 "syscall"
11 )
12
13 func (file *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) {
14
15 d := file.dirinfo.Load()
16 if d == nil {
17 d = new(dirInfo)
18 file.dirinfo.Store(d)
19 }
20 d.mu.Lock()
21 defer d.mu.Unlock()
22
23 size := n
24 if size <= 0 {
25 size = 100
26 n = -1
27 }
28 for n != 0 {
29
30 if d.bufp >= d.nbuf {
31 nb, err := file.Read(d.buf[:])
32
33
34 d.bufp, d.nbuf = 0, nb
35
36 if err != nil {
37 if err == io.EOF {
38 break
39 }
40 return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: err}
41 }
42 if nb < syscall.STATFIXLEN {
43 return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: syscall.ErrShortStat}
44 }
45 }
46
47
48 b := d.buf[d.bufp:]
49 m := int(uint16(b[0])|uint16(b[1])<<8) + 2
50 if m < syscall.STATFIXLEN {
51 return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: syscall.ErrShortStat}
52 }
53
54 dir, err := syscall.UnmarshalDir(b[:m])
55 if err != nil {
56 return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: err}
57 }
58
59 if mode == readdirName {
60 names = append(names, dir.Name)
61 } else {
62 f := fileInfoFromStat(dir)
63 if mode == readdirDirEntry {
64 dirents = append(dirents, dirEntry{f})
65 } else {
66 infos = append(infos, f)
67 }
68 }
69 d.bufp += m
70 n--
71 }
72
73 if n > 0 && len(names)+len(dirents)+len(infos) == 0 {
74 return nil, nil, nil, io.EOF
75 }
76 return names, dirents, infos, nil
77 }
78
79 type dirEntry struct {
80 fs *fileStat
81 }
82
83 func (de dirEntry) Name() string { return de.fs.Name() }
84 func (de dirEntry) IsDir() bool { return de.fs.IsDir() }
85 func (de dirEntry) Type() FileMode { return de.fs.Mode().Type() }
86 func (de dirEntry) Info() (FileInfo, error) { return de.fs, nil }
87
88 func (de dirEntry) String() string {
89 return fs.FormatDirEntry(de)
90 }
91
View as plain text