github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/src/os/dir_unix.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 // +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris 6 7 package os 8 9 import ( 10 "io" 11 "runtime" 12 "syscall" 13 ) 14 15 const ( 16 // More than 5760 to work around https://golang.org/issue/24015. 17 blockSize = 8192 18 ) 19 20 func (f *File) readdir(n int) (fi []FileInfo, err error) { 21 dirname := f.name 22 if dirname == "" { 23 dirname = "." 24 } 25 names, err := f.Readdirnames(n) 26 fi = make([]FileInfo, 0, len(names)) 27 for _, filename := range names { 28 fip, lerr := lstat(dirname + "/" + filename) 29 if IsNotExist(lerr) { 30 // File disappeared between readdir + stat. 31 // Just treat it as if it didn't exist. 32 continue 33 } 34 if lerr != nil { 35 return fi, lerr 36 } 37 fi = append(fi, fip) 38 } 39 if len(fi) == 0 && err == nil && n > 0 { 40 // Per File.Readdir, the slice must be non-empty or err 41 // must be non-nil if n > 0. 42 err = io.EOF 43 } 44 return fi, err 45 } 46 47 func (f *File) readdirnames(n int) (names []string, err error) { 48 // If this file has no dirinfo, create one. 49 if f.dirinfo == nil { 50 f.dirinfo = new(dirInfo) 51 // The buffer must be at least a block long. 52 f.dirinfo.buf = make([]byte, blockSize) 53 } 54 d := f.dirinfo 55 56 size := n 57 if size <= 0 { 58 size = 100 59 n = -1 60 } 61 62 names = make([]string, 0, size) // Empty with room to grow. 63 for n != 0 { 64 // Refill the buffer if necessary 65 if d.bufp >= d.nbuf { 66 d.bufp = 0 67 var errno error 68 d.nbuf, errno = f.pfd.ReadDirent(d.buf) 69 runtime.KeepAlive(f) 70 if errno != nil { 71 return names, wrapSyscallError("readdirent", errno) 72 } 73 if d.nbuf <= 0 { 74 break // EOF 75 } 76 } 77 78 // Drain the buffer 79 var nb, nc int 80 nb, nc, names = syscall.ParseDirent(d.buf[d.bufp:d.nbuf], n, names) 81 d.bufp += nb 82 n -= nc 83 } 84 if n >= 0 && len(names) == 0 { 85 return names, io.EOF 86 } 87 return names, nil 88 }