diff --git a/README.md b/README.md index f9276e3..d1e8893 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,15 @@ Thanks also to [distri's squashfs library](https://github.com/distr1/distri/tree * Give a list of files * In string & io.FileStat (?) form +* Figure out fragments * Extracting files * from inodes. * from path. * from file info. * Reading the UID, GUID, Xatt, Compression Options, Export, and Fragment tables. * Implement other compression types (Should be relatively easy) -* Squashing \ No newline at end of file +* Squashing + +# Where I'm at. + +* I CAN READ THE ENTIRE DIRECTORY!!!!! (This is a big ol' step) \ No newline at end of file diff --git a/blockreader.go b/blockreader.go index 476402c..6a3ca8c 100644 --- a/blockreader.go +++ b/blockreader.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/binary" "errors" - "fmt" "io" ) @@ -90,7 +89,6 @@ func (br *BlockReader) readNextDataBlock() error { } func (br *BlockReader) Read(p []byte) (int, error) { - fmt.Println("reading", len(p), "bytes") if br.readOffset+len(p) < len(br.data) { for i := 0; i < len(p); i++ { p[i] = br.data[br.readOffset+i] @@ -111,7 +109,6 @@ func (br *BlockReader) Read(p []byte) (int, error) { return read, err } for ; read < len(p); read++ { - // fmt.Println("Reading...") if br.readOffset+read < len(br.data) { p[read] = br.data[br.readOffset+read] } else { diff --git a/internal/directory/directory.go b/internal/directory/directory.go index e86146d..03f0842 100644 --- a/internal/directory/directory.go +++ b/internal/directory/directory.go @@ -23,8 +23,9 @@ type EntryInit struct { //Entry is an entry in a directory. type Entry struct { - Init EntryInit - Name string + Init EntryInit + Name string + Header *Header } //NewEntry creates a new directory entry @@ -85,6 +86,7 @@ func NewDirectory(base io.Reader, size uint16) (*Directory, error) { if err != nil { return nil, err } + ent.Header = &dir.Headers[len(dir.Headers)-1] dir.Entries = append(dir.Entries, ent) } } diff --git a/internal/inode/inode.go b/internal/inode/inode.go index 389d3cf..ad6cced 100644 --- a/internal/inode/inode.go +++ b/internal/inode/inode.go @@ -60,11 +60,11 @@ type ExtendedDirectory struct { } //NewExtendedDirectory creates a new ExtendedDirectory -func NewExtendedDirectory(rdr io.Reader) (*ExtendedDirectory, error) { +func NewExtendedDirectory(rdr io.Reader) (ExtendedDirectory, error) { var inode ExtendedDirectory err := binary.Read(rdr, binary.LittleEndian, &inode.Init) if err != nil { - return &inode, err + return inode, err } if inode.Init.IndexCount > 0 { inode.Indexes = make([]DirectoryIndex, inode.Init.IndexCount) @@ -72,11 +72,11 @@ func NewExtendedDirectory(rdr io.Reader) (*ExtendedDirectory, error) { inode.Indexes[i], err = NewDirectoryIndex(rdr) if err != nil { fmt.Println("Error while reading Directory Index ", i) - return &inode, err + return inode, err } } } - return &inode, err + return inode, err } //DirectoryIndexInit holds the values that can be easily decoded @@ -116,22 +116,24 @@ type BasicFileInit struct { type BasicFile struct { Init BasicFileInit BlockSizes []uint32 + Fragmented bool } //NewBasicFile creates a new BasicFile -func NewBasicFile(rdr io.Reader, blockSize uint32) (*BasicFile, error) { +func NewBasicFile(rdr io.Reader, blockSize uint32) (BasicFile, error) { var inode BasicFile err := binary.Read(rdr, binary.LittleEndian, &inode.Init) if err != nil { - return &inode, err + return inode, err } + inode.Fragmented = inode.Init.FragmentIndex != 0xFFFFFFFF blocks := inode.Init.Size / blockSize if inode.Init.Size%blockSize > 0 { blocks++ } inode.BlockSizes = make([]uint32, blocks, blocks) err = binary.Read(rdr, binary.LittleEndian, &inode.BlockSizes) - return &inode, err + return inode, err } //ExtendedFileInit is the information that can be directly decoded diff --git a/squashfsreader.go b/squashfsreader.go index a41c457..54e7180 100644 --- a/squashfsreader.go +++ b/squashfsreader.go @@ -47,6 +47,35 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) { return &rdr, nil } +func (r *Reader) readDir(i *inode.Inode) (paths []string, err error) { + dir, err := r.ReadDirFromInode(*i) + if err != nil { + return + } + for _, entry := range dir.Entries { + if entry.Init.Type == inode.BasicDirectoryType { + paths = append(paths) + i, err = r.GetInodeFromEntry(&entry) + if err != nil { + return + } + var subPaths []string + subPaths, err = r.readDir(i) + if err != nil { + return + } + for pathI := range subPaths { + subPaths[pathI] = entry.Name + "/" + subPaths[pathI] + } + paths = append(paths, entry.Name+"/") + paths = append(paths, subPaths...) + } else { + paths = append(paths, entry.Name) + } + } + return +} + func (r *Reader) readDirTable() error { inoderdr, err := r.NewBlockReaderFromInodeRef(r.super.RootInodeRef) if err != nil { @@ -56,12 +85,12 @@ func (r *Reader) readDirTable() error { if err != nil { return err } - dir, err := r.ReadDirFromInode(i) + paths, err := r.readDir(&i) if err != nil { return err } - for _, entry := range dir.Entries { - fmt.Println(entry.Name) + for _, path := range paths { + fmt.Println(path) } return nil } diff --git a/utils.go b/utils.go index 7589152..c44d48e 100644 --- a/utils.go +++ b/utils.go @@ -49,3 +49,19 @@ func (r *Reader) ReadDirFromInode(i inode.Inode) (*directory.Directory, error) { } return dir, nil } + +func (r *Reader) GetInodeFromEntry(en *directory.Entry) (*inode.Inode, error) { + br, err := r.NewBlockReader(int64(r.super.InodeTableStart + uint64(en.Header.InodeOffset))) + if err != nil { + return nil, err + } + _, err = br.Seek(int64(en.Init.Offset), 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 +}