diff --git a/file_reader.go b/file_reader.go index 485b727c..3537d9c4 100644 --- a/file_reader.go +++ b/file_reader.go @@ -192,12 +192,24 @@ func (f *FileReader) ReadAt(b []byte, off int64) (int, error) { return 0, io.ErrClosedPipe } + if off < 0 { + return 0, &os.PathError{"readat", f.name, errors.New("negative offset")} + } + _, err := f.Seek(off, 0) if err != nil { return 0, err } - return io.ReadFull(f, b) + n, err := io.ReadFull(f, b) + + // For some reason, os.File.ReadAt returns io.EOF in this case instead of + // io.ErrUnexpectedEOF. + if err == io.ErrUnexpectedEOF { + err = io.EOF + } + + return n, err } // Readdir reads the contents of the directory associated with file and returns diff --git a/file_reader_test.go b/file_reader_test.go index f5b3addd..d0149a6e 100644 --- a/file_reader_test.go +++ b/file_reader_test.go @@ -130,6 +130,18 @@ func TestFileReadAt(t *testing.T) { assert.EqualValues(t, testStr2, string(buf)) } +func TestFileReadAtEOF(t *testing.T) { + client := getClient(t) + + file, err := client.Open("/_test/foo.txt") + require.NoError(t, err) + + buf := make([]byte, 10) + _, err = file.ReadAt(buf, 1) + + assert.Equal(t, err, io.EOF) +} + func TestFileSeek(t *testing.T) { client := getClient(t)