iofs compatibillity ReadDir on EOF
Hi,
I implemented a FAT filesystem myself and added a similar wrapper like afero has now to support the io.FS interface.
But now I tried to instead use the wrapper from afero and noticed something I am not sure about how it is intended to be:
The code for this is here, just run go generate && go test ./...
First of all, I am new to filesystems and maybe I am doing something wrong :-)
My implementation returns on ReadDir(n) EOF if the directoryContentCount < offset + n but also the directories already read.
Quote from the interface description of go https://golang.org/src/io/fs/fs.go
// ReadDir reads the contents of the directory and returns
// a slice of up to n DirEntry values in directory order.
// Subsequent calls on the same file will yield further DirEntry values.
//
// If n > 0, ReadDir returns at most n DirEntry 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 DirEntry values 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 DirEntry list read until that point and a non-nil error.
ReadDir(n int) ([]DirEntry, error)
As I understand it from that EOF should be returned if I try to read over the end of the directory list. But if any error occurs it should still return all valid data read until the error occured.
Now when using your wrapper my FS doesn't pass the fstest.TestFS anymore because when comparing the full-directory-list with a list read in chunks, the resulting lists are different because affero cuts away the data if any error (or EOF) occurs and just returns nil.
This would result in changing this: (Note that it may be in different places also)
https://github.com/spf13/afero/blob/bc94f58beda5dbff6f74599fcb1f1717c5b1c111/iofs.go#L129
func (r readDirFile) ReadDir(n int) ([]fs.DirEntry, error) {
items, err := r.File.Readdir(n)
if err != nil {
return nil, err
}
ret := make([]fs.DirEntry, len(items))
for i := range items {
ret[i] = dirEntry{items[i]}
}
return ret, nil
}
to
func (r readDirFile) ReadDir(n int) ([]fs.DirEntry, error) {
items, err := r.File.Readdir(n)
if err != nil && items == nil {
return nil, err
}
ret := make([]fs.DirEntry, len(items))
for i := range items {
ret[i] = dirEntry{items[i]}
}
return ret, err
}
Tested this with my fs implementation and it worked (I got a next error though, but I will create another issue for that :-)
Now the question is if I am right with my assumption or if I implemented it in a wrong way...