Directorty table info parsing.
Futher work on reading data.
This commit is contained in:
@@ -19,3 +19,7 @@ I am focusing purely on unsquashing before squashing.
|
|||||||
* Reading the Directory structure
|
* Reading the Directory structure
|
||||||
* Implement other compression types
|
* Implement other compression types
|
||||||
* Squashing
|
* Squashing
|
||||||
|
|
||||||
|
# Where I'm at
|
||||||
|
|
||||||
|
* I can read the metadata, but can't read inodes just yet.
|
||||||
+19
-16
@@ -1,12 +1,14 @@
|
|||||||
package squashfs
|
package squashfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"compress/zlib"
|
"compress/gzip"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"gopkg.in/src-d/go-git.v4/utils/ioutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
zlibCompression = 1 + iota
|
gzipCompression = 1 + iota
|
||||||
lzmaCompression
|
lzmaCompression
|
||||||
lzoCompression
|
lzoCompression
|
||||||
xzCompression
|
xzCompression
|
||||||
@@ -95,13 +97,13 @@ func NewGzipOptions(raw gzipOptionsRaw) *GzipOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gzipOp *GzipOptions) Decompress(rdr *io.SectionReader, blockSize int) ([]byte, error) {
|
func (gzipOp *GzipOptions) Decompress(rdr *io.SectionReader, blockSize int) ([]byte, error) {
|
||||||
zlibRdr, err := zlib.NewReader(rdr)
|
gzipRdr, err := gzip.NewReader(rdr)
|
||||||
defer zlibRdr.Close()
|
defer gzipRdr.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
bytrw := newByteReadWrite(0)
|
bytrw := newByteReadWrite(0)
|
||||||
_, err = io.Copy(bytrw, zlibRdr)
|
_, err = io.Copy(bytrw, gzipRdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return bytrw.byts, err
|
return bytrw.byts, err
|
||||||
}
|
}
|
||||||
@@ -109,20 +111,20 @@ func (gzipOp *GzipOptions) Decompress(rdr *io.SectionReader, blockSize int) ([]b
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gzipOp *GzipOptions) DecompressCopy(rdr *io.Reader, wrt *io.Writer) (int, error) {
|
func (gzipOp *GzipOptions) DecompressCopy(rdr *io.Reader, wrt *io.Writer) (int, error) {
|
||||||
zlibRdr, err := zlib.NewReader(*rdr)
|
gzipRdr, err := gzip.NewReader(*rdr)
|
||||||
defer zlibRdr.Close()
|
defer gzipRdr.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
n, err := io.Copy(*wrt, zlibRdr)
|
n, err := io.Copy(*wrt, gzipRdr)
|
||||||
return int(n), err
|
return int(n), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gzipOp *GzipOptions) Compress(rdr *io.SectionReader, blockSize int) ([]byte, error) {
|
func (gzipOp *GzipOptions) Compress(rdr *io.SectionReader, blockSize int) ([]byte, error) {
|
||||||
bytWrt := newByteReadWrite(0)
|
bytWrt := newByteReadWrite(0)
|
||||||
zlibWrt := zlib.NewWriter(bytWrt) //TODO: allow setting level
|
gzipWrt := gzip.NewWriter(bytWrt) //TODO: allow setting level
|
||||||
defer zlibWrt.Close()
|
defer gzipWrt.Close()
|
||||||
_, err := io.Copy(zlibWrt, rdr)
|
_, err := io.Copy(gzipWrt, rdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return bytWrt.byts, err
|
return bytWrt.byts, err
|
||||||
}
|
}
|
||||||
@@ -130,15 +132,16 @@ func (gzipOp *GzipOptions) Compress(rdr *io.SectionReader, blockSize int) ([]byt
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gzipOp *GzipOptions) CompressCopy(rdr *io.Reader, wrt *io.Writer) (int, error) {
|
func (gzipOp *GzipOptions) CompressCopy(rdr *io.Reader, wrt *io.Writer) (int, error) {
|
||||||
zlibWrt := zlib.NewWriter(*wrt) //TODO: allow setting level
|
gzipWrt := gzip.NewWriter(*wrt) //TODO: allow setting level
|
||||||
defer zlibWrt.Close()
|
defer gzipWrt.Close()
|
||||||
n, err := io.Copy(zlibWrt, *rdr)
|
n, err := io.Copy(gzipWrt, *rdr)
|
||||||
return int(n), err
|
return int(n), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gzipOp *GzipOptions) Reader(rdr io.Reader) (*io.ReadCloser, error) {
|
func (gzipOp *GzipOptions) Reader(rdr io.Reader) (*io.ReadCloser, error) {
|
||||||
read, err := zlib.NewReader(rdr)
|
read, err := gzip.NewReader(rdr)
|
||||||
return &read, err
|
redClo := ioutil.NewReadCloser(read, read)
|
||||||
|
return &redClo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
type xzOptionsRaw struct {
|
type xzOptionsRaw struct {
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package directory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
//Header is the header for a directory in the directory table
|
||||||
|
type Header struct {
|
||||||
|
Count uint32
|
||||||
|
InodeOffset uint32
|
||||||
|
InodeNumber uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
//EntryInit is the values that can be easily decoded
|
||||||
|
type EntryInit struct {
|
||||||
|
Offset uint16
|
||||||
|
InodeOffset int16
|
||||||
|
Type uint16
|
||||||
|
NameSize uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
//Entry is an entry in a directory.
|
||||||
|
type Entry struct {
|
||||||
|
Init EntryInit
|
||||||
|
Name []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
//NewEntry creates a new directory entry
|
||||||
|
func NewEntry(rdr io.Reader) (Entry, error) {
|
||||||
|
var entry Entry
|
||||||
|
err := binary.Read(rdr, binary.LittleEndian, entry.Init)
|
||||||
|
if err != nil {
|
||||||
|
return entry, err
|
||||||
|
}
|
||||||
|
entry.Name = make([]byte, entry.Init.NameSize, entry.Init.NameSize)
|
||||||
|
err = binary.Read(rdr, binary.LittleEndian, entry.Name)
|
||||||
|
return entry, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//Directory is an entry in the directory table of a squashfs.
|
||||||
|
//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
|
||||||
|
func NewDirectory(rdr io.Reader) (*Directory, error) {
|
||||||
|
var dir Directory
|
||||||
|
var hdr Header
|
||||||
|
err := binary.Read(rdr, binary.LittleEndian, &hdr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
headers := hdr.Count / 256
|
||||||
|
if headers%256 > 0 {
|
||||||
|
headers++
|
||||||
|
}
|
||||||
|
headersRead := 1
|
||||||
|
dir.Headers = make([]Header, headers)
|
||||||
|
dir.Headers[0] = hdr
|
||||||
|
for i := uint32(0); i < hdr.Count; i++ {
|
||||||
|
if i != 0 && i%256 == 0 {
|
||||||
|
var newHdr Header
|
||||||
|
err = binary.Read(rdr, binary.LittleEndian, &newHdr)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error processing header ", headersRead)
|
||||||
|
return &dir, err
|
||||||
|
}
|
||||||
|
dir.Headers[headersRead] = newHdr
|
||||||
|
headersRead++
|
||||||
|
}
|
||||||
|
ent, err := NewEntry(rdr)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error processing entry ", len(dir.Entries))
|
||||||
|
return &dir, err
|
||||||
|
}
|
||||||
|
dir.Entries = append(dir.Entries, ent)
|
||||||
|
}
|
||||||
|
return &dir, nil
|
||||||
|
}
|
||||||
+58
-18
@@ -2,11 +2,12 @@ package inode
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
//InodeCommon is the comon header for all inodes
|
//Common is the comon header for all inodes
|
||||||
type InodeCommon struct {
|
type Common struct {
|
||||||
InodeType uint16
|
InodeType uint16
|
||||||
Permissions uint16
|
Permissions uint16
|
||||||
UID uint16
|
UID uint16
|
||||||
@@ -37,25 +38,61 @@ type ExtendedDirectoryInit struct {
|
|||||||
|
|
||||||
//ExtendedDirectory is a directory with extra info
|
//ExtendedDirectory is a directory with extra info
|
||||||
type ExtendedDirectory struct {
|
type ExtendedDirectory struct {
|
||||||
Init ExtendedDirectoryInit
|
Init ExtendedDirectoryInit
|
||||||
//TODO: indexes []DirectoryIndex
|
Indexes []DirectoryIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
//NewExtendedDirectory creates a new ExtendedDirectory
|
//NewExtendedDirectory creates a new ExtendedDirectory
|
||||||
func NewExtendedDirectory(rdr *io.Reader) (*ExtendedDirectory, error) {
|
func NewExtendedDirectory(rdr *io.Reader) (*ExtendedDirectory, error) {
|
||||||
var inode ExtendedDirectory
|
var inode ExtendedDirectory
|
||||||
err := binary.Read(*rdr, binary.LittleEndian, inode.Init)
|
err := binary.Read(*rdr, binary.LittleEndian, inode.Init)
|
||||||
//TODO: Read directory indexes
|
if err != nil {
|
||||||
|
return &inode, err
|
||||||
|
}
|
||||||
|
if inode.Init.IndexCount > 0 {
|
||||||
|
inode.Indexes = make([]DirectoryIndex, inode.Init.IndexCount)
|
||||||
|
for i := uint16(0); i < inode.Init.IndexCount; i++ {
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//DirectoryIndexInit holds the values that can be easily decoded
|
||||||
|
type DirectoryIndexInit struct {
|
||||||
|
Offset uint32
|
||||||
|
DirTableOffset uint32
|
||||||
|
NameSize uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
//DirectoryIndex is a quick lookup provided by an ExtendedDirectory
|
||||||
|
type DirectoryIndex struct {
|
||||||
|
Init DirectoryIndexInit
|
||||||
|
Name []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
//NewDirectoryIndex return a new DirectoryIndex
|
||||||
|
func NewDirectoryIndex(rdr *io.Reader) (DirectoryIndex, error) {
|
||||||
|
var index DirectoryIndex
|
||||||
|
err := binary.Read(*rdr, binary.LittleEndian, index.Init)
|
||||||
|
if err != nil {
|
||||||
|
return index, err
|
||||||
|
}
|
||||||
|
index.Name = make([]byte, index.Init.NameSize, index.Init.NameSize)
|
||||||
|
err = binary.Read(*rdr, binary.LittleEndian, index.Name)
|
||||||
|
return index, err
|
||||||
|
}
|
||||||
|
|
||||||
//BasicFileInit is the information that can be directoy decoded
|
//BasicFileInit is the information that can be directoy decoded
|
||||||
type BasicFileInit struct {
|
type BasicFileInit struct {
|
||||||
BlockStart uint32
|
BlockStart uint32
|
||||||
FragmentIndex uint32
|
FragmentIndex uint32
|
||||||
FragmentOffset uint32
|
FragmentOffset uint32
|
||||||
Size uint32
|
Size uint32
|
||||||
//TODO: possibly fix BlockSizes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//BasicFile is self explainatory
|
//BasicFile is self explainatory
|
||||||
@@ -89,7 +126,6 @@ type ExtendedFileInit struct {
|
|||||||
FragmentIndex uint32
|
FragmentIndex uint32
|
||||||
FragmentOffset uint32
|
FragmentOffset uint32
|
||||||
XattrIndex uint32
|
XattrIndex uint32
|
||||||
//TODO: possibly fix BlockSizes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//ExtendedFile is a file with more information
|
//ExtendedFile is a file with more information
|
||||||
@@ -99,11 +135,11 @@ type ExtendedFile struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//NewExtendedFile creates a new ExtendedFile
|
//NewExtendedFile creates a new ExtendedFile
|
||||||
func NewExtendedFile(rdr *io.Reader, blockSize uint32) (*ExtendedFile, error) {
|
func NewExtendedFile(rdr *io.Reader, blockSize uint32) (ExtendedFile, error) {
|
||||||
var inode ExtendedFile
|
var inode ExtendedFile
|
||||||
err := binary.Read(*rdr, binary.LittleEndian, inode.Init)
|
err := binary.Read(*rdr, binary.LittleEndian, inode.Init)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &inode, err
|
return inode, err
|
||||||
}
|
}
|
||||||
blocks := inode.Init.Size / blockSize
|
blocks := inode.Init.Size / blockSize
|
||||||
if inode.Init.Size%blockSize > 0 {
|
if inode.Init.Size%blockSize > 0 {
|
||||||
@@ -111,7 +147,7 @@ func NewExtendedFile(rdr *io.Reader, blockSize uint32) (*ExtendedFile, error) {
|
|||||||
}
|
}
|
||||||
inode.BlockSizes = make([]uint32, blocks, blocks)
|
inode.BlockSizes = make([]uint32, blocks, blocks)
|
||||||
err = binary.Read(*rdr, binary.LittleEndian, inode.BlockSizes)
|
err = binary.Read(*rdr, binary.LittleEndian, inode.BlockSizes)
|
||||||
return &inode, err
|
return inode, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//BasicSymlinkInit is all the values that can be directly decoded
|
//BasicSymlinkInit is all the values that can be directly decoded
|
||||||
@@ -123,19 +159,19 @@ type BasicSymlinkInit struct {
|
|||||||
//BasicSymlink is a symlink
|
//BasicSymlink is a symlink
|
||||||
type BasicSymlink struct {
|
type BasicSymlink struct {
|
||||||
Init BasicSymlinkInit
|
Init BasicSymlinkInit
|
||||||
targetPath []uint8 //len is TargetPathSize
|
targetPath []byte //len is TargetPathSize
|
||||||
}
|
}
|
||||||
|
|
||||||
//NewBasicSymlink creates a new BasicSymlink
|
//NewBasicSymlink creates a new BasicSymlink
|
||||||
func NewBasicSymlink(rdr *io.Reader) (*BasicSymlink, error) {
|
func NewBasicSymlink(rdr *io.Reader) (BasicSymlink, error) {
|
||||||
var inode BasicSymlink
|
var inode BasicSymlink
|
||||||
err := binary.Read(*rdr, binary.LittleEndian, inode.Init)
|
err := binary.Read(*rdr, binary.LittleEndian, inode.Init)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return inode, err
|
||||||
}
|
}
|
||||||
inode.targetPath = make([]uint8, inode.Init.TargetPathSize, inode.Init.TargetPathSize)
|
inode.targetPath = make([]byte, inode.Init.TargetPathSize, inode.Init.TargetPathSize)
|
||||||
err = binary.Read(*rdr, binary.LittleEndian, inode.targetPath)
|
err = binary.Read(*rdr, binary.LittleEndian, inode.targetPath)
|
||||||
return &inode, err
|
return inode, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//ExtendedSymlinkInit is all the values that can be directly decoded
|
//ExtendedSymlinkInit is all the values that can be directly decoded
|
||||||
@@ -152,31 +188,35 @@ type ExtendedSymlink struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//NewExtendedSymlink creates a new ExtendedSymlink
|
//NewExtendedSymlink creates a new ExtendedSymlink
|
||||||
func NewExtendedSymlink(rdr *io.Reader) (*ExtendedSymlink, error) {
|
func NewExtendedSymlink(rdr *io.Reader) (ExtendedSymlink, error) {
|
||||||
var inode ExtendedSymlink
|
var inode ExtendedSymlink
|
||||||
err := binary.Read(*rdr, binary.LittleEndian, inode.Init)
|
err := binary.Read(*rdr, binary.LittleEndian, inode.Init)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &inode, err
|
return inode, err
|
||||||
}
|
}
|
||||||
inode.TargetPath = make([]uint8, inode.Init.TargetPathSize, inode.Init.TargetPathSize)
|
inode.TargetPath = make([]uint8, inode.Init.TargetPathSize, inode.Init.TargetPathSize)
|
||||||
err = binary.Read(*rdr, binary.LittleEndian, &inode.XattrIndex)
|
err = binary.Read(*rdr, binary.LittleEndian, &inode.XattrIndex)
|
||||||
return &inode, err
|
return inode, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//BasicDevice is a device
|
||||||
type BasicDevice struct {
|
type BasicDevice struct {
|
||||||
HardLinks uint32
|
HardLinks uint32
|
||||||
Device uint32
|
Device uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ExtendedDevice is a device with more info
|
||||||
type ExtendedDevice struct {
|
type ExtendedDevice struct {
|
||||||
BasicDevice
|
BasicDevice
|
||||||
XattrIndex uint32
|
XattrIndex uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//BasicIPC is a Fifo or Socket device
|
||||||
type BasicIPC struct {
|
type BasicIPC struct {
|
||||||
HardLink uint32
|
HardLink uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ExtendedIPC is a IPC device with extra info
|
||||||
type ExtendedIPC struct {
|
type ExtendedIPC struct {
|
||||||
BasicIPC
|
BasicIPC
|
||||||
XattrIndex uint32
|
XattrIndex uint32
|
||||||
|
|||||||
@@ -8,80 +8,83 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
basicDirectory = iota + 1
|
//The inode type from inode.Common.InodeType
|
||||||
basicFile
|
|
||||||
basicSymlink
|
BasicDirectoryType = iota + 1
|
||||||
basicBlockDevice
|
BasicFileType
|
||||||
basicCharDevice
|
BasicSymlinkType
|
||||||
basicFifo
|
BasicBlockDeviceType
|
||||||
basicSocket
|
BasicCharDeviceType
|
||||||
extendedDirectory
|
BasicFifoType
|
||||||
extendedFile
|
BasicSocketType
|
||||||
extendedSymlink
|
ExtendedDirectoryType
|
||||||
extendedBlockDevice
|
ExtendedFileType
|
||||||
extendedCharDevice
|
ExtendedSymlinkType
|
||||||
extendedFifo
|
ExtendedBlockDeviceType
|
||||||
extendedSocket
|
ExtendedCharDeviceType
|
||||||
|
ExtendedFifoType
|
||||||
|
ExtendedSocketType
|
||||||
)
|
)
|
||||||
|
|
||||||
func ProcessInode(rdr *io.Reader) (*InodeCommon, interface{}, error) {
|
//ProcessInode processes the next inode in the given reader
|
||||||
var inodeHeader InodeCommon
|
func ProcessInode(rdr *io.Reader, blockSize uint32) (*Common, interface{}, error) {
|
||||||
|
var inodeHeader Common
|
||||||
err := binary.Read(*rdr, binary.LittleEndian, &inodeHeader)
|
err := binary.Read(*rdr, binary.LittleEndian, &inodeHeader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
switch inodeHeader.InodeType {
|
switch inodeHeader.InodeType {
|
||||||
case basicDirectory:
|
case BasicDirectoryType:
|
||||||
var inode BasicDirectory
|
var inode BasicDirectory
|
||||||
err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
||||||
|
return &inodeHeader, &inode, err
|
||||||
|
case BasicFileType:
|
||||||
|
inode, err := NewBasicFile(rdr, blockSize)
|
||||||
return &inodeHeader, inode, err
|
return &inodeHeader, inode, err
|
||||||
case basicFile:
|
case BasicSymlinkType:
|
||||||
var inode BasicFile
|
|
||||||
err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
|
||||||
return &inodeHeader, inode, err
|
|
||||||
case basicSymlink:
|
|
||||||
inode, err := NewBasicSymlink(rdr)
|
inode, err := NewBasicSymlink(rdr)
|
||||||
return &inodeHeader, inode, err
|
return &inodeHeader, inode, err
|
||||||
// case basicFile:
|
case BasicBlockDeviceType:
|
||||||
// var inode BasicFile
|
var inode BasicDevice
|
||||||
// err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
||||||
// return &inodeHeader, inode, err
|
return &inodeHeader, inode, err
|
||||||
// case basicFile:
|
case BasicCharDeviceType:
|
||||||
// var inode BasicFile
|
var inode BasicDevice
|
||||||
// err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
||||||
// return &inodeHeader, inode, err
|
return &inodeHeader, inode, err
|
||||||
// case basicFile:
|
case BasicFifoType:
|
||||||
// var inode BasicFile
|
var inode BasicIPC
|
||||||
// err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
||||||
// return &inodeHeader, inode, err
|
return &inodeHeader, inode, err
|
||||||
// case basicFile:
|
case BasicSocketType:
|
||||||
// var inode BasicFile
|
var inode BasicIPC
|
||||||
// err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
||||||
// return &inodeHeader, inode, err
|
return &inodeHeader, inode, err
|
||||||
// case basicFile:
|
case ExtendedDirectoryType:
|
||||||
// var inode BasicFile
|
inode, err := NewExtendedDirectory(rdr)
|
||||||
// err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
return &inodeHeader, inode, err
|
||||||
// return &inodeHeader, inode, err
|
case ExtendedFileType:
|
||||||
// case basicFile:
|
inode, err := NewExtendedFile(rdr, blockSize)
|
||||||
// var inode BasicFile
|
return &inodeHeader, inode, err
|
||||||
// err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
case ExtendedSymlinkType:
|
||||||
// return &inodeHeader, inode, err
|
inode, err := NewExtendedSymlink(rdr)
|
||||||
// case basicFile:
|
return &inodeHeader, inode, err
|
||||||
// var inode BasicFile
|
case ExtendedBlockDeviceType:
|
||||||
// err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
var inode ExtendedDevice
|
||||||
// return &inodeHeader, inode, err
|
err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
||||||
// case basicFile:
|
return &inodeHeader, inode, err
|
||||||
// var inode BasicFile
|
case ExtendedCharDeviceType:
|
||||||
// err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
var inode ExtendedDevice
|
||||||
// return &inodeHeader, inode, err
|
err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
||||||
// case basicFile:
|
return &inodeHeader, inode, err
|
||||||
// var inode BasicFile
|
case ExtendedFifoType:
|
||||||
// err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
var inode ExtendedIPC
|
||||||
// return &inodeHeader, inode, err
|
err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
||||||
// case basicFile:
|
return &inodeHeader, inode, err
|
||||||
// var inode BasicFile
|
case ExtendedSocketType:
|
||||||
// err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
var inode ExtendedIPC
|
||||||
// return &inodeHeader, inode, err
|
err = binary.Read(*rdr, binary.LittleEndian, &inode)
|
||||||
|
return &inodeHeader, inode, err
|
||||||
//TODO: implement ALL cases
|
//TODO: implement ALL cases
|
||||||
default:
|
default:
|
||||||
return nil, nil, errors.New("Inode type is unrecognized: " + strconv.FormatInt(int64(inodeHeader.InodeType), 2))
|
return nil, nil, errors.New("Inode type is unrecognized: " + strconv.FormatInt(int64(inodeHeader.InodeType), 2))
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package inode
|
||||||
|
|
||||||
|
//ProcessInodeRef processes an inode reference and returns two values
|
||||||
|
//The first value is the inode table offset. AKA, it's where the metadata block of the inode STARTS.
|
||||||
|
//The second value is the offset of the inode, INSIDE of the metadata.
|
||||||
|
func ProcessInodeRef(inodeRef uint64) (tableOffset uint32, metaOffset uint16) {
|
||||||
|
tableOffset = uint32(inodeRef >> 16)
|
||||||
|
metaOffset = uint16(inodeRef &^ 0xFFFFFFFF0000)
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -9,9 +9,6 @@ import (
|
|||||||
|
|
||||||
//Reader is a reader which implements Reader, ReaderAt, and Seeker, all with an accesible offset (for reasons)
|
//Reader is a reader which implements Reader, ReaderAt, and Seeker, all with an accesible offset (for reasons)
|
||||||
type Reader struct {
|
type Reader struct {
|
||||||
io.Reader
|
|
||||||
io.ReaderAt
|
|
||||||
io.Seeker
|
|
||||||
rdr io.ReaderAt
|
rdr io.ReaderAt
|
||||||
offset int64
|
offset int64
|
||||||
}
|
}
|
||||||
|
|||||||
+45
-11
@@ -3,7 +3,10 @@ package squashfs
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/CalebQ42/GoSquashfs/internal/inode"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -34,7 +37,7 @@ func NewSquashfs(reader io.ReaderAt) (*Squashfs, error) {
|
|||||||
flags := superblock.GetFlags()
|
flags := superblock.GetFlags()
|
||||||
var compressionOptions CompressionOptions
|
var compressionOptions CompressionOptions
|
||||||
switch superblock.Compression {
|
switch superblock.Compression {
|
||||||
case zlibCompression:
|
case gzipCompression:
|
||||||
if flags.CompressorOptions {
|
if flags.CompressorOptions {
|
||||||
var gzipOpRaw gzipOptionsRaw
|
var gzipOpRaw gzipOptionsRaw
|
||||||
err = binary.Read(&rdr, binary.LittleEndian, &gzipOpRaw)
|
err = binary.Read(&rdr, binary.LittleEndian, &gzipOpRaw)
|
||||||
@@ -69,9 +72,39 @@ func NewSquashfs(reader io.ReaderAt) (*Squashfs, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Squashfs) readRootDirectoryTable() error {
|
||||||
|
offset, metaOffset := inode.ProcessInodeRef(s.super.RootInode)
|
||||||
|
meta, err := s.parseMetadataAt(int64(s.super.InodeTableOffset) + int64(offset))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error processing metadata")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = meta.Data.Read(make([]byte, metaOffset))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("error reading forward to offset")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
common, _, err := inode.ProcessInode(&meta.Data, s.super.BlockSize)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error reading inode")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if common.InodeType != inode.BasicDirectoryType {
|
||||||
|
return errors.New("Not a basic directory")
|
||||||
|
}
|
||||||
|
// dirTable, err := directory.NewDirectory(meta.Data)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// for _, entry := range dirTable.Entries {
|
||||||
|
// fmt.Println(entry.Name)
|
||||||
|
// }
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
//GetFlags return the SuperblockFlags of the Squashfs
|
//GetFlags return the SuperblockFlags of the Squashfs
|
||||||
func (s *Squashfs) GetFlags() SuperblockFlags {
|
func (s *Squashfs) GetFlags() SuperblockFlags {
|
||||||
return s.super.GetFlags()
|
return s.flags
|
||||||
}
|
}
|
||||||
|
|
||||||
//metadata is a parsed metadata block
|
//metadata is a parsed metadata block
|
||||||
@@ -90,13 +123,14 @@ func (m *metadata) close() {
|
|||||||
|
|
||||||
func (s *Squashfs) parseNextMetadata() (*metadata, error) {
|
func (s *Squashfs) parseNextMetadata() (*metadata, error) {
|
||||||
var metaHeader uint16
|
var metaHeader uint16
|
||||||
err := binary.Read(s.rdr, binary.LittleEndian, metaHeader)
|
err := binary.Read(s.rdr, binary.LittleEndian, &metaHeader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
reader := io.NewSectionReader(s.rdr, s.rdr.offset, s.rdr.offset+int64(metaHeader))
|
||||||
if metaHeader&0x8000 == 0x8000 {
|
if metaHeader&0x8000 == 0x8000 {
|
||||||
metaHeader = metaHeader &^ 0x8000
|
metaHeader = metaHeader &^ 0x8000
|
||||||
compressRead, err := s.compressionOptions.Reader(io.NewSectionReader(s.rdr, s.rdr.offset, int64(metaHeader)))
|
compressRead, err := s.compressionOptions.Reader(reader)
|
||||||
return &metadata{
|
return &metadata{
|
||||||
Compressed: true,
|
Compressed: true,
|
||||||
Size: metaHeader,
|
Size: metaHeader,
|
||||||
@@ -106,19 +140,19 @@ func (s *Squashfs) parseNextMetadata() (*metadata, error) {
|
|||||||
return &metadata{
|
return &metadata{
|
||||||
Compressed: false,
|
Compressed: false,
|
||||||
Size: metaHeader,
|
Size: metaHeader,
|
||||||
Data: io.NewSectionReader(s.rdr, s.rdr.offset, int64(metaHeader)),
|
Data: reader,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Squashfs) parseMetadataAt(offset int64) (*metadata, error) {
|
func (s *Squashfs) parseMetadataAt(offset int64) (*metadata, error) {
|
||||||
var metaHeader uint16
|
var metaHeader uint16
|
||||||
err := binary.Read(s.rdr, binary.LittleEndian, metaHeader)
|
var headerBytes []byte
|
||||||
if err != nil {
|
headerBytes = make([]byte, 2)
|
||||||
return nil, err
|
s.rdr.ReadAt(headerBytes, offset)
|
||||||
}
|
metaHeader = binary.LittleEndian.Uint16(headerBytes)
|
||||||
if metaHeader&0x8000 == 0x8000 {
|
if metaHeader&0x8000 == 0x8000 {
|
||||||
metaHeader = metaHeader &^ 0x8000
|
metaHeader = metaHeader &^ 0x8000
|
||||||
compressRead, err := s.compressionOptions.Reader(io.NewSectionReader(s.rdr, offset, int64(metaHeader)))
|
compressRead, err := s.compressionOptions.Reader(io.NewSectionReader(s.rdr, s.rdr.offset, s.rdr.offset+int64(s.super.BlockSize)))
|
||||||
return &metadata{
|
return &metadata{
|
||||||
Compressed: true,
|
Compressed: true,
|
||||||
Size: metaHeader,
|
Size: metaHeader,
|
||||||
@@ -128,6 +162,6 @@ func (s *Squashfs) parseMetadataAt(offset int64) (*metadata, error) {
|
|||||||
return &metadata{
|
return &metadata{
|
||||||
Compressed: false,
|
Compressed: false,
|
||||||
Size: metaHeader,
|
Size: metaHeader,
|
||||||
Data: io.NewSectionReader(s.rdr, offset, int64(metaHeader)),
|
Data: io.NewSectionReader(s.rdr, s.rdr.offset, s.rdr.offset+int64(s.super.BlockSize)),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -1,7 +1,6 @@
|
|||||||
package squashfs
|
package squashfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@@ -36,8 +35,8 @@ func TestAppImageSquash(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
fmt.Println(squash.GetFlags())
|
err = squash.readRootDirectoryTable()
|
||||||
t.Fatal("Testing")
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateSquashFromAppImage(t *testing.T) {
|
func TestCreateSquashFromAppImage(t *testing.T) {
|
||||||
@@ -78,6 +77,7 @@ func TestCreateSquashFromAppImage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func downloadTestAppImage(t *testing.T, dir string) {
|
func downloadTestAppImage(t *testing.T, dir string) {
|
||||||
|
//seems to time out. Need to fix that at some point
|
||||||
appImage, err := os.Create(dir + "/" + appImageName)
|
appImage, err := os.Create(dir + "/" + appImageName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
Reference in New Issue
Block a user