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
7package os
8
9import (
10	"io"
11	"syscall"
12)
13
14const (
15	blockSize = 4096
16)
17
18func (f *File) readdirnames(n int) (names []string, err error) {
19	// If this file has no dirinfo, create one.
20	if f.dirinfo == nil {
21		f.dirinfo = new(dirInfo)
22		// The buffer must be at least a block long.
23		f.dirinfo.buf = make([]byte, blockSize)
24	}
25	d := f.dirinfo
26
27	size := n
28	if size <= 0 {
29		size = 100
30		n = -1
31	}
32
33	names = make([]string, 0, size) // Empty with room to grow.
34	for n != 0 {
35		// Refill the buffer if necessary
36		if d.bufp >= d.nbuf {
37			d.bufp = 0
38			var errno error
39			d.nbuf, errno = fixCount(syscall.ReadDirent(f.fd, d.buf))
40			if errno != nil {
41				return names, NewSyscallError("readdirent", errno)
42			}
43			if d.nbuf <= 0 {
44				break // EOF
45			}
46		}
47
48		// Drain the buffer
49		var nb, nc int
50		nb, nc, names = syscall.ParseDirent(d.buf[d.bufp:d.nbuf], n, names)
51		d.bufp += nb
52		n -= nc
53	}
54	if n >= 0 && len(names) == 0 {
55		return names, io.EOF
56	}
57	return names, nil
58}
59