Possibly finished gzip compression option

More metadata stuff
Started work on inode parsing
This commit is contained in:
Caleb Gardner
2020-11-11 02:55:21 -06:00
parent 89b19b06f6
commit 8fa093763f
3 changed files with 215 additions and 40 deletions
+70 -23
View File
@@ -14,12 +14,13 @@ const (
zstdCompression
)
//TODO: implement decompress for each type of Options
//TODO: implement for each type of Options
type CompressionOptions interface {
Decompress(*io.SectionReader, int) ([]byte, error)
DecompressCopy(*io.Reader, *io.Writer) (int, error)
Compress(*io.SectionReader, int) ([]byte, error)
CompressCopy(*io.Reader, *io.Writer) (int, error)
Reader(io.Reader) (*io.ReadCloser, error)
}
//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.
type GzipOptions struct {
CompressionOptions //TODO: remove
CompressionOptions
raw *gzipOptionsRaw
DefaultStrategy bool
FilteredStrategy bool
@@ -41,9 +42,54 @@ type GzipOptions struct {
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
return GzipOptions{
return &GzipOptions{
raw: &raw,
}
}
@@ -54,21 +100,12 @@ func (gzipOp *GzipOptions) Decompress(rdr *io.SectionReader, blockSize int) ([]b
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
bytrw := newByteReadWrite(0)
_, err = io.Copy(bytrw, zlibRdr)
if err != nil {
return bytrw.byts, 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) {
@@ -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) {
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) {
zlibWrt, err := zlib.NewWriter(*wrt) //TODO: allow setting level
zlibWrt := zlib.NewWriter(*wrt) //TODO: allow setting level
defer zlibWrt.Close()
if err != nil {
return 0, err
}
n, err := io.Copy(zlibWrt, *rdr)
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 {
+91
View File
@@ -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
}
+49 -12
View File
@@ -33,29 +33,33 @@ func NewSquashfs(reader io.ReaderAt) (*Squashfs, error) {
}
flags := superblock.GetFlags()
var compressionOptions CompressionOptions
if flags.CompressorOptions {
switch superblock.Compression {
case zlibCompression:
if flags.CompressorOptions {
var gzipOpRaw gzipOptionsRaw
err = binary.Read(&rdr, binary.LittleEndian, &gzipOpRaw)
if err != nil {
return nil, err
}
compressionOptions = NewGzipOptions(gzipOpRaw)
break
} else {
compressionOptions = NewGzipOptions(gzipOptionsRaw{})
}
case xzCompression:
if flags.CompressorOptions {
var xzOpRaw xzOptionsRaw
err = binary.Read(&rdr, binary.LittleEndian, xzOpRaw)
if err != nil {
return nil, err
}
compressionOptions = NewXzOption(xzOpRaw)
break
} else {
compressionOptions = NewXzOption(xzOptionsRaw{})
}
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,
@@ -70,14 +74,21 @@ func (s *Squashfs) GetFlags() SuperblockFlags {
return s.super.GetFlags()
}
//Metadata is a parsed metadata block
type Metadata struct {
//metadata is a parsed metadata block
type metadata struct {
Compressed bool
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
err := binary.Read(s.rdr, binary.LittleEndian, metaHeader)
if err != nil {
@@ -85,12 +96,38 @@ func (s *Squashfs) parseNextMetadata() (*Metadata, error) {
}
if metaHeader&0x8000 == 0x8000 {
metaHeader = metaHeader &^ 0x8000
//TODO: read compressed metadata
return nil, errors.New("Metadata is compressed, which is not implemented yet")
compressRead, err := s.compressionOptions.Reader(io.NewSectionReader(s.rdr, s.rdr.offset, int64(metaHeader)))
return &metadata{
Compressed: true,
Size: metaHeader,
Data: *compressRead,
}, err
}
return &Metadata{
return &metadata{
Compressed: false,
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
}