rclone/vfs/dir_handle.go

108 lines
2.9 KiB
Go

package vfs
import (
"io"
"os"
)
// DirHandle represents an open directory
type DirHandle struct {
baseHandle
d *Dir
fis []os.FileInfo // where Readdir got to
}
// newDirHandle opens a directory for read
func newDirHandle(d *Dir) *DirHandle {
return &DirHandle{
d: d,
}
}
// String converts it to printable
func (fh *DirHandle) String() string {
if fh == nil {
return "<nil *DirHandle>"
}
if fh.d == nil {
return "<nil *DirHandle.d>"
}
return fh.d.String() + " (r)"
}
// Stat returns info about the current directory
func (fh *DirHandle) Stat() (fi os.FileInfo, err error) {
return fh.d, nil
}
// Node returns the Node assocuated with this - satisfies Noder interface
func (fh *DirHandle) Node() Node {
return fh.d
}
// Readdir reads the contents of the directory associated with file and returns
// a slice of up to n FileInfo values, as would be returned by Lstat, in
// directory order. Subsequent calls on the same file will yield further
// FileInfos.
//
// If n > 0, Readdir returns at most n FileInfo structures. In this case, if
// Readdir returns an empty slice, it will return a non-nil error explaining
// why. At the end of a directory, the error is io.EOF.
//
// If n <= 0, Readdir returns all the FileInfo from the directory in a single
// slice. In this case, if Readdir succeeds (reads all the way to the end of
// the directory), it returns the slice and a nil error. If it encounters an
// error before the end of the directory, Readdir returns the FileInfo read
// until that point and a non-nil error.
func (fh *DirHandle) Readdir(n int) (fis []os.FileInfo, err error) {
if fh.fis == nil {
nodes, err := fh.d.ReadDirAll()
if err != nil {
return nil, err
}
fh.fis = []os.FileInfo{}
for _, node := range nodes {
fh.fis = append(fh.fis, node)
}
}
nn := len(fh.fis)
if n > 0 {
if nn == 0 {
return nil, io.EOF
}
if nn > n {
nn = n
}
}
fis, fh.fis = fh.fis[:nn], fh.fis[nn:]
return fis, nil
}
// Readdirnames reads and returns a slice of names from the directory f.
//
// If n > 0, Readdirnames returns at most n names. In this case, if
// Readdirnames returns an empty slice, it will return a non-nil error
// explaining why. At the end of a directory, the error is io.EOF.
//
// If n <= 0, Readdirnames returns all the names from the directory in a single
// slice. In this case, if Readdirnames succeeds (reads all the way to the end
// of the directory), it returns the slice and a nil error. If it encounters an
// error before the end of the directory, Readdirnames returns the names read
// until that point and a non-nil error.
func (fh *DirHandle) Readdirnames(n int) (names []string, err error) {
nodes, err := fh.Readdir(n)
if err != nil {
return nil, err
}
for _, node := range nodes {
names = append(names, node.Name())
}
return names, nil
}
// Close closes the handle
func (fh *DirHandle) Close() (err error) {
fh.fis = nil
return nil
}