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