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.
All parsing code for C++11/STL generated by Kaitai Struct depends on the C++/STL runtime library. You have to install it before you can parse data.
For C++, the easiest way is to clone the runtime library sources and build them along with your project.
Using Kaitai Struct in C++/STL usually consists of 3 steps.
std::istream
). One can open local file for that, or use existing std::string
or char*
buffer.
#include <fstream>
std::ifstream is("path/to/local/file.cpio", std::ifstream::binary);
#include <sstream>
std::istringstream is(str);
#include <sstream>
const char buf[] = { ... };
std::string str(buf, sizeof buf);
std::istringstream is(str);
#include "kaitai/kaitaistream.h"
kaitai::kstream ks(&is);
cpio_old_le_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.files() // => get files
#pragma once
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "kaitai/kaitaistruct.h"
#include <stdint.h>
#include <memory>
#include <vector>
#if KAITAI_STRUCT_VERSION < 9000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
#endif
class cpio_old_le_t : public kaitai::kstruct {
public:
class file_t;
class file_header_t;
class four_byte_unsigned_integer_t;
cpio_old_le_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, cpio_old_le_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~cpio_old_le_t();
class file_t : public kaitai::kstruct {
public:
file_t(kaitai::kstream* p__io, cpio_old_le_t* p__parent = nullptr, cpio_old_le_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~file_t();
private:
std::unique_ptr<file_header_t> m_header;
std::string m_path_name;
std::string m_string_terminator;
std::string m_path_name_padding;
bool n_path_name_padding;
public:
bool _is_null_path_name_padding() { path_name_padding(); return n_path_name_padding; };
private:
std::string m_file_data;
std::string m_file_data_padding;
bool n_file_data_padding;
public:
bool _is_null_file_data_padding() { file_data_padding(); return n_file_data_padding; };
private:
std::string m_end_of_file_padding;
bool n_end_of_file_padding;
public:
bool _is_null_end_of_file_padding() { end_of_file_padding(); return n_end_of_file_padding; };
private:
cpio_old_le_t* m__root;
cpio_old_le_t* m__parent;
public:
file_header_t* header() const { return m_header.get(); }
std::string path_name() const { return m_path_name; }
std::string string_terminator() const { return m_string_terminator; }
std::string path_name_padding() const { return m_path_name_padding; }
std::string file_data() const { return m_file_data; }
std::string file_data_padding() const { return m_file_data_padding; }
std::string end_of_file_padding() const { return m_end_of_file_padding; }
cpio_old_le_t* _root() const { return m__root; }
cpio_old_le_t* _parent() const { return m__parent; }
};
class file_header_t : public kaitai::kstruct {
public:
file_header_t(kaitai::kstream* p__io, cpio_old_le_t::file_t* p__parent = nullptr, cpio_old_le_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~file_header_t();
private:
std::string m_magic;
uint16_t m_device_number;
uint16_t m_inode_number;
uint16_t m_mode;
uint16_t m_user_id;
uint16_t m_group_id;
uint16_t m_number_of_links;
uint16_t m_r_device_number;
std::unique_ptr<four_byte_unsigned_integer_t> m_modification_time;
uint16_t m_path_name_size;
std::unique_ptr<four_byte_unsigned_integer_t> m_file_size;
cpio_old_le_t* m__root;
cpio_old_le_t::file_t* m__parent;
public:
std::string magic() const { return m_magic; }
uint16_t device_number() const { return m_device_number; }
uint16_t inode_number() const { return m_inode_number; }
uint16_t mode() const { return m_mode; }
uint16_t user_id() const { return m_user_id; }
uint16_t group_id() const { return m_group_id; }
uint16_t number_of_links() const { return m_number_of_links; }
uint16_t r_device_number() const { return m_r_device_number; }
four_byte_unsigned_integer_t* modification_time() const { return m_modification_time.get(); }
uint16_t path_name_size() const { return m_path_name_size; }
four_byte_unsigned_integer_t* file_size() const { return m_file_size.get(); }
cpio_old_le_t* _root() const { return m__root; }
cpio_old_le_t::file_t* _parent() const { return m__parent; }
};
class four_byte_unsigned_integer_t : public kaitai::kstruct {
public:
four_byte_unsigned_integer_t(kaitai::kstream* p__io, cpio_old_le_t::file_header_t* p__parent = nullptr, cpio_old_le_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~four_byte_unsigned_integer_t();
private:
bool f_value;
int32_t m_value;
public:
int32_t value();
private:
uint16_t m_most_significant_bits;
uint16_t m_least_significant_bits;
cpio_old_le_t* m__root;
cpio_old_le_t::file_header_t* m__parent;
public:
uint16_t most_significant_bits() const { return m_most_significant_bits; }
uint16_t least_significant_bits() const { return m_least_significant_bits; }
cpio_old_le_t* _root() const { return m__root; }
cpio_old_le_t::file_header_t* _parent() const { return m__parent; }
};
private:
std::unique_ptr<std::vector<std::unique_ptr<file_t>>> m_files;
cpio_old_le_t* m__root;
kaitai::kstruct* m__parent;
public:
std::vector<std::unique_ptr<file_t>>* files() const { return m_files.get(); }
cpio_old_le_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "cpio_old_le.h"
#include "kaitai/exceptions.h"
cpio_old_le_t::cpio_old_le_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, cpio_old_le_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this;
m_files = nullptr;
_read();
}
void cpio_old_le_t::_read() {
m_files = std::unique_ptr<std::vector<std::unique_ptr<file_t>>>(new std::vector<std::unique_ptr<file_t>>());
{
int i = 0;
while (!m__io->is_eof()) {
m_files->push_back(std::move(std::unique_ptr<file_t>(new file_t(m__io, this, m__root))));
i++;
}
}
}
cpio_old_le_t::~cpio_old_le_t() {
_clean_up();
}
void cpio_old_le_t::_clean_up() {
}
cpio_old_le_t::file_t::file_t(kaitai::kstream* p__io, cpio_old_le_t* p__parent, cpio_old_le_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_header = nullptr;
_read();
}
void cpio_old_le_t::file_t::_read() {
m_header = std::unique_ptr<file_header_t>(new file_header_t(m__io, this, m__root));
m_path_name = m__io->read_bytes((header()->path_name_size() - 1));
m_string_terminator = m__io->read_bytes(1);
if (!(string_terminator() == std::string("\x00", 1))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x00", 1), string_terminator(), _io(), std::string("/types/file/seq/2"));
}
n_path_name_padding = true;
if (kaitai::kstream::mod(header()->path_name_size(), 2) == 1) {
n_path_name_padding = false;
m_path_name_padding = m__io->read_bytes(1);
if (!(path_name_padding() == std::string("\x00", 1))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x00", 1), path_name_padding(), _io(), std::string("/types/file/seq/3"));
}
}
m_file_data = m__io->read_bytes(header()->file_size()->value());
n_file_data_padding = true;
if (kaitai::kstream::mod(header()->file_size()->value(), 2) == 1) {
n_file_data_padding = false;
m_file_data_padding = m__io->read_bytes(1);
if (!(file_data_padding() == std::string("\x00", 1))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x00", 1), file_data_padding(), _io(), std::string("/types/file/seq/5"));
}
}
n_end_of_file_padding = true;
if ( ((path_name() == std::string("\x54\x52\x41\x49\x4C\x45\x52\x21\x21\x21", 10)) && (header()->file_size()->value() == 0)) ) {
n_end_of_file_padding = false;
m_end_of_file_padding = m__io->read_bytes_full();
}
}
cpio_old_le_t::file_t::~file_t() {
_clean_up();
}
void cpio_old_le_t::file_t::_clean_up() {
if (!n_path_name_padding) {
}
if (!n_file_data_padding) {
}
if (!n_end_of_file_padding) {
}
}
cpio_old_le_t::file_header_t::file_header_t(kaitai::kstream* p__io, cpio_old_le_t::file_t* p__parent, cpio_old_le_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_modification_time = nullptr;
m_file_size = nullptr;
_read();
}
void cpio_old_le_t::file_header_t::_read() {
m_magic = m__io->read_bytes(2);
if (!(magic() == std::string("\xC7\x71", 2))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\xC7\x71", 2), magic(), _io(), std::string("/types/file_header/seq/0"));
}
m_device_number = m__io->read_u2le();
m_inode_number = m__io->read_u2le();
m_mode = m__io->read_u2le();
m_user_id = m__io->read_u2le();
m_group_id = m__io->read_u2le();
m_number_of_links = m__io->read_u2le();
m_r_device_number = m__io->read_u2le();
m_modification_time = std::unique_ptr<four_byte_unsigned_integer_t>(new four_byte_unsigned_integer_t(m__io, this, m__root));
m_path_name_size = m__io->read_u2le();
m_file_size = std::unique_ptr<four_byte_unsigned_integer_t>(new four_byte_unsigned_integer_t(m__io, this, m__root));
}
cpio_old_le_t::file_header_t::~file_header_t() {
_clean_up();
}
void cpio_old_le_t::file_header_t::_clean_up() {
}
cpio_old_le_t::four_byte_unsigned_integer_t::four_byte_unsigned_integer_t(kaitai::kstream* p__io, cpio_old_le_t::file_header_t* p__parent, cpio_old_le_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
f_value = false;
_read();
}
void cpio_old_le_t::four_byte_unsigned_integer_t::_read() {
m_most_significant_bits = m__io->read_u2le();
m_least_significant_bits = m__io->read_u2le();
}
cpio_old_le_t::four_byte_unsigned_integer_t::~four_byte_unsigned_integer_t() {
_clean_up();
}
void cpio_old_le_t::four_byte_unsigned_integer_t::_clean_up() {
}
int32_t cpio_old_le_t::four_byte_unsigned_integer_t::value() {
if (f_value)
return m_value;
m_value = (least_significant_bits() + (most_significant_bits() << 16));
f_value = true;
return m_value;
}