more work on decompression
This commit is contained in:
+78
-6
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user