ISO9660 is standard filesystem used on read-only optical discs (mostly CD-ROM). The standard was based on earlier High Sierra Format (HSF), proposed for CD-ROMs in 1985, and, after several revisions, it was accepted as ISO9960:1998.
The format emphasizes portability (thus having pretty minimal features and very conservative file names standards) and sequential access (which favors disc devices with relatively slow rotation speed).
This page hosts a formal specification of ISO9660 CD 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.iso", 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);
iso9660_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.sector_size() // => get sector size
#ifndef ISO9660_H_
#define ISO9660_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
/**
* ISO9660 is standard filesystem used on read-only optical discs
* (mostly CD-ROM). The standard was based on earlier High Sierra
* Format (HSF), proposed for CD-ROMs in 1985, and, after several
* revisions, it was accepted as ISO9960:1998.
*
* The format emphasizes portability (thus having pretty minimal
* features and very conservative file names standards) and sequential
* access (which favors disc devices with relatively slow rotation
* speed).
*/
class iso9660_t : public kaitai::kstruct {
public:
class vol_desc_primary_t;
class vol_desc_boot_record_t;
class datetime_t;
class dir_entry_t;
class vol_desc_t;
class path_table_entry_le_t;
class dir_entries_t;
class u4bi_t;
class u2bi_t;
class path_table_le_t;
class dec_datetime_t;
class dir_entry_body_t;
iso9660_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, iso9660_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~iso9660_t();
/**
* \sa https://wiki.osdev.org/ISO_9660#The_Primary_Volume_Descriptor Source
*/
class vol_desc_primary_t : public kaitai::kstruct {
public:
vol_desc_primary_t(kaitai::kstream* p__io, iso9660_t::vol_desc_t* p__parent = 0, iso9660_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~vol_desc_primary_t();
private:
bool f_path_table;
path_table_le_t* m_path_table;
public:
path_table_le_t* path_table();
private:
std::string m_unused1;
std::string m_system_id;
std::string m_volume_id;
std::string m_unused2;
u4bi_t* m_vol_space_size;
std::string m_unused3;
u2bi_t* m_vol_set_size;
u2bi_t* m_vol_seq_num;
u2bi_t* m_logical_block_size;
u4bi_t* m_path_table_size;
uint32_t m_lba_path_table_le;
uint32_t m_lba_opt_path_table_le;
uint32_t m_lba_path_table_be;
uint32_t m_lba_opt_path_table_be;
dir_entry_t* m_root_dir;
std::string m_vol_set_id;
std::string m_publisher_id;
std::string m_data_preparer_id;
std::string m_application_id;
std::string m_copyright_file_id;
std::string m_abstract_file_id;
std::string m_bibliographic_file_id;
dec_datetime_t* m_vol_create_datetime;
dec_datetime_t* m_vol_mod_datetime;
dec_datetime_t* m_vol_expire_datetime;
dec_datetime_t* m_vol_effective_datetime;
uint8_t m_file_structure_version;
uint8_t m_unused4;
std::string m_application_area;
iso9660_t* m__root;
iso9660_t::vol_desc_t* m__parent;
std::string m__raw_root_dir;
kaitai::kstream* m__io__raw_root_dir;
std::string m__raw_path_table;
kaitai::kstream* m__io__raw_path_table;
public:
std::string unused1() const { return m_unused1; }
std::string system_id() const { return m_system_id; }
std::string volume_id() const { return m_volume_id; }
std::string unused2() const { return m_unused2; }
u4bi_t* vol_space_size() const { return m_vol_space_size; }
std::string unused3() const { return m_unused3; }
u2bi_t* vol_set_size() const { return m_vol_set_size; }
u2bi_t* vol_seq_num() const { return m_vol_seq_num; }
u2bi_t* logical_block_size() const { return m_logical_block_size; }
u4bi_t* path_table_size() const { return m_path_table_size; }
uint32_t lba_path_table_le() const { return m_lba_path_table_le; }
uint32_t lba_opt_path_table_le() const { return m_lba_opt_path_table_le; }
uint32_t lba_path_table_be() const { return m_lba_path_table_be; }
uint32_t lba_opt_path_table_be() const { return m_lba_opt_path_table_be; }
dir_entry_t* root_dir() const { return m_root_dir; }
std::string vol_set_id() const { return m_vol_set_id; }
std::string publisher_id() const { return m_publisher_id; }
std::string data_preparer_id() const { return m_data_preparer_id; }
std::string application_id() const { return m_application_id; }
std::string copyright_file_id() const { return m_copyright_file_id; }
std::string abstract_file_id() const { return m_abstract_file_id; }
std::string bibliographic_file_id() const { return m_bibliographic_file_id; }
dec_datetime_t* vol_create_datetime() const { return m_vol_create_datetime; }
dec_datetime_t* vol_mod_datetime() const { return m_vol_mod_datetime; }
dec_datetime_t* vol_expire_datetime() const { return m_vol_expire_datetime; }
dec_datetime_t* vol_effective_datetime() const { return m_vol_effective_datetime; }
uint8_t file_structure_version() const { return m_file_structure_version; }
uint8_t unused4() const { return m_unused4; }
std::string application_area() const { return m_application_area; }
iso9660_t* _root() const { return m__root; }
iso9660_t::vol_desc_t* _parent() const { return m__parent; }
std::string _raw_root_dir() const { return m__raw_root_dir; }
kaitai::kstream* _io__raw_root_dir() const { return m__io__raw_root_dir; }
std::string _raw_path_table() const { return m__raw_path_table; }
kaitai::kstream* _io__raw_path_table() const { return m__io__raw_path_table; }
};
class vol_desc_boot_record_t : public kaitai::kstruct {
public:
vol_desc_boot_record_t(kaitai::kstream* p__io, iso9660_t::vol_desc_t* p__parent = 0, iso9660_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~vol_desc_boot_record_t();
private:
std::string m_boot_system_id;
std::string m_boot_id;
iso9660_t* m__root;
iso9660_t::vol_desc_t* m__parent;
public:
std::string boot_system_id() const { return m_boot_system_id; }
std::string boot_id() const { return m_boot_id; }
iso9660_t* _root() const { return m__root; }
iso9660_t::vol_desc_t* _parent() const { return m__parent; }
};
class datetime_t : public kaitai::kstruct {
public:
datetime_t(kaitai::kstream* p__io, iso9660_t::dir_entry_body_t* p__parent = 0, iso9660_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~datetime_t();
private:
uint8_t m_year;
uint8_t m_month;
uint8_t m_day;
uint8_t m_hour;
uint8_t m_minute;
uint8_t m_sec;
uint8_t m_timezone;
iso9660_t* m__root;
iso9660_t::dir_entry_body_t* m__parent;
public:
uint8_t year() const { return m_year; }
uint8_t month() const { return m_month; }
uint8_t day() const { return m_day; }
uint8_t hour() const { return m_hour; }
uint8_t minute() const { return m_minute; }
uint8_t sec() const { return m_sec; }
uint8_t timezone() const { return m_timezone; }
iso9660_t* _root() const { return m__root; }
iso9660_t::dir_entry_body_t* _parent() const { return m__parent; }
};
class dir_entry_t : public kaitai::kstruct {
public:
dir_entry_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, iso9660_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~dir_entry_t();
private:
uint8_t m_len;
dir_entry_body_t* m_body;
bool n_body;
public:
bool _is_null_body() { body(); return n_body; };
private:
iso9660_t* m__root;
kaitai::kstruct* m__parent;
std::string m__raw_body;
bool n__raw_body;
public:
bool _is_null__raw_body() { _raw_body(); return n__raw_body; };
private:
kaitai::kstream* m__io__raw_body;
public:
uint8_t len() const { return m_len; }
dir_entry_body_t* body() const { return m_body; }
iso9660_t* _root() const { return m__root; }
kaitai::kstruct* _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 vol_desc_t : public kaitai::kstruct {
public:
vol_desc_t(kaitai::kstream* p__io, iso9660_t* p__parent = 0, iso9660_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~vol_desc_t();
private:
uint8_t m_type;
std::string m_magic;
uint8_t m_version;
vol_desc_boot_record_t* m_vol_desc_boot_record;
bool n_vol_desc_boot_record;
public:
bool _is_null_vol_desc_boot_record() { vol_desc_boot_record(); return n_vol_desc_boot_record; };
private:
vol_desc_primary_t* m_vol_desc_primary;
bool n_vol_desc_primary;
public:
bool _is_null_vol_desc_primary() { vol_desc_primary(); return n_vol_desc_primary; };
private:
iso9660_t* m__root;
iso9660_t* m__parent;
public:
uint8_t type() const { return m_type; }
std::string magic() const { return m_magic; }
uint8_t version() const { return m_version; }
vol_desc_boot_record_t* vol_desc_boot_record() const { return m_vol_desc_boot_record; }
vol_desc_primary_t* vol_desc_primary() const { return m_vol_desc_primary; }
iso9660_t* _root() const { return m__root; }
iso9660_t* _parent() const { return m__parent; }
};
class path_table_entry_le_t : public kaitai::kstruct {
public:
path_table_entry_le_t(kaitai::kstream* p__io, iso9660_t::path_table_le_t* p__parent = 0, iso9660_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~path_table_entry_le_t();
private:
uint8_t m_len_dir_name;
uint8_t m_len_ext_attr_rec;
uint32_t m_lba_extent;
uint16_t m_parent_dir_idx;
std::string m_dir_name;
uint8_t m_padding;
bool n_padding;
public:
bool _is_null_padding() { padding(); return n_padding; };
private:
iso9660_t* m__root;
iso9660_t::path_table_le_t* m__parent;
public:
uint8_t len_dir_name() const { return m_len_dir_name; }
uint8_t len_ext_attr_rec() const { return m_len_ext_attr_rec; }
uint32_t lba_extent() const { return m_lba_extent; }
uint16_t parent_dir_idx() const { return m_parent_dir_idx; }
std::string dir_name() const { return m_dir_name; }
uint8_t padding() const { return m_padding; }
iso9660_t* _root() const { return m__root; }
iso9660_t::path_table_le_t* _parent() const { return m__parent; }
};
class dir_entries_t : public kaitai::kstruct {
public:
dir_entries_t(kaitai::kstream* p__io, iso9660_t::dir_entry_body_t* p__parent = 0, iso9660_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~dir_entries_t();
private:
std::vector<dir_entry_t*>* m_entries;
iso9660_t* m__root;
iso9660_t::dir_entry_body_t* m__parent;
public:
std::vector<dir_entry_t*>* entries() const { return m_entries; }
iso9660_t* _root() const { return m__root; }
iso9660_t::dir_entry_body_t* _parent() const { return m__parent; }
};
class u4bi_t : public kaitai::kstruct {
public:
u4bi_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, iso9660_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~u4bi_t();
private:
uint32_t m_le;
uint32_t m_be;
iso9660_t* m__root;
kaitai::kstruct* m__parent;
public:
uint32_t le() const { return m_le; }
uint32_t be() const { return m_be; }
iso9660_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
class u2bi_t : public kaitai::kstruct {
public:
u2bi_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, iso9660_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~u2bi_t();
private:
uint16_t m_le;
uint16_t m_be;
iso9660_t* m__root;
kaitai::kstruct* m__parent;
public:
uint16_t le() const { return m_le; }
uint16_t be() const { return m_be; }
iso9660_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
/**
* \sa https://wiki.osdev.org/ISO_9660#The_Path_Table Source
*/
class path_table_le_t : public kaitai::kstruct {
public:
path_table_le_t(kaitai::kstream* p__io, iso9660_t::vol_desc_primary_t* p__parent = 0, iso9660_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~path_table_le_t();
private:
std::vector<path_table_entry_le_t*>* m_entries;
iso9660_t* m__root;
iso9660_t::vol_desc_primary_t* m__parent;
public:
std::vector<path_table_entry_le_t*>* entries() const { return m_entries; }
iso9660_t* _root() const { return m__root; }
iso9660_t::vol_desc_primary_t* _parent() const { return m__parent; }
};
/**
* \sa https://wiki.osdev.org/ISO_9660#Date.2Ftime_format Source
*/
class dec_datetime_t : public kaitai::kstruct {
public:
dec_datetime_t(kaitai::kstream* p__io, iso9660_t::vol_desc_primary_t* p__parent = 0, iso9660_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~dec_datetime_t();
private:
std::string m_year;
std::string m_month;
std::string m_day;
std::string m_hour;
std::string m_minute;
std::string m_sec;
std::string m_sec_hundreds;
uint8_t m_timezone;
iso9660_t* m__root;
iso9660_t::vol_desc_primary_t* m__parent;
public:
std::string year() const { return m_year; }
std::string month() const { return m_month; }
std::string day() const { return m_day; }
std::string hour() const { return m_hour; }
std::string minute() const { return m_minute; }
std::string sec() const { return m_sec; }
std::string sec_hundreds() const { return m_sec_hundreds; }
uint8_t timezone() const { return m_timezone; }
iso9660_t* _root() const { return m__root; }
iso9660_t::vol_desc_primary_t* _parent() const { return m__parent; }
};
class dir_entry_body_t : public kaitai::kstruct {
public:
dir_entry_body_t(kaitai::kstream* p__io, iso9660_t::dir_entry_t* p__parent = 0, iso9660_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~dir_entry_body_t();
private:
bool f_extent_as_dir;
dir_entries_t* m_extent_as_dir;
bool n_extent_as_dir;
public:
bool _is_null_extent_as_dir() { extent_as_dir(); return n_extent_as_dir; };
private:
public:
dir_entries_t* extent_as_dir();
private:
bool f_extent_as_file;
std::string m_extent_as_file;
bool n_extent_as_file;
public:
bool _is_null_extent_as_file() { extent_as_file(); return n_extent_as_file; };
private:
public:
std::string extent_as_file();
private:
uint8_t m_len_ext_attr_rec;
u4bi_t* m_lba_extent;
u4bi_t* m_size_extent;
datetime_t* m_datetime;
uint8_t m_file_flags;
uint8_t m_file_unit_size;
uint8_t m_interleave_gap_size;
u2bi_t* m_vol_seq_num;
uint8_t m_len_file_name;
std::string m_file_name;
uint8_t m_padding;
bool n_padding;
public:
bool _is_null_padding() { padding(); return n_padding; };
private:
std::string m_rest;
iso9660_t* m__root;
iso9660_t::dir_entry_t* m__parent;
std::string m__raw_extent_as_dir;
bool n__raw_extent_as_dir;
public:
bool _is_null__raw_extent_as_dir() { _raw_extent_as_dir(); return n__raw_extent_as_dir; };
private:
kaitai::kstream* m__io__raw_extent_as_dir;
public:
uint8_t len_ext_attr_rec() const { return m_len_ext_attr_rec; }
u4bi_t* lba_extent() const { return m_lba_extent; }
u4bi_t* size_extent() const { return m_size_extent; }
datetime_t* datetime() const { return m_datetime; }
uint8_t file_flags() const { return m_file_flags; }
uint8_t file_unit_size() const { return m_file_unit_size; }
uint8_t interleave_gap_size() const { return m_interleave_gap_size; }
u2bi_t* vol_seq_num() const { return m_vol_seq_num; }
uint8_t len_file_name() const { return m_len_file_name; }
std::string file_name() const { return m_file_name; }
uint8_t padding() const { return m_padding; }
std::string rest() const { return m_rest; }
iso9660_t* _root() const { return m__root; }
iso9660_t::dir_entry_t* _parent() const { return m__parent; }
std::string _raw_extent_as_dir() const { return m__raw_extent_as_dir; }
kaitai::kstream* _io__raw_extent_as_dir() const { return m__io__raw_extent_as_dir; }
};
private:
bool f_sector_size;
int32_t m_sector_size;
public:
int32_t sector_size();
private:
bool f_primary_vol_desc;
vol_desc_t* m_primary_vol_desc;
public:
vol_desc_t* primary_vol_desc();
private:
iso9660_t* m__root;
kaitai::kstruct* m__parent;
public:
iso9660_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
#endif // ISO9660_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "iso9660.h"
#include "kaitai/exceptions.h"
iso9660_t::iso9660_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, iso9660_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this;
m_primary_vol_desc = 0;
f_sector_size = false;
f_primary_vol_desc = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void iso9660_t::_read() {
}
iso9660_t::~iso9660_t() {
_clean_up();
}
void iso9660_t::_clean_up() {
if (f_primary_vol_desc) {
if (m_primary_vol_desc) {
delete m_primary_vol_desc; m_primary_vol_desc = 0;
}
}
}
iso9660_t::vol_desc_primary_t::vol_desc_primary_t(kaitai::kstream* p__io, iso9660_t::vol_desc_t* p__parent, iso9660_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_vol_space_size = 0;
m_vol_set_size = 0;
m_vol_seq_num = 0;
m_logical_block_size = 0;
m_path_table_size = 0;
m_root_dir = 0;
m__io__raw_root_dir = 0;
m_vol_create_datetime = 0;
m_vol_mod_datetime = 0;
m_vol_expire_datetime = 0;
m_vol_effective_datetime = 0;
m_path_table = 0;
m__io__raw_path_table = 0;
f_path_table = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void iso9660_t::vol_desc_primary_t::_read() {
m_unused1 = m__io->read_bytes(1);
if (!(unused1() == std::string("\x00", 1))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x00", 1), unused1(), _io(), std::string("/types/vol_desc_primary/seq/0"));
}
m_system_id = kaitai::kstream::bytes_to_str(m__io->read_bytes(32), std::string("UTF-8"));
m_volume_id = kaitai::kstream::bytes_to_str(m__io->read_bytes(32), std::string("UTF-8"));
m_unused2 = m__io->read_bytes(8);
if (!(unused2() == std::string("\x00\x00\x00\x00\x00\x00\x00\x00", 8))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x00\x00\x00\x00\x00\x00\x00\x00", 8), unused2(), _io(), std::string("/types/vol_desc_primary/seq/3"));
}
m_vol_space_size = new u4bi_t(m__io, this, m__root);
m_unused3 = m__io->read_bytes(32);
if (!(unused3() == std::string("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32), unused3(), _io(), std::string("/types/vol_desc_primary/seq/5"));
}
m_vol_set_size = new u2bi_t(m__io, this, m__root);
m_vol_seq_num = new u2bi_t(m__io, this, m__root);
m_logical_block_size = new u2bi_t(m__io, this, m__root);
m_path_table_size = new u4bi_t(m__io, this, m__root);
m_lba_path_table_le = m__io->read_u4le();
m_lba_opt_path_table_le = m__io->read_u4le();
m_lba_path_table_be = m__io->read_u4be();
m_lba_opt_path_table_be = m__io->read_u4be();
m__raw_root_dir = m__io->read_bytes(34);
m__io__raw_root_dir = new kaitai::kstream(m__raw_root_dir);
m_root_dir = new dir_entry_t(m__io__raw_root_dir, this, m__root);
m_vol_set_id = kaitai::kstream::bytes_to_str(m__io->read_bytes(128), std::string("UTF-8"));
m_publisher_id = kaitai::kstream::bytes_to_str(m__io->read_bytes(128), std::string("UTF-8"));
m_data_preparer_id = kaitai::kstream::bytes_to_str(m__io->read_bytes(128), std::string("UTF-8"));
m_application_id = kaitai::kstream::bytes_to_str(m__io->read_bytes(128), std::string("UTF-8"));
m_copyright_file_id = kaitai::kstream::bytes_to_str(m__io->read_bytes(38), std::string("UTF-8"));
m_abstract_file_id = kaitai::kstream::bytes_to_str(m__io->read_bytes(36), std::string("UTF-8"));
m_bibliographic_file_id = kaitai::kstream::bytes_to_str(m__io->read_bytes(37), std::string("UTF-8"));
m_vol_create_datetime = new dec_datetime_t(m__io, this, m__root);
m_vol_mod_datetime = new dec_datetime_t(m__io, this, m__root);
m_vol_expire_datetime = new dec_datetime_t(m__io, this, m__root);
m_vol_effective_datetime = new dec_datetime_t(m__io, this, m__root);
m_file_structure_version = m__io->read_u1();
m_unused4 = m__io->read_u1();
m_application_area = m__io->read_bytes(512);
}
iso9660_t::vol_desc_primary_t::~vol_desc_primary_t() {
_clean_up();
}
void iso9660_t::vol_desc_primary_t::_clean_up() {
if (m_vol_space_size) {
delete m_vol_space_size; m_vol_space_size = 0;
}
if (m_vol_set_size) {
delete m_vol_set_size; m_vol_set_size = 0;
}
if (m_vol_seq_num) {
delete m_vol_seq_num; m_vol_seq_num = 0;
}
if (m_logical_block_size) {
delete m_logical_block_size; m_logical_block_size = 0;
}
if (m_path_table_size) {
delete m_path_table_size; m_path_table_size = 0;
}
if (m__io__raw_root_dir) {
delete m__io__raw_root_dir; m__io__raw_root_dir = 0;
}
if (m_root_dir) {
delete m_root_dir; m_root_dir = 0;
}
if (m_vol_create_datetime) {
delete m_vol_create_datetime; m_vol_create_datetime = 0;
}
if (m_vol_mod_datetime) {
delete m_vol_mod_datetime; m_vol_mod_datetime = 0;
}
if (m_vol_expire_datetime) {
delete m_vol_expire_datetime; m_vol_expire_datetime = 0;
}
if (m_vol_effective_datetime) {
delete m_vol_effective_datetime; m_vol_effective_datetime = 0;
}
if (f_path_table) {
if (m__io__raw_path_table) {
delete m__io__raw_path_table; m__io__raw_path_table = 0;
}
if (m_path_table) {
delete m_path_table; m_path_table = 0;
}
}
}
iso9660_t::path_table_le_t* iso9660_t::vol_desc_primary_t::path_table() {
if (f_path_table)
return m_path_table;
std::streampos _pos = m__io->pos();
m__io->seek((lba_path_table_le() * _root()->sector_size()));
m__raw_path_table = m__io->read_bytes(path_table_size()->le());
m__io__raw_path_table = new kaitai::kstream(m__raw_path_table);
m_path_table = new path_table_le_t(m__io__raw_path_table, this, m__root);
m__io->seek(_pos);
f_path_table = true;
return m_path_table;
}
iso9660_t::vol_desc_boot_record_t::vol_desc_boot_record_t(kaitai::kstream* p__io, iso9660_t::vol_desc_t* p__parent, iso9660_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void iso9660_t::vol_desc_boot_record_t::_read() {
m_boot_system_id = kaitai::kstream::bytes_to_str(m__io->read_bytes(32), std::string("UTF-8"));
m_boot_id = kaitai::kstream::bytes_to_str(m__io->read_bytes(32), std::string("UTF-8"));
}
iso9660_t::vol_desc_boot_record_t::~vol_desc_boot_record_t() {
_clean_up();
}
void iso9660_t::vol_desc_boot_record_t::_clean_up() {
}
iso9660_t::datetime_t::datetime_t(kaitai::kstream* p__io, iso9660_t::dir_entry_body_t* p__parent, iso9660_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void iso9660_t::datetime_t::_read() {
m_year = m__io->read_u1();
m_month = m__io->read_u1();
m_day = m__io->read_u1();
m_hour = m__io->read_u1();
m_minute = m__io->read_u1();
m_sec = m__io->read_u1();
m_timezone = m__io->read_u1();
}
iso9660_t::datetime_t::~datetime_t() {
_clean_up();
}
void iso9660_t::datetime_t::_clean_up() {
}
iso9660_t::dir_entry_t::dir_entry_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, iso9660_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_body = 0;
m__io__raw_body = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void iso9660_t::dir_entry_t::_read() {
m_len = m__io->read_u1();
n_body = true;
if (len() > 0) {
n_body = false;
m__raw_body = m__io->read_bytes((len() - 1));
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new dir_entry_body_t(m__io__raw_body, this, m__root);
}
}
iso9660_t::dir_entry_t::~dir_entry_t() {
_clean_up();
}
void iso9660_t::dir_entry_t::_clean_up() {
if (!n_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;
}
}
}
iso9660_t::vol_desc_t::vol_desc_t(kaitai::kstream* p__io, iso9660_t* p__parent, iso9660_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_vol_desc_boot_record = 0;
m_vol_desc_primary = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void iso9660_t::vol_desc_t::_read() {
m_type = m__io->read_u1();
m_magic = m__io->read_bytes(5);
if (!(magic() == std::string("\x43\x44\x30\x30\x31", 5))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x43\x44\x30\x30\x31", 5), magic(), _io(), std::string("/types/vol_desc/seq/1"));
}
m_version = m__io->read_u1();
n_vol_desc_boot_record = true;
if (type() == 0) {
n_vol_desc_boot_record = false;
m_vol_desc_boot_record = new vol_desc_boot_record_t(m__io, this, m__root);
}
n_vol_desc_primary = true;
if (type() == 1) {
n_vol_desc_primary = false;
m_vol_desc_primary = new vol_desc_primary_t(m__io, this, m__root);
}
}
iso9660_t::vol_desc_t::~vol_desc_t() {
_clean_up();
}
void iso9660_t::vol_desc_t::_clean_up() {
if (!n_vol_desc_boot_record) {
if (m_vol_desc_boot_record) {
delete m_vol_desc_boot_record; m_vol_desc_boot_record = 0;
}
}
if (!n_vol_desc_primary) {
if (m_vol_desc_primary) {
delete m_vol_desc_primary; m_vol_desc_primary = 0;
}
}
}
iso9660_t::path_table_entry_le_t::path_table_entry_le_t(kaitai::kstream* p__io, iso9660_t::path_table_le_t* p__parent, iso9660_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void iso9660_t::path_table_entry_le_t::_read() {
m_len_dir_name = m__io->read_u1();
m_len_ext_attr_rec = m__io->read_u1();
m_lba_extent = m__io->read_u4le();
m_parent_dir_idx = m__io->read_u2le();
m_dir_name = kaitai::kstream::bytes_to_str(m__io->read_bytes(len_dir_name()), std::string("UTF-8"));
n_padding = true;
if (kaitai::kstream::mod(len_dir_name(), 2) == 1) {
n_padding = false;
m_padding = m__io->read_u1();
}
}
iso9660_t::path_table_entry_le_t::~path_table_entry_le_t() {
_clean_up();
}
void iso9660_t::path_table_entry_le_t::_clean_up() {
if (!n_padding) {
}
}
iso9660_t::dir_entries_t::dir_entries_t(kaitai::kstream* p__io, iso9660_t::dir_entry_body_t* p__parent, iso9660_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 iso9660_t::dir_entries_t::_read() {
m_entries = new std::vector<dir_entry_t*>();
{
int i = 0;
dir_entry_t* _;
do {
_ = new dir_entry_t(m__io, this, m__root);
m_entries->push_back(_);
i++;
} while (!(_->len() == 0));
}
}
iso9660_t::dir_entries_t::~dir_entries_t() {
_clean_up();
}
void iso9660_t::dir_entries_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;
}
}
iso9660_t::u4bi_t::u4bi_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, iso9660_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void iso9660_t::u4bi_t::_read() {
m_le = m__io->read_u4le();
m_be = m__io->read_u4be();
}
iso9660_t::u4bi_t::~u4bi_t() {
_clean_up();
}
void iso9660_t::u4bi_t::_clean_up() {
}
iso9660_t::u2bi_t::u2bi_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, iso9660_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void iso9660_t::u2bi_t::_read() {
m_le = m__io->read_u2le();
m_be = m__io->read_u2be();
}
iso9660_t::u2bi_t::~u2bi_t() {
_clean_up();
}
void iso9660_t::u2bi_t::_clean_up() {
}
iso9660_t::path_table_le_t::path_table_le_t(kaitai::kstream* p__io, iso9660_t::vol_desc_primary_t* p__parent, iso9660_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 iso9660_t::path_table_le_t::_read() {
m_entries = new std::vector<path_table_entry_le_t*>();
{
int i = 0;
while (!m__io->is_eof()) {
m_entries->push_back(new path_table_entry_le_t(m__io, this, m__root));
i++;
}
}
}
iso9660_t::path_table_le_t::~path_table_le_t() {
_clean_up();
}
void iso9660_t::path_table_le_t::_clean_up() {
if (m_entries) {
for (std::vector<path_table_entry_le_t*>::iterator it = m_entries->begin(); it != m_entries->end(); ++it) {
delete *it;
}
delete m_entries; m_entries = 0;
}
}
iso9660_t::dec_datetime_t::dec_datetime_t(kaitai::kstream* p__io, iso9660_t::vol_desc_primary_t* p__parent, iso9660_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void iso9660_t::dec_datetime_t::_read() {
m_year = kaitai::kstream::bytes_to_str(m__io->read_bytes(4), std::string("ASCII"));
m_month = kaitai::kstream::bytes_to_str(m__io->read_bytes(2), std::string("ASCII"));
m_day = kaitai::kstream::bytes_to_str(m__io->read_bytes(2), std::string("ASCII"));
m_hour = kaitai::kstream::bytes_to_str(m__io->read_bytes(2), std::string("ASCII"));
m_minute = kaitai::kstream::bytes_to_str(m__io->read_bytes(2), std::string("ASCII"));
m_sec = kaitai::kstream::bytes_to_str(m__io->read_bytes(2), std::string("ASCII"));
m_sec_hundreds = kaitai::kstream::bytes_to_str(m__io->read_bytes(2), std::string("ASCII"));
m_timezone = m__io->read_u1();
}
iso9660_t::dec_datetime_t::~dec_datetime_t() {
_clean_up();
}
void iso9660_t::dec_datetime_t::_clean_up() {
}
iso9660_t::dir_entry_body_t::dir_entry_body_t(kaitai::kstream* p__io, iso9660_t::dir_entry_t* p__parent, iso9660_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_lba_extent = 0;
m_size_extent = 0;
m_datetime = 0;
m_vol_seq_num = 0;
m_extent_as_dir = 0;
m__io__raw_extent_as_dir = 0;
f_extent_as_dir = false;
f_extent_as_file = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void iso9660_t::dir_entry_body_t::_read() {
m_len_ext_attr_rec = m__io->read_u1();
m_lba_extent = new u4bi_t(m__io, this, m__root);
m_size_extent = new u4bi_t(m__io, this, m__root);
m_datetime = new datetime_t(m__io, this, m__root);
m_file_flags = m__io->read_u1();
m_file_unit_size = m__io->read_u1();
m_interleave_gap_size = m__io->read_u1();
m_vol_seq_num = new u2bi_t(m__io, this, m__root);
m_len_file_name = m__io->read_u1();
m_file_name = kaitai::kstream::bytes_to_str(m__io->read_bytes(len_file_name()), std::string("UTF-8"));
n_padding = true;
if (kaitai::kstream::mod(len_file_name(), 2) == 0) {
n_padding = false;
m_padding = m__io->read_u1();
}
m_rest = m__io->read_bytes_full();
}
iso9660_t::dir_entry_body_t::~dir_entry_body_t() {
_clean_up();
}
void iso9660_t::dir_entry_body_t::_clean_up() {
if (m_lba_extent) {
delete m_lba_extent; m_lba_extent = 0;
}
if (m_size_extent) {
delete m_size_extent; m_size_extent = 0;
}
if (m_datetime) {
delete m_datetime; m_datetime = 0;
}
if (m_vol_seq_num) {
delete m_vol_seq_num; m_vol_seq_num = 0;
}
if (!n_padding) {
}
if (f_extent_as_dir && !n_extent_as_dir) {
if (m__io__raw_extent_as_dir) {
delete m__io__raw_extent_as_dir; m__io__raw_extent_as_dir = 0;
}
if (m_extent_as_dir) {
delete m_extent_as_dir; m_extent_as_dir = 0;
}
}
if (f_extent_as_file && !n_extent_as_file) {
}
}
iso9660_t::dir_entries_t* iso9660_t::dir_entry_body_t::extent_as_dir() {
if (f_extent_as_dir)
return m_extent_as_dir;
n_extent_as_dir = true;
if ((file_flags() & 2) != 0) {
n_extent_as_dir = false;
kaitai::kstream *io = _root()->_io();
std::streampos _pos = io->pos();
io->seek((lba_extent()->le() * _root()->sector_size()));
m__raw_extent_as_dir = io->read_bytes(size_extent()->le());
m__io__raw_extent_as_dir = new kaitai::kstream(m__raw_extent_as_dir);
m_extent_as_dir = new dir_entries_t(m__io__raw_extent_as_dir, this, m__root);
io->seek(_pos);
f_extent_as_dir = true;
}
return m_extent_as_dir;
}
std::string iso9660_t::dir_entry_body_t::extent_as_file() {
if (f_extent_as_file)
return m_extent_as_file;
n_extent_as_file = true;
if ((file_flags() & 2) == 0) {
n_extent_as_file = false;
kaitai::kstream *io = _root()->_io();
std::streampos _pos = io->pos();
io->seek((lba_extent()->le() * _root()->sector_size()));
m_extent_as_file = io->read_bytes(size_extent()->le());
io->seek(_pos);
f_extent_as_file = true;
}
return m_extent_as_file;
}
int32_t iso9660_t::sector_size() {
if (f_sector_size)
return m_sector_size;
m_sector_size = 2048;
f_sector_size = true;
return m_sector_size;
}
iso9660_t::vol_desc_t* iso9660_t::primary_vol_desc() {
if (f_primary_vol_desc)
return m_primary_vol_desc;
std::streampos _pos = m__io->pos();
m__io->seek((16 * sector_size()));
m_primary_vol_desc = new vol_desc_t(m__io, this, m__root);
m__io->seek(_pos);
f_primary_vol_desc = true;
return m_primary_vol_desc;
}