Restructure for 1.16 io/fs interface
This commit is contained in:
@@ -0,0 +1,126 @@
|
|||||||
|
package squashfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/CalebQ42/squashfs/internal/directory"
|
||||||
|
"github.com/CalebQ42/squashfs/internal/inode"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DirEntry struct {
|
||||||
|
en *directory.Entry
|
||||||
|
parent *FS
|
||||||
|
r *Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Reader) newDirEntry(en *directory.Entry, parent *FS) *DirEntry {
|
||||||
|
return &DirEntry{
|
||||||
|
en: en,
|
||||||
|
parent: parent,
|
||||||
|
r: r,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d DirEntry) Name() string {
|
||||||
|
return d.en.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d DirEntry) IsDir() bool {
|
||||||
|
return d.en.Type == inode.DirType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d DirEntry) Type() fs.FileMode {
|
||||||
|
switch d.en.Type {
|
||||||
|
case inode.DirType:
|
||||||
|
return fs.ModeDir
|
||||||
|
case inode.SymType:
|
||||||
|
return fs.ModeSymlink
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d DirEntry) Info() (fs.FileInfo, error) {
|
||||||
|
in, err := d.r.getInodeFromEntry(d.en)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &FileInfo{
|
||||||
|
name: d.en.Name,
|
||||||
|
i: in,
|
||||||
|
parent: d.parent,
|
||||||
|
r: d.r,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetInodeFromEntry returns the inode associated with a given directory.Entry
|
||||||
|
func (r *Reader) getInodeFromEntry(en *directory.Entry) (*inode.Inode, error) {
|
||||||
|
br, err := r.newMetadataReader(int64(r.super.InodeTableStart + uint64(en.InodeOffset)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = br.Seek(int64(en.InodeBlockOffset), io.SeekStart)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
i, err := inode.ProcessInode(br, r.super.BlockSize)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return i, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileInfo struct {
|
||||||
|
i *inode.Inode
|
||||||
|
parent *FS
|
||||||
|
r *Reader
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FileInfo) Name() string {
|
||||||
|
return f.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FileInfo) Size() int64 {
|
||||||
|
switch f.i.Type {
|
||||||
|
case inode.FileType:
|
||||||
|
return int64(f.i.Info.(inode.File).Size)
|
||||||
|
case inode.ExtFileType:
|
||||||
|
return int64(f.i.Info.(inode.ExtFile).Size)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FileInfo) Mode() fs.FileMode {
|
||||||
|
mode := fs.FileMode(f.i.Permissions)
|
||||||
|
switch f.i.Type {
|
||||||
|
case inode.DirType | inode.ExtDirType:
|
||||||
|
return mode | fs.ModeDir
|
||||||
|
case inode.ExtDirType:
|
||||||
|
return mode | fs.ModeDir
|
||||||
|
case inode.SymType:
|
||||||
|
return mode | fs.ModeSymlink
|
||||||
|
case inode.ExtSymType:
|
||||||
|
return mode | fs.ModeSymlink
|
||||||
|
}
|
||||||
|
return mode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FileInfo) ModTime() time.Time {
|
||||||
|
return time.Unix(int64(f.i.ModifiedTime), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FileInfo) IsDir() bool {
|
||||||
|
return f.i.Type == inode.DirType || f.i.Type == inode.ExtDirType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FileInfo) Sys() interface{} {
|
||||||
|
return &File{
|
||||||
|
name: f.name,
|
||||||
|
i: f.i,
|
||||||
|
r: f.r,
|
||||||
|
parent: f.parent,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
package squashfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
|
|
||||||
|
"github.com/CalebQ42/squashfs/internal/directory"
|
||||||
|
"github.com/CalebQ42/squashfs/internal/inode"
|
||||||
|
)
|
||||||
|
|
||||||
|
type File struct {
|
||||||
|
i *inode.Inode
|
||||||
|
parent *FS
|
||||||
|
r *Reader
|
||||||
|
reader *fileReader
|
||||||
|
name string
|
||||||
|
dirsRead int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FileInfo) File() (file *File, err error) {
|
||||||
|
file = &File{
|
||||||
|
name: f.name,
|
||||||
|
r: f.r,
|
||||||
|
parent: f.parent,
|
||||||
|
i: f.i,
|
||||||
|
}
|
||||||
|
file.reader, err = f.r.newFileReader(f.i)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Reader) newFileFromDirEntry(en *directory.Entry, parent *FS) (file *File, err error) {
|
||||||
|
file = &File{
|
||||||
|
name: en.Name,
|
||||||
|
r: r,
|
||||||
|
parent: parent,
|
||||||
|
}
|
||||||
|
file.i, err = r.getInodeFromEntry(en)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
file.reader, err = r.newFileReader(file.i)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *File) Stat() (fs.FileInfo, error) {
|
||||||
|
return &FileInfo{
|
||||||
|
i: f.i,
|
||||||
|
name: f.name,
|
||||||
|
parent: f.parent,
|
||||||
|
r: f.r,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *File) Read(p []byte) (int, error) {
|
||||||
|
if f.i.Type == inode.FileType || f.i.Type == inode.ExtFileType {
|
||||||
|
if f.reader == nil {
|
||||||
|
return 0, fs.ErrClosed
|
||||||
|
}
|
||||||
|
return f.reader.Read(p)
|
||||||
|
}
|
||||||
|
return 0, errors.New("Can only read files")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *File) WriteTo(w io.Writer) (int64, error) {
|
||||||
|
if f.i.Type == inode.FileType || f.i.Type == inode.ExtFileType {
|
||||||
|
if f.reader == nil {
|
||||||
|
return 0, fs.ErrClosed
|
||||||
|
}
|
||||||
|
return f.reader.WriteTo(w)
|
||||||
|
}
|
||||||
|
return 0, errors.New("Can only read files")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *File) Close() error {
|
||||||
|
f.reader = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *File) ReadDir(n int) ([]fs.DirEntry, error) {
|
||||||
|
if !f.IsDir() {
|
||||||
|
return nil, errors.New("File is not a directory")
|
||||||
|
}
|
||||||
|
ffs, err := f.FS()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var beg, end int
|
||||||
|
if n <= 0 {
|
||||||
|
beg, end = 0, len(ffs.entries)
|
||||||
|
} else {
|
||||||
|
beg, end = f.dirsRead, f.dirsRead+n
|
||||||
|
if end > len(ffs.entries) {
|
||||||
|
end = len(ffs.entries)
|
||||||
|
err = io.EOF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out := make([]fs.DirEntry, end-beg)
|
||||||
|
for i, ent := range ffs.entries[beg:end] {
|
||||||
|
out[i] = f.r.newDirEntry(ent, ffs)
|
||||||
|
}
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f File) FS() (*FS, error) {
|
||||||
|
if !f.IsDir() {
|
||||||
|
return nil, errors.New("File is not a directory")
|
||||||
|
}
|
||||||
|
ents, err := f.r.readDirFromInode(f.i)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &FS{
|
||||||
|
entries: ents,
|
||||||
|
parent: f.parent,
|
||||||
|
r: f.r,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f File) IsDir() bool {
|
||||||
|
return f.i.Type == inode.DirType || f.i.Type == inode.ExtDirType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f File) Path()
|
||||||
|
|
||||||
|
//ReadDirFromInode returns a fully populated Directory from a given Inode.
|
||||||
|
//If the given inode is not a directory it returns an error.
|
||||||
|
func (r *Reader) readDirFromInode(i *inode.Inode) ([]*directory.Entry, error) {
|
||||||
|
var offset uint32
|
||||||
|
var metaOffset uint16
|
||||||
|
var size uint32
|
||||||
|
switch i.Type {
|
||||||
|
case inode.DirType:
|
||||||
|
offset = i.Info.(inode.Dir).DirectoryIndex
|
||||||
|
metaOffset = i.Info.(inode.Dir).DirectoryOffset
|
||||||
|
size = uint32(i.Info.(inode.Dir).DirectorySize)
|
||||||
|
case inode.ExtDirType:
|
||||||
|
offset = i.Info.(inode.ExtDir).DirectoryIndex
|
||||||
|
metaOffset = i.Info.(inode.ExtDir).DirectoryOffset
|
||||||
|
size = i.Info.(inode.ExtDir).DirectorySize
|
||||||
|
default:
|
||||||
|
return nil, errors.New("Not a directory inode")
|
||||||
|
}
|
||||||
|
br, err := r.newMetadataReader(int64(r.super.DirTableStart + uint64(offset)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = br.Seek(int64(metaOffset), io.SeekStart)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ents, err := directory.NewDirectory(br, size)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ents, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package squashfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/fs"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/CalebQ42/squashfs/internal/directory"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FS struct {
|
||||||
|
r *Reader
|
||||||
|
parent *FS
|
||||||
|
entries []*directory.Entry
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FS) Open(name string) (fs.File, error) {
|
||||||
|
if !fs.ValidPath(name) {
|
||||||
|
return nil, &fs.PathError{
|
||||||
|
Op: "open",
|
||||||
|
Path: name,
|
||||||
|
Err: fs.ErrInvalid,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
name = path.Clean(strings.TrimPrefix(name, "/"))
|
||||||
|
split := strings.Split(name, "/")
|
||||||
|
for i := 0; i < len(f.entries); i++ {
|
||||||
|
if match, _ := path.Match(split[0], f.entries[i].Name); match {
|
||||||
|
if len(split) == 1 {
|
||||||
|
return f.r.newFileFromDirEntry(f.entries[i], &f)
|
||||||
|
}
|
||||||
|
sub, err := f.Sub(split[0])
|
||||||
|
if err != nil {
|
||||||
|
if pathErr, ok := err.(*fs.PathError); ok {
|
||||||
|
pathErr.Op = "open"
|
||||||
|
pathErr.Path = name
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, &fs.PathError{
|
||||||
|
Op: "open",
|
||||||
|
Path: name,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fil, err := sub.Open(strings.Join(split[1:], "/"))
|
||||||
|
if err != nil {
|
||||||
|
if pathErr, ok := err.(*fs.PathError); ok {
|
||||||
|
if pathErr.Err == fs.ErrNotExist {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pathErr.Op = "open"
|
||||||
|
pathErr.Path = name
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, &fs.PathError{
|
||||||
|
Op: "open",
|
||||||
|
Path: name,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, &fs.PathError{
|
||||||
|
Op: "open",
|
||||||
|
Path: name,
|
||||||
|
Err: fs.ErrNotExist,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FS) Glob(pattern string) ([]string, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FS) ReadDir(name string) ([]DirEntry, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FS) ReadFile(name string) ([]byte, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FS) Stat(name string) ([]byte, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FS) Sub(dir string) (fs.FS, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
@@ -23,38 +23,33 @@ type EntryRaw struct {
|
|||||||
|
|
||||||
//Entry is an entry in a directory.
|
//Entry is an entry in a directory.
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
*Header
|
|
||||||
Name string
|
Name string
|
||||||
EntryRaw
|
InodeOffset uint32
|
||||||
|
InodeBlockOffset int16
|
||||||
|
Type uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
//NewEntry creates a new directory entry
|
//NewEntry creates a new directory entry
|
||||||
func NewEntry(rdr io.Reader) (Entry, error) {
|
func NewEntry(rdr io.Reader) (*Entry, error) {
|
||||||
var entry Entry
|
var raw EntryRaw
|
||||||
err := binary.Read(rdr, binary.LittleEndian, &entry.EntryRaw)
|
err := binary.Read(rdr, binary.LittleEndian, &raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Entry{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tmp := make([]byte, entry.EntryRaw.NameSize+1)
|
tmp := make([]byte, raw.NameSize+1)
|
||||||
err = binary.Read(rdr, binary.LittleEndian, &tmp)
|
err = binary.Read(rdr, binary.LittleEndian, &tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Entry{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
entry.Name = string(tmp)
|
return &Entry{
|
||||||
return entry, err
|
InodeBlockOffset: raw.InodeOffset,
|
||||||
}
|
Type: raw.Type,
|
||||||
|
Name: string(tmp),
|
||||||
//Directory is an entry in the directory table of a squashfs.
|
}, nil
|
||||||
//Will only have multiple headers if there are more then 256 entries
|
|
||||||
type Directory struct {
|
|
||||||
Headers []Header
|
|
||||||
Entries []Entry
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//NewDirectory reads the directory from rdr
|
//NewDirectory reads the directory from rdr
|
||||||
func NewDirectory(base io.Reader, size uint32) (*Directory, error) {
|
func NewDirectory(base io.Reader, size uint32) (entries []*Entry, err error) {
|
||||||
var dir Directory
|
|
||||||
var err error
|
|
||||||
tmp := make([]byte, size)
|
tmp := make([]byte, size)
|
||||||
base.Read(tmp)
|
base.Read(tmp)
|
||||||
rdr := bytes.NewBuffer(tmp)
|
rdr := bytes.NewBuffer(tmp)
|
||||||
@@ -62,6 +57,7 @@ func NewDirectory(base io.Reader, size uint32) (*Directory, error) {
|
|||||||
var hdr Header
|
var hdr Header
|
||||||
err = binary.Read(rdr, binary.LittleEndian, &hdr)
|
err = binary.Read(rdr, binary.LittleEndian, &hdr)
|
||||||
if err == io.ErrUnexpectedEOF {
|
if err == io.ErrUnexpectedEOF {
|
||||||
|
err = nil
|
||||||
break
|
break
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -71,24 +67,21 @@ func NewDirectory(base io.Reader, size uint32) (*Directory, error) {
|
|||||||
if hdr.Count%256 > 0 {
|
if hdr.Count%256 > 0 {
|
||||||
headers++
|
headers++
|
||||||
}
|
}
|
||||||
dir.Headers = append(dir.Headers, hdr)
|
|
||||||
for i := uint32(0); i < hdr.Count; i++ {
|
for i := uint32(0); i < hdr.Count; i++ {
|
||||||
if i != 0 && i%256 == 0 {
|
if i != 0 && i%256 == 0 {
|
||||||
var newHdr Header
|
err = binary.Read(rdr, binary.LittleEndian, &hdr)
|
||||||
err = binary.Read(rdr, binary.LittleEndian, &newHdr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dir.Headers = append(dir.Headers, newHdr)
|
|
||||||
}
|
}
|
||||||
var ent Entry
|
var ent *Entry
|
||||||
ent, err = NewEntry(rdr)
|
ent, err = NewEntry(rdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ent.Header = &dir.Headers[len(dir.Headers)-1]
|
ent.InodeOffset = hdr.InodeOffset
|
||||||
dir.Entries = append(dir.Entries, ent)
|
entries = append(entries, ent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &dir, nil
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/CalebQ42/squashfs/internal/compression"
|
"github.com/CalebQ42/squashfs/internal/compression"
|
||||||
"github.com/CalebQ42/squashfs/internal/inode"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -159,117 +158,117 @@ func (r *Reader) ModTime() time.Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//ExtractTo tries to extract ALL files to the given path. This is the same as getting the root folder and extracting that.
|
//ExtractTo tries to extract ALL files to the given path. This is the same as getting the root folder and extracting that.
|
||||||
func (r *Reader) ExtractTo(path string) []error {
|
// func (r *Reader) ExtractTo(path string) []error {
|
||||||
if r.root == nil {
|
// if r.root == nil {
|
||||||
_, err := r.GetRootFolder()
|
// _, err := r.GetRootFolder()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return []error{err}
|
// return []error{err}
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return r.root.ExtractTo(path)
|
// return r.root.ExtractTo(path)
|
||||||
}
|
// }
|
||||||
|
|
||||||
//GetRootFolder returns a squashfs.File that references the root directory of the squashfs archive.
|
//GetRootFolder returns a squashfs.File that references the root directory of the squashfs archive.
|
||||||
func (r *Reader) GetRootFolder() (*File, error) {
|
func (r *Reader) GetRootFolder() (*File, error) {
|
||||||
if r.root != nil {
|
if r.root != nil {
|
||||||
return r.root, nil
|
return r.root, nil
|
||||||
}
|
}
|
||||||
mr, err := r.newMetadataReaderFromInodeRef(r.super.RootInodeRef)
|
// mr, err := r.newMetadataReaderFromInodeRef(r.super.RootInodeRef)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
var root File
|
var root File
|
||||||
root.in, err = inode.ProcessInode(mr, r.super.BlockSize)
|
// root.in, err = inode.ProcessInode(mr, r.super.BlockSize)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
root.dir = "/"
|
// root.dir = "/"
|
||||||
root.filType = root.in.Type
|
// root.filType = root.in.Type
|
||||||
root.r = r
|
// root.r = r
|
||||||
r.root = &root
|
r.root = &root
|
||||||
return r.root, nil
|
return r.root, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetAllFiles returns a slice of ALL files and folders contained in the squashfs.
|
//GetAllFiles returns a slice of ALL files and folders contained in the squashfs.
|
||||||
func (r *Reader) GetAllFiles() (fils []*File, err error) {
|
// func (r *Reader) GetAllFiles() (fils []*File, err error) {
|
||||||
if r.root == nil {
|
// if r.root == nil {
|
||||||
_, err := r.GetRootFolder()
|
// _, err := r.GetRootFolder()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return r.root.GetChildrenRecursively()
|
// return r.root.GetChildrenRecursively()
|
||||||
}
|
// }
|
||||||
|
|
||||||
//FindFile returns the first file (in the same order as Reader.GetAllFiles) that the given function returns true for. Returns nil if nothing is found.
|
//FindFile returns the first file (in the same order as Reader.GetAllFiles) that the given function returns true for. Returns nil if nothing is found.
|
||||||
func (r *Reader) FindFile(query func(*File) bool) *File {
|
// func (r *Reader) FindFile(query func(*File) bool) *File {
|
||||||
if r.root == nil {
|
// if r.root == nil {
|
||||||
_, err := r.GetRootFolder()
|
// _, err := r.GetRootFolder()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
fils, err := r.root.GetChildren()
|
// fils, err := r.root.GetChildren()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
var childrenDirs []*File
|
// var childrenDirs []*File
|
||||||
for _, fil := range fils {
|
// for _, fil := range fils {
|
||||||
if query(fil) {
|
// if query(fil) {
|
||||||
return fil
|
// return fil
|
||||||
}
|
// }
|
||||||
if fil.IsDir() {
|
// if fil.IsDir() {
|
||||||
childrenDirs = append(childrenDirs, fil)
|
// childrenDirs = append(childrenDirs, fil)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
for len(childrenDirs) != 0 {
|
// for len(childrenDirs) != 0 {
|
||||||
var tmp []*File
|
// var tmp []*File
|
||||||
for _, dirs := range childrenDirs {
|
// for _, dirs := range childrenDirs {
|
||||||
chil, err := dirs.GetChildren()
|
// chil, err := dirs.GetChildren()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
for _, child := range chil {
|
// for _, child := range chil {
|
||||||
if query(child) {
|
// if query(child) {
|
||||||
return child
|
// return child
|
||||||
}
|
// }
|
||||||
if child.IsDir() {
|
// if child.IsDir() {
|
||||||
tmp = append(tmp, child)
|
// tmp = append(tmp, child)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
childrenDirs = tmp
|
// childrenDirs = tmp
|
||||||
}
|
// }
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
//FindAll returns all files where the given function returns true.
|
//FindAll returns all files where the given function returns true.
|
||||||
func (r *Reader) FindAll(query func(*File) bool) (all []*File) {
|
// func (r *Reader) FindAll(query func(*File) bool) (all []*File) {
|
||||||
if r.root == nil {
|
// if r.root == nil {
|
||||||
_, err := r.GetRootFolder()
|
// _, err := r.GetRootFolder()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
fils, err := r.root.GetChildrenRecursively()
|
// fils, err := r.root.GetChildrenRecursively()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
for _, fil := range fils {
|
// for _, fil := range fils {
|
||||||
if query(fil) {
|
// if query(fil) {
|
||||||
all = append(all, fil)
|
// all = append(all, fil)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
//GetFileAtPath will return the file at the given path. If the file cannot be found, will return nil.
|
//GetFileAtPath will return the file at the given path. If the file cannot be found, will return nil.
|
||||||
func (r *Reader) GetFileAtPath(filepath string) *File {
|
// func (r *Reader) GetFileAtPath(filepath string) *File {
|
||||||
if r.root == nil {
|
// if r.root == nil {
|
||||||
_, err := r.GetRootFolder()
|
// _, err := r.GetRootFolder()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return r.root.GetFileAtPath(filepath)
|
// return r.root.GetFileAtPath(filepath)
|
||||||
}
|
// }
|
||||||
|
|||||||
+21
-21
@@ -34,18 +34,18 @@ func TestSquashfs(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
fmt.Println("stuff", rdr.super.CompressionType)
|
fmt.Println("stuff", rdr.super.CompressionType)
|
||||||
fil := rdr.GetFileAtPath("*.desktop")
|
// fil := rdr.GetFileAtPath("*.desktop")
|
||||||
if fil == nil {
|
// if fil == nil {
|
||||||
t.Fatal("Can't find desktop fil")
|
// t.Fatal("Can't find desktop fil")
|
||||||
}
|
// }
|
||||||
errs := fil.ExtractTo(wd + "/testing")
|
// errs := fil.ExtractTo(wd + "/testing")
|
||||||
if len(errs) > 0 {
|
// if len(errs) > 0 {
|
||||||
t.Fatal(errs)
|
// t.Fatal(errs)
|
||||||
}
|
// }
|
||||||
errs = rdr.ExtractTo(wd + "/testing/" + squashfsName + ".d")
|
// errs = rdr.ExtractTo(wd + "/testing/" + squashfsName + ".d")
|
||||||
if len(errs) > 0 {
|
// if len(errs) > 0 {
|
||||||
t.Fatal(errs)
|
// t.Fatal(errs)
|
||||||
}
|
// }
|
||||||
t.Fatal("No Problems")
|
t.Fatal("No Problems")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ func BenchmarkDragRace(b *testing.B) {
|
|||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
stat, _ := aiFil.Stat()
|
// stat, _ := aiFil.Stat()
|
||||||
ai := goappimage.NewAppImage(wd + "/testing/" + appImageName)
|
ai := goappimage.NewAppImage(wd + "/testing/" + appImageName)
|
||||||
os.RemoveAll(wd + "/testing/unsquashFirefox")
|
os.RemoveAll(wd + "/testing/unsquashFirefox")
|
||||||
os.RemoveAll(wd + "/testing/firefox")
|
os.RemoveAll(wd + "/testing/firefox")
|
||||||
@@ -143,14 +143,14 @@ func BenchmarkDragRace(b *testing.B) {
|
|||||||
}
|
}
|
||||||
unsquashTime := time.Since(start)
|
unsquashTime := time.Since(start)
|
||||||
start = time.Now()
|
start = time.Now()
|
||||||
rdr, err := NewSquashfsReader(io.NewSectionReader(aiFil, ai.Offset, stat.Size()-ai.Offset))
|
// rdr, err := NewSquashfsReader(io.NewSectionReader(aiFil, ai.Offset, stat.Size()-ai.Offset))
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
b.Fatal(err)
|
// b.Fatal(err)
|
||||||
}
|
// }
|
||||||
errs := rdr.ExtractTo(wd + "/testing/firefox")
|
// errs := rdr.ExtractTo(wd + "/testing/firefox")
|
||||||
if len(errs) > 0 {
|
// if len(errs) > 0 {
|
||||||
b.Fatal(errs)
|
// b.Fatal(errs)
|
||||||
}
|
// }
|
||||||
libTime := time.Since(start)
|
libTime := time.Since(start)
|
||||||
b.Log("Unsqushfs:", unsquashTime.Round(time.Millisecond))
|
b.Log("Unsqushfs:", unsquashTime.Round(time.Millisecond))
|
||||||
b.Log("Library:", libTime.Round(time.Millisecond))
|
b.Log("Library:", libTime.Round(time.Millisecond))
|
||||||
|
|||||||
Reference in New Issue
Block a user