Renamed BlockReader to MetadataReader (more correct)

SOME work on fragments (not working still...)
This commit is contained in:
Caleb Gardner
2020-11-23 16:50:00 -06:00
parent ae2cc5ab54
commit 5761ad59cf
9 changed files with 80 additions and 24 deletions
+3 -2
View File
@@ -17,7 +17,7 @@ Thanks also to [distri's squashfs library](https://github.com/distr1/distri/tree
# Not Working (Yet). Roughly in order. # Not Working (Yet). Roughly in order.
* Figure out fragments * Figure out fragments (I can't seem to make them work ATM)
* Extracting files * Extracting files
* from inodes. * from inodes.
* from path. * from path.
@@ -30,4 +30,5 @@ Thanks also to [distri's squashfs library](https://github.com/distr1/distri/tree
# Where I'm at. # Where I'm at.
* Reading fragments does not seem to be working right now * I've given up on fragments for now and will work on reading files.
* Once I have basic file reading working, I'll have a first pre-release available. No fragment support, but shouldn't be too hard... right?
+17
View File
@@ -0,0 +1,17 @@
package squashfs
type FileReader struct {
r *Reader
data *DataReader
fragmentData []byte
}
//TODO: Yes
func (r *Reader) ReadFile(location string) (*FileReader, error) {
}
func (f *FileReader) Read(p []byte) (int, error) {
}
+9 -3
View File
@@ -1,6 +1,7 @@
package squashfs package squashfs
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
@@ -9,6 +10,7 @@ import (
"github.com/CalebQ42/GoSquashfs/internal/inode" "github.com/CalebQ42/GoSquashfs/internal/inode"
) )
//FragmentEntry is an entry in the fragment table
type FragmentEntry struct { type FragmentEntry struct {
Start uint64 Start uint64
Size uint32 Size uint32
@@ -51,8 +53,7 @@ func (r *Reader) GetFragmentDataFromInode(in *inode.Inode) ([]byte, error) {
} }
fmt.Println("fragment index", fragIndex) fmt.Println("fragment index", fragIndex)
//reading the fragment entry first //reading the fragment entry first
fragBlockIndex := int(fragIndex / 512) fragEntryRdr, err := r.NewMetadataReader(int64(r.fragOffsets[int(fragIndex/512)]))
fragEntryRdr, err := r.NewBlockReader(int64(r.fragOffsets[fragBlockIndex]))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -79,5 +80,10 @@ func (r *Reader) GetFragmentDataFromInode(in *inode.Inode) ([]byte, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return tmp, nil dataRdr := bytes.NewBuffer(tmp)
dta, err := r.decompressor.Decompress(dataRdr)
if err != nil {
return nil, err
}
return dta, nil
} }
+5 -1
View File
@@ -2,4 +2,8 @@ module github.com/CalebQ42/GoSquashfs
go 1.15 go 1.15
require github.com/CalebQ42/GoAppImage v0.4.0 require (
github.com/CalebQ42/GoAppImage v0.4.0
github.com/google/go-cmp v0.5.3 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
)
+11
View File
@@ -7,6 +7,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
@@ -27,13 +31,20 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
go.lsp.dev/uri v0.3.0 h1:KcZJmh6nFIBeJzTugn5JTU6OOyG0lDOo3R9KwTxTYbo= go.lsp.dev/uri v0.3.0 h1:KcZJmh6nFIBeJzTugn5JTU6OOyG0lDOo3R9KwTxTYbo=
go.lsp.dev/uri v0.3.0/go.mod h1:P5sbO1IQR+qySTWOCnhnK7phBx+W3zbLqSMDJNTw88I= go.lsp.dev/uri v0.3.0/go.mod h1:P5sbO1IQR+qySTWOCnhnK7phBx+W3zbLqSMDJNTw88I=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+9 -11
View File
@@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt"
"io" "io"
) )
@@ -14,7 +13,7 @@ type metadata struct {
compressed bool compressed bool
} }
type BlockReader struct { type MetadataReader struct {
s *Reader s *Reader
offset int64 offset int64
headers []*metadata headers []*metadata
@@ -22,8 +21,8 @@ type BlockReader struct {
readOffset int readOffset int
} }
func (s *Reader) NewBlockReader(offset int64) (*BlockReader, error) { func (s *Reader) NewMetadataReader(offset int64) (*MetadataReader, error) {
var br BlockReader var br MetadataReader
br.s = s br.s = s
br.offset = offset br.offset = offset
err := br.parseMetadata() err := br.parseMetadata()
@@ -37,9 +36,9 @@ func (s *Reader) NewBlockReader(offset int64) (*BlockReader, error) {
return &br, nil return &br, nil
} }
func (s *Reader) NewBlockReaderFromInodeRef(ref uint64) (*BlockReader, error) { func (s *Reader) NewMetadataReaderFromInodeRef(ref uint64) (*MetadataReader, error) {
offset, metaOffset := processInodeRef(ref) offset, metaOffset := processInodeRef(ref)
br, err := s.NewBlockReader(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
} }
@@ -50,7 +49,7 @@ func (s *Reader) NewBlockReaderFromInodeRef(ref uint64) (*BlockReader, error) {
return br, nil return br, nil
} }
func (br *BlockReader) 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 {
@@ -67,8 +66,7 @@ func (br *BlockReader) parseMetadata() error {
return nil return nil
} }
func (br *BlockReader) readNextDataBlock() error { func (br *MetadataReader) readNextDataBlock() error {
fmt.Println("reading new block")
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 {
@@ -90,7 +88,7 @@ func (br *BlockReader) readNextDataBlock() error {
return nil return nil
} }
func (br *BlockReader) 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]
@@ -128,7 +126,7 @@ func (br *BlockReader) Read(p []byte) (int, error) {
//Seek will seek to the specified location (if possible). //Seek will seek to the specified location (if possible).
//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 *BlockReader) 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)
+15 -1
View File
@@ -78,7 +78,7 @@ 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 / //Paths that terminate in a folder end with /
func (r *Reader) GetFilesList() ([]string, error) { func (r *Reader) GetFilesList() ([]string, error) {
inoderdr, err := r.NewBlockReaderFromInodeRef(r.super.RootInodeRef) inoderdr, err := r.NewMetadataReaderFromInodeRef(r.super.RootInodeRef)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -100,6 +100,12 @@ func (r *Reader) readDir(i *inode.Inode) (paths []string, err error) {
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)
@@ -122,3 +128,11 @@ func (r *Reader) readDir(i *inode.Inode) (paths []string, err error) {
} }
return return
} }
func (r *Reader) GetFileStructure() ([]string, error) {
in, err := r.GetInodeFromPath("")
if err != nil {
return nil, err
}
return r.readDir(in)
}
+5 -3
View File
@@ -35,12 +35,14 @@ func TestMain(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
i, err := rdr.GetInodeFromPath("code-oss.desktop") rdr.GetFileStructure()
extractionFil := ".DirIcon"
i, err := rdr.GetInodeFromPath(extractionFil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
os.Remove(wd + "/testing/code-oss.desktop") os.Remove(wd + "/testing/" + extractionFil)
desk, err := os.Create(wd + "/testing/code-oss.desktop") desk, err := os.Create(wd + "/testing/" + extractionFil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
+6 -3
View File
@@ -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.NewBlockReader(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
} }
@@ -60,7 +60,7 @@ 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.NewBlockReader(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.NewBlockReaderFromInodeRef(r.super.RootInodeRef) rdr, err := r.NewMetadataReaderFromInodeRef(r.super.RootInodeRef)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -88,6 +88,9 @@ func (r *Reader) GetInodeFromPath(path string) (*inode.Inode, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if path == "" {
return curInodeDir, nil
}
for depth := 0; depth < len(pathDirs); depth++ { for depth := 0; depth < len(pathDirs); depth++ {
if curInodeDir.Type != inode.BasicDirectoryType && curInodeDir.Type != inode.ExtDirType { if curInodeDir.Type != inode.BasicDirectoryType && curInodeDir.Type != inode.ExtDirType {
return nil, ErrNotFound return nil, ErrNotFound