From e8a8c531a90f5d2e61bc7161e82287308f516646 Mon Sep 17 00:00:00 2001 From: Caleb Gardner Date: Mon, 27 Sep 2021 01:27:58 -0500 Subject: [PATCH] Tweaks to make FromReader work --- internal/rawreader/rawreader.go | 76 +++++++++++++++++---------------- reader.go | 19 ++++++--- reader_test.go | 15 +------ 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/internal/rawreader/rawreader.go b/internal/rawreader/rawreader.go index 4acdaa9..b5cbb49 100644 --- a/internal/rawreader/rawreader.go +++ b/internal/rawreader/rawreader.go @@ -1,23 +1,28 @@ package rawreader import ( + "bytes" "errors" "io" ) -func ConvertReader(r io.Reader) RawReader { +func ConvertReader(r io.Reader) (RawReader, error) { if rr, ok := r.(RawReader); ok { - return rr + return rr, nil } if rs, is := r.(io.ReadSeeker); is { return &fromReadSeeker{ ReadSeeker: rs, - } + }, nil + } + buf := new(bytes.Buffer) + _, err := io.Copy(buf, r) + if err != nil { + return nil, err } return &fromReader{ - rdr: r, - cache: make([]byte, 0), - } + data: buf.Bytes(), + }, nil } func ConvertReaderAt(r io.ReaderAt) RawReader { @@ -37,27 +42,21 @@ type RawReader interface { } type fromReader struct { - rdr io.Reader - cache []byte - off int -} - -func (r *fromReader) increaseCache(len int) error { - newCache := make([]byte, len) - _, err := r.rdr.Read(newCache) - if err != nil { - return err - } - r.cache = append(r.cache, newCache...) - return nil + data []byte + off int } func (r *fromReader) ReadAt(p []byte, off int64) (n int, err error) { - if int(off)+len(p) > len(r.cache) { - r.increaseCache((int(off) + len(p)) - len(r.cache)) + n = len(p) + if int(off)+len(p) > len(r.data) { + n = len(r.data) - int(off) + err = io.EOF } - for i := int64(0); i < int64(len(p)); i++ { - p[i] = r.cache[off+i] + if n < 0 { + n = 0 + } + for i := 0; i < n; i++ { + p[i] = r.data[int(off)+i] } return } @@ -65,32 +64,35 @@ func (r *fromReader) ReadAt(p []byte, off int64) (n int, err error) { func (r *fromReader) Seek(off int64, whence int) (n int64, err error) { switch whence { case io.SeekEnd: - return 0, errors.New("cannot SeekEnd RawReader") + r.off = len(r.data) - int(off) + if r.off < 0 { + r.off = 0 + err = io.EOF + } case io.SeekCurrent: r.off += int(off) case io.SeekStart: r.off = int(off) } - if r.off > len(r.cache) { - err = r.increaseCache(len(r.cache) - r.off) - if err != nil { - r.off = len(r.cache) - } + if r.off > len(r.data) { + r.off = len(r.data) + return int64(r.off), io.EOF } return int64(r.off), err } func (r *fromReader) Read(p []byte) (n int, err error) { - if len(p)+r.off > len(r.cache) { - err = r.increaseCache((len(p) + r.off) - len(r.cache)) - if err != nil { - return - } + n = len(p) + if r.off+len(p) > len(r.data) { + n = len(r.data) - r.off + err = io.EOF } - for i := 0; i < len(p); i++ { - p[i] = r.cache[r.off+i] + if n < 0 { + n = 0 + } + for i := 0; i < n; i++ { + p[i] = r.data[r.off+i] } - r.off += len(p) return } diff --git a/reader.go b/reader.go index a647f73..9c9b070 100644 --- a/reader.go +++ b/reader.go @@ -46,12 +46,18 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) { } //NewSquashfsReaderFromReader returns a new squashfs.Reader from an io.Reader. -//If possible, try to use a io.ReaderAt. -//With an io.Reader, much of the data has to be cached to memory. +//If the io.Reader implements io.Seeker, the seek functions are used. +//It is NOT recommended to use a pure io.Reader as due to how squashfs +//archives are formatted, the ENTIRETY of the io.Reader's data is loaded into +//memory first before it can be used. func NewSquashfsReaderFromReader(r io.Reader) (*Reader, error) { var rdr Reader - rdr.r = rawreader.ConvertReader(r) - err := rdr.Init() + var err error + rdr.r, err = rawreader.ConvertReader(r) + if err != nil { + return nil, err + } + err = rdr.Init() if err != nil { return nil, err } @@ -145,7 +151,10 @@ func (r *Reader) Init() error { } unread := r.super.IDCount blockOffsets := make([]uint64, int(math.Ceil(float64(r.super.IDCount)/2048))) - r.r.Seek(int64(r.super.IDTableStart), io.SeekStart) + _, err = r.r.Seek(int64(r.super.IDTableStart), io.SeekStart) + if err != nil { + return err + } for i := range blockOffsets { err = binary.Read(r.r, binary.LittleEndian, &blockOffsets[i]) if err != nil { diff --git a/reader_test.go b/reader_test.go index 8af98fb..3ac0384 100644 --- a/reader_test.go +++ b/reader_test.go @@ -40,25 +40,13 @@ func TestSquashfs(t *testing.T) { if err != nil { t.Fatal(err) } + os.RemoveAll(wd + "/testing/" + squashfsName + ".d") op := DefaultOptions() op.Verbose = true err = rdr.ExtractWithOptions(wd+"/testing/"+squashfsName+".d", op) if err != nil { t.Fatal(err) } - fmt.Println("stuff", rdr.super.CompressionType) - // fil := rdr.GetFileAtPath("*.desktop") - // if fil == nil { - // t.Fatal("Can't find desktop fil") - // } - // errs := fil.ExtractTo(wd + "/testing") - // if len(errs) > 0 { - // t.Fatal(errs) - // } - // errs = rdr.ExtractTo(wd + "/testing/" + squashfsName + ".d") - // if len(errs) > 0 { - // t.Fatal(errs) - // } t.Fatal("No Problems") } @@ -72,6 +60,7 @@ func TestSquashfsFromReader(t *testing.T) { if err != nil { t.Fatal(err) } + os.RemoveAll("testing/" + squashfsName + ".d") op := DefaultOptions() op.Verbose = true err = rdr.ExtractWithOptions("testing/"+squashfsName+".d", op)