mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
os: add File.ReadDir method and DirEntry type
ReadDir provides a portable, efficient way to read a directory and discover the type of directory entries. This enables a more efficient file system walk, yet to be added. See #41467 for the proposal review for the API. Fixes #41467. Change-Id: I461a526793ae46df48821aa448b04f1705546739 Reviewed-on: https://go-review.googlesource.com/c/go/+/261540 Trust: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
parent
8fe372c7b3
commit
a4ede9f9a6
20 changed files with 784 additions and 110 deletions
|
|
@ -9,7 +9,6 @@ package os
|
|||
import (
|
||||
"internal/poll"
|
||||
"internal/syscall/unix"
|
||||
"io"
|
||||
"runtime"
|
||||
"syscall"
|
||||
)
|
||||
|
|
@ -353,33 +352,6 @@ func Symlink(oldname, newname string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (f *File) readdir(n int) (fi []FileInfo, err error) {
|
||||
dirname := f.name
|
||||
if dirname == "" {
|
||||
dirname = "."
|
||||
}
|
||||
names, err := f.Readdirnames(n)
|
||||
fi = make([]FileInfo, 0, len(names))
|
||||
for _, filename := range names {
|
||||
fip, lerr := lstat(dirname + "/" + filename)
|
||||
if IsNotExist(lerr) {
|
||||
// File disappeared between readdir + stat.
|
||||
// Just treat it as if it didn't exist.
|
||||
continue
|
||||
}
|
||||
if lerr != nil {
|
||||
return fi, lerr
|
||||
}
|
||||
fi = append(fi, fip)
|
||||
}
|
||||
if len(fi) == 0 && err == nil && n > 0 {
|
||||
// Per File.Readdir, the slice must be non-empty or err
|
||||
// must be non-nil if n > 0.
|
||||
err = io.EOF
|
||||
}
|
||||
return fi, err
|
||||
}
|
||||
|
||||
// Readlink returns the destination of the named symbolic link.
|
||||
// If there is an error, it will be of type *PathError.
|
||||
func Readlink(name string) (string, error) {
|
||||
|
|
@ -407,3 +379,41 @@ func Readlink(name string) (string, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
type unixDirent struct {
|
||||
parent string
|
||||
name string
|
||||
typ FileMode
|
||||
info FileInfo
|
||||
}
|
||||
|
||||
func (d *unixDirent) Name() string { return d.name }
|
||||
func (d *unixDirent) IsDir() bool { return d.typ.IsDir() }
|
||||
func (d *unixDirent) Type() FileMode { return d.typ }
|
||||
|
||||
func (d *unixDirent) Info() (FileInfo, error) {
|
||||
if d.info != nil {
|
||||
return d.info, nil
|
||||
}
|
||||
return lstat(d.parent + "/" + d.name)
|
||||
}
|
||||
|
||||
func newUnixDirent(parent, name string, typ FileMode) (DirEntry, error) {
|
||||
ude := &unixDirent{
|
||||
parent: parent,
|
||||
name: name,
|
||||
typ: typ,
|
||||
}
|
||||
if typ != ^FileMode(0) && !testingForceReadDirLstat {
|
||||
return ude, nil
|
||||
}
|
||||
|
||||
info, err := lstat(parent + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ude.typ = info.Mode().Type()
|
||||
ude.info = info
|
||||
return ude, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue