cpio archive, old binary variant, little-endian: Nim parsing library

File extension

cpio

KS implementation details

License: CC0-1.0

References

This page hosts a formal specification of cpio archive, old binary variant, little-endian using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Nim source code to parse cpio archive, old binary variant, little-endian

cpio_old_le.nim

import kaitai_struct_nim_runtime
import options

type
  CpioOldLe* = ref object of KaitaiStruct
    `files`*: seq[CpioOldLe_File]
    `parent`*: KaitaiStruct
  CpioOldLe_File* = ref object of KaitaiStruct
    `header`*: CpioOldLe_FileHeader
    `pathName`*: seq[byte]
    `stringTerminator`*: seq[byte]
    `pathNamePadding`*: seq[byte]
    `fileData`*: seq[byte]
    `fileDataPadding`*: seq[byte]
    `endOfFilePadding`*: seq[byte]
    `parent`*: CpioOldLe
  CpioOldLe_FileHeader* = ref object of KaitaiStruct
    `magic`*: seq[byte]
    `deviceNumber`*: uint16
    `inodeNumber`*: uint16
    `mode`*: uint16
    `userId`*: uint16
    `groupId`*: uint16
    `numberOfLinks`*: uint16
    `rDeviceNumber`*: uint16
    `modificationTime`*: CpioOldLe_FourByteUnsignedInteger
    `pathNameSize`*: uint16
    `fileSize`*: CpioOldLe_FourByteUnsignedInteger
    `parent`*: CpioOldLe_File
  CpioOldLe_FourByteUnsignedInteger* = ref object of KaitaiStruct
    `mostSignificantBits`*: uint16
    `leastSignificantBits`*: uint16
    `parent`*: CpioOldLe_FileHeader
    `valueInst`*: int

proc read*(_: typedesc[CpioOldLe], io: KaitaiStream, root: KaitaiStruct, parent: KaitaiStruct): CpioOldLe
proc read*(_: typedesc[CpioOldLe_File], io: KaitaiStream, root: KaitaiStruct, parent: CpioOldLe): CpioOldLe_File
proc read*(_: typedesc[CpioOldLe_FileHeader], io: KaitaiStream, root: KaitaiStruct, parent: CpioOldLe_File): CpioOldLe_FileHeader
proc read*(_: typedesc[CpioOldLe_FourByteUnsignedInteger], io: KaitaiStream, root: KaitaiStruct, parent: CpioOldLe_FileHeader): CpioOldLe_FourByteUnsignedInteger

proc value*(this: CpioOldLe_FourByteUnsignedInteger): int

proc read*(_: typedesc[CpioOldLe], io: KaitaiStream, root: KaitaiStruct, parent: KaitaiStruct): CpioOldLe =
  template this: untyped = result
  this = new(CpioOldLe)
  let root = if root == nil: cast[CpioOldLe](this) else: cast[CpioOldLe](root)
  this.io = io
  this.root = root
  this.parent = parent

  block:
    var i: int
    while not this.io.isEof:
      let it = CpioOldLe_File.read(this.io, this.root, this)
      this.files.add(it)
      inc i

proc fromFile*(_: typedesc[CpioOldLe], filename: string): CpioOldLe =
  CpioOldLe.read(newKaitaiFileStream(filename), nil, nil)

proc read*(_: typedesc[CpioOldLe_File], io: KaitaiStream, root: KaitaiStruct, parent: CpioOldLe): CpioOldLe_File =
  template this: untyped = result
  this = new(CpioOldLe_File)
  let root = if root == nil: cast[CpioOldLe](this) else: cast[CpioOldLe](root)
  this.io = io
  this.root = root
  this.parent = parent

  let headerExpr = CpioOldLe_FileHeader.read(this.io, this.root, this)
  this.header = headerExpr
  let pathNameExpr = this.io.readBytes(int((this.header.pathNameSize - 1)))
  this.pathName = pathNameExpr
  let stringTerminatorExpr = this.io.readBytes(int(1))
  this.stringTerminator = stringTerminatorExpr
  if (this.header.pathNameSize %%% 2) == 1:
    let pathNamePaddingExpr = this.io.readBytes(int(1))
    this.pathNamePadding = pathNamePaddingExpr
  let fileDataExpr = this.io.readBytes(int(this.header.fileSize.value))
  this.fileData = fileDataExpr
  if (this.header.fileSize.value %%% 2) == 1:
    let fileDataPaddingExpr = this.io.readBytes(int(1))
    this.fileDataPadding = fileDataPaddingExpr
  if  ((this.pathName == @[84'u8, 82'u8, 65'u8, 73'u8, 76'u8, 69'u8, 82'u8, 33'u8, 33'u8, 33'u8]) and (this.header.fileSize.value == 0)) :
    let endOfFilePaddingExpr = this.io.readBytesFull()
    this.endOfFilePadding = endOfFilePaddingExpr

proc fromFile*(_: typedesc[CpioOldLe_File], filename: string): CpioOldLe_File =
  CpioOldLe_File.read(newKaitaiFileStream(filename), nil, nil)

proc read*(_: typedesc[CpioOldLe_FileHeader], io: KaitaiStream, root: KaitaiStruct, parent: CpioOldLe_File): CpioOldLe_FileHeader =
  template this: untyped = result
  this = new(CpioOldLe_FileHeader)
  let root = if root == nil: cast[CpioOldLe](this) else: cast[CpioOldLe](root)
  this.io = io
  this.root = root
  this.parent = parent

  let magicExpr = this.io.readBytes(int(2))
  this.magic = magicExpr
  let deviceNumberExpr = this.io.readU2le()
  this.deviceNumber = deviceNumberExpr
  let inodeNumberExpr = this.io.readU2le()
  this.inodeNumber = inodeNumberExpr
  let modeExpr = this.io.readU2le()
  this.mode = modeExpr
  let userIdExpr = this.io.readU2le()
  this.userId = userIdExpr
  let groupIdExpr = this.io.readU2le()
  this.groupId = groupIdExpr
  let numberOfLinksExpr = this.io.readU2le()
  this.numberOfLinks = numberOfLinksExpr
  let rDeviceNumberExpr = this.io.readU2le()
  this.rDeviceNumber = rDeviceNumberExpr
  let modificationTimeExpr = CpioOldLe_FourByteUnsignedInteger.read(this.io, this.root, this)
  this.modificationTime = modificationTimeExpr
  let pathNameSizeExpr = this.io.readU2le()
  this.pathNameSize = pathNameSizeExpr
  let fileSizeExpr = CpioOldLe_FourByteUnsignedInteger.read(this.io, this.root, this)
  this.fileSize = fileSizeExpr

proc fromFile*(_: typedesc[CpioOldLe_FileHeader], filename: string): CpioOldLe_FileHeader =
  CpioOldLe_FileHeader.read(newKaitaiFileStream(filename), nil, nil)

proc read*(_: typedesc[CpioOldLe_FourByteUnsignedInteger], io: KaitaiStream, root: KaitaiStruct, parent: CpioOldLe_FileHeader): CpioOldLe_FourByteUnsignedInteger =
  template this: untyped = result
  this = new(CpioOldLe_FourByteUnsignedInteger)
  let root = if root == nil: cast[CpioOldLe](this) else: cast[CpioOldLe](root)
  this.io = io
  this.root = root
  this.parent = parent

  let mostSignificantBitsExpr = this.io.readU2le()
  this.mostSignificantBits = mostSignificantBitsExpr
  let leastSignificantBitsExpr = this.io.readU2le()
  this.leastSignificantBits = leastSignificantBitsExpr

proc value(this: CpioOldLe_FourByteUnsignedInteger): int = 
  if this.valueInst != nil:
    return this.valueInst
  let valueInstExpr = int((this.leastSignificantBits + (this.mostSignificantBits shl 16)))
  this.valueInst = valueInstExpr
  if this.valueInst != nil:
    return this.valueInst

proc fromFile*(_: typedesc[CpioOldLe_FourByteUnsignedInteger], filename: string): CpioOldLe_FourByteUnsignedInteger =
  CpioOldLe_FourByteUnsignedInteger.read(newKaitaiFileStream(filename), nil, nil)