diff --git a/memfs/memory.go b/memfs/memory.go index 3f10d13..c9f40bb 100644 --- a/memfs/memory.go +++ b/memfs/memory.go @@ -170,8 +170,10 @@ type file struct { func (f *file) Read(b []byte) (int, error) { n, err := f.ReadAt(b, f.position) - if err != nil { - return 0, err + f.position += int64(n) + + if err == io.EOF && n != 0 { + err = nil } return n, err @@ -187,7 +189,6 @@ func (f *file) ReadAt(b []byte, off int64) (int, error) { } n, err := f.content.ReadAt(b, off) - f.position += int64(n) return n, err } diff --git a/memfs/storage.go b/memfs/storage.go index 03e39c3..0856f82 100644 --- a/memfs/storage.go +++ b/memfs/storage.go @@ -185,7 +185,7 @@ func (c *content) WriteAt(p []byte, off int64) (int, error) { return len(p), nil } -func (c *content) ReadAt(b []byte, off int64) (int, error) { +func (c *content) ReadAt(b []byte, off int64) (n int, err error) { size := int64(len(c.bytes)) if off >= size { return 0, io.EOF @@ -196,6 +196,11 @@ func (c *content) ReadAt(b []byte, off int64) (int, error) { l = size - off } - n := copy(b, c.bytes[off:off+l]) - return n, nil + btr := c.bytes[off : off+l] + if len(btr) < len(b) { + err = io.EOF + } + n = copy(b, btr) + + return } diff --git a/test/fs_suite.go b/test/fs_suite.go index ebe1f2b..e819d69 100644 --- a/test/fs_suite.go +++ b/test/fs_suite.go @@ -715,6 +715,54 @@ func (s *FilesystemSuite) TestReadAtOnReadOnly(c *C) { c.Assert(f.Close(), IsNil) } +func (s *FilesystemSuite) TestReadAtEOF(c *C) { + err := WriteFile(s.FS, "foo", []byte("TEST"), 0644) + c.Assert(err, IsNil) + + f, err := s.FS.Open("foo") + c.Assert(err, IsNil) + + rf, ok := f.(io.ReaderAt) + c.Assert(ok, Equals, true) + + b := make([]byte, 5) + n, err := rf.ReadAt(b, 0) + c.Assert(err, Equals, io.EOF) + c.Assert(n, Equals, 4) + c.Assert(string(b), Equals, "TEST\x00") + + err = f.Close() + c.Assert(err, IsNil) +} + +func (s *FilesystemSuite) TestReadAtOffset(c *C) { + err := WriteFile(s.FS, "foo", []byte("TEST"), 0644) + c.Assert(err, IsNil) + + f, err := s.FS.Open("foo") + c.Assert(err, IsNil) + + rf, ok := f.(io.ReaderAt) + c.Assert(ok, Equals, true) + + o, err := f.Seek(0, io.SeekCurrent) + c.Assert(err, IsNil) + c.Assert(o, Equals, int64(0)) + + b := make([]byte, 4) + n, err := rf.ReadAt(b, 0) + c.Assert(err, IsNil) + c.Assert(n, Equals, 4) + c.Assert(string(b), Equals, "TEST") + + o, err = f.Seek(0, io.SeekCurrent) + c.Assert(err, IsNil) + c.Assert(o, Equals, int64(0)) + + err = f.Close() + c.Assert(err, IsNil) +} + func (s *FilesystemSuite) TestReadWriteLargeFile(c *C) { f, err := s.FS.Create("foo") c.Assert(err, IsNil)