FILE EXTRACTION WORKS!

This commit is contained in:
Caleb Gardner
2020-11-25 04:26:48 -06:00
parent af36f9b9aa
commit f0f32a2445
4 changed files with 58 additions and 39 deletions
+31 -16
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)