From 071cf8b5f5cd58c7871452d32ffa00d364bd8399 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 3 Apr 2025 16:11:11 +0000 Subject: [PATCH 1/3] add testcase --- tarfs/tarfs_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/tarfs/tarfs_test.go b/tarfs/tarfs_test.go index 228ed9b4..c5e1c84c 100644 --- a/tarfs/tarfs_test.go +++ b/tarfs/tarfs_test.go @@ -150,6 +150,51 @@ func TestReadAt(t *testing.T) { } } +func TestMultipleReads(t *testing.T) { + for _, f := range files { + if !f.exists { + continue + } + + readFile := func(file afero.File) { + buf := make([]byte, 8) + n, err := file.Read(buf) + if f.isdir && (err != syscall.EISDIR) { + t.Errorf("%v got error %v, expected EISDIR", f.name, err) + } else if !f.isdir && (err != nil) { + if err != nil { + t.Errorf("%v: %v", f.name, err) + } else if n != 8 { + t.Errorf("%v: got %d read bytes, expected 8", f.name, n) + } else if string(buf) != f.content { + t.Errorf("%v: got <%s>, expected <%s>", f.name, f.content, string(buf)) + } + } + + _, err = io.ReadAll(file) + if f.isdir && (err != syscall.EISDIR) { + t.Errorf("%v got error %v, expected EISDIR", f.name, err) + } else if !f.isdir && (err != nil) { + t.Errorf("reading %v: %v", f.name, err) + } + + err = file.Close() + if err != nil { + t.Errorf("closing %v: %v", f.name, err) + } + } + + fileA, err := afs.Open(f.name) + fileB, err := afs.Open(f.name) + if err != nil { + t.Fatalf("opening %v: %v", f.name, err) + } + + readFile(fileA) + readFile(fileB) + } +} + func TestSeek(t *testing.T) { for _, f := range files { if !f.exists { From f06e86036696c9183a96122f68691b2363c21337 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 3 Apr 2025 15:54:40 +0000 Subject: [PATCH 2/3] construct a new bytes.Reader per each opened file --- tarfs/fs.go | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/tarfs/fs.go b/tarfs/fs.go index 0d764e5f..c8e4e1e3 100644 --- a/tarfs/fs.go +++ b/tarfs/fs.go @@ -14,7 +14,12 @@ import ( ) type Fs struct { - files map[string]map[string]*File + files map[string]map[string]*fsEntry +} + +type fsEntry struct { + h *tar.Header + data []byte } func splitpath(name string) (dir, file string) { @@ -29,7 +34,7 @@ func splitpath(name string) (dir, file string) { } func New(t *tar.Reader) *Fs { - fs := &Fs{files: make(map[string]map[string]*File)} + fs := &Fs{files: make(map[string]map[string]*fsEntry)} for { hdr, err := t.Next() if err == io.EOF { @@ -41,7 +46,7 @@ func New(t *tar.Reader) *Fs { d, f := splitpath(hdr.Name) if _, ok := fs.files[d]; !ok { - fs.files[d] = make(map[string]*File) + fs.files[d] = make(map[string]*fsEntry) } var buf bytes.Buffer @@ -54,27 +59,25 @@ func New(t *tar.Reader) *Fs { panic("tarfs: size mismatch") } - file := &File{ + file := &fsEntry{ h: hdr, - data: bytes.NewReader(buf.Bytes()), - fs: fs, + data: buf.Bytes(), } fs.files[d][f] = file } if fs.files[afero.FilePathSeparator] == nil { - fs.files[afero.FilePathSeparator] = make(map[string]*File) + fs.files[afero.FilePathSeparator] = make(map[string]*fsEntry) } // Add a pseudoroot - fs.files[afero.FilePathSeparator][""] = &File{ + fs.files[afero.FilePathSeparator][""] = &fsEntry{ h: &tar.Header{ Name: afero.FilePathSeparator, Typeflag: tar.TypeDir, Size: 0, }, - data: bytes.NewReader(nil), - fs: fs, + data: nil, } return fs @@ -91,7 +94,11 @@ func (fs *Fs) Open(name string) (afero.File, error) { return nil, &os.PathError{Op: "open", Path: name, Err: syscall.ENOENT} } - nf := *file + nf := File{ + h: file.h, + data: bytes.NewReader(file.data), + fs: fs, + } return &nf, nil } From 4bec43805227814e12dc5361830de273a794d369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=B1=E3=82=A4=E3=83=A9?= Date: Thu, 24 Apr 2025 09:33:40 -0700 Subject: [PATCH 3/3] add missing error check --- tarfs/tarfs_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tarfs/tarfs_test.go b/tarfs/tarfs_test.go index c5e1c84c..1258f02d 100644 --- a/tarfs/tarfs_test.go +++ b/tarfs/tarfs_test.go @@ -185,6 +185,9 @@ func TestMultipleReads(t *testing.T) { } fileA, err := afs.Open(f.name) + if err != nil { + t.Fatalf("opening %v: %v", f.name, err) + } fileB, err := afs.Open(f.name) if err != nil { t.Fatalf("opening %v: %v", f.name, err)