more work on decompression

This commit is contained in:
Caleb Gardner
2020-11-10 22:31:21 -06:00
parent ac2b6da841
commit 89b19b06f6
3 changed files with 93 additions and 12 deletions
+78 -6
View File
@@ -1,6 +1,9 @@
package squashfs package squashfs
import "io" import (
"compress/zlib"
"io"
)
const ( const (
zlibCompression = 1 + iota zlibCompression = 1 + iota
@@ -13,10 +16,10 @@ const (
//TODO: implement decompress for each type of Options //TODO: implement decompress for each type of Options
type CompressionOptions interface { type CompressionOptions interface {
Decompress([]byte) []byte Decompress(*io.SectionReader, int) ([]byte, error)
DecompressCopy(*io.Reader, *io.Writer) DecompressCopy(*io.Reader, *io.Writer) (int, error)
Compress([]byte) []byte Compress(*io.SectionReader, int) ([]byte, error)
CompressCopy(*io.Reader, *io.Writer) CompressCopy(*io.Reader, *io.Writer) (int, error)
} }
//TODO: Allow creation of options for compression. //TODO: Allow creation of options for compression.
@@ -29,7 +32,7 @@ type gzipOptionsRaw struct {
//GzipOptions is the options used for gzip compression. Backed by the raw format, with strategies parsed. //GzipOptions is the options used for gzip compression. Backed by the raw format, with strategies parsed.
type GzipOptions struct { type GzipOptions struct {
CompressionOptions CompressionOptions //TODO: remove
raw *gzipOptionsRaw raw *gzipOptionsRaw
DefaultStrategy bool DefaultStrategy bool
FilteredStrategy bool FilteredStrategy bool
@@ -45,11 +48,80 @@ func NewGzipOptions(raw gzipOptionsRaw) GzipOptions {
} }
} }
func (gzipOp *GzipOptions) Decompress(rdr *io.SectionReader, blockSize int) ([]byte, error) {
zlibRdr, err := zlib.NewReader(rdr)
defer zlibRdr.Close()
if err != nil {
return nil, err
}
out := make([]byte, 0)
var tmp []byte
read := blockSize
for read == blockSize {
tmp = make([]byte, blockSize)
read, err = zlibRdr.Read(tmp)
if err != io.EOF {
return nil, err
}
if read < blockSize {
tmp = tmp[:read]
}
out = append(out, tmp...)
}
return out, nil
}
func (gzipOp *GzipOptions) DecompressCopy(rdr *io.Reader, wrt *io.Writer) (int, error) {
zlibRdr, err := zlib.NewReader(*rdr)
defer zlibRdr.Close()
if err != nil {
return 0, err
}
n, err := io.Copy(*wrt, zlibRdr)
return int(n), err
}
func (gzipOp *GzipOptions) Compress(rdr *io.SectionReader, blockSize int) ([]byte, error) {
}
func (gzipOp *GzipOptions) CompressCopy(rdr *io.Reader, wrt *io.Writer) (int, error) {
zlibWrt, err := zlib.NewWriter(*wrt) //TODO: allow setting level
defer zlibWrt.Close()
if err != nil {
return 0, err
}
}
type xzOptionsRaw struct { type xzOptionsRaw struct {
dictionarySize int32 dictionarySize int32
executableFilters int32 executableFilters int32
} }
type XzOptions struct {
CompressionOptions //TODO: Remove
raw *xzOptionsRaw
Execx86 bool
ExecPower bool
Execa64 bool
ExecArm bool
ExecArmThumb bool
ExecSparc bool
}
func NewXzOption(raw xzOptionsRaw) XzOptions {
return XzOptions{
raw: &raw,
Execx86: raw.executableFilters&0x1 == 0x1,
ExecPower: raw.executableFilters&0x2 == 0x2,
Execa64: raw.executableFilters&0x4 == 0x4,
ExecArm: raw.executableFilters&0x8 == 0x8,
ExecArmThumb: raw.executableFilters&0x10 == 0x10,
ExecSparc: raw.executableFilters&0x20 == 0x20,
}
}
type lz4OptionsRaw struct { type lz4OptionsRaw struct {
version int32 version int32
flags int32 flags int32
+1 -1
View File
@@ -16,7 +16,7 @@ type Reader struct {
offset int64 offset int64
} }
//NewReader creates a //NewReader creates a squashfs.Reader from a io.ReaderAt
func NewReader(baseReader io.ReaderAt) Reader { func NewReader(baseReader io.ReaderAt) Reader {
return Reader{ return Reader{
rdr: baseReader, rdr: baseReader,
+14 -5
View File
@@ -13,7 +13,7 @@ var (
//Squashfs is a squashfs backed by a ReadSeeker. //Squashfs is a squashfs backed by a ReadSeeker.
type Squashfs struct { type Squashfs struct {
rdr *io.SectionReader //underlying reader rdr *Reader //underlying reader
offset int offset int
super Superblock super Superblock
flags SuperblockFlags flags SuperblockFlags
@@ -21,9 +21,10 @@ type Squashfs struct {
} }
//NewSquashfs creates a new Squashfs backed by the given reader //NewSquashfs creates a new Squashfs backed by the given reader
func NewSquashfs(reader *io.SectionReader) (*Squashfs, error) { func NewSquashfs(reader io.ReaderAt) (*Squashfs, error) {
rdr := NewReader(reader)
var superblock Superblock var superblock Superblock
err := binary.Read(reader, binary.LittleEndian, &superblock) err := binary.Read(&rdr, binary.LittleEndian, &superblock)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -36,12 +37,20 @@ func NewSquashfs(reader *io.SectionReader) (*Squashfs, error) {
switch superblock.Compression { switch superblock.Compression {
case zlibCompression: case zlibCompression:
var gzipOpRaw gzipOptionsRaw var gzipOpRaw gzipOptionsRaw
err = binary.Read(reader, binary.LittleEndian, &gzipOpRaw) err = binary.Read(&rdr, binary.LittleEndian, &gzipOpRaw)
if err != nil { if err != nil {
return nil, err return nil, err
} }
compressionOptions = NewGzipOptions(gzipOpRaw) compressionOptions = NewGzipOptions(gzipOpRaw)
break break
case xzCompression:
var xzOpRaw xzOptionsRaw
err = binary.Read(&rdr, binary.LittleEndian, xzOpRaw)
if err != nil {
return nil, err
}
compressionOptions = NewXzOption(xzOpRaw)
break
default: default:
//TODO: all the compression options //TODO: all the compression options
return nil, errors.New("This type of compression isn't supported yet") return nil, errors.New("This type of compression isn't supported yet")
@@ -49,7 +58,7 @@ func NewSquashfs(reader *io.SectionReader) (*Squashfs, error) {
} }
//TODO: parse more info //TODO: parse more info
return &Squashfs{ return &Squashfs{
rdr: reader, rdr: &rdr,
super: superblock, super: superblock,
flags: flags, flags: flags,
compressionOptions: compressionOptions, compressionOptions: compressionOptions,