From 5761ad59cf907be0c660f4726bddba7460aa9901 Mon Sep 17 00:00:00 2001 From: Caleb Gardner Date: Mon, 23 Nov 2020 16:50:00 -0600 Subject: [PATCH] Renamed BlockReader to MetadataReader (more correct) SOME work on fragments (not working still...) --- README.md | 5 +++-- filereader.go | 17 +++++++++++++++++ fragment.go | 12 +++++++++--- go.mod | 6 +++++- go.sum | 11 +++++++++++ blockreader.go => metadatareader.go | 20 +++++++++----------- reader.go | 16 +++++++++++++++- squash_test.go | 8 +++++--- utils.go | 9 ++++++--- 9 files changed, 80 insertions(+), 24 deletions(-) create mode 100644 filereader.go rename blockreader.go => metadatareader.go (86%) diff --git a/README.md b/README.md index fc85bd2..ea3487c 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Thanks also to [distri's squashfs library](https://github.com/distr1/distri/tree # Not Working (Yet). Roughly in order. -* Figure out fragments +* Figure out fragments (I can't seem to make them work ATM) * Extracting files * from inodes. * from path. @@ -30,4 +30,5 @@ Thanks also to [distri's squashfs library](https://github.com/distr1/distri/tree # Where I'm at. -* Reading fragments does not seem to be working right now \ No newline at end of file +* 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? \ No newline at end of file diff --git a/filereader.go b/filereader.go new file mode 100644 index 0000000..95d084c --- /dev/null +++ b/filereader.go @@ -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) { + +} diff --git a/fragment.go b/fragment.go index 2d28f04..012a5db 100644 --- a/fragment.go +++ b/fragment.go @@ -1,6 +1,7 @@ package squashfs import ( + "bytes" "encoding/binary" "errors" "fmt" @@ -9,6 +10,7 @@ import ( "github.com/CalebQ42/GoSquashfs/internal/inode" ) +//FragmentEntry is an entry in the fragment table type FragmentEntry struct { Start uint64 Size uint32 @@ -51,8 +53,7 @@ func (r *Reader) GetFragmentDataFromInode(in *inode.Inode) ([]byte, error) { } fmt.Println("fragment index", fragIndex) //reading the fragment entry first - fragBlockIndex := int(fragIndex / 512) - fragEntryRdr, err := r.NewBlockReader(int64(r.fragOffsets[fragBlockIndex])) + fragEntryRdr, err := r.NewMetadataReader(int64(r.fragOffsets[int(fragIndex/512)])) if err != nil { return nil, err } @@ -79,5 +80,10 @@ func (r *Reader) GetFragmentDataFromInode(in *inode.Inode) ([]byte, error) { if err != nil { 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 } diff --git a/go.mod b/go.mod index 64e11a4..6852f3c 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,8 @@ module github.com/CalebQ42/GoSquashfs 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 +) diff --git a/go.sum b/go.sum index d557baf..0d51b8c 100644 --- a/go.sum +++ b/go.sum @@ -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/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.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/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 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= go.lsp.dev/uri v0.3.0 h1:KcZJmh6nFIBeJzTugn5JTU6OOyG0lDOo3R9KwTxTYbo= 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/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= 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/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 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/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-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 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/blockreader.go b/metadatareader.go similarity index 86% rename from blockreader.go rename to metadatareader.go index 75ad9b0..cc33ed2 100644 --- a/blockreader.go +++ b/metadatareader.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/binary" "errors" - "fmt" "io" ) @@ -14,7 +13,7 @@ type metadata struct { compressed bool } -type BlockReader struct { +type MetadataReader struct { s *Reader offset int64 headers []*metadata @@ -22,8 +21,8 @@ type BlockReader struct { readOffset int } -func (s *Reader) NewBlockReader(offset int64) (*BlockReader, error) { - var br BlockReader +func (s *Reader) NewMetadataReader(offset int64) (*MetadataReader, error) { + var br MetadataReader br.s = s br.offset = offset err := br.parseMetadata() @@ -37,9 +36,9 @@ func (s *Reader) NewBlockReader(offset int64) (*BlockReader, error) { return &br, nil } -func (s *Reader) NewBlockReaderFromInodeRef(ref uint64) (*BlockReader, error) { +func (s *Reader) NewMetadataReaderFromInodeRef(ref uint64) (*MetadataReader, error) { 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 { return nil, err } @@ -50,7 +49,7 @@ func (s *Reader) NewBlockReaderFromInodeRef(ref uint64) (*BlockReader, error) { return br, nil } -func (br *BlockReader) parseMetadata() error { +func (br *MetadataReader) parseMetadata() error { var raw uint16 err := binary.Read(io.NewSectionReader(br.s.r, br.offset, 2), binary.LittleEndian, &raw) if err != nil { @@ -67,8 +66,7 @@ func (br *BlockReader) parseMetadata() error { return nil } -func (br *BlockReader) readNextDataBlock() error { - fmt.Println("reading new block") +func (br *MetadataReader) readNextDataBlock() error { meta := br.headers[len(br.headers)-1] r := io.NewSectionReader(br.s.r, br.offset, int64(meta.size)) if meta.compressed { @@ -90,7 +88,7 @@ func (br *BlockReader) readNextDataBlock() error { 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) { for i := 0; i < len(p); 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). //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. -func (br *BlockReader) Seek(offset int64, whence int) (int64, error) { +func (br *MetadataReader) Seek(offset int64, whence int) (int64, error) { switch whence { case io.SeekCurrent: br.readOffset += int(offset) diff --git a/reader.go b/reader.go index e97b599..606b63d 100644 --- a/reader.go +++ b/reader.go @@ -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. //Paths that terminate in a folder end with / func (r *Reader) GetFilesList() ([]string, error) { - inoderdr, err := r.NewBlockReaderFromInodeRef(r.super.RootInodeRef) + inoderdr, err := r.NewMetadataReaderFromInodeRef(r.super.RootInodeRef) if err != nil { return nil, err } @@ -100,6 +100,12 @@ func (r *Reader) readDir(i *inode.Inode) (paths []string, err error) { return } 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 { paths = append(paths) i, err = r.GetInodeFromEntry(&entry) @@ -122,3 +128,11 @@ func (r *Reader) readDir(i *inode.Inode) (paths []string, err error) { } return } + +func (r *Reader) GetFileStructure() ([]string, error) { + in, err := r.GetInodeFromPath("") + if err != nil { + return nil, err + } + return r.readDir(in) +} diff --git a/squash_test.go b/squash_test.go index 28743ca..0391799 100644 --- a/squash_test.go +++ b/squash_test.go @@ -35,12 +35,14 @@ func TestMain(t *testing.T) { if err != nil { t.Fatal(err) } - i, err := rdr.GetInodeFromPath("code-oss.desktop") + rdr.GetFileStructure() + extractionFil := ".DirIcon" + i, err := rdr.GetInodeFromPath(extractionFil) if err != nil { t.Fatal(err) } - os.Remove(wd + "/testing/code-oss.desktop") - desk, err := os.Create(wd + "/testing/code-oss.desktop") + os.Remove(wd + "/testing/" + extractionFil) + desk, err := os.Create(wd + "/testing/" + extractionFil) if err != nil { t.Fatal(err) } diff --git a/utils.go b/utils.go index e1770e9..f78e428 100644 --- a/utils.go +++ b/utils.go @@ -43,7 +43,7 @@ func (r *Reader) ReadDirFromInode(i *inode.Inode) (*directory.Directory, error) default: 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 { 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 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 { 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) { path = strings.TrimSuffix(strings.TrimPrefix(path, "/"), "/") pathDirs := strings.Split(path, "/") - rdr, err := r.NewBlockReaderFromInodeRef(r.super.RootInodeRef) + rdr, err := r.NewMetadataReaderFromInodeRef(r.super.RootInodeRef) if err != nil { return nil, err } @@ -88,6 +88,9 @@ func (r *Reader) GetInodeFromPath(path string) (*inode.Inode, error) { if err != nil { return nil, err } + if path == "" { + return curInodeDir, nil + } for depth := 0; depth < len(pathDirs); depth++ { if curInodeDir.Type != inode.BasicDirectoryType && curInodeDir.Type != inode.ExtDirType { return nil, ErrNotFound