OLD | NEW |
(Empty) | |
| 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 "syscall"; |
| 9 "unsafe"; |
| 10 ) |
| 11 |
| 12 const ( |
| 13 blockSize = 4096; // TODO(r): use statfs |
| 14 ) |
| 15 |
| 16 // Readdirnames reads the contents of the directory associated with file and |
| 17 // returns an array of up to count names, in directory order. Subsequent |
| 18 // calls on the same file will yield further names. |
| 19 // A negative count means to read until EOF. |
| 20 // Readdirnames returns the array and an Error, if any. |
| 21 func (file *File) Readdirnames(count int) (names []string, err Error) { |
| 22 // If this file has no dirinfo, create one. |
| 23 if file.dirinfo == nil { |
| 24 file.dirinfo = new(dirInfo); |
| 25 // The buffer must be at least a block long. |
| 26 // TODO(r): use fstatfs to find fs block size. |
| 27 file.dirinfo.buf = make([]byte, blockSize); |
| 28 } |
| 29 d := file.dirinfo; |
| 30 size := count; |
| 31 if size < 0 { |
| 32 size = 100 |
| 33 } |
| 34 names = make([]string, 0, size); // Empty with room to grow. |
| 35 for count != 0 { |
| 36 // Refill the buffer if necessary |
| 37 if d.bufp >= d.nbuf { |
| 38 var errno int; |
| 39 d.bufp = 0; |
| 40 // Final argument is (basep *uintptr) and the syscall do
esn't take nil. |
| 41 d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, ne
w(uintptr)); |
| 42 if errno != 0 { |
| 43 d.nbuf = 0; |
| 44 return names, NewSyscallError("getdirentries", e
rrno); |
| 45 } |
| 46 if d.nbuf <= 0 { |
| 47 break // EOF |
| 48 } |
| 49 } |
| 50 // Drain the buffer |
| 51 for count != 0 && d.bufp < d.nbuf { |
| 52 dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp
])); |
| 53 if dirent.Reclen == 0 { |
| 54 d.bufp = d.nbuf; |
| 55 break; |
| 56 } |
| 57 d.bufp += int(dirent.Reclen); |
| 58 if dirent.Fileno == 0 { // File absent in directory. |
| 59 continue |
| 60 } |
| 61 bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&diren
t.Name[0])); |
| 62 var name = string(bytes[0:dirent.Namlen]); |
| 63 if name == "." || name == ".." { // Useless names |
| 64 continue |
| 65 } |
| 66 count--; |
| 67 if len(names) == cap(names) { |
| 68 nnames := make([]string, len(names), 2*len(names
)); |
| 69 for i := 0; i < len(names); i++ { |
| 70 nnames[i] = names[i] |
| 71 } |
| 72 names = nnames; |
| 73 } |
| 74 names = names[0 : len(names)+1]; |
| 75 names[len(names)-1] = name; |
| 76 } |
| 77 } |
| 78 return names, nil; |
| 79 } |
OLD | NEW |