cpio archive, old binary variant, little-endian: C++11/STL 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.

Usage

Runtime 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.

Code

Using Kaitai Struct in C++/STL usually consists of 3 steps.

  1. We need to create an STL input stream (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);
    
  2. We need to wrap our input stream into Kaitai stream:
    #include "kaitai/kaitaistream.h"
    
    kaitai::kstream ks(&is);
    
  3. And finally, we can invoke the parsing:
    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

C++11/STL source code to parse cpio archive, old binary variant, little-endian

cpio_old_le.h

#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; }
};

cpio_old_le.cpp

// 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;
}