Restarted some stuff so I can do it better.
Made a reader that can reade across data blocks if necessary Still can't get things to read right
This commit is contained in:
+35
-128
@@ -2,166 +2,73 @@ package squashfs
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/CalebQ42/GoSquashfs/internal/directory"
|
||||
"github.com/CalebQ42/GoSquashfs/internal/inode"
|
||||
)
|
||||
|
||||
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
|
||||
r Reader
|
||||
super Superblock
|
||||
flags SuperblockFlags
|
||||
compression 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)
|
||||
func NewSquashfs(rdr io.ReaderAt) (*Squashfs, error) {
|
||||
var squash Squashfs
|
||||
squash.r = NewReader(rdr)
|
||||
err := binary.Read(&squash.r, binary.LittleEndian, &squash.super)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if superblock.Magic != squashfsMagic {
|
||||
return nil, ErrNotMagical
|
||||
}
|
||||
flags := superblock.GetFlags()
|
||||
var compressionOptions CompressionOptions
|
||||
switch superblock.Compression {
|
||||
squash.flags = squash.super.getFlags()
|
||||
switch squash.super.Compression {
|
||||
case gzipCompression:
|
||||
if flags.CompressorOptions {
|
||||
var gzipOpRaw gzipOptionsRaw
|
||||
err = binary.Read(&rdr, binary.LittleEndian, &gzipOpRaw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
compressionOptions = NewGzipOptions(gzipOpRaw)
|
||||
} 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)
|
||||
} else {
|
||||
compressionOptions = NewXzOption(xzOptionsRaw{})
|
||||
var raw gzipOptionsRaw
|
||||
err := binary.Read(&squash.r, binary.LittleEndian, &raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
squash.compression = NewGzipOptions(raw)
|
||||
default:
|
||||
//TODO: all the compression options
|
||||
return nil, errors.New("This type of compression isn't supported yet")
|
||||
fmt.Println("Other compression options are not currently supported")
|
||||
return nil, err
|
||||
}
|
||||
//TODO: parse more info
|
||||
return &Squashfs{
|
||||
rdr: &rdr,
|
||||
super: superblock,
|
||||
flags: flags,
|
||||
compressionOptions: compressionOptions,
|
||||
}, nil
|
||||
return &squash, nil
|
||||
}
|
||||
|
||||
func (s *Squashfs) readRootDirectoryTable() error {
|
||||
func (s *Squashfs) printDirTable() error {
|
||||
offset, metaOffset := inode.ProcessInodeRef(s.super.RootInode)
|
||||
meta, err := s.parseMetadataAt(int64(s.super.InodeTableOffset) + int64(offset))
|
||||
br, err := s.NewBlockReader(int64(offset))
|
||||
if err != nil {
|
||||
fmt.Println("Error processing metadata")
|
||||
return err
|
||||
}
|
||||
_, err = meta.Data.Read(make([]byte, metaOffset))
|
||||
fmt.Println(offset, metaOffset)
|
||||
br.dataOffset = int64(metaOffset)
|
||||
_, inodeType, err := inode.ProcessInode(br, s.super.BlockSize)
|
||||
if err != nil {
|
||||
fmt.Println("error reading forward to offset")
|
||||
return err
|
||||
}
|
||||
common, _, err := inode.ProcessInode(&meta.Data, s.super.BlockSize)
|
||||
rootDir := inodeType.(*inode.BasicDirectory)
|
||||
fmt.Println(*rootDir)
|
||||
br, err = s.NewBlockReader(int64(s.super.DirectoryTableOffset) + int64(rootDir.DirectoryIndex))
|
||||
if err != nil {
|
||||
fmt.Println("Error reading inode")
|
||||
return err
|
||||
}
|
||||
if common.InodeType != inode.BasicDirectoryType {
|
||||
return errors.New("Not a basic directory")
|
||||
br.dataOffset = int64(rootDir.DirectoryOffset)
|
||||
dir, err := directory.NewDirectory(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, entry := range dir.Entries {
|
||||
fmt.Println(entry.Name)
|
||||
}
|
||||
// dirTable, err := directory.NewDirectory(meta.Data)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// for _, entry := range dirTable.Entries {
|
||||
// fmt.Println(entry.Name)
|
||||
// }
|
||||
return nil
|
||||
}
|
||||
|
||||
//GetFlags return the SuperblockFlags of the Squashfs
|
||||
//GetFlags returns the SuperblockFlags from the Superblock
|
||||
func (s *Squashfs) GetFlags() SuperblockFlags {
|
||||
return s.flags
|
||||
}
|
||||
|
||||
//metadata is a parsed metadata block
|
||||
type metadata struct {
|
||||
Compressed bool
|
||||
Size uint16
|
||||
Data io.Reader
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
reader := io.NewSectionReader(s.rdr, s.rdr.offset, s.rdr.offset+int64(metaHeader))
|
||||
if metaHeader&0x8000 == 0x8000 {
|
||||
metaHeader = metaHeader &^ 0x8000
|
||||
compressRead, err := s.compressionOptions.Reader(reader)
|
||||
return &metadata{
|
||||
Compressed: true,
|
||||
Size: metaHeader,
|
||||
Data: *compressRead,
|
||||
}, err
|
||||
}
|
||||
return &metadata{
|
||||
Compressed: false,
|
||||
Size: metaHeader,
|
||||
Data: reader,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Squashfs) parseMetadataAt(offset int64) (*metadata, error) {
|
||||
var metaHeader uint16
|
||||
var headerBytes []byte
|
||||
headerBytes = make([]byte, 2)
|
||||
s.rdr.ReadAt(headerBytes, offset)
|
||||
metaHeader = binary.LittleEndian.Uint16(headerBytes)
|
||||
if metaHeader&0x8000 == 0x8000 {
|
||||
metaHeader = metaHeader &^ 0x8000
|
||||
compressRead, err := s.compressionOptions.Reader(io.NewSectionReader(s.rdr, s.rdr.offset, s.rdr.offset+int64(s.super.BlockSize)))
|
||||
return &metadata{
|
||||
Compressed: true,
|
||||
Size: metaHeader,
|
||||
Data: *compressRead,
|
||||
}, err
|
||||
}
|
||||
return &metadata{
|
||||
Compressed: false,
|
||||
Size: metaHeader,
|
||||
Data: io.NewSectionReader(s.rdr, s.rdr.offset, s.rdr.offset+int64(s.super.BlockSize)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user