Made most functions private.
This will probably be the first version of the library.
This commit is contained in:
+3
-3
@@ -7,15 +7,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
//Decompressor is a squashfs decompressor interface. Allows for easy decompression no matter the type of compression.
|
//Decompressor is a squashfs decompressor interface. Allows for easy decompression no matter the type of compression.
|
||||||
type Decompressor interface {
|
type decompressor interface {
|
||||||
Decompress(io.Reader) ([]byte, error)
|
Decompress(io.Reader) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
//ZlibDecompressor is a decompressor for gzip type compression
|
//ZlibDecompressor is a decompressor for gzip type compression
|
||||||
type ZlibDecompressor struct{}
|
type zlibDecompressor struct{}
|
||||||
|
|
||||||
//Decompress reads the entirety of the given reader and returns it uncompressed as a byte slice.
|
//Decompress reads the entirety of the given reader and returns it uncompressed as a byte slice.
|
||||||
func (z *ZlibDecompressor) Decompress(r io.Reader) ([]byte, error) {
|
func (z *zlibDecompressor) Decompress(r io.Reader) ([]byte, error) {
|
||||||
rdr, err := zlib.NewReader(r)
|
rdr, err := zlib.NewReader(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
+14
-24
@@ -3,7 +3,6 @@ package squashfs
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/CalebQ42/GoSquashfs/internal/inode"
|
"github.com/CalebQ42/GoSquashfs/internal/inode"
|
||||||
@@ -17,17 +16,17 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
//DataReader reads data from data blocks.
|
//DataReader reads data from data blocks.
|
||||||
type DataReader struct {
|
type dataReader struct {
|
||||||
r *Reader
|
r *Reader
|
||||||
offset int64 //offset relative to the beginning of the squash file
|
offset int64 //offset relative to the beginning of the squash file
|
||||||
blocks []DataBlock
|
blocks []dataBlock
|
||||||
curBlock int //Which block in sizes is currently cached
|
curBlock int //Which block in sizes is currently cached
|
||||||
curData []byte
|
curData []byte
|
||||||
curReadOffset int //offset relative to the currently cached data
|
curReadOffset int //offset relative to the currently cached data
|
||||||
}
|
}
|
||||||
|
|
||||||
//DataBlock holds info about a given data block from it's size
|
//DataBlock holds info about a given data block from it's size
|
||||||
type DataBlock struct {
|
type dataBlock struct {
|
||||||
begOffset int64 //The offset relative to the beginning of the squash file. Makes it easier to seek to it.
|
begOffset int64 //The offset relative to the beginning of the squash file. Makes it easier to seek to it.
|
||||||
size uint32
|
size uint32
|
||||||
compressed bool
|
compressed bool
|
||||||
@@ -35,7 +34,7 @@ type DataBlock struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//NewDataBlock creates a new squashfs.datablock from a given size.
|
//NewDataBlock creates a new squashfs.datablock from a given size.
|
||||||
func NewDataBlock(raw uint32) (dbs DataBlock) {
|
func newDataBlock(raw uint32) (dbs dataBlock) {
|
||||||
dbs.compressed = raw&(1<<24) != (1 << 24)
|
dbs.compressed = raw&(1<<24) != (1 << 24)
|
||||||
dbs.size = raw &^ (1 << 24)
|
dbs.size = raw &^ (1 << 24)
|
||||||
if !dbs.compressed {
|
if !dbs.compressed {
|
||||||
@@ -45,12 +44,12 @@ func NewDataBlock(raw uint32) (dbs DataBlock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//NewDataReader creates a new data reader at the given offset, with the blocks defined by sizes
|
//NewDataReader creates a new data reader at the given offset, with the blocks defined by sizes
|
||||||
func (r *Reader) NewDataReader(offset int64, sizes []uint32) (*DataReader, error) {
|
func (r *Reader) newDataReader(offset int64, sizes []uint32) (*dataReader, error) {
|
||||||
var dr DataReader
|
var dr dataReader
|
||||||
dr.r = r
|
dr.r = r
|
||||||
dr.offset = offset
|
dr.offset = offset
|
||||||
for _, size := range sizes {
|
for _, size := range sizes {
|
||||||
dr.blocks = append(dr.blocks, NewDataBlock(size))
|
dr.blocks = append(dr.blocks, newDataBlock(size))
|
||||||
}
|
}
|
||||||
err := dr.readCurBlock()
|
err := dr.readCurBlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -60,8 +59,8 @@ func (r *Reader) NewDataReader(offset int64, sizes []uint32) (*DataReader, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
//NewDataReaderFromInode creates a new DataReader from a given inode. Inode must be of BasicFile or ExtendedFile types
|
//NewDataReaderFromInode creates a new DataReader from a given inode. Inode must be of BasicFile or ExtendedFile types
|
||||||
func (r *Reader) NewDataReaderFromInode(i *inode.Inode) (*DataReader, error) {
|
func (r *Reader) newDataReaderFromInode(i *inode.Inode) (*dataReader, error) {
|
||||||
var rdr DataReader
|
var rdr dataReader
|
||||||
rdr.r = r
|
rdr.r = r
|
||||||
switch i.Type {
|
switch i.Type {
|
||||||
case inode.BasicFileType:
|
case inode.BasicFileType:
|
||||||
@@ -71,7 +70,7 @@ func (r *Reader) NewDataReaderFromInode(i *inode.Inode) (*DataReader, error) {
|
|||||||
}
|
}
|
||||||
rdr.offset = int64(fil.Init.BlockStart)
|
rdr.offset = int64(fil.Init.BlockStart)
|
||||||
for _, sizes := range fil.BlockSizes {
|
for _, sizes := range fil.BlockSizes {
|
||||||
rdr.blocks = append(rdr.blocks, NewDataBlock(sizes))
|
rdr.blocks = append(rdr.blocks, newDataBlock(sizes))
|
||||||
}
|
}
|
||||||
if fil.Fragmented {
|
if fil.Fragmented {
|
||||||
rdr.blocks = rdr.blocks[:len(rdr.blocks)-1]
|
rdr.blocks = rdr.blocks[:len(rdr.blocks)-1]
|
||||||
@@ -83,7 +82,7 @@ func (r *Reader) NewDataReaderFromInode(i *inode.Inode) (*DataReader, error) {
|
|||||||
}
|
}
|
||||||
rdr.offset = int64(fil.Init.BlockStart)
|
rdr.offset = int64(fil.Init.BlockStart)
|
||||||
for _, sizes := range fil.BlockSizes {
|
for _, sizes := range fil.BlockSizes {
|
||||||
rdr.blocks = append(rdr.blocks, NewDataBlock(sizes))
|
rdr.blocks = append(rdr.blocks, newDataBlock(sizes))
|
||||||
}
|
}
|
||||||
if fil.Fragmented {
|
if fil.Fragmented {
|
||||||
rdr.blocks = rdr.blocks[:len(rdr.blocks)-1]
|
rdr.blocks = rdr.blocks[:len(rdr.blocks)-1]
|
||||||
@@ -98,7 +97,7 @@ func (r *Reader) NewDataReaderFromInode(i *inode.Inode) (*DataReader, error) {
|
|||||||
return &rdr, nil
|
return &rdr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DataReader) readNextBlock() error {
|
func (d *dataReader) readNextBlock() error {
|
||||||
d.curBlock++
|
d.curBlock++
|
||||||
if d.curBlock >= len(d.blocks) {
|
if d.curBlock >= len(d.blocks) {
|
||||||
d.curBlock--
|
d.curBlock--
|
||||||
@@ -108,15 +107,12 @@ func (d *DataReader) readNextBlock() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
d.curBlock--
|
d.curBlock--
|
||||||
d.readCurBlock()
|
d.readCurBlock()
|
||||||
fmt.Println("running back because of issues")
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println("Read block success!")
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DataReader) readCurBlock() error {
|
func (d *dataReader) readCurBlock() error {
|
||||||
fmt.Println("reading into block", d.curBlock, "out of", len(d.blocks))
|
|
||||||
if d.curBlock >= len(d.blocks) {
|
if d.curBlock >= len(d.blocks) {
|
||||||
return io.EOF
|
return io.EOF
|
||||||
}
|
}
|
||||||
@@ -127,12 +123,9 @@ func (d *DataReader) readCurBlock() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
sec := io.NewSectionReader(d.r.r, d.offset, int64(d.blocks[d.curBlock].size))
|
sec := io.NewSectionReader(d.r.r, d.offset, int64(d.blocks[d.curBlock].size))
|
||||||
fmt.Println("block size", d.r.super.BlockSize)
|
|
||||||
fmt.Println("compressed size", int64(d.blocks[d.curBlock].size))
|
|
||||||
if d.blocks[d.curBlock].compressed {
|
if d.blocks[d.curBlock].compressed {
|
||||||
btys, err := d.r.decompressor.Decompress(sec)
|
btys, err := d.r.decompressor.Decompress(sec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("HERE!")
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
d.blocks[d.curBlock].uncompressedSize = uint32(len(btys))
|
d.blocks[d.curBlock].uncompressedSize = uint32(len(btys))
|
||||||
@@ -152,9 +145,8 @@ func (d *DataReader) readCurBlock() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DataReader) Read(p []byte) (int, error) {
|
func (d *dataReader) Read(p []byte) (int, error) {
|
||||||
if d.curReadOffset+len(p) < len(d.curData) {
|
if d.curReadOffset+len(p) < len(d.curData) {
|
||||||
fmt.Println("Enough data in cache for direct read")
|
|
||||||
for i := 0; i < len(p); i++ {
|
for i := 0; i < len(p); i++ {
|
||||||
p[i] = d.curData[d.curReadOffset+i]
|
p[i] = d.curData[d.curReadOffset+i]
|
||||||
}
|
}
|
||||||
@@ -164,7 +156,6 @@ func (d *DataReader) Read(p []byte) (int, error) {
|
|||||||
read := 0
|
read := 0
|
||||||
for read < len(p) {
|
for read < len(p) {
|
||||||
if d.curReadOffset == len(d.curData) {
|
if d.curReadOffset == len(d.curData) {
|
||||||
fmt.Println("reading new block...")
|
|
||||||
err := d.readNextBlock()
|
err := d.readNextBlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return read, err
|
return read, err
|
||||||
@@ -176,7 +167,6 @@ func (d *DataReader) Read(p []byte) (int, error) {
|
|||||||
if d.curReadOffset < len(d.curData) {
|
if d.curReadOffset < len(d.curData) {
|
||||||
p[read] = d.curData[d.curReadOffset]
|
p[read] = d.curData[d.curReadOffset]
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("breaking out!")
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-9
@@ -3,16 +3,15 @@ package squashfs
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/CalebQ42/GoSquashfs/internal/inode"
|
"github.com/CalebQ42/GoSquashfs/internal/inode"
|
||||||
)
|
)
|
||||||
|
|
||||||
//FileReader provides a io.Reader interface for files within
|
//FileReader provides a io.Reader interface for files within a squashfs archive
|
||||||
type FileReader struct {
|
type FileReader struct {
|
||||||
r *Reader
|
r *Reader
|
||||||
data *DataReader
|
data *dataReader
|
||||||
fragmentData []byte
|
fragmentData []byte
|
||||||
fragged bool
|
fragged bool
|
||||||
fragOnly bool
|
fragOnly bool
|
||||||
@@ -49,21 +48,19 @@ func (r *Reader) ReadFile(location string) (*FileReader, error) {
|
|||||||
rdr.FileSize = int(fil.Init.Size)
|
rdr.FileSize = int(fil.Init.Size)
|
||||||
}
|
}
|
||||||
if rdr.fragged {
|
if rdr.fragged {
|
||||||
rdr.fragmentData, err = r.GetFragmentDataFromInode(in)
|
rdr.fragmentData, err = r.getFragmentDataFromInode(in)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !rdr.fragOnly {
|
if !rdr.fragOnly {
|
||||||
rdr.data, err = r.NewDataReaderFromInode(in)
|
rdr.data, err = r.newDataReaderFromInode(in)
|
||||||
}
|
}
|
||||||
return &rdr, nil
|
return &rdr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FileReader) Read(p []byte) (int, error) {
|
func (f *FileReader) Read(p []byte) (int, error) {
|
||||||
fmt.Println("reading!", len(p))
|
|
||||||
if f.fragOnly {
|
if f.fragOnly {
|
||||||
fmt.Println("HII")
|
|
||||||
n, err := bytes.NewBuffer(f.fragmentData[f.read:]).Read(p)
|
n, err := bytes.NewBuffer(f.fragmentData[f.read:]).Read(p)
|
||||||
f.read += n
|
f.read += n
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -75,7 +72,6 @@ func (f *FileReader) Read(p []byte) (int, error) {
|
|||||||
n, err := f.data.Read(p)
|
n, err := f.data.Read(p)
|
||||||
read += n
|
read += n
|
||||||
if f.fragged && err == io.EOF {
|
if f.fragged && err == io.EOF {
|
||||||
fmt.Println("Trying to read fragment AFTER main data")
|
|
||||||
n, err = bytes.NewBuffer(f.fragmentData).Read(p[read:])
|
n, err = bytes.NewBuffer(f.fragmentData).Read(p[read:])
|
||||||
read += n
|
read += n
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -84,6 +80,5 @@ func (f *FileReader) Read(p []byte) (int, error) {
|
|||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return read, err
|
return read, err
|
||||||
}
|
}
|
||||||
fmt.Println("read", n)
|
|
||||||
return read, nil
|
return read, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-5
@@ -3,7 +3,6 @@ package squashfs
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/CalebQ42/GoSquashfs/internal/inode"
|
"github.com/CalebQ42/GoSquashfs/internal/inode"
|
||||||
@@ -18,7 +17,7 @@ type FragmentEntry struct {
|
|||||||
|
|
||||||
//GetFragmentDataFromInode returns the fragment data for a given inode.
|
//GetFragmentDataFromInode returns the fragment data for a given inode.
|
||||||
//If the inode does not have a fragment, harmlessly returns an empty slice without an error.
|
//If the inode does not have a fragment, harmlessly returns an empty slice without an error.
|
||||||
func (r *Reader) GetFragmentDataFromInode(in *inode.Inode) ([]byte, error) {
|
func (r *Reader) getFragmentDataFromInode(in *inode.Inode) ([]byte, error) {
|
||||||
var size uint32
|
var size uint32
|
||||||
var fragIndex uint32
|
var fragIndex uint32
|
||||||
var fragOffset uint32
|
var fragOffset uint32
|
||||||
@@ -50,7 +49,7 @@ func (r *Reader) GetFragmentDataFromInode(in *inode.Inode) ([]byte, error) {
|
|||||||
return nil, errors.New("Inode type not supported")
|
return nil, errors.New("Inode type not supported")
|
||||||
}
|
}
|
||||||
//reading the fragment entry first
|
//reading the fragment entry first
|
||||||
fragEntryRdr, err := r.NewMetadataReader(int64(r.fragOffsets[int(fragIndex/512)]))
|
fragEntryRdr, err := r.newMetadataReader(int64(r.fragOffsets[int(fragIndex/512)]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -64,7 +63,7 @@ func (r *Reader) GetFragmentDataFromInode(in *inode.Inode) ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
//now reading the actual fragment
|
//now reading the actual fragment
|
||||||
dr, err := r.NewDataReader(int64(entry.Start), []uint32{entry.Size})
|
dr, err := r.newDataReader(int64(entry.Start), []uint32{entry.Size})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -77,6 +76,5 @@ func (r *Reader) GetFragmentDataFromInode(in *inode.Inode) ([]byte, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
fmt.Println("read fragment with size", len(tmp))
|
|
||||||
return tmp, nil
|
return tmp, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-9
@@ -14,7 +14,7 @@ type metadata struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//MetadataReader is a block reader for metadata. It will automatically read the next block, when it reaches the end of a block.
|
//MetadataReader is a block reader for metadata. It will automatically read the next block, when it reaches the end of a block.
|
||||||
type MetadataReader struct {
|
type metadataReader struct {
|
||||||
s *Reader
|
s *Reader
|
||||||
offset int64
|
offset int64
|
||||||
headers []*metadata
|
headers []*metadata
|
||||||
@@ -23,8 +23,8 @@ type MetadataReader struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//NewMetadataReader creates a new MetadataReader, beginning to read at the given offset. It will automatically cache the first block at the location.
|
//NewMetadataReader creates a new MetadataReader, beginning to read at the given offset. It will automatically cache the first block at the location.
|
||||||
func (s *Reader) NewMetadataReader(offset int64) (*MetadataReader, error) {
|
func (s *Reader) newMetadataReader(offset int64) (*metadataReader, error) {
|
||||||
var br MetadataReader
|
var br metadataReader
|
||||||
br.s = s
|
br.s = s
|
||||||
br.offset = offset
|
br.offset = offset
|
||||||
err := br.parseMetadata()
|
err := br.parseMetadata()
|
||||||
@@ -39,9 +39,9 @@ func (s *Reader) NewMetadataReader(offset int64) (*MetadataReader, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//NewMetadataReaderFromInodeRef creates a new MetadataReader with the offsets set by the given inode reference.
|
//NewMetadataReaderFromInodeRef creates a new MetadataReader with the offsets set by the given inode reference.
|
||||||
func (s *Reader) NewMetadataReaderFromInodeRef(ref uint64) (*MetadataReader, error) {
|
func (s *Reader) newMetadataReaderFromInodeRef(ref uint64) (*metadataReader, error) {
|
||||||
offset, metaOffset := processInodeRef(ref)
|
offset, metaOffset := processInodeRef(ref)
|
||||||
br, err := s.NewMetadataReader(int64(s.super.InodeTableStart + offset))
|
br, err := s.newMetadataReader(int64(s.super.InodeTableStart + offset))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ func (s *Reader) NewMetadataReaderFromInodeRef(ref uint64) (*MetadataReader, err
|
|||||||
return br, nil
|
return br, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (br *MetadataReader) parseMetadata() error {
|
func (br *metadataReader) parseMetadata() error {
|
||||||
var raw uint16
|
var raw uint16
|
||||||
err := binary.Read(io.NewSectionReader(br.s.r, br.offset, 2), binary.LittleEndian, &raw)
|
err := binary.Read(io.NewSectionReader(br.s.r, br.offset, 2), binary.LittleEndian, &raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -69,7 +69,7 @@ func (br *MetadataReader) parseMetadata() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (br *MetadataReader) readNextDataBlock() error {
|
func (br *metadataReader) readNextDataBlock() error {
|
||||||
meta := br.headers[len(br.headers)-1]
|
meta := br.headers[len(br.headers)-1]
|
||||||
r := io.NewSectionReader(br.s.r, br.offset, int64(meta.size))
|
r := io.NewSectionReader(br.s.r, br.offset, int64(meta.size))
|
||||||
if meta.compressed {
|
if meta.compressed {
|
||||||
@@ -92,7 +92,7 @@ func (br *MetadataReader) readNextDataBlock() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Read reads bytes into the given byte slice. Returns the amount of data read.
|
//Read reads bytes into the given byte slice. Returns the amount of data read.
|
||||||
func (br *MetadataReader) Read(p []byte) (int, error) {
|
func (br *metadataReader) Read(p []byte) (int, error) {
|
||||||
if br.readOffset+len(p) < len(br.data) {
|
if br.readOffset+len(p) < len(br.data) {
|
||||||
for i := 0; i < len(p); i++ {
|
for i := 0; i < len(p); i++ {
|
||||||
p[i] = br.data[br.readOffset+i]
|
p[i] = br.data[br.readOffset+i]
|
||||||
@@ -130,7 +130,7 @@ func (br *MetadataReader) Read(p []byte) (int, error) {
|
|||||||
//Seek will seek to the specified location (if possible). Seeking is relative to the uncompressed data.
|
//Seek will seek to the specified location (if possible). Seeking is relative to the uncompressed data.
|
||||||
//When io.SeekCurrent or io.SeekStart is set, if seeking would put the offset beyond the current cached data, it will try to read the next data blocks to accomodate. On a failure it will seek to the end of the data.
|
//When io.SeekCurrent or io.SeekStart is set, if seeking would put the offset beyond the current cached data, it will try to read the next data blocks to accomodate. On a failure it will seek to the end of the data.
|
||||||
//When io.SeekEnd is set, it wil seek reletive to the currently cached data.
|
//When io.SeekEnd is set, it wil seek reletive to the currently cached data.
|
||||||
func (br *MetadataReader) Seek(offset int64, whence int) (int64, error) {
|
func (br *metadataReader) Seek(offset int64, whence int) (int64, error) {
|
||||||
switch whence {
|
switch whence {
|
||||||
case io.SeekCurrent:
|
case io.SeekCurrent:
|
||||||
br.readOffset += int(offset)
|
br.readOffset += int(offset)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package squashfs
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
@@ -30,9 +29,9 @@ var (
|
|||||||
//TODO: Give a way to actually read files :P
|
//TODO: Give a way to actually read files :P
|
||||||
type Reader struct {
|
type Reader struct {
|
||||||
r io.ReaderAt
|
r io.ReaderAt
|
||||||
super Superblock
|
super superblock
|
||||||
flags SuperblockFlags
|
flags superblockFlags
|
||||||
decompressor Decompressor
|
decompressor decompressor
|
||||||
fragOffsets []uint64
|
fragOffsets []uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +49,7 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) {
|
|||||||
rdr.flags = rdr.super.GetFlags()
|
rdr.flags = rdr.super.GetFlags()
|
||||||
switch rdr.super.CompressionType {
|
switch rdr.super.CompressionType {
|
||||||
case gzipCompression:
|
case gzipCompression:
|
||||||
rdr.decompressor = &ZlibDecompressor{}
|
rdr.decompressor = &zlibDecompressor{}
|
||||||
default:
|
default:
|
||||||
return nil, ErrIncompatibleCompression
|
return nil, ErrIncompatibleCompression
|
||||||
}
|
}
|
||||||
@@ -65,7 +64,6 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) {
|
|||||||
tmp := make([]byte, 8)
|
tmp := make([]byte, 8)
|
||||||
_, err = r.ReadAt(tmp, offset)
|
_, err = r.ReadAt(tmp, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error while reading fragment block offsets")
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
rdr.fragOffsets = append(rdr.fragOffsets, binary.LittleEndian.Uint64(tmp))
|
rdr.fragOffsets = append(rdr.fragOffsets, binary.LittleEndian.Uint64(tmp))
|
||||||
@@ -76,9 +74,9 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//GetFilesList returns a list of ALL files in the squashfs, going down every folder.
|
//GetFilesList returns a list of ALL files in the squashfs, going down every folder.
|
||||||
//Paths that terminate in a folder end with /
|
//Folders end in /
|
||||||
func (r *Reader) GetFilesList() ([]string, error) {
|
func (r *Reader) GetFilesList() ([]string, error) {
|
||||||
inoderdr, err := r.NewMetadataReaderFromInodeRef(r.super.RootInodeRef)
|
inoderdr, err := r.newMetadataReaderFromInodeRef(r.super.RootInodeRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -95,20 +93,14 @@ func (r *Reader) GetFilesList() ([]string, error) {
|
|||||||
|
|
||||||
//readDir returns a list of all decendents of a given inode. Inode given MUST be a directory type.
|
//readDir returns a list of all decendents of a given inode. Inode given MUST be a directory type.
|
||||||
func (r *Reader) readDir(i *inode.Inode) (paths []string, err error) {
|
func (r *Reader) readDir(i *inode.Inode) (paths []string, err error) {
|
||||||
dir, err := r.ReadDirFromInode(i)
|
dir, err := r.readDirFromInode(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, entry := range dir.Entries {
|
for _, entry := range dir.Entries {
|
||||||
if entry.Init.Type == inode.BasicFileType {
|
|
||||||
in, _ := r.GetInodeFromEntry(&entry)
|
|
||||||
fil := in.Info.(inode.BasicFile)
|
|
||||||
fmt.Println("name:", entry.Name)
|
|
||||||
fmt.Println("frag index:", fil.Init.FragmentIndex, "frag offset:", fil.Init.FragmentOffset)
|
|
||||||
}
|
|
||||||
if entry.Init.Type == inode.BasicDirectoryType {
|
if entry.Init.Type == inode.BasicDirectoryType {
|
||||||
paths = append(paths)
|
paths = append(paths)
|
||||||
i, err = r.GetInodeFromEntry(&entry)
|
i, err = r.getInodeFromEntry(&entry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -128,12 +120,3 @@ func (r *Reader) readDir(i *inode.Inode) (paths []string, err error) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetFileStructure returns ALL folders and files contained in the squashfs. Folders end with a "/".
|
|
||||||
func (r *Reader) GetFileStructure() ([]string, error) {
|
|
||||||
in, err := r.GetInodeFromPath("")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return r.readDir(in)
|
|
||||||
}
|
|
||||||
|
|||||||
+4
-4
@@ -10,7 +10,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
//Superblock contains important information about a squashfs file. Located at the very front of the archive.
|
//Superblock contains important information about a squashfs file. Located at the very front of the archive.
|
||||||
type Superblock struct {
|
type superblock struct {
|
||||||
Magic uint32
|
Magic uint32
|
||||||
InodeCount uint32
|
InodeCount uint32
|
||||||
CreationTime uint32
|
CreationTime uint32
|
||||||
@@ -33,7 +33,7 @@ type Superblock struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//SuperblockFlags is the parsed version of Superblock.Flags
|
//SuperblockFlags is the parsed version of Superblock.Flags
|
||||||
type SuperblockFlags struct {
|
type superblockFlags struct {
|
||||||
UncompressedInodes bool
|
UncompressedInodes bool
|
||||||
UncompressedData bool
|
UncompressedData bool
|
||||||
Check bool
|
Check bool
|
||||||
@@ -49,8 +49,8 @@ type SuperblockFlags struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//GetFlags returns a SuperblockFlags for a given superblock.
|
//GetFlags returns a SuperblockFlags for a given superblock.
|
||||||
func (s *Superblock) GetFlags() SuperblockFlags {
|
func (s *superblock) GetFlags() superblockFlags {
|
||||||
return SuperblockFlags{
|
return superblockFlags{
|
||||||
UncompressedInodes: s.Flags&0x1 == 0x1,
|
UncompressedInodes: s.Flags&0x1 == 0x1,
|
||||||
UncompressedData: s.Flags&0x2 == 0x2,
|
UncompressedData: s.Flags&0x2 == 0x2,
|
||||||
Check: s.Flags&0x4 == 0x4,
|
Check: s.Flags&0x4 == 0x4,
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ func processInodeRef(inodeRef uint64) (tableOffset uint64, metaOffset uint64) {
|
|||||||
|
|
||||||
//ReadDirFromInode returns a fully populated directory.Directory from a given inode.Inode.
|
//ReadDirFromInode returns a fully populated directory.Directory from a given inode.Inode.
|
||||||
//If the given inode is not a directory it returns an error.
|
//If the given inode is not a directory it returns an error.
|
||||||
func (r *Reader) ReadDirFromInode(i *inode.Inode) (*directory.Directory, error) {
|
func (r *Reader) readDirFromInode(i *inode.Inode) (*directory.Directory, error) {
|
||||||
var offset uint32
|
var offset uint32
|
||||||
var metaOffset uint16
|
var metaOffset uint16
|
||||||
var size uint16
|
var size uint16
|
||||||
@@ -43,7 +43,7 @@ func (r *Reader) ReadDirFromInode(i *inode.Inode) (*directory.Directory, error)
|
|||||||
default:
|
default:
|
||||||
return nil, errors.New("Not a directory inode")
|
return nil, errors.New("Not a directory inode")
|
||||||
}
|
}
|
||||||
br, err := r.NewMetadataReader(int64(r.super.DirTableStart + uint64(offset)))
|
br, err := r.newMetadataReader(int64(r.super.DirTableStart + uint64(offset)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -59,8 +59,8 @@ func (r *Reader) ReadDirFromInode(i *inode.Inode) (*directory.Directory, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//GetInodeFromEntry returns the inode associated with a given directory.Entry
|
//GetInodeFromEntry returns the inode associated with a given directory.Entry
|
||||||
func (r *Reader) GetInodeFromEntry(en *directory.Entry) (*inode.Inode, error) {
|
func (r *Reader) getInodeFromEntry(en *directory.Entry) (*inode.Inode, error) {
|
||||||
br, err := r.NewMetadataReader(int64(r.super.InodeTableStart + uint64(en.Header.InodeOffset)))
|
br, err := r.newMetadataReader(int64(r.super.InodeTableStart + uint64(en.Header.InodeOffset)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@ func (r *Reader) GetInodeFromEntry(en *directory.Entry) (*inode.Inode, error) {
|
|||||||
func (r *Reader) GetInodeFromPath(path string) (*inode.Inode, error) {
|
func (r *Reader) GetInodeFromPath(path string) (*inode.Inode, error) {
|
||||||
path = strings.TrimSuffix(strings.TrimPrefix(path, "/"), "/")
|
path = strings.TrimSuffix(strings.TrimPrefix(path, "/"), "/")
|
||||||
pathDirs := strings.Split(path, "/")
|
pathDirs := strings.Split(path, "/")
|
||||||
rdr, err := r.NewMetadataReaderFromInodeRef(r.super.RootInodeRef)
|
rdr, err := r.newMetadataReaderFromInodeRef(r.super.RootInodeRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -95,20 +95,20 @@ func (r *Reader) GetInodeFromPath(path string) (*inode.Inode, error) {
|
|||||||
if curInodeDir.Type != inode.BasicDirectoryType && curInodeDir.Type != inode.ExtDirType {
|
if curInodeDir.Type != inode.BasicDirectoryType && curInodeDir.Type != inode.ExtDirType {
|
||||||
return nil, ErrNotFound
|
return nil, ErrNotFound
|
||||||
}
|
}
|
||||||
dir, err := r.ReadDirFromInode(curInodeDir)
|
dir, err := r.readDirFromInode(curInodeDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, entry := range dir.Entries {
|
for _, entry := range dir.Entries {
|
||||||
if entry.Name == pathDirs[depth] {
|
if entry.Name == pathDirs[depth] {
|
||||||
if depth == len(pathDirs)-1 {
|
if depth == len(pathDirs)-1 {
|
||||||
in, err := r.GetInodeFromEntry(&entry)
|
in, err := r.getInodeFromEntry(&entry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return in, nil
|
return in, nil
|
||||||
}
|
}
|
||||||
curInodeDir, err = r.GetInodeFromEntry(&entry)
|
curInodeDir, err = r.getInodeFromEntry(&entry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user