This page hosts a formal specification of ext2 filesystem 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.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);
ext2_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.bg1() // => get bg1
#ifndef EXT2_H_
#define EXT2_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
class ext2_t : public kaitai::kstruct {
public:
class super_block_struct_t;
class dir_entry_t;
class inode_t;
class block_ptr_t;
class dir_t;
class block_group_t;
class bgd_t;
class raw_block_t;
ext2_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, ext2_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~ext2_t();
class super_block_struct_t : public kaitai::kstruct {
public:
enum state_enum_t {
STATE_ENUM_VALID_FS = 1,
STATE_ENUM_ERROR_FS = 2
};
enum errors_enum_t {
ERRORS_ENUM_ACT_CONTINUE = 1,
ERRORS_ENUM_ACT_RO = 2,
ERRORS_ENUM_ACT_PANIC = 3
};
super_block_struct_t(kaitai::kstream* p__io, ext2_t::block_group_t* p__parent = 0, ext2_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~super_block_struct_t();
private:
bool f_block_size;
int32_t m_block_size;
public:
int32_t block_size();
private:
bool f_block_group_count;
int32_t m_block_group_count;
public:
int32_t block_group_count();
private:
uint32_t m_inodes_count;
uint32_t m_blocks_count;
uint32_t m_r_blocks_count;
uint32_t m_free_blocks_count;
uint32_t m_free_inodes_count;
uint32_t m_first_data_block;
uint32_t m_log_block_size;
uint32_t m_log_frag_size;
uint32_t m_blocks_per_group;
uint32_t m_frags_per_group;
uint32_t m_inodes_per_group;
uint32_t m_mtime;
uint32_t m_wtime;
uint16_t m_mnt_count;
uint16_t m_max_mnt_count;
std::string m_magic;
state_enum_t m_state;
errors_enum_t m_errors;
uint16_t m_minor_rev_level;
uint32_t m_lastcheck;
uint32_t m_checkinterval;
uint32_t m_creator_os;
uint32_t m_rev_level;
uint16_t m_def_resuid;
uint16_t m_def_resgid;
uint32_t m_first_ino;
uint16_t m_inode_size;
uint16_t m_block_group_nr;
uint32_t m_feature_compat;
uint32_t m_feature_incompat;
uint32_t m_feature_ro_compat;
std::string m_uuid;
std::string m_volume_name;
std::string m_last_mounted;
uint32_t m_algo_bitmap;
uint8_t m_prealloc_blocks;
uint8_t m_prealloc_dir_blocks;
std::string m_padding1;
std::string m_journal_uuid;
uint32_t m_journal_inum;
uint32_t m_journal_dev;
uint32_t m_last_orphan;
std::vector<uint32_t>* m_hash_seed;
uint8_t m_def_hash_version;
ext2_t* m__root;
ext2_t::block_group_t* m__parent;
public:
uint32_t inodes_count() const { return m_inodes_count; }
uint32_t blocks_count() const { return m_blocks_count; }
uint32_t r_blocks_count() const { return m_r_blocks_count; }
uint32_t free_blocks_count() const { return m_free_blocks_count; }
uint32_t free_inodes_count() const { return m_free_inodes_count; }
uint32_t first_data_block() const { return m_first_data_block; }
uint32_t log_block_size() const { return m_log_block_size; }
uint32_t log_frag_size() const { return m_log_frag_size; }
uint32_t blocks_per_group() const { return m_blocks_per_group; }
uint32_t frags_per_group() const { return m_frags_per_group; }
uint32_t inodes_per_group() const { return m_inodes_per_group; }
uint32_t mtime() const { return m_mtime; }
uint32_t wtime() const { return m_wtime; }
uint16_t mnt_count() const { return m_mnt_count; }
uint16_t max_mnt_count() const { return m_max_mnt_count; }
std::string magic() const { return m_magic; }
state_enum_t state() const { return m_state; }
errors_enum_t errors() const { return m_errors; }
uint16_t minor_rev_level() const { return m_minor_rev_level; }
uint32_t lastcheck() const { return m_lastcheck; }
uint32_t checkinterval() const { return m_checkinterval; }
uint32_t creator_os() const { return m_creator_os; }
uint32_t rev_level() const { return m_rev_level; }
uint16_t def_resuid() const { return m_def_resuid; }
uint16_t def_resgid() const { return m_def_resgid; }
uint32_t first_ino() const { return m_first_ino; }
uint16_t inode_size() const { return m_inode_size; }
uint16_t block_group_nr() const { return m_block_group_nr; }
uint32_t feature_compat() const { return m_feature_compat; }
uint32_t feature_incompat() const { return m_feature_incompat; }
uint32_t feature_ro_compat() const { return m_feature_ro_compat; }
std::string uuid() const { return m_uuid; }
std::string volume_name() const { return m_volume_name; }
std::string last_mounted() const { return m_last_mounted; }
uint32_t algo_bitmap() const { return m_algo_bitmap; }
uint8_t prealloc_blocks() const { return m_prealloc_blocks; }
uint8_t prealloc_dir_blocks() const { return m_prealloc_dir_blocks; }
std::string padding1() const { return m_padding1; }
std::string journal_uuid() const { return m_journal_uuid; }
uint32_t journal_inum() const { return m_journal_inum; }
uint32_t journal_dev() const { return m_journal_dev; }
uint32_t last_orphan() const { return m_last_orphan; }
std::vector<uint32_t>* hash_seed() const { return m_hash_seed; }
uint8_t def_hash_version() const { return m_def_hash_version; }
ext2_t* _root() const { return m__root; }
ext2_t::block_group_t* _parent() const { return m__parent; }
};
class dir_entry_t : public kaitai::kstruct {
public:
enum file_type_enum_t {
FILE_TYPE_ENUM_UNKNOWN = 0,
FILE_TYPE_ENUM_REG_FILE = 1,
FILE_TYPE_ENUM_DIR = 2,
FILE_TYPE_ENUM_CHRDEV = 3,
FILE_TYPE_ENUM_BLKDEV = 4,
FILE_TYPE_ENUM_FIFO = 5,
FILE_TYPE_ENUM_SOCK = 6,
FILE_TYPE_ENUM_SYMLINK = 7
};
dir_entry_t(kaitai::kstream* p__io, ext2_t::dir_t* p__parent = 0, ext2_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~dir_entry_t();
private:
bool f_inode;
inode_t* m_inode;
public:
inode_t* inode();
private:
uint32_t m_inode_ptr;
uint16_t m_rec_len;
uint8_t m_name_len;
file_type_enum_t m_file_type;
std::string m_name;
std::string m_padding;
ext2_t* m__root;
ext2_t::dir_t* m__parent;
public:
uint32_t inode_ptr() const { return m_inode_ptr; }
uint16_t rec_len() const { return m_rec_len; }
uint8_t name_len() const { return m_name_len; }
file_type_enum_t file_type() const { return m_file_type; }
std::string name() const { return m_name; }
std::string padding() const { return m_padding; }
ext2_t* _root() const { return m__root; }
ext2_t::dir_t* _parent() const { return m__parent; }
};
class inode_t : public kaitai::kstruct {
public:
inode_t(kaitai::kstream* p__io, ext2_t::bgd_t* p__parent = 0, ext2_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~inode_t();
private:
bool f_as_dir;
dir_t* m_as_dir;
public:
dir_t* as_dir();
private:
uint16_t m_mode;
uint16_t m_uid;
uint32_t m_size;
uint32_t m_atime;
uint32_t m_ctime;
uint32_t m_mtime;
uint32_t m_dtime;
uint16_t m_gid;
uint16_t m_links_count;
uint32_t m_blocks;
uint32_t m_flags;
uint32_t m_osd1;
std::vector<block_ptr_t*>* m_block;
uint32_t m_generation;
uint32_t m_file_acl;
uint32_t m_dir_acl;
uint32_t m_faddr;
std::string m_osd2;
ext2_t* m__root;
ext2_t::bgd_t* m__parent;
public:
uint16_t mode() const { return m_mode; }
uint16_t uid() const { return m_uid; }
uint32_t size() const { return m_size; }
uint32_t atime() const { return m_atime; }
uint32_t ctime() const { return m_ctime; }
uint32_t mtime() const { return m_mtime; }
uint32_t dtime() const { return m_dtime; }
uint16_t gid() const { return m_gid; }
uint16_t links_count() const { return m_links_count; }
uint32_t blocks() const { return m_blocks; }
uint32_t flags() const { return m_flags; }
uint32_t osd1() const { return m_osd1; }
std::vector<block_ptr_t*>* block() const { return m_block; }
uint32_t generation() const { return m_generation; }
uint32_t file_acl() const { return m_file_acl; }
uint32_t dir_acl() const { return m_dir_acl; }
uint32_t faddr() const { return m_faddr; }
std::string osd2() const { return m_osd2; }
ext2_t* _root() const { return m__root; }
ext2_t::bgd_t* _parent() const { return m__parent; }
};
class block_ptr_t : public kaitai::kstruct {
public:
block_ptr_t(kaitai::kstream* p__io, ext2_t::inode_t* p__parent = 0, ext2_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~block_ptr_t();
private:
bool f_body;
raw_block_t* m_body;
public:
raw_block_t* body();
private:
uint32_t m_ptr;
ext2_t* m__root;
ext2_t::inode_t* m__parent;
std::string m__raw_body;
kaitai::kstream* m__io__raw_body;
public:
uint32_t ptr() const { return m_ptr; }
ext2_t* _root() const { return m__root; }
ext2_t::inode_t* _parent() const { return m__parent; }
std::string _raw_body() const { return m__raw_body; }
kaitai::kstream* _io__raw_body() const { return m__io__raw_body; }
};
class dir_t : public kaitai::kstruct {
public:
dir_t(kaitai::kstream* p__io, ext2_t::inode_t* p__parent = 0, ext2_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~dir_t();
private:
std::vector<dir_entry_t*>* m_entries;
ext2_t* m__root;
ext2_t::inode_t* m__parent;
public:
std::vector<dir_entry_t*>* entries() const { return m_entries; }
ext2_t* _root() const { return m__root; }
ext2_t::inode_t* _parent() const { return m__parent; }
};
class block_group_t : public kaitai::kstruct {
public:
block_group_t(kaitai::kstream* p__io, ext2_t* p__parent = 0, ext2_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~block_group_t();
private:
super_block_struct_t* m_super_block;
std::vector<bgd_t*>* m_block_groups;
ext2_t* m__root;
ext2_t* m__parent;
std::string m__raw_super_block;
kaitai::kstream* m__io__raw_super_block;
public:
super_block_struct_t* super_block() const { return m_super_block; }
std::vector<bgd_t*>* block_groups() const { return m_block_groups; }
ext2_t* _root() const { return m__root; }
ext2_t* _parent() const { return m__parent; }
std::string _raw_super_block() const { return m__raw_super_block; }
kaitai::kstream* _io__raw_super_block() const { return m__io__raw_super_block; }
};
class bgd_t : public kaitai::kstruct {
public:
bgd_t(kaitai::kstream* p__io, ext2_t::block_group_t* p__parent = 0, ext2_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~bgd_t();
private:
bool f_block_bitmap;
std::string m_block_bitmap;
public:
std::string block_bitmap();
private:
bool f_inode_bitmap;
std::string m_inode_bitmap;
public:
std::string inode_bitmap();
private:
bool f_inodes;
std::vector<inode_t*>* m_inodes;
public:
std::vector<inode_t*>* inodes();
private:
uint32_t m_block_bitmap_block;
uint32_t m_inode_bitmap_block;
uint32_t m_inode_table_block;
uint16_t m_free_blocks_count;
uint16_t m_free_inodes_count;
uint16_t m_used_dirs_count;
std::string m_pad_reserved;
ext2_t* m__root;
ext2_t::block_group_t* m__parent;
public:
uint32_t block_bitmap_block() const { return m_block_bitmap_block; }
uint32_t inode_bitmap_block() const { return m_inode_bitmap_block; }
uint32_t inode_table_block() const { return m_inode_table_block; }
uint16_t free_blocks_count() const { return m_free_blocks_count; }
uint16_t free_inodes_count() const { return m_free_inodes_count; }
uint16_t used_dirs_count() const { return m_used_dirs_count; }
std::string pad_reserved() const { return m_pad_reserved; }
ext2_t* _root() const { return m__root; }
ext2_t::block_group_t* _parent() const { return m__parent; }
};
class raw_block_t : public kaitai::kstruct {
public:
raw_block_t(kaitai::kstream* p__io, ext2_t::block_ptr_t* p__parent = 0, ext2_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~raw_block_t();
private:
std::string m_body;
ext2_t* m__root;
ext2_t::block_ptr_t* m__parent;
public:
std::string body() const { return m_body; }
ext2_t* _root() const { return m__root; }
ext2_t::block_ptr_t* _parent() const { return m__parent; }
};
private:
bool f_bg1;
block_group_t* m_bg1;
public:
block_group_t* bg1();
private:
bool f_root_dir;
dir_t* m_root_dir;
public:
dir_t* root_dir();
private:
ext2_t* m__root;
kaitai::kstruct* m__parent;
public:
ext2_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
#endif // EXT2_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "ext2.h"
#include "kaitai/exceptions.h"
ext2_t::ext2_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, ext2_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this;
m_bg1 = 0;
f_bg1 = false;
f_root_dir = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void ext2_t::_read() {
}
ext2_t::~ext2_t() {
_clean_up();
}
void ext2_t::_clean_up() {
if (f_bg1) {
if (m_bg1) {
delete m_bg1; m_bg1 = 0;
}
}
}
ext2_t::super_block_struct_t::super_block_struct_t(kaitai::kstream* p__io, ext2_t::block_group_t* p__parent, ext2_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_hash_seed = 0;
f_block_size = false;
f_block_group_count = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void ext2_t::super_block_struct_t::_read() {
m_inodes_count = m__io->read_u4le();
m_blocks_count = m__io->read_u4le();
m_r_blocks_count = m__io->read_u4le();
m_free_blocks_count = m__io->read_u4le();
m_free_inodes_count = m__io->read_u4le();
m_first_data_block = m__io->read_u4le();
m_log_block_size = m__io->read_u4le();
m_log_frag_size = m__io->read_u4le();
m_blocks_per_group = m__io->read_u4le();
m_frags_per_group = m__io->read_u4le();
m_inodes_per_group = m__io->read_u4le();
m_mtime = m__io->read_u4le();
m_wtime = m__io->read_u4le();
m_mnt_count = m__io->read_u2le();
m_max_mnt_count = m__io->read_u2le();
m_magic = m__io->read_bytes(2);
if (!(magic() == std::string("\x53\xEF", 2))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x53\xEF", 2), magic(), _io(), std::string("/types/super_block_struct/seq/15"));
}
m_state = static_cast<ext2_t::super_block_struct_t::state_enum_t>(m__io->read_u2le());
m_errors = static_cast<ext2_t::super_block_struct_t::errors_enum_t>(m__io->read_u2le());
m_minor_rev_level = m__io->read_u2le();
m_lastcheck = m__io->read_u4le();
m_checkinterval = m__io->read_u4le();
m_creator_os = m__io->read_u4le();
m_rev_level = m__io->read_u4le();
m_def_resuid = m__io->read_u2le();
m_def_resgid = m__io->read_u2le();
m_first_ino = m__io->read_u4le();
m_inode_size = m__io->read_u2le();
m_block_group_nr = m__io->read_u2le();
m_feature_compat = m__io->read_u4le();
m_feature_incompat = m__io->read_u4le();
m_feature_ro_compat = m__io->read_u4le();
m_uuid = m__io->read_bytes(16);
m_volume_name = m__io->read_bytes(16);
m_last_mounted = m__io->read_bytes(64);
m_algo_bitmap = m__io->read_u4le();
m_prealloc_blocks = m__io->read_u1();
m_prealloc_dir_blocks = m__io->read_u1();
m_padding1 = m__io->read_bytes(2);
m_journal_uuid = m__io->read_bytes(16);
m_journal_inum = m__io->read_u4le();
m_journal_dev = m__io->read_u4le();
m_last_orphan = m__io->read_u4le();
m_hash_seed = new std::vector<uint32_t>();
const int l_hash_seed = 4;
for (int i = 0; i < l_hash_seed; i++) {
m_hash_seed->push_back(m__io->read_u4le());
}
m_def_hash_version = m__io->read_u1();
}
ext2_t::super_block_struct_t::~super_block_struct_t() {
_clean_up();
}
void ext2_t::super_block_struct_t::_clean_up() {
if (m_hash_seed) {
delete m_hash_seed; m_hash_seed = 0;
}
}
int32_t ext2_t::super_block_struct_t::block_size() {
if (f_block_size)
return m_block_size;
m_block_size = (1024 << log_block_size());
f_block_size = true;
return m_block_size;
}
int32_t ext2_t::super_block_struct_t::block_group_count() {
if (f_block_group_count)
return m_block_group_count;
m_block_group_count = (blocks_count() / blocks_per_group());
f_block_group_count = true;
return m_block_group_count;
}
ext2_t::dir_entry_t::dir_entry_t(kaitai::kstream* p__io, ext2_t::dir_t* p__parent, ext2_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
f_inode = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void ext2_t::dir_entry_t::_read() {
m_inode_ptr = m__io->read_u4le();
m_rec_len = m__io->read_u2le();
m_name_len = m__io->read_u1();
m_file_type = static_cast<ext2_t::dir_entry_t::file_type_enum_t>(m__io->read_u1());
m_name = kaitai::kstream::bytes_to_str(m__io->read_bytes(name_len()), std::string("UTF-8"));
m_padding = m__io->read_bytes(((rec_len() - name_len()) - 8));
}
ext2_t::dir_entry_t::~dir_entry_t() {
_clean_up();
}
void ext2_t::dir_entry_t::_clean_up() {
}
ext2_t::inode_t* ext2_t::dir_entry_t::inode() {
if (f_inode)
return m_inode;
m_inode = _root()->bg1()->block_groups()->at(((inode_ptr() - 1) / _root()->bg1()->super_block()->inodes_per_group()))->inodes()->at(kaitai::kstream::mod((inode_ptr() - 1), _root()->bg1()->super_block()->inodes_per_group()));
f_inode = true;
return m_inode;
}
ext2_t::inode_t::inode_t(kaitai::kstream* p__io, ext2_t::bgd_t* p__parent, ext2_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_block = 0;
m_as_dir = 0;
f_as_dir = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void ext2_t::inode_t::_read() {
m_mode = m__io->read_u2le();
m_uid = m__io->read_u2le();
m_size = m__io->read_u4le();
m_atime = m__io->read_u4le();
m_ctime = m__io->read_u4le();
m_mtime = m__io->read_u4le();
m_dtime = m__io->read_u4le();
m_gid = m__io->read_u2le();
m_links_count = m__io->read_u2le();
m_blocks = m__io->read_u4le();
m_flags = m__io->read_u4le();
m_osd1 = m__io->read_u4le();
m_block = new std::vector<block_ptr_t*>();
const int l_block = 15;
for (int i = 0; i < l_block; i++) {
m_block->push_back(new block_ptr_t(m__io, this, m__root));
}
m_generation = m__io->read_u4le();
m_file_acl = m__io->read_u4le();
m_dir_acl = m__io->read_u4le();
m_faddr = m__io->read_u4le();
m_osd2 = m__io->read_bytes(12);
}
ext2_t::inode_t::~inode_t() {
_clean_up();
}
void ext2_t::inode_t::_clean_up() {
if (m_block) {
for (std::vector<block_ptr_t*>::iterator it = m_block->begin(); it != m_block->end(); ++it) {
delete *it;
}
delete m_block; m_block = 0;
}
if (f_as_dir) {
if (m_as_dir) {
delete m_as_dir; m_as_dir = 0;
}
}
}
ext2_t::dir_t* ext2_t::inode_t::as_dir() {
if (f_as_dir)
return m_as_dir;
kaitai::kstream *io = block()->at(0)->body()->_io();
std::streampos _pos = io->pos();
io->seek(0);
m_as_dir = new dir_t(io, this, m__root);
io->seek(_pos);
f_as_dir = true;
return m_as_dir;
}
ext2_t::block_ptr_t::block_ptr_t(kaitai::kstream* p__io, ext2_t::inode_t* p__parent, ext2_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_body = 0;
m__io__raw_body = 0;
f_body = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void ext2_t::block_ptr_t::_read() {
m_ptr = m__io->read_u4le();
}
ext2_t::block_ptr_t::~block_ptr_t() {
_clean_up();
}
void ext2_t::block_ptr_t::_clean_up() {
if (f_body) {
if (m__io__raw_body) {
delete m__io__raw_body; m__io__raw_body = 0;
}
if (m_body) {
delete m_body; m_body = 0;
}
}
}
ext2_t::raw_block_t* ext2_t::block_ptr_t::body() {
if (f_body)
return m_body;
std::streampos _pos = m__io->pos();
m__io->seek((ptr() * _root()->bg1()->super_block()->block_size()));
m__raw_body = m__io->read_bytes(_root()->bg1()->super_block()->block_size());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new raw_block_t(m__io__raw_body, this, m__root);
m__io->seek(_pos);
f_body = true;
return m_body;
}
ext2_t::dir_t::dir_t(kaitai::kstream* p__io, ext2_t::inode_t* p__parent, ext2_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_entries = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void ext2_t::dir_t::_read() {
m_entries = new std::vector<dir_entry_t*>();
{
int i = 0;
while (!m__io->is_eof()) {
m_entries->push_back(new dir_entry_t(m__io, this, m__root));
i++;
}
}
}
ext2_t::dir_t::~dir_t() {
_clean_up();
}
void ext2_t::dir_t::_clean_up() {
if (m_entries) {
for (std::vector<dir_entry_t*>::iterator it = m_entries->begin(); it != m_entries->end(); ++it) {
delete *it;
}
delete m_entries; m_entries = 0;
}
}
ext2_t::block_group_t::block_group_t(kaitai::kstream* p__io, ext2_t* p__parent, ext2_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_super_block = 0;
m__io__raw_super_block = 0;
m_block_groups = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void ext2_t::block_group_t::_read() {
m__raw_super_block = m__io->read_bytes(1024);
m__io__raw_super_block = new kaitai::kstream(m__raw_super_block);
m_super_block = new super_block_struct_t(m__io__raw_super_block, this, m__root);
m_block_groups = new std::vector<bgd_t*>();
const int l_block_groups = super_block()->block_group_count();
for (int i = 0; i < l_block_groups; i++) {
m_block_groups->push_back(new bgd_t(m__io, this, m__root));
}
}
ext2_t::block_group_t::~block_group_t() {
_clean_up();
}
void ext2_t::block_group_t::_clean_up() {
if (m__io__raw_super_block) {
delete m__io__raw_super_block; m__io__raw_super_block = 0;
}
if (m_super_block) {
delete m_super_block; m_super_block = 0;
}
if (m_block_groups) {
for (std::vector<bgd_t*>::iterator it = m_block_groups->begin(); it != m_block_groups->end(); ++it) {
delete *it;
}
delete m_block_groups; m_block_groups = 0;
}
}
ext2_t::bgd_t::bgd_t(kaitai::kstream* p__io, ext2_t::block_group_t* p__parent, ext2_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_inodes = 0;
f_block_bitmap = false;
f_inode_bitmap = false;
f_inodes = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void ext2_t::bgd_t::_read() {
m_block_bitmap_block = m__io->read_u4le();
m_inode_bitmap_block = m__io->read_u4le();
m_inode_table_block = m__io->read_u4le();
m_free_blocks_count = m__io->read_u2le();
m_free_inodes_count = m__io->read_u2le();
m_used_dirs_count = m__io->read_u2le();
m_pad_reserved = m__io->read_bytes((2 + 12));
}
ext2_t::bgd_t::~bgd_t() {
_clean_up();
}
void ext2_t::bgd_t::_clean_up() {
if (f_block_bitmap) {
}
if (f_inode_bitmap) {
}
if (f_inodes) {
if (m_inodes) {
for (std::vector<inode_t*>::iterator it = m_inodes->begin(); it != m_inodes->end(); ++it) {
delete *it;
}
delete m_inodes; m_inodes = 0;
}
}
}
std::string ext2_t::bgd_t::block_bitmap() {
if (f_block_bitmap)
return m_block_bitmap;
std::streampos _pos = m__io->pos();
m__io->seek((block_bitmap_block() * _root()->bg1()->super_block()->block_size()));
m_block_bitmap = m__io->read_bytes(1024);
m__io->seek(_pos);
f_block_bitmap = true;
return m_block_bitmap;
}
std::string ext2_t::bgd_t::inode_bitmap() {
if (f_inode_bitmap)
return m_inode_bitmap;
std::streampos _pos = m__io->pos();
m__io->seek((inode_bitmap_block() * _root()->bg1()->super_block()->block_size()));
m_inode_bitmap = m__io->read_bytes(1024);
m__io->seek(_pos);
f_inode_bitmap = true;
return m_inode_bitmap;
}
std::vector<ext2_t::inode_t*>* ext2_t::bgd_t::inodes() {
if (f_inodes)
return m_inodes;
std::streampos _pos = m__io->pos();
m__io->seek((inode_table_block() * _root()->bg1()->super_block()->block_size()));
m_inodes = new std::vector<inode_t*>();
const int l_inodes = _root()->bg1()->super_block()->inodes_per_group();
for (int i = 0; i < l_inodes; i++) {
m_inodes->push_back(new inode_t(m__io, this, m__root));
}
m__io->seek(_pos);
f_inodes = true;
return m_inodes;
}
ext2_t::raw_block_t::raw_block_t(kaitai::kstream* p__io, ext2_t::block_ptr_t* p__parent, ext2_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void ext2_t::raw_block_t::_read() {
m_body = m__io->read_bytes(_root()->bg1()->super_block()->block_size());
}
ext2_t::raw_block_t::~raw_block_t() {
_clean_up();
}
void ext2_t::raw_block_t::_clean_up() {
}
ext2_t::block_group_t* ext2_t::bg1() {
if (f_bg1)
return m_bg1;
std::streampos _pos = m__io->pos();
m__io->seek(1024);
m_bg1 = new block_group_t(m__io, this, m__root);
m__io->seek(_pos);
f_bg1 = true;
return m_bg1;
}
ext2_t::dir_t* ext2_t::root_dir() {
if (f_root_dir)
return m_root_dir;
m_root_dir = bg1()->block_groups()->at(0)->inodes()->at(1)->as_dir();
f_root_dir = true;
return m_root_dir;
}