A native VirtualBox file format
Images for testing can be downloaded from
or you can convert images of other formats.
This page hosts a formal specification of VirtualBox Disk Image 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++98/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.vdi", 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);
vdi_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.blocks_map() // => block_index = offset_in_virtual_disk / block_size actual_data_offset = blocks_map[block_index]*block_size+metadata_size+offset_in_block
The blocks_map will take up blocks_in_image_max * sizeof(uint32_t) bytes; since the blocks_map is read and written in a single operation, its size needs to be limited to INT_MAX; furthermore, when opening an image, the blocks_map size is rounded up to be aligned on BDRV_SECTOR_SIZE. Therefore this should satisfy the following: blocks_in_image_max * sizeof(uint32_t) + BDRV_SECTOR_SIZE == INT_MAX + 1 (INT_MAX + 1 is the first value not representable as an int) This guarantees that any value below or equal to the constant will, when multiplied by sizeof(uint32_t) and rounded up to a BDRV_SECTOR_SIZE boundary, still be below or equal to INT_MAX.
#ifndef VDI_H_
#define VDI_H_
// 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 <vector>
#if KAITAI_STRUCT_VERSION < 9000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
#endif
/**
* A native VirtualBox file format
*
* Images for testing can be downloaded from
*
* * <https://www.osboxes.org/virtualbox-images/>
* * <https://virtualboxes.org/images/>
*
* or you can convert images of other formats.
* \sa https://github.com/qemu/qemu/blob/master/block/vdi.c Source
*/
class vdi_t : public kaitai::kstruct {
public:
class header_t;
class blocks_map_t;
class disk_t;
enum image_type_t {
IMAGE_TYPE_DYNAMIC = 1,
IMAGE_TYPE_STATIC = 2,
IMAGE_TYPE_UNDO = 3,
IMAGE_TYPE_DIFF = 4
};
vdi_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, vdi_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~vdi_t();
class header_t : public kaitai::kstruct {
public:
class uuid_t;
class version_t;
class header_main_t;
header_t(kaitai::kstream* p__io, vdi_t* p__parent = 0, vdi_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~header_t();
class uuid_t : public kaitai::kstruct {
public:
uuid_t(kaitai::kstream* p__io, vdi_t::header_t::header_main_t* p__parent = 0, vdi_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~uuid_t();
private:
std::string m_uuid;
vdi_t* m__root;
vdi_t::header_t::header_main_t* m__parent;
public:
std::string uuid() const { return m_uuid; }
vdi_t* _root() const { return m__root; }
vdi_t::header_t::header_main_t* _parent() const { return m__parent; }
};
class version_t : public kaitai::kstruct {
public:
version_t(kaitai::kstream* p__io, vdi_t::header_t* p__parent = 0, vdi_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~version_t();
private:
uint16_t m_major;
uint16_t m_minor;
vdi_t* m__root;
vdi_t::header_t* m__parent;
public:
uint16_t major() const { return m_major; }
uint16_t minor() const { return m_minor; }
vdi_t* _root() const { return m__root; }
vdi_t::header_t* _parent() const { return m__parent; }
};
class header_main_t : public kaitai::kstruct {
public:
class geometry_t;
class flags_t;
header_main_t(kaitai::kstream* p__io, vdi_t::header_t* p__parent = 0, vdi_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~header_main_t();
class geometry_t : public kaitai::kstruct {
public:
geometry_t(kaitai::kstream* p__io, vdi_t::header_t::header_main_t* p__parent = 0, vdi_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~geometry_t();
private:
uint32_t m_cylinders;
uint32_t m_heads;
uint32_t m_sectors;
uint32_t m_sector_size;
vdi_t* m__root;
vdi_t::header_t::header_main_t* m__parent;
public:
uint32_t cylinders() const { return m_cylinders; }
uint32_t heads() const { return m_heads; }
uint32_t sectors() const { return m_sectors; }
uint32_t sector_size() const { return m_sector_size; }
vdi_t* _root() const { return m__root; }
vdi_t::header_t::header_main_t* _parent() const { return m__parent; }
};
class flags_t : public kaitai::kstruct {
public:
flags_t(kaitai::kstream* p__io, vdi_t::header_t::header_main_t* p__parent = 0, vdi_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~flags_t();
private:
uint64_t m_reserved0;
bool m_zero_expand;
uint64_t m_reserved1;
bool m_diff;
bool m_fixed;
uint64_t m_reserved2;
vdi_t* m__root;
vdi_t::header_t::header_main_t* m__parent;
public:
uint64_t reserved0() const { return m_reserved0; }
bool zero_expand() const { return m_zero_expand; }
uint64_t reserved1() const { return m_reserved1; }
bool diff() const { return m_diff; }
bool fixed() const { return m_fixed; }
uint64_t reserved2() const { return m_reserved2; }
vdi_t* _root() const { return m__root; }
vdi_t::header_t::header_main_t* _parent() const { return m__parent; }
};
private:
image_type_t m_image_type;
flags_t* m_image_flags;
std::string m_description;
uint32_t m_blocks_map_offset;
bool n_blocks_map_offset;
public:
bool _is_null_blocks_map_offset() { blocks_map_offset(); return n_blocks_map_offset; };
private:
uint32_t m_offset_data;
bool n_offset_data;
public:
bool _is_null_offset_data() { offset_data(); return n_offset_data; };
private:
geometry_t* m_geometry;
uint32_t m_reserved1;
bool n_reserved1;
public:
bool _is_null_reserved1() { reserved1(); return n_reserved1; };
private:
uint64_t m_disk_size;
uint32_t m_block_data_size;
uint32_t m_block_metadata_size;
bool n_block_metadata_size;
public:
bool _is_null_block_metadata_size() { block_metadata_size(); return n_block_metadata_size; };
private:
uint32_t m_blocks_in_image;
uint32_t m_blocks_allocated;
uuid_t* m_uuid_image;
uuid_t* m_uuid_last_snap;
uuid_t* m_uuid_link;
uuid_t* m_uuid_parent;
bool n_uuid_parent;
public:
bool _is_null_uuid_parent() { uuid_parent(); return n_uuid_parent; };
private:
geometry_t* m_lchc_geometry;
bool n_lchc_geometry;
public:
bool _is_null_lchc_geometry() { lchc_geometry(); return n_lchc_geometry; };
private:
vdi_t* m__root;
vdi_t::header_t* m__parent;
public:
image_type_t image_type() const { return m_image_type; }
flags_t* image_flags() const { return m_image_flags; }
std::string description() const { return m_description; }
uint32_t blocks_map_offset() const { return m_blocks_map_offset; }
uint32_t offset_data() const { return m_offset_data; }
geometry_t* geometry() const { return m_geometry; }
uint32_t reserved1() const { return m_reserved1; }
uint64_t disk_size() const { return m_disk_size; }
/**
* Size of block (bytes).
*/
uint32_t block_data_size() const { return m_block_data_size; }
uint32_t block_metadata_size() const { return m_block_metadata_size; }
uint32_t blocks_in_image() const { return m_blocks_in_image; }
uint32_t blocks_allocated() const { return m_blocks_allocated; }
uuid_t* uuid_image() const { return m_uuid_image; }
uuid_t* uuid_last_snap() const { return m_uuid_last_snap; }
uuid_t* uuid_link() const { return m_uuid_link; }
uuid_t* uuid_parent() const { return m_uuid_parent; }
geometry_t* lchc_geometry() const { return m_lchc_geometry; }
vdi_t* _root() const { return m__root; }
vdi_t::header_t* _parent() const { return m__parent; }
};
private:
bool f_header_size;
int32_t m_header_size;
public:
int32_t header_size();
private:
bool f_blocks_map_offset;
uint32_t m_blocks_map_offset;
public:
uint32_t blocks_map_offset();
private:
bool f_subheader_size_is_dynamic;
bool m_subheader_size_is_dynamic;
public:
bool subheader_size_is_dynamic();
private:
bool f_blocks_offset;
uint32_t m_blocks_offset;
public:
uint32_t blocks_offset();
private:
bool f_block_size;
int32_t m_block_size;
public:
int32_t block_size();
private:
bool f_blocks_map_size;
int32_t m_blocks_map_size;
public:
int32_t blocks_map_size();
private:
std::string m_text;
std::string m_signature;
version_t* m_version;
uint32_t m_header_size_optional;
bool n_header_size_optional;
public:
bool _is_null_header_size_optional() { header_size_optional(); return n_header_size_optional; };
private:
header_main_t* m_header_main;
vdi_t* m__root;
vdi_t* m__parent;
std::string m__raw_header_main;
kaitai::kstream* m__io__raw_header_main;
public:
std::string text() const { return m_text; }
std::string signature() const { return m_signature; }
version_t* version() const { return m_version; }
uint32_t header_size_optional() const { return m_header_size_optional; }
header_main_t* header_main() const { return m_header_main; }
vdi_t* _root() const { return m__root; }
vdi_t* _parent() const { return m__parent; }
std::string _raw_header_main() const { return m__raw_header_main; }
kaitai::kstream* _io__raw_header_main() const { return m__io__raw_header_main; }
};
class blocks_map_t : public kaitai::kstruct {
public:
class block_index_t;
blocks_map_t(kaitai::kstream* p__io, vdi_t* p__parent = 0, vdi_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~blocks_map_t();
class block_index_t : public kaitai::kstruct {
public:
block_index_t(kaitai::kstream* p__io, vdi_t::blocks_map_t* p__parent = 0, vdi_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~block_index_t();
private:
bool f_is_allocated;
bool m_is_allocated;
public:
bool is_allocated();
private:
bool f_block;
block_t* m_block;
bool n_block;
public:
bool _is_null_block() { block(); return n_block; };
private:
public:
block_t* block();
private:
uint32_t m_index;
vdi_t* m__root;
vdi_t::blocks_map_t* m__parent;
public:
uint32_t index() const { return m_index; }
vdi_t* _root() const { return m__root; }
vdi_t::blocks_map_t* _parent() const { return m__parent; }
};
private:
std::vector<block_index_t*>* m_index;
vdi_t* m__root;
vdi_t* m__parent;
public:
std::vector<block_index_t*>* index() const { return m_index; }
vdi_t* _root() const { return m__root; }
vdi_t* _parent() const { return m__parent; }
};
class disk_t : public kaitai::kstruct {
public:
class block_t;
disk_t(kaitai::kstream* p__io, vdi_t* p__parent = 0, vdi_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~disk_t();
class block_t : public kaitai::kstruct {
public:
class sector_t;
block_t(kaitai::kstream* p__io, vdi_t::disk_t* p__parent = 0, vdi_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~block_t();
class sector_t : public kaitai::kstruct {
public:
sector_t(kaitai::kstream* p__io, vdi_t::disk_t::block_t* p__parent = 0, vdi_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~sector_t();
private:
std::string m_data;
vdi_t* m__root;
vdi_t::disk_t::block_t* m__parent;
public:
std::string data() const { return m_data; }
vdi_t* _root() const { return m__root; }
vdi_t::disk_t::block_t* _parent() const { return m__parent; }
};
private:
std::string m_metadata;
std::vector<sector_t*>* m_data;
vdi_t* m__root;
vdi_t::disk_t* m__parent;
std::vector<std::string>* m__raw_data;
std::vector<kaitai::kstream*>* m__io__raw_data;
public:
std::string metadata() const { return m_metadata; }
std::vector<sector_t*>* data() const { return m_data; }
vdi_t* _root() const { return m__root; }
vdi_t::disk_t* _parent() const { return m__parent; }
std::vector<std::string>* _raw_data() const { return m__raw_data; }
std::vector<kaitai::kstream*>* _io__raw_data() const { return m__io__raw_data; }
};
private:
std::vector<block_t*>* m_blocks;
vdi_t* m__root;
vdi_t* m__parent;
public:
std::vector<block_t*>* blocks() const { return m_blocks; }
vdi_t* _root() const { return m__root; }
vdi_t* _parent() const { return m__parent; }
};
private:
bool f_block_discarded;
int32_t m_block_discarded;
public:
int32_t block_discarded();
private:
bool f_block_unallocated;
int32_t m_block_unallocated;
public:
int32_t block_unallocated();
private:
bool f_blocks_map;
blocks_map_t* m_blocks_map;
public:
/**
* block_index = offset_in_virtual_disk / block_size actual_data_offset = blocks_map[block_index]*block_size+metadata_size+offset_in_block
* The blocks_map will take up blocks_in_image_max * sizeof(uint32_t) bytes; since the blocks_map is read and written in a single operation, its size needs to be limited to INT_MAX; furthermore, when opening an image, the blocks_map size is rounded up to be aligned on BDRV_SECTOR_SIZE. Therefore this should satisfy the following: blocks_in_image_max * sizeof(uint32_t) + BDRV_SECTOR_SIZE == INT_MAX + 1 (INT_MAX + 1 is the first value not representable as an int) This guarantees that any value below or equal to the constant will, when multiplied by sizeof(uint32_t) and rounded up to a BDRV_SECTOR_SIZE boundary, still be below or equal to INT_MAX.
*/
blocks_map_t* blocks_map();
private:
bool f_disk;
disk_t* m_disk;
public:
disk_t* disk();
private:
header_t* m_header;
vdi_t* m__root;
kaitai::kstruct* m__parent;
std::string m__raw_blocks_map;
kaitai::kstream* m__io__raw_blocks_map;
public:
header_t* header() const { return m_header; }
vdi_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
std::string _raw_blocks_map() const { return m__raw_blocks_map; }
kaitai::kstream* _io__raw_blocks_map() const { return m__io__raw_blocks_map; }
};
#endif // VDI_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "vdi.h"
#include "kaitai/exceptions.h"
vdi_t::vdi_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, vdi_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this;
m_header = 0;
m_blocks_map = 0;
m__io__raw_blocks_map = 0;
m_disk = 0;
f_block_discarded = false;
f_block_unallocated = false;
f_blocks_map = false;
f_disk = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void vdi_t::_read() {
m_header = new header_t(m__io, this, m__root);
}
vdi_t::~vdi_t() {
_clean_up();
}
void vdi_t::_clean_up() {
if (m_header) {
delete m_header; m_header = 0;
}
if (f_blocks_map) {
if (m__io__raw_blocks_map) {
delete m__io__raw_blocks_map; m__io__raw_blocks_map = 0;
}
if (m_blocks_map) {
delete m_blocks_map; m_blocks_map = 0;
}
}
if (f_disk) {
if (m_disk) {
delete m_disk; m_disk = 0;
}
}
}
vdi_t::header_t::header_t(kaitai::kstream* p__io, vdi_t* p__parent, vdi_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_version = 0;
m_header_main = 0;
m__io__raw_header_main = 0;
f_header_size = false;
f_blocks_map_offset = false;
f_subheader_size_is_dynamic = false;
f_blocks_offset = false;
f_block_size = false;
f_blocks_map_size = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void vdi_t::header_t::_read() {
m_text = kaitai::kstream::bytes_to_str(m__io->read_bytes(64), std::string("utf-8"));
m_signature = m__io->read_bytes(4);
if (!(signature() == std::string("\x7F\x10\xDA\xBE", 4))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x7F\x10\xDA\xBE", 4), signature(), _io(), std::string("/types/header/seq/1"));
}
m_version = new version_t(m__io, this, m__root);
n_header_size_optional = true;
if (subheader_size_is_dynamic()) {
n_header_size_optional = false;
m_header_size_optional = m__io->read_u4le();
}
m__raw_header_main = m__io->read_bytes(header_size());
m__io__raw_header_main = new kaitai::kstream(m__raw_header_main);
m_header_main = new header_main_t(m__io__raw_header_main, this, m__root);
}
vdi_t::header_t::~header_t() {
_clean_up();
}
void vdi_t::header_t::_clean_up() {
if (m_version) {
delete m_version; m_version = 0;
}
if (!n_header_size_optional) {
}
if (m__io__raw_header_main) {
delete m__io__raw_header_main; m__io__raw_header_main = 0;
}
if (m_header_main) {
delete m_header_main; m_header_main = 0;
}
}
vdi_t::header_t::uuid_t::uuid_t(kaitai::kstream* p__io, vdi_t::header_t::header_main_t* p__parent, vdi_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void vdi_t::header_t::uuid_t::_read() {
m_uuid = m__io->read_bytes(16);
}
vdi_t::header_t::uuid_t::~uuid_t() {
_clean_up();
}
void vdi_t::header_t::uuid_t::_clean_up() {
}
vdi_t::header_t::version_t::version_t(kaitai::kstream* p__io, vdi_t::header_t* p__parent, vdi_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void vdi_t::header_t::version_t::_read() {
m_major = m__io->read_u2le();
m_minor = m__io->read_u2le();
}
vdi_t::header_t::version_t::~version_t() {
_clean_up();
}
void vdi_t::header_t::version_t::_clean_up() {
}
vdi_t::header_t::header_main_t::header_main_t(kaitai::kstream* p__io, vdi_t::header_t* p__parent, vdi_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_image_flags = 0;
m_geometry = 0;
m_uuid_image = 0;
m_uuid_last_snap = 0;
m_uuid_link = 0;
m_uuid_parent = 0;
m_lchc_geometry = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void vdi_t::header_t::header_main_t::_read() {
m_image_type = static_cast<vdi_t::image_type_t>(m__io->read_u4le());
m_image_flags = new flags_t(m__io, this, m__root);
m_description = kaitai::kstream::bytes_to_str(m__io->read_bytes(256), std::string("utf-8"));
n_blocks_map_offset = true;
if (_parent()->version()->major() >= 1) {
n_blocks_map_offset = false;
m_blocks_map_offset = m__io->read_u4le();
}
n_offset_data = true;
if (_parent()->version()->major() >= 1) {
n_offset_data = false;
m_offset_data = m__io->read_u4le();
}
m_geometry = new geometry_t(m__io, this, m__root);
n_reserved1 = true;
if (_parent()->version()->major() >= 1) {
n_reserved1 = false;
m_reserved1 = m__io->read_u4le();
}
m_disk_size = m__io->read_u8le();
m_block_data_size = m__io->read_u4le();
n_block_metadata_size = true;
if (_parent()->version()->major() >= 1) {
n_block_metadata_size = false;
m_block_metadata_size = m__io->read_u4le();
}
m_blocks_in_image = m__io->read_u4le();
m_blocks_allocated = m__io->read_u4le();
m_uuid_image = new uuid_t(m__io, this, m__root);
m_uuid_last_snap = new uuid_t(m__io, this, m__root);
m_uuid_link = new uuid_t(m__io, this, m__root);
n_uuid_parent = true;
if (_parent()->version()->major() >= 1) {
n_uuid_parent = false;
m_uuid_parent = new uuid_t(m__io, this, m__root);
}
n_lchc_geometry = true;
if ( ((_parent()->version()->major() >= 1) && ((_io()->pos() + 16) <= _io()->size())) ) {
n_lchc_geometry = false;
m_lchc_geometry = new geometry_t(m__io, this, m__root);
}
}
vdi_t::header_t::header_main_t::~header_main_t() {
_clean_up();
}
void vdi_t::header_t::header_main_t::_clean_up() {
if (m_image_flags) {
delete m_image_flags; m_image_flags = 0;
}
if (!n_blocks_map_offset) {
}
if (!n_offset_data) {
}
if (m_geometry) {
delete m_geometry; m_geometry = 0;
}
if (!n_reserved1) {
}
if (!n_block_metadata_size) {
}
if (m_uuid_image) {
delete m_uuid_image; m_uuid_image = 0;
}
if (m_uuid_last_snap) {
delete m_uuid_last_snap; m_uuid_last_snap = 0;
}
if (m_uuid_link) {
delete m_uuid_link; m_uuid_link = 0;
}
if (!n_uuid_parent) {
if (m_uuid_parent) {
delete m_uuid_parent; m_uuid_parent = 0;
}
}
if (!n_lchc_geometry) {
if (m_lchc_geometry) {
delete m_lchc_geometry; m_lchc_geometry = 0;
}
}
}
vdi_t::header_t::header_main_t::geometry_t::geometry_t(kaitai::kstream* p__io, vdi_t::header_t::header_main_t* p__parent, vdi_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void vdi_t::header_t::header_main_t::geometry_t::_read() {
m_cylinders = m__io->read_u4le();
m_heads = m__io->read_u4le();
m_sectors = m__io->read_u4le();
m_sector_size = m__io->read_u4le();
}
vdi_t::header_t::header_main_t::geometry_t::~geometry_t() {
_clean_up();
}
void vdi_t::header_t::header_main_t::geometry_t::_clean_up() {
}
vdi_t::header_t::header_main_t::flags_t::flags_t(kaitai::kstream* p__io, vdi_t::header_t::header_main_t* p__parent, vdi_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void vdi_t::header_t::header_main_t::flags_t::_read() {
m_reserved0 = m__io->read_bits_int_be(15);
m_zero_expand = m__io->read_bits_int_be(1);
m_reserved1 = m__io->read_bits_int_be(6);
m_diff = m__io->read_bits_int_be(1);
m_fixed = m__io->read_bits_int_be(1);
m_reserved2 = m__io->read_bits_int_be(8);
}
vdi_t::header_t::header_main_t::flags_t::~flags_t() {
_clean_up();
}
void vdi_t::header_t::header_main_t::flags_t::_clean_up() {
}
int32_t vdi_t::header_t::header_size() {
if (f_header_size)
return m_header_size;
m_header_size = ((subheader_size_is_dynamic()) ? (header_size_optional()) : (336));
f_header_size = true;
return m_header_size;
}
uint32_t vdi_t::header_t::blocks_map_offset() {
if (f_blocks_map_offset)
return m_blocks_map_offset;
m_blocks_map_offset = header_main()->blocks_map_offset();
f_blocks_map_offset = true;
return m_blocks_map_offset;
}
bool vdi_t::header_t::subheader_size_is_dynamic() {
if (f_subheader_size_is_dynamic)
return m_subheader_size_is_dynamic;
m_subheader_size_is_dynamic = version()->major() >= 1;
f_subheader_size_is_dynamic = true;
return m_subheader_size_is_dynamic;
}
uint32_t vdi_t::header_t::blocks_offset() {
if (f_blocks_offset)
return m_blocks_offset;
m_blocks_offset = header_main()->offset_data();
f_blocks_offset = true;
return m_blocks_offset;
}
int32_t vdi_t::header_t::block_size() {
if (f_block_size)
return m_block_size;
m_block_size = (header_main()->block_metadata_size() + header_main()->block_data_size());
f_block_size = true;
return m_block_size;
}
int32_t vdi_t::header_t::blocks_map_size() {
if (f_blocks_map_size)
return m_blocks_map_size;
m_blocks_map_size = (((((header_main()->blocks_in_image() * 4) + header_main()->geometry()->sector_size()) - 1) / header_main()->geometry()->sector_size()) * header_main()->geometry()->sector_size());
f_blocks_map_size = true;
return m_blocks_map_size;
}
vdi_t::blocks_map_t::blocks_map_t(kaitai::kstream* p__io, vdi_t* p__parent, vdi_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_index = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void vdi_t::blocks_map_t::_read() {
m_index = new std::vector<block_index_t*>();
const int l_index = _root()->header()->header_main()->blocks_in_image();
for (int i = 0; i < l_index; i++) {
m_index->push_back(new block_index_t(m__io, this, m__root));
}
}
vdi_t::blocks_map_t::~blocks_map_t() {
_clean_up();
}
void vdi_t::blocks_map_t::_clean_up() {
if (m_index) {
for (std::vector<block_index_t*>::iterator it = m_index->begin(); it != m_index->end(); ++it) {
delete *it;
}
delete m_index; m_index = 0;
}
}
vdi_t::blocks_map_t::block_index_t::block_index_t(kaitai::kstream* p__io, vdi_t::blocks_map_t* p__parent, vdi_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
f_is_allocated = false;
f_block = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void vdi_t::blocks_map_t::block_index_t::_read() {
m_index = m__io->read_u4le();
}
vdi_t::blocks_map_t::block_index_t::~block_index_t() {
_clean_up();
}
void vdi_t::blocks_map_t::block_index_t::_clean_up() {
}
bool vdi_t::blocks_map_t::block_index_t::is_allocated() {
if (f_is_allocated)
return m_is_allocated;
m_is_allocated = index() < _root()->block_discarded();
f_is_allocated = true;
return m_is_allocated;
}
vdi_t::disk_t::block_t* vdi_t::blocks_map_t::block_index_t::block() {
if (f_block)
return m_block;
n_block = true;
if (is_allocated()) {
n_block = false;
m_block = _root()->disk()->blocks()->at(index());
}
f_block = true;
return m_block;
}
vdi_t::disk_t::disk_t(kaitai::kstream* p__io, vdi_t* p__parent, vdi_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_blocks = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void vdi_t::disk_t::_read() {
m_blocks = new std::vector<block_t*>();
const int l_blocks = _root()->header()->header_main()->blocks_in_image();
for (int i = 0; i < l_blocks; i++) {
m_blocks->push_back(new block_t(m__io, this, m__root));
}
}
vdi_t::disk_t::~disk_t() {
_clean_up();
}
void vdi_t::disk_t::_clean_up() {
if (m_blocks) {
for (std::vector<block_t*>::iterator it = m_blocks->begin(); it != m_blocks->end(); ++it) {
delete *it;
}
delete m_blocks; m_blocks = 0;
}
}
vdi_t::disk_t::block_t::block_t(kaitai::kstream* p__io, vdi_t::disk_t* p__parent, vdi_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_data = 0;
m__raw_data = 0;
m__io__raw_data = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void vdi_t::disk_t::block_t::_read() {
m_metadata = m__io->read_bytes(_root()->header()->header_main()->block_metadata_size());
m__raw_data = new std::vector<std::string>();
m__io__raw_data = new std::vector<kaitai::kstream*>();
m_data = new std::vector<sector_t*>();
{
int i = 0;
while (!m__io->is_eof()) {
m__raw_data->push_back(m__io->read_bytes(_root()->header()->header_main()->block_data_size()));
kaitai::kstream* io__raw_data = new kaitai::kstream(m__raw_data->at(m__raw_data->size() - 1));
m__io__raw_data->push_back(io__raw_data);
m_data->push_back(new sector_t(io__raw_data, this, m__root));
i++;
}
}
}
vdi_t::disk_t::block_t::~block_t() {
_clean_up();
}
void vdi_t::disk_t::block_t::_clean_up() {
if (m__raw_data) {
delete m__raw_data; m__raw_data = 0;
}
if (m__io__raw_data) {
for (std::vector<kaitai::kstream*>::iterator it = m__io__raw_data->begin(); it != m__io__raw_data->end(); ++it) {
delete *it;
}
delete m__io__raw_data; m__io__raw_data = 0;
}
if (m_data) {
for (std::vector<sector_t*>::iterator it = m_data->begin(); it != m_data->end(); ++it) {
delete *it;
}
delete m_data; m_data = 0;
}
}
vdi_t::disk_t::block_t::sector_t::sector_t(kaitai::kstream* p__io, vdi_t::disk_t::block_t* p__parent, vdi_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void vdi_t::disk_t::block_t::sector_t::_read() {
m_data = m__io->read_bytes(_root()->header()->header_main()->geometry()->sector_size());
}
vdi_t::disk_t::block_t::sector_t::~sector_t() {
_clean_up();
}
void vdi_t::disk_t::block_t::sector_t::_clean_up() {
}
int32_t vdi_t::block_discarded() {
if (f_block_discarded)
return m_block_discarded;
m_block_discarded = 4294967294UL;
f_block_discarded = true;
return m_block_discarded;
}
int32_t vdi_t::block_unallocated() {
if (f_block_unallocated)
return m_block_unallocated;
m_block_unallocated = 4294967295UL;
f_block_unallocated = true;
return m_block_unallocated;
}
vdi_t::blocks_map_t* vdi_t::blocks_map() {
if (f_blocks_map)
return m_blocks_map;
std::streampos _pos = m__io->pos();
m__io->seek(header()->blocks_map_offset());
m__raw_blocks_map = m__io->read_bytes(header()->blocks_map_size());
m__io__raw_blocks_map = new kaitai::kstream(m__raw_blocks_map);
m_blocks_map = new blocks_map_t(m__io__raw_blocks_map, this, m__root);
m__io->seek(_pos);
f_blocks_map = true;
return m_blocks_map;
}
vdi_t::disk_t* vdi_t::disk() {
if (f_disk)
return m_disk;
std::streampos _pos = m__io->pos();
m__io->seek(header()->blocks_offset());
m_disk = new disk_t(m__io, this, m__root);
m__io->seek(_pos);
f_disk = true;
return m_disk;
}