1 //---------------------------------------------------------------------- 2 // This software is part of the OpenBeOS distribution and is covered 3 // by the OpenBeOS license. 4 // 5 // Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net 6 //--------------------------------------------------------------------- 7 #ifndef _UDF_DISK_STRUCTURES_H 8 #define _UDF_DISK_STRUCTURES_H 9 10 #include <string.h> 11 12 #include <ByteOrder.h> 13 #include <SupportDefs.h> 14 15 #include "kernel_cpp.h" 16 #include "UdfDebug.h" 17 18 #include "Array.h" 19 20 /*! \file UdfStructures.h 21 22 \brief UDF on-disk data structure declarations 23 24 UDF is a specialization of the ECMA-167 standard. For the most part, 25 ECMA-167 structures are used by UDF with special restrictions. In a 26 few instances, UDF introduces its own structures to augment those 27 supplied by ECMA-167; those structures are clearly marked. 28 29 For UDF info: <a href='http://www.osta.org'>http://www.osta.org</a> 30 For ECMA info: <a href='http://www.ecma-international.org'>http://www.ecma-international.org</a> 31 32 For lack of a better place to store this info, the structures that 33 are allowed to have length greater than the logical block size are 34 as follows (other length restrictions may be found in UDF-2.01 5.1): 35 - \c logical_volume_descriptor 36 - \c unallocated_space_descriptor 37 - \c logical_volume_integrity_descriptor 38 - \c space_bitmap_descriptor 39 40 Other links of interest: 41 - <a href='http://www.extra.research.philips.com/udf/'>Philips UDF verifier</a> 42 - <a href='http://www.hi-ho.ne.jp/y-komachi/committees/fpro/fpro.htm'>Possible test disc image generator (?)</a> 43 */ 44 45 namespace Udf { 46 47 //---------------------------------------------------------------------- 48 // ECMA-167 Part 1 49 //---------------------------------------------------------------------- 50 51 /*! \brief Character set specifications 52 53 The character_set_info field shall be set to the ASCII string 54 "OSTA Compressed Unicode" (padded right with NULL chars). 55 56 See also: ECMA 167 1/7.2.1, UDF-2.01 2.1.2 57 */ 58 struct charspec { 59 public: 60 void dump() const; 61 62 uint8 character_set_type() const { return _character_set_type; } 63 const char* character_set_info() const { return _character_set_info; } 64 char* character_set_info() { return _character_set_info; } 65 66 void set_character_set_type(uint8 type) { _character_set_type = type; } 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 73 extern const charspec kCS0Charspec; 74 75 76 /*! \brief Date and time stamp 77 78 See also: ECMA 167 1/7.3, UDF-2.01 2.1.4 79 */ 80 class timestamp { 81 private: 82 union type_and_timezone_accessor { 83 uint16 type_and_timezone; 84 struct { 85 uint16 type:4, 86 timezone:12; 87 } bits; 88 }; 89 90 public: 91 void dump() const; 92 93 // Get functions 94 uint16 type_and_timezone() const { return B_LENDIAN_TO_HOST_INT16(_type_and_timezone); } 95 uint8 type() const { 96 type_and_timezone_accessor t; 97 t.type_and_timezone = type_and_timezone(); 98 return t.bits.type; 99 } 100 int16 timezone() const { 101 type_and_timezone_accessor t; 102 t.type_and_timezone = type_and_timezone(); 103 return t.bits.timezone; 104 } 105 uint16 year() const { return B_LENDIAN_TO_HOST_INT16(_year); } 106 uint8 month() const { return _month; } 107 uint8 day() const { return _day; } 108 uint8 hour() const { return _hour; } 109 uint8 minute() const { return _minute; } 110 uint8 second() const { return _second; } 111 uint8 centisecond() const { return _centisecond; } 112 uint8 hundred_microsecond() const { return _hundred_microsecond; } 113 uint8 microsecond() const { return _microsecond; } 114 115 // Set functions 116 void set_type_and_timezone(uint16 type_and_timezone) { _type_and_timezone = B_HOST_TO_LENDIAN_INT16(type_and_timezone); } 117 void set_type(uint8 type) { 118 type_and_timezone_accessor t; 119 t.type_and_timezone = type_and_timezone(); 120 t.bits.type = type; 121 set_type_and_timezone(t.type_and_timezone); 122 } 123 void set_timezone(uint8 timezone) { 124 type_and_timezone_accessor t; 125 t.type_and_timezone = type_and_timezone(); 126 t.bits.timezone = timezone; 127 set_type_and_timezone(t.type_and_timezone); 128 } 129 void set_year(uint16 year) { _year = B_HOST_TO_LENDIAN_INT16(year); } 130 void set_month(uint8 month) { _month = month; } 131 void set_day(uint8 day) { _day = day; } 132 void set_hour(uint8 hour) { _hour = hour; } 133 void set_minute(uint8 minute) { _minute = minute; } 134 void set_second(uint8 second) { _second = second; } 135 void set_centisecond(uint8 centisecond) { _centisecond = centisecond; } 136 void set_hundred_microsecond(uint8 hundred_microsecond) { _hundred_microsecond = hundred_microsecond; } 137 void set_microsecond(uint8 microsecond) { _microsecond = microsecond; } 138 private: 139 uint16 _type_and_timezone; 140 uint16 _year; 141 uint8 _month; 142 uint8 _day; 143 uint8 _hour; 144 uint8 _minute; 145 uint8 _second; 146 uint8 _centisecond; 147 uint8 _hundred_microsecond; 148 uint8 _microsecond; 149 150 } __attribute__((packed)); 151 152 153 /*! \brief Identifier used to designate the implementation responsible 154 for writing associated data structures on the medium. 155 156 See also: ECMA 167 1/7.4, UDF 2.01 2.1.5 157 */ 158 struct entity_id { 159 public: 160 entity_id(uint8 flags = 0, char *identifier = NULL, 161 char *identifier_suffix = NULL); 162 163 void dump() const; 164 bool matches(const entity_id &id) const; 165 166 // Get functions 167 uint8 flags() const { return _flags; } 168 const char* identifier() const { return _identifier; } 169 char* identifier() { return _identifier; } 170 const char* identifier_suffix() const { return _identifier_suffix; } 171 char* identifier_suffix() { return _identifier_suffix; } 172 173 // Set functions 174 void set_flags(uint8 flags) { _flags = flags; } 175 176 static const int kIdentifierLength = 23; 177 static const int kIdentifierSuffixLength = 8; 178 private: 179 uint8 _flags; 180 char _identifier[kIdentifierLength]; 181 char _identifier_suffix[kIdentifierSuffixLength]; 182 } __attribute__((packed)); 183 184 extern const entity_id kMetadataPartitionMapId; 185 extern const entity_id kSparablePartitionMapId; 186 extern const entity_id kVirtualPartitionMapId; 187 188 //---------------------------------------------------------------------- 189 // ECMA-167 Part 2 190 //---------------------------------------------------------------------- 191 192 193 /*! \brief Header for volume structure descriptors 194 195 Each descriptor consumes an entire block. All unused trailing 196 bytes in the descriptor should be set to 0. 197 198 The following descriptors contain no more information than 199 that contained in the header: 200 201 - BEA01: 202 - type: 0 203 - id: "BEA01" 204 - version: 1 205 206 - TEA01: 207 - type: 0 208 - id: "TEA01" 209 - version: 1 210 211 - NSR03: 212 - type: 0 213 - id: "NSR03" 214 - version: 1 215 216 See also: ECMA 167 2/9.1 217 */ 218 struct volume_structure_descriptor_header { 219 public: 220 volume_structure_descriptor_header(uint8 type, const char *id, uint8 version); 221 222 uint8 type; 223 char id[5]; 224 uint8 version; 225 226 bool id_matches(const char *id); 227 } __attribute__((packed)); 228 229 // Volume structure descriptor ids 230 extern const char* kVSDID_BEA; 231 extern const char* kVSDID_TEA; 232 extern const char* kVSDID_BOOT; 233 extern const char* kVSDID_ISO; 234 extern const char* kVSDID_ECMA167_2; 235 extern const char* kVSDID_ECMA167_3; 236 extern const char* kVSDID_ECMA168; 237 238 //---------------------------------------------------------------------- 239 // ECMA-167 Part 3 240 //---------------------------------------------------------------------- 241 242 243 /*! \brief Location and length of a contiguous chunk of data on the volume. 244 245 \c _location is an absolute block address. 246 247 See also: ECMA 167 3/7.1 248 */ 249 struct extent_address { 250 public: 251 extent_address(uint32 location = 0, uint32 length = 0); 252 253 void dump() const; 254 255 uint32 length() const { return B_LENDIAN_TO_HOST_INT32(_length); } 256 uint32 location() const { return B_LENDIAN_TO_HOST_INT32(_location); } 257 258 void set_length(int32 length) { _length = B_HOST_TO_LENDIAN_INT32(length); } 259 void set_location(int32 location) { _location = B_HOST_TO_LENDIAN_INT32(location); } 260 private: 261 uint32 _length; 262 uint32 _location; 263 } __attribute__((packed)); 264 265 266 /*! \brief Location of a logical block within a logical volume. 267 268 See also: ECMA 167 4/7.1 269 */ 270 struct logical_block_address { 271 public: 272 void dump() const; 273 274 uint32 block() const { return B_LENDIAN_TO_HOST_INT32(_block); } 275 uint16 partition() const { return B_LENDIAN_TO_HOST_INT16(_partition); } 276 277 void set_block(uint32 block) { _block = B_HOST_TO_LENDIAN_INT32(block); } 278 void set_partition(uint16 partition) { _partition = B_HOST_TO_LENDIAN_INT16(partition); } 279 280 private: 281 uint32 _block; //!< Block location relative to start of corresponding partition 282 uint16 _partition; //!< Numeric partition id within logical volume 283 } __attribute__((packed)); 284 285 /*! \brief Extent types used in short_address, long_address, 286 and extended_address. 287 288 See also: ECMA-167 4/14.14.1.1 289 */ 290 enum extent_type { 291 EXTENT_TYPE_RECORDED = 0, //!< Allocated and recorded 292 EXTENT_TYPE_ALLOCATED, //!< Allocated but unrecorded 293 EXTENT_TYPE_UNALLOCATED, //!< Unallocated and unrecorded 294 EXTENT_TYPE_CONTINUATION, //!< Specifies next extent of descriptors 295 }; 296 297 298 /*! \brief Allocation descriptor. 299 300 See also: ECMA 167 4/14.14.1 301 */ 302 struct short_address { 303 private: 304 union type_and_length_accessor { 305 uint32 type_and_length; 306 struct { 307 uint32 length:30, 308 type:2; 309 // uint32 type:2, 310 // length:30; 311 } bits; 312 }; 313 314 public: 315 void dump() const; 316 317 uint8 type() const { 318 type_and_length_accessor t; 319 t.type_and_length = type_and_length(); 320 return t.bits.type; 321 } 322 uint32 length() const { 323 type_and_length_accessor t; 324 t.type_and_length = type_and_length(); 325 return t.bits.length; 326 } 327 uint32 block() const { return B_LENDIAN_TO_HOST_INT32(_block); } 328 329 void set_type(uint8 type) { 330 type_and_length_accessor t; 331 t.type_and_length = type_and_length(); 332 t.bits.type = type; 333 set_type_and_length(t.type_and_length); 334 } 335 void set_length(uint32 length) { 336 type_and_length_accessor t; 337 t.type_and_length = type_and_length(); 338 t.bits.length = length; 339 set_type_and_length(t.type_and_length); 340 } 341 void set_block(uint32 block) { _block = B_HOST_TO_LENDIAN_INT32(block); } 342 private: 343 uint32 type_and_length() const { return B_LENDIAN_TO_HOST_INT32(_type_and_length); } 344 void set_type_and_length(uint32 value) { _type_and_length = B_HOST_TO_LENDIAN_INT32(value); } 345 346 uint32 _type_and_length; 347 uint32 _block; 348 } __attribute__((packed)); 349 350 351 /*! \brief Allocation descriptor w/ 6 byte implementation use field. 352 353 See also: ECMA 167 4/14.14.2 354 */ 355 struct long_address { 356 private: 357 union type_and_length_accessor { 358 uint32 type_and_length; 359 struct { 360 uint32 length:30, 361 type:2; 362 } bits; 363 }; 364 365 public: 366 void dump() const; 367 368 uint8 type() const { 369 type_and_length_accessor t; 370 t.type_and_length = type_and_length(); 371 return t.bits.type; 372 } 373 uint32 length() const { 374 type_and_length_accessor t; 375 t.type_and_length = type_and_length(); 376 return t.bits.length; 377 } 378 379 uint32 block() const { return _location.block(); } 380 uint16 partition() const { return _location.partition(); } 381 382 const array<uint8, 6>& implementation_use() const { return _implementation_use; } 383 array<uint8, 6>& implementation_use() { return _implementation_use; } 384 385 void set_type(uint8 type) { 386 type_and_length_accessor t; 387 t.type_and_length = type_and_length(); 388 t.bits.type = type; 389 set_type_and_length(t.type_and_length); 390 } 391 void set_length(uint32 length) { 392 type_and_length_accessor t; 393 t.type_and_length = type_and_length(); 394 t.bits.length = length; 395 set_type_and_length(t.type_and_length); 396 } 397 void set_block(uint32 block) { _location.set_block(block); } 398 void set_partition(uint16 partition) { _location.set_partition(partition); } 399 400 void set_to(uint32 block, uint16 partition, uint32 length = 1, 401 uint8 type = EXTENT_TYPE_RECORDED) 402 { 403 set_block(block); 404 set_partition(partition); 405 set_length(length); 406 set_type(type); 407 } 408 409 private: 410 uint32 type_and_length() const { return B_LENDIAN_TO_HOST_INT32(_type_and_length); } 411 void set_type_and_length(uint32 value) { _type_and_length = B_HOST_TO_LENDIAN_INT32(value); } 412 413 uint32 _type_and_length; 414 logical_block_address _location; 415 array<uint8, 6> _implementation_use; 416 } __attribute__((packed)); 417 418 /*! \brief Common tag found at the beginning of most udf descriptor structures. 419 420 For error checking, \c descriptor_tag structures have: 421 - The disk location of the tag redundantly stored in the tag itself 422 - A checksum value for the tag 423 - A CRC value and length 424 425 See also: ECMA 167 1/7.2, UDF 2.01 2.2.1, UDF 2.01 2.3.1 426 */ 427 struct descriptor_tag { 428 public: 429 void dump() const; 430 431 status_t init_check(uint32 diskBlock); 432 433 uint16 id() const { return B_LENDIAN_TO_HOST_INT16(_id); } 434 uint16 version() const { return B_LENDIAN_TO_HOST_INT16(_version); } 435 uint8 checksum() const { return _checksum; } 436 uint16 serial_number() const { return B_LENDIAN_TO_HOST_INT16(_serial_number); } 437 uint16 crc() const { return B_LENDIAN_TO_HOST_INT16(_crc); } 438 uint16 crc_length() const { return B_LENDIAN_TO_HOST_INT16(_crc_length); } 439 uint32 location() const { return B_LENDIAN_TO_HOST_INT32(_location); } 440 441 void set_id(uint16 id) { _id = B_HOST_TO_LENDIAN_INT16(id); } 442 void set_version(uint16 version) { _version = B_HOST_TO_LENDIAN_INT16(version); } 443 void set_checksum(uint8 checksum) { _checksum = checksum; } 444 void set_serial_number(uint16 serial_number) { _serial_number = B_HOST_TO_LENDIAN_INT16(serial_number); } 445 void set_crc(uint16 crc) { _crc = B_HOST_TO_LENDIAN_INT16(crc); } 446 void set_crc_length(uint16 crc_length) { _crc_length = B_HOST_TO_LENDIAN_INT16(crc_length); } 447 void set_location(uint32 location) { _location = B_HOST_TO_LENDIAN_INT32(location); } 448 449 private: 450 uint16 _id; 451 uint16 _version; 452 uint8 _checksum; //!< Sum modulo 256 of bytes 0-3 and 5-15 of this struct. 453 uint8 _reserved; //!< Set to #00. 454 uint16 _serial_number; 455 uint16 _crc; //!< May be 0 if \c crc_length field is 0. 456 /*! \brief Length of the data chunk used to calculate CRC. 457 458 If 0, no CRC was calculated, and the \c crc field must be 0. 459 460 According to UDF-2.01 2.3.1.2, the CRC shall be calculated for all descriptors 461 unless otherwise noted, and this field shall be set to: 462 463 <code>(descriptor length) - (descriptor tag length)</code> 464 */ 465 uint16 _crc_length; 466 /*! \brief Address of this tag within its partition (for error checking). 467 468 For virtually addressed structures (i.e. those accessed thru a VAT), this 469 shall be the virtual address, not the physical or logical address. 470 */ 471 uint32 _location; 472 473 } __attribute__((packed)); 474 475 476 /*! \c descriptor_tag ::id values 477 */ 478 enum tag_id { 479 TAGID_UNDEFINED = 0, 480 481 // ECMA 167, PART 3 482 TAGID_PRIMARY_VOLUME_DESCRIPTOR, 483 TAGID_ANCHOR_VOLUME_DESCRIPTOR_POINTER, 484 TAGID_VOLUME_DESCRIPTOR_POINTER, 485 TAGID_IMPLEMENTATION_USE_VOLUME_DESCRIPTOR, 486 TAGID_PARTITION_DESCRIPTOR, 487 TAGID_LOGICAL_VOLUME_DESCRIPTOR, 488 TAGID_UNALLOCATED_SPACE_DESCRIPTOR, 489 TAGID_TERMINATING_DESCRIPTOR, 490 TAGID_LOGICAL_VOLUME_INTEGRITY_DESCRIPTOR, 491 492 TAGID_CUSTOM_START = 65280, 493 TAGID_CUSTOM_END = 65535, 494 495 // ECMA 167, PART 4 496 TAGID_FILE_SET_DESCRIPTOR = 256, 497 TAGID_FILE_IDENTIFIER_DESCRIPTOR, 498 TAGID_ALLOCATION_EXTENT_DESCRIPTOR, 499 TAGID_INDIRECT_ENTRY, 500 TAGID_TERMINAL_ENTRY, 501 TAGID_FILE_ENTRY, 502 TAGID_EXTENDED_ATTRIBUTE_HEADER_DESCRIPTOR, 503 TAGID_UNALLOCATED_SPACE_ENTRY, 504 TAGID_SPACE_BITMAP_DESCRIPTOR, 505 TAGID_PARTITION_INTEGRITY_ENTRY, 506 TAGID_EXTENDED_FILE_ENTRY, 507 }; 508 509 const char *tag_id_to_string(tag_id id); 510 511 /*! \brief Primary volume descriptor 512 */ 513 struct primary_volume_descriptor { 514 public: 515 void dump() const; 516 517 // Get functions 518 const descriptor_tag & tag() const { return _tag; } 519 descriptor_tag & tag() { return _tag; } 520 521 uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); } 522 uint32 primary_volume_descriptor_number() const { return B_LENDIAN_TO_HOST_INT32(_primary_volume_descriptor_number); } 523 524 const array<char, 32>& volume_identifier() const { return _volume_identifier; } 525 array<char, 32>& volume_identifier() { return _volume_identifier; } 526 527 uint16 volume_sequence_number() const { return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); } 528 uint16 max_volume_sequence_number() const { return B_LENDIAN_TO_HOST_INT16(_max_volume_sequence_number); } 529 uint16 interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_interchange_level); } 530 uint16 max_interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_max_interchange_level); } 531 uint32 character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_character_set_list); } 532 uint32 max_character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_max_character_set_list); } 533 534 const array<char, 128>& volume_set_identifier() const { return _volume_set_identifier; } 535 array<char, 128>& volume_set_identifier() { return _volume_set_identifier; } 536 537 const charspec& descriptor_character_set() const { return _descriptor_character_set; } 538 charspec& descriptor_character_set() { return _descriptor_character_set; } 539 540 const charspec& explanatory_character_set() const { return _explanatory_character_set; } 541 charspec& explanatory_character_set() { return _explanatory_character_set; } 542 543 const extent_address& volume_abstract() const { return _volume_abstract; } 544 extent_address& volume_abstract() { return _volume_abstract; } 545 const extent_address& volume_copyright_notice() const { return _volume_copyright_notice; } 546 extent_address& volume_copyright_notice() { return _volume_copyright_notice; } 547 548 const entity_id& application_id() const { return _application_id; } 549 entity_id& application_id() { return _application_id; } 550 551 const timestamp& recording_date_and_time() const { return _recording_date_and_time; } 552 timestamp& recording_date_and_time() { return _recording_date_and_time; } 553 554 const entity_id& implementation_id() const { return _implementation_id; } 555 entity_id& implementation_id() { return _implementation_id; } 556 557 const array<uint8, 64>& implementation_use() const { return _implementation_use; } 558 array<uint8, 64>& implementation_use() { return _implementation_use; } 559 560 uint32 predecessor_volume_descriptor_sequence_location() const 561 { return B_LENDIAN_TO_HOST_INT32(_predecessor_volume_descriptor_sequence_location); } 562 uint16 flags() const { return B_LENDIAN_TO_HOST_INT16(_flags); } 563 564 // Set functions 565 void set_vds_number(uint32 number) 566 { _vds_number = B_HOST_TO_LENDIAN_INT32(number); } 567 void set_primary_volume_descriptor_number(uint32 number) 568 { _primary_volume_descriptor_number = B_HOST_TO_LENDIAN_INT32(number); } 569 void set_volume_sequence_number(uint16 number) 570 { _volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); } 571 void set_max_volume_sequence_number(uint16 number) 572 { _max_volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); } 573 void set_interchange_level(uint16 level) 574 { _interchange_level = B_HOST_TO_LENDIAN_INT16(level); } 575 void set_max_interchange_level(uint16 level) 576 { _max_interchange_level = B_HOST_TO_LENDIAN_INT16(level); } 577 void set_character_set_list(uint32 list) 578 { _character_set_list = B_HOST_TO_LENDIAN_INT32(list); } 579 void set_max_character_set_list(uint32 list) 580 { _max_character_set_list = B_HOST_TO_LENDIAN_INT32(list); } 581 void set_predecessor_volume_descriptor_sequence_location(uint32 location) 582 { _predecessor_volume_descriptor_sequence_location = B_HOST_TO_LENDIAN_INT32(location); } 583 void set_flags(uint16 flags) 584 { _flags = B_HOST_TO_LENDIAN_INT16(flags); } 585 586 private: 587 descriptor_tag _tag; 588 uint32 _vds_number; 589 uint32 _primary_volume_descriptor_number; 590 array<char, 32> _volume_identifier; 591 uint16 _volume_sequence_number; 592 uint16 _max_volume_sequence_number; 593 uint16 _interchange_level; //!< to be set to 3 if part of multivolume set, 2 otherwise 594 uint16 _max_interchange_level; //!< to be set to 3 unless otherwise directed by user 595 uint32 _character_set_list; 596 uint32 _max_character_set_list; 597 array<char, 128> _volume_set_identifier; 598 599 /*! \brief Identifies the character set for the \c volume_identifier 600 and \c volume_set_identifier fields. 601 602 To be set to CS0. 603 */ 604 charspec _descriptor_character_set; 605 606 /*! \brief Identifies the character set used in the \c volume_abstract 607 and \c volume_copyright_notice extents. 608 609 To be set to CS0. 610 */ 611 charspec _explanatory_character_set; 612 613 extent_address _volume_abstract; 614 extent_address _volume_copyright_notice; 615 616 entity_id _application_id; 617 timestamp _recording_date_and_time; 618 entity_id _implementation_id; 619 array<uint8, 64> _implementation_use; 620 uint32 _predecessor_volume_descriptor_sequence_location; 621 uint16 _flags; 622 char _reserved[22]; 623 624 } __attribute__((packed)); 625 626 627 /*! \brief Anchor Volume Descriptor Pointer 628 629 vd recorded at preset locations in the partition, used as a reference 630 point to the main vd sequences 631 632 According to UDF 2.01, an avdp shall be recorded in at least 2 of 633 the 3 following locations, where N is the last recordable sector 634 of the partition: 635 - 256 636 - (N - 256) 637 - N 638 639 See also: ECMA 167 3/10.2, UDF-2.01 2.2.3 640 */ 641 struct anchor_volume_descriptor { 642 public: 643 void dump() const; 644 645 descriptor_tag & tag() { return _tag; } 646 const descriptor_tag & tag() const { return _tag; } 647 648 extent_address& main_vds() { return _main_vds; } 649 const extent_address& main_vds() const { return _main_vds; } 650 651 extent_address& reserve_vds() { return _reserve_vds; } 652 const extent_address& reserve_vds() const { return _reserve_vds; } 653 private: 654 descriptor_tag _tag; 655 extent_address _main_vds; //!< min length of 16 sectors 656 extent_address _reserve_vds; //!< min length of 16 sectors 657 char _reserved[480]; 658 } __attribute__((packed)); 659 660 661 /*! \brief Volume Descriptor Pointer 662 663 Used to chain extents of volume descriptor sequences together. 664 665 See also: ECMA 167 3/10.3 666 */ 667 struct descriptor_pointer { 668 descriptor_tag tag; 669 uint32 vds_number; 670 extent_address next; 671 } __attribute__((packed)); 672 673 674 /*! \brief Implementation Use Volume Descriptor 675 676 See also: ECMA 167 3/10.4 677 */ 678 struct implementation_use_descriptor { 679 public: 680 void dump() const; 681 682 // Get functions 683 const descriptor_tag & tag() const { return _tag; } 684 descriptor_tag & tag() { return _tag; } 685 686 uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); } 687 688 const entity_id& implementation_id() const { return _implementation_id; } 689 entity_id& implementation_id() { return _implementation_id; } 690 691 const array<uint8, 460>& implementation_use() const { return _implementation_use; } 692 array<uint8, 460>& implementation_use() { return _implementation_use; } 693 694 // Set functions 695 void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); } 696 private: 697 descriptor_tag _tag; 698 uint32 _vds_number; 699 entity_id _implementation_id; 700 array<uint8, 460> _implementation_use; 701 } __attribute__((packed)); 702 703 704 /*! \brief Maximum number of partition descriptors to be found in volume 705 descriptor sequence, per UDF-2.50 706 */ 707 extern const uint8 kMaxPartitionDescriptors; 708 #define UDF_MAX_PARTITION_MAPS 2 709 #define UDF_MAX_PARTITION_MAP_SIZE 64 710 711 /*! \brief Partition Descriptor 712 713 See also: ECMA 167 3/10.5 714 */ 715 struct partition_descriptor { 716 private: 717 union partition_flags_accessor { 718 uint16 partition_flags; 719 struct { 720 uint16 allocated:1, 721 reserved:15; 722 } bits; 723 }; 724 725 public: 726 void dump() const; 727 728 // Get functions 729 const descriptor_tag & tag() const { return _tag; } 730 descriptor_tag & tag() { return _tag; } 731 732 uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); } 733 uint16 partition_flags() const { return B_LENDIAN_TO_HOST_INT16(_partition_flags); } 734 bool allocated() const { 735 partition_flags_accessor f; 736 f.partition_flags = partition_flags(); 737 return f.bits.allocated; 738 } 739 uint16 partition_number() const { return B_LENDIAN_TO_HOST_INT16(_partition_number); } 740 741 const entity_id& partition_contents() const { return _partition_contents; } 742 entity_id& partition_contents() { return _partition_contents; } 743 744 const array<uint8, 128>& partition_contents_use() const { return _partition_contents_use; } 745 array<uint8, 128>& partition_contents_use() { return _partition_contents_use; } 746 747 uint32 access_type() const { return B_LENDIAN_TO_HOST_INT32(_access_type); } 748 uint32 start() const { return B_LENDIAN_TO_HOST_INT32(_start); } 749 uint32 length() const { return B_LENDIAN_TO_HOST_INT32(_length); } 750 751 const entity_id& implementation_id() const { return _implementation_id; } 752 entity_id& implementation_id() { return _implementation_id; } 753 754 const array<uint8, 128>& implementation_use() const { return _implementation_use; } 755 array<uint8, 128>& implementation_use() { return _implementation_use; } 756 757 // Set functions 758 void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); } 759 void set_partition_flags(uint16 flags) { _partition_flags = B_HOST_TO_LENDIAN_INT16(flags); } 760 void set_allocated(bool allocated) { 761 partition_flags_accessor f; 762 f.partition_flags = partition_flags(); 763 f.bits.allocated = allocated; 764 set_partition_flags(f.partition_flags); 765 } 766 767 void set_access_type(uint32 type) { _access_type = B_HOST_TO_LENDIAN_INT32(type); } 768 void set_start(uint32 start) { _start = B_HOST_TO_LENDIAN_INT32(start); } 769 void set_length(uint32 length) { _length = B_HOST_TO_LENDIAN_INT32(length); } 770 771 private: 772 descriptor_tag _tag; 773 uint32 _vds_number; 774 /*! Bit 0: If 0, shall mean volume space has not been allocated. If 1, 775 shall mean volume space has been allocated. 776 */ 777 uint16 _partition_flags; 778 uint16 _partition_number; 779 780 /*! - "+NSR03" Volume recorded according to ECMA-167, i.e. UDF 781 - "+CD001" Volume recorded according to ECMA-119, i.e. iso9660 782 - "+FDC01" Volume recorded according to ECMA-107 783 - "+CDW02" Volume recorded according to ECMA-168 784 */ 785 entity_id _partition_contents; 786 array<uint8, 128> _partition_contents_use; 787 788 /*! See \c partition_access_type enum 789 */ 790 uint32 _access_type; 791 uint32 _start; 792 uint32 _length; 793 entity_id _implementation_id; 794 array<uint8, 128> _implementation_use; 795 uint8 _reserved[156]; 796 } __attribute__((packed)); 797 798 799 enum partition_access_type { 800 PAT_UNSPECIFIED, 801 PAT_READ_ONLY, 802 PAT_WRITE_ONCE, 803 PAT_REWRITABLE, 804 PAT_OVERWRITABLE, 805 }; 806 807 808 /*! \brief Logical volume descriptor 809 810 See also: ECMA 167 3/10.6, UDF-2.01 2.2.4 811 */ 812 struct logical_volume_descriptor { 813 void dump() const; 814 815 // Get functions 816 const descriptor_tag & tag() const { return _tag; } 817 descriptor_tag & tag() { return _tag; } 818 819 uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); } 820 821 const charspec& character_set() const { return _character_set; } 822 charspec& character_set() { return _character_set; } 823 824 const array<char, 128>& logical_volume_identifier() const { return _logical_volume_identifier; } 825 array<char, 128>& logical_volume_identifier() { return _logical_volume_identifier; } 826 827 uint32 logical_block_size() const { return B_LENDIAN_TO_HOST_INT32(_logical_block_size); } 828 829 const entity_id& domain_id() const { return _domain_id; } 830 entity_id& domain_id() { return _domain_id; } 831 832 const array<uint8, 16>& logical_volume_contents_use() const { return _logical_volume_contents_use; } 833 array<uint8, 16>& logical_volume_contents_use() { return _logical_volume_contents_use; } 834 835 const long_address& file_set_address() const { return _file_set_address; } 836 long_address& file_set_address() { return _file_set_address; } 837 838 uint32 map_table_length() const { return B_LENDIAN_TO_HOST_INT32(_map_table_length); } 839 uint32 partition_map_count() const { return B_LENDIAN_TO_HOST_INT32(_partition_map_count); } 840 841 const entity_id& implementation_id() const { return _implementation_id; } 842 entity_id& implementation_id() { return _implementation_id; } 843 844 const array<uint8, 128>& implementation_use() const { return _implementation_use; } 845 array<uint8, 128>& implementation_use() { return _implementation_use; } 846 847 const extent_address& integrity_sequence_extent() const { return _integrity_sequence_extent; } 848 extent_address& integrity_sequence_extent() { return _integrity_sequence_extent; } 849 850 const uint8* partition_maps() const { return _partition_maps; } 851 uint8* partition_maps() { return _partition_maps; } 852 853 // Set functions 854 void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); } 855 void set_logical_block_size(uint32 size) { _logical_block_size = B_HOST_TO_LENDIAN_INT32(size); } 856 857 void set_map_table_length(uint32 length) { _map_table_length = B_HOST_TO_LENDIAN_INT32(length); } 858 void set_partition_map_count(uint32 count) { _partition_map_count = B_HOST_TO_LENDIAN_INT32(count); } 859 860 // Other functions 861 logical_volume_descriptor& operator=(const logical_volume_descriptor &rhs); 862 863 private: 864 descriptor_tag _tag; 865 uint32 _vds_number; 866 867 /*! \brief Identifies the character set for the 868 \c logical_volume_identifier field. 869 870 To be set to CS0. 871 */ 872 charspec _character_set; 873 array<char, 128> _logical_volume_identifier; 874 uint32 _logical_block_size; 875 876 /*! \brief To be set to 0 or "*OSTA UDF Compliant". See UDF specs. 877 */ 878 entity_id _domain_id; 879 880 union { 881 /*! \brief For UDF, shall contain a \c long_address which identifies 882 the location of the logical volume's first file set. 883 */ 884 array<uint8, 16> _logical_volume_contents_use; 885 long_address _file_set_address; 886 }; 887 888 uint32 _map_table_length; 889 uint32 _partition_map_count; 890 entity_id _implementation_id; 891 array<uint8, 128> _implementation_use; 892 893 /*! \brief Logical volume integrity sequence location. 894 895 For re/overwritable media, shall be a min of 8KB in length. 896 For WORM media, shall be quite frickin large, as a new volume 897 must be added to the set if the extent fills up (since you 898 can't chain lvis's I guess). 899 */ 900 extent_address _integrity_sequence_extent; 901 902 /*! \brief Restricted to maps of type 1 for normal maps and 903 UDF type 2 for virtual maps or maps on systems not supporting 904 defect management. 905 906 Note that we actually allocate memory for the partition maps 907 here due to the fact that we allocate logical_volume_descriptor 908 objects on the stack sometimes. 909 910 See UDF-2.01 2.2.8, 2.2.9 911 */ 912 uint8 _partition_maps[UDF_MAX_PARTITION_MAPS * UDF_MAX_PARTITION_MAP_SIZE]; 913 } __attribute__((packed)); 914 915 916 /*! \brief (Mostly) common portion of various partition maps 917 918 See also: ECMA-167 3/10.7.1 919 */ 920 struct partition_map_header { 921 public: 922 uint8 type() const { return _type; } 923 uint8 length() const { return _length; } 924 uint8 *map_data() { return _map_data; } 925 const uint8 *map_data() const { return _map_data; } 926 927 entity_id& partition_type_id() 928 { return *reinterpret_cast<entity_id*>(&_map_data[2]); } 929 const entity_id& partition_type_id() const 930 { return *reinterpret_cast<const entity_id*>(&_map_data[2]); } 931 932 void set_type(uint8 type) { _type = type; } 933 void set_length(uint8 length) { _length = length; } 934 private: 935 uint8 _type; 936 uint8 _length; 937 uint8 _map_data[0]; 938 };// __attribute__((packed)); 939 940 941 /*! \brief Physical partition map (i.e. ECMA-167 Type 1 partition map) 942 943 See also: ECMA-167 3/10.7.2 944 */ 945 struct physical_partition_map { 946 public: 947 void dump(); 948 949 uint8 type() const { return _type; } 950 uint8 length() const { return _length; } 951 952 uint16 volume_sequence_number() const { 953 return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); } 954 uint16 partition_number() const { 955 return B_LENDIAN_TO_HOST_INT16(_partition_number); } 956 957 void set_type(uint8 type) { _type = type; } 958 void set_length(uint8 length) { _length = length; } 959 void set_volume_sequence_number(uint16 number) { 960 _volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); } 961 void set_partition_number(uint16 number) { 962 _partition_number = B_HOST_TO_LENDIAN_INT16(number); } 963 private: 964 uint8 _type; 965 uint8 _length; 966 uint16 _volume_sequence_number; 967 uint16 _partition_number; 968 } __attribute__((packed)); 969 970 971 /* ----UDF Specific---- */ 972 /*! \brief Virtual partition map 973 974 Note that this map is a customization of the ECMA-167 975 type 2 partition map. 976 977 See also: UDF-2.01 2.2.8 978 */ 979 struct virtual_partition_map { 980 uint8 type; 981 uint8 length; 982 uint8 reserved1[2]; 983 984 /*! - flags: 0 985 - identifier: "*UDF Virtual Partition" 986 - identifier_suffix: per UDF-2.01 2.1.5.3 987 */ 988 entity_id partition_type_id; 989 uint16 volume_sequence_number; 990 991 /*! corresponding type 1 partition map in same logical volume 992 */ 993 uint16 partition_number; 994 uint8 reserved2[24]; 995 } __attribute__((packed)); 996 997 998 /*! \brief Maximum number of redundant sparing tables found in 999 sparable_partition_map structures. 1000 */ 1001 #define UDF_MAX_SPARING_TABLE_COUNT 4 1002 1003 /* ----UDF Specific---- */ 1004 /*! \brief Sparable partition map 1005 1006 Note that this map is a customization of the ECMA-167 1007 type 2 partition map. 1008 1009 See also: UDF-2.01 2.2.9 1010 */ 1011 struct sparable_partition_map { 1012 public: 1013 void dump(); 1014 1015 uint8 type() const { return _type; } 1016 uint8 length() const { return _length; } 1017 1018 entity_id& partition_type_id() { return _partition_type_id; } 1019 const entity_id& partition_type_id() const { return _partition_type_id; } 1020 1021 uint16 volume_sequence_number() const { 1022 return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); } 1023 uint16 partition_number() const { 1024 return B_LENDIAN_TO_HOST_INT16(_partition_number); } 1025 uint16 packet_length() const { 1026 return B_LENDIAN_TO_HOST_INT16(_packet_length); } 1027 uint8 sparing_table_count() const { return _sparing_table_count; } 1028 uint32 sparing_table_size() const { 1029 return B_LENDIAN_TO_HOST_INT32(_sparing_table_size); } 1030 uint32 sparing_table_location(uint8 index) const { 1031 return B_LENDIAN_TO_HOST_INT32(_sparing_table_locations[index]); } 1032 1033 1034 void set_type(uint8 type) { _type = type; } 1035 void set_length(uint8 length) { _length = length; } 1036 void set_volume_sequence_number(uint16 number) { 1037 _volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); } 1038 void set_partition_number(uint16 number) { 1039 _partition_number = B_HOST_TO_LENDIAN_INT16(number); } 1040 void set_packet_length(uint16 length) { 1041 _packet_length = B_HOST_TO_LENDIAN_INT16(length); } 1042 void set_sparing_table_count(uint8 count) { 1043 _sparing_table_count = count; } 1044 void set_sparing_table_size(uint32 size) { 1045 _sparing_table_size = B_HOST_TO_LENDIAN_INT32(size); } 1046 void set_sparing_table_location(uint8 index, uint32 location) { 1047 _sparing_table_locations[index] = B_HOST_TO_LENDIAN_INT32(location); } 1048 private: 1049 uint8 _type; 1050 uint8 _length; 1051 uint8 _reserved1[2]; 1052 1053 /*! - flags: 0 1054 - identifier: "*UDF Sparable Partition" 1055 - identifier_suffix: per UDF-2.01 2.1.5.3 1056 */ 1057 entity_id _partition_type_id; 1058 uint16 _volume_sequence_number; 1059 1060 //! partition number of corresponding partition descriptor 1061 uint16 _partition_number; 1062 uint16 _packet_length; 1063 uint8 _sparing_table_count; 1064 uint8 _reserved2; 1065 uint32 _sparing_table_size; 1066 uint32 _sparing_table_locations[UDF_MAX_SPARING_TABLE_COUNT]; 1067 } __attribute__((packed)); 1068 1069 1070 /* ----UDF Specific---- */ 1071 /*! \brief Metadata partition map 1072 1073 Note that this map is a customization of the ECMA-167 1074 type 2 partition map. 1075 1076 See also: UDF-2.50 2.2.10 1077 */ 1078 struct metadata_partition_map { 1079 uint8 type; 1080 uint8 length; 1081 uint8 reserved1[2]; 1082 1083 /*! - flags: 0 1084 - identifier: "*UDF Metadata Partition" 1085 - identifier_suffix: per UDF-2.50 2.1.5 1086 */ 1087 entity_id partition_type_id; 1088 uint16 volume_sequence_number; 1089 1090 /*! corresponding type 1 or type 2 sparable partition 1091 map in same logical volume 1092 */ 1093 uint16 partition_number; 1094 uint8 reserved2[24]; 1095 } __attribute__((packed)); 1096 1097 1098 /*! \brief Unallocated space descriptor 1099 1100 See also: ECMA-167 3/10.8 1101 */ 1102 struct unallocated_space_descriptor { 1103 void dump() const; 1104 1105 // Get functions 1106 const descriptor_tag & tag() const { return _tag; } 1107 descriptor_tag & tag() { return _tag; } 1108 uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); } 1109 uint32 allocation_descriptor_count() const { return B_LENDIAN_TO_HOST_INT32(_allocation_descriptor_count); } 1110 extent_address* allocation_descriptors() { return _allocation_descriptors; } 1111 1112 // Set functions 1113 void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); } 1114 void set_allocation_descriptor_count(uint32 count) { _allocation_descriptor_count = B_HOST_TO_LENDIAN_INT32(count); } 1115 private: 1116 descriptor_tag _tag; 1117 uint32 _vds_number; 1118 uint32 _allocation_descriptor_count; 1119 extent_address _allocation_descriptors[0]; 1120 } __attribute__((packed)); 1121 1122 1123 /*! \brief Terminating descriptor 1124 1125 See also: ECMA-167 3/10.9 1126 */ 1127 struct terminating_descriptor { 1128 void dump() const; 1129 1130 // Get functions 1131 const descriptor_tag & tag() const { return _tag; } 1132 descriptor_tag & tag() { return _tag; } 1133 1134 private: 1135 descriptor_tag _tag; 1136 uint8 _reserved[496]; 1137 } __attribute__((packed)); 1138 1139 1140 /*! \brief Logical volume integrity descriptor 1141 1142 See also: ECMA-167 3/10.10 1143 */ 1144 struct logical_volume_integrity_descriptor { 1145 descriptor_tag tag; 1146 timestamp recording_time; 1147 uint32 integrity_type; 1148 extent_address next_integrity_extent; 1149 array<uint8, 32> logical_volume_contents_use; 1150 uint32 partition_count; 1151 uint32 implementation_use_length; 1152 1153 /*! \todo double-check the pointer arithmetic here. */ 1154 uint32* free_space_table() { return (uint32*)(this+80); } 1155 uint32* size_table() { return (uint32*)(free_space_table()+partition_count*sizeof(uint32)); } 1156 uint8* implementation_use() { return (uint8*)(size_table()+partition_count*sizeof(uint32)); } 1157 1158 } __attribute__((packed)); 1159 1160 /*! \brief Logical volume integrity types 1161 */ 1162 enum { 1163 LVIT_OPEN = 1, 1164 LVIT_CLOSED, 1165 }; 1166 1167 //---------------------------------------------------------------------- 1168 // ECMA-167 Part 4 1169 //---------------------------------------------------------------------- 1170 1171 1172 1173 /*! \brief File set descriptor 1174 1175 Contains all the pertinent info about a file set (i.e. a hierarchy of files) 1176 1177 According to UDF-2.01, only one file set descriptor shall be recorded, 1178 except on WORM media, where the following rules apply: 1179 - Multiple file sets are allowed only on WORM media 1180 - The default file set shall be the one with highest value \c file_set_number field. 1181 - Only the default file set may be flagged as writeable. All others shall be 1182 flagged as "hard write protect". 1183 - No writeable file set may reference metadata structures which are referenced 1184 (directly or indirectly) by any other file set. Writeable file sets may, however, 1185 reference actual file data extents that are also referenced by other file sets. 1186 */ 1187 struct file_set_descriptor { 1188 void dump() const; 1189 1190 // Get functions 1191 const descriptor_tag & tag() const { return _tag; } 1192 descriptor_tag & tag() { return _tag; } 1193 1194 const timestamp& recording_date_and_time() const { return _recording_date_and_time; } 1195 timestamp& recording_date_and_time() { return _recording_date_and_time; } 1196 1197 uint16 interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_interchange_level); } 1198 uint16 max_interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_max_interchange_level); } 1199 uint32 character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_character_set_list); } 1200 uint32 max_character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_max_character_set_list); } 1201 uint32 file_set_number() const { return B_LENDIAN_TO_HOST_INT32(_file_set_number); } 1202 uint32 file_set_descriptor_number() const { return B_LENDIAN_TO_HOST_INT32(_file_set_descriptor_number); } 1203 1204 const charspec& logical_volume_id_character_set() const { return _logical_volume_id_character_set; } 1205 charspec& logical_volume_id_character_set() { return _logical_volume_id_character_set; } 1206 1207 const array<char, 128>& logical_volume_id() const { return _logical_volume_id; } 1208 array<char, 128>& logical_volume_id() { return _logical_volume_id; } 1209 1210 const array<char, 32>& file_set_id() const { return _file_set_id; } 1211 array<char, 32>& file_set_id() { return _file_set_id; } 1212 1213 const array<char, 32>& copyright_file_id() const { return _copyright_file_id; } 1214 array<char, 32>& copyright_file_id() { return _copyright_file_id; } 1215 1216 const array<char, 32>& abstract_file_id() const { return _abstract_file_id; } 1217 array<char, 32>& abstract_file_id() { return _abstract_file_id; } 1218 1219 const charspec& file_set_charspec() const { return _file_set_charspec; } 1220 charspec& file_set_charspec() { return _file_set_charspec; } 1221 1222 const long_address& root_directory_icb() const { return _root_directory_icb; } 1223 long_address& root_directory_icb() { return _root_directory_icb; } 1224 1225 const entity_id& domain_id() const { return _domain_id; } 1226 entity_id& domain_id() { return _domain_id; } 1227 1228 const long_address& next_extent() const { return _next_extent; } 1229 long_address& next_extent() { return _next_extent; } 1230 1231 const long_address& system_stream_directory_icb() const { return _system_stream_directory_icb; } 1232 long_address& system_stream_directory_icb() { return _system_stream_directory_icb; } 1233 1234 // Set functions 1235 void set_interchange_level(uint16 level) { _interchange_level = B_HOST_TO_LENDIAN_INT16(level); } 1236 void set_max_interchange_level(uint16 level) { _max_interchange_level = B_HOST_TO_LENDIAN_INT16(level); } 1237 void set_character_set_list(uint32 list) { _character_set_list = B_HOST_TO_LENDIAN_INT32(list); } 1238 void set_max_character_set_list(uint32 list) { _max_character_set_list = B_HOST_TO_LENDIAN_INT32(list); } 1239 void set_file_set_number(uint32 number) { _file_set_number = B_HOST_TO_LENDIAN_INT32(number); } 1240 void set_file_set_descriptor_number(uint32 number) { _file_set_descriptor_number = B_HOST_TO_LENDIAN_INT32(number); } 1241 private: 1242 descriptor_tag _tag; 1243 timestamp _recording_date_and_time; 1244 uint16 _interchange_level; //!< To be set to 3 (see UDF-2.01 2.3.2.1) 1245 uint16 _max_interchange_level; //!< To be set to 3 (see UDF-2.01 2.3.2.2) 1246 uint32 _character_set_list; 1247 uint32 _max_character_set_list; 1248 uint32 _file_set_number; 1249 uint32 _file_set_descriptor_number; 1250 charspec _logical_volume_id_character_set; //!< To be set to kCSOCharspec 1251 array<char, 128> _logical_volume_id; 1252 charspec _file_set_charspec; 1253 array<char, 32> _file_set_id; 1254 array<char, 32> _copyright_file_id; 1255 array<char, 32> _abstract_file_id; 1256 long_address _root_directory_icb; 1257 entity_id _domain_id; 1258 long_address _next_extent; 1259 long_address _system_stream_directory_icb; 1260 uint8 _reserved[32]; 1261 } __attribute__((packed)); 1262 1263 1264 /*! \brief Partition header descriptor 1265 1266 Contains references to unallocated and freed space data structures. 1267 1268 Note that unallocated space is space ready to be written with no 1269 preprocessing. Freed space is space needing preprocessing (i.e. 1270 a special write pass) before use. 1271 1272 Per UDF-2.01 2.3.3, the use of tables or bitmaps shall be consistent, 1273 i.e. only one type or the other shall be used, not both. 1274 1275 To indicate disuse of a certain field, the fields of the allocation 1276 descriptor shall all be set to 0. 1277 1278 See also: ECMA-167 4/14.3, UDF-2.01 2.2.3 1279 */ 1280 struct partition_header_descriptor { 1281 long_address unallocated_space_table; 1282 long_address unallocated_space_bitmap; 1283 /*! Unused, per UDF-2.01 2.2.3 */ 1284 long_address partition_integrity_table; 1285 long_address freed_space_table; 1286 long_address freed_space_bitmap; 1287 uint8 reserved[88]; 1288 } __attribute__((packed)); 1289 1290 #define kMaxFileIdSize (sizeof(file_id_descriptor)+512+3) 1291 1292 /*! \brief File identifier descriptor 1293 1294 Identifies the name of a file entry, and the location of its corresponding 1295 ICB. 1296 1297 See also: ECMA-167 4/14.4, UDF-2.01 2.3.4 1298 1299 \todo Check pointer arithmetic 1300 */ 1301 struct file_id_descriptor { 1302 public: 1303 void dump() const; 1304 1305 descriptor_tag & tag() { return _tag; } 1306 const descriptor_tag & tag() const { return _tag; } 1307 1308 uint16 version_number() const { return B_LENDIAN_TO_HOST_INT16(_version_number); } 1309 1310 uint8 characteristics() const { return _characteristics; } 1311 1312 bool may_be_hidden() const { 1313 characteristics_accessor c; 1314 c.all = characteristics(); 1315 return c.bits.may_be_hidden; 1316 } 1317 1318 bool is_directory() const { 1319 characteristics_accessor c; 1320 c.all = characteristics(); 1321 return c.bits.is_directory; 1322 } 1323 1324 bool is_deleted() const { 1325 characteristics_accessor c; 1326 c.all = characteristics(); 1327 return c.bits.is_deleted; 1328 } 1329 1330 bool is_parent() const { 1331 characteristics_accessor c; 1332 c.all = characteristics(); 1333 return c.bits.is_parent; 1334 } 1335 1336 bool is_metadata_stream() const { 1337 characteristics_accessor c; 1338 c.all = characteristics(); 1339 return c.bits.is_metadata_stream; 1340 } 1341 1342 uint8 id_length() const { return _id_length; } 1343 1344 long_address& icb() { return _icb; } 1345 const long_address& icb() const { return _icb; } 1346 1347 uint8 implementation_use_length() const { return _implementation_use_length; } 1348 1349 /*! If implementation_use_length is greater than 0, the first 32 1350 bytes of implementation_use() shall be an entity_id identifying 1351 the implementation that generated the rest of the data in the 1352 implementation_use() field. 1353 */ 1354 uint8* implementation_use() { return ((uint8*)this)+38; } 1355 char* id() { return ((char*)this)+38+implementation_use_length(); } 1356 const char* id() const { return ((const char*)this)+38+implementation_use_length(); } 1357 1358 uint16 structure_length() const { return 38 + id_length() + implementation_use_length(); } 1359 uint16 padding_length() const { return ((structure_length()+3)/4)*4 - structure_length(); } 1360 uint16 total_length() const { return structure_length() + padding_length(); } 1361 1362 // Set functions 1363 void set_version_number(uint16 number) { _version_number = B_HOST_TO_LENDIAN_INT16(number); } 1364 1365 void set_characteristics(uint8 characteristics) { _characteristics = characteristics; } 1366 1367 void set_may_be_hidden(bool how) { 1368 characteristics_accessor c; 1369 c.all = characteristics(); 1370 c.bits.may_be_hidden = how; 1371 set_characteristics(c.all); 1372 } 1373 1374 void set_is_directory(bool how) { 1375 characteristics_accessor c; 1376 c.all = characteristics(); 1377 c.bits.is_directory = how; 1378 set_characteristics(c.all); 1379 } 1380 1381 void set_is_deleted(bool how) { 1382 characteristics_accessor c; 1383 c.all = characteristics(); 1384 c.bits.is_deleted = how; 1385 set_characteristics(c.all); 1386 } 1387 1388 void set_is_parent(bool how) { 1389 characteristics_accessor c; 1390 c.all = characteristics(); 1391 c.bits.is_parent = how; 1392 set_characteristics(c.all); 1393 } 1394 1395 void set_is_metadata_stream(bool how) { 1396 characteristics_accessor c; 1397 c.all = characteristics(); 1398 c.bits.is_metadata_stream = how; 1399 set_characteristics(c.all); 1400 } 1401 1402 1403 void set_id_length(uint8 id_length) { _id_length = id_length; } 1404 void set_implementation_use_length(uint8 implementation_use_length) { _implementation_use_length = implementation_use_length; } 1405 1406 1407 1408 private: 1409 union characteristics_accessor { 1410 uint8 all; 1411 struct { 1412 uint8 may_be_hidden:1, 1413 is_directory:1, 1414 is_deleted:1, 1415 is_parent:1, 1416 is_metadata_stream:1, 1417 reserved_characteristics:3; 1418 } bits; 1419 }; 1420 1421 descriptor_tag _tag; 1422 /*! According to ECMA-167: 1 <= valid version_number <= 32767, 32768 <= reserved <= 65535. 1423 1424 However, according to UDF-2.01, there shall be exactly one version of 1425 a file, and it shall be 1. 1426 */ 1427 uint16 _version_number; 1428 /*! \todo Check UDF-2.01 2.3.4.2 for some more restrictions. */ 1429 uint8 _characteristics; 1430 uint8 _id_length; 1431 long_address _icb; 1432 uint8 _implementation_use_length; 1433 } __attribute__((packed)); 1434 1435 1436 /*! \brief Allocation extent descriptor 1437 1438 See also: ECMA-167 4/14.5 1439 */ 1440 struct allocation_extent_descriptor { 1441 descriptor_tag tag; 1442 uint32 previous_allocation_extent_location; 1443 uint32 length_of_allocation_descriptors; 1444 1445 /*! \todo Check that this is really how things work: */ 1446 uint8* allocation_descriptors() { return (uint8*)(this+sizeof(allocation_extent_descriptor)); } 1447 } __attribute__((packed)); 1448 1449 1450 /*! \brief icb_tag::file_type values 1451 1452 See also ECMA-167 4/14.6.6 1453 */ 1454 enum icb_file_types { 1455 ICB_TYPE_UNSPECIFIED = 0, 1456 ICB_TYPE_UNALLOCATED_SPACE_ENTRY, 1457 ICB_TYPE_PARTITION_INTEGRITY_ENTRY, 1458 ICB_TYPE_INDIRECT_ENTRY, 1459 ICB_TYPE_DIRECTORY, 1460 ICB_TYPE_REGULAR_FILE, 1461 ICB_TYPE_BLOCK_SPECIAL_DEVICE, 1462 ICB_TYPE_CHARACTER_SPECIAL_DEVICE, 1463 ICB_TYPE_EXTENDED_ATTRIBUTES_FILE, 1464 ICB_TYPE_FIFO, 1465 ICB_TYPE_ISSOCK, 1466 ICB_TYPE_TERMINAL, 1467 ICB_TYPE_SYMLINK, 1468 ICB_TYPE_STREAM_DIRECTORY, 1469 1470 ICB_TYPE_RESERVED_START = 14, 1471 ICB_TYPE_RESERVED_END = 247, 1472 1473 ICB_TYPE_CUSTOM_START = 248, 1474 ICB_TYPE_CUSTOM_END = 255, 1475 }; 1476 1477 /*! \brief idb_entry_tag::_flags::descriptor_flags() values 1478 1479 See also ECMA-167 4/14.6.8 1480 */ 1481 enum icb_descriptor_types { 1482 ICB_DESCRIPTOR_TYPE_SHORT = 0, 1483 ICB_DESCRIPTOR_TYPE_LONG, 1484 ICB_DESCRIPTOR_TYPE_EXTENDED, 1485 ICB_DESCRIPTOR_TYPE_EMBEDDED, 1486 }; 1487 1488 /*! \brief ICB entry tag 1489 1490 Common tag found in all ICB entries (in addition to, and immediately following, 1491 the descriptor tag). 1492 1493 See also: ECMA-167 4/14.6, UDF-2.01 2.3.5 1494 */ 1495 struct icb_entry_tag { 1496 private: 1497 union flags_accessor { 1498 uint16 all_flags; 1499 struct { 1500 uint16 descriptor_flags:3, 1501 if_directory_then_sort:1, //!< To be set to 0 per UDF-2.01 2.3.5.4 1502 non_relocatable:1, 1503 archive:1, 1504 setuid:1, 1505 setgid:1, 1506 sticky:1, 1507 contiguous:1, 1508 system:1, 1509 transformed:1, 1510 multi_version:1, //!< To be set to 0 per UDF-2.01 2.3.5.4 1511 is_stream:1, 1512 reserved_icb_entry_flags:2; 1513 } flags; 1514 }; 1515 1516 public: 1517 void dump() const; 1518 1519 uint32 prior_recorded_number_of_direct_entries() const { return B_LENDIAN_TO_HOST_INT32(_prior_recorded_number_of_direct_entries); } 1520 uint16 strategy_type() const { return B_LENDIAN_TO_HOST_INT16(_strategy_type); } 1521 1522 array<uint8, 2>& strategy_parameters() { return _strategy_parameters; } 1523 const array<uint8, 2>& strategy_parameters() const { return _strategy_parameters; } 1524 1525 uint16 entry_count() const { return B_LENDIAN_TO_HOST_INT16(_entry_count); } 1526 uint8 file_type() const { return _file_type; } 1527 logical_block_address& parent_icb_location() { return _parent_icb_location; } 1528 const logical_block_address& parent_icb_location() const { return _parent_icb_location; } 1529 1530 uint16 flags() const { return B_LENDIAN_TO_HOST_INT16(_flags); } 1531 1532 // flags accessor functions 1533 uint8 descriptor_flags() const { 1534 flags_accessor f; 1535 f.all_flags = flags(); 1536 return f.flags.descriptor_flags; 1537 } 1538 1539 void set_prior_recorded_number_of_direct_entries(uint32 entries) { _prior_recorded_number_of_direct_entries = B_LENDIAN_TO_HOST_INT32(entries); } 1540 void set_strategy_type(uint16 type) { _strategy_type = B_HOST_TO_LENDIAN_INT16(type); } 1541 1542 void set_entry_count(uint16 count) { _entry_count = B_LENDIAN_TO_HOST_INT16(count); } 1543 void set_file_type(uint8 type) { _file_type = type; } 1544 1545 void set_flags(uint16 flags) { _flags = B_LENDIAN_TO_HOST_INT16(flags); } 1546 1547 private: 1548 uint32 _prior_recorded_number_of_direct_entries; 1549 /*! Per UDF-2.01 2.3.5.1, only strategy types 4 and 4096 shall be supported. 1550 1551 \todo Describe strategy types here. 1552 */ 1553 uint16 _strategy_type; 1554 array<uint8, 2> _strategy_parameters; 1555 uint16 _entry_count; 1556 uint8 _reserved; 1557 /*! \brief icb_file_type value identifying the type of this icb entry */ 1558 uint8 _file_type; 1559 logical_block_address _parent_icb_location; 1560 uint16 _flags; 1561 } __attribute__((packed)); 1562 1563 /*! \brief Header portion of an ICB entry. 1564 */ 1565 struct icb_header { 1566 public: 1567 void dump() const; 1568 1569 descriptor_tag &tag() { return _tag; } 1570 const descriptor_tag &tag() const { return _tag; } 1571 1572 icb_entry_tag &icb_tag() { return _icb_tag; } 1573 const icb_entry_tag &icb_tag() const { return _icb_tag; } 1574 private: 1575 descriptor_tag _tag; 1576 icb_entry_tag _icb_tag; 1577 }; 1578 1579 /*! \brief Indirect ICB entry 1580 */ 1581 struct indirect_icb_entry { 1582 descriptor_tag tag; 1583 icb_entry_tag icb_tag; 1584 long_address indirect_icb; 1585 } __attribute__((packed)); 1586 1587 1588 /*! \brief Terminal ICB entry 1589 */ 1590 struct terminal_icb_entry { 1591 descriptor_tag tag; 1592 icb_entry_tag icb_tag; 1593 } __attribute__((packed)); 1594 1595 1596 /*! \brief File ICB entry 1597 1598 See also: ECMA-167 4/14.9 1599 1600 \todo Check pointer math. 1601 */ 1602 struct file_icb_entry { 1603 // get functions 1604 descriptor_tag & tag() { return _tag; } 1605 const descriptor_tag & tag() const { return _tag; } 1606 1607 icb_entry_tag& icb_tag() { return _icb_tag; } 1608 const icb_entry_tag& icb_tag() const { return _icb_tag; } 1609 1610 uint32 uid() { return B_LENDIAN_TO_HOST_INT32(_uid); } 1611 uint32 gid() { return B_LENDIAN_TO_HOST_INT32(_gid); } 1612 uint32 permissions() { return B_LENDIAN_TO_HOST_INT32(_permissions); } 1613 uint16 file_link_count() { return B_LENDIAN_TO_HOST_INT16(_file_link_count); } 1614 uint8 record_format() { return _record_format; } 1615 uint8 record_display_attributes() { return _record_display_attributes; } 1616 uint8 record_length() { return _record_length; } 1617 uint64 information_length() { return B_LENDIAN_TO_HOST_INT64(_information_length); } 1618 uint64 logical_blocks_recorded() { return B_LENDIAN_TO_HOST_INT64(_logical_blocks_recorded); } 1619 1620 timestamp& access_date_and_time() { return _access_date_and_time; } 1621 const timestamp& access_date_and_time() const { return _access_date_and_time; } 1622 1623 timestamp& modification_date_and_time() { return _modification_date_and_time; } 1624 const timestamp& modification_date_and_time() const { return _modification_date_and_time; } 1625 1626 timestamp& attribute_date_and_time() { return _attribute_date_and_time; } 1627 const timestamp& attribute_date_and_time() const { return _attribute_date_and_time; } 1628 1629 uint32 checkpoint() { return B_LENDIAN_TO_HOST_INT32(_checkpoint); } 1630 1631 long_address& extended_attribute_icb() { return _extended_attribute_icb; } 1632 const long_address& extended_attribute_icb() const { return _extended_attribute_icb; } 1633 1634 entity_id& implementation_id() { return _implementation_id; } 1635 const entity_id& implementation_id() const { return _implementation_id; } 1636 1637 uint64 unique_id() { return B_LENDIAN_TO_HOST_INT64(_unique_id); } 1638 uint32 extended_attributes_length() { return B_LENDIAN_TO_HOST_INT32(_extended_attributes_length); } 1639 uint32 allocation_descriptors_length() { return B_LENDIAN_TO_HOST_INT32(_allocation_descriptors_length); } 1640 1641 uint8* extended_attributes() { return ((uint8*)(this))+sizeof(file_icb_entry); } 1642 uint8* allocation_descriptors() { return ((uint8*)(this))+sizeof(file_icb_entry)+extended_attributes_length(); } 1643 1644 // set functions 1645 void set_uid(uint32 uid) { _uid = B_HOST_TO_LENDIAN_INT32(uid); } 1646 void set_gid(uint32 gid) { _gid = B_HOST_TO_LENDIAN_INT32(gid); } 1647 void set_permissions(uint32 permissions) { _permissions = B_HOST_TO_LENDIAN_INT32(permissions); } 1648 1649 void set_file_link_count(uint16 count) { _file_link_count = B_HOST_TO_LENDIAN_INT16(count); } 1650 void set_record_format(uint8 format) { _record_format = format; } 1651 void set_record_display_attributes(uint8 attributes) { _record_display_attributes = attributes; } 1652 void set_record_length(uint8 length) { _record_length = length; } 1653 1654 void set_information_length(uint64 length) { _information_length = B_HOST_TO_LENDIAN_INT64(length); } 1655 void set_logical_blocks_recorded(uint64 blocks) { _logical_blocks_recorded = B_HOST_TO_LENDIAN_INT64(blocks); } 1656 1657 void set_checkpoint(uint32 checkpoint) { _checkpoint = B_HOST_TO_LENDIAN_INT32(checkpoint); } 1658 1659 void set_unique_id(uint64 id) { _unique_id = B_HOST_TO_LENDIAN_INT64(id); } 1660 1661 void set_extended_attributes_length(uint32 length) { _extended_attributes_length = B_HOST_TO_LENDIAN_INT32(length); } 1662 void set_allocation_descriptors_length(uint32 length) { _allocation_descriptors_length = B_HOST_TO_LENDIAN_INT32(length); } 1663 1664 private: 1665 descriptor_tag _tag; 1666 icb_entry_tag _icb_tag; 1667 uint32 _uid; 1668 uint32 _gid; 1669 /*! \todo List perms in comment and add handy union thingy */ 1670 uint32 _permissions; 1671 /*! Identifies the number of file identifier descriptors referencing 1672 this icb. 1673 */ 1674 uint16 _file_link_count; 1675 uint8 _record_format; //!< To be set to 0 per UDF-2.01 2.3.6.1 1676 uint8 _record_display_attributes; //!< To be set to 0 per UDF-2.01 2.3.6.2 1677 uint8 _record_length; //!< To be set to 0 per UDF-2.01 2.3.6.3 1678 uint64 _information_length; 1679 uint64 _logical_blocks_recorded; //!< To be 0 for files and dirs with embedded data 1680 timestamp _access_date_and_time; 1681 timestamp _modification_date_and_time; 1682 1683 // NOTE: data members following this point in the descriptor are in 1684 // different locations in extended file entries 1685 1686 timestamp _attribute_date_and_time; 1687 /*! \brief Initially 1, may be incremented upon user request. */ 1688 uint32 _checkpoint; 1689 long_address _extended_attribute_icb; 1690 entity_id _implementation_id; 1691 /*! \brief The unique id identifying this file entry 1692 1693 The id of the root directory of a file set shall be 0. 1694 1695 \todo Detail the system specific requirements for unique ids from UDF-2.01 1696 */ 1697 uint64 _unique_id; 1698 uint32 _extended_attributes_length; 1699 uint32 _allocation_descriptors_length; 1700 1701 }; 1702 1703 1704 /*! \brief Extended file ICB entry 1705 1706 See also: ECMA-167 4/14.17 1707 1708 \todo Check pointer math. 1709 */ 1710 struct extended_file_icb_entry { 1711 // get functions 1712 descriptor_tag & tag() { return _tag; } 1713 const descriptor_tag & tag() const { return _tag; } 1714 1715 icb_entry_tag& icb_tag() { return _icb_tag; } 1716 const icb_entry_tag& icb_tag() const { return _icb_tag; } 1717 1718 uint32 uid() { return B_LENDIAN_TO_HOST_INT32(_uid); } 1719 uint32 gid() { return B_LENDIAN_TO_HOST_INT32(_gid); } 1720 uint32 permissions() { return B_LENDIAN_TO_HOST_INT32(_permissions); } 1721 uint16 file_link_count() { return B_LENDIAN_TO_HOST_INT16(_file_link_count); } 1722 uint8 record_format() { return _record_format; } 1723 uint8 record_display_attributes() { return _record_display_attributes; } 1724 uint8 record_length() { return _record_length; } 1725 uint64 information_length() { return B_LENDIAN_TO_HOST_INT64(_information_length); } 1726 uint64 logical_blocks_recorded() { return B_LENDIAN_TO_HOST_INT64(_logical_blocks_recorded); } 1727 1728 timestamp& access_date_and_time() { return _access_date_and_time; } 1729 const timestamp& access_date_and_time() const { return _access_date_and_time; } 1730 1731 timestamp& modification_date_and_time() { return _modification_date_and_time; } 1732 const timestamp& modification_date_and_time() const { return _modification_date_and_time; } 1733 1734 timestamp& attribute_date_and_time() { return _attribute_date_and_time; } 1735 const timestamp& attribute_date_and_time() const { return _attribute_date_and_time; } 1736 1737 uint32 checkpoint() { return B_LENDIAN_TO_HOST_INT32(_checkpoint); } 1738 1739 long_address& extended_attribute_icb() { return _extended_attribute_icb; } 1740 const long_address& extended_attribute_icb() const { return _extended_attribute_icb; } 1741 1742 entity_id& implementation_id() { return _implementation_id; } 1743 const entity_id& implementation_id() const { return _implementation_id; } 1744 1745 uint64 unique_id() { return B_LENDIAN_TO_HOST_INT64(_unique_id); } 1746 uint32 extended_attributes_length() { return B_LENDIAN_TO_HOST_INT32(_extended_attributes_length); } 1747 uint32 allocation_descriptors_length() { return B_LENDIAN_TO_HOST_INT32(_allocation_descriptors_length); } 1748 1749 uint8* extended_attributes() { return (uint8*)(this+sizeof(*this)); } 1750 uint8* allocation_descriptors() { return (uint8*)(this+sizeof(*this)+extended_attributes_length()); } 1751 1752 // set functions 1753 void set_uid(uint32 uid) { _uid = B_HOST_TO_LENDIAN_INT32(uid); } 1754 void set_gid(uint32 gid) { _gid = B_HOST_TO_LENDIAN_INT32(gid); } 1755 void set_permissions(uint32 permissions) { _permissions = B_HOST_TO_LENDIAN_INT32(permissions); } 1756 1757 void set_file_link_count(uint16 count) { _file_link_count = B_HOST_TO_LENDIAN_INT16(count); } 1758 void set_record_format(uint8 format) { _record_format = format; } 1759 void set_record_display_attributes(uint8 attributes) { _record_display_attributes = attributes; } 1760 void set_record_length(uint8 length) { _record_length = length; } 1761 1762 void set_information_length(uint64 length) { _information_length = B_HOST_TO_LENDIAN_INT64(length); } 1763 void set_logical_blocks_recorded(uint64 blocks) { _logical_blocks_recorded = B_HOST_TO_LENDIAN_INT64(blocks); } 1764 1765 void set_checkpoint(uint32 checkpoint) { _checkpoint = B_HOST_TO_LENDIAN_INT32(checkpoint); } 1766 1767 void set_unique_id(uint64 id) { _unique_id = B_HOST_TO_LENDIAN_INT64(id); } 1768 1769 void set_extended_attributes_length(uint32 length) { _extended_attributes_length = B_HOST_TO_LENDIAN_INT32(length); } 1770 void set_allocation_descriptors_length(uint32 length) { _allocation_descriptors_length = B_HOST_TO_LENDIAN_INT32(length); } 1771 1772 private: 1773 descriptor_tag _tag; 1774 icb_entry_tag _icb_tag; 1775 uint32 _uid; 1776 uint32 _gid; 1777 /*! \todo List perms in comment and add handy union thingy */ 1778 uint32 _permissions; 1779 /*! Identifies the number of file identifier descriptors referencing 1780 this icb. 1781 */ 1782 uint16 _file_link_count; 1783 uint8 _record_format; //!< To be set to 0 per UDF-2.01 2.3.6.1 1784 uint8 _record_display_attributes; //!< To be set to 0 per UDF-2.01 2.3.6.2 1785 uint8 _record_length; //!< To be set to 0 per UDF-2.01 2.3.6.3 1786 uint64 _information_length; 1787 uint64 _logical_blocks_recorded; //!< To be 0 for files and dirs with embedded data 1788 timestamp _access_date_and_time; 1789 timestamp _modification_date_and_time; 1790 timestamp _creation_date_and_time; // <== EXTENDED FILE ENTRY ONLY 1791 timestamp _attribute_date_and_time; 1792 /*! \brief Initially 1, may be incremented upon user request. */ 1793 uint32 _checkpoint; 1794 uint32 _reserved; // <== EXTENDED FILE ENTRY ONLY 1795 long_address _extended_attribute_icb; 1796 long_address _stream_directory_icb; // <== EXTENDED FILE ENTRY ONLY 1797 entity_id _implementation_id; 1798 /*! \brief The unique id identifying this file entry 1799 1800 The id of the root directory of a file set shall be 0. 1801 1802 \todo Detail the system specific requirements for unique ids from UDF-2.01 3.2.1.1 1803 */ 1804 uint64 _unique_id; 1805 uint32 _extended_attributes_length; 1806 uint32 _allocation_descriptors_length; 1807 1808 }; 1809 1810 1811 }; // namespace Udf 1812 1813 #endif // _UDF_DISK_STRUCTURES_H 1814 1815