github.com/AESNooper/go/src@v0.0.0-20220218095104-b56a4ab1bbbb/os/dir_plan9.go (about) 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 "syscall" 10 ) 11 12 func (file *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) { 13 // If this file has no dirinfo, create one. 14 if file.dirinfo == nil { 15 file.dirinfo = new(dirInfo) 16 } 17 d := file.dirinfo 18 size := n 19 if size <= 0 { 20 size = 100 21 n = -1 22 } 23 for n != 0 { 24 // Refill the buffer if necessary. 25 if d.bufp >= d.nbuf { 26 nb, err := file.Read(d.buf[:]) 27 28 // Update the buffer state before checking for errors. 29 d.bufp, d.nbuf = 0, nb 30 31 if err != nil { 32 if err == io.EOF { 33 break 34 } 35 return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: err} 36 } 37 if nb < syscall.STATFIXLEN { 38 return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: syscall.ErrShortStat} 39 } 40 } 41 42 // Get a record from the buffer. 43 b := d.buf[d.bufp:] 44 m := int(uint16(b[0])|uint16(b[1])<<8) + 2 45 if m < syscall.STATFIXLEN { 46 return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: syscall.ErrShortStat} 47 } 48 49 dir, err := syscall.UnmarshalDir(b[:m]) 50 if err != nil { 51 return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: err} 52 } 53 54 if mode == readdirName { 55 names = append(names, dir.Name) 56 } else { 57 f := fileInfoFromStat(dir) 58 if mode == readdirDirEntry { 59 dirents = append(dirents, dirEntry{f}) 60 } else { 61 infos = append(infos, f) 62 } 63 } 64 d.bufp += m 65 n-- 66 } 67 68 if n > 0 && len(names)+len(dirents)+len(infos) == 0 { 69 return nil, nil, nil, io.EOF 70 } 71 return names, dirents, infos, nil 72 } 73 74 type dirEntry struct { 75 fs *fileStat 76 } 77 78 func (de dirEntry) Name() string { return de.fs.Name() } 79 func (de dirEntry) IsDir() bool { return de.fs.IsDir() } 80 func (de dirEntry) Type() FileMode { return de.fs.Mode().Type() } 81 func (de dirEntry) Info() (FileInfo, error) { return de.fs, nil }