Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iofs compatibillity ReadDir on EOF #292

Open
aligator opened this issue Mar 23, 2021 · 0 comments
Open

iofs compatibillity ReadDir on EOF #292

aligator opened this issue Mar 23, 2021 · 0 comments

Comments

@aligator
Copy link

aligator commented Mar 23, 2021

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)

afero/iofs.go

Line 129 in bc94f58

func (r readDirFile) ReadDir(n int) ([]fs.DirEntry, error) {

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...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant