Files
squashfs/reader_inode.go
T
Caleb Gardner 16ef5838c3 Move changes from exp2 to main
This is largely a move to simplify a lot of the readers
Also further breaks out functions.
2022-05-10 01:12:13 -05:00

135 lines
3.8 KiB
Go

package squashfs
import (
"errors"
"io"
"github.com/CalebQ42/squashfs/internal/data"
"github.com/CalebQ42/squashfs/internal/directory"
"github.com/CalebQ42/squashfs/internal/inode"
"github.com/CalebQ42/squashfs/internal/metadata"
"github.com/CalebQ42/squashfs/internal/toreader"
)
func (r Reader) inodeFromRef(ref uint64) (i inode.Inode, err error) {
offset, meta := (ref>>16)+r.s.InodeTableStart, ref&0xFFFF
rdr, err := metadata.NewReader(toreader.NewReader(r.r, int64(offset)), r.d)
if err != nil {
return
}
_, err = rdr.Read(make([]byte, meta))
if err != nil {
return
}
return inode.Read(rdr, r.s.BlockSize)
}
func (r Reader) inodeFromDir(e directory.Entry) (i inode.Inode, err error) {
rdr, err := metadata.NewReader(toreader.NewReader(r.r, int64(uint64(e.BlockStart)+r.s.InodeTableStart)), r.d)
if err != nil {
return
}
_, err = rdr.Read(make([]byte, e.Offset))
if err != nil {
return
}
return inode.Read(rdr, r.s.BlockSize)
}
func (r Reader) getData(i inode.Inode) (io.Reader, error) {
var fragOffset uint64
var blockOffset uint32
var blockSizes []uint32
var fragInd uint32
if i.Type == inode.Fil {
fragOffset = uint64(i.Data.(inode.File).Offset)
blockOffset = i.Data.(inode.File).BlockStart
blockSizes = i.Data.(inode.File).BlockSizes
fragInd = i.Data.(inode.File).FragInd
} else if i.Type == inode.EFil {
fragOffset = uint64(i.Data.(inode.EFile).Offset)
blockOffset = i.Data.(inode.EFile).BlockStart
blockSizes = i.Data.(inode.EFile).BlockSizes
fragInd = i.Data.(inode.EFile).FragInd
} else {
return nil, errors.New("getData called on non-file type")
}
rdr, err := data.NewReader(toreader.NewReader(r.r, int64(blockOffset)), r.d, blockSizes, r.s.BlockSize)
if err != nil {
return nil, err
}
if fragInd != 0xFFFFFFFF {
var fragRdr io.Reader
fragRdr, err = r.fragReader(fragInd)
if err != nil {
return nil, err
}
_, err = fragRdr.Read(make([]byte, fragOffset))
if err != nil {
return nil, err
}
rdr.AddFragment(fragRdr)
}
return rdr, nil
}
func (r Reader) getFullReader(i inode.Inode) (rdr *data.FullReader, err error) {
var fragOffset uint64
var blockOffset uint32
var blockSizes []uint32
var fragInd uint32
if i.Type == inode.Fil {
fragOffset = uint64(i.Data.(inode.File).Offset)
blockOffset = i.Data.(inode.File).BlockStart
blockSizes = i.Data.(inode.File).BlockSizes
fragInd = i.Data.(inode.File).FragInd
} else if i.Type == inode.EFil {
fragOffset = uint64(i.Data.(inode.EFile).Offset)
blockOffset = i.Data.(inode.EFile).BlockStart
blockSizes = i.Data.(inode.EFile).BlockSizes
fragInd = i.Data.(inode.EFile).FragInd
} else {
return nil, errors.New("getData called on non-file type")
}
rdr = data.NewFullReader(r.r, uint64(blockOffset), r.d, blockSizes, r.s.BlockSize)
if fragInd != 0xFFFFFFFF {
var fragRdr io.Reader
fragRdr, err = r.fragReader(fragInd)
if err != nil {
return nil, err
}
_, err = fragRdr.Read(make([]byte, fragOffset))
if err != nil {
return nil, err
}
rdr.AddFragment(fragRdr)
}
return rdr, nil
}
func (r Reader) readDirectory(i inode.Inode) ([]directory.Entry, error) {
var offset uint64
var blockOffset uint16
var size uint32
if i.Type == inode.Dir {
offset = uint64(i.Data.(inode.Directory).BlockStart)
blockOffset = i.Data.(inode.Directory).Offset
size = uint32(i.Data.(inode.Directory).Size)
} else if i.Type == inode.EDir {
offset = uint64(i.Data.(inode.EDirectory).BlockStart)
blockOffset = i.Data.(inode.EDirectory).Offset
size = i.Data.(inode.EDirectory).Size
} else {
return nil, errors.New("readDirectory called on non-directory type")
}
rdr, err := metadata.NewReader(toreader.NewReader(r.r, int64(offset+r.s.DirTableStart)), r.d)
if err != nil {
return nil, err
}
_, err = rdr.Read(make([]byte, blockOffset))
if err != nil {
return nil, err
}
return directory.ReadEntries(rdr, size)
}