FILE EXTRACTION WORKS!
This commit is contained in:
+31
-16
@@ -12,6 +12,8 @@ import (
|
|||||||
var (
|
var (
|
||||||
//ErrInodeNotFile is given when giving an inode, but the function requires a file inode.
|
//ErrInodeNotFile is given when giving an inode, but the function requires a file inode.
|
||||||
ErrInodeNotFile = errors.New("Given inode is NOT a file type")
|
ErrInodeNotFile = errors.New("Given inode is NOT a file type")
|
||||||
|
//ErrInodeOnlyFragment is given when trying to make a DataReader from an inode, but the inode only had data in a fragment
|
||||||
|
ErrInodeOnlyFragment = errors.New("Given inode ONLY has fragment data")
|
||||||
)
|
)
|
||||||
|
|
||||||
//DataReader reads data from data blocks.
|
//DataReader reads data from data blocks.
|
||||||
@@ -34,8 +36,8 @@ 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 {
|
||||||
dbs.uncompressedSize = dbs.size
|
dbs.uncompressedSize = dbs.size
|
||||||
}
|
}
|
||||||
@@ -60,19 +62,32 @@ 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
|
||||||
switch i.Type {
|
switch i.Type {
|
||||||
case inode.BasicFileType:
|
case inode.BasicFileType:
|
||||||
fil := i.Info.(inode.BasicFile)
|
fil := i.Info.(inode.BasicFile)
|
||||||
|
if fil.Init.BlockStart == 0 {
|
||||||
|
return nil, ErrInodeOnlyFragment
|
||||||
|
}
|
||||||
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 {
|
||||||
|
rdr.blocks = rdr.blocks[:len(rdr.blocks)-1]
|
||||||
|
}
|
||||||
case inode.ExtFileType:
|
case inode.ExtFileType:
|
||||||
fil := i.Info.(inode.ExtendedFile)
|
fil := i.Info.(inode.ExtendedFile)
|
||||||
|
if fil.Init.BlockStart == 0 {
|
||||||
|
return nil, ErrInodeOnlyFragment
|
||||||
|
}
|
||||||
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 {
|
||||||
|
rdr.blocks = rdr.blocks[:len(rdr.blocks)-1]
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return nil, ErrInodeNotFile
|
return nil, ErrInodeNotFile
|
||||||
}
|
}
|
||||||
@@ -87,18 +102,21 @@ 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--
|
||||||
return errors.New("Ran out of blocks")
|
return io.EOF
|
||||||
}
|
}
|
||||||
err := d.readCurBlock()
|
err := d.readCurBlock()
|
||||||
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
|
||||||
}
|
}
|
||||||
@@ -106,22 +124,21 @@ func (d *DataReader) readCurBlock() error {
|
|||||||
d.curData = make([]byte, d.r.super.BlockSize)
|
d.curData = make([]byte, d.r.super.BlockSize)
|
||||||
d.blocks[d.curBlock].uncompressedSize = d.r.super.BlockSize
|
d.blocks[d.curBlock].uncompressedSize = d.r.super.BlockSize
|
||||||
d.blocks[d.curBlock].begOffset = d.offset
|
d.blocks[d.curBlock].begOffset = d.offset
|
||||||
fmt.Println("dat red")
|
|
||||||
fmt.Println(len(d.curData))
|
|
||||||
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))
|
||||||
d.curData = btys
|
d.curData = btys
|
||||||
d.blocks[d.curBlock].begOffset = d.offset
|
d.blocks[d.curBlock].begOffset = d.offset
|
||||||
d.offset += int64(d.blocks[d.curBlock].size)
|
d.offset += int64(d.blocks[d.curBlock].size)
|
||||||
fmt.Println("dat red")
|
|
||||||
fmt.Println(len(d.curData))
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
@@ -132,15 +149,12 @@ func (d *DataReader) readCurBlock() error {
|
|||||||
d.curData = buf.Bytes()
|
d.curData = buf.Bytes()
|
||||||
d.blocks[d.curBlock].begOffset = d.offset
|
d.blocks[d.curBlock].begOffset = d.offset
|
||||||
d.offset += int64(d.blocks[d.curBlock].size)
|
d.offset += int64(d.blocks[d.curBlock].size)
|
||||||
fmt.Println("dat red")
|
|
||||||
fmt.Println(len(d.curData))
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DataReader) Read(p []byte) (int, error) {
|
func (d *DataReader) Read(p []byte) (int, error) {
|
||||||
fmt.Println("dat")
|
|
||||||
fmt.Println(len(d.curData))
|
|
||||||
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]
|
||||||
}
|
}
|
||||||
@@ -148,20 +162,21 @@ func (d *DataReader) Read(p []byte) (int, error) {
|
|||||||
return len(p), nil
|
return len(p), nil
|
||||||
}
|
}
|
||||||
read := 0
|
read := 0
|
||||||
curRead := 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
|
||||||
}
|
}
|
||||||
curRead = 0
|
d.curReadOffset = 0
|
||||||
}
|
}
|
||||||
for ; read < len(p); read++ {
|
for ; read < len(p); read++ {
|
||||||
curRead++
|
d.curReadOffset++
|
||||||
if d.curReadOffset+curRead < len(d.curData) {
|
if d.curReadOffset < len(d.curData) {
|
||||||
p[read] = d.curData[d.curReadOffset+curRead]
|
p[read] = d.curData[d.curReadOffset]
|
||||||
} else {
|
} else {
|
||||||
|
fmt.Println("breaking out!")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-18
@@ -36,43 +36,46 @@ func (r *Reader) ReadFile(location string) (*FileReader, error) {
|
|||||||
if in.Type != inode.BasicFileType && in.Type != inode.ExtFileType {
|
if in.Type != inode.BasicFileType && in.Type != inode.ExtFileType {
|
||||||
return nil, ErrPathIsNotFile
|
return nil, ErrPathIsNotFile
|
||||||
}
|
}
|
||||||
var offset uint32
|
|
||||||
var sizes []uint32
|
|
||||||
switch in.Type {
|
switch in.Type {
|
||||||
case inode.BasicFileType:
|
case inode.BasicFileType:
|
||||||
rdr.fragged = in.Info.(inode.BasicFile).Fragmented
|
fil := in.Info.(inode.BasicFile)
|
||||||
rdr.fragOnly = in.Info.(inode.BasicFile).Init.BlockStart == 0
|
rdr.fragged = fil.Fragmented
|
||||||
rdr.FileSize = int(in.Info.(inode.BasicFile).Init.Size)
|
rdr.fragOnly = fil.Init.BlockStart == 0
|
||||||
offset = in.Info.(inode.BasicFile).Init.BlockStart
|
rdr.FileSize = int(fil.Init.Size)
|
||||||
sizes = in.Info.(inode.BasicFile).BlockSizes
|
|
||||||
case inode.ExtFileType:
|
case inode.ExtFileType:
|
||||||
rdr.fragged = in.Info.(inode.ExtendedFile).Fragmented
|
fil := in.Info.(inode.ExtendedFile)
|
||||||
rdr.fragOnly = in.Info.(inode.ExtendedFile).Init.BlockStart == 0
|
rdr.fragged = fil.Fragmented
|
||||||
rdr.FileSize = int(in.Info.(inode.ExtendedFile).Init.Size)
|
rdr.fragOnly = fil.Init.BlockStart == 0
|
||||||
offset = in.Info.(inode.ExtendedFile).Init.BlockStart
|
rdr.FileSize = int(fil.Init.Size)
|
||||||
sizes = in.Info.(inode.ExtendedFile).BlockSizes
|
|
||||||
}
|
}
|
||||||
fmt.Println("HIIII")
|
|
||||||
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.fragged {
|
if !rdr.fragOnly {
|
||||||
rdr.data, err = r.NewDataReader(int64(offset), sizes[:len(sizes)-1])
|
rdr.data, err = r.NewDataReaderFromInode(in)
|
||||||
} else {
|
|
||||||
rdr.data, err = r.NewDataReader(int64(offset), sizes)
|
|
||||||
}
|
}
|
||||||
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!")
|
fmt.Println("reading!", len(p))
|
||||||
|
if f.fragOnly {
|
||||||
|
fmt.Println("HII")
|
||||||
|
n, err := bytes.NewBuffer(f.fragmentData[f.read:]).Read(p)
|
||||||
|
f.read += n
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
var read int
|
var read int
|
||||||
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 {
|
||||||
@@ -81,5 +84,6 @@ 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
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -49,8 +49,6 @@ func (r *Reader) GetFragmentDataFromInode(in *inode.Inode) ([]byte, error) {
|
|||||||
} else {
|
} else {
|
||||||
return nil, errors.New("Inode type not supported")
|
return nil, errors.New("Inode type not supported")
|
||||||
}
|
}
|
||||||
fmt.Println(fragIndex, fragOffset, size)
|
|
||||||
fmt.Println("fragment index", fragIndex)
|
|
||||||
//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 {
|
||||||
@@ -79,5 +77,6 @@ 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
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -13,7 +13,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
downloadURL = "https://github.com/zilti/code-oss.AppImage/releases/download/continuous/Code_OSS-x86_64.AppImage"
|
downloadURL = "https://github.com/zilti/code-oss.AppImage/releases/download/continuous/Code_OSS-x86_64.AppImage"
|
||||||
appImageName = "Code_OSS.AppImage"
|
appImageName = "Code_OSS.AppImage"
|
||||||
squashfsName = "Code_OSS.Squashfs"
|
squashfsName = "testing.squashfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(t *testing.T) {
|
func TestMain(t *testing.T) {
|
||||||
@@ -38,7 +38,7 @@ func TestMain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
//testing code to print out the directory structure
|
//testing code to print out the directory structure
|
||||||
// rdr.GetFileStructure()
|
// rdr.GetFileStructure()
|
||||||
extractionFil := "code-oss.desktop"
|
extractionFil := "Proton-5.9-GE-8-ST.tar.gz"
|
||||||
os.Remove(wd + "/testing/" + extractionFil)
|
os.Remove(wd + "/testing/" + extractionFil)
|
||||||
desk, err := os.Create(wd + "/testing/" + extractionFil)
|
desk, err := os.Create(wd + "/testing/" + extractionFil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -48,7 +48,8 @@ func TestMain(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
n, err := io.Copy(desk, ext)
|
fmt.Println("Size!", ext.FileSize)
|
||||||
|
n, err := io.CopyBuffer(desk, ext, make([]byte, rdr.super.BlockSize/2))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Read", n)
|
fmt.Println("Read", n)
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
Reference in New Issue
Block a user