UBIFS is a file system for raw flash memory devices. It works on top of UBI (Unsorted Block Images), which works as an abstraction layer so UBIFS does not need to care about low level details. This specification only covers UBIFS, not UBI.
A UBIFS image is divided into several Logical Erase Blocks (LEB). The first LEB (LEB0) contains the superblock node, which includes information about LEB size, amongst others. The next two LEBs (LEB1 and LEB2) comprise the so called "master area" and both contain a copy of the master node, which includes information about where to find the root index node, which is then used to access all the files on the file system.
Limitations of this Kaitai Struct implementation:
mkfs.ubifs (such as those in
firmware images built by OpenWrt), not file systems modified after
creation, e.g. by writing files to them on a running Linux system. The
Linux kernel appends a new copy of the master node to LEB1 and LEB2
whenever it mounts the file system read-write, unmounts it, or commits
changes (updates the index on flash to include them). When mounting, Linux
uses the
last copy,
whereas this implementation reads the first one (master_1), which still
describes the file system as it was created. Changes made since then are
therefore not visible via index_root.index_root either. Until they are committed,
UBIFS keeps them only in the journal. This only matters for file systems
that were not unmounted cleanly, because unmounting
commits
all changes.len_image. For the same reason,
parsing doesn't fail if the image is truncated. To detect that, check
that the stream is at least len_image bytes long
(_io.size >= len_image).This page hosts a formal specification of UBIFS using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
// Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT.
import (
"github.com/kaitai-io/kaitai_struct_go_runtime/kaitai"
"io"
"bytes"
)
/**
* UBIFS is a file system for raw flash memory devices. It works on top of
* UBI (Unsorted Block Images), which works as an abstraction layer so UBIFS
* does not need to care about low level details. This specification only covers
* UBIFS, not UBI.
*
* A UBIFS image is divided into several Logical Erase Blocks (LEB). The first
* LEB (LEB0) contains the superblock node, which includes information about LEB
* size, amongst others. The next two LEBs (LEB1 and LEB2) comprise the so called
* "master area" and both contain a copy of the master node, which includes
* information about where to find the root index node, which is then used to
* access all the files on the file system.
*
* **Limitations of this Kaitai Struct implementation:**
*
* 1. It only supports UBIFS images created by `mkfs.ubifs` (such as those in
* firmware images built by OpenWrt), not file systems modified after
* creation, e.g. by writing files to them on a running Linux system. The
* Linux kernel appends a new copy of the master node to LEB1 and LEB2
* whenever it mounts the file system read-write, unmounts it, or commits
* changes (updates the index on flash to include them). When mounting, Linux
* uses the
* [last copy](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/master.c#L84-L165),
* whereas this implementation reads the first one (`master_1`), which still
* describes the file system as it was created. Changes made since then are
* therefore not visible via `index_root`.
* 2. Changes that have not been committed yet are not in the index at all, so
* they are not visible via `index_root` either. Until they are committed,
* UBIFS keeps them only in the journal. This only matters for file systems
* that were not unmounted cleanly, because unmounting
* [commits](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/super.c#L486-L493)
* all changes.
* 3. Parsing doesn't advance the stream position. This implementation reads
* the image only through instances, so that parsing doesn't copy the
* whole image into memory. To find where the image ends, e.g. when
* carving it out of a larger file, use `len_image`. For the same reason,
* parsing doesn't fail if the image is truncated. To detect that, check
* that the stream is at least `len_image` bytes long
* (`_io.size >= len_image`).
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h">Git tag "v7.2"</a>
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/key.h">Git tag "v7.2"</a>
* @see <a href="http://www.linux-mtd.infradead.org/doc/ubifs.pdf">Source</a>
*/
type Ubifs_Compression int
const (
Ubifs_Compression__NoCompression Ubifs_Compression = 0
Ubifs_Compression__Lzo Ubifs_Compression = 1
Ubifs_Compression__Zlib Ubifs_Compression = 2
Ubifs_Compression__Zstd Ubifs_Compression = 3
)
var values_Ubifs_Compression = map[Ubifs_Compression]struct{}{0: {}, 1: {}, 2: {}, 3: {}}
func (v Ubifs_Compression) isDefined() bool {
_, ok := values_Ubifs_Compression[v]
return ok
}
type Ubifs_HashAlgos int
const (
Ubifs_HashAlgos__Md4 Ubifs_HashAlgos = 0
Ubifs_HashAlgos__Md5 Ubifs_HashAlgos = 1
Ubifs_HashAlgos__Sha1 Ubifs_HashAlgos = 2
Ubifs_HashAlgos__RipeMd160 Ubifs_HashAlgos = 3
Ubifs_HashAlgos__Sha256 Ubifs_HashAlgos = 4
Ubifs_HashAlgos__Sha384 Ubifs_HashAlgos = 5
Ubifs_HashAlgos__Sha512 Ubifs_HashAlgos = 6
Ubifs_HashAlgos__Sha224 Ubifs_HashAlgos = 7
Ubifs_HashAlgos__RipeMd128 Ubifs_HashAlgos = 8
Ubifs_HashAlgos__RipeMd256 Ubifs_HashAlgos = 9
Ubifs_HashAlgos__RipeMd320 Ubifs_HashAlgos = 10
Ubifs_HashAlgos__Wp256 Ubifs_HashAlgos = 11
Ubifs_HashAlgos__Wp384 Ubifs_HashAlgos = 12
Ubifs_HashAlgos__Wp512 Ubifs_HashAlgos = 13
Ubifs_HashAlgos__Tgr128 Ubifs_HashAlgos = 14
Ubifs_HashAlgos__Tgr160 Ubifs_HashAlgos = 15
Ubifs_HashAlgos__Tgr192 Ubifs_HashAlgos = 16
Ubifs_HashAlgos__Sm3256 Ubifs_HashAlgos = 17
Ubifs_HashAlgos__Streebog256 Ubifs_HashAlgos = 18
Ubifs_HashAlgos__Streebog512 Ubifs_HashAlgos = 19
Ubifs_HashAlgos__Sha3256 Ubifs_HashAlgos = 20
Ubifs_HashAlgos__Sha3384 Ubifs_HashAlgos = 21
Ubifs_HashAlgos__Sha3512 Ubifs_HashAlgos = 22
)
var values_Ubifs_HashAlgos = map[Ubifs_HashAlgos]struct{}{0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {}, 8: {}, 9: {}, 10: {}, 11: {}, 12: {}, 13: {}, 14: {}, 15: {}, 16: {}, 17: {}, 18: {}, 19: {}, 20: {}, 21: {}, 22: {}}
func (v Ubifs_HashAlgos) isDefined() bool {
_, ok := values_Ubifs_HashAlgos[v]
return ok
}
type Ubifs_Hashes int
const (
Ubifs_Hashes__R5 Ubifs_Hashes = 0
Ubifs_Hashes__TestHash Ubifs_Hashes = 1
)
var values_Ubifs_Hashes = map[Ubifs_Hashes]struct{}{0: {}, 1: {}}
func (v Ubifs_Hashes) isDefined() bool {
_, ok := values_Ubifs_Hashes[v]
return ok
}
type Ubifs_InodeTypes int
const (
Ubifs_InodeTypes__Regular Ubifs_InodeTypes = 0
Ubifs_InodeTypes__Directory Ubifs_InodeTypes = 1
Ubifs_InodeTypes__Link Ubifs_InodeTypes = 2
Ubifs_InodeTypes__BlockDevice Ubifs_InodeTypes = 3
Ubifs_InodeTypes__CharacterDevice Ubifs_InodeTypes = 4
Ubifs_InodeTypes__Fifo Ubifs_InodeTypes = 5
Ubifs_InodeTypes__Socket Ubifs_InodeTypes = 6
)
var values_Ubifs_InodeTypes = map[Ubifs_InodeTypes]struct{}{0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}}
func (v Ubifs_InodeTypes) isDefined() bool {
_, ok := values_Ubifs_InodeTypes[v]
return ok
}
type Ubifs_KeyFormats int
const (
Ubifs_KeyFormats__Simple Ubifs_KeyFormats = 0
)
var values_Ubifs_KeyFormats = map[Ubifs_KeyFormats]struct{}{0: {}}
func (v Ubifs_KeyFormats) isDefined() bool {
_, ok := values_Ubifs_KeyFormats[v]
return ok
}
type Ubifs_KeyTypes int
const (
Ubifs_KeyTypes__Inode Ubifs_KeyTypes = 0
Ubifs_KeyTypes__Data Ubifs_KeyTypes = 1
Ubifs_KeyTypes__Directory Ubifs_KeyTypes = 2
Ubifs_KeyTypes__ExtendedAttribute Ubifs_KeyTypes = 3
)
var values_Ubifs_KeyTypes = map[Ubifs_KeyTypes]struct{}{0: {}, 1: {}, 2: {}, 3: {}}
func (v Ubifs_KeyTypes) isDefined() bool {
_, ok := values_Ubifs_KeyTypes[v]
return ok
}
type Ubifs_NodeGroupTypes int
const (
Ubifs_NodeGroupTypes__NoNodeGroup Ubifs_NodeGroupTypes = 0
Ubifs_NodeGroupTypes__InNodeGroup Ubifs_NodeGroupTypes = 1
Ubifs_NodeGroupTypes__LastOfNodeGroup Ubifs_NodeGroupTypes = 2
)
var values_Ubifs_NodeGroupTypes = map[Ubifs_NodeGroupTypes]struct{}{0: {}, 1: {}, 2: {}}
func (v Ubifs_NodeGroupTypes) isDefined() bool {
_, ok := values_Ubifs_NodeGroupTypes[v]
return ok
}
type Ubifs_NodeTypes int
const (
Ubifs_NodeTypes__Inode Ubifs_NodeTypes = 0
Ubifs_NodeTypes__Data Ubifs_NodeTypes = 1
Ubifs_NodeTypes__Directory Ubifs_NodeTypes = 2
Ubifs_NodeTypes__ExtendedAttribute Ubifs_NodeTypes = 3
Ubifs_NodeTypes__Truncation Ubifs_NodeTypes = 4
Ubifs_NodeTypes__Padding Ubifs_NodeTypes = 5
Ubifs_NodeTypes__Superblock Ubifs_NodeTypes = 6
Ubifs_NodeTypes__Master Ubifs_NodeTypes = 7
Ubifs_NodeTypes__Reference Ubifs_NodeTypes = 8
Ubifs_NodeTypes__Index Ubifs_NodeTypes = 9
Ubifs_NodeTypes__CommitStart Ubifs_NodeTypes = 10
Ubifs_NodeTypes__Orphan Ubifs_NodeTypes = 11
Ubifs_NodeTypes__Authentication Ubifs_NodeTypes = 12
Ubifs_NodeTypes__Signature Ubifs_NodeTypes = 13
)
var values_Ubifs_NodeTypes = map[Ubifs_NodeTypes]struct{}{0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {}, 8: {}, 9: {}, 10: {}, 11: {}, 12: {}, 13: {}}
func (v Ubifs_NodeTypes) isDefined() bool {
_, ok := values_Ubifs_NodeTypes[v]
return ok
}
type Ubifs struct {
_io *kaitai.Stream
_root *Ubifs
_parent kaitai.Struct
_raw_index []byte
_raw_master1 []byte
_raw_master2 []byte
_f_index bool
index *Ubifs_Dummy
_f_indexRoot bool
indexRoot *Ubifs_IndexBlock
_f_lebs bool
lebs [][]byte
_f_lenImage bool
lenImage int
_f_master1 bool
master1 *Ubifs_MasterblockNode
_f_master2 bool
master2 *Ubifs_MasterblockNode
_f_superblock bool
superblock *Ubifs_SuperblockNode
}
func NewUbifs() *Ubifs {
return &Ubifs{
}
}
func (this Ubifs) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs) Read(io *kaitai.Stream, parent kaitai.Struct, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
return err
}
/**
* The LEB containing the root index node, as given by `leb_root` in
* `master_1`.
*
* This instance only provides the substream for `index_root`, which can then
* use `ofs_root` (an offset within the LEB) as its `pos` directly.
*/
func (this *Ubifs) Index() (v *Ubifs_Dummy, err error) {
if (this._f_index) {
return this.index, nil
}
this._f_index = true
_pos, err := this._io.Pos()
if err != nil {
return nil, err
}
tmp1, err := this.Superblock()
if err != nil {
return nil, err
}
tmp2, err := this.Master1()
if err != nil {
return nil, err
}
_, err = this._io.Seek(int64(tmp1.NodeHeader.LebSize * tmp2.NodeHeader.LebRoot), io.SeekStart)
if err != nil {
return nil, err
}
tmp3, err := this.Superblock()
if err != nil {
return nil, err
}
tmp4, err := this._io.ReadBytes(int(tmp3.NodeHeader.LebSize))
if err != nil {
return nil, err
}
tmp4 = tmp4
this._raw_index = tmp4
_io__raw_index := kaitai.NewStream(bytes.NewReader(this._raw_index))
tmp5 := NewUbifs_Dummy()
err = tmp5.Read(_io__raw_index, this, this._root)
if err != nil {
return nil, err
}
this.index = tmp5
_, err = this._io.Seek(_pos, io.SeekStart)
if err != nil {
return nil, err
}
return this.index, nil
}
/**
* The root index node, in the `index` LEB at the offset given by
* `ofs_root` in `master_1`. All other index nodes, and through them all
* the files, are reached from it by recursively following the `target` of
* each of the `branches`.
*/
func (this *Ubifs) IndexRoot() (v *Ubifs_IndexBlock, err error) {
if (this._f_indexRoot) {
return this.indexRoot, nil
}
this._f_indexRoot = true
tmp6, err := this.Index()
if err != nil {
return nil, err
}
thisIo := tmp6._io
_pos, err := thisIo.Pos()
if err != nil {
return nil, err
}
tmp7, err := this.Master1()
if err != nil {
return nil, err
}
_, err = thisIo.Seek(int64(tmp7.NodeHeader.OfsRoot), io.SeekStart)
if err != nil {
return nil, err
}
tmp8 := NewUbifs_IndexBlock()
err = tmp8.Read(thisIo, this, this._root)
if err != nil {
return nil, err
}
this.indexRoot = tmp8
{
_it := this.indexRoot
tmp9, err := this.Master1()
if err != nil {
return nil, err
}
if !(_it.Header.LenFullNode == tmp9.NodeHeader.LenRoot) {
return nil, kaitai.NewValidationExprError(this.indexRoot, this._io, "/instances/index_root")
}
}
_, err = thisIo.Seek(_pos, io.SeekStart)
if err != nil {
return nil, err
}
return this.indexRoot, nil
}
/**
* All LEBs of the file system: `lebs[n]` is LEB number `n`, which starts
* at offset `n * <superblock_header>.leb_size`.
*
* Accessing this instance reads the whole image into memory. To get a
* single LEB, it's cheaper to read `<superblock_header>.leb_size` bytes
* at the offset of that LEB.
*/
func (this *Ubifs) Lebs() (v [][]byte, err error) {
if (this._f_lebs) {
return this.lebs, nil
}
this._f_lebs = true
_pos, err := this._io.Pos()
if err != nil {
return nil, err
}
_, err = this._io.Seek(int64(0), io.SeekStart)
if err != nil {
return nil, err
}
tmp10, err := this.Superblock()
if err != nil {
return nil, err
}
for i := 0; i < int(tmp10.NodeHeader.NumLebs); i++ {
_ = i
tmp11, err := this.Superblock()
if err != nil {
return nil, err
}
tmp12, err := this._io.ReadBytes(int(tmp11.NodeHeader.LebSize))
if err != nil {
return nil, err
}
tmp12 = tmp12
this.lebs = append(this.lebs, tmp12)
}
_, err = this._io.Seek(_pos, io.SeekStart)
if err != nil {
return nil, err
}
return this.lebs, nil
}
/**
* Length of the file system image in bytes:
* `<superblock_header>.num_lebs` LEBs of `<superblock_header>.leb_size`
* bytes each. Use it to find where the image ends and to detect a
* truncated image (see the top-level `doc`).
*/
func (this *Ubifs) LenImage() (v int, err error) {
if (this._f_lenImage) {
return this.lenImage, nil
}
this._f_lenImage = true
tmp13, err := this.Superblock()
if err != nil {
return 0, err
}
tmp14, err := this.Superblock()
if err != nil {
return 0, err
}
this.lenImage = int(tmp13.NodeHeader.LebSize * tmp14.NodeHeader.NumLebs)
return this.lenImage, nil
}
/**
* The first copy of the master node in LEB1. This Kaitai Struct
* implementation uses it to locate `index_root`. In an image created by
* `mkfs.ubifs`, it is the only copy in LEB1.
* @see <a href="https://github.com/sigma-star/mtd-utils/blob/053ee1038e5dedae61a88cadfb7bdfe9894d8bb6/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c#L2627-L2633">Git tag "v2.3.1"</a>
*/
func (this *Ubifs) Master1() (v *Ubifs_MasterblockNode, err error) {
if (this._f_master1) {
return this.master1, nil
}
this._f_master1 = true
_pos, err := this._io.Pos()
if err != nil {
return nil, err
}
tmp15, err := this.Superblock()
if err != nil {
return nil, err
}
_, err = this._io.Seek(int64(tmp15.NodeHeader.LebSize), io.SeekStart)
if err != nil {
return nil, err
}
tmp16, err := this.Superblock()
if err != nil {
return nil, err
}
tmp17, err := this._io.ReadBytes(int(tmp16.NodeHeader.LebSize))
if err != nil {
return nil, err
}
tmp17 = tmp17
this._raw_master1 = tmp17
_io__raw_master1 := kaitai.NewStream(bytes.NewReader(this._raw_master1))
tmp18 := NewUbifs_MasterblockNode()
err = tmp18.Read(_io__raw_master1, this, this._root)
if err != nil {
return nil, err
}
this.master1 = tmp18
_, err = this._io.Seek(_pos, io.SeekStart)
if err != nil {
return nil, err
}
return this.master1, nil
}
/**
* The first copy of the master node in LEB2. In an image created by
* `mkfs.ubifs`, it is the same as `master_1` except for the sequence
* number and CRC in the common header. Linux keeps the master node in both
* LEB1 and LEB2 for redundancy, and when mounting, it checks that the
* copies in both match.
* @see <a href="https://github.com/sigma-star/mtd-utils/blob/053ee1038e5dedae61a88cadfb7bdfe9894d8bb6/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c#L2627-L2633">Git tag "v2.3.1"</a>
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/master.c#L115-L130">Git tag "v7.2"</a>
*/
func (this *Ubifs) Master2() (v *Ubifs_MasterblockNode, err error) {
if (this._f_master2) {
return this.master2, nil
}
this._f_master2 = true
_pos, err := this._io.Pos()
if err != nil {
return nil, err
}
tmp19, err := this.Superblock()
if err != nil {
return nil, err
}
_, err = this._io.Seek(int64(tmp19.NodeHeader.LebSize * 2), io.SeekStart)
if err != nil {
return nil, err
}
tmp20, err := this.Superblock()
if err != nil {
return nil, err
}
tmp21, err := this._io.ReadBytes(int(tmp20.NodeHeader.LebSize))
if err != nil {
return nil, err
}
tmp21 = tmp21
this._raw_master2 = tmp21
_io__raw_master2 := kaitai.NewStream(bytes.NewReader(this._raw_master2))
tmp22 := NewUbifs_MasterblockNode()
err = tmp22.Read(_io__raw_master2, this, this._root)
if err != nil {
return nil, err
}
this.master2 = tmp22
_, err = this._io.Seek(_pos, io.SeekStart)
if err != nil {
return nil, err
}
return this.master2, nil
}
/**
* The superblock node will always be at the start of
* the first LEB.
*/
func (this *Ubifs) Superblock() (v *Ubifs_SuperblockNode, err error) {
if (this._f_superblock) {
return this.superblock, nil
}
this._f_superblock = true
_pos, err := this._io.Pos()
if err != nil {
return nil, err
}
_, err = this._io.Seek(int64(0), io.SeekStart)
if err != nil {
return nil, err
}
tmp23 := NewUbifs_SuperblockNode()
err = tmp23.Read(this._io, this, this._root)
if err != nil {
return nil, err
}
this.superblock = tmp23
_, err = this._io.Seek(_pos, io.SeekStart)
if err != nil {
return nil, err
}
return this.superblock, nil
}
/**
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L774-L782">Git tag "v7.2"</a>
*/
type Ubifs_AuthenticationHeader struct {
Hmac []byte
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs_Block
}
func NewUbifs_AuthenticationHeader() *Ubifs_AuthenticationHeader {
return &Ubifs_AuthenticationHeader{
}
}
func (this Ubifs_AuthenticationHeader) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_AuthenticationHeader) Read(io *kaitai.Stream, parent *Ubifs_Block, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp24, err := this._root.Superblock()
if err != nil {
return err
}
tmp25, err := tmp24.NodeHeader.LenHash()
if err != nil {
return err
}
tmp26, err := this._io.ReadBytes(int(tmp25))
if err != nil {
return err
}
tmp26 = tmp26
this.Hmac = tmp26
return err
}
/**
* HMAC authenticating the journal before this node, keyed with the
* file system's authentication key (which is not stored on flash).
* The kernel [uses](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/auth.c#L275-L276)
* HMAC with the hash algorithm in `<superblock_header>.hash_algo`
* ([checked when mounting](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/sb.c#L575-L580)),
* so `hmac` is as long as its digest, e.g. 32 bytes for SHA-256.
*/
type Ubifs_Block struct {
Header *Ubifs_CommonHeader
NodeHeader interface{}
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs_Branch
_raw_NodeHeader []byte
}
func NewUbifs_Block() *Ubifs_Block {
return &Ubifs_Block{
}
}
func (this Ubifs_Block) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_Block) Read(io *kaitai.Stream, parent *Ubifs_Branch, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp27 := NewUbifs_CommonHeader()
err = tmp27.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Header = tmp27
switch (this.Header.NodeType) {
case Ubifs_NodeTypes__Authentication:
tmp28, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp28 = tmp28
this._raw_NodeHeader = tmp28
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp29 := NewUbifs_AuthenticationHeader()
err = tmp29.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp29
case Ubifs_NodeTypes__CommitStart:
tmp30, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp30 = tmp30
this._raw_NodeHeader = tmp30
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp31 := NewUbifs_CommitStartHeader()
err = tmp31.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp31
case Ubifs_NodeTypes__Data:
tmp32, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp32 = tmp32
this._raw_NodeHeader = tmp32
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp33 := NewUbifs_DataHeader()
err = tmp33.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp33
case Ubifs_NodeTypes__Directory:
tmp34, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp34 = tmp34
this._raw_NodeHeader = tmp34
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp35 := NewUbifs_DirectoryHeader()
err = tmp35.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp35
case Ubifs_NodeTypes__ExtendedAttribute:
tmp36, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp36 = tmp36
this._raw_NodeHeader = tmp36
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp37 := NewUbifs_DirectoryHeader()
err = tmp37.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp37
case Ubifs_NodeTypes__Index:
tmp38, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp38 = tmp38
this._raw_NodeHeader = tmp38
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp39 := NewUbifs_IndexHeader()
err = tmp39.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp39
case Ubifs_NodeTypes__Inode:
tmp40, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp40 = tmp40
this._raw_NodeHeader = tmp40
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp41 := NewUbifs_InodeHeader()
err = tmp41.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp41
case Ubifs_NodeTypes__Master:
tmp42, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp42 = tmp42
this._raw_NodeHeader = tmp42
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp43 := NewUbifs_MasterHeader()
err = tmp43.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp43
case Ubifs_NodeTypes__Orphan:
tmp44, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp44 = tmp44
this._raw_NodeHeader = tmp44
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp45 := NewUbifs_OrphanHeader()
err = tmp45.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp45
case Ubifs_NodeTypes__Padding:
tmp46, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp46 = tmp46
this._raw_NodeHeader = tmp46
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp47 := NewUbifs_PaddingHeader()
err = tmp47.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp47
case Ubifs_NodeTypes__Reference:
tmp48, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp48 = tmp48
this._raw_NodeHeader = tmp48
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp49 := NewUbifs_ReferenceHeader()
err = tmp49.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp49
case Ubifs_NodeTypes__Signature:
tmp50, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp50 = tmp50
this._raw_NodeHeader = tmp50
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp51 := NewUbifs_SignatureHeader()
err = tmp51.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp51
case Ubifs_NodeTypes__Superblock:
tmp52, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp52 = tmp52
this._raw_NodeHeader = tmp52
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp53 := NewUbifs_SuperblockHeader()
err = tmp53.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp53
case Ubifs_NodeTypes__Truncation:
tmp54, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp54 = tmp54
this._raw_NodeHeader = tmp54
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp55 := NewUbifs_TruncationHeader()
err = tmp55.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp55
default:
tmp56, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp56 = tmp56
this._raw_NodeHeader = tmp56
}
return err
}
/**
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L801-L817">Git tag "v7.2"</a>
*/
type Ubifs_Branch struct {
TargetLeb uint32
OfsTarget uint32
LenTarget uint32
Key *Ubifs_Key
Hash []byte
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs_IndexHeader
_raw_Key []byte
_raw_target []byte
_f_target bool
target *Ubifs_Block
}
func NewUbifs_Branch() *Ubifs_Branch {
return &Ubifs_Branch{
}
}
func (this Ubifs_Branch) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_Branch) Read(io *kaitai.Stream, parent *Ubifs_IndexHeader, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp57, err := this._io.ReadU4le()
if err != nil {
return err
}
this.TargetLeb = uint32(tmp57)
tmp58, err := this._io.ReadU4le()
if err != nil {
return err
}
this.OfsTarget = uint32(tmp58)
tmp59, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LenTarget = uint32(tmp59)
tmp60, err := this._io.ReadBytes(int(8))
if err != nil {
return err
}
tmp60 = tmp60
this._raw_Key = tmp60
_io__raw_Key := kaitai.NewStream(bytes.NewReader(this._raw_Key))
tmp61 := NewUbifs_Key()
err = tmp61.Read(_io__raw_Key, this, this._root)
if err != nil {
return err
}
this.Key = tmp61
tmp62, err := this._root.Superblock()
if err != nil {
return err
}
tmp63, err := tmp62.NodeHeader.LenHash()
if err != nil {
return err
}
tmp64, err := this._io.ReadBytes(int(tmp63))
if err != nil {
return err
}
tmp64 = tmp64
this.Hash = tmp64
return err
}
func (this *Ubifs_Branch) Target() (v *Ubifs_Block, err error) {
if (this._f_target) {
return this.target, nil
}
this._f_target = true
thisIo := this._root._io
_pos, err := thisIo.Pos()
if err != nil {
return nil, err
}
tmp65, err := this._root.Superblock()
if err != nil {
return nil, err
}
_, err = thisIo.Seek(int64(tmp65.NodeHeader.LebSize * this.TargetLeb + this.OfsTarget), io.SeekStart)
if err != nil {
return nil, err
}
tmp66, err := thisIo.ReadBytes(int(this.LenTarget))
if err != nil {
return nil, err
}
tmp66 = tmp66
this._raw_target = tmp66
_io__raw_target := kaitai.NewStream(bytes.NewReader(this._raw_target))
tmp67 := NewUbifs_Block()
err = tmp67.Read(_io__raw_target, this, this._root)
if err != nil {
return nil, err
}
this.target = tmp67
{
_it := this.target
var tmp68 bool;
if (this._parent.Level != 0) {
tmp68 = _it.Header.NodeType == Ubifs_NodeTypes__Index
} else {
tmp68 = _it.Header.NodeType == this.Key.Type
}
if !( ((_it.Header.LenFullNode == this.LenTarget) && (tmp68)) ) {
return nil, kaitai.NewValidationExprError(this.target, this._io, "/types/branch/instances/target")
}
}
_, err = thisIo.Seek(_pos, io.SeekStart)
if err != nil {
return nil, err
}
return this.target, nil
}
/**
* LEB number of the target node
*/
/**
* offset within the LEB `target_leb`
*/
/**
* target node length
*/
/**
* Hash of the target node. It is empty in a file system without
* authentication (see `<superblock_header>.len_hash`).
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs.h#L1642-L1654">Git tag "v7.2"</a>
*/
/**
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L833-L841">Git tag "v7.2"</a>
*/
type Ubifs_CommitStartHeader struct {
CommitNumber uint64
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs_Block
}
func NewUbifs_CommitStartHeader() *Ubifs_CommitStartHeader {
return &Ubifs_CommitStartHeader{
}
}
func (this Ubifs_CommitStartHeader) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_CommitStartHeader) Read(io *kaitai.Stream, parent *Ubifs_Block, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp69, err := this._io.ReadU8le()
if err != nil {
return err
}
this.CommitNumber = uint64(tmp69)
return err
}
/**
* commit number
*/
/**
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L443-L464">Git tag "v7.2"</a>
*/
type Ubifs_CommonHeader struct {
Magic uint32
Crc uint32
SequenceNumber uint64
LenFullNode uint32
NodeType Ubifs_NodeTypes
GroupType Ubifs_NodeGroupTypes
Padding []byte
_io *kaitai.Stream
_root *Ubifs
_parent kaitai.Struct
}
func NewUbifs_CommonHeader() *Ubifs_CommonHeader {
return &Ubifs_CommonHeader{
}
}
func (this Ubifs_CommonHeader) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_CommonHeader) Read(io *kaitai.Stream, parent kaitai.Struct, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp70, err := this._io.ReadU4le()
if err != nil {
return err
}
this.Magic = uint32(tmp70)
if !(this.Magic == 101718065) {
return kaitai.NewValidationNotEqualError(101718065, this.Magic, this._io, "/types/common_header/seq/0")
}
tmp71, err := this._io.ReadU4le()
if err != nil {
return err
}
this.Crc = uint32(tmp71)
tmp72, err := this._io.ReadU8le()
if err != nil {
return err
}
this.SequenceNumber = uint64(tmp72)
tmp73, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LenFullNode = uint32(tmp73)
tmp74, err := this._io.ReadU1()
if err != nil {
return err
}
this.NodeType = Ubifs_NodeTypes(tmp74)
tmp75, err := this._io.ReadU1()
if err != nil {
return err
}
this.GroupType = Ubifs_NodeGroupTypes(tmp75)
tmp76, err := this._io.ReadBytes(int(2))
if err != nil {
return err
}
tmp76 = tmp76
this.Padding = tmp76
if !(bytes.Equal(this.Padding, []uint8{0, 0})) {
return kaitai.NewValidationNotEqualError([]uint8{0, 0}, this.Padding, this._io, "/types/common_header/seq/6")
}
return err
}
/**
* UBIFS node magic number (`UBIFS_NODE_MAGIC`)
*/
/**
* CRC-32 checksum of the whole node except `magic` and `crc` (i.e.
* starting at offset 8). It is computed with an initial register value
* of 0xFFFFFFFF and no final XOR, so it is the bitwise NOT of a standard
* CRC-32 (e.g.
* [`zlib.crc32()`](https://docs.python.org/3/library/zlib.html#zlib.crc32)
* in Python).
*/
/**
* sequence number
*/
/**
* full node length
*/
/**
* node type
*/
/**
* node group type
*/
/**
* reserved for future, zeroes
*/
/**
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L567-L584">Git tag "v7.2"</a>
*/
type Ubifs_DataHeader struct {
Key *Ubifs_Key
LenUncompressed uint32
Compression Ubifs_Compression
LenCompressedData uint16
Data []byte
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs_Block
_raw_Key []byte
}
func NewUbifs_DataHeader() *Ubifs_DataHeader {
return &Ubifs_DataHeader{
}
}
func (this Ubifs_DataHeader) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_DataHeader) Read(io *kaitai.Stream, parent *Ubifs_Block, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp77, err := this._io.ReadBytes(int(16))
if err != nil {
return err
}
tmp77 = tmp77
this._raw_Key = tmp77
_io__raw_Key := kaitai.NewStream(bytes.NewReader(this._raw_Key))
tmp78 := NewUbifs_Key()
err = tmp78.Read(_io__raw_Key, this, this._root)
if err != nil {
return err
}
this.Key = tmp78
tmp79, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LenUncompressed = uint32(tmp79)
if !(this.LenUncompressed >= 1) {
return kaitai.NewValidationLessThanError(1, this.LenUncompressed, this._io, "/types/data_header/seq/1")
}
if !(this.LenUncompressed <= 4096) {
return kaitai.NewValidationGreaterThanError(4096, this.LenUncompressed, this._io, "/types/data_header/seq/1")
}
tmp80, err := this._io.ReadU2le()
if err != nil {
return err
}
this.Compression = Ubifs_Compression(tmp80)
if !this.Compression.isDefined() {
return kaitai.NewValidationNotInEnumError(this.Compression, this._io, "/types/data_header/seq/2")
}
tmp81, err := this._io.ReadU2le()
if err != nil {
return err
}
this.LenCompressedData = uint16(tmp81)
tmp82, err := this._io.ReadBytesFull()
if err != nil {
return err
}
tmp82 = tmp82
this.Data = tmp82
return err
}
/**
* node key
*/
/**
* uncompressed data size in bytes
*/
/**
* compression type (`compression::no_compression`, `compression::lzo`,
* etc.)
*/
/**
* compressed data size in bytes, only valid when data is encrypted
*/
/**
* One block (up to 4096 bytes) of the file, block number `key.value`,
* compressed as given by `compression`. Blocks missing from the index
* are holes (zeros). In an encrypted inode, the compressed data is
* padded
* and [encrypted](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/crypto.c#L38-L59),
* and `len_compressed_data` is the length of the compressed data
* before padding.
*/
/**
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L541-L565">Git tag "v7.2"</a>
*/
type Ubifs_DirectoryHeader struct {
Key *Ubifs_Key
InodeNumber uint64
Padding1 []byte
InodeType Ubifs_InodeTypes
LenName uint16
Cookie uint32
Name []byte
NameTerminator []byte
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs_Block
_raw_Key []byte
}
func NewUbifs_DirectoryHeader() *Ubifs_DirectoryHeader {
return &Ubifs_DirectoryHeader{
}
}
func (this Ubifs_DirectoryHeader) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_DirectoryHeader) Read(io *kaitai.Stream, parent *Ubifs_Block, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp83, err := this._io.ReadBytes(int(16))
if err != nil {
return err
}
tmp83 = tmp83
this._raw_Key = tmp83
_io__raw_Key := kaitai.NewStream(bytes.NewReader(this._raw_Key))
tmp84 := NewUbifs_Key()
err = tmp84.Read(_io__raw_Key, this, this._root)
if err != nil {
return err
}
this.Key = tmp84
{
_it := this.Key
if !( ((_it.Type == Ubifs_KeyTypes__Directory) || (_it.Type == Ubifs_KeyTypes__ExtendedAttribute)) ) {
return kaitai.NewValidationExprError(this.Key, this._io, "/types/directory_header/seq/0")
}
}
tmp85, err := this._io.ReadU8le()
if err != nil {
return err
}
this.InodeNumber = uint64(tmp85)
if !(this.InodeNumber <= uint32(4294967295)) {
return kaitai.NewValidationGreaterThanError(uint32(4294967295), this.InodeNumber, this._io, "/types/directory_header/seq/1")
}
tmp86, err := this._io.ReadBytes(int(1))
if err != nil {
return err
}
tmp86 = tmp86
this.Padding1 = tmp86
if !(bytes.Equal(this.Padding1, []uint8{0})) {
return kaitai.NewValidationNotEqualError([]uint8{0}, this.Padding1, this._io, "/types/directory_header/seq/2")
}
tmp87, err := this._io.ReadU1()
if err != nil {
return err
}
this.InodeType = Ubifs_InodeTypes(tmp87)
if !this.InodeType.isDefined() {
return kaitai.NewValidationNotInEnumError(this.InodeType, this._io, "/types/directory_header/seq/3")
}
tmp88, err := this._io.ReadU2le()
if err != nil {
return err
}
this.LenName = uint16(tmp88)
tmp89, err := this._io.ReadU4le()
if err != nil {
return err
}
this.Cookie = uint32(tmp89)
tmp90, err := this._io.ReadBytes(int(this.LenName))
if err != nil {
return err
}
tmp90 = tmp90
this.Name = tmp90
tmp91, err := this._io.ReadBytes(int(1))
if err != nil {
return err
}
tmp91 = tmp91
this.NameTerminator = tmp91
if !(bytes.Equal(this.NameTerminator, []uint8{0})) {
return kaitai.NewValidationNotEqualError([]uint8{0}, this.NameTerminator, this._io, "/types/directory_header/seq/7")
}
return err
}
/**
* node key
*/
/**
* target inode number
*/
/**
* reserved for future, zeroes
*/
/**
* type of the target inode (`inode_types::regular`,
* `inode_types::directory`, etc.)
*/
/**
* name length
*/
/**
* A 32bits random number, used to construct a 64bits identifier.
*/
/**
* Name of the entry.
*
* It is kept as bytes rather than decoded as a string: names in a
* directory whose inode has `<inode_header>.encrypted` set are
* ciphertext, which may contain any bytes, including zeros.
*
* Unencrypted names, including all names of extended attributes, contain
* no zero bytes, because Linux can't create such names. They aren't
* necessarily valid UTF-8, though, as UBIFS doesn't enforce any encoding
* of file names. A zero byte in such a name means that the image was
* crafted, since an accidental corruption would most likely fail the
* node's
* [CRC check](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/io.c#L287-L293).
*/
/**
* Zero byte after `name`, [not counted in
* `len_name`](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/replay.c#L487-L489).
*/
type Ubifs_Dummy struct {
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs
}
func NewUbifs_Dummy() *Ubifs_Dummy {
return &Ubifs_Dummy{
}
}
func (this Ubifs_Dummy) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_Dummy) Read(io *kaitai.Stream, parent *Ubifs, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
return err
}
type Ubifs_IndexBlock struct {
Header *Ubifs_CommonHeader
NodeHeader *Ubifs_IndexHeader
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs
_raw_NodeHeader []byte
}
func NewUbifs_IndexBlock() *Ubifs_IndexBlock {
return &Ubifs_IndexBlock{
}
}
func (this Ubifs_IndexBlock) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_IndexBlock) Read(io *kaitai.Stream, parent *Ubifs, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp92 := NewUbifs_CommonHeader()
err = tmp92.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Header = tmp92
{
_it := this.Header
if !(_it.NodeType == Ubifs_NodeTypes__Index) {
return kaitai.NewValidationExprError(this.Header, this._io, "/types/index_block/seq/0")
}
}
tmp93, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp93 = tmp93
this._raw_NodeHeader = tmp93
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp94 := NewUbifs_IndexHeader()
err = tmp94.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp94
return err
}
/**
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L819-L831">Git tag "v7.2"</a>
*/
type Ubifs_IndexHeader struct {
NumBranches uint16
Level uint16
Branches []*Ubifs_Branch
_io *kaitai.Stream
_root *Ubifs
_parent kaitai.Struct
}
func NewUbifs_IndexHeader() *Ubifs_IndexHeader {
return &Ubifs_IndexHeader{
}
}
func (this Ubifs_IndexHeader) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_IndexHeader) Read(io *kaitai.Stream, parent kaitai.Struct, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp95, err := this._io.ReadU2le()
if err != nil {
return err
}
this.NumBranches = uint16(tmp95)
tmp96, err := this._io.ReadU2le()
if err != nil {
return err
}
this.Level = uint16(tmp96)
for i := 0; i < int(this.NumBranches); i++ {
_ = i
tmp97 := NewUbifs_Branch()
err = tmp97.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Branches = append(this.Branches, tmp97)
}
return err
}
/**
* number of child index nodes
*/
/**
* tree level
*/
/**
* LEB number / offset / length / key branches
*
* All branches have the same size, which is 20 bytes (with the simple
* key format) plus the hash length in an authenticated file system.
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/misc.h#L186-L205">Git tag "v7.2"</a>
*/
/**
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L480-L539">Git tag "v7.2"</a>
*/
type Ubifs_InodeHeader struct {
Key *Ubifs_Key
CreationSequenceNumber uint64
LenUncompressed uint64
AtimeSec uint64
CtimeSec uint64
MtimeSec uint64
AtimeNsec uint32
CtimeNsec uint32
MtimeNsec uint32
NumLinks uint32
Uid uint32
Gid uint32
Mode uint32
Flags uint32
LenData uint32
NumXattrs uint32
XattrSize uint32
Padding1 []byte
XattrNames uint32
Compression Ubifs_Compression
Padding2 []byte
Data []byte
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs_Block
_raw_Key []byte
_f_append bool
append bool
_f_compressed bool
compressed bool
_f_dirsync bool
dirsync bool
_f_encrypted bool
encrypted bool
_f_immutable bool
immutable bool
_f_isBlockDevice bool
isBlockDevice bool
_f_isCharacterDevice bool
isCharacterDevice bool
_f_isDir bool
isDir bool
_f_isFifo bool
isFifo bool
_f_isLink bool
isLink bool
_f_isRegular bool
isRegular bool
_f_isSocket bool
isSocket bool
_f_synchronous bool
synchronous bool
_f_xattr bool
xattr bool
}
func NewUbifs_InodeHeader() *Ubifs_InodeHeader {
return &Ubifs_InodeHeader{
}
}
func (this Ubifs_InodeHeader) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_InodeHeader) Read(io *kaitai.Stream, parent *Ubifs_Block, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp98, err := this._io.ReadBytes(int(16))
if err != nil {
return err
}
tmp98 = tmp98
this._raw_Key = tmp98
_io__raw_Key := kaitai.NewStream(bytes.NewReader(this._raw_Key))
tmp99 := NewUbifs_Key()
err = tmp99.Read(_io__raw_Key, this, this._root)
if err != nil {
return err
}
this.Key = tmp99
tmp100, err := this._io.ReadU8le()
if err != nil {
return err
}
this.CreationSequenceNumber = uint64(tmp100)
tmp101, err := this._io.ReadU8le()
if err != nil {
return err
}
this.LenUncompressed = uint64(tmp101)
tmp102, err := this._io.ReadU8le()
if err != nil {
return err
}
this.AtimeSec = uint64(tmp102)
tmp103, err := this._io.ReadU8le()
if err != nil {
return err
}
this.CtimeSec = uint64(tmp103)
tmp104, err := this._io.ReadU8le()
if err != nil {
return err
}
this.MtimeSec = uint64(tmp104)
tmp105, err := this._io.ReadU4le()
if err != nil {
return err
}
this.AtimeNsec = uint32(tmp105)
tmp106, err := this._io.ReadU4le()
if err != nil {
return err
}
this.CtimeNsec = uint32(tmp106)
tmp107, err := this._io.ReadU4le()
if err != nil {
return err
}
this.MtimeNsec = uint32(tmp107)
tmp108, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumLinks = uint32(tmp108)
tmp109, err := this._io.ReadU4le()
if err != nil {
return err
}
this.Uid = uint32(tmp109)
tmp110, err := this._io.ReadU4le()
if err != nil {
return err
}
this.Gid = uint32(tmp110)
tmp111, err := this._io.ReadU4le()
if err != nil {
return err
}
this.Mode = uint32(tmp111)
tmp112, err := this._io.ReadU4le()
if err != nil {
return err
}
this.Flags = uint32(tmp112)
tmp113, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LenData = uint32(tmp113)
tmp114, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumXattrs = uint32(tmp114)
tmp115, err := this._io.ReadU4le()
if err != nil {
return err
}
this.XattrSize = uint32(tmp115)
tmp116, err := this._io.ReadBytes(int(4))
if err != nil {
return err
}
tmp116 = tmp116
this.Padding1 = tmp116
if !(bytes.Equal(this.Padding1, []uint8{0, 0, 0, 0})) {
return kaitai.NewValidationNotEqualError([]uint8{0, 0, 0, 0}, this.Padding1, this._io, "/types/inode_header/seq/17")
}
tmp117, err := this._io.ReadU4le()
if err != nil {
return err
}
this.XattrNames = uint32(tmp117)
tmp118, err := this._io.ReadU2le()
if err != nil {
return err
}
this.Compression = Ubifs_Compression(tmp118)
if !this.Compression.isDefined() {
return kaitai.NewValidationNotInEnumError(this.Compression, this._io, "/types/inode_header/seq/19")
}
tmp119, err := this._io.ReadBytes(int(26))
if err != nil {
return err
}
tmp119 = tmp119
this.Padding2 = tmp119
tmp120, err := this._io.ReadBytes(int(this.LenData))
if err != nil {
return err
}
tmp120 = tmp120
this.Data = tmp120
return err
}
/**
* writes to the inode may only append data
*/
func (this *Ubifs_InodeHeader) Append() (v bool, err error) {
if (this._f_append) {
return this.append, nil
}
this._f_append = true
this.append = bool(this.Flags & 8 != 0)
return this.append, nil
}
/**
* use compression for this inode
*/
func (this *Ubifs_InodeHeader) Compressed() (v bool, err error) {
if (this._f_compressed) {
return this.compressed, nil
}
this._f_compressed = true
this.compressed = bool(this.Flags & 1 != 0)
return this.compressed, nil
}
/**
* I/O on this directory inode has to be synchronous
*/
func (this *Ubifs_InodeHeader) Dirsync() (v bool, err error) {
if (this._f_dirsync) {
return this.dirsync, nil
}
this._f_dirsync = true
this.dirsync = bool(this.Flags & 16 != 0)
return this.dirsync, nil
}
/**
* use encryption for this inode
*/
func (this *Ubifs_InodeHeader) Encrypted() (v bool, err error) {
if (this._f_encrypted) {
return this.encrypted, nil
}
this._f_encrypted = true
this.encrypted = bool(this.Flags & 64 != 0)
return this.encrypted, nil
}
/**
* inode is immutable
*/
func (this *Ubifs_InodeHeader) Immutable() (v bool, err error) {
if (this._f_immutable) {
return this.immutable, nil
}
this._f_immutable = true
this.immutable = bool(this.Flags & 4 != 0)
return this.immutable, nil
}
func (this *Ubifs_InodeHeader) IsBlockDevice() (v bool, err error) {
if (this._f_isBlockDevice) {
return this.isBlockDevice, nil
}
this._f_isBlockDevice = true
this.isBlockDevice = bool(this.Mode & 61440 == 24576)
return this.isBlockDevice, nil
}
func (this *Ubifs_InodeHeader) IsCharacterDevice() (v bool, err error) {
if (this._f_isCharacterDevice) {
return this.isCharacterDevice, nil
}
this._f_isCharacterDevice = true
this.isCharacterDevice = bool(this.Mode & 61440 == 8192)
return this.isCharacterDevice, nil
}
func (this *Ubifs_InodeHeader) IsDir() (v bool, err error) {
if (this._f_isDir) {
return this.isDir, nil
}
this._f_isDir = true
this.isDir = bool(this.Mode & 61440 == 16384)
return this.isDir, nil
}
func (this *Ubifs_InodeHeader) IsFifo() (v bool, err error) {
if (this._f_isFifo) {
return this.isFifo, nil
}
this._f_isFifo = true
this.isFifo = bool(this.Mode & 61440 == 4096)
return this.isFifo, nil
}
func (this *Ubifs_InodeHeader) IsLink() (v bool, err error) {
if (this._f_isLink) {
return this.isLink, nil
}
this._f_isLink = true
this.isLink = bool(this.Mode & 61440 == 40960)
return this.isLink, nil
}
func (this *Ubifs_InodeHeader) IsRegular() (v bool, err error) {
if (this._f_isRegular) {
return this.isRegular, nil
}
this._f_isRegular = true
this.isRegular = bool(this.Mode & 61440 == 32768)
return this.isRegular, nil
}
func (this *Ubifs_InodeHeader) IsSocket() (v bool, err error) {
if (this._f_isSocket) {
return this.isSocket, nil
}
this._f_isSocket = true
this.isSocket = bool(this.Mode & 61440 == 49152)
return this.isSocket, nil
}
/**
* I/O on this inode has to be synchronous
*/
func (this *Ubifs_InodeHeader) Synchronous() (v bool, err error) {
if (this._f_synchronous) {
return this.synchronous, nil
}
this._f_synchronous = true
this.synchronous = bool(this.Flags & 2 != 0)
return this.synchronous, nil
}
/**
* this inode is the inode for an extended attribute value
*/
func (this *Ubifs_InodeHeader) Xattr() (v bool, err error) {
if (this._f_xattr) {
return this.xattr, nil
}
this._f_xattr = true
this.xattr = bool(this.Flags & 32 != 0)
return this.xattr, nil
}
/**
* node key
*/
/**
* sequence number at time of creation
*/
/**
* inode size in bytes (amount of uncompressed data)
*/
/**
* access time seconds
*/
/**
* status change time seconds
*/
/**
* modification time seconds
*/
/**
* access time nanoseconds
*/
/**
* status change time nanoseconds
*/
/**
* modification time nanoseconds
*/
/**
* number of hard links
*/
/**
* owner ID
*/
/**
* group ID
*/
/**
* file type and permissions, as in `st_mode` (see the `is_*`
* instances for the file type)
*/
/**
* per-inode flags (see the instances `compressed`, `synchronous`,
* etc.)
*/
/**
* inode data length
*/
/**
* count of extended attributes this inode has
*/
/**
* summarized size of all extended attributes in bytes
*/
/**
* sum of lengths of all extended attribute names belonging
* to this inode
*/
/**
* compression type used for this inode
*/
/**
* reserved for future, zeroes
*/
/**
* Target of a [symbolic link](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/dir.c#L1220-L1241),
* (encrypted if the inode is encrypted), device number of a device node
* ([`union ubifs_dev_desc`](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L466-L478):
* 4 bytes from Linux, 8 from `mkfs.ubifs`), or value of an
* [extended attribute](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/xattr.c#L115-L121)
* (in its own inode, see `xattr`). Empty otherwise.
*/
/**
* Inode nodes (`inode_header`), directory and extended attribute entry
* nodes (`directory_header`) and data nodes (`data_header`) store keys in a
* 16-byte field (`UBIFS_MAX_KEY_LEN`). The simple key format, the only one
* there is (see `<superblock_header>.key_fmt`), uses only the first 8
* bytes, and Linux (v7.2)
* [zeroes](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/key.h#L432-L440)
* the rest. Branches of index nodes (`branch`)
* [store only these 8 bytes](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/key.h#L448-L455).
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/key.h#L16-L22">Git tag "v7.2"</a>
*/
type Ubifs_Key struct {
InodeNumber uint32
Value uint64
Type Ubifs_KeyTypes
Unused []byte
_io *kaitai.Stream
_root *Ubifs
_parent kaitai.Struct
}
func NewUbifs_Key() *Ubifs_Key {
return &Ubifs_Key{
}
}
func (this Ubifs_Key) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_Key) Read(io *kaitai.Stream, parent kaitai.Struct, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp121, err := this._io.ReadU4le()
if err != nil {
return err
}
this.InodeNumber = uint32(tmp121)
tmp122, err := this._io.ReadBitsIntLe(29)
if err != nil {
return err
}
this.Value = tmp122
tmp123, err := this._io.ReadBitsIntLe(3)
if err != nil {
return err
}
this.Type = Ubifs_KeyTypes(tmp123)
if !this.Type.isDefined() {
return kaitai.NewValidationNotInEnumError(this.Type, this._io, "/types/key/seq/2")
}
this._io.AlignToByte()
tmp124, err := this._io.ReadBytesFull()
if err != nil {
return err
}
tmp124 = tmp124
this.Unused = tmp124
return err
}
/**
* Number of the inode that the node belongs to: the parent directory
* for a directory entry, the inode that the attribute belongs to for an
* extended attribute entry.
*/
/**
* Block number for a data node, hash of the name (see
* `<superblock_header>.key_hash`) for a directory or extended
* attribute entry, 0 for an inode node.
*/
/**
* Type of the key, which matches the type of the node.
*/
/**
* Rest of the field holding the key: 8 zero bytes in `inode_header`,
* `directory_header` and `data_header`, empty in `branch`.
*/
/**
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L685-L756">Git tag "v7.2"</a>
*/
type Ubifs_MasterHeader struct {
HighestInum uint64
CommitNumber uint64
Flags uint32
LebLog uint32
LebRoot uint32
OfsRoot uint32
LenRoot uint32
LebGarbageCollect uint32
LebIndexHead uint32
OfsIndexHead uint32
LenIndex uint64
TotalFree uint64
TotalDirty uint64
TotalUsed uint64
TotalDead uint64
TotalDark uint64
LebLpt uint32
OfsLpt uint32
LebNhead uint32
OfsNhead uint32
LebLpropsTable uint32
OfsLpropsTable uint32
LebSaveTable uint32
OfsSaveTable uint32
LebLastLptScan uint32
NumEmptyLebs uint32
NumIndexLebs uint32
NumLebs uint32
HashRootIndex []byte
HashLpt []byte
Hmac []byte
Padding []byte
_io *kaitai.Stream
_root *Ubifs
_parent kaitai.Struct
_f_dirty bool
dirty bool
_f_noOrphans bool
noOrphans bool
_f_recovery bool
recovery bool
}
func NewUbifs_MasterHeader() *Ubifs_MasterHeader {
return &Ubifs_MasterHeader{
}
}
func (this Ubifs_MasterHeader) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_MasterHeader) Read(io *kaitai.Stream, parent kaitai.Struct, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp125, err := this._io.ReadU8le()
if err != nil {
return err
}
this.HighestInum = uint64(tmp125)
tmp126, err := this._io.ReadU8le()
if err != nil {
return err
}
this.CommitNumber = uint64(tmp126)
tmp127, err := this._io.ReadU4le()
if err != nil {
return err
}
this.Flags = uint32(tmp127)
tmp128, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LebLog = uint32(tmp128)
tmp129, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LebRoot = uint32(tmp129)
tmp130, err := this._io.ReadU4le()
if err != nil {
return err
}
this.OfsRoot = uint32(tmp130)
tmp131, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LenRoot = uint32(tmp131)
tmp132, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LebGarbageCollect = uint32(tmp132)
tmp133, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LebIndexHead = uint32(tmp133)
tmp134, err := this._io.ReadU4le()
if err != nil {
return err
}
this.OfsIndexHead = uint32(tmp134)
tmp135, err := this._io.ReadU8le()
if err != nil {
return err
}
this.LenIndex = uint64(tmp135)
tmp136, err := this._io.ReadU8le()
if err != nil {
return err
}
this.TotalFree = uint64(tmp136)
tmp137, err := this._io.ReadU8le()
if err != nil {
return err
}
this.TotalDirty = uint64(tmp137)
tmp138, err := this._io.ReadU8le()
if err != nil {
return err
}
this.TotalUsed = uint64(tmp138)
tmp139, err := this._io.ReadU8le()
if err != nil {
return err
}
this.TotalDead = uint64(tmp139)
tmp140, err := this._io.ReadU8le()
if err != nil {
return err
}
this.TotalDark = uint64(tmp140)
tmp141, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LebLpt = uint32(tmp141)
tmp142, err := this._io.ReadU4le()
if err != nil {
return err
}
this.OfsLpt = uint32(tmp142)
tmp143, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LebNhead = uint32(tmp143)
tmp144, err := this._io.ReadU4le()
if err != nil {
return err
}
this.OfsNhead = uint32(tmp144)
tmp145, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LebLpropsTable = uint32(tmp145)
tmp146, err := this._io.ReadU4le()
if err != nil {
return err
}
this.OfsLpropsTable = uint32(tmp146)
tmp147, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LebSaveTable = uint32(tmp147)
tmp148, err := this._io.ReadU4le()
if err != nil {
return err
}
this.OfsSaveTable = uint32(tmp148)
tmp149, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LebLastLptScan = uint32(tmp149)
tmp150, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumEmptyLebs = uint32(tmp150)
tmp151, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumIndexLebs = uint32(tmp151)
tmp152, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumLebs = uint32(tmp152)
tmp153, err := this._io.ReadBytes(int(64))
if err != nil {
return err
}
tmp153 = tmp153
this.HashRootIndex = tmp153
tmp154, err := this._io.ReadBytes(int(64))
if err != nil {
return err
}
tmp154 = tmp154
this.HashLpt = tmp154
tmp155, err := this._io.ReadBytes(int(64))
if err != nil {
return err
}
tmp155 = tmp155
this.Hmac = tmp155
tmp156, err := this._io.ReadBytes(int(152))
if err != nil {
return err
}
tmp156 = tmp156
this.Padding = tmp156
return err
}
/**
* master node is dirty
*/
func (this *Ubifs_MasterHeader) Dirty() (v bool, err error) {
if (this._f_dirty) {
return this.dirty, nil
}
this._f_dirty = true
this.dirty = bool(this.Flags & 1 != 0)
return this.dirty, nil
}
/**
* no orphan inodes present
*/
func (this *Ubifs_MasterHeader) NoOrphans() (v bool, err error) {
if (this._f_noOrphans) {
return this.noOrphans, nil
}
this._f_noOrphans = true
this.noOrphans = bool(this.Flags & 2 != 0)
return this.noOrphans, nil
}
/**
* written by recovery
*/
func (this *Ubifs_MasterHeader) Recovery() (v bool, err error) {
if (this._f_recovery) {
return this.recovery, nil
}
this._f_recovery = true
this.recovery = bool(this.Flags & 4 != 0)
return this.recovery, nil
}
/**
* highest inode number in the committed index
*/
/**
* commit number
*/
/**
* various flags (see the instances `dirty`, `no_orphans` and
* `recovery`)
*/
/**
* start of the log
*/
/**
* LEB number of the root indexing node
*/
/**
* offset within the LEB `leb_root`
*/
/**
* root indexing node length
*/
/**
* LEB reserved for garbage collection, which must be in the main area.
*
* The [comment above `struct ubifs_mst_node`](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L695-L696)
* says that -1 (`0xffff_ffff`) means the LEB was not reserved and should
* be reserved on mount. However, Linux refuses to mount a file system
* with -1. Linux
* [stores](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/master.c#L362)
* the field in an
* [`int`](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs.h#L1424),
* so `0xffff_ffff` becomes -1. Then -1 is rejected by the condition
* `c->gc_lnum < c->main_first`, because the main area
* [starts](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/sb.c#L775-L777)
* after the superblock, master, log, LPT and orphan areas.
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/master.c#L214-L217">Git tag "v7.2"</a>
*/
/**
* LEB number of index head
*/
/**
* offset of index head
*/
/**
* size of index on flash
*/
/**
* total free space in bytes
*/
/**
* total dirty space in bytes
*/
/**
* total used space in bytes (includes only data LEBs)
*/
/**
* total dead space in bytes (includes only data LEBs)
*/
/**
* total dark space in bytes (includes only data LEBs)
*/
/**
* LEB number of LPT root nnode
*/
/**
* offset of LPT root nnode
*/
/**
* LEB number of LPT head
*/
/**
* offset of LPT head
*/
/**
* LEB number of LPT's own lprops table
*/
/**
* offset of LPT's own lprops table
*/
/**
* LEB number of LPT's save table. Present in every master node, but
* only meaningful if `<superblock_header>.biglpt` is set: only then
* does Linux [check the location of the save table](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/master.c#L252-L256).
*/
/**
* offset of LPT's save table (only meaningful if
* `<superblock_header>.biglpt` is set, see `leb_save_table`)
*/
/**
* LEB number of last LPT scan
*/
/**
* number of empty logical eraseblocks
*/
/**
* number of indexing logical eraseblocks
*/
/**
* count of LEBs used by file-system
*/
/**
* the hash of the root index node
*/
/**
* the hash of the LPT
*/
/**
* HMAC to authenticate the master node
*/
/**
* reserved for future, zeroes
*/
type Ubifs_MasterblockNode struct {
Header *Ubifs_CommonHeader
NodeHeader *Ubifs_MasterHeader
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs
_raw_NodeHeader []byte
}
func NewUbifs_MasterblockNode() *Ubifs_MasterblockNode {
return &Ubifs_MasterblockNode{
}
}
func (this Ubifs_MasterblockNode) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_MasterblockNode) Read(io *kaitai.Stream, parent *Ubifs, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp157 := NewUbifs_CommonHeader()
err = tmp157.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Header = tmp157
{
_it := this.Header
if !(_it.NodeType == Ubifs_NodeTypes__Master) {
return kaitai.NewValidationExprError(this.Header, this._io, "/types/masterblock_node/seq/0")
}
}
tmp158, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp158 = tmp158
this._raw_NodeHeader = tmp158
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp159 := NewUbifs_MasterHeader()
err = tmp159.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp159
return err
}
/**
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L843-L853">Git tag "v7.2"</a>
*/
type Ubifs_OrphanHeader struct {
CommitNumber uint64
InodeNumbers []uint64
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs_Block
}
func NewUbifs_OrphanHeader() *Ubifs_OrphanHeader {
return &Ubifs_OrphanHeader{
}
}
func (this Ubifs_OrphanHeader) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_OrphanHeader) Read(io *kaitai.Stream, parent *Ubifs_Block, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp160, err := this._io.ReadU8le()
if err != nil {
return err
}
this.CommitNumber = uint64(tmp160)
for i := 0;; i++ {
tmp161, err := this._io.EOF()
if err != nil {
return err
}
if tmp161 {
break
}
tmp162, err := this._io.ReadU8le()
if err != nil {
return err
}
this.InodeNumbers = append(this.InodeNumbers, tmp162)
}
return err
}
/**
* commit number (also top bit is set on the last node of the commit)
*/
/**
* inode numbers of orphans
*/
/**
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L606-L615">Git tag "v7.2"</a>
*/
type Ubifs_PaddingHeader struct {
LenPadding uint32
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs_Block
}
func NewUbifs_PaddingHeader() *Ubifs_PaddingHeader {
return &Ubifs_PaddingHeader{
}
}
func (this Ubifs_PaddingHeader) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_PaddingHeader) Read(io *kaitai.Stream, parent *Ubifs_Block, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp163, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LenPadding = uint32(tmp163)
return err
}
/**
* how many bytes after this node are unused (because padded)
*/
/**
* logical eraseblock reference node.
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L758-L772">Git tag "v7.2"</a>
*/
type Ubifs_ReferenceHeader struct {
LebNumber uint32
OfsLeb uint32
JournalHeadNumber uint32
Padding []byte
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs_Block
}
func NewUbifs_ReferenceHeader() *Ubifs_ReferenceHeader {
return &Ubifs_ReferenceHeader{
}
}
func (this Ubifs_ReferenceHeader) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_ReferenceHeader) Read(io *kaitai.Stream, parent *Ubifs_Block, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp164, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LebNumber = uint32(tmp164)
tmp165, err := this._io.ReadU4le()
if err != nil {
return err
}
this.OfsLeb = uint32(tmp165)
tmp166, err := this._io.ReadU4le()
if err != nil {
return err
}
this.JournalHeadNumber = uint32(tmp166)
tmp167, err := this._io.ReadBytes(int(28))
if err != nil {
return err
}
tmp167 = tmp167
this.Padding = tmp167
return err
}
/**
* the referred logical eraseblock number
*/
/**
* start offset in the referred LEB
*/
/**
* journal head number
*/
/**
* reserved for future, zeroes
*/
/**
* Signature of the superblock node of a file system signed when it was
* created (`mkfs.ubifs` with a key). Linux
* [expects it](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/auth.c#L198-L216)
* as the first node after the superblock node in LEB0.
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L784-L799">Git tag "v7.2"</a>
*/
type Ubifs_SignatureHeader struct {
Type uint32
LenSignature uint32
Padding []byte
Signature []byte
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs_Block
}
func NewUbifs_SignatureHeader() *Ubifs_SignatureHeader {
return &Ubifs_SignatureHeader{
}
}
func (this Ubifs_SignatureHeader) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_SignatureHeader) Read(io *kaitai.Stream, parent *Ubifs_Block, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp168, err := this._io.ReadU4le()
if err != nil {
return err
}
this.Type = uint32(tmp168)
if !(this.Type == 1) {
return kaitai.NewValidationNotEqualError(1, this.Type, this._io, "/types/signature_header/seq/0")
}
tmp169, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LenSignature = uint32(tmp169)
tmp170, err := this._io.ReadBytes(int(32))
if err != nil {
return err
}
tmp170 = tmp170
this.Padding = tmp170
tmp171, err := this._io.ReadBytes(int(this.LenSignature))
if err != nil {
return err
}
tmp171 = tmp171
this.Signature = tmp171
return err
}
/**
* type of the signature
*/
/**
* length of `signature` in bytes
*/
/**
* reserved for future, zeroes
*/
/**
* [PKCS #7 signature](https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/auth.c#L233-L236)
* of the whole superblock node (4096 bytes, including the common
* header)
*/
/**
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L617-L683">Git tag "v7.2"</a>
*/
type Ubifs_SuperblockHeader struct {
Padding0 []byte
KeyHash Ubifs_Hashes
KeyFmt Ubifs_KeyFormats
Flags uint32
MinIoSize uint32
LebSize uint32
NumLebs uint32
MaxNumLebs uint32
MaxBudBytes uint64
NumLogLebs uint32
NumLptLebs uint32
NumOrphanLebs uint32
NumJournalHeads uint32
Fanout uint32
NumSaveTableEntries uint32
FmtVersion uint32
DefaultCompression Ubifs_Compression
Padding1 []byte
ReservePoolUid uint32
ReservePoolGid uint32
ReservePoolSize uint64
TimeGranularity uint32
Uuid []byte
RoCompatVersion uint32
Hmac []byte
HmacWkm []byte
HashAlgo Ubifs_HashAlgos
HashAlgoUnused uint16
HashMst []byte
Padding2 []byte
_io *kaitai.Stream
_root *Ubifs
_parent kaitai.Struct
_f_authenticated bool
authenticated bool
_f_biglpt bool
biglpt bool
_f_doubleHash bool
doubleHash bool
_f_encrypted bool
encrypted bool
_f_lenHash bool
lenHash int
_f_spaceFixup bool
spaceFixup bool
}
func NewUbifs_SuperblockHeader() *Ubifs_SuperblockHeader {
return &Ubifs_SuperblockHeader{
}
}
func (this Ubifs_SuperblockHeader) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_SuperblockHeader) Read(io *kaitai.Stream, parent kaitai.Struct, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp172, err := this._io.ReadBytes(int(2))
if err != nil {
return err
}
tmp172 = tmp172
this.Padding0 = tmp172
if !(bytes.Equal(this.Padding0, []uint8{0, 0})) {
return kaitai.NewValidationNotEqualError([]uint8{0, 0}, this.Padding0, this._io, "/types/superblock_header/seq/0")
}
tmp173, err := this._io.ReadU1()
if err != nil {
return err
}
this.KeyHash = Ubifs_Hashes(tmp173)
if !this.KeyHash.isDefined() {
return kaitai.NewValidationNotInEnumError(this.KeyHash, this._io, "/types/superblock_header/seq/1")
}
tmp174, err := this._io.ReadU1()
if err != nil {
return err
}
this.KeyFmt = Ubifs_KeyFormats(tmp174)
if !(this.KeyFmt == Ubifs_KeyFormats__Simple) {
return kaitai.NewValidationNotEqualError(Ubifs_KeyFormats__Simple, this.KeyFmt, this._io, "/types/superblock_header/seq/2")
}
tmp175, err := this._io.ReadU4le()
if err != nil {
return err
}
this.Flags = uint32(tmp175)
tmp176, err := this._io.ReadU4le()
if err != nil {
return err
}
this.MinIoSize = uint32(tmp176)
tmp177, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LebSize = uint32(tmp177)
tmp178, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumLebs = uint32(tmp178)
tmp179, err := this._io.ReadU4le()
if err != nil {
return err
}
this.MaxNumLebs = uint32(tmp179)
if !(this.MaxNumLebs >= this.NumLebs) {
return kaitai.NewValidationLessThanError(this.NumLebs, this.MaxNumLebs, this._io, "/types/superblock_header/seq/7")
}
tmp180, err := this._io.ReadU8le()
if err != nil {
return err
}
this.MaxBudBytes = uint64(tmp180)
tmp181, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumLogLebs = uint32(tmp181)
if !(this.NumLogLebs >= 2) {
return kaitai.NewValidationLessThanError(2, this.NumLogLebs, this._io, "/types/superblock_header/seq/9")
}
tmp182, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumLptLebs = uint32(tmp182)
if !(this.NumLptLebs >= 2) {
return kaitai.NewValidationLessThanError(2, this.NumLptLebs, this._io, "/types/superblock_header/seq/10")
}
tmp183, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumOrphanLebs = uint32(tmp183)
if !(this.NumOrphanLebs >= 1) {
return kaitai.NewValidationLessThanError(1, this.NumOrphanLebs, this._io, "/types/superblock_header/seq/11")
}
tmp184, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumJournalHeads = uint32(tmp184)
tmp185, err := this._io.ReadU4le()
if err != nil {
return err
}
this.Fanout = uint32(tmp185)
tmp186, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumSaveTableEntries = uint32(tmp186)
tmp187, err := this._io.ReadU4le()
if err != nil {
return err
}
this.FmtVersion = uint32(tmp187)
if !(this.FmtVersion >= 4) {
return kaitai.NewValidationLessThanError(4, this.FmtVersion, this._io, "/types/superblock_header/seq/15")
}
tmp188, err := this._io.ReadU2le()
if err != nil {
return err
}
this.DefaultCompression = Ubifs_Compression(tmp188)
if !this.DefaultCompression.isDefined() {
return kaitai.NewValidationNotInEnumError(this.DefaultCompression, this._io, "/types/superblock_header/seq/16")
}
tmp189, err := this._io.ReadBytes(int(2))
if err != nil {
return err
}
tmp189 = tmp189
this.Padding1 = tmp189
if !(bytes.Equal(this.Padding1, []uint8{0, 0})) {
return kaitai.NewValidationNotEqualError([]uint8{0, 0}, this.Padding1, this._io, "/types/superblock_header/seq/17")
}
tmp190, err := this._io.ReadU4le()
if err != nil {
return err
}
this.ReservePoolUid = uint32(tmp190)
tmp191, err := this._io.ReadU4le()
if err != nil {
return err
}
this.ReservePoolGid = uint32(tmp191)
tmp192, err := this._io.ReadU8le()
if err != nil {
return err
}
this.ReservePoolSize = uint64(tmp192)
tmp193, err := this._io.ReadU4le()
if err != nil {
return err
}
this.TimeGranularity = uint32(tmp193)
if !(this.TimeGranularity >= 1) {
return kaitai.NewValidationLessThanError(1, this.TimeGranularity, this._io, "/types/superblock_header/seq/21")
}
if !(this.TimeGranularity <= 1000000000) {
return kaitai.NewValidationGreaterThanError(1000000000, this.TimeGranularity, this._io, "/types/superblock_header/seq/21")
}
tmp194, err := this._io.ReadBytes(int(16))
if err != nil {
return err
}
tmp194 = tmp194
this.Uuid = tmp194
tmp195, err := this._io.ReadU4le()
if err != nil {
return err
}
this.RoCompatVersion = uint32(tmp195)
tmp196, err := this._io.ReadBytes(int(64))
if err != nil {
return err
}
tmp196 = tmp196
this.Hmac = tmp196
tmp197, err := this._io.ReadBytes(int(64))
if err != nil {
return err
}
tmp197 = tmp197
this.HmacWkm = tmp197
tmp198, err := this.Authenticated()
if err != nil {
return err
}
if (tmp198) {
tmp199, err := this._io.ReadU2le()
if err != nil {
return err
}
this.HashAlgo = Ubifs_HashAlgos(tmp199)
if !this.HashAlgo.isDefined() {
return kaitai.NewValidationNotInEnumError(this.HashAlgo, this._io, "/types/superblock_header/seq/26")
}
}
tmp200, err := this.Authenticated()
if err != nil {
return err
}
if (!(tmp200)) {
tmp201, err := this._io.ReadU2le()
if err != nil {
return err
}
this.HashAlgoUnused = uint16(tmp201)
}
tmp202, err := this._io.ReadBytes(int(64))
if err != nil {
return err
}
tmp202 = tmp202
this.HashMst = tmp202
tmp203, err := this._io.ReadBytes(int(3774))
if err != nil {
return err
}
tmp203 = tmp203
this.Padding2 = tmp203
return err
}
/**
* this filesystem contains hashes for authentication
*/
func (this *Ubifs_SuperblockHeader) Authenticated() (v bool, err error) {
if (this._f_authenticated) {
return this.authenticated, nil
}
this._f_authenticated = true
this.authenticated = bool(this.Flags & 32 != 0)
return this.authenticated, nil
}
/**
* if "big" LPT model is used if set
*/
func (this *Ubifs_SuperblockHeader) Biglpt() (v bool, err error) {
if (this._f_biglpt) {
return this.biglpt, nil
}
this._f_biglpt = true
this.biglpt = bool(this.Flags & 2 != 0)
return this.biglpt, nil
}
/**
* store a 32bit cookie in directory entry nodes to
* support 64bit cookies for lookups by hash
*/
func (this *Ubifs_SuperblockHeader) DoubleHash() (v bool, err error) {
if (this._f_doubleHash) {
return this.doubleHash, nil
}
this._f_doubleHash = true
this.doubleHash = bool(this.Flags & 8 != 0)
return this.doubleHash, nil
}
/**
* filesystem contains encrypted files
*/
func (this *Ubifs_SuperblockHeader) Encrypted() (v bool, err error) {
if (this._f_encrypted) {
return this.encrypted, nil
}
this._f_encrypted = true
this.encrypted = bool(this.Flags & 16 != 0)
return this.encrypted, nil
}
/**
* Length in bytes of the hash of a node (`c->hash_len` in Linux), e.g.
* in each branch of an index node. In an authenticated file system, it
* is determined by `hash_algo`. Otherwise, it is 0.
*/
func (this *Ubifs_SuperblockHeader) LenHash() (v int, err error) {
if (this._f_lenHash) {
return this.lenHash, nil
}
this._f_lenHash = true
var tmp204 int8;
tmp205, err := this.Authenticated()
if err != nil {
return 0, err
}
if (!(tmp205)) {
tmp204 = 0
} else {
var tmp206 int8;
if ( ((this.HashAlgo == Ubifs_HashAlgos__Md4) || (this.HashAlgo == Ubifs_HashAlgos__Md5) || (this.HashAlgo == Ubifs_HashAlgos__RipeMd128) || (this.HashAlgo == Ubifs_HashAlgos__Tgr128)) ) {
tmp206 = 16
} else {
var tmp207 int8;
if ( ((this.HashAlgo == Ubifs_HashAlgos__Sha1) || (this.HashAlgo == Ubifs_HashAlgos__RipeMd160) || (this.HashAlgo == Ubifs_HashAlgos__Tgr160)) ) {
tmp207 = 20
} else {
var tmp208 int8;
if (this.HashAlgo == Ubifs_HashAlgos__Tgr192) {
tmp208 = 24
} else {
var tmp209 int8;
if (this.HashAlgo == Ubifs_HashAlgos__Sha224) {
tmp209 = 28
} else {
var tmp210 int8;
if ( ((this.HashAlgo == Ubifs_HashAlgos__Sha256) || (this.HashAlgo == Ubifs_HashAlgos__RipeMd256) || (this.HashAlgo == Ubifs_HashAlgos__Wp256) || (this.HashAlgo == Ubifs_HashAlgos__Sm3256) || (this.HashAlgo == Ubifs_HashAlgos__Streebog256) || (this.HashAlgo == Ubifs_HashAlgos__Sha3256)) ) {
tmp210 = 32
} else {
var tmp211 int8;
if (this.HashAlgo == Ubifs_HashAlgos__RipeMd320) {
tmp211 = 40
} else {
var tmp212 int8;
if ( ((this.HashAlgo == Ubifs_HashAlgos__Sha384) || (this.HashAlgo == Ubifs_HashAlgos__Wp384) || (this.HashAlgo == Ubifs_HashAlgos__Sha3384)) ) {
tmp212 = 48
} else {
var tmp213 int8;
if ( ((this.HashAlgo == Ubifs_HashAlgos__Sha512) || (this.HashAlgo == Ubifs_HashAlgos__Wp512) || (this.HashAlgo == Ubifs_HashAlgos__Streebog512) || (this.HashAlgo == Ubifs_HashAlgos__Sha3512)) ) {
tmp213 = 64
} else {
tmp213 = -1
}
tmp212 = tmp213
}
tmp211 = tmp212
}
tmp210 = tmp211
}
tmp209 = tmp210
}
tmp208 = tmp209
}
tmp207 = tmp208
}
tmp206 = tmp207
}
tmp204 = tmp206
}
this.lenHash = int(tmp204)
return this.lenHash, nil
}
/**
* first-mount "fixup" of free space within LEBs needed
*/
func (this *Ubifs_SuperblockHeader) SpaceFixup() (v bool, err error) {
if (this._f_spaceFixup) {
return this.spaceFixup, nil
}
this._f_spaceFixup = true
this.spaceFixup = bool(this.Flags & 4 != 0)
return this.spaceFixup, nil
}
/**
* reserved for future, zeroes
*/
/**
* type of hash function used in keys
*/
/**
* format of the key
*/
/**
* file-system flags (see the instances `biglpt`, `space_fixup`, etc.)
*/
/**
* minimal input/output unit size
*/
/**
* logical eraseblock size in bytes
*/
/**
* count of LEBs used by file-system
*/
/**
* maximum count of LEBs used by file-system
*/
/**
* maximum amount of data stored in buds
*/
/**
* log size in logical eraseblocks
*/
/**
* number of LEBs used for lprops table
*/
/**
* number of LEBs used for recording orphans
*/
/**
* count of journal heads
*/
/**
* tree fanout (max. number of links per indexing node)
*/
/**
* number of LEB numbers in LPT's save table
*/
/**
* UBIFS on-flash format version
*/
/**
* default compression algorithm (`compression::lzo`, etc.)
*/
/**
* reserved for future, zeroes
*/
/**
* reserve pool UID
*/
/**
* reserve pool GID
*/
/**
* size of the reserved pool in bytes
*/
/**
* time granularity in nanoseconds
*/
/**
* UUID generated when the file system image was created
*/
/**
* UBIFS R/O compatibility version
*/
/**
* HMAC to authenticate the superblock node
*/
/**
* HMAC of a well known message (the string "UBIFS") as a convenience
* to the user to check if the correct key is passed
*/
/**
* The hash algo used for this filesystem
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/sb.c#L549-L573">Git tag "v7.2"</a>
*/
/**
* Unused field (would only be meaningful in an authenticated file
* system, see `hash_algo`). The kernel writes it as 0xffff, `mkfs.ubifs`
* writes it as 0.
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/sb.c#L183-L191">Git tag "v7.2"</a>
*/
/**
* hash of the master node, only valid for signed images in which the
* master node does not contain a hmac
*/
/**
* reserved for future, zeroes
*/
type Ubifs_SuperblockNode struct {
Header *Ubifs_CommonHeader
NodeHeader *Ubifs_SuperblockHeader
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs
_raw_NodeHeader []byte
}
func NewUbifs_SuperblockNode() *Ubifs_SuperblockNode {
return &Ubifs_SuperblockNode{
}
}
func (this Ubifs_SuperblockNode) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_SuperblockNode) Read(io *kaitai.Stream, parent *Ubifs, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp214 := NewUbifs_CommonHeader()
err = tmp214.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Header = tmp214
{
_it := this.Header
if !(_it.NodeType == Ubifs_NodeTypes__Superblock) {
return kaitai.NewValidationExprError(this.Header, this._io, "/types/superblock_node/seq/0")
}
}
tmp215, err := this._io.ReadBytes(int(this.Header.LenFullNode - 24))
if err != nil {
return err
}
tmp215 = tmp215
this._raw_NodeHeader = tmp215
_io__raw_NodeHeader := kaitai.NewStream(bytes.NewReader(this._raw_NodeHeader))
tmp216 := NewUbifs_SuperblockHeader()
err = tmp216.Read(_io__raw_NodeHeader, this, this._root)
if err != nil {
return err
}
this.NodeHeader = tmp216
return err
}
/**
* This node exists only in the journal and never goes to the main area.
* @see <a href="https://github.com/torvalds/linux/blob/8d3ae59288f1e7d58d76558a6ee96d533bc5019f/fs/ubifs/ubifs-media.h#L586-L604">Git tag "v7.2"</a>
*/
type Ubifs_TruncationHeader struct {
InodeNumber uint32
Padding []byte
OldSize uint64
NewSize uint64
_io *kaitai.Stream
_root *Ubifs
_parent *Ubifs_Block
}
func NewUbifs_TruncationHeader() *Ubifs_TruncationHeader {
return &Ubifs_TruncationHeader{
}
}
func (this Ubifs_TruncationHeader) IO_() *kaitai.Stream {
return this._io
}
func (this *Ubifs_TruncationHeader) Read(io *kaitai.Stream, parent *Ubifs_Block, root *Ubifs) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp217, err := this._io.ReadU4le()
if err != nil {
return err
}
this.InodeNumber = uint32(tmp217)
tmp218, err := this._io.ReadBytes(int(12))
if err != nil {
return err
}
tmp218 = tmp218
this.Padding = tmp218
tmp219, err := this._io.ReadU8le()
if err != nil {
return err
}
this.OldSize = uint64(tmp219)
if !(this.OldSize >= 1) {
return kaitai.NewValidationLessThanError(1, this.OldSize, this._io, "/types/truncation_header/seq/2")
}
tmp220, err := this._io.ReadU8le()
if err != nil {
return err
}
this.NewSize = uint64(tmp220)
if !(this.NewSize <= this.OldSize - 1) {
return kaitai.NewValidationGreaterThanError(this.OldSize - 1, this.NewSize, this._io, "/types/truncation_header/seq/3")
}
return err
}
/**
* truncated inode number
*/
/**
* reserved for future, zeroes
*/
/**
* size before truncation
*/
/**
* size after truncation
*/