From 78c35cf72078952c16163b19e720c6e3ec560299 Mon Sep 17 00:00:00 2001 From: Caleb Gardner Date: Thu, 12 Nov 2020 09:50:52 -0600 Subject: [PATCH] Further work on Inode --- README.md | 28 +++++------ internal/inode/inode.go | 56 ++++++++++++++++++--- internal/inode/processInode.go | 89 ++++++++++++++++++++++++++++++++++ reader.go | 2 +- 4 files changed, 154 insertions(+), 21 deletions(-) create mode 100644 internal/inode/processInode.go diff --git a/README.md b/README.md index 1621c2c..73efa1a 100644 --- a/README.md +++ b/README.md @@ -5,17 +5,17 @@ Right Now it's mostly based on [distri's squashfs library](https://github.com/di Special thanks to https://dr-emann.github.io/squashfs/ for some VERY important information in an easy to understand format -# Ideas -* Link directly to squashfs-tool using cgo - * cgo can be a butt - * Would require the least amount of code for me to do - * Doing things in pure Go is definately highly superior -* Improve [distri's](https://github.com/distr1/distri) or [diskfs](https://github.com/diskfs/go-diskfs) squashfs library to meet my needs - * Both don't work at all ATM. - * distri's doesn't seem to support any sort of compression, which causes issues all over the place. - * diskfs seems closer, but the squashfs code is incomplete -* Create an original squashfs library - * MUCH more research needed - * Could look at [squashfs-tools'](https://github.com/plougher/squashfs-tools) code to help out - * Don't have to deal with other people's code :P - * Honestly a bit unnecessary based on how close distri & diskfs's code is AND how little I know about squashfs. +I am focusing purely on unsquashing before squashing. + +# Working + +* Reading the header +* (Maybe) reading gzip compressed data + +# Not Working (Yet). Roughly in order. + +* Actually reading the compressed data +* Reading Inodes +* Reading the Directory structure +* Implement other compression types +* Squashing \ No newline at end of file diff --git a/internal/inode/inode.go b/internal/inode/inode.go index 08b7906..a5d7eab 100644 --- a/internal/inode/inode.go +++ b/internal/inode/inode.go @@ -1,6 +1,12 @@ package inode -type CommonHeader struct { +import ( + "encoding/binary" + "io" +) + +//InodeCommon is the comon header for all inodes +type InodeCommon struct { InodeType uint16 Permissions uint16 UID uint16 @@ -9,6 +15,7 @@ type CommonHeader struct { Number uint32 } +//BasicDirectory is self explainatory type BasicDirectory struct { DirectoryIndex uint32 HardLinks uint32 @@ -17,6 +24,7 @@ type BasicDirectory struct { ParentInodeNumber uint32 } +//ExtendedDirectoryInit is the information that can be directoy decoded type ExtendedDirectoryInit struct { HardLinks uint32 DirectorySize uint32 @@ -27,19 +35,31 @@ type ExtendedDirectoryInit struct { XattrIndex uint32 } +//ExtendedDirectory is a directory with extra info type ExtendedDirectory struct { - ExtendedDirectoryInit - //TODO indexes []DirectoryIndex + Init ExtendedDirectoryInit + //TODO: indexes []DirectoryIndex } +//NewExtendedDirectory creates a new ExtendedDirectory +func NewExtendedDirectory(rdr *io.Reader) (*ExtendedDirectory, error) { + var inode ExtendedDirectory + err := binary.Read(*rdr, binary.LittleEndian, inode.Init) + //TODO: Read directory indexes + return &inode, err +} + +//BasicFile is self explainatory type BasicFile struct { BlockStart uint32 FragmentIndex uint32 FragmentOffset uint32 Size uint32 BlockSizes []uint32 + //TODO: possibly fix BlockSizes } +//ExtendedFile is a file with additional information type ExtendedFile struct { BlockStart uint32 Size uint32 @@ -49,6 +69,7 @@ type ExtendedFile struct { FragmentOffset uint32 XattrIndex uint32 BlockSizes []uint32 + //TODO: possibly fix BlockSizes } type BasicSymlinkInit struct { @@ -57,8 +78,19 @@ type BasicSymlinkInit struct { } type BasicSymlink struct { - BasicSymlinkInit - targetPath []byte //len is TargetPathSize + Init BasicSymlinkInit + targetPath []uint8 //len is TargetPathSize +} + +func NewBasicSymlink(rdr *io.Reader) (*BasicSymlink, error) { + var inode BasicSymlink + err := binary.Read(*rdr, binary.LittleEndian, inode.Init) + if err != nil { + return nil, err + } + inode.targetPath = make([]uint8, inode.Init.TargetPathSize) + err = binary.Read(*rdr, binary.LittleEndian, inode.targetPath) + return &inode, err } type ExtendedSymlinkInit struct { @@ -67,10 +99,22 @@ type ExtendedSymlinkInit struct { } type ExtendedSymlink struct { - targetPath []byte + Init ExtendedSymlinkInit + TargetPath []uint8 XattrIndex uint32 } +func NewExtendedSymlink(rdr *io.Reader) (*ExtendedSymlink, error) { + var inode ExtendedSymlink + err := binary.Read(*rdr, binary.LittleEndian, inode.Init) + if err != nil { + return &inode, err + } + inode.TargetPath = make([]uint8, inode.Init.TargetPathSize) + err = binary.Read(*rdr, binary.LittleEndian, &inode.XattrIndex) + return &inode, err +} + type BasicDevice struct { HardLinks uint32 Device uint32 diff --git a/internal/inode/processInode.go b/internal/inode/processInode.go new file mode 100644 index 0000000..522753a --- /dev/null +++ b/internal/inode/processInode.go @@ -0,0 +1,89 @@ +package inode + +import ( + "encoding/binary" + "errors" + "io" + "strconv" +) + +const ( + basicDirectory = iota + 1 + basicFile + basicSymlink + basicBlockDevice + basicCharDevice + basicFifo + basicSocket + extendedDirectory + extendedFile + extendedSymlink + extendedBlockDevice + extendedCharDevice + extendedFifo + extendedSocket +) + +func ProcessInode(rdr *io.Reader) (*InodeCommon, interface{}, error) { + var inodeHeader InodeCommon + err := binary.Read(*rdr, binary.LittleEndian, &inodeHeader) + if err != nil { + return nil, nil, err + } + switch inodeHeader.InodeType { + case basicDirectory: + var inode BasicDirectory + err = binary.Read(*rdr, binary.LittleEndian, &inode) + return &inodeHeader, inode, err + case basicFile: + var inode BasicFile + err = binary.Read(*rdr, binary.LittleEndian, &inode) + return &inodeHeader, inode, err + case basicSymlink: + inode, err := NewBasicSymlink(rdr) + return &inodeHeader, inode, err + // case basicFile: + // var inode BasicFile + // err = binary.Read(*rdr, binary.LittleEndian, &inode) + // return &inodeHeader, inode, err + // case basicFile: + // var inode BasicFile + // err = binary.Read(*rdr, binary.LittleEndian, &inode) + // return &inodeHeader, inode, err + // case basicFile: + // var inode BasicFile + // err = binary.Read(*rdr, binary.LittleEndian, &inode) + // return &inodeHeader, inode, err + // case basicFile: + // var inode BasicFile + // err = binary.Read(*rdr, binary.LittleEndian, &inode) + // return &inodeHeader, inode, err + // case basicFile: + // var inode BasicFile + // err = binary.Read(*rdr, binary.LittleEndian, &inode) + // return &inodeHeader, inode, err + // case basicFile: + // var inode BasicFile + // err = binary.Read(*rdr, binary.LittleEndian, &inode) + // return &inodeHeader, inode, err + // case basicFile: + // var inode BasicFile + // err = binary.Read(*rdr, binary.LittleEndian, &inode) + // return &inodeHeader, inode, err + // case basicFile: + // var inode BasicFile + // err = binary.Read(*rdr, binary.LittleEndian, &inode) + // return &inodeHeader, inode, err + // case basicFile: + // var inode BasicFile + // err = binary.Read(*rdr, binary.LittleEndian, &inode) + // return &inodeHeader, inode, err + // case basicFile: + // var inode BasicFile + // err = binary.Read(*rdr, binary.LittleEndian, &inode) + // return &inodeHeader, inode, err + //TODO: implement ALL cases + default: + return nil, nil, errors.New("Inode type is unrecognized: " + strconv.FormatInt(int64(inodeHeader.InodeType), 2)) + } +} diff --git a/reader.go b/reader.go index f688d44..0955825 100644 --- a/reader.go +++ b/reader.go @@ -56,7 +56,7 @@ func (r *Reader) Seek(offset int64, whence int) (int64, error) { n, err := r.Read(make([]byte, offset)) return int64(n), err case io.SeekEnd: - return 0, errors.New("SeekEnd is NOT currently supported") + return 0, errors.New("SeekEnd is NOT supported") } return 0, errors.New("incorrect whence") }