From 1d641259b2abc194588dfb5813f4661f144f8cdf Mon Sep 17 00:00:00 2001 From: Caleb Gardner Date: Tue, 10 Nov 2020 11:25:56 -0600 Subject: [PATCH] Somre more stuff for parsting Working on metadata parsing Runnning into some Reader issues so I might create my own. --- compressionoptions.go | 21 +++++++++++ reader.go | 12 ++++++ squashfs.go | 87 +++++++++++++++++++++++++++++++++++++++++++ squashfs_test.go | 3 +- superblock.go | 2 + unsquash.go | 32 ---------------- 6 files changed, 124 insertions(+), 33 deletions(-) create mode 100644 reader.go create mode 100644 squashfs.go delete mode 100644 unsquash.go diff --git a/compressionoptions.go b/compressionoptions.go index 65e604b..ca9d2e5 100644 --- a/compressionoptions.go +++ b/compressionoptions.go @@ -1,8 +1,22 @@ package squashfs +import "io" + +const ( + zlibCompression = 1 + iota + lzmaCompression + lzoCompression + xzCompression + lz4Compression + zstdCompression +) + //TODO: implement decompress for each type of Options type CompressionOptions interface { Decompress([]byte) []byte + DecompressCopy(*io.Reader, *io.Writer) + Compress([]byte) []byte + CompressCopy(*io.Reader, *io.Writer) } //TODO: Allow creation of options for compression. @@ -24,6 +38,13 @@ type GzipOptions struct { FixedStretegy bool } +func NewGzipOptions(raw gzipOptionsRaw) GzipOptions { + //TODO: parse strategies + return GzipOptions{ + raw: &raw, + } +} + type xzOptionsRaw struct { dictionarySize int32 executableFilters int32 diff --git a/reader.go b/reader.go new file mode 100644 index 0000000..9a9c3e4 --- /dev/null +++ b/reader.go @@ -0,0 +1,12 @@ +package squashfs + +import "io" + +//TODO: possible custom reader because I'm havng some issuse... + +type Reader struct { + rdr *io.SectionReader + Offset int //Offset is the current offset of the reader +} + +func NewReader(io.ReaderAt) diff --git a/squashfs.go b/squashfs.go new file mode 100644 index 0000000..77a8009 --- /dev/null +++ b/squashfs.go @@ -0,0 +1,87 @@ +package squashfs + +import ( + "encoding/binary" + "errors" + "io" +) + +var ( + //ErrNotMagical happens when making a new Squashfs and it doesn't have the magic number + ErrNotMagical = errors.New("Not Magical") +) + +//Squashfs is a squashfs backed by a ReadSeeker. +type Squashfs struct { + rdr *io.SectionReader //underlying reader + offset int + super Superblock + flags SuperblockFlags + compressionOptions CompressionOptions +} + +//NewSquashfs creates a new Squashfs backed by the given reader +func NewSquashfs(reader *io.SectionReader) (*Squashfs, error) { + var superblock Superblock + err := binary.Read(reader, binary.LittleEndian, &superblock) + if err != nil { + return nil, err + } + if superblock.Magic != squashfsMagic { + return nil, ErrNotMagical + } + flags := superblock.GetFlags() + var compressionOptions CompressionOptions + if flags.CompressorOptions { + switch superblock.Compression { + case zlibCompression: + var gzipOpRaw gzipOptionsRaw + err = binary.Read(reader, binary.LittleEndian, &gzipOpRaw) + if err != nil { + return nil, err + } + compressionOptions = NewGzipOptions(gzipOpRaw) + break + default: + //TODO: all the compression options + return nil, errors.New("This type of compression isn't supported yet") + } + } + //TODO: parse more info + return &Squashfs{ + rdr: reader, + super: superblock, + flags: flags, + compressionOptions: compressionOptions, + }, nil +} + +//GetFlags return the SuperblockFlags of the Squashfs +func (s *Squashfs) GetFlags() SuperblockFlags { + return s.super.GetFlags() +} + +//Metadata is a parsed metadata block +type Metadata struct { + Compressed bool + Size uint16 + Data *io.SectionReader +} + +func (s *Squashfs) parseNextMetadata() (*Metadata, error) { + var metaHeader uint16 + err := binary.Read(s.rdr, binary.LittleEndian, metaHeader) + if err != nil { + return nil, err + } + if metaHeader&0x8000 == 0x8000 { + metaHeader = metaHeader &^ 0x8000 + //TODO: read compressed metadata + return nil, errors.New("Metadata is compressed, which is not implemented yet") + } + return &Metadata{ + Compressed: false, + Size: metaHeader, + //TODO: Data: io.NewSectionReader(s.rdr, , metaHeader), + }, nil +} diff --git a/squashfs_test.go b/squashfs_test.go index 98986fe..2cf4c66 100644 --- a/squashfs_test.go +++ b/squashfs_test.go @@ -31,7 +31,8 @@ func TestAppImageSquash(t *testing.T) { } } defer squashFil.Close() - squash, err := NewSquashfs(squashFil) + stat, _ := squashFil.Stat() + squash, err := NewSquashfs(io.NewSectionReader(squashFil, 0, stat.Size())) if err != nil { t.Error(err) } diff --git a/superblock.go b/superblock.go index 6c7225a..59550ec 100644 --- a/superblock.go +++ b/superblock.go @@ -1,5 +1,7 @@ package squashfs +const squashfsMagic = 0x73717368 + //Superblock is a raw representation of a squashfs //Descriptions provided by https://dr-emann.github.io/squashfs/ type Superblock struct { diff --git a/unsquash.go b/unsquash.go deleted file mode 100644 index bcc3c20..0000000 --- a/unsquash.go +++ /dev/null @@ -1,32 +0,0 @@ -package squashfs - -import ( - "encoding/binary" - "io" -) - -//Squashfs is a squashfs backed by a ReadSeeker. -type Squashfs struct { - rdr *io.ReadSeeker //underlying reader - super Superblock -} - -//NewSquashfs creates a new Squashfs backed by the given reader -func NewSquashfs(reader io.ReadSeeker) (*Squashfs, error) { - var superblock Superblock - err := binary.Read(reader, binary.LittleEndian, &superblock) - if err != nil { - return nil, err - } - //TODO: check magic - //TODO: parse more info - return &Squashfs{ - rdr: &reader, - super: superblock, - }, nil -} - -//GetFlags return the SuperblockFlags of the Squashfs -func (s *Squashfs) GetFlags() SuperblockFlags { - return s.super.GetFlags() -}