97 lines
2.4 KiB
Go
97 lines
2.4 KiB
Go
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 *Reader //underlying reader
|
|
offset int
|
|
super Superblock
|
|
flags SuperblockFlags
|
|
compressionOptions CompressionOptions
|
|
}
|
|
|
|
//NewSquashfs creates a new Squashfs backed by the given reader
|
|
func NewSquashfs(reader io.ReaderAt) (*Squashfs, error) {
|
|
rdr := NewReader(reader)
|
|
var superblock Superblock
|
|
err := binary.Read(&rdr, 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(&rdr, binary.LittleEndian, &gzipOpRaw)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
compressionOptions = NewGzipOptions(gzipOpRaw)
|
|
break
|
|
case xzCompression:
|
|
var xzOpRaw xzOptionsRaw
|
|
err = binary.Read(&rdr, binary.LittleEndian, xzOpRaw)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
compressionOptions = NewXzOption(xzOpRaw)
|
|
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: &rdr,
|
|
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
|
|
}
|