From 23ec7ea6dd004c979eace7013261386526ef9ac7 Mon Sep 17 00:00:00 2001 From: Caleb Gardner Date: Fri, 27 Nov 2020 00:36:21 -0600 Subject: [PATCH] First version of File interface. This will allow you to easily find and extract files. Extraction of whole folders coming next. (Maybe) --- file.go | 10 +++++++--- filereader.go | 4 +++- reader.go | 16 +++++++++++----- squash_test.go | 37 ++++++++++++++++++++++++------------- 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/file.go b/file.go index 6222105..3421bd0 100644 --- a/file.go +++ b/file.go @@ -32,6 +32,7 @@ type File struct { //get a File from a directory.entry func (r *Reader) newFileFromDirEntry(entry *directory.Entry) (fil *File, err error) { + fil = new(File) fil.in, err = r.getInodeFromEntry(entry) if err != nil { return nil, err @@ -39,12 +40,12 @@ func (r *Reader) newFileFromDirEntry(entry *directory.Entry) (fil *File, err err fil.Name = entry.Name fil.r = r fil.filType = fil.in.Type - return } //GetChildren returns a *squashfs.File slice of every direct child of the directory. If the File is not a directory, will return ErrNotDirectory func (f *File) GetChildren() (children []*File, err error) { + children = make([]*File, 0) if f.r == nil { return nil, ErrNotReading } @@ -62,7 +63,9 @@ func (f *File) GetChildren() (children []*File, err error) { return } fil.Parent = f - fil.Path = f.Path + "/" + f.Name + if f.Name != "" { + fil.Path = f.Path + "/" + f.Name + } children = append(children, fil) } return @@ -70,6 +73,7 @@ func (f *File) GetChildren() (children []*File, err error) { //GetChildrenRecursively returns ALL children. Goes down ALL folder paths. func (f *File) GetChildrenRecursively() (children []*File, err error) { + children = make([]*File, 0) if f.r == nil { return nil, ErrNotReading } @@ -104,7 +108,7 @@ func (f *File) IsDir() bool { } //Close frees up the memory held up by the underlying reader. Should NOT be called when writing. -//When reading, Close is safe to use, as any subsequent Read calls reinitialize the reader. +//When reading, Close is safe to use, but any subsequent Read calls resets to the beginning of the file. func (f *File) Close() error { if f.IsDir() { return ErrNotFile diff --git a/filereader.go b/filereader.go index 41be95c..bf07f2d 100644 --- a/filereader.go +++ b/filereader.go @@ -59,7 +59,9 @@ func (r *Reader) newFileReader(in *inode.Inode) (*fileReader, error) { //Close runs Close on the data reader and frees the fragmentdata func (f *fileReader) Close() error { - f.data.Close() + if f.data != nil { + f.data.Close() + } f.fragmentData = nil return nil } diff --git a/reader.go b/reader.go index 5363976..b4454e1 100644 --- a/reader.go +++ b/reader.go @@ -76,6 +76,7 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) { //GetRootFolder returns a squashfs.File that references the root directory of the squashfs archive. func (r *Reader) GetRootFolder() (root *File, err error) { + root = new(File) mr, err := r.newMetadataReaderFromInodeRef(r.super.RootInodeRef) if err != nil { return nil, err @@ -86,6 +87,7 @@ func (r *Reader) GetRootFolder() (root *File, err error) { } root.Path = "/" root.filType = root.in.Type + root.r = r return root, nil } @@ -158,7 +160,7 @@ func (r *Reader) FindAll(query func(*File) bool) (all []*File) { //GetFileAtPath will return the file at the given path. If the file cannot be found, will return nil. func (r *Reader) GetFileAtPath(path string) *File { - path = "/" + strings.TrimSuffix(strings.TrimPrefix(path, "/"), "/") + path = strings.TrimSuffix(strings.TrimPrefix(path, "/"), "/") pathDirs := strings.Split(path, "/") dir, err := r.GetRootFolder() if err != nil { @@ -172,15 +174,19 @@ func (r *Reader) GetFileAtPath(path string) *File { for _, child := range children { if child.Name == folder { dir = child - children, err = dir.GetChildren() - if err != nil { - return nil + if dir.IsDir() { + children, err = dir.GetChildren() + if err != nil { + return nil + } + } else { + children = make([]*File, 0) } break } } } - if dir.Path+"/"+dir.Name == path { + if dir.Path+"/"+dir.Name == "/"+path { return dir } return nil diff --git a/squash_test.go b/squash_test.go index b2f5b64..a9cecde 100644 --- a/squash_test.go +++ b/squash_test.go @@ -1,9 +1,11 @@ package squashfs import ( + "fmt" "io" "net/http" "os" + "strings" "testing" goappimage "github.com/CalebQ42/GoAppImage" @@ -27,7 +29,7 @@ func TestMain(t *testing.T) { if err != nil { t.Fatal(err) } - } else { + } else if err != nil { t.Fatal(err) } defer aiFil.Close() @@ -37,22 +39,31 @@ func TestMain(t *testing.T) { if err != nil { t.Fatal(err) } - extractionFil := "code-oss.desktop" - os.Remove(wd + "/testing/" + extractionFil) - desk, err := os.Create(wd + "/testing/" + extractionFil) - if err != nil { - t.Fatal(err) - } - ext := rdr.FindFile(func(fil *File) bool { - return fil.Name == extractionFil + rdr.FindAll(func(fil *File) bool { + return strings.HasSuffix(fil.Name, ".desktop") }) - if ext == nil { - t.Fatal("Cannot find file") - } - _, err = io.Copy(desk, ext) + fils, err := rdr.GetAllFiles() if err != nil { t.Fatal(err) } + for _, fil := range fils { + fmt.Println(fil.Path + "/" + fil.Name) + } + // extractionFil := "code-oss.desktop" + // os.Remove(wd + "/testing/" + extractionFil) + // desk, err := os.Create(wd + "/testing/" + extractionFil) + // if err != nil { + // t.Fatal(err) + // } + // ext := rdr.GetFileAtPath(extractionFil) + // if ext == nil { + // t.Fatal("Cannot find file") + // } + // defer ext.Close() + // _, err = io.Copy(desk, ext) + // if err != nil { + // t.Fatal(err) + // } t.Fatal("No problems here!") }