Working on file reading (Not working right now)
This commit is contained in:
+41
-3
@@ -3,7 +3,15 @@ package squashfs
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/CalebQ42/GoSquashfs/internal/inode"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
//ErrInodeNotFile is given when giving an inode, but the function requires a file inode.
|
||||||
|
ErrInodeNotFile = errors.New("Given inode is NOT a file type")
|
||||||
)
|
)
|
||||||
|
|
||||||
//DataReader reads data from data blocks.
|
//DataReader reads data from data blocks.
|
||||||
@@ -24,8 +32,8 @@ type DataBlock struct {
|
|||||||
uncompressedSize uint32
|
uncompressedSize uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
//NewDataBlockSize creates a new squashfs.datablock from a given size.
|
//NewDataBlock creates a new squashfs.datablock from a given size.
|
||||||
func NewDataBlockSize(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 {
|
||||||
@@ -40,7 +48,7 @@ func (r *Reader) NewDataReader(offset int64, sizes []uint32) (*DataReader, error
|
|||||||
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, NewDataBlockSize(size))
|
dr.blocks = append(dr.blocks, NewDataBlock(size))
|
||||||
}
|
}
|
||||||
err := dr.readCurBlock()
|
err := dr.readCurBlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -49,6 +57,32 @@ func (r *Reader) NewDataReader(offset int64, sizes []uint32) (*DataReader, error
|
|||||||
return &dr, nil
|
return &dr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//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) {
|
||||||
|
var rdr DataReader
|
||||||
|
switch i.Type {
|
||||||
|
case inode.BasicFileType:
|
||||||
|
fil := i.Info.(inode.BasicFile)
|
||||||
|
rdr.offset = int64(fil.Init.BlockStart)
|
||||||
|
for _, sizes := range fil.BlockSizes {
|
||||||
|
rdr.blocks = append(rdr.blocks, NewDataBlock(sizes))
|
||||||
|
}
|
||||||
|
case inode.ExtFileType:
|
||||||
|
fil := i.Info.(inode.ExtendedFile)
|
||||||
|
rdr.offset = int64(fil.Init.BlockStart)
|
||||||
|
for _, sizes := range fil.BlockSizes {
|
||||||
|
rdr.blocks = append(rdr.blocks, NewDataBlock(sizes))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, ErrInodeNotFile
|
||||||
|
}
|
||||||
|
err := rdr.readCurBlock()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
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) {
|
||||||
@@ -94,10 +128,14 @@ 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) {
|
||||||
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]
|
||||||
|
|||||||
+71
-3
@@ -1,17 +1,85 @@
|
|||||||
package squashfs
|
package squashfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/CalebQ42/GoSquashfs/internal/inode"
|
||||||
|
)
|
||||||
|
|
||||||
|
//FileReader provides a io.Reader interface for files within
|
||||||
type FileReader struct {
|
type FileReader struct {
|
||||||
r *Reader
|
r *Reader
|
||||||
data *DataReader
|
data *DataReader
|
||||||
fragmentData []byte
|
fragmentData []byte
|
||||||
|
fragged bool
|
||||||
|
fragOnly bool
|
||||||
|
read int
|
||||||
|
FileSize int //FileSize is the total size of the given file
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Yes
|
var (
|
||||||
|
//ErrPathIsNotFile returns when trying to read from a file, but the given path is NOT a file.
|
||||||
|
ErrPathIsNotFile = errors.New("The given path is not a file")
|
||||||
|
)
|
||||||
|
|
||||||
|
//ReadFile provides a squashfs.FileReader for the file at the given location.
|
||||||
func (r *Reader) ReadFile(location string) (*FileReader, error) {
|
func (r *Reader) ReadFile(location string) (*FileReader, error) {
|
||||||
|
var rdr FileReader
|
||||||
|
rdr.r = r
|
||||||
|
in, err := r.GetInodeFromPath(location)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if in.Type != inode.BasicFileType && in.Type != inode.ExtFileType {
|
||||||
|
return nil, ErrPathIsNotFile
|
||||||
|
}
|
||||||
|
var offset uint32
|
||||||
|
var sizes []uint32
|
||||||
|
switch in.Type {
|
||||||
|
case inode.BasicFileType:
|
||||||
|
rdr.fragged = in.Info.(inode.BasicFile).Fragmented
|
||||||
|
rdr.fragOnly = in.Info.(inode.BasicFile).Init.BlockStart == 0
|
||||||
|
rdr.FileSize = int(in.Info.(inode.BasicFile).Init.Size)
|
||||||
|
offset = in.Info.(inode.BasicFile).Init.BlockStart
|
||||||
|
sizes = in.Info.(inode.BasicFile).BlockSizes
|
||||||
|
case inode.ExtFileType:
|
||||||
|
rdr.fragged = in.Info.(inode.ExtendedFile).Fragmented
|
||||||
|
rdr.fragOnly = in.Info.(inode.ExtendedFile).Init.BlockStart == 0
|
||||||
|
rdr.FileSize = int(in.Info.(inode.ExtendedFile).Init.Size)
|
||||||
|
offset = in.Info.(inode.ExtendedFile).Init.BlockStart
|
||||||
|
sizes = in.Info.(inode.ExtendedFile).BlockSizes
|
||||||
|
}
|
||||||
|
fmt.Println("HIIII")
|
||||||
|
if rdr.fragged {
|
||||||
|
rdr.fragmentData, err = r.GetFragmentDataFromInode(in)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rdr.fragged {
|
||||||
|
rdr.data, err = r.NewDataReader(int64(offset), sizes[:len(sizes)-1])
|
||||||
|
} else {
|
||||||
|
rdr.data, err = r.NewDataReader(int64(offset), sizes)
|
||||||
|
}
|
||||||
|
return &rdr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FileReader) Read(p []byte) (int, error) {
|
func (f *FileReader) Read(p []byte) (int, error) {
|
||||||
|
fmt.Println("reading!")
|
||||||
|
var read int
|
||||||
|
n, err := f.data.Read(p)
|
||||||
|
read += n
|
||||||
|
if f.fragged && err == io.EOF {
|
||||||
|
n, err = bytes.NewBuffer(f.fragmentData).Read(p[read:])
|
||||||
|
read += n
|
||||||
|
if err != nil {
|
||||||
|
return read, err
|
||||||
|
}
|
||||||
|
} else if err != nil {
|
||||||
|
return read, err
|
||||||
|
}
|
||||||
|
return read, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-8
@@ -1,7 +1,6 @@
|
|||||||
package squashfs
|
package squashfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -35,7 +34,6 @@ func (r *Reader) GetFragmentDataFromInode(in *inode.Inode) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
fragIndex = bf.Init.FragmentIndex
|
fragIndex = bf.Init.FragmentIndex
|
||||||
fragOffset = bf.Init.FragmentOffset
|
fragOffset = bf.Init.FragmentOffset
|
||||||
fmt.Println(fragIndex, fragOffset, size)
|
|
||||||
} else if in.Type == inode.ExtFileType {
|
} else if in.Type == inode.ExtFileType {
|
||||||
bf := in.Info.(inode.ExtendedFile)
|
bf := in.Info.(inode.ExtendedFile)
|
||||||
if !bf.Fragmented {
|
if !bf.Fragmented {
|
||||||
@@ -51,6 +49,7 @@ 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)
|
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)]))
|
||||||
@@ -80,10 +79,5 @@ func (r *Reader) GetFragmentDataFromInode(in *inode.Inode) ([]byte, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dataRdr := bytes.NewBuffer(tmp)
|
return tmp, nil
|
||||||
dta, err := r.decompressor.Decompress(dataRdr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return dta, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-8
@@ -1,6 +1,7 @@
|
|||||||
package squashfs
|
package squashfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@@ -35,23 +36,21 @@ func TestMain(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
rdr.GetFileStructure()
|
//testing code to print out the directory structure
|
||||||
extractionFil := ".DirIcon"
|
// rdr.GetFileStructure()
|
||||||
i, err := rdr.GetInodeFromPath(extractionFil)
|
extractionFil := "code-oss.desktop"
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
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 {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
btys, err := rdr.GetFragmentDataFromInode(i)
|
ext, err := rdr.ReadFile(extractionFil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
_, err = desk.Write(btys)
|
n, err := io.Copy(desk, ext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("Read", n)
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
t.Fatal("No problems here!")
|
t.Fatal("No problems here!")
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ func (r *Reader) GetInodeFromEntry(en *directory.Entry) (*inode.Inode, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//GetInodeFromPath returns the inode at the given path, relative to root.
|
//GetInodeFromPath returns the inode at the given path, relative to root.
|
||||||
//The given path can start or without "/".
|
//The given path can start with or without "/"
|
||||||
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, "/")
|
||||||
|
|||||||
Reference in New Issue
Block a user