Files
squashfs/blocks.go
T
Caleb Gardner 06b188d53c 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
2020-11-13 16:11:44 -06:00

118 lines
3.1 KiB
Go

package squashfs
import (
"encoding/binary"
"fmt"
"io"
"github.com/CalebQ42/GoSquashfs/bytereadwrite"
)
type MetadataHeader struct {
rawHeader uint16
Compressed bool
Size uint16
}
type BlockReader struct {
initalOffset int64
offset int64
squash *Squashfs
headers []MetadataHeader
dataCache []byte
dataOffset int64
}
//NewBlockReader creates a new BlockReader from a squashfs.Reader. Reads the first header and caches the first set of data.
func (s *Squashfs) NewBlockReader(offset int64) (*BlockReader, error) {
var br BlockReader
br.squash = s
br.initalOffset = offset
br.offset = offset
br.headers = make([]MetadataHeader, 0)
br.dataCache = make([]byte, 0)
err := br.parseNewBlock()
if err != nil {
fmt.Println("Problem creating BlockReader")
return nil, err
}
return &br, nil
}
func (br *BlockReader) parseNewBlock() error {
var header MetadataHeader
err := binary.Read(io.NewSectionReader(&br.squash.r, br.offset, 2), binary.LittleEndian, &header.rawHeader)
if err != nil {
fmt.Println("Error while reading the header ", len(br.headers), " in BlockReader")
return err
}
header.Compressed = (header.rawHeader&0x8000 == 0x8000)
header.Size = header.rawHeader &^ 0x8000
br.headers = append(br.headers, header)
br.offset += 2
sectionReader := io.NewSectionReader(&br.squash.r, br.offset, br.offset+int64(header.Size))
dataWriter := bytereadwrite.NewByteReaderWriter()
_, err = io.Copy(dataWriter, sectionReader)
br.offset += int64(header.Size)
if header.Compressed {
data, err := br.squash.compression.Decompress(dataWriter)
if err != nil {
fmt.Println("Error while reading the encrypted data block in header", len(br.headers))
return err
}
br.dataCache = append(br.dataCache, data...)
return nil
}
if err != nil {
fmt.Println("Error while reading uncompressed data in header", len(br.headers))
return err
}
br.dataCache = append(br.dataCache, dataWriter.GetBytes()...)
return nil
}
//Read reads data into p. If it reaches EOF, tries to read a new block and add it's data to the cache
func (br *BlockReader) Read(p []byte) (n int, err error) {
read := 0
for {
byter := bytereadwrite.NewByteReaderWriterFromBytes(br.dataCache[br.dataOffset:])
temp, err := byter.Read(p[read:])
br.dataOffset += int64(temp)
read += temp
if err == nil {
return read, nil
} else if err != io.EOF {
return read, err
}
if err == io.EOF {
err = br.parseNewBlock()
if err != nil {
fmt.Println("Error while reading a new block")
return read, err
}
}
}
}
//ReadAt reads data into p from the offset. If it reaches EOF, tries to read a new block and add it's data to the cache.
//
//Offset is reletive to the offset set on creation.
func (br *BlockReader) ReadAt(p []byte, offset int) (n int, err error) {
read := 0
for err == io.EOF {
byter := bytereadwrite.NewByteReaderWriterFromBytes(br.dataCache[offset+read:])
temp, inErr := byter.Read(p[read:])
err = inErr
read += temp
br.dataOffset += int64(temp)
if err == io.EOF {
inErr = br.parseNewBlock()
if inErr != nil {
fmt.Println("Error while reading a new block")
return read, inErr
}
}
}
return
}