diff --git a/internal/metadata/reader.go b/internal/metadata/reader.go index 5a810d1..e91c0a6 100644 --- a/internal/metadata/reader.go +++ b/internal/metadata/reader.go @@ -23,14 +23,15 @@ func NewReader(r io.Reader, d decompress.Decompressor) *Reader { func (r *Reader) advance() error { r.curOffset = 0 - var size uint16 - err := binary.Read(r.r, binary.LittleEndian, &size) + dat := make([]byte, 2) + _, err := r.r.Read(dat) if err != nil { return err } + size := binary.LittleEndian.Uint16(dat) realSize := size &^ 0x8000 r.dat = make([]byte, realSize) - err = binary.Read(r.r, binary.LittleEndian, &r.dat) + _, err = r.r.Read(r.dat) if err != nil { return err } diff --git a/low/data/fullreader.go b/low/data/fullreader.go index f016a57..8ab50d6 100644 --- a/low/data/fullreader.go +++ b/low/data/fullreader.go @@ -1,7 +1,6 @@ package data import ( - "encoding/binary" "errors" "io" "io/fs" @@ -10,7 +9,6 @@ import ( "sync" "github.com/CalebQ42/squashfs/internal/decompress" - "github.com/CalebQ42/squashfs/internal/toreader" ) type FragReaderConstructor func() (io.Reader, error) @@ -80,7 +78,7 @@ func (r FullReader) process(index uint64, fileOffset uint64, pool *sync.Pool, re return } ret.data = make([]byte, realSize) - ret.err = binary.Read(toreader.NewReader(r.r, int64(r.initialOffset)+int64(fileOffset)), binary.LittleEndian, &ret.data) + _, ret.err = r.r.ReadAt(ret.data, r.initialOffset+int64(fileOffset)) if r.sizes[index] == realSize { ret.data, ret.err = r.d.Decompress(ret.data) } diff --git a/low/data/reader.go b/low/data/reader.go index ba593ac..898ab09 100644 --- a/low/data/reader.go +++ b/low/data/reader.go @@ -1,7 +1,6 @@ package data import ( - "encoding/binary" "io" "io/fs" @@ -56,7 +55,7 @@ func (r *Reader) advance() error { return nil } r.dat = make([]byte, realSize) - err = binary.Read(r.r, binary.LittleEndian, &r.dat) + _, err = r.r.Read(r.dat) if err != nil { return err } diff --git a/low/file_base.go b/low/file_base.go index 90c9de3..96aa5ef 100644 --- a/low/file_base.go +++ b/low/file_base.go @@ -130,7 +130,7 @@ func (b FileBase) GetRegFileReaders(r Reader) (data.Reader, data.FullReader, err return outRdr, outFull, nil } -func (b *FileBase) GetFullReader(r *Reader) (data.FullReader, error) { +func (b FileBase) GetFullReader(r *Reader) (data.FullReader, error) { if !b.IsRegular() { return data.FullReader{}, errors.New("not a regular file") } @@ -167,7 +167,7 @@ func (b *FileBase) GetFullReader(r *Reader) (data.FullReader, error) { return outFull, nil } -func (b *FileBase) GetReader(r *Reader) (data.Reader, error) { +func (b FileBase) GetReader(r *Reader) (data.Reader, error) { if !b.IsRegular() { return data.Reader{}, errors.New("not a regular file") } diff --git a/low/inode/dir.go b/low/inode/dir.go index bffe973..ec5ff7e 100644 --- a/low/inode/dir.go +++ b/low/inode/dir.go @@ -13,7 +13,7 @@ type Directory struct { ParentNum uint32 } -type eDirectoryInit struct { +type EDirectory struct { LinkCount uint32 Size uint32 BlockStart uint32 @@ -21,42 +21,55 @@ type eDirectoryInit struct { IndCount uint16 Offset uint16 XattrInd uint32 -} - -type EDirectory struct { - eDirectoryInit - Indexes []DirectoryIndex -} - -type directoryIndexInit struct { - Ind uint32 - Start uint32 - NameSize uint32 + Indexes []DirectoryIndex } type DirectoryIndex struct { - directoryIndexInit - Name []byte + Ind uint32 + Start uint32 + NameSize uint32 + Name []byte } func ReadDir(r io.Reader) (d Directory, err error) { - err = binary.Read(r, binary.LittleEndian, &d) + dat := make([]byte, 16) + _, err = r.Read(dat) + if err != nil { + return + } + d.BlockStart = binary.LittleEndian.Uint32(dat) + d.LinkCount = binary.LittleEndian.Uint32(dat[4:]) + d.Size = binary.LittleEndian.Uint16(dat[8:]) + d.Offset = binary.LittleEndian.Uint16(dat[10:]) + d.ParentNum = binary.LittleEndian.Uint32(dat[12:]) return } func ReadEDir(r io.Reader) (d EDirectory, err error) { - err = binary.Read(r, binary.LittleEndian, &d.eDirectoryInit) + dat := make([]byte, 24) + _, err = r.Read(dat) if err != nil { return } + d.LinkCount = binary.LittleEndian.Uint32(dat) + d.Size = binary.LittleEndian.Uint32(dat[4:]) + d.BlockStart = binary.LittleEndian.Uint32(dat[8:]) + d.ParentNum = binary.LittleEndian.Uint32(dat[12:]) + d.IndCount = binary.LittleEndian.Uint16(dat[16:]) + d.Offset = binary.LittleEndian.Uint16(dat[18:]) + d.XattrInd = binary.LittleEndian.Uint32(dat[20:]) d.Indexes = make([]DirectoryIndex, d.IndCount) - for i := range d.Indexes { - err = binary.Read(r, binary.LittleEndian, &d.Indexes[i].directoryIndexInit) + for i := range d.IndCount { + dat = make([]byte, 12) + _, err = r.Read(dat) if err != nil { return } + d.Indexes[i].Ind = binary.LittleEndian.Uint32(dat) + d.Indexes[i].Start = binary.LittleEndian.Uint32(dat[4:]) + d.Indexes[i].NameSize = binary.LittleEndian.Uint32(dat[8:]) d.Indexes[i].Name = make([]byte, d.Indexes[i].NameSize+1) - err = binary.Read(r, binary.LittleEndian, &d.Indexes[i].Name) + _, err = r.Read(d.Indexes[i].Name) if err != nil { return } diff --git a/low/inode/file.go b/low/inode/file.go index 1b4d461..2b81014 100644 --- a/low/inode/file.go +++ b/low/inode/file.go @@ -6,15 +6,11 @@ import ( "math" ) -type fileInit struct { +type File struct { BlockStart uint32 FragInd uint32 FragOffset uint32 Size uint32 -} - -type File struct { - fileInit BlockSizes []uint32 } @@ -34,16 +30,28 @@ type EFile struct { } func ReadFile(r io.Reader, blockSize uint32) (f File, err error) { - err = binary.Read(r, binary.LittleEndian, &f.fileInit) + dat := make([]byte, 16) + _, err = r.Read(dat) if err != nil { return } + f.BlockStart = binary.LittleEndian.Uint32(dat) + f.FragInd = binary.LittleEndian.Uint32(dat[4:]) + f.FragOffset = binary.LittleEndian.Uint32(dat[8:]) + f.Size = binary.LittleEndian.Uint32(dat[12:]) toRead := int(math.Floor(float64(f.Size) / float64(blockSize))) if f.FragInd == 0xFFFFFFFF && f.Size%blockSize > 0 { toRead++ } + dat = make([]byte, toRead*4) + _, err = r.Read(dat) + if err != nil { + return + } f.BlockSizes = make([]uint32, toRead) - err = binary.Read(r, binary.LittleEndian, &f.BlockSizes) + for i := range toRead { + f.BlockSizes[i] = binary.LittleEndian.Uint32(dat[i*4:]) + } return } diff --git a/squashfs.test b/squashfs.test new file mode 100755 index 0000000..22a7559 Binary files /dev/null and b/squashfs.test differ diff --git a/squashfs_test.go b/squashfs_test.go index ff3f074..4e7a7a5 100644 --- a/squashfs_test.go +++ b/squashfs_test.go @@ -68,6 +68,26 @@ func TestMisc(t *testing.T) { // t.Fatal("UM") } +func BenchmarkExtract(b *testing.B) { + tmpDir := "testing" + fil, err := preTest(tmpDir) + if err != nil { + b.Fatal(err) + } + libPath := filepath.Join(tmpDir, "ExtractLib") + os.RemoveAll(libPath) + op := FastOptions() + op.IgnorePerm = true + rdr, err := NewReader(fil) + if err != nil { + b.Fatal(err) + } + err = rdr.ExtractWithOptions(libPath, op) + if err != nil { + b.Fatal(err) + } +} + func BenchmarkRace(b *testing.B) { tmpDir := "testing" fil, err := preTest(tmpDir)