This page hosts a formal specification of GPT (GUID) partition table 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.bin", 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);
gpt_partition_table_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.sector_size() // => get sector size
#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
/**
* \sa https://en.wikipedia.org/wiki/GUID_Partition_Table Source
*/
class gpt_partition_table_t : public kaitai::kstruct {
public:
class partition_entry_t;
class partition_header_t;
gpt_partition_table_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, gpt_partition_table_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~gpt_partition_table_t();
class partition_entry_t : public kaitai::kstruct {
public:
partition_entry_t(kaitai::kstream* p__io, gpt_partition_table_t::partition_header_t* p__parent = nullptr, gpt_partition_table_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~partition_entry_t();
private:
std::string m_type_guid;
std::string m_guid;
uint64_t m_first_lba;
uint64_t m_last_lba;
uint64_t m_attributes;
std::string m_name;
gpt_partition_table_t* m__root;
gpt_partition_table_t::partition_header_t* m__parent;
public:
std::string type_guid() const { return m_type_guid; }
std::string guid() const { return m_guid; }
uint64_t first_lba() const { return m_first_lba; }
uint64_t last_lba() const { return m_last_lba; }
uint64_t attributes() const { return m_attributes; }
std::string name() const { return m_name; }
gpt_partition_table_t* _root() const { return m__root; }
gpt_partition_table_t::partition_header_t* _parent() const { return m__parent; }
};
class partition_header_t : public kaitai::kstruct {
public:
partition_header_t(kaitai::kstream* p__io, gpt_partition_table_t* p__parent = nullptr, gpt_partition_table_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~partition_header_t();
private:
bool f_entries;
std::unique_ptr<std::vector<std::unique_ptr<partition_entry_t>>> m_entries;
public:
std::vector<std::unique_ptr<partition_entry_t>>* entries();
private:
std::string m_signature;
uint32_t m_revision;
uint32_t m_header_size;
uint32_t m_crc32_header;
uint32_t m_reserved;
uint64_t m_current_lba;
uint64_t m_backup_lba;
uint64_t m_first_usable_lba;
uint64_t m_last_usable_lba;
std::string m_disk_guid;
uint64_t m_entries_start;
uint32_t m_entries_count;
uint32_t m_entries_size;
uint32_t m_crc32_array;
gpt_partition_table_t* m__root;
gpt_partition_table_t* m__parent;
std::unique_ptr<std::vector<std::string>> m__raw_entries;
std::unique_ptr<std::vector<std::unique_ptr<kaitai::kstream>>> m__io__raw_entries;
public:
std::string signature() const { return m_signature; }
uint32_t revision() const { return m_revision; }
uint32_t header_size() const { return m_header_size; }
uint32_t crc32_header() const { return m_crc32_header; }
uint32_t reserved() const { return m_reserved; }
uint64_t current_lba() const { return m_current_lba; }
uint64_t backup_lba() const { return m_backup_lba; }
uint64_t first_usable_lba() const { return m_first_usable_lba; }
uint64_t last_usable_lba() const { return m_last_usable_lba; }
std::string disk_guid() const { return m_disk_guid; }
uint64_t entries_start() const { return m_entries_start; }
uint32_t entries_count() const { return m_entries_count; }
uint32_t entries_size() const { return m_entries_size; }
uint32_t crc32_array() const { return m_crc32_array; }
gpt_partition_table_t* _root() const { return m__root; }
gpt_partition_table_t* _parent() const { return m__parent; }
std::vector<std::string>* _raw_entries() const { return m__raw_entries.get(); }
std::vector<std::unique_ptr<kaitai::kstream>>* _io__raw_entries() const { return m__io__raw_entries.get(); }
};
private:
bool f_sector_size;
int32_t m_sector_size;
public:
int32_t sector_size();
private:
bool f_primary;
std::unique_ptr<partition_header_t> m_primary;
public:
partition_header_t* primary();
private:
bool f_backup;
std::unique_ptr<partition_header_t> m_backup;
public:
partition_header_t* backup();
private:
gpt_partition_table_t* m__root;
kaitai::kstruct* m__parent;
public:
gpt_partition_table_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 "gpt_partition_table.h"
#include "kaitai/exceptions.h"
gpt_partition_table_t::gpt_partition_table_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, gpt_partition_table_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this;
m_primary = nullptr;
m_backup = nullptr;
f_sector_size = false;
f_primary = false;
f_backup = false;
_read();
}
void gpt_partition_table_t::_read() {
}
gpt_partition_table_t::~gpt_partition_table_t() {
_clean_up();
}
void gpt_partition_table_t::_clean_up() {
if (f_primary) {
}
if (f_backup) {
}
}
gpt_partition_table_t::partition_entry_t::partition_entry_t(kaitai::kstream* p__io, gpt_partition_table_t::partition_header_t* p__parent, gpt_partition_table_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
_read();
}
void gpt_partition_table_t::partition_entry_t::_read() {
m_type_guid = m__io->read_bytes(16);
m_guid = m__io->read_bytes(16);
m_first_lba = m__io->read_u8le();
m_last_lba = m__io->read_u8le();
m_attributes = m__io->read_u8le();
m_name = kaitai::kstream::bytes_to_str(m__io->read_bytes(72), std::string("UTF-16LE"));
}
gpt_partition_table_t::partition_entry_t::~partition_entry_t() {
_clean_up();
}
void gpt_partition_table_t::partition_entry_t::_clean_up() {
}
gpt_partition_table_t::partition_header_t::partition_header_t(kaitai::kstream* p__io, gpt_partition_table_t* p__parent, gpt_partition_table_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_entries = nullptr;
m__raw_entries = nullptr;
m__io__raw_entries = nullptr;
f_entries = false;
_read();
}
void gpt_partition_table_t::partition_header_t::_read() {
m_signature = m__io->read_bytes(8);
if (!(signature() == std::string("\x45\x46\x49\x20\x50\x41\x52\x54", 8))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x45\x46\x49\x20\x50\x41\x52\x54", 8), signature(), _io(), std::string("/types/partition_header/seq/0"));
}
m_revision = m__io->read_u4le();
m_header_size = m__io->read_u4le();
m_crc32_header = m__io->read_u4le();
m_reserved = m__io->read_u4le();
m_current_lba = m__io->read_u8le();
m_backup_lba = m__io->read_u8le();
m_first_usable_lba = m__io->read_u8le();
m_last_usable_lba = m__io->read_u8le();
m_disk_guid = m__io->read_bytes(16);
m_entries_start = m__io->read_u8le();
m_entries_count = m__io->read_u4le();
m_entries_size = m__io->read_u4le();
m_crc32_array = m__io->read_u4le();
}
gpt_partition_table_t::partition_header_t::~partition_header_t() {
_clean_up();
}
void gpt_partition_table_t::partition_header_t::_clean_up() {
if (f_entries) {
}
}
std::vector<std::unique_ptr<gpt_partition_table_t::partition_entry_t>>* gpt_partition_table_t::partition_header_t::entries() {
if (f_entries)
return m_entries.get();
kaitai::kstream *io = _root()->_io();
std::streampos _pos = io->pos();
io->seek((entries_start() * _root()->sector_size()));
m__raw_entries = std::unique_ptr<std::vector<std::string>>(new std::vector<std::string>());
m__io__raw_entries = std::unique_ptr<std::vector<std::unique_ptr<kaitai::kstream>>>(new std::vector<std::unique_ptr<kaitai::kstream>>());
m_entries = std::unique_ptr<std::vector<std::unique_ptr<partition_entry_t>>>(new std::vector<std::unique_ptr<partition_entry_t>>());
const int l_entries = entries_count();
for (int i = 0; i < l_entries; i++) {
m__raw_entries->push_back(std::move(io->read_bytes(entries_size())));
kaitai::kstream* io__raw_entries = new kaitai::kstream(m__raw_entries->at(m__raw_entries->size() - 1));
m__io__raw_entries->emplace_back(io__raw_entries);
m_entries->push_back(std::move(std::unique_ptr<partition_entry_t>(new partition_entry_t(io__raw_entries, this, m__root))));
}
io->seek(_pos);
f_entries = true;
return m_entries.get();
}
int32_t gpt_partition_table_t::sector_size() {
if (f_sector_size)
return m_sector_size;
m_sector_size = 512;
f_sector_size = true;
return m_sector_size;
}
gpt_partition_table_t::partition_header_t* gpt_partition_table_t::primary() {
if (f_primary)
return m_primary.get();
kaitai::kstream *io = _root()->_io();
std::streampos _pos = io->pos();
io->seek(_root()->sector_size());
m_primary = std::unique_ptr<partition_header_t>(new partition_header_t(io, this, m__root));
io->seek(_pos);
f_primary = true;
return m_primary.get();
}
gpt_partition_table_t::partition_header_t* gpt_partition_table_t::backup() {
if (f_backup)
return m_backup.get();
kaitai::kstream *io = _root()->_io();
std::streampos _pos = io->pos();
io->seek((_io()->size() - _root()->sector_size()));
m_backup = std::unique_ptr<partition_header_t>(new partition_header_t(io, this, m__root));
io->seek(_pos);
f_backup = true;
return m_backup.get();
}