]> Cypherpunks.ru repositories - gostls13.git/blob - src/os/dir_plan9.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / src / os / dir_plan9.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
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         // If this file has no dirinfo, create one.
15         if file.dirinfo == nil {
16                 file.dirinfo = new(dirInfo)
17         }
18         d := file.dirinfo
19         size := n
20         if size <= 0 {
21                 size = 100
22                 n = -1
23         }
24         for n != 0 {
25                 // Refill the buffer if necessary.
26                 if d.bufp >= d.nbuf {
27                         nb, err := file.Read(d.buf[:])
28
29                         // Update the buffer state before checking for errors.
30                         d.bufp, d.nbuf = 0, nb
31
32                         if err != nil {
33                                 if err == io.EOF {
34                                         break
35                                 }
36                                 return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: err}
37                         }
38                         if nb < syscall.STATFIXLEN {
39                                 return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: syscall.ErrShortStat}
40                         }
41                 }
42
43                 // Get a record from the buffer.
44                 b := d.buf[d.bufp:]
45                 m := int(uint16(b[0])|uint16(b[1])<<8) + 2
46                 if m < syscall.STATFIXLEN {
47                         return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: syscall.ErrShortStat}
48                 }
49
50                 dir, err := syscall.UnmarshalDir(b[:m])
51                 if err != nil {
52                         return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: err}
53                 }
54
55                 if mode == readdirName {
56                         names = append(names, dir.Name)
57                 } else {
58                         f := fileInfoFromStat(dir)
59                         if mode == readdirDirEntry {
60                                 dirents = append(dirents, dirEntry{f})
61                         } else {
62                                 infos = append(infos, f)
63                         }
64                 }
65                 d.bufp += m
66                 n--
67         }
68
69         if n > 0 && len(names)+len(dirents)+len(infos) == 0 {
70                 return nil, nil, nil, io.EOF
71         }
72         return names, dirents, infos, nil
73 }
74
75 type dirEntry struct {
76         fs *fileStat
77 }
78
79 func (de dirEntry) Name() string            { return de.fs.Name() }
80 func (de dirEntry) IsDir() bool             { return de.fs.IsDir() }
81 func (de dirEntry) Type() FileMode          { return de.fs.Mode().Type() }
82 func (de dirEntry) Info() (FileInfo, error) { return de.fs, nil }
83
84 func (de dirEntry) String() string {
85         return fs.FormatDirEntry(de)
86 }