Possibly finished gzip compression option
More metadata stuff Started work on inode parsing
This commit is contained in:
+70
-23
@@ -14,12 +14,13 @@ const (
|
|||||||
zstdCompression
|
zstdCompression
|
||||||
)
|
)
|
||||||
|
|
||||||
//TODO: implement decompress for each type of Options
|
//TODO: implement for each type of Options
|
||||||
type CompressionOptions interface {
|
type CompressionOptions interface {
|
||||||
Decompress(*io.SectionReader, int) ([]byte, error)
|
Decompress(*io.SectionReader, int) ([]byte, error)
|
||||||
DecompressCopy(*io.Reader, *io.Writer) (int, error)
|
DecompressCopy(*io.Reader, *io.Writer) (int, error)
|
||||||
Compress(*io.SectionReader, int) ([]byte, error)
|
Compress(*io.SectionReader, int) ([]byte, error)
|
||||||
CompressCopy(*io.Reader, *io.Writer) (int, error)
|
CompressCopy(*io.Reader, *io.Writer) (int, error)
|
||||||
|
Reader(io.Reader) (*io.ReadCloser, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Allow creation of options for compression.
|
//TODO: Allow creation of options for compression.
|
||||||
@@ -32,7 +33,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 //TODO: remove
|
CompressionOptions
|
||||||
raw *gzipOptionsRaw
|
raw *gzipOptionsRaw
|
||||||
DefaultStrategy bool
|
DefaultStrategy bool
|
||||||
FilteredStrategy bool
|
FilteredStrategy bool
|
||||||
@@ -41,9 +42,54 @@ type GzipOptions struct {
|
|||||||
FixedStretegy bool
|
FixedStretegy bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGzipOptions(raw gzipOptionsRaw) GzipOptions {
|
type byteWriterReader struct {
|
||||||
|
byts []byte
|
||||||
|
offset int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newByteReadWrite(length int) *byteWriterReader {
|
||||||
|
return &byteWriterReader{
|
||||||
|
byts: make([]byte, length),
|
||||||
|
offset: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newByteReadWriteFromBytes(byts []byte) *byteWriterReader {
|
||||||
|
return &byteWriterReader{
|
||||||
|
byts: byts,
|
||||||
|
offset: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bwr *byteWriterReader) getBytes() []byte {
|
||||||
|
return bwr.byts
|
||||||
|
}
|
||||||
|
|
||||||
|
//Read reads the bytes.
|
||||||
|
func (bwr *byteWriterReader) Read(byt []byte) (int, error) {
|
||||||
|
if len(bwr.byts) < bwr.offset+len(byt) {
|
||||||
|
bytesWritten := len(bwr.byts) - bwr.offset
|
||||||
|
for i := 0; i < bytesWritten; i++ {
|
||||||
|
byt[i] = bwr.byts[i+bwr.offset]
|
||||||
|
}
|
||||||
|
return bytesWritten, io.EOF
|
||||||
|
}
|
||||||
|
for i := 0; i < len(byt); i++ {
|
||||||
|
byt[i] = bwr.byts[bwr.offset+i]
|
||||||
|
}
|
||||||
|
bwr.offset += len(byt)
|
||||||
|
return len(byt), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Write writes to the bytes. WILL expand to accept the incoming bytes.
|
||||||
|
func (bwr *byteWriterReader) Write(byts []byte) (int, error) {
|
||||||
|
bwr.byts = append(bwr.byts, byts...)
|
||||||
|
return len(byts), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGzipOptions(raw gzipOptionsRaw) *GzipOptions {
|
||||||
//TODO: parse strategies
|
//TODO: parse strategies
|
||||||
return GzipOptions{
|
return &GzipOptions{
|
||||||
raw: &raw,
|
raw: &raw,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,21 +100,12 @@ func (gzipOp *GzipOptions) Decompress(rdr *io.SectionReader, blockSize int) ([]b
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
out := make([]byte, 0)
|
bytrw := newByteReadWrite(0)
|
||||||
var tmp []byte
|
_, err = io.Copy(bytrw, zlibRdr)
|
||||||
read := blockSize
|
if err != nil {
|
||||||
for read == blockSize {
|
return bytrw.byts, err
|
||||||
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
|
return bytrw.byts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gzipOp *GzipOptions) DecompressCopy(rdr *io.Reader, wrt *io.Writer) (int, error) {
|
func (gzipOp *GzipOptions) DecompressCopy(rdr *io.Reader, wrt *io.Writer) (int, error) {
|
||||||
@@ -82,16 +119,26 @@ func (gzipOp *GzipOptions) DecompressCopy(rdr *io.Reader, wrt *io.Writer) (int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gzipOp *GzipOptions) Compress(rdr *io.SectionReader, blockSize int) ([]byte, error) {
|
func (gzipOp *GzipOptions) Compress(rdr *io.SectionReader, blockSize int) ([]byte, error) {
|
||||||
|
bytWrt := newByteReadWrite(0)
|
||||||
|
zlibWrt := zlib.NewWriter(bytWrt) //TODO: allow setting level
|
||||||
|
defer zlibWrt.Close()
|
||||||
|
_, err := io.Copy(zlibWrt, rdr)
|
||||||
|
if err != nil {
|
||||||
|
return bytWrt.byts, err
|
||||||
|
}
|
||||||
|
return bytWrt.byts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gzipOp *GzipOptions) CompressCopy(rdr *io.Reader, wrt *io.Writer) (int, error) {
|
func (gzipOp *GzipOptions) CompressCopy(rdr *io.Reader, wrt *io.Writer) (int, error) {
|
||||||
zlibWrt, err := zlib.NewWriter(*wrt) //TODO: allow setting level
|
zlibWrt := zlib.NewWriter(*wrt) //TODO: allow setting level
|
||||||
defer zlibWrt.Close()
|
defer zlibWrt.Close()
|
||||||
if err != nil {
|
n, err := io.Copy(zlibWrt, *rdr)
|
||||||
return 0, err
|
return int(n), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gzipOp *GzipOptions) Reader(rdr io.Reader) (*io.ReadCloser, error) {
|
||||||
|
read, err := zlib.NewReader(rdr)
|
||||||
|
return &read, err
|
||||||
}
|
}
|
||||||
|
|
||||||
type xzOptionsRaw struct {
|
type xzOptionsRaw struct {
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package inode
|
||||||
|
|
||||||
|
type CommonHeader struct {
|
||||||
|
InodeType uint16
|
||||||
|
Permissions uint16
|
||||||
|
UID uint16
|
||||||
|
GID uint16
|
||||||
|
ModifiedTime uint32
|
||||||
|
Number uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type BasicDirectory struct {
|
||||||
|
DirectoryIndex uint32
|
||||||
|
HardLinks uint32
|
||||||
|
DirectorySize uint16
|
||||||
|
DirectoryOffset uint16
|
||||||
|
ParentInodeNumber uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExtendedDirectoryInit struct {
|
||||||
|
HardLinks uint32
|
||||||
|
DirectorySize uint32
|
||||||
|
DirectoryIndex uint32
|
||||||
|
ParentInodeNumber uint32
|
||||||
|
IndexCount uint16 //one less then directory indexes following structure
|
||||||
|
DirectoryOffset uint16
|
||||||
|
XattrIndex uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExtendedDirectory struct {
|
||||||
|
ExtendedDirectoryInit
|
||||||
|
//TODO indexes []DirectoryIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
type BasicFile struct {
|
||||||
|
BlockStart uint32
|
||||||
|
FragmentIndex uint32
|
||||||
|
FragmentOffset uint32
|
||||||
|
Size uint32
|
||||||
|
BlockSizes []uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExtendedFile struct {
|
||||||
|
BlockStart uint32
|
||||||
|
Size uint32
|
||||||
|
Sparse uint64
|
||||||
|
HardLinks uint32
|
||||||
|
FragmentIndex uint32
|
||||||
|
FragmentOffset uint32
|
||||||
|
XattrIndex uint32
|
||||||
|
BlockSizes []uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type BasicSymlinkInit struct {
|
||||||
|
HardLinks uint32
|
||||||
|
TargetPathSize uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type BasicSymlink struct {
|
||||||
|
BasicSymlinkInit
|
||||||
|
targetPath []byte //len is TargetPathSize
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExtendedSymlinkInit struct {
|
||||||
|
HardLinks uint32
|
||||||
|
TargetPathSize uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExtendedSymlink struct {
|
||||||
|
targetPath []byte
|
||||||
|
XattrIndex uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type BasicDevice struct {
|
||||||
|
HardLinks uint32
|
||||||
|
Device uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExtendedDevice struct {
|
||||||
|
BasicDevice
|
||||||
|
XattrIndex uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type BasicIPC struct {
|
||||||
|
HardLink uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExtendedIPC struct {
|
||||||
|
BasicIPC
|
||||||
|
XattrIndex uint32
|
||||||
|
}
|
||||||
+54
-17
@@ -33,28 +33,32 @@ func NewSquashfs(reader io.ReaderAt) (*Squashfs, error) {
|
|||||||
}
|
}
|
||||||
flags := superblock.GetFlags()
|
flags := superblock.GetFlags()
|
||||||
var compressionOptions CompressionOptions
|
var compressionOptions CompressionOptions
|
||||||
if flags.CompressorOptions {
|
switch superblock.Compression {
|
||||||
switch superblock.Compression {
|
case zlibCompression:
|
||||||
case zlibCompression:
|
if flags.CompressorOptions {
|
||||||
var gzipOpRaw gzipOptionsRaw
|
var gzipOpRaw gzipOptionsRaw
|
||||||
err = binary.Read(&rdr, 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
|
} else {
|
||||||
case xzCompression:
|
compressionOptions = NewGzipOptions(gzipOptionsRaw{})
|
||||||
|
}
|
||||||
|
case xzCompression:
|
||||||
|
if flags.CompressorOptions {
|
||||||
var xzOpRaw xzOptionsRaw
|
var xzOpRaw xzOptionsRaw
|
||||||
err = binary.Read(&rdr, binary.LittleEndian, xzOpRaw)
|
err = binary.Read(&rdr, binary.LittleEndian, xzOpRaw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
compressionOptions = NewXzOption(xzOpRaw)
|
compressionOptions = NewXzOption(xzOpRaw)
|
||||||
break
|
} else {
|
||||||
default:
|
compressionOptions = NewXzOption(xzOptionsRaw{})
|
||||||
//TODO: all the compression options
|
|
||||||
return nil, errors.New("This type of compression isn't supported yet")
|
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
//TODO: all the compression options
|
||||||
|
return nil, errors.New("This type of compression isn't supported yet")
|
||||||
}
|
}
|
||||||
//TODO: parse more info
|
//TODO: parse more info
|
||||||
return &Squashfs{
|
return &Squashfs{
|
||||||
@@ -70,14 +74,21 @@ func (s *Squashfs) GetFlags() SuperblockFlags {
|
|||||||
return s.super.GetFlags()
|
return s.super.GetFlags()
|
||||||
}
|
}
|
||||||
|
|
||||||
//Metadata is a parsed metadata block
|
//metadata is a parsed metadata block
|
||||||
type Metadata struct {
|
type metadata struct {
|
||||||
Compressed bool
|
Compressed bool
|
||||||
Size uint16
|
Size uint16
|
||||||
Data *io.SectionReader
|
Data io.Reader
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Squashfs) parseNextMetadata() (*Metadata, error) {
|
func (m *metadata) close() {
|
||||||
|
switch m.Data.(type) {
|
||||||
|
case io.ReadCloser:
|
||||||
|
m.Data.(io.ReadCloser).Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Squashfs) parseNextMetadata() (*metadata, error) {
|
||||||
var metaHeader uint16
|
var metaHeader uint16
|
||||||
err := binary.Read(s.rdr, binary.LittleEndian, metaHeader)
|
err := binary.Read(s.rdr, binary.LittleEndian, metaHeader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -85,12 +96,38 @@ func (s *Squashfs) parseNextMetadata() (*Metadata, error) {
|
|||||||
}
|
}
|
||||||
if metaHeader&0x8000 == 0x8000 {
|
if metaHeader&0x8000 == 0x8000 {
|
||||||
metaHeader = metaHeader &^ 0x8000
|
metaHeader = metaHeader &^ 0x8000
|
||||||
//TODO: read compressed metadata
|
compressRead, err := s.compressionOptions.Reader(io.NewSectionReader(s.rdr, s.rdr.offset, int64(metaHeader)))
|
||||||
return nil, errors.New("Metadata is compressed, which is not implemented yet")
|
return &metadata{
|
||||||
|
Compressed: true,
|
||||||
|
Size: metaHeader,
|
||||||
|
Data: *compressRead,
|
||||||
|
}, err
|
||||||
}
|
}
|
||||||
return &Metadata{
|
return &metadata{
|
||||||
Compressed: false,
|
Compressed: false,
|
||||||
Size: metaHeader,
|
Size: metaHeader,
|
||||||
//TODO: Data: io.NewSectionReader(s.rdr, , metaHeader),
|
Data: io.NewSectionReader(s.rdr, s.rdr.offset, int64(metaHeader)),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Squashfs) parseMetadataAt(offset int64) (*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
|
||||||
|
compressRead, err := s.compressionOptions.Reader(io.NewSectionReader(s.rdr, offset, int64(metaHeader)))
|
||||||
|
return &metadata{
|
||||||
|
Compressed: true,
|
||||||
|
Size: metaHeader,
|
||||||
|
Data: *compressRead,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
return &metadata{
|
||||||
|
Compressed: false,
|
||||||
|
Size: metaHeader,
|
||||||
|
Data: io.NewSectionReader(s.rdr, offset, int64(metaHeader)),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user