* Copyright 2012, Jérôme Duval, korli@users.berlios.de.
* Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
* This file may be used under the terms of the MIT License.
*/
UDF on-disk data structure definitions
*/
#include "UdfStructures.h"
#include <string.h>
#include "UdfString.h"
#include "Utils.h"
const charspec kCs0CharacterSet(0, "OSTA Compressed Unicode");
const char* kVSDID_BEA = "BEA01";
const char* kVSDID_TEA = "TEA01";
const char* kVSDID_BOOT = "BOOT2";
const char* kVSDID_ISO = "CD001";
const char* kVSDID_ECMA167_2 = "NSR02";
const char* kVSDID_ECMA167_3 = "NSR03";
const char* kVSDID_ECMA168 = "CDW02";
const uint16 kCrcTable[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
const uint32 kLogicalVolumeDescriptorBaseSize = sizeof(logical_volume_descriptor)
- (UDF_MAX_PARTITION_MAPS
* UDF_MAX_PARTITION_MAP_SIZE);
entity_id kMetadataPartitionMapId;
entity_id kSparablePartitionMapId;
entity_id kVirtualPartitionMapId;
entity_id kImplementationId;
entity_id kPartitionContentsId1xx;
entity_id kPartitionContentsId2xx;
entity_id kLogicalVolumeInfoId150;
entity_id kLogicalVolumeInfoId201;
entity_id kDomainId150;
entity_id kDomainId201;
void
init_entities()
{
kMetadataPartitionMapId = entity_id(0, "*UDF Metadata Partition");
kSparablePartitionMapId = entity_id(0, "*UDF Sparable Partition");
kVirtualPartitionMapId = entity_id(0, "*UDF Virtual Partition");
kImplementationId = entity_id(0, "*Haiku UDF", implementation_id_suffix(OS_BEOS, BEOS_GENERIC));
kPartitionContentsId1xx = entity_id(0, "+NSR02");
kPartitionContentsId2xx = entity_id(0, "+NSR03");
kLogicalVolumeInfoId150 = entity_id(0, "*UDF LV Info", udf_id_suffix(0x0150, OS_BEOS, BEOS_GENERIC));
kLogicalVolumeInfoId201 = entity_id(0, "*UDF LV Info", udf_id_suffix(0x0201, OS_BEOS, BEOS_GENERIC));
kDomainId150 = entity_id(0, "*OSTA UDF Compliant", domain_id_suffix(0x0150,
DF_HARD_WRITE_PROTECT));
kDomainId201 = entity_id(0, "*OSTA UDF Compliant", domain_id_suffix(0x0201,
DF_HARD_WRITE_PROTECT));
}
const char *tag_id_to_string(tag_id id)
{
switch (id) {
case TAGID_UNDEFINED:
return "undefined";
case TAGID_PRIMARY_VOLUME_DESCRIPTOR:
return "primary volume descriptor";
case TAGID_ANCHOR_VOLUME_DESCRIPTOR_POINTER:
return "anchor volume descriptor pointer";
case TAGID_VOLUME_DESCRIPTOR_POINTER:
return "volume descriptor pointer";
case TAGID_IMPLEMENTATION_USE_VOLUME_DESCRIPTOR:
return "implementation use volume descriptor";
case TAGID_PARTITION_DESCRIPTOR:
return "partition descriptor";
case TAGID_LOGICAL_VOLUME_DESCRIPTOR:
return "logical volume descriptor";
case TAGID_UNALLOCATED_SPACE_DESCRIPTOR:
return "unallocated space descriptor";
case TAGID_TERMINATING_DESCRIPTOR:
return "terminating descriptor";
case TAGID_LOGICAL_VOLUME_INTEGRITY_DESCRIPTOR:
return "logical volume integrity descriptor";
case TAGID_FILE_SET_DESCRIPTOR:
return "file set descriptor";
case TAGID_FILE_ID_DESCRIPTOR:
return "file identifier descriptor";
case TAGID_ALLOCATION_EXTENT_DESCRIPTOR:
return "allocation extent descriptor";
case TAGID_INDIRECT_ENTRY:
return "indirect entry";
case TAGID_TERMINAL_ENTRY:
return "terminal entry";
case TAGID_FILE_ENTRY:
return "file entry";
case TAGID_EXTENDED_ATTRIBUTE_HEADER_DESCRIPTOR:
return "extended attribute header descriptor";
case TAGID_UNALLOCATED_SPACE_ENTRY:
return "unallocated space entry";
case TAGID_SPACE_BITMAP_DESCRIPTOR:
return "space bitmap descriptor";
case TAGID_PARTITION_INTEGRITY_ENTRY:
return "partition integrity entry";
case TAGID_EXTENDED_FILE_ENTRY:
return "extended file entry";
default:
if (TAGID_CUSTOM_START <= id && id <= TAGID_CUSTOM_END)
return "custom";
return "reserved";
}
}
volume_structure_descriptor_header::volume_structure_descriptor_header(uint8 type, const char *_id, uint8 version)
: type(type)
, version(version)
{
memcpy(id, _id, 5);
}
*/
bool
volume_structure_descriptor_header::id_matches(const char *id)
{
return strncmp(this->id, id, 5) == 0;
}
charspec::charspec(uint8 type, const char *info)
{
set_character_set_type(type);
set_character_set_info(info);
}
void
charspec::dump() const
{
DUMP_INIT("charspec");
PRINT(("character_set_type: %d\n", character_set_type()));
PRINT(("character_set_info: `%s'\n", character_set_info()));
}
void
charspec::set_character_set_info(const char *info)
{
memset(_character_set_info, 0, 63);
if (info)
strncpy(_character_set_info, info, 63);
}
#if _KERNEL_MODE
static
int
get_month_length(int month, int year)
{
if (0 <= month && month < 12 && year >= 1970) {
const int monthLengths[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int result = monthLengths[month];
if (month == 1 && ((year - 1968) % 4 == 0))
result++;
return result;
} else {
DEBUG_INIT_ETC(NULL, ("month: %d, year: %d", month, year));
PRINT(("Invalid month or year! Returning 0\n"));
return 0;
}
}
#endif
timestamp::timestamp(time_t time)
{
#if !_KERNEL_MODE
tm *local = localtime(&time);
if (local) {
set_microsecond(0);
set_hundred_microsecond(0);
set_centisecond(0);
set_second(local->tm_sec);
set_minute(local->tm_min);
set_hour(local->tm_hour);
set_day(local->tm_mday);
set_month(local->tm_mon+1);
set_year(local->tm_year+1900);
set_type(1);
set_timezone(local->tm_gmtoff / 60);
} else {
_clear();
}
#else
time += 16 * 60 * 60;
set_microsecond(0);
set_hundred_microsecond(0);
set_centisecond(0);
set_second(time % 60);
time = time / 60;
set_minute(time % 60);
time = time / 60;
set_hour(time % 24);
time = time / 24;
int year = 0;
int month = 0;
time_t clock = 0;
for (clock = 0;
clock + get_month_length(month, year+1970) < time;
clock += get_month_length(month, year+1970))
{
month++;
if (month == 12) {
year++;
month = 0;
}
}
int day = time - clock;
set_day(day);
set_month(month+1);
set_year(year+1970);
set_type(1);
set_timezone(-2047);
#endif
}
void
timestamp::dump() const
{
DUMP_INIT("timestamp");
PRINT(("type: %d\n", type()));
PRINT(("timezone: %d\n", timezone()));
PRINT(("year: %d\n", year()));
PRINT(("month: %d\n", month()));
PRINT(("day: %d\n", day()));
PRINT(("hour: %d\n", hour()));
PRINT(("minute: %d\n", minute()));
PRINT(("second: %d\n", second()));
PRINT(("centisecond: %d\n", centisecond()));
PRINT(("hundred_microsecond: %d\n", hundred_microsecond()));
PRINT(("microsecond: %d\n", microsecond()));
}
void
timestamp::_clear()
{
set_microsecond(0);
set_hundred_microsecond(0);
set_centisecond(0);
set_second(0);
set_minute(0);
set_hour(0);
set_day(0);
set_month(0);
set_year(0);
set_type(0);
set_timezone(0);
}
udf_id_suffix::udf_id_suffix(uint16 udfRevision, uint8 os_class,
uint8 os_identifier)
: _udf_revision(udfRevision)
, _os_class(os_class)
, _os_identifier(os_identifier)
{
memset(_reserved.data, 0, _reserved.size());
}
implementation_id_suffix::implementation_id_suffix(uint8 os_class,
uint8 os_identifier)
: _os_class(os_class)
, _os_identifier(os_identifier)
{
memset(_implementation_use.data, 0, _implementation_use.size());
}
domain_id_suffix::domain_id_suffix(uint16 udfRevision, uint8 domainFlags)
: _udf_revision(udfRevision)
, _domain_flags(domainFlags)
{
memset(_reserved.data, 0, _reserved.size());
}
entity_id::entity_id(uint8 flags, const char *identifier, uint8 *identifier_suffix)
: _flags(flags)
{
memset(_identifier, 0, kIdentifierLength);
if (identifier)
strncpy(_identifier, identifier, kIdentifierLength);
if (identifier_suffix)
memcpy(_identifier_suffix.data, identifier_suffix, kIdentifierSuffixLength);
else
memset(_identifier_suffix.data, 0, kIdentifierSuffixLength);
}
entity_id::entity_id(uint8 flags, const char *identifier,
const udf_id_suffix &suffix)
: _flags(flags)
{
memset(_identifier, 0, kIdentifierLength);
if (identifier)
strncpy(_identifier, identifier, kIdentifierLength);
memcpy(_identifier_suffix.data, &suffix, kIdentifierSuffixLength);
}
entity_id::entity_id(uint8 flags, const char *identifier,
const implementation_id_suffix &suffix)
: _flags(flags)
{
memset(_identifier, 0, kIdentifierLength);
if (identifier)
strncpy(_identifier, identifier, kIdentifierLength);
memcpy(_identifier_suffix.data, &suffix, kIdentifierSuffixLength);
}
entity_id::entity_id(uint8 flags, const char *identifier,
const domain_id_suffix &suffix)
: _flags(flags)
{
memset(_identifier, 0, kIdentifierLength);
if (identifier)
strncpy(_identifier, identifier, kIdentifierLength);
memcpy(_identifier_suffix.data, &suffix, kIdentifierSuffixLength);
}
void
entity_id::dump() const
{
DUMP_INIT("entity_id");
PRINT(("flags: %d\n", flags()));
PRINT(("identifier: `%.23s'\n", identifier()));
PRINT(("identifier_suffix:\n"));
DUMP(identifier_suffix());
}
bool
entity_id::matches(const entity_id &id) const
{
bool result = true;
for (int i = 0; i < entity_id::kIdentifierLength; i++) {
if (identifier()[i] != id.identifier()[i]) {
result = false;
break;
}
}
return result;
}
extent_address::extent_address(uint32 location, uint32 length)
{
set_location(location);
set_length(length);
}
void
extent_address::dump() const
{
DUMP_INIT("extent_address");
PRINT(("length: %" B_PRIu32 "\n", length()));
PRINT(("location: %" B_PRIu32 "\n", location()));
}
void
logical_block_address::dump() const
{
DUMP_INIT("logical_block_address");
PRINT(("block: %" B_PRIu32 "\n", block()));
PRINT(("partition: %d\n", partition()));
}
logical_block_address::logical_block_address(uint16 partition, uint32 block)
{
set_partition(partition);
set_block(block);
}
long_address::long_address(uint16 partition, uint32 block, uint32 length,
uint8 type)
{
set_partition(partition);
set_block(block);
set_length(length);
set_type(type);
memset(_implementation_use.data, 0, _implementation_use.size());
}
void
long_address::dump() const
{
DUMP_INIT("long_address");
PRINT(("length: %" B_PRIu32 "\n", length()));
PRINT(("block: %" B_PRIu32 "\n", block()));
PRINT(("partition: %d\n", partition()));
PRINT(("implementation_use:\n"));
DUMP(implementation_use());
}
void
descriptor_tag::dump() const
{
DUMP_INIT("descriptor_tag");
PRINT(("id: %d (%s)\n", id(), tag_id_to_string(tag_id(id()))));
PRINT(("version: %d\n", version()));
PRINT(("checksum: %d\n", checksum()));
PRINT(("serial_number: %d\n", serial_number()));
PRINT(("crc: %d\n", crc()));
PRINT(("crc_length: %d\n", crc_length()));
PRINT(("location: %" B_PRIu32 "\n", location()));
}
verifies the tag's location on the medium.
Note that this function makes the assumption that the descriptor_tag
is the first data member in a larger descriptor structure, the remainder
of which immediately follows the descriptor_tag itself in memory. This
is generally a safe assumption, as long as the entire descriptor (and
not the its tag) is read in before init_check() is called. If this is
not the case, it's best to call this function with a \a calculateCrc
value of false, to keep from trying to calculate a crc value on invalid
and possibly unowned memory.
\param block The block location of this descriptor as taken from the
corresponding allocation descriptor. If the address specifies
a block in a partition, the partition block is the desired
location, not the mapped physical disk block.
\param calculateCrc Whether or not to perform the crc calculation
on the descriptor data following the tag.
*/
status_t
descriptor_tag::init_check(uint32 block, bool calculateCrc)
{
DEBUG_INIT_ETC("descriptor_tag", ("location: %" B_PRIu32 ", "
"calculateCrc: %s",
block, bool_to_string(calculateCrc)));
PRINT(("location (parameter) == %" B_PRIu32 "\n", block));
PRINT(("location (in structure) == %" B_PRIu32 "\n", location()));
if (calculateCrc) {
PRINT(("crc (calculated) == %d\n",
calculate_crc(reinterpret_cast<uint8*>(this)+sizeof(descriptor_tag),
crc_length())))
} else {
PRINT(("crc (calculated) == (not calculated)\n"));
}
PRINT(("crc (in structure) == %d\n", crc()));
PRINT(("crc_length (in structure) == %d\n", crc_length()));
status_t error = (block == location()) ? B_OK : B_NO_INIT;
if (!error) {
uint32 sum = 0;
for (int i = 0; i <= 3; i++)
sum += reinterpret_cast<uint8*>(this)[i];
for (int i = 5; i <= 15; i++)
sum += reinterpret_cast<uint8*>(this)[i];
error = sum % 256 == checksum() ? B_OK : B_NO_INIT;
}
if (!error && calculateCrc) {
uint16 _crc = calculate_crc(reinterpret_cast<uint8*>(this)
+ sizeof(descriptor_tag), crc_length());
error = _crc == crc() ? B_OK : B_NO_INIT;
}
RETURN(error);
}
void
primary_volume_descriptor::dump() const
{
DUMP_INIT("primary_volume_descriptor");
UdfString string;
PRINT(("tag:\n"));
DUMP(tag());
PRINT(("vds_number: %" B_PRIu32 "\n", vds_number()));
PRINT(("primary_volume_descriptor_number: %" B_PRIu32 "\n",
primary_volume_descriptor_number()));
string = volume_identifier();
PRINT(("volume_identifier: `%s'\n", string.Utf8()));
PRINT(("volume_sequence_number: %d\n", volume_sequence_number()));
PRINT(("max_volume_sequence_number: %d\n", max_volume_sequence_number()));
PRINT(("interchange_level: %d\n", interchange_level()));
PRINT(("max_interchange_level: %d\n", max_interchange_level()));
PRINT(("character_set_list: %" B_PRIu32 "\n",
character_set_list()));
PRINT(("max_character_set_list: %" B_PRIu32 "\n",
max_character_set_list()));
string = volume_set_identifier();
PRINT(("volume_set_identifier: `%s'\n", string.Utf8()));
PRINT(("descriptor_character_set:\n"));
DUMP(descriptor_character_set());
PRINT(("explanatory_character_set:\n"));
DUMP(explanatory_character_set());
PRINT(("volume_abstract:\n"));
DUMP(volume_abstract());
PRINT(("volume_copyright_notice:\n"));
DUMP(volume_copyright_notice());
PRINT(("application_id:\n"));
DUMP(application_id());
PRINT(("recording_date_and_time:\n"));
DUMP(recording_date_and_time());
PRINT(("implementation_id:\n"));
DUMP(implementation_id());
PRINT(("implementation_use:\n"));
DUMP(implementation_use());
PRINT(("predecessor_vds_location: %" B_PRIu32 "\n",
predecessor_volume_descriptor_sequence_location()));
PRINT(("flags: %d\n", flags()));
}
void
anchor_volume_descriptor::dump() const
{
DUMP_INIT("anchor_volume_descriptor");
PRINT(("tag:\n"));
DUMP(tag());
PRINT(("main_vds:\n"));
DUMP(main_vds());
PRINT(("reserve_vds:\n"));
DUMP(reserve_vds());
}
void
logical_volume_info::dump() const
{
UdfString string;
DUMP_INIT("logical_volume_information");
PRINT(("character_set:\n"));
DUMP(character_set());
string = logical_volume_id();
PRINT(("logical_volume_id: `%s'\n", string.Utf8()));
for (uint32 i = 0; i < _logical_volume_info.length(); i++) {
string = _logical_volume_info[i];
PRINT(("logical_volume_info #%" B_PRIu32 ": %s\n", i, string.Utf8()));
}
PRINT(("implementation_id:\n"));
DUMP(implementation_id());
PRINT(("implementation_use:\n"));
DUMP(implementation_use());
}
void
implementation_use_descriptor::dump() const
{
DUMP_INIT("implementation_use_descriptor");
PRINT(("tag:\n"));
DUMP(tag());
PRINT(("vds_number: %" B_PRIu32 "\n", vds_number()));
PRINT(("implementation_id:\n"));
DUMP(implementation_id());
PRINT(("implementation_use: XXX\n"));
DUMP(implementation_use());
}
void
partition_descriptor::dump() const
{
DUMP_INIT("partition_descriptor");
PRINT(("tag:\n"));
DUMP(tag());
PRINT(("vds_number: %" B_PRIu32 "\n", vds_number()));
PRINT(("partition_flags: %d\n", partition_flags()));
PRINT(("partition_flags.allocated: %s\n", allocated() ? "true" : "false"));
PRINT(("partition_number: %d\n", partition_number()));
PRINT(("partition_contents:\n"));
DUMP(partition_contents());
PRINT(("partition_contents_use: XXX\n"));
DUMP(partition_contents_use());
PRINT(("access_type: %" B_PRIu32 "\n", access_type()));
PRINT(("start: %" B_PRIu32 "\n", start()));
PRINT(("length: %" B_PRIu32 "\n", length()));
PRINT(("implementation_id:\n"));
DUMP(implementation_id());
PRINT(("implementation_use: XXX\n"));
DUMP(implementation_use());
}
void
logical_volume_descriptor::dump() const
{
DUMP_INIT("logical_volume_descriptor");
PRINT(("tag:\n"));
DUMP(tag());
PRINT(("vds_number: %" B_PRIu32 "\n", vds_number()));
PRINT(("character_set:\n"));
DUMP(character_set());
UdfString string(logical_volume_identifier());
PRINT(("logical_volume_identifier: `%s'\n", string.Utf8()));
PRINT(("logical_block_size: %" B_PRIu32 "\n",
logical_block_size()));
PRINT(("domain_id:\n"));
DUMP(domain_id());
PRINT(("logical_volume_contents_use:\n"));
DUMP(logical_volume_contents_use());
PRINT(("file_set_address:\n"));
DUMP(file_set_address());
PRINT(("map_table_length: %" B_PRIu32 "\n", map_table_length()));
PRINT(("partition_map_count: %" B_PRIu32 "\n",
partition_map_count()));
PRINT(("implementation_id:\n"));
DUMP(implementation_id());
PRINT(("implementation_use:\n"));
DUMP(implementation_use());
PRINT(("integrity_sequence_extent:\n"));
DUMP(integrity_sequence_extent());
const uint8 *maps = partition_maps();
int offset = 0;
for (uint i = 0; i < partition_map_count(); i++) {
PRINT(("partition_map #%d:\n", i));
uint8 type = maps[offset];
uint8 length = maps[offset+1];
PRINT((" type: %d\n", type));
PRINT((" length: %d\n", length));
switch (type) {
case 1:
for (int j = 0; j < length-2; j++)
PRINT((" data[%d]: %d\n", j, maps[offset+2+j]));
break;
case 2: {
PRINT((" partition_number: %d\n", *reinterpret_cast<const uint16*>(&(maps[offset+38]))));
PRINT((" entity_id:\n"));
const entity_id *id = reinterpret_cast<const entity_id*>(&(maps[offset+4]));
if (id)
PDUMP(id);
break;
}
}
offset += maps[offset+1];
}
}
logical_volume_descriptor&
logical_volume_descriptor::operator=(const logical_volume_descriptor &rhs)
{
_tag = rhs._tag;
_vds_number = rhs._vds_number;
_character_set = rhs._character_set;
_logical_volume_identifier = rhs._logical_volume_identifier;
_logical_block_size = rhs._logical_block_size;
_domain_id = rhs._domain_id;
_logical_volume_contents_use = rhs._logical_volume_contents_use;
_map_table_length = rhs._map_table_length;
_partition_map_count = rhs._partition_map_count;
_implementation_id = rhs._implementation_id;
_implementation_use = rhs._implementation_use;
_integrity_sequence_extent = rhs._integrity_sequence_extent;
uint8 *lhsMaps = partition_maps();
const uint8 *rhsMaps = rhs.partition_maps();
int offset = 0;
for (uint8 i = 0; i < rhs.partition_map_count(); i++) {
uint8 length = rhsMaps[offset+1];
memcpy(&lhsMaps[offset], &rhsMaps[offset], length);
offset += length;
}
return *this;
}
void
physical_partition_map::dump()
{
DUMP_INIT("physical_partition_map");
PRINT(("type: %d\n", type()));
PRINT(("length: %d\n", length()));
PRINT(("volume_sequence_number: %d\n", volume_sequence_number()));
PRINT(("partition_number: %d\n", partition_number()));
}
void
sparable_partition_map::dump()
{
DUMP_INIT("sparable_partition_map");
PRINT(("type: %d\n", type()));
PRINT(("length: %d\n", length()));
PRINT(("partition_type_id:"));
DUMP(partition_type_id());
PRINT(("volume_sequence_number: %d\n", volume_sequence_number()));
PRINT(("partition_number: %d\n", partition_number()));
PRINT(("sparing_table_count: %d\n", sparing_table_count()));
PRINT(("sparing_table_size: %" B_PRIu32 "\n", sparing_table_size()));
PRINT(("sparing_table_locations:"));
for (uint8 i = 0; i < sparing_table_count(); i++)
PRINT((" %d: %" B_PRIu32 "\n", i, sparing_table_location(i)));
}
void
unallocated_space_descriptor::dump() const
{
DUMP_INIT("unallocated_space_descriptor");
PRINT(("tag:\n"));
DUMP(tag());
PRINT(("vds_number: %" B_PRIu32 "\n", vds_number()));
PRINT(("allocation_descriptor_count: %" B_PRIu32 "\n",
allocation_descriptor_count()));
}
void
terminating_descriptor::dump() const
{
DUMP_INIT("terminating_descriptor");
PRINT(("tag:\n"));
DUMP(tag());
}
void
file_set_descriptor::dump() const
{
DUMP_INIT("file_set_descriptor");
PRINT(("tag:\n"));
DUMP(tag());
PRINT(("recording_date_and_time:\n"));
DUMP(recording_date_and_time());
PRINT(("interchange_level: %d\n", interchange_level()));
PRINT(("max_interchange_level: %d\n", max_interchange_level()));
PRINT(("character_set_list: %" B_PRIu32 "\n", character_set_list()));
PRINT(("max_character_set_list: %" B_PRIu32 "\n",
max_character_set_list()));
PRINT(("file_set_number: %" B_PRIu32 "\n", file_set_number()));
PRINT(("file_set_descriptor_number: %" B_PRIu32 "\n",
file_set_descriptor_number()));
PRINT(("logical_volume_id_character_set:\n"));
DUMP(logical_volume_id_character_set());
PRINT(("logical_volume_id:\n"));
DUMP(logical_volume_id());
PRINT(("file_set_id_character_set:\n"));
DUMP(file_set_id_character_set());
PRINT(("file_set_id:\n"));
DUMP(file_set_id());
PRINT(("copyright_file_id:\n"));
DUMP(copyright_file_id());
PRINT(("abstract_file_id:\n"));
DUMP(abstract_file_id());
PRINT(("root_directory_icb:\n"));
DUMP(root_directory_icb());
PRINT(("domain_id:\n"));
DUMP(domain_id());
PRINT(("next_extent:\n"));
DUMP(next_extent());
PRINT(("system_stream_directory_icb:\n"));
DUMP(system_stream_directory_icb());
}
void
logical_volume_integrity_descriptor::dump() const
{
DUMP_INIT("logical_volume_integrity_descriptor");
PRINT(("tag:\n"));
DUMP(tag());
PRINT(("recording_time:\n"));
DUMP(recording_time());
PRINT(("integrity_type: "));
switch (integrity_type()) {
case INTEGRITY_OPEN:
SIMPLE_PRINT(("open\n"));
break;
case INTEGRITY_CLOSED:
SIMPLE_PRINT(("closed\n"));
break;
default:
SIMPLE_PRINT(("invalid integrity type (%" B_PRIu32 ")",
integrity_type()));
break;
}
PRINT(("next_integrity_extent:\n"));
DUMP(next_integrity_extent());
PRINT(("logical_volume_contents_use:\n"));
DUMP(logical_volume_contents_use());
PRINT(("next_unique_id: %" B_PRIu64 "\n", next_unique_id()));
PRINT(("partition_count: %" B_PRIu32 "\n", partition_count()));
PRINT(("implementation_use_length: %" B_PRIu32 "\n",
implementation_use_length()));
if (partition_count() > 0) {
PRINT(("free_space_table:\n"));
for (uint32 i = 0; i < partition_count(); i++) {
PRINT(("partition %" B_PRIu32 ": %" B_PRIu32 " free blocks\n",
i, free_space_table()[i]));
}
PRINT(("size_table:\n"));
for (uint32 i = 0; i < partition_count(); i++) {
PRINT(("partition %" B_PRIu32 ": %" B_PRIu32 " blocks large\n",
i, size_table()[i]));
}
}
if (implementation_use_length() >= minimum_implementation_use_length) {
PRINT(("implementation_id:\n"));
DUMP(implementation_id());
PRINT(("file_count: %" B_PRIu32 "\n", file_count()));
PRINT(("directory_count: %" B_PRIu32 "\n",
directory_count()));
PRINT(("minimum_udf_read_revision: 0x%04x\n", minimum_udf_read_revision()));
PRINT(("minimum_udf_write_revision: 0x%04x\n", minimum_udf_write_revision()));
PRINT(("maximum_udf_write_revision: 0x%04x\n", maximum_udf_write_revision()));
} else {
PRINT(("NOTE: implementation_use() field of insufficient length to contain \n"));
PRINT((" appropriate UDF-2.50 2.2.6.4 fields.\n"));
}
}
void
file_id_descriptor::dump() const
{
DUMP_INIT("file_id_descriptor");
PRINT(("tag:\n"));
DUMP(tag());
PRINT(("version_number: %d\n", version_number()));
PRINT(("may_be_hidden: %d\n", may_be_hidden()));
PRINT(("is_directory: %d\n", is_directory()));
PRINT(("is_deleted: %d\n", is_deleted()));
PRINT(("is_parent: %d\n", is_parent()));
PRINT(("is_metadata_stream: %d\n", is_metadata_stream()));
PRINT(("id_length: %d\n", id_length()));
PRINT(("icb:\n"));
DUMP(icb());
PRINT(("implementation_use_length: %d\n", is_parent()));
UdfString fileId(id());
PRINT(("id: `%s'", fileId.Utf8()));
}
void
icb_entry_tag::dump() const
{
DUMP_INIT("icb_entry_tag");
PRINT(("prior_entries: %" B_PRIu32 "\n",
prior_recorded_number_of_direct_entries()));
PRINT(("strategy_type: %d\n", strategy_type()));
PRINT(("strategy_parameters:\n"));
DUMP(strategy_parameters());
PRINT(("entry_count: %d\n", entry_count()));
PRINT(("file_type: %d\n", file_type()));
PRINT(("parent_icb_location:\n"));
DUMP(parent_icb_location());
PRINT(("all_flags: %d\n", flags()));
uint32 prior_recorded_number_of_direct_entries;
uint16 strategy_type;
array<uint8, 2> strategy_parameters;
uint16 entry_count;
uint8 reserved;
uint8 file_type;
logical_block_address parent_icb_location;
union {
uint16 all_flags;
struct {
uint16 descriptor_flags:3,
if_directory_then_sort:1, //!< To be set to 0 per UDF-2.01 2.3.5.4
non_relocatable:1,
archive:1,
setuid:1,
setgid:1,
sticky:1,
contiguous:1,
system:1,
transformed:1,
multi_version:1, //!< To be set to 0 per UDF-2.01 2.3.5.4
is_stream:1,
reserved_icb_entry_flags:2;
} flags;
};
*/
}
void
icb_header::dump() const
{
DUMP_INIT("icb_header");
PRINT(("tag:\n"));
DUMP(tag());
PRINT(("icb_tag:\n"));
DUMP(icb_tag());
}
long_address file_icb_entry::_dummy_stream_directory_icb;
void
file_icb_entry::dump() const
{
DUMP_INIT("file_icb_entry");
PRINT(("tag:\n"));
DUMP(tag());
PRINT(("icb_tag:\n"));
DUMP(icb_tag());
PRINT(("uid: %" B_PRIu32 ", 0x%" B_PRIx32 "\n",
uid(), uid()));
PRINT(("gid: %" B_PRIu32 ", 0x%" B_PRIx32 "\n",
gid(), gid()));
PRINT(("permissions: %" B_PRIu32 ", 0x%" B_PRIx32 "\n",
permissions(), permissions()));
PRINT(("file_link_count: %d\n", file_link_count()));
PRINT(("record_format: %d\n", record_format()));
PRINT(("record_display_attributes: %d\n", record_display_attributes()));
PRINT(("record_length: %d\n", record_length()));
PRINT(("information_length: %" B_PRIu64 "\n",
information_length()));
PRINT(("logical_blocks_recorded: %" B_PRIu64 "\n",
logical_blocks_recorded()));
PRINT(("access_date_and_time:\n"));
DUMP(access_date_and_time());
PRINT(("modification_date_and_time:\n"));
DUMP(modification_date_and_time());
PRINT(("attribute_date_and_time:\n"));
DUMP(attribute_date_and_time());
PRINT(("checkpoint: %" B_PRIu32 "\n", checkpoint()));
PRINT(("extended_attribute_icb:\n"));
DUMP(extended_attribute_icb());
PRINT(("implementation_id:\n"));
DUMP(implementation_id());
PRINT(("unique_id: %" B_PRIu64 "\n", unique_id()));
PRINT(("extended_attributes_length: %" B_PRIu32 "\n",
extended_attributes_length()));
PRINT(("allocation_descriptors_length: %" B_PRIu32 "\n",
allocation_descriptors_length()));
PRINT(("allocation_descriptors:\n"));
switch (icb_tag().descriptor_flags()) {
case ICB_DESCRIPTOR_TYPE_SHORT:
PRINT((" short descriptors...\n"));
break;
case ICB_DESCRIPTOR_TYPE_LONG:
{
const long_address *address = reinterpret_cast<const long_address*>(allocation_descriptors());
for (uint32 length = allocation_descriptors_length();
length >= sizeof(long_address);
length -= sizeof(long_address), address++)
{
PDUMP(address);
}
break;
}
case ICB_DESCRIPTOR_TYPE_EXTENDED:
PRINT((" extended descriptors...\n"));
break;
case ICB_DESCRIPTOR_TYPE_EMBEDDED:
PRINT((" embedded descriptors...\n"));
break;
default:
PRINT((" invalid descriptors type\n"));
break;
}
}
void
extended_file_icb_entry::dump() const
{
DUMP_INIT("extended_file_icb_entry");
PRINT(("tag:\n"));
DUMP(tag());
PRINT(("icb_tag:\n"));
DUMP(icb_tag());
PRINT(("uid: %" B_PRIu32 ", 0x%" B_PRIx32 "\n",
uid(), uid()));
PRINT(("gid: %" B_PRIu32 ", 0x%" B_PRIx32 "\n",
gid(), gid()));
PRINT(("permissions: %" B_PRIu32 ", 0x%" B_PRIx32 "\n",
permissions(), permissions()));
PRINT(("file_link_count: %d\n", file_link_count()));
PRINT(("record_format: %d\n", record_format()));
PRINT(("record_display_attributes: %d\n", record_display_attributes()));
PRINT(("record_length: %" B_PRIu32 "\n", record_length()));
PRINT(("information_length: %" B_PRIu64 "\n",
information_length()));
PRINT(("logical_blocks_recorded: %" B_PRIu64 "\n",
logical_blocks_recorded()));
PRINT(("access_date_and_time:\n"));
DUMP(access_date_and_time());
PRINT(("modification_date_and_time:\n"));
DUMP(modification_date_and_time());
PRINT(("creation_date_and_time:\n"));
DUMP(creation_date_and_time());
PRINT(("attribute_date_and_time:\n"));
DUMP(attribute_date_and_time());
PRINT(("checkpoint: %" B_PRIu32 "\n", checkpoint()));
PRINT(("extended_attribute_icb:\n"));
DUMP(extended_attribute_icb());
PRINT(("stream_directory_icb:\n"));
DUMP(stream_directory_icb());
PRINT(("implementation_id:\n"));
DUMP(implementation_id());
PRINT(("unique_id: %" B_PRIu64 "\n", unique_id()));
PRINT(("extended_attributes_length: %" B_PRIu32 "\n",
extended_attributes_length()));
PRINT(("allocation_descriptors_length: %" B_PRIu32 "\n",
allocation_descriptors_length()));
PRINT(("allocation_descriptors:\n"));
switch (icb_tag().descriptor_flags()) {
case ICB_DESCRIPTOR_TYPE_SHORT:
PRINT((" short descriptors...\n"));
break;
case ICB_DESCRIPTOR_TYPE_LONG:
{
const long_address *address = reinterpret_cast<const long_address*>(allocation_descriptors());
for (uint32 length = allocation_descriptors_length();
length >= sizeof(long_address);
length -= sizeof(long_address), address++)
{
PDUMP(address);
}
break;
}
case ICB_DESCRIPTOR_TYPE_EXTENDED:
PRINT((" extended descriptors...\n"));
break;
case ICB_DESCRIPTOR_TYPE_EMBEDDED:
PRINT((" embedded descriptors...\n"));
break;
default:
PRINT((" invalid descriptors type\n"));
break;
}
}