1 /* 2 * Copyright 2012, Jérôme Duval, korli@users.berlios.de. 3 * Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net 4 * This file may be used under the terms of the MIT License. 5 */ 6 #ifndef _UDF_DISK_STRUCTURES_H 7 #define _UDF_DISK_STRUCTURES_H 8 9 #include <string.h> 10 11 #include <ByteOrder.h> 12 #include <SupportDefs.h> 13 14 #include "UdfDebug.h" 15 #include "Utils.h" 16 17 #include "Array.h" 18 19 /*! \file UdfStructures.h 20 21 \brief UDF on-disk data structure declarations 22 23 UDF is a specialization of the ECMA-167 standard. For the most part, 24 ECMA-167 structures are used by UDF with special restrictions. In a 25 few instances, UDF introduces its own structures to augment those 26 supplied by ECMA-167; those structures are clearly marked. 27 28 For UDF info: <a href='http://www.osta.org'>http://www.osta.org</a> 29 For ECMA info: <a href='http://www.ecma-international.org'>http://www.ecma-international.org</a> 30 31 For lack of a better place to store this info, the structures that 32 are allowed to have length greater than the logical block size are 33 as follows (other length restrictions may be found in UDF-2.01 5.1): 34 - \c logical_volume_descriptor 35 - \c unallocated_space_descriptor 36 - \c logical_volume_integrity_descriptor 37 - \c space_bitmap_descriptor 38 39 Other links of interest: 40 - <a href='http://www.extra.research.philips.com/udf/'>Philips UDF verifier</a> 41 - <a href='http://www.hi-ho.ne.jp/y-komachi/committees/fpro/fpro.htm'>Possible test disc image generator (?)</a> 42 */ 43 44 //---------------------------------------------------------------------- 45 // ECMA-167 Part 1 46 //---------------------------------------------------------------------- 47 48 /*! \brief Character set specifications 49 50 The character_set_info field shall be set to the ASCII string 51 "OSTA Compressed Unicode" (padded right with NULL chars). 52 53 See also: ECMA 167 1/7.2.1, UDF-2.01 2.1.2 54 */ 55 struct charspec { 56 public: 57 charspec(uint8 type = 0, const char *info = NULL); 58 59 void dump() const; 60 character_set_typecharspec61 uint8 character_set_type() const { return _character_set_type; } character_set_infocharspec62 const char* character_set_info() const { return _character_set_info; } character_set_infocharspec63 char* character_set_info() { return _character_set_info; } 64 set_character_set_typecharspec65 void set_character_set_type(uint8 type) { _character_set_type = type; } 66 void set_character_set_info(const char *info); 67 private: 68 uint8 _character_set_type; //!< to be set to 0 to indicate CS0 69 char _character_set_info[63]; //!< "OSTA Compressed Unicode" 70 } __attribute__((packed)); 71 72 extern const charspec kCs0CharacterSet; 73 74 /*! \brief Date and time stamp 75 76 See also: ECMA 167 1/7.3, UDF-2.01 2.1.4 77 */ 78 class timestamp { 79 private: 80 union type_and_timezone_accessor { 81 uint16 type_and_timezone; 82 struct { 83 uint16 timezone:12, 84 type:4; 85 } bits; 86 }; 87 88 public: timestamp()89 timestamp() { _clear(); } 90 timestamp(time_t time); 91 92 void dump() const; 93 94 // Get functions type_and_timezone()95 uint16 type_and_timezone() const { return B_LENDIAN_TO_HOST_INT16(_type_and_timezone); } type()96 uint8 type() const { 97 type_and_timezone_accessor t; 98 t.type_and_timezone = type_and_timezone(); 99 return t.bits.type; 100 } timezone()101 int16 timezone() const { 102 type_and_timezone_accessor t; 103 t.type_and_timezone = type_and_timezone(); 104 int16 result = t.bits.timezone; 105 // Fill the lefmost bits with ones if timezone is negative 106 result <<= 4; 107 result >>= 4; 108 return result; 109 } year()110 uint16 year() const { return B_LENDIAN_TO_HOST_INT16(_year); } month()111 uint8 month() const { return _month; } day()112 uint8 day() const { return _day; } hour()113 uint8 hour() const { return _hour; } minute()114 uint8 minute() const { return _minute; } second()115 uint8 second() const { return _second; } centisecond()116 uint8 centisecond() const { return _centisecond; } hundred_microsecond()117 uint8 hundred_microsecond() const { return _hundred_microsecond; } microsecond()118 uint8 microsecond() const { return _microsecond; } 119 120 // Set functions set_type_and_timezone(uint16 type_and_timezone)121 void set_type_and_timezone(uint16 type_and_timezone) { 122 _type_and_timezone = B_HOST_TO_LENDIAN_INT16(type_and_timezone); } set_type(uint8 type)123 void set_type(uint8 type) { 124 type_and_timezone_accessor t; 125 t.type_and_timezone = type_and_timezone(); 126 t.bits.type = type; 127 set_type_and_timezone(t.type_and_timezone); 128 } set_timezone(int16 tz)129 void set_timezone(int16 tz) { 130 type_and_timezone_accessor t; 131 t.type_and_timezone = type_and_timezone(); 132 t.bits.timezone = tz; 133 set_type_and_timezone(t.type_and_timezone); 134 } set_year(uint16 year)135 void set_year(uint16 year) { _year = B_HOST_TO_LENDIAN_INT16(year); } set_month(uint8 month)136 void set_month(uint8 month) { _month = month; } set_day(uint8 day)137 void set_day(uint8 day) { _day = day; } set_hour(uint8 hour)138 void set_hour(uint8 hour) { _hour = hour; } set_minute(uint8 minute)139 void set_minute(uint8 minute) { _minute = minute; } set_second(uint8 second)140 void set_second(uint8 second) { _second = second; } set_centisecond(uint8 centisecond)141 void set_centisecond(uint8 centisecond) { _centisecond = centisecond; } set_hundred_microsecond(uint8 hundred_microsecond)142 void set_hundred_microsecond(uint8 hundred_microsecond) { 143 _hundred_microsecond = hundred_microsecond; } set_microsecond(uint8 microsecond)144 void set_microsecond(uint8 microsecond) { _microsecond = microsecond; } 145 private: 146 void _clear(); 147 148 uint16 _type_and_timezone; 149 uint16 _year; 150 uint8 _month; 151 uint8 _day; 152 uint8 _hour; 153 uint8 _minute; 154 uint8 _second; 155 uint8 _centisecond; 156 uint8 _hundred_microsecond; 157 uint8 _microsecond; 158 159 } __attribute__((packed)); 160 161 162 /*! \brief UDF ID Identify Suffix 163 164 See also: UDF 2.50 2.1.5.3 165 */ 166 struct udf_id_suffix { 167 public: 168 udf_id_suffix(uint16 udfRevision, uint8 os_class, uint8 os_identifier); 169 170 //! Note that revision 2.50 is denoted by 0x0250. udf_revisionudf_id_suffix171 uint16 udf_revision() const { return _udf_revision; } os_classudf_id_suffix172 uint8 os_class() const { return _os_class; } os_identifierudf_id_suffix173 uint8 os_identifier() const { return _os_identifier; } 174 set_os_classudf_id_suffix175 void set_os_class(uint8 os_class) { _os_class = os_class; } set_os_identifierudf_id_suffix176 void set_os_identifier(uint8 identifier) { _os_identifier = identifier; } 177 private: 178 uint16 _udf_revision; 179 uint8 _os_class; 180 uint8 _os_identifier; 181 array<uint8, 4> _reserved; 182 }; 183 184 /*! \brief Implementation ID Identify Suffix 185 186 See also: UDF 2.50 2.1.5.3 187 */ 188 struct implementation_id_suffix { 189 public: 190 implementation_id_suffix(uint8 os_class, uint8 os_identifier); 191 os_classimplementation_id_suffix192 uint8 os_class() const { return _os_class; } os_identifierimplementation_id_suffix193 uint8 os_identifier() const { return _os_identifier; } 194 set_os_classimplementation_id_suffix195 void set_os_class(uint8 os_class) { _os_class = os_class; } set_os_identifierimplementation_id_suffix196 void set_os_identifier(uint8 identifier) { _os_identifier = identifier; } 197 private: 198 uint8 _os_class; 199 uint8 _os_identifier; 200 array<uint8, 6> _implementation_use; 201 }; 202 203 /*! \brief Operating system classes for implementation_id_suffixes 204 205 See also: Udf 2.50 6.3 206 */ 207 enum { 208 OS_UNDEFINED = 0, 209 OS_DOS, 210 OS_OS2, 211 OS_MACOS, 212 OS_UNIX, 213 OS_WIN9X, 214 OS_WINNT, 215 OS_OS400, 216 OS_BEOS, 217 OS_WINCE 218 }; 219 220 /*! \brief BeOS operating system classes identifiers for implementation_id_suffixes 221 222 See also: Udf 2.50 6.3 223 */ 224 enum { 225 BEOS_GENERIC = 0, 226 BEOS_OPENBEOS = 1 // not part of the standard, but perhaps someday. :-) 227 }; 228 229 /*! \brief Domain ID Identify Suffix 230 231 See also: UDF 2.50 2.1.5.3 232 */ 233 struct domain_id_suffix { 234 public: 235 domain_id_suffix(uint16 udfRevision, uint8 domainFlags); 236 237 //! Note that revision 2.50 is denoted by 0x0250. udf_revisiondomain_id_suffix238 uint16 udf_revision() const { return _udf_revision; } domain_flagsdomain_id_suffix239 uint8 domain_flags() const { return _domain_flags; } 240 set_udf_revisiondomain_id_suffix241 void set_udf_revision(uint16 revision) { _udf_revision = B_HOST_TO_LENDIAN_INT16(revision); } set_domain_flagsdomain_id_suffix242 void set_domain_flags(uint8 flags) { _domain_flags = flags; } 243 private: 244 uint16 _udf_revision; 245 uint8 _domain_flags; 246 array<uint8, 5> _reserved; 247 }; 248 249 /*! \brief Domain flags 250 251 See also: UDF 2.50 2.1.5.3 252 */ 253 enum { 254 DF_HARD_WRITE_PROTECT = 0x01, 255 DF_SOFT_WRITE_PROTECT = 0x02 256 }; 257 258 /*! \brief Identifier used to designate the implementation responsible 259 for writing associated data structures on the medium. 260 261 See also: ECMA 167 1/7.4, UDF 2.01 2.1.5 262 */ 263 struct entity_id { 264 public: 265 static const int kIdentifierLength = 23; 266 static const int kIdentifierSuffixLength = 8; 267 268 entity_id(uint8 flags = 0, const char *identifier = NULL, 269 uint8 *identifier_suffix = NULL); 270 entity_id(uint8 flags, const char *identifier, 271 const udf_id_suffix &suffix); 272 entity_id(uint8 flags, const char *identifier, 273 const implementation_id_suffix &suffix); 274 entity_id(uint8 flags, const char *identifier, 275 const domain_id_suffix &suffix); 276 277 void dump() const; 278 bool matches(const entity_id &id) const; 279 280 // Get functions flagsentity_id281 uint8 flags() const { return _flags; } identifierentity_id282 const char* identifier() const { return _identifier; } identifierentity_id283 char* identifier() { return _identifier; } identifier_suffixentity_id284 const array<uint8, kIdentifierSuffixLength>& identifier_suffix() const { return _identifier_suffix; } identifier_suffixentity_id285 array<uint8, kIdentifierSuffixLength>& identifier_suffix() { return _identifier_suffix; } 286 287 // Set functions set_flagsentity_id288 void set_flags(uint8 flags) { _flags = flags; } 289 private: 290 uint8 _flags; 291 char _identifier[kIdentifierLength]; 292 array<uint8, kIdentifierSuffixLength> _identifier_suffix; 293 } __attribute__((packed)); 294 295 extern entity_id kMetadataPartitionMapId; 296 extern entity_id kSparablePartitionMapId; 297 extern entity_id kVirtualPartitionMapId; 298 extern entity_id kImplementationId; 299 extern entity_id kPartitionContentsId1xx; 300 extern entity_id kPartitionContentsId2xx; 301 extern entity_id kUdfId; 302 extern entity_id kLogicalVolumeInfoId150; 303 extern entity_id kLogicalVolumeInfoId201; 304 extern entity_id kDomainId150; 305 extern entity_id kDomainId201; 306 extern void init_entities(void); 307 308 //---------------------------------------------------------------------- 309 // ECMA-167 Part 2 310 //---------------------------------------------------------------------- 311 312 313 /*! \brief Header for volume structure descriptors 314 315 Each descriptor consumes an entire block. All unused trailing 316 bytes in the descriptor should be set to 0. 317 318 The following descriptors contain no more information than 319 that contained in the header: 320 321 - BEA01: 322 - type: 0 323 - id: "BEA01" 324 - version: 1 325 326 - TEA01: 327 - type: 0 328 - id: "TEA01" 329 - version: 1 330 331 - NSR03: 332 - type: 0 333 - id: "NSR03" 334 - version: 1 335 336 See also: ECMA 167 2/9.1 337 */ 338 struct volume_structure_descriptor_header { 339 public: 340 volume_structure_descriptor_header(uint8 type, const char *id, uint8 version); 341 342 uint8 type; 343 char id[5]; 344 uint8 version; 345 346 bool id_matches(const char *id); 347 } __attribute__((packed)); 348 349 // Volume structure descriptor ids 350 extern const char* kVSDID_BEA; 351 extern const char* kVSDID_TEA; 352 extern const char* kVSDID_BOOT; 353 extern const char* kVSDID_ISO; 354 extern const char* kVSDID_ECMA167_2; 355 extern const char* kVSDID_ECMA167_3; 356 extern const char* kVSDID_ECMA168; 357 358 //---------------------------------------------------------------------- 359 // ECMA-167 Part 3 360 //---------------------------------------------------------------------- 361 362 363 /*! \brief Location and length of a contiguous chunk of data on the volume. 364 365 \c _location is an absolute block address. 366 367 See also: ECMA 167 3/7.1 368 */ 369 struct extent_address { 370 public: 371 extent_address(uint32 location = 0, uint32 length = 0); 372 373 void dump() const; 374 lengthextent_address375 uint32 length() const { return B_LENDIAN_TO_HOST_INT32(_length); } locationextent_address376 uint32 location() const { return B_LENDIAN_TO_HOST_INT32(_location); } 377 set_lengthextent_address378 void set_length(int32 length) { _length = B_HOST_TO_LENDIAN_INT32(length); } set_locationextent_address379 void set_location(int32 location) { _location = B_HOST_TO_LENDIAN_INT32(location); } 380 private: 381 uint32 _length; 382 uint32 _location; 383 } __attribute__((packed)); 384 385 386 /*! \brief Location of a logical block within a logical volume. 387 388 See also: ECMA 167 4/7.1 389 */ 390 struct logical_block_address { 391 public: 392 void dump() const; 393 logical_block_address(uint16 partition = 0, uint32 block = 0); 394 blocklogical_block_address395 uint32 block() const { return B_LENDIAN_TO_HOST_INT32(_block); } partitionlogical_block_address396 uint16 partition() const { return B_LENDIAN_TO_HOST_INT16(_partition); } 397 set_blocklogical_block_address398 void set_block(uint32 block) { _block = B_HOST_TO_LENDIAN_INT32(block); } set_partitionlogical_block_address399 void set_partition(uint16 partition) { _partition = B_HOST_TO_LENDIAN_INT16(partition); } 400 401 private: 402 uint32 _block; //!< Block location relative to start of corresponding partition 403 uint16 _partition; //!< Numeric partition id within logical volume 404 } __attribute__((packed)); 405 406 /*! \brief Extent types used in short_address, long_address, 407 and extended_address. 408 409 See also: ECMA-167 4/14.14.1.1 410 */ 411 enum extent_type { 412 EXTENT_TYPE_RECORDED = 0, //!< Allocated and recorded 413 EXTENT_TYPE_ALLOCATED, //!< Allocated but unrecorded 414 EXTENT_TYPE_UNALLOCATED, //!< Unallocated and unrecorded 415 EXTENT_TYPE_CONTINUATION, //!< Specifies next extent of descriptors 416 }; 417 418 419 /*! \brief Allocation descriptor. 420 421 See also: ECMA 167 4/14.14.1 422 */ 423 struct short_address { 424 private: 425 union type_and_length_accessor { 426 uint32 type_and_length; 427 struct { 428 uint32 length:30, 429 type:2; 430 // uint32 type:2, 431 // length:30; 432 } bits; 433 }; 434 435 public: 436 void dump() const; 437 typeshort_address438 uint8 type() const { 439 type_and_length_accessor t; 440 t.type_and_length = type_and_length(); 441 return t.bits.type; 442 } lengthshort_address443 uint32 length() const { 444 type_and_length_accessor t; 445 t.type_and_length = type_and_length(); 446 return t.bits.length; 447 } blockshort_address448 uint32 block() const { return B_LENDIAN_TO_HOST_INT32(_block); } 449 set_typeshort_address450 void set_type(uint8 type) { 451 type_and_length_accessor t; 452 t.type_and_length = type_and_length(); 453 t.bits.type = type; 454 set_type_and_length(t.type_and_length); 455 } set_lengthshort_address456 void set_length(uint32 length) { 457 type_and_length_accessor t; 458 t.type_and_length = type_and_length(); 459 t.bits.length = length; 460 set_type_and_length(t.type_and_length); 461 } set_blockshort_address462 void set_block(uint32 block) { _block = B_HOST_TO_LENDIAN_INT32(block); } 463 private: type_and_lengthshort_address464 uint32 type_and_length() const { return B_LENDIAN_TO_HOST_INT32(_type_and_length); } set_type_and_lengthshort_address465 void set_type_and_length(uint32 value) { _type_and_length = B_HOST_TO_LENDIAN_INT32(value); } 466 467 uint32 _type_and_length; 468 uint32 _block; 469 } __attribute__((packed)); 470 471 472 /*! \brief Allocation descriptor w/ 6 byte implementation use field. 473 474 See also: ECMA 167 4/14.14.2 475 */ 476 struct long_address { 477 private: 478 union type_and_length_accessor { 479 uint32 type_and_length; 480 struct { 481 uint32 length:30, 482 type:2; 483 } bits; 484 }; 485 486 public: 487 long_address(uint16 partition = 0, uint32 block = 0, uint32 length = 0, 488 uint8 type = 0); 489 490 void dump() const; 491 typelong_address492 uint8 type() const { 493 type_and_length_accessor t; 494 t.type_and_length = type_and_length(); 495 return t.bits.type; 496 } lengthlong_address497 uint32 length() const { 498 type_and_length_accessor t; 499 t.type_and_length = type_and_length(); 500 return t.bits.length; 501 } 502 blocklong_address503 uint32 block() const { return _location.block(); } partitionlong_address504 uint16 partition() const { return _location.partition(); } 505 implementation_uselong_address506 const array<uint8, 6>& implementation_use() const { return _implementation_use; } implementation_uselong_address507 array<uint8, 6>& implementation_use() { return _implementation_use; } 508 flagslong_address509 uint16 flags() const { return B_LENDIAN_TO_HOST_INT16(_accessor().flags); } unique_idlong_address510 uint32 unique_id() const { return B_LENDIAN_TO_HOST_INT32(_accessor().unique_id); } 511 set_typelong_address512 void set_type(uint8 type) { 513 type_and_length_accessor t; 514 t.type_and_length = type_and_length(); 515 t.bits.type = type; 516 set_type_and_length(t.type_and_length); 517 } set_lengthlong_address518 void set_length(uint32 length) { 519 type_and_length_accessor t; 520 t.type_and_length = type_and_length(); 521 t.bits.length = length; 522 set_type_and_length(t.type_and_length); 523 } set_blocklong_address524 void set_block(uint32 block) { _location.set_block(block); } set_partitionlong_address525 void set_partition(uint16 partition) { _location.set_partition(partition); } 526 set_flagslong_address527 void set_flags(uint16 flags) { _accessor().flags = B_HOST_TO_LENDIAN_INT16(flags); } set_unique_idlong_address528 void set_unique_id(uint32 id) { _accessor().unique_id = B_HOST_TO_LENDIAN_INT32(id); } 529 530 void set_to(uint32 block, uint16 partition, uint32 length = 1, 531 uint8 type = EXTENT_TYPE_RECORDED, uint16 flags = 0, uint32 unique_id = 0) 532 { 533 set_block(block); 534 set_partition(partition); 535 set_length(length); 536 set_type(type); 537 set_flags(flags); 538 set_unique_id(unique_id); 539 } 540 541 private: 542 //! See UDF-2.50 2.3.4.3 543 struct _implementation_use_accessor { 544 uint16 flags; 545 uint32 unique_id; 546 } __attribute__((packed)); 547 _accessorlong_address548 _implementation_use_accessor& _accessor() { return 549 *reinterpret_cast<_implementation_use_accessor*>(implementation_use().data); } _accessorlong_address550 const _implementation_use_accessor& _accessor() const { return 551 *reinterpret_cast<const _implementation_use_accessor*>(implementation_use().data); } 552 type_and_lengthlong_address553 uint32 type_and_length() const { return B_LENDIAN_TO_HOST_INT32(_type_and_length); } set_type_and_lengthlong_address554 void set_type_and_length(uint32 value) { _type_and_length = B_HOST_TO_LENDIAN_INT32(value); } 555 556 uint32 _type_and_length; 557 logical_block_address _location; 558 array<uint8, 6> _implementation_use; 559 } __attribute__((packed)); 560 561 /*! \brief Common tag found at the beginning of most udf descriptor structures. 562 563 For error checking, \c descriptor_tag structures have: 564 - The disk location of the tag redundantly stored in the tag itself 565 - A checksum value for the tag 566 - A CRC value and length 567 568 See also: ECMA 167 1/7.2, UDF 2.01 2.2.1, UDF 2.01 2.3.1 569 */ 570 struct descriptor_tag { 571 public: 572 void dump() const; 573 574 status_t init_check(uint32 block, bool calculateCrc = true); 575 iddescriptor_tag576 uint16 id() const { return B_LENDIAN_TO_HOST_INT16(_id); } versiondescriptor_tag577 uint16 version() const { return B_LENDIAN_TO_HOST_INT16(_version); } checksumdescriptor_tag578 uint8 checksum() const { return _checksum; } serial_numberdescriptor_tag579 uint16 serial_number() const { return B_LENDIAN_TO_HOST_INT16(_serial_number); } crcdescriptor_tag580 uint16 crc() const { return B_LENDIAN_TO_HOST_INT16(_crc); } crc_lengthdescriptor_tag581 uint16 crc_length() const { return B_LENDIAN_TO_HOST_INT16(_crc_length); } locationdescriptor_tag582 uint32 location() const { return B_LENDIAN_TO_HOST_INT32(_location); } 583 set_iddescriptor_tag584 void set_id(uint16 id) { _id = B_HOST_TO_LENDIAN_INT16(id); } set_versiondescriptor_tag585 void set_version(uint16 version) { _version = B_HOST_TO_LENDIAN_INT16(version); } set_checksumdescriptor_tag586 void set_checksum(uint8 checksum) { _checksum = checksum; } set_serial_numberdescriptor_tag587 void set_serial_number(uint16 serial_number) { _serial_number = B_HOST_TO_LENDIAN_INT16(serial_number); } set_crcdescriptor_tag588 void set_crc(uint16 crc) { _crc = B_HOST_TO_LENDIAN_INT16(crc); } set_crc_lengthdescriptor_tag589 void set_crc_length(uint16 crc_length) { _crc_length = B_HOST_TO_LENDIAN_INT16(crc_length); } set_locationdescriptor_tag590 void set_location(uint32 location) { _location = B_HOST_TO_LENDIAN_INT32(location); } 591 592 /*! \brief Calculates and sets the crc length, crc checksumm, and 593 checksum for the tag. 594 595 This function should not be called until all member variables in 596 the descriptor_tag's enclosing descriptor and all member variables 597 in the descriptor_tag itself other than crc_length, crc, and checksum 598 have been set (since the checksum is based off of values in the 599 descriptor_tag, and the crc is based off the values in and the 600 size of the enclosing descriptor). 601 602 \param The tag's enclosing descriptor. 603 \param The size of the tag's enclosing descriptor (including the 604 tag); only necessary if different from sizeof(Descriptor). 605 */ 606 template <class Descriptor> 607 void 608 set_checksums(Descriptor &descriptor, uint16 size = sizeof(Descriptor)) 609 { 610 611 // check that this tag is actually owned by 612 // the given descriptor 613 if (this == &descriptor.tag()) 614 { 615 // crc_length, based off provided descriptor 616 set_crc_length(size - sizeof(descriptor_tag)); 617 // crc 618 uint16 crc = calculate_crc(reinterpret_cast<uint8*>(this) 619 + sizeof(descriptor_tag), crc_length()); 620 set_crc(crc); 621 // checksum (which depends on the other two values) 622 uint32 sum = 0; 623 for (int i = 0; i <= 3; i++) 624 sum += reinterpret_cast<uint8*>(this)[i]; 625 for (int i = 5; i <= 15; i++) 626 sum += reinterpret_cast<uint8*>(this)[i]; 627 set_checksum(sum % 256); 628 } 629 } 630 private: 631 uint16 _id; 632 uint16 _version; 633 uint8 _checksum; //!< Sum modulo 256 of bytes 0-3 and 5-15 of this struct. 634 uint8 _reserved; //!< Set to #00. 635 uint16 _serial_number; 636 uint16 _crc; //!< May be 0 if \c crc_length field is 0. 637 /*! \brief Length of the data chunk used to calculate CRC. 638 639 If 0, no CRC was calculated, and the \c crc field must be 0. 640 641 According to UDF-2.01 2.3.1.2, the CRC shall be calculated for all descriptors 642 unless otherwise noted, and this field shall be set to: 643 644 <code>(descriptor length) - (descriptor tag length)</code> 645 */ 646 uint16 _crc_length; 647 /*! \brief Address of this tag within its partition (for error checking). 648 649 For virtually addressed structures (i.e. those accessed thru a VAT), this 650 shall be the virtual address, not the physical or logical address. 651 */ 652 uint32 _location; 653 654 } __attribute__((packed)); 655 656 657 /*! \c descriptor_tag ::id values 658 */ 659 enum tag_id { 660 TAGID_UNDEFINED = 0, 661 662 // ECMA 167, PART 3 663 TAGID_PRIMARY_VOLUME_DESCRIPTOR, 664 TAGID_ANCHOR_VOLUME_DESCRIPTOR_POINTER, 665 TAGID_VOLUME_DESCRIPTOR_POINTER, 666 TAGID_IMPLEMENTATION_USE_VOLUME_DESCRIPTOR, 667 TAGID_PARTITION_DESCRIPTOR, 668 TAGID_LOGICAL_VOLUME_DESCRIPTOR, 669 TAGID_UNALLOCATED_SPACE_DESCRIPTOR, 670 TAGID_TERMINATING_DESCRIPTOR, 671 TAGID_LOGICAL_VOLUME_INTEGRITY_DESCRIPTOR, 672 673 TAGID_CUSTOM_START = 65280, 674 TAGID_CUSTOM_END = 65535, 675 676 // ECMA 167, PART 4 677 TAGID_FILE_SET_DESCRIPTOR = 256, 678 TAGID_FILE_ID_DESCRIPTOR, 679 TAGID_ALLOCATION_EXTENT_DESCRIPTOR, 680 TAGID_INDIRECT_ENTRY, 681 TAGID_TERMINAL_ENTRY, 682 TAGID_FILE_ENTRY, 683 TAGID_EXTENDED_ATTRIBUTE_HEADER_DESCRIPTOR, 684 TAGID_UNALLOCATED_SPACE_ENTRY, 685 TAGID_SPACE_BITMAP_DESCRIPTOR, 686 TAGID_PARTITION_INTEGRITY_ENTRY, 687 TAGID_EXTENDED_FILE_ENTRY, 688 }; 689 690 const char *tag_id_to_string(tag_id id); 691 692 extern const uint16 kCrcTable[256]; 693 694 /*! \brief Primary volume descriptor 695 */ 696 struct primary_volume_descriptor { 697 public: 698 void dump() const; 699 700 // Get functions tagprimary_volume_descriptor701 const descriptor_tag & tag() const { return _tag; } tagprimary_volume_descriptor702 descriptor_tag & tag() { return _tag; } 703 vds_numberprimary_volume_descriptor704 uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); } primary_volume_descriptor_numberprimary_volume_descriptor705 uint32 primary_volume_descriptor_number() const { return B_LENDIAN_TO_HOST_INT32(_primary_volume_descriptor_number); } 706 volume_identifierprimary_volume_descriptor707 const array<char, 32>& volume_identifier() const { return _volume_identifier; } volume_identifierprimary_volume_descriptor708 array<char, 32>& volume_identifier() { return _volume_identifier; } 709 volume_sequence_numberprimary_volume_descriptor710 uint16 volume_sequence_number() const { return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); } max_volume_sequence_numberprimary_volume_descriptor711 uint16 max_volume_sequence_number() const { return B_LENDIAN_TO_HOST_INT16(_max_volume_sequence_number); } interchange_levelprimary_volume_descriptor712 uint16 interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_interchange_level); } max_interchange_levelprimary_volume_descriptor713 uint16 max_interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_max_interchange_level); } character_set_listprimary_volume_descriptor714 uint32 character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_character_set_list); } max_character_set_listprimary_volume_descriptor715 uint32 max_character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_max_character_set_list); } 716 volume_set_identifierprimary_volume_descriptor717 const array<char, 128>& volume_set_identifier() const { return _volume_set_identifier; } volume_set_identifierprimary_volume_descriptor718 array<char, 128>& volume_set_identifier() { return _volume_set_identifier; } 719 descriptor_character_setprimary_volume_descriptor720 const charspec& descriptor_character_set() const { return _descriptor_character_set; } descriptor_character_setprimary_volume_descriptor721 charspec& descriptor_character_set() { return _descriptor_character_set; } 722 explanatory_character_setprimary_volume_descriptor723 const charspec& explanatory_character_set() const { return _explanatory_character_set; } explanatory_character_setprimary_volume_descriptor724 charspec& explanatory_character_set() { return _explanatory_character_set; } 725 volume_abstractprimary_volume_descriptor726 const extent_address& volume_abstract() const { return _volume_abstract; } volume_abstractprimary_volume_descriptor727 extent_address& volume_abstract() { return _volume_abstract; } volume_copyright_noticeprimary_volume_descriptor728 const extent_address& volume_copyright_notice() const { return _volume_copyright_notice; } volume_copyright_noticeprimary_volume_descriptor729 extent_address& volume_copyright_notice() { return _volume_copyright_notice; } 730 application_idprimary_volume_descriptor731 const entity_id& application_id() const { return _application_id; } application_idprimary_volume_descriptor732 entity_id& application_id() { return _application_id; } 733 recording_date_and_timeprimary_volume_descriptor734 const timestamp& recording_date_and_time() const { return _recording_date_and_time; } recording_date_and_timeprimary_volume_descriptor735 timestamp& recording_date_and_time() { return _recording_date_and_time; } 736 implementation_idprimary_volume_descriptor737 const entity_id& implementation_id() const { return _implementation_id; } implementation_idprimary_volume_descriptor738 entity_id& implementation_id() { return _implementation_id; } 739 implementation_useprimary_volume_descriptor740 const array<uint8, 64>& implementation_use() const { return _implementation_use; } implementation_useprimary_volume_descriptor741 array<uint8, 64>& implementation_use() { return _implementation_use; } 742 predecessor_volume_descriptor_sequence_locationprimary_volume_descriptor743 uint32 predecessor_volume_descriptor_sequence_location() const 744 { return B_LENDIAN_TO_HOST_INT32(_predecessor_volume_descriptor_sequence_location); } flagsprimary_volume_descriptor745 uint16 flags() const { return B_LENDIAN_TO_HOST_INT16(_flags); } 746 reservedprimary_volume_descriptor747 const array<uint8, 22>& reserved() const { return _reserved; } reservedprimary_volume_descriptor748 array<uint8, 22>& reserved() { return _reserved; } 749 750 // Set functions set_vds_numberprimary_volume_descriptor751 void set_vds_number(uint32 number) 752 { _vds_number = B_HOST_TO_LENDIAN_INT32(number); } set_primary_volume_descriptor_numberprimary_volume_descriptor753 void set_primary_volume_descriptor_number(uint32 number) 754 { _primary_volume_descriptor_number = B_HOST_TO_LENDIAN_INT32(number); } set_volume_sequence_numberprimary_volume_descriptor755 void set_volume_sequence_number(uint16 number) 756 { _volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); } set_max_volume_sequence_numberprimary_volume_descriptor757 void set_max_volume_sequence_number(uint16 number) 758 { _max_volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); } set_interchange_levelprimary_volume_descriptor759 void set_interchange_level(uint16 level) 760 { _interchange_level = B_HOST_TO_LENDIAN_INT16(level); } set_max_interchange_levelprimary_volume_descriptor761 void set_max_interchange_level(uint16 level) 762 { _max_interchange_level = B_HOST_TO_LENDIAN_INT16(level); } set_character_set_listprimary_volume_descriptor763 void set_character_set_list(uint32 list) 764 { _character_set_list = B_HOST_TO_LENDIAN_INT32(list); } set_max_character_set_listprimary_volume_descriptor765 void set_max_character_set_list(uint32 list) 766 { _max_character_set_list = B_HOST_TO_LENDIAN_INT32(list); } set_predecessor_volume_descriptor_sequence_locationprimary_volume_descriptor767 void set_predecessor_volume_descriptor_sequence_location(uint32 location) 768 { _predecessor_volume_descriptor_sequence_location = B_HOST_TO_LENDIAN_INT32(location); } set_flagsprimary_volume_descriptor769 void set_flags(uint16 flags) 770 { _flags = B_HOST_TO_LENDIAN_INT16(flags); } 771 772 private: 773 descriptor_tag _tag; 774 uint32 _vds_number; 775 uint32 _primary_volume_descriptor_number; 776 array<char, 32> _volume_identifier; 777 uint16 _volume_sequence_number; 778 uint16 _max_volume_sequence_number; 779 uint16 _interchange_level; //!< to be set to 3 if part of multivolume set, 2 otherwise 780 uint16 _max_interchange_level; //!< to be set to 3 unless otherwise directed by user 781 uint32 _character_set_list; 782 uint32 _max_character_set_list; 783 array<char, 128> _volume_set_identifier; 784 785 /*! \brief Identifies the character set for the \c volume_identifier 786 and \c volume_set_identifier fields. 787 788 To be set to CS0. 789 */ 790 charspec _descriptor_character_set; 791 792 /*! \brief Identifies the character set used in the \c volume_abstract 793 and \c volume_copyright_notice extents. 794 795 To be set to CS0. 796 */ 797 charspec _explanatory_character_set; 798 799 extent_address _volume_abstract; 800 extent_address _volume_copyright_notice; 801 802 entity_id _application_id; 803 timestamp _recording_date_and_time; 804 entity_id _implementation_id; 805 array<uint8, 64> _implementation_use; 806 uint32 _predecessor_volume_descriptor_sequence_location; 807 uint16 _flags; 808 array<uint8, 22> _reserved; 809 810 } __attribute__((packed)); 811 812 813 /*! \brief Anchor Volume Descriptor Pointer 814 815 vd recorded at preset locations in the partition, used as a reference 816 point to the main vd sequences 817 818 According to UDF 2.01, an avdp shall be recorded in at least 2 of 819 the 3 following locations, where N is the last recordable sector 820 of the partition: 821 - 256 822 - (N - 256) 823 - N 824 825 See also: ECMA 167 3/10.2, UDF-2.01 2.2.3 826 */ 827 struct anchor_volume_descriptor { 828 public: anchor_volume_descriptoranchor_volume_descriptor829 anchor_volume_descriptor() { memset(_reserved.data, 0, _reserved.size()); } 830 void dump() const; 831 taganchor_volume_descriptor832 descriptor_tag & tag() { return _tag; } taganchor_volume_descriptor833 const descriptor_tag & tag() const { return _tag; } 834 main_vdsanchor_volume_descriptor835 extent_address& main_vds() { return _main_vds; } main_vdsanchor_volume_descriptor836 const extent_address& main_vds() const { return _main_vds; } 837 reserve_vdsanchor_volume_descriptor838 extent_address& reserve_vds() { return _reserve_vds; } reserve_vdsanchor_volume_descriptor839 const extent_address& reserve_vds() const { return _reserve_vds; } 840 private: 841 descriptor_tag _tag; 842 extent_address _main_vds; //!< min length of 16 sectors 843 extent_address _reserve_vds; //!< min length of 16 sectors 844 array<uint8, 480> _reserved; 845 } __attribute__((packed)); 846 847 848 /*! \brief Volume Descriptor Pointer 849 850 Used to chain extents of volume descriptor sequences together. 851 852 See also: ECMA 167 3/10.3 853 */ 854 struct descriptor_pointer { 855 descriptor_tag tag; 856 uint32 vds_number; 857 extent_address next; 858 } __attribute__((packed)); 859 860 861 /*! \brief UDF Implementation Use Volume Descriptor struct found in 862 implementation_use() field of implementation_use_descriptor when 863 said descriptor's implementation_id() field specifies "*UDF LV Info" 864 865 See also: UDF 2.50 2.2.7 866 */ 867 struct logical_volume_info { 868 public: 869 void dump() const; 870 character_setlogical_volume_info871 charspec& character_set() { return _character_set; } character_setlogical_volume_info872 const charspec& character_set() const { return _character_set; } 873 logical_volume_idlogical_volume_info874 array<char, 128>& logical_volume_id() { return _logical_volume_id; } logical_volume_idlogical_volume_info875 const array<char, 128>& logical_volume_id() const { return _logical_volume_id; } 876 logical_volume_info_1logical_volume_info877 array<char, 36>& logical_volume_info_1() { return _logical_volume_info.data[0]; } logical_volume_info_1logical_volume_info878 const array<char, 36>& logical_volume_info_1() const { return _logical_volume_info.data[0]; } 879 logical_volume_info_2logical_volume_info880 array<char, 36>& logical_volume_info_2() { return _logical_volume_info.data[1]; } logical_volume_info_2logical_volume_info881 const array<char, 36>& logical_volume_info_2() const { return _logical_volume_info.data[1]; } 882 logical_volume_info_3logical_volume_info883 array<char, 36>& logical_volume_info_3() { return _logical_volume_info.data[2]; } logical_volume_info_3logical_volume_info884 const array<char, 36>& logical_volume_info_3() const { return _logical_volume_info.data[2]; } 885 implementation_idlogical_volume_info886 entity_id& implementation_id() { return _implementation_id; } implementation_idlogical_volume_info887 const entity_id& implementation_id() const { return _implementation_id; } 888 implementation_uselogical_volume_info889 array<uint8, 128>& implementation_use() { return _implementation_use; } implementation_uselogical_volume_info890 const array<uint8, 128>& implementation_use() const { return _implementation_use; } 891 private: 892 charspec _character_set; 893 array<char, 128> _logical_volume_id; // d-string 894 array<array<char, 36>, 3> _logical_volume_info; // d-strings 895 entity_id _implementation_id; 896 array<uint8, 128> _implementation_use; 897 } __attribute__((packed)); 898 899 /*! \brief Implementation Use Volume Descriptor 900 901 See also: ECMA 167 3/10.4 902 */ 903 struct implementation_use_descriptor { 904 public: 905 void dump() const; 906 907 // Get functions tagimplementation_use_descriptor908 const descriptor_tag & tag() const { return _tag; } tagimplementation_use_descriptor909 descriptor_tag & tag() { return _tag; } 910 vds_numberimplementation_use_descriptor911 uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); } 912 implementation_idimplementation_use_descriptor913 const entity_id& implementation_id() const { return _implementation_id; } implementation_idimplementation_use_descriptor914 entity_id& implementation_id() { return _implementation_id; } 915 implementation_useimplementation_use_descriptor916 const array<uint8, 460>& implementation_use() const { return _implementation_use; } implementation_useimplementation_use_descriptor917 array<uint8, 460>& implementation_use() { return _implementation_use; } 918 919 // Only valid if implementation_id() returns Udf::kLogicalVolumeInfoId. infoimplementation_use_descriptor920 logical_volume_info& info() { return *reinterpret_cast<logical_volume_info*>(_implementation_use.data); } infoimplementation_use_descriptor921 const logical_volume_info& info() const { return *reinterpret_cast<const logical_volume_info*>(_implementation_use.data); } 922 923 // Set functions set_vds_numberimplementation_use_descriptor924 void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); } 925 private: 926 descriptor_tag _tag; 927 uint32 _vds_number; 928 entity_id _implementation_id; 929 array<uint8, 460> _implementation_use; 930 } __attribute__((packed)); 931 932 933 /*! \brief Maximum number of partition descriptors to be found in volume 934 descriptor sequence, per UDF-2.50 935 */ 936 const uint8 kMaxPartitionDescriptors = 2; 937 #define UDF_MAX_PARTITION_MAPS 2 938 #define UDF_MAX_PARTITION_MAP_SIZE 64 939 940 /*! \brief Partition Descriptor 941 942 See also: ECMA 167 3/10.5 943 */ 944 struct partition_descriptor { 945 private: 946 union partition_flags_accessor { 947 uint16 partition_flags; 948 struct { 949 uint16 allocated:1, 950 reserved:15; 951 } bits; 952 }; 953 954 public: 955 void dump() const; 956 957 // Get functions tagpartition_descriptor958 const descriptor_tag & tag() const { return _tag; } tagpartition_descriptor959 descriptor_tag & tag() { return _tag; } 960 vds_numberpartition_descriptor961 uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); } partition_flagspartition_descriptor962 uint16 partition_flags() const { return B_LENDIAN_TO_HOST_INT16(_partition_flags); } allocatedpartition_descriptor963 bool allocated() const { 964 partition_flags_accessor f; 965 f.partition_flags = partition_flags(); 966 return f.bits.allocated; 967 } partition_numberpartition_descriptor968 uint16 partition_number() const { return B_LENDIAN_TO_HOST_INT16(_partition_number); } 969 partition_contentspartition_descriptor970 const entity_id& partition_contents() const { return _partition_contents; } partition_contentspartition_descriptor971 entity_id& partition_contents() { return _partition_contents; } 972 partition_contents_usepartition_descriptor973 const array<uint8, 128>& partition_contents_use() const { return _partition_contents_use; } partition_contents_usepartition_descriptor974 array<uint8, 128>& partition_contents_use() { return _partition_contents_use; } 975 access_typepartition_descriptor976 uint32 access_type() const { return B_LENDIAN_TO_HOST_INT32(_access_type); } startpartition_descriptor977 uint32 start() const { return B_LENDIAN_TO_HOST_INT32(_start); } lengthpartition_descriptor978 uint32 length() const { return B_LENDIAN_TO_HOST_INT32(_length); } 979 implementation_idpartition_descriptor980 const entity_id& implementation_id() const { return _implementation_id; } implementation_idpartition_descriptor981 entity_id& implementation_id() { return _implementation_id; } 982 implementation_usepartition_descriptor983 const array<uint8, 128>& implementation_use() const { return _implementation_use; } implementation_usepartition_descriptor984 array<uint8, 128>& implementation_use() { return _implementation_use; } 985 reservedpartition_descriptor986 const array<uint8, 156>& reserved() const { return _reserved; } reservedpartition_descriptor987 array<uint8, 156>& reserved() { return _reserved; } 988 989 // Set functions set_vds_numberpartition_descriptor990 void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); } set_partition_flagspartition_descriptor991 void set_partition_flags(uint16 flags) { _partition_flags = B_HOST_TO_LENDIAN_INT16(flags); } set_allocatedpartition_descriptor992 void set_allocated(bool allocated) { 993 partition_flags_accessor f; 994 f.partition_flags = partition_flags(); 995 f.bits.allocated = allocated; 996 set_partition_flags(f.partition_flags); 997 } set_partition_numberpartition_descriptor998 void set_partition_number(uint16 number) { _partition_number = B_HOST_TO_LENDIAN_INT16(number); } set_access_typepartition_descriptor999 void set_access_type(uint32 type) { _access_type = B_HOST_TO_LENDIAN_INT32(type); } set_startpartition_descriptor1000 void set_start(uint32 start) { _start = B_HOST_TO_LENDIAN_INT32(start); } set_lengthpartition_descriptor1001 void set_length(uint32 length) { _length = B_HOST_TO_LENDIAN_INT32(length); } 1002 1003 private: 1004 descriptor_tag _tag; 1005 uint32 _vds_number; 1006 /*! Bit 0: If 0, shall mean volume space has not been allocated. If 1, 1007 shall mean volume space has been allocated. 1008 */ 1009 uint16 _partition_flags; 1010 uint16 _partition_number; 1011 1012 /*! - "+NSR03" Volume recorded according to ECMA-167, i.e. UDF 1013 - "+CD001" Volume recorded according to ECMA-119, i.e. iso9660 1014 - "+FDC01" Volume recorded according to ECMA-107 1015 - "+CDW02" Volume recorded according to ECMA-168 1016 */ 1017 entity_id _partition_contents; 1018 array<uint8, 128> _partition_contents_use; 1019 1020 /*! See \c partition_access_type enum 1021 */ 1022 uint32 _access_type; 1023 uint32 _start; 1024 uint32 _length; 1025 entity_id _implementation_id; 1026 array<uint8, 128> _implementation_use; 1027 array<uint8, 156> _reserved; 1028 } __attribute__((packed)); 1029 1030 1031 enum partition_access_type { 1032 ACCESS_UNSPECIFIED, 1033 ACCESS_READ_ONLY, 1034 ACCESS_WRITE_ONCE, 1035 ACCESS_REWRITABLE, 1036 ACCESS_OVERWRITABLE, 1037 }; 1038 1039 1040 /*! \brief Logical volume descriptor 1041 1042 See also: ECMA 167 3/10.6, UDF-2.01 2.2.4 1043 */ 1044 struct logical_volume_descriptor { 1045 void dump() const; 1046 1047 // Get functions taglogical_volume_descriptor1048 const descriptor_tag & tag() const { return _tag; } taglogical_volume_descriptor1049 descriptor_tag & tag() { return _tag; } 1050 vds_numberlogical_volume_descriptor1051 uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); } 1052 character_setlogical_volume_descriptor1053 const charspec& character_set() const { return _character_set; } character_setlogical_volume_descriptor1054 charspec& character_set() { return _character_set; } 1055 logical_volume_identifierlogical_volume_descriptor1056 const array<char, 128>& logical_volume_identifier() const { return _logical_volume_identifier; } logical_volume_identifierlogical_volume_descriptor1057 array<char, 128>& logical_volume_identifier() { return _logical_volume_identifier; } 1058 logical_block_sizelogical_volume_descriptor1059 uint32 logical_block_size() const { return B_LENDIAN_TO_HOST_INT32(_logical_block_size); } 1060 domain_idlogical_volume_descriptor1061 const entity_id& domain_id() const { return _domain_id; } domain_idlogical_volume_descriptor1062 entity_id& domain_id() { return _domain_id; } 1063 logical_volume_contents_uselogical_volume_descriptor1064 const array<uint8, 16>& logical_volume_contents_use() const { return _logical_volume_contents_use; } logical_volume_contents_uselogical_volume_descriptor1065 array<uint8, 16>& logical_volume_contents_use() { return _logical_volume_contents_use; } 1066 file_set_addresslogical_volume_descriptor1067 const long_address& file_set_address() const { return *reinterpret_cast<const long_address*>(&_logical_volume_contents_use); } file_set_addresslogical_volume_descriptor1068 long_address& file_set_address() { return *reinterpret_cast<long_address*>(&_logical_volume_contents_use); } 1069 map_table_lengthlogical_volume_descriptor1070 uint32 map_table_length() const { return B_LENDIAN_TO_HOST_INT32(_map_table_length); } partition_map_countlogical_volume_descriptor1071 uint32 partition_map_count() const { return B_LENDIAN_TO_HOST_INT32(_partition_map_count); } 1072 implementation_idlogical_volume_descriptor1073 const entity_id& implementation_id() const { return _implementation_id; } implementation_idlogical_volume_descriptor1074 entity_id& implementation_id() { return _implementation_id; } 1075 implementation_uselogical_volume_descriptor1076 const array<uint8, 128>& implementation_use() const { return _implementation_use; } implementation_uselogical_volume_descriptor1077 array<uint8, 128>& implementation_use() { return _implementation_use; } 1078 integrity_sequence_extentlogical_volume_descriptor1079 const extent_address& integrity_sequence_extent() const { return _integrity_sequence_extent; } integrity_sequence_extentlogical_volume_descriptor1080 extent_address& integrity_sequence_extent() { return _integrity_sequence_extent; } 1081 partition_mapslogical_volume_descriptor1082 const uint8* partition_maps() const { return _partition_maps; } partition_mapslogical_volume_descriptor1083 uint8* partition_maps() { return _partition_maps; } 1084 1085 // Set functions set_vds_numberlogical_volume_descriptor1086 void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); } set_logical_block_sizelogical_volume_descriptor1087 void set_logical_block_size(uint32 size) { _logical_block_size = B_HOST_TO_LENDIAN_INT32(size); } 1088 set_map_table_lengthlogical_volume_descriptor1089 void set_map_table_length(uint32 length) { _map_table_length = B_HOST_TO_LENDIAN_INT32(length); } set_partition_map_countlogical_volume_descriptor1090 void set_partition_map_count(uint32 count) { _partition_map_count = B_HOST_TO_LENDIAN_INT32(count); } 1091 1092 // Other functions 1093 logical_volume_descriptor& operator=(const logical_volume_descriptor &rhs); 1094 1095 private: 1096 descriptor_tag _tag; 1097 uint32 _vds_number; 1098 1099 /*! \brief Identifies the character set for the 1100 \c logical_volume_identifier field. 1101 1102 To be set to CS0. 1103 */ 1104 charspec _character_set; 1105 array<char, 128> _logical_volume_identifier; 1106 uint32 _logical_block_size; 1107 1108 /*! \brief To be set to 0 or "*OSTA UDF Compliant". See UDF specs. 1109 */ 1110 entity_id _domain_id; 1111 1112 /*! \brief For UDF, shall contain a \c long_address which identifies 1113 the location of the logical volume's first file set. 1114 */ 1115 array<uint8, 16> _logical_volume_contents_use; 1116 1117 uint32 _map_table_length; 1118 uint32 _partition_map_count; 1119 entity_id _implementation_id; 1120 array<uint8, 128> _implementation_use; 1121 1122 /*! \brief Logical volume integrity sequence location. 1123 1124 For re/overwritable media, shall be a min of 8KB in length. 1125 For WORM media, shall be quite frickin large, as a new volume 1126 must be added to the set if the extent fills up (since you 1127 can't chain lvis's I guess). 1128 */ 1129 extent_address _integrity_sequence_extent; 1130 1131 /*! \brief Restricted to maps of type 1 for normal maps and 1132 UDF type 2 for virtual maps or maps on systems not supporting 1133 defect management. 1134 1135 Note that we actually allocate memory for the partition maps 1136 here due to the fact that we allocate logical_volume_descriptor 1137 objects on the stack sometimes. 1138 1139 See UDF-2.01 2.2.8, 2.2.9 1140 */ 1141 uint8 _partition_maps[UDF_MAX_PARTITION_MAPS * UDF_MAX_PARTITION_MAP_SIZE]; 1142 } __attribute__((packed)); 1143 1144 //! Base size (excluding partition maps) of lvd 1145 extern const uint32 kLogicalVolumeDescriptorBaseSize; 1146 1147 /*! \brief (Mostly) common portion of various partition maps 1148 1149 See also: ECMA-167 3/10.7.1 1150 */ 1151 struct partition_map_header { 1152 public: typepartition_map_header1153 uint8 type() const { return _type; } lengthpartition_map_header1154 uint8 length() const { return _length; } map_datapartition_map_header1155 uint8 *map_data() { return _map_data; } map_datapartition_map_header1156 const uint8 *map_data() const { return _map_data; } 1157 partition_type_idpartition_map_header1158 entity_id& partition_type_id() 1159 { return *reinterpret_cast<entity_id*>(&_map_data[2]); } partition_type_idpartition_map_header1160 const entity_id& partition_type_id() const 1161 { return *reinterpret_cast<const entity_id*>(&_map_data[2]); } 1162 set_typepartition_map_header1163 void set_type(uint8 type) { _type = type; } set_lengthpartition_map_header1164 void set_length(uint8 length) { _length = length; } 1165 private: 1166 uint8 _type; 1167 uint8 _length; 1168 uint8 _map_data[0]; 1169 };// __attribute__((packed)); 1170 1171 1172 /*! \brief Physical partition map (i.e. ECMA-167 Type 1 partition map) 1173 1174 See also: ECMA-167 3/10.7.2 1175 */ 1176 struct physical_partition_map { 1177 public: 1178 void dump(); 1179 typephysical_partition_map1180 uint8 type() const { return _type; } lengthphysical_partition_map1181 uint8 length() const { return _length; } 1182 volume_sequence_numberphysical_partition_map1183 uint16 volume_sequence_number() const { 1184 return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); } partition_numberphysical_partition_map1185 uint16 partition_number() const { 1186 return B_LENDIAN_TO_HOST_INT16(_partition_number); } 1187 set_typephysical_partition_map1188 void set_type(uint8 type) { _type = type; } set_lengthphysical_partition_map1189 void set_length(uint8 length) { _length = length; } set_volume_sequence_numberphysical_partition_map1190 void set_volume_sequence_number(uint16 number) { 1191 _volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); } set_partition_numberphysical_partition_map1192 void set_partition_number(uint16 number) { 1193 _partition_number = B_HOST_TO_LENDIAN_INT16(number); } 1194 private: 1195 uint8 _type; 1196 uint8 _length; 1197 uint16 _volume_sequence_number; 1198 uint16 _partition_number; 1199 } __attribute__((packed)); 1200 1201 1202 /* ----UDF Specific---- */ 1203 /*! \brief Virtual partition map 1204 1205 Note that this map is a customization of the ECMA-167 1206 type 2 partition map. 1207 1208 See also: UDF-2.01 2.2.8 1209 */ 1210 struct virtual_partition_map { 1211 uint8 type; 1212 uint8 length; 1213 uint8 reserved1[2]; 1214 1215 /*! - flags: 0 1216 - identifier: "*UDF Virtual Partition" 1217 - identifier_suffix: per UDF-2.01 2.1.5.3 1218 */ 1219 entity_id partition_type_id; 1220 uint16 volume_sequence_number; 1221 1222 /*! corresponding type 1 partition map in same logical volume 1223 */ 1224 uint16 partition_number; 1225 uint8 reserved2[24]; 1226 } __attribute__((packed)); 1227 1228 1229 /*! \brief Maximum number of redundant sparing tables found in 1230 sparable_partition_map structures. 1231 */ 1232 #define UDF_MAX_SPARING_TABLE_COUNT 4 1233 1234 /* ----UDF Specific---- */ 1235 /*! \brief Sparable partition map 1236 1237 Note that this map is a customization of the ECMA-167 1238 type 2 partition map. 1239 1240 See also: UDF-2.01 2.2.9 1241 */ 1242 struct sparable_partition_map { 1243 public: 1244 void dump(); 1245 typesparable_partition_map1246 uint8 type() const { return _type; } lengthsparable_partition_map1247 uint8 length() const { return _length; } 1248 partition_type_idsparable_partition_map1249 entity_id& partition_type_id() { return _partition_type_id; } partition_type_idsparable_partition_map1250 const entity_id& partition_type_id() const { return _partition_type_id; } 1251 volume_sequence_numbersparable_partition_map1252 uint16 volume_sequence_number() const { 1253 return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); } partition_numbersparable_partition_map1254 uint16 partition_number() const { 1255 return B_LENDIAN_TO_HOST_INT16(_partition_number); } packet_lengthsparable_partition_map1256 uint16 packet_length() const { 1257 return B_LENDIAN_TO_HOST_INT16(_packet_length); } sparing_table_countsparable_partition_map1258 uint8 sparing_table_count() const { return _sparing_table_count; } sparing_table_sizesparable_partition_map1259 uint32 sparing_table_size() const { 1260 return B_LENDIAN_TO_HOST_INT32(_sparing_table_size); } sparing_table_locationsparable_partition_map1261 uint32 sparing_table_location(uint8 index) const { 1262 return B_LENDIAN_TO_HOST_INT32(_sparing_table_locations[index]); } 1263 1264 set_typesparable_partition_map1265 void set_type(uint8 type) { _type = type; } set_lengthsparable_partition_map1266 void set_length(uint8 length) { _length = length; } set_volume_sequence_numbersparable_partition_map1267 void set_volume_sequence_number(uint16 number) { 1268 _volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); } set_partition_numbersparable_partition_map1269 void set_partition_number(uint16 number) { 1270 _partition_number = B_HOST_TO_LENDIAN_INT16(number); } set_packet_lengthsparable_partition_map1271 void set_packet_length(uint16 length) { 1272 _packet_length = B_HOST_TO_LENDIAN_INT16(length); } set_sparing_table_countsparable_partition_map1273 void set_sparing_table_count(uint8 count) { 1274 _sparing_table_count = count; } set_sparing_table_sizesparable_partition_map1275 void set_sparing_table_size(uint32 size) { 1276 _sparing_table_size = B_HOST_TO_LENDIAN_INT32(size); } set_sparing_table_locationsparable_partition_map1277 void set_sparing_table_location(uint8 index, uint32 location) { 1278 _sparing_table_locations[index] = B_HOST_TO_LENDIAN_INT32(location); } 1279 private: 1280 uint8 _type; 1281 uint8 _length; 1282 uint8 _reserved1[2]; 1283 1284 /*! - flags: 0 1285 - identifier: "*UDF Sparable Partition" 1286 - identifier_suffix: per UDF-2.01 2.1.5.3 1287 */ 1288 entity_id _partition_type_id; 1289 uint16 _volume_sequence_number; 1290 1291 //! partition number of corresponding partition descriptor 1292 uint16 _partition_number; 1293 uint16 _packet_length; 1294 uint8 _sparing_table_count; 1295 uint8 _reserved2; 1296 uint32 _sparing_table_size; 1297 uint32 _sparing_table_locations[UDF_MAX_SPARING_TABLE_COUNT]; 1298 } __attribute__((packed)); 1299 1300 1301 /* ----UDF Specific---- */ 1302 /*! \brief Metadata partition map 1303 1304 Note that this map is a customization of the ECMA-167 1305 type 2 partition map. 1306 1307 See also: UDF-2.50 2.2.10 1308 */ 1309 struct metadata_partition_map { 1310 public: partition_type_idmetadata_partition_map1311 entity_id& partition_type_id() { return _partition_type_id; } partition_type_idmetadata_partition_map1312 const entity_id& partition_type_id() const { return _partition_type_id; } 1313 volume_sequence_numbermetadata_partition_map1314 uint16 volume_sequence_number() const { 1315 return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); } set_volume_sequence_numbermetadata_partition_map1316 void set_volume_sequence_number(uint16 number) { 1317 _volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); } 1318 partition_numbermetadata_partition_map1319 uint16 partition_number() const { 1320 return B_LENDIAN_TO_HOST_INT16(_partition_number); } set_partition_numbermetadata_partition_map1321 void set_partition_number(uint16 number) { 1322 _partition_number = B_HOST_TO_LENDIAN_INT16(number); } 1323 metadata_file_locationmetadata_partition_map1324 uint32 metadata_file_location() const { 1325 return B_LENDIAN_TO_HOST_INT32(_metadata_file_location); } set_metadata_file_locationmetadata_partition_map1326 void set_metadata_file_location(uint32 location) { 1327 _metadata_file_location = B_HOST_TO_LENDIAN_INT32(location); } 1328 metadata_mirror_file_locationmetadata_partition_map1329 uint32 metadata_mirror_file_location() const { 1330 return B_LENDIAN_TO_HOST_INT32(_metadata_mirror_file_location); } set_metadata_mirror_file_locationmetadata_partition_map1331 void set_metadata_mirror_file_location(uint32 location) { 1332 _metadata_mirror_file_location = B_HOST_TO_LENDIAN_INT32(location); } 1333 metadata_bitmap_file_locationmetadata_partition_map1334 uint32 metadata_bitmap_file_location() const { 1335 return B_LENDIAN_TO_HOST_INT32(_metadata_bitmap_file_location); } set_metadata_bitmap_file_locationmetadata_partition_map1336 void set_metadata_bitmap_file_location(uint32 location) { 1337 _metadata_bitmap_file_location = B_HOST_TO_LENDIAN_INT32(location); } 1338 allocation_unit_sizemetadata_partition_map1339 uint32 allocation_unit_size() const { 1340 return B_LENDIAN_TO_HOST_INT32(_allocation_unit_size); } set_allocation_unit_sizemetadata_partition_map1341 void set_allocation_unit_size(uint32 size) { 1342 _allocation_unit_size = B_HOST_TO_LENDIAN_INT32(size); } 1343 alignment_unit_sizemetadata_partition_map1344 uint32 alignment_unit_size() const { 1345 return B_LENDIAN_TO_HOST_INT32(_alignment_unit_size); } set_alignment_unit_sizemetadata_partition_map1346 void set_alignment_unit_size(uint32 size) { 1347 _alignment_unit_size = B_HOST_TO_LENDIAN_INT32(size); } 1348 flagsmetadata_partition_map1349 uint8 flags() const { return _flags; } set_flagsmetadata_partition_map1350 void set_flags(uint8 flags) { _flags = flags; } 1351 1352 private: 1353 uint8 type; 1354 uint8 length; 1355 uint8 reserved1[2]; 1356 1357 /*! - flags: 0 1358 - identifier: "*UDF Metadata Partition" 1359 - identifier_suffix: per UDF-2.50 2.1.5 1360 */ 1361 entity_id _partition_type_id; 1362 uint16 _volume_sequence_number; 1363 1364 /*! corresponding type 1 or type 2 sparable partition 1365 map in same logical volume 1366 */ 1367 uint16 _partition_number; 1368 uint32 _metadata_file_location; 1369 uint32 _metadata_mirror_file_location; 1370 uint32 _metadata_bitmap_file_location; 1371 uint32 _allocation_unit_size; 1372 uint16 _alignment_unit_size; 1373 uint8 _flags; 1374 uint8 reserved2[5]; 1375 } __attribute__((packed)); 1376 1377 1378 /*! \brief Unallocated space descriptor 1379 1380 See also: ECMA-167 3/10.8 1381 */ 1382 struct unallocated_space_descriptor { 1383 void dump() const; 1384 1385 // Get functions tagunallocated_space_descriptor1386 const descriptor_tag & tag() const { return _tag; } tagunallocated_space_descriptor1387 descriptor_tag & tag() { return _tag; } vds_numberunallocated_space_descriptor1388 uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); } allocation_descriptor_countunallocated_space_descriptor1389 uint32 allocation_descriptor_count() const { return B_LENDIAN_TO_HOST_INT32(_allocation_descriptor_count); } allocation_descriptorsunallocated_space_descriptor1390 extent_address* allocation_descriptors() { return _allocation_descriptors; } 1391 1392 // Set functions set_vds_numberunallocated_space_descriptor1393 void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); } set_allocation_descriptor_countunallocated_space_descriptor1394 void set_allocation_descriptor_count(uint32 count) { _allocation_descriptor_count = B_HOST_TO_LENDIAN_INT32(count); } 1395 private: 1396 descriptor_tag _tag; 1397 uint32 _vds_number; 1398 uint32 _allocation_descriptor_count; 1399 extent_address _allocation_descriptors[0]; 1400 } __attribute__((packed)); 1401 1402 1403 /*! \brief Terminating descriptor 1404 1405 See also: ECMA-167 3/10.9 1406 */ 1407 struct terminating_descriptor { terminating_descriptorterminating_descriptor1408 terminating_descriptor() { memset(_reserved.data, 0, _reserved.size()); } 1409 void dump() const; 1410 1411 // Get functions tagterminating_descriptor1412 const descriptor_tag & tag() const { return _tag; } tagterminating_descriptor1413 descriptor_tag & tag() { return _tag; } 1414 private: 1415 descriptor_tag _tag; 1416 array<uint8, 496> _reserved; 1417 } __attribute__((packed)); 1418 1419 1420 /*! \brief Logical volume integrity descriptor 1421 1422 See also: ECMA-167 3/10.10, UDF-2.50 2.2.6 1423 */ 1424 struct logical_volume_integrity_descriptor { 1425 public: 1426 static const uint32 minimum_implementation_use_length = 46; 1427 1428 void dump() const; descriptor_sizelogical_volume_integrity_descriptor1429 uint32 descriptor_size() const { return sizeof(*this)+implementation_use_length() 1430 + partition_count()*sizeof(uint32)*2; } 1431 taglogical_volume_integrity_descriptor1432 descriptor_tag& tag() { return _tag; } taglogical_volume_integrity_descriptor1433 const descriptor_tag& tag() const { return _tag; } 1434 recording_timelogical_volume_integrity_descriptor1435 timestamp& recording_time() { return _recording_time; } recording_timelogical_volume_integrity_descriptor1436 const timestamp& recording_time() const { return _recording_time; } 1437 integrity_typelogical_volume_integrity_descriptor1438 uint32 integrity_type() const { return B_LENDIAN_TO_HOST_INT32(_integrity_type); } 1439 next_integrity_extentlogical_volume_integrity_descriptor1440 extent_address& next_integrity_extent() { return _next_integrity_extent; } next_integrity_extentlogical_volume_integrity_descriptor1441 const extent_address& next_integrity_extent() const { return _next_integrity_extent; } 1442 logical_volume_contents_uselogical_volume_integrity_descriptor1443 array<uint8, 32>& logical_volume_contents_use() { return _logical_volume_contents_use; } logical_volume_contents_uselogical_volume_integrity_descriptor1444 const array<uint8, 32>& logical_volume_contents_use() const { return _logical_volume_contents_use; } 1445 1446 // next_unique_id() field is actually stored in the logical_volume_contents_use() 1447 // field, per UDF-2.50 3.2.1 next_unique_idlogical_volume_integrity_descriptor1448 uint64 next_unique_id() const { return B_LENDIAN_TO_HOST_INT64(_next_unique_id()); } 1449 partition_countlogical_volume_integrity_descriptor1450 uint32 partition_count() const { return B_LENDIAN_TO_HOST_INT32(_partition_count); } implementation_use_lengthlogical_volume_integrity_descriptor1451 uint32 implementation_use_length() const { return B_LENDIAN_TO_HOST_INT32(_implementation_use_length); } 1452 1453 /*! \todo double-check the pointer arithmetic here. */ free_space_tablelogical_volume_integrity_descriptor1454 uint32* free_space_table() { return reinterpret_cast<uint32*>(reinterpret_cast<uint8*>(this)+80); } free_space_tablelogical_volume_integrity_descriptor1455 const uint32* free_space_table() const { return reinterpret_cast<const uint32*>(reinterpret_cast<const uint8*>(this)+80); } size_tablelogical_volume_integrity_descriptor1456 uint32* size_table() { return reinterpret_cast<uint32*>(reinterpret_cast<uint8*>(free_space_table())+partition_count()*sizeof(uint32)); } size_tablelogical_volume_integrity_descriptor1457 const uint32* size_table() const { return reinterpret_cast<const uint32*>(reinterpret_cast<const uint8*>(free_space_table())+partition_count()*sizeof(uint32)); } implementation_uselogical_volume_integrity_descriptor1458 uint8* implementation_use() { return reinterpret_cast<uint8*>(reinterpret_cast<uint8*>(size_table())+partition_count()*sizeof(uint32)); } implementation_uselogical_volume_integrity_descriptor1459 const uint8* implementation_use() const { return reinterpret_cast<const uint8*>(reinterpret_cast<const uint8*>(size_table())+partition_count()*sizeof(uint32)); } 1460 1461 // accessors for fields stored in implementation_use() field per UDF-2.50 2.2.6.4 implementation_idlogical_volume_integrity_descriptor1462 entity_id& implementation_id() { return _accessor().id; } implementation_idlogical_volume_integrity_descriptor1463 const entity_id& implementation_id() const { return _accessor().id; } file_countlogical_volume_integrity_descriptor1464 uint32 file_count() const { return B_LENDIAN_TO_HOST_INT32(_accessor().file_count); } directory_countlogical_volume_integrity_descriptor1465 uint32 directory_count() const { return B_LENDIAN_TO_HOST_INT32(_accessor().directory_count); } minimum_udf_read_revisionlogical_volume_integrity_descriptor1466 uint16 minimum_udf_read_revision() const { return B_LENDIAN_TO_HOST_INT16(_accessor().minimum_udf_read_revision); } minimum_udf_write_revisionlogical_volume_integrity_descriptor1467 uint16 minimum_udf_write_revision() const { return B_LENDIAN_TO_HOST_INT16(_accessor().minimum_udf_write_revision); } maximum_udf_write_revisionlogical_volume_integrity_descriptor1468 uint16 maximum_udf_write_revision() const { return B_LENDIAN_TO_HOST_INT16(_accessor().maximum_udf_write_revision); } 1469 1470 // set functions set_integrity_typelogical_volume_integrity_descriptor1471 void set_integrity_type(uint32 type) { _integrity_type = B_HOST_TO_LENDIAN_INT32(type); } set_next_unique_idlogical_volume_integrity_descriptor1472 void set_next_unique_id(uint64 id) { _next_unique_id() = B_HOST_TO_LENDIAN_INT64(id); } set_partition_countlogical_volume_integrity_descriptor1473 void set_partition_count(uint32 count) { _partition_count = B_HOST_TO_LENDIAN_INT32(count); } set_implementation_use_lengthlogical_volume_integrity_descriptor1474 void set_implementation_use_length(uint32 length) { _implementation_use_length = B_HOST_TO_LENDIAN_INT32(length); } 1475 1476 // set functions for fields stored in implementation_use() field per UDF-2.50 2.2.6.4 set_file_countlogical_volume_integrity_descriptor1477 void set_file_count(uint32 count) { _accessor().file_count = B_HOST_TO_LENDIAN_INT32(count); } set_directory_countlogical_volume_integrity_descriptor1478 void set_directory_count(uint32 count) { _accessor().directory_count = B_HOST_TO_LENDIAN_INT32(count); } set_minimum_udf_read_revisionlogical_volume_integrity_descriptor1479 void set_minimum_udf_read_revision(uint16 revision) { _accessor().minimum_udf_read_revision = B_HOST_TO_LENDIAN_INT16(revision); } set_minimum_udf_write_revisionlogical_volume_integrity_descriptor1480 void set_minimum_udf_write_revision(uint16 revision) { _accessor().minimum_udf_write_revision = B_HOST_TO_LENDIAN_INT16(revision); } set_maximum_udf_write_revisionlogical_volume_integrity_descriptor1481 void set_maximum_udf_write_revision(uint16 revision) { _accessor().maximum_udf_write_revision = B_HOST_TO_LENDIAN_INT16(revision); } 1482 1483 private: 1484 struct _lvid_implementation_use_accessor { 1485 entity_id id; 1486 uint32 file_count; 1487 uint32 directory_count; 1488 uint16 minimum_udf_read_revision; 1489 uint16 minimum_udf_write_revision; 1490 uint16 maximum_udf_write_revision; 1491 }; 1492 _accessorlogical_volume_integrity_descriptor1493 _lvid_implementation_use_accessor& _accessor() { 1494 return *reinterpret_cast<_lvid_implementation_use_accessor*>(implementation_use()); 1495 } _accessorlogical_volume_integrity_descriptor1496 const _lvid_implementation_use_accessor& _accessor() const { 1497 return *reinterpret_cast<const _lvid_implementation_use_accessor*>(implementation_use()); 1498 } 1499 _next_unique_idlogical_volume_integrity_descriptor1500 uint64& _next_unique_id() { return *reinterpret_cast<uint64*>(logical_volume_contents_use().data); } _next_unique_idlogical_volume_integrity_descriptor1501 const uint64& _next_unique_id() const { return *reinterpret_cast<const uint64*>(logical_volume_contents_use().data); } 1502 1503 descriptor_tag _tag; 1504 timestamp _recording_time; 1505 uint32 _integrity_type; 1506 extent_address _next_integrity_extent; 1507 array<uint8, 32> _logical_volume_contents_use; 1508 uint32 _partition_count; 1509 uint32 _implementation_use_length; 1510 1511 } __attribute__((packed)); 1512 1513 /*! \brief Logical volume integrity types 1514 */ 1515 enum { 1516 INTEGRITY_OPEN = 0, 1517 INTEGRITY_CLOSED = 1, 1518 }; 1519 1520 /*! \brief Highest currently supported UDF read revision. 1521 */ 1522 #define UDF_MAX_READ_REVISION 0x0250 1523 1524 //---------------------------------------------------------------------- 1525 // ECMA-167 Part 4 1526 //---------------------------------------------------------------------- 1527 1528 1529 1530 /*! \brief File set descriptor 1531 1532 Contains all the pertinent info about a file set (i.e. a hierarchy of files) 1533 1534 According to UDF-2.01, only one file set descriptor shall be recorded, 1535 except on WORM media, where the following rules apply: 1536 - Multiple file sets are allowed only on WORM media 1537 - The default file set shall be the one with highest value \c file_set_number field. 1538 - Only the default file set may be flagged as writeable. All others shall be 1539 flagged as "hard write protect". 1540 - No writeable file set may reference metadata structures which are referenced 1541 (directly or indirectly) by any other file set. Writeable file sets may, however, 1542 reference actual file data extents that are also referenced by other file sets. 1543 */ 1544 struct file_set_descriptor { 1545 void dump() const; 1546 1547 // Get functions tagfile_set_descriptor1548 const descriptor_tag & tag() const { return _tag; } tagfile_set_descriptor1549 descriptor_tag & tag() { return _tag; } 1550 recording_date_and_timefile_set_descriptor1551 const timestamp& recording_date_and_time() const { return _recording_date_and_time; } recording_date_and_timefile_set_descriptor1552 timestamp& recording_date_and_time() { return _recording_date_and_time; } 1553 interchange_levelfile_set_descriptor1554 uint16 interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_interchange_level); } max_interchange_levelfile_set_descriptor1555 uint16 max_interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_max_interchange_level); } character_set_listfile_set_descriptor1556 uint32 character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_character_set_list); } max_character_set_listfile_set_descriptor1557 uint32 max_character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_max_character_set_list); } file_set_numberfile_set_descriptor1558 uint32 file_set_number() const { return B_LENDIAN_TO_HOST_INT32(_file_set_number); } file_set_descriptor_numberfile_set_descriptor1559 uint32 file_set_descriptor_number() const { return B_LENDIAN_TO_HOST_INT32(_file_set_descriptor_number); } 1560 logical_volume_id_character_setfile_set_descriptor1561 const charspec& logical_volume_id_character_set() const { return _logical_volume_id_character_set; } logical_volume_id_character_setfile_set_descriptor1562 charspec& logical_volume_id_character_set() { return _logical_volume_id_character_set; } 1563 logical_volume_idfile_set_descriptor1564 const array<char, 128>& logical_volume_id() const { return _logical_volume_id; } logical_volume_idfile_set_descriptor1565 array<char, 128>& logical_volume_id() { return _logical_volume_id; } 1566 file_set_id_character_setfile_set_descriptor1567 const charspec& file_set_id_character_set() const { return _file_set_id_character_set; } file_set_id_character_setfile_set_descriptor1568 charspec& file_set_id_character_set() { return _file_set_id_character_set; } 1569 file_set_idfile_set_descriptor1570 const array<char, 32>& file_set_id() const { return _file_set_id; } file_set_idfile_set_descriptor1571 array<char, 32>& file_set_id() { return _file_set_id; } 1572 copyright_file_idfile_set_descriptor1573 const array<char, 32>& copyright_file_id() const { return _copyright_file_id; } copyright_file_idfile_set_descriptor1574 array<char, 32>& copyright_file_id() { return _copyright_file_id; } 1575 abstract_file_idfile_set_descriptor1576 const array<char, 32>& abstract_file_id() const { return _abstract_file_id; } abstract_file_idfile_set_descriptor1577 array<char, 32>& abstract_file_id() { return _abstract_file_id; } 1578 root_directory_icbfile_set_descriptor1579 const long_address& root_directory_icb() const { return _root_directory_icb; } root_directory_icbfile_set_descriptor1580 long_address& root_directory_icb() { return _root_directory_icb; } 1581 domain_idfile_set_descriptor1582 const entity_id& domain_id() const { return _domain_id; } domain_idfile_set_descriptor1583 entity_id& domain_id() { return _domain_id; } 1584 next_extentfile_set_descriptor1585 const long_address& next_extent() const { return _next_extent; } next_extentfile_set_descriptor1586 long_address& next_extent() { return _next_extent; } 1587 system_stream_directory_icbfile_set_descriptor1588 const long_address& system_stream_directory_icb() const { return _system_stream_directory_icb; } system_stream_directory_icbfile_set_descriptor1589 long_address& system_stream_directory_icb() { return _system_stream_directory_icb; } 1590 reservedfile_set_descriptor1591 const array<uint8, 32>& reserved() const { return _reserved; } reservedfile_set_descriptor1592 array<uint8, 32>& reserved() { return _reserved; } 1593 1594 // Set functions set_interchange_levelfile_set_descriptor1595 void set_interchange_level(uint16 level) { _interchange_level = B_HOST_TO_LENDIAN_INT16(level); } set_max_interchange_levelfile_set_descriptor1596 void set_max_interchange_level(uint16 level) { _max_interchange_level = B_HOST_TO_LENDIAN_INT16(level); } set_character_set_listfile_set_descriptor1597 void set_character_set_list(uint32 list) { _character_set_list = B_HOST_TO_LENDIAN_INT32(list); } set_max_character_set_listfile_set_descriptor1598 void set_max_character_set_list(uint32 list) { _max_character_set_list = B_HOST_TO_LENDIAN_INT32(list); } set_file_set_numberfile_set_descriptor1599 void set_file_set_number(uint32 number) { _file_set_number = B_HOST_TO_LENDIAN_INT32(number); } set_file_set_descriptor_numberfile_set_descriptor1600 void set_file_set_descriptor_number(uint32 number) { _file_set_descriptor_number = B_HOST_TO_LENDIAN_INT32(number); } 1601 private: 1602 descriptor_tag _tag; 1603 timestamp _recording_date_and_time; 1604 uint16 _interchange_level; //!< To be set to 3 (see UDF-2.01 2.3.2.1) 1605 uint16 _max_interchange_level; //!< To be set to 3 (see UDF-2.01 2.3.2.2) 1606 uint32 _character_set_list; 1607 uint32 _max_character_set_list; 1608 uint32 _file_set_number; 1609 uint32 _file_set_descriptor_number; 1610 charspec _logical_volume_id_character_set; //!< To be set to kCSOCharspec 1611 array<char, 128> _logical_volume_id; 1612 charspec _file_set_id_character_set; 1613 array<char, 32> _file_set_id; 1614 array<char, 32> _copyright_file_id; 1615 array<char, 32> _abstract_file_id; 1616 long_address _root_directory_icb; 1617 entity_id _domain_id; 1618 long_address _next_extent; 1619 long_address _system_stream_directory_icb; 1620 array<uint8, 32> _reserved; 1621 } __attribute__((packed)); 1622 1623 1624 /*! \brief Partition header descriptor 1625 1626 Contains references to unallocated and freed space data structures. 1627 1628 Note that unallocated space is space ready to be written with no 1629 preprocessing. Freed space is space needing preprocessing (i.e. 1630 a special write pass) before use. 1631 1632 Per UDF-2.01 2.3.3, the use of tables or bitmaps shall be consistent, 1633 i.e. only one type or the other shall be used, not both. 1634 1635 To indicate disuse of a certain field, the fields of the allocation 1636 descriptor shall all be set to 0. 1637 1638 See also: ECMA-167 4/14.3, UDF-2.01 2.2.3 1639 */ 1640 struct partition_header_descriptor { 1641 long_address unallocated_space_table; 1642 long_address unallocated_space_bitmap; 1643 /*! Unused, per UDF-2.01 2.2.3 */ 1644 long_address partition_integrity_table; 1645 long_address freed_space_table; 1646 long_address freed_space_bitmap; 1647 uint8 reserved[88]; 1648 } __attribute__((packed)); 1649 1650 #define kMaxFileIdSize (sizeof(file_id_descriptor)+512+3) 1651 1652 /*! \brief File identifier descriptor 1653 1654 Identifies the name of a file entry, and the location of its corresponding 1655 ICB. 1656 1657 See also: ECMA-167 4/14.4, UDF-2.01 2.3.4 1658 1659 \todo Check pointer arithmetic 1660 */ 1661 struct file_id_descriptor { 1662 public: descriptor_sizefile_id_descriptor1663 uint32 descriptor_size() const { return total_length(); } 1664 void dump() const; 1665 tagfile_id_descriptor1666 descriptor_tag & tag() { return _tag; } tagfile_id_descriptor1667 const descriptor_tag & tag() const { return _tag; } 1668 version_numberfile_id_descriptor1669 uint16 version_number() const { return B_LENDIAN_TO_HOST_INT16(_version_number); } 1670 characteristicsfile_id_descriptor1671 uint8 characteristics() const { return _characteristics; } 1672 may_be_hiddenfile_id_descriptor1673 bool may_be_hidden() const { 1674 characteristics_accessor c; 1675 c.all = characteristics(); 1676 return c.bits.may_be_hidden; 1677 } 1678 is_directoryfile_id_descriptor1679 bool is_directory() const { 1680 characteristics_accessor c; 1681 c.all = characteristics(); 1682 return c.bits.is_directory; 1683 } 1684 is_deletedfile_id_descriptor1685 bool is_deleted() const { 1686 characteristics_accessor c; 1687 c.all = characteristics(); 1688 return c.bits.is_deleted; 1689 } 1690 is_parentfile_id_descriptor1691 bool is_parent() const { 1692 characteristics_accessor c; 1693 c.all = characteristics(); 1694 return c.bits.is_parent; 1695 } 1696 is_metadata_streamfile_id_descriptor1697 bool is_metadata_stream() const { 1698 characteristics_accessor c; 1699 c.all = characteristics(); 1700 return c.bits.is_metadata_stream; 1701 } 1702 id_lengthfile_id_descriptor1703 uint8 id_length() const { return _id_length; } 1704 icbfile_id_descriptor1705 long_address& icb() { return _icb; } icbfile_id_descriptor1706 const long_address& icb() const { return _icb; } 1707 implementation_use_lengthfile_id_descriptor1708 uint16 implementation_use_length() const { return B_LENDIAN_TO_HOST_INT16(_implementation_use_length); } 1709 1710 /*! If implementation_use_length is greater than 0, the first 32 1711 bytes of implementation_use() shall be an entity_id identifying 1712 the implementation that generated the rest of the data in the 1713 implementation_use() field. 1714 */ implementation_usefile_id_descriptor1715 uint8* implementation_use() { return ((uint8*)this)+(38); } idfile_id_descriptor1716 char* id() { return ((char*)this)+(38)+implementation_use_length(); } idfile_id_descriptor1717 const char* id() const { return ((const char*)this)+(38)+implementation_use_length(); } 1718 structure_lengthfile_id_descriptor1719 uint16 structure_length() const { return (38) + id_length() + implementation_use_length(); } padding_lengthfile_id_descriptor1720 uint16 padding_length() const { return ((structure_length()+3)/4)*4 - structure_length(); } total_lengthfile_id_descriptor1721 uint16 total_length() const { return structure_length() + padding_length(); } 1722 1723 // Set functions set_version_numberfile_id_descriptor1724 void set_version_number(uint16 number) { _version_number = B_HOST_TO_LENDIAN_INT16(number); } 1725 set_characteristicsfile_id_descriptor1726 void set_characteristics(uint8 characteristics) { _characteristics = characteristics; } 1727 set_may_be_hiddenfile_id_descriptor1728 void set_may_be_hidden(bool how) { 1729 characteristics_accessor c; 1730 c.all = characteristics(); 1731 c.bits.may_be_hidden = how; 1732 set_characteristics(c.all); 1733 } 1734 set_is_directoryfile_id_descriptor1735 void set_is_directory(bool how) { 1736 characteristics_accessor c; 1737 c.all = characteristics(); 1738 c.bits.is_directory = how; 1739 set_characteristics(c.all); 1740 } 1741 set_is_deletedfile_id_descriptor1742 void set_is_deleted(bool how) { 1743 characteristics_accessor c; 1744 c.all = characteristics(); 1745 c.bits.is_deleted = how; 1746 set_characteristics(c.all); 1747 } 1748 set_is_parentfile_id_descriptor1749 void set_is_parent(bool how) { 1750 characteristics_accessor c; 1751 c.all = characteristics(); 1752 c.bits.is_parent = how; 1753 set_characteristics(c.all); 1754 } 1755 set_is_metadata_streamfile_id_descriptor1756 void set_is_metadata_stream(bool how) { 1757 characteristics_accessor c; 1758 c.all = characteristics(); 1759 c.bits.is_metadata_stream = how; 1760 set_characteristics(c.all); 1761 } 1762 1763 set_id_lengthfile_id_descriptor1764 void set_id_length(uint8 id_length) { _id_length = id_length; } set_implementation_use_lengthfile_id_descriptor1765 void set_implementation_use_length(uint16 implementation_use_length) { _implementation_use_length = B_HOST_TO_LENDIAN_INT16(implementation_use_length); } 1766 1767 1768 1769 private: 1770 union characteristics_accessor { 1771 uint8 all; 1772 struct { 1773 uint8 may_be_hidden:1, 1774 is_directory:1, 1775 is_deleted:1, 1776 is_parent:1, 1777 is_metadata_stream:1, 1778 reserved_characteristics:3; 1779 } bits; 1780 }; 1781 1782 descriptor_tag _tag; 1783 /*! According to ECMA-167: 1 <= valid version_number <= 32767, 32768 <= reserved <= 65535. 1784 1785 However, according to UDF-2.01, there shall be exactly one version of 1786 a file, and it shall be 1. 1787 */ 1788 uint16 _version_number; 1789 /*! \todo Check UDF-2.01 2.3.4.2 for some more restrictions. */ 1790 uint8 _characteristics; 1791 uint8 _id_length; 1792 long_address _icb; 1793 uint16 _implementation_use_length; 1794 } __attribute__((packed)); 1795 1796 1797 /*! \brief Allocation extent descriptor 1798 1799 See also: ECMA-167 4/14.5 1800 */ 1801 struct allocation_extent_descriptor { 1802 descriptor_tag tag; 1803 uint32 previous_allocation_extent_location; 1804 uint32 length_of_allocation_descriptors; 1805 1806 /*! \todo Check that this is really how things work: */ allocation_descriptorsallocation_extent_descriptor1807 uint8* allocation_descriptors() { return (uint8*)(reinterpret_cast<uint8*>(this)+sizeof(allocation_extent_descriptor)); } 1808 } __attribute__((packed)); 1809 1810 1811 /*! \brief icb_tag::file_type values 1812 1813 See also ECMA-167 4/14.6.6 1814 */ 1815 enum icb_file_types { 1816 ICB_TYPE_UNSPECIFIED = 0, 1817 ICB_TYPE_UNALLOCATED_SPACE_ENTRY, 1818 ICB_TYPE_PARTITION_INTEGRITY_ENTRY, 1819 ICB_TYPE_INDIRECT_ENTRY, 1820 ICB_TYPE_DIRECTORY, 1821 ICB_TYPE_REGULAR_FILE, 1822 ICB_TYPE_BLOCK_SPECIAL_DEVICE, 1823 ICB_TYPE_CHARACTER_SPECIAL_DEVICE, 1824 ICB_TYPE_EXTENDED_ATTRIBUTES_FILE, 1825 ICB_TYPE_FIFO, 1826 ICB_TYPE_ISSOCK, 1827 ICB_TYPE_TERMINAL, 1828 ICB_TYPE_SYMLINK, 1829 ICB_TYPE_STREAM_DIRECTORY, 1830 1831 ICB_TYPE_RESERVED_START = 14, 1832 ICB_TYPE_RESERVED_END = 247, 1833 1834 ICB_TYPE_CUSTOM_START = 248, 1835 ICB_TYPE_CUSTOM_END = 255, 1836 }; 1837 1838 /*! \brief idb_entry_tag::_flags::descriptor_flags() values 1839 1840 See also ECMA-167 4/14.6.8 1841 */ 1842 enum icb_descriptor_types { 1843 ICB_DESCRIPTOR_TYPE_SHORT = 0, 1844 ICB_DESCRIPTOR_TYPE_LONG, 1845 ICB_DESCRIPTOR_TYPE_EXTENDED, 1846 ICB_DESCRIPTOR_TYPE_EMBEDDED, 1847 }; 1848 1849 /*! \brief idb_entry_tag::strategy_type() values 1850 1851 See also UDF-2.50 2.3.5.1 1852 */ 1853 enum icb_strategy_types { 1854 ICB_STRATEGY_SINGLE = 4, 1855 ICB_STRATEGY_LINKED_LIST = 4096 1856 }; 1857 1858 /*! \brief ICB entry tag 1859 1860 Common tag found in all ICB entries (in addition to, and immediately following, 1861 the descriptor tag). 1862 1863 See also: ECMA-167 4/14.6, UDF-2.01 2.3.5 1864 */ 1865 struct icb_entry_tag { 1866 public: 1867 union flags_accessor { 1868 uint16 all_flags; 1869 struct { 1870 uint16 descriptor_flags:3, 1871 if_directory_then_sort:1, //!< To be set to 0 per UDF-2.01 2.3.5.4 1872 non_relocatable:1, 1873 archive:1, 1874 setuid:1, 1875 setgid:1, 1876 sticky:1, 1877 contiguous:1, 1878 system:1, 1879 transformed:1, 1880 multi_version:1, //!< To be set to 0 per UDF-2.01 2.3.5.4 1881 is_stream:1, 1882 reserved_icb_entry_flags:2; 1883 } flags; 1884 }; 1885 1886 public: 1887 void dump() const; 1888 prior_recorded_number_of_direct_entriesicb_entry_tag1889 uint32 prior_recorded_number_of_direct_entries() const { return B_LENDIAN_TO_HOST_INT32(_prior_recorded_number_of_direct_entries); } strategy_typeicb_entry_tag1890 uint16 strategy_type() const { return B_LENDIAN_TO_HOST_INT16(_strategy_type); } 1891 strategy_parametersicb_entry_tag1892 array<uint8, 2>& strategy_parameters() { return _strategy_parameters; } strategy_parametersicb_entry_tag1893 const array<uint8, 2>& strategy_parameters() const { return _strategy_parameters; } 1894 entry_counticb_entry_tag1895 uint16 entry_count() const { return B_LENDIAN_TO_HOST_INT16(_entry_count); } reservedicb_entry_tag1896 uint8& reserved() { return _reserved; } file_typeicb_entry_tag1897 uint8 file_type() const { return _file_type; } parent_icb_locationicb_entry_tag1898 logical_block_address& parent_icb_location() { return _parent_icb_location; } parent_icb_locationicb_entry_tag1899 const logical_block_address& parent_icb_location() const { return _parent_icb_location; } 1900 flagsicb_entry_tag1901 uint16 flags() const { return B_LENDIAN_TO_HOST_INT16(_flags); } flags_accessicb_entry_tag1902 flags_accessor& flags_access() { return *reinterpret_cast<flags_accessor*>(&_flags); } 1903 1904 // flags accessor functions descriptor_flagsicb_entry_tag1905 uint8 descriptor_flags() const { 1906 flags_accessor f; 1907 f.all_flags = flags(); 1908 return f.flags.descriptor_flags; 1909 } 1910 /* void set_descriptor_flags(uint8 value) { 1911 flags_accessor f; 1912 f.all_flags = flags(); 1913 f.flags.descriptor_flags = value; 1914 set_flags 1915 */ 1916 set_prior_recorded_number_of_direct_entriesicb_entry_tag1917 void set_prior_recorded_number_of_direct_entries(uint32 entries) { _prior_recorded_number_of_direct_entries = B_LENDIAN_TO_HOST_INT32(entries); } set_strategy_typeicb_entry_tag1918 void set_strategy_type(uint16 type) { _strategy_type = B_HOST_TO_LENDIAN_INT16(type); } 1919 set_entry_counticb_entry_tag1920 void set_entry_count(uint16 count) { _entry_count = B_LENDIAN_TO_HOST_INT16(count); } set_file_typeicb_entry_tag1921 void set_file_type(uint8 type) { _file_type = type; } 1922 set_flagsicb_entry_tag1923 void set_flags(uint16 flags) { _flags = B_LENDIAN_TO_HOST_INT16(flags); } 1924 1925 private: 1926 uint32 _prior_recorded_number_of_direct_entries; 1927 /*! Per UDF-2.01 2.3.5.1, only strategy types 4 and 4096 shall be supported. 1928 1929 \todo Describe strategy types here. 1930 */ 1931 uint16 _strategy_type; 1932 array<uint8, 2> _strategy_parameters; 1933 uint16 _entry_count; 1934 uint8 _reserved; 1935 /*! \brief icb_file_type value identifying the type of this icb entry */ 1936 uint8 _file_type; 1937 logical_block_address _parent_icb_location; 1938 uint16 _flags; 1939 } __attribute__((packed)); 1940 1941 /*! \brief Header portion of an ICB entry. 1942 */ 1943 struct icb_header { 1944 public: 1945 void dump() const; 1946 tagicb_header1947 descriptor_tag &tag() { return _tag; } tagicb_header1948 const descriptor_tag &tag() const { return _tag; } 1949 icb_tagicb_header1950 icb_entry_tag &icb_tag() { return _icb_tag; } icb_tagicb_header1951 const icb_entry_tag &icb_tag() const { return _icb_tag; } 1952 private: 1953 descriptor_tag _tag; 1954 icb_entry_tag _icb_tag; 1955 }; 1956 1957 /*! \brief Indirect ICB entry 1958 */ 1959 struct indirect_icb_entry { 1960 descriptor_tag tag; 1961 icb_entry_tag icb_tag; 1962 long_address indirect_icb; 1963 } __attribute__((packed)); 1964 1965 1966 /*! \brief Terminal ICB entry 1967 */ 1968 struct terminal_icb_entry { 1969 descriptor_tag tag; 1970 icb_entry_tag icb_tag; 1971 } __attribute__((packed)); 1972 1973 enum permissions { 1974 OTHER_EXECUTE = 0x0001, 1975 OTHER_WRITE = 0x0002, 1976 OTHER_READ = 0x0004, 1977 OTHER_ATTRIBUTES = 0x0008, 1978 OTHER_DELETE = 0x0010, 1979 GROUP_EXECUTE = 0x0020, 1980 GROUP_WRITE = 0x0040, 1981 GROUP_READ = 0x0080, 1982 GROUP_ATTRIBUTES = 0x0100, 1983 GROUP_DELETE = 0x0200, 1984 USER_EXECUTE = 0x0400, 1985 USER_WRITE = 0x0800, 1986 USER_READ = 0x1000, 1987 USER_ATTRIBUTES = 0x2000, 1988 USER_DELETE = 0x4000, 1989 }; 1990 1991 /*! \brief File ICB entry 1992 1993 See also: ECMA-167 4/14.9 1994 1995 \todo Check pointer math. 1996 */ 1997 struct file_icb_entry { 1998 void dump() const; descriptor_sizefile_icb_entry1999 uint32 descriptor_size() const { return sizeof(*this)+extended_attributes_length() 2000 +allocation_descriptors_length(); } descriptor_namefile_icb_entry2001 const char* descriptor_name() const { return "file_icb_entry"; } 2002 2003 // get functions tagfile_icb_entry2004 descriptor_tag & tag() { return _tag; } tagfile_icb_entry2005 const descriptor_tag & tag() const { return _tag; } 2006 icb_tagfile_icb_entry2007 icb_entry_tag& icb_tag() { return _icb_tag; } icb_tagfile_icb_entry2008 const icb_entry_tag& icb_tag() const { return _icb_tag; } 2009 uidfile_icb_entry2010 uint32 uid() const { return B_LENDIAN_TO_HOST_INT32(_uid); } gidfile_icb_entry2011 uint32 gid() const { return B_LENDIAN_TO_HOST_INT32(_gid); } permissionsfile_icb_entry2012