diff --git a/src/add-ons/kernel/file_systems/udf/DiskStructures.cpp b/src/add-ons/kernel/file_systems/udf/DiskStructures.cpp
index 47922dbff3..091a05547f 100644
--- a/src/add-ons/kernel/file_systems/udf/DiskStructures.cpp
+++ b/src/add-ons/kernel/file_systems/udf/DiskStructures.cpp
@@ -28,17 +28,26 @@ const charspec kCS0Charspec = { character_set_type: 0,
// udf_tag
//----------------------------------------------------------------------
-/*! \brief Calculates the tag's CRC and verifies the tag's location on
- the medium.
+/*! \brief Calculates the tag's CRC, verifies the tag's checksum, and
+ verifies the tag's location on the medium.
\todo Calc the CRC.
*/
status_t
descriptor_tag::init_check(off_t diskLocation)
{
- if (diskLocation == (off_t)location)
- return B_OK;
- else
- return B_NO_INIT;
+ status_t err = (diskLocation == (off_t)location) ? B_OK : B_NO_INIT;
+ // checksum
+ if (!err) {
+ uint32 sum = 0;
+ for (int i = 0; i <= 3; i++)
+ sum += ((uint8*)this)[i];
+ for (int i = 5; i <= 15; i++)
+ sum += ((uint8*)this)[i];
+ err = sum % 256 == checksum ? B_OK : B_NO_INIT;
+ }
+
+ return err;
+
}
diff --git a/src/add-ons/kernel/file_systems/udf/DiskStructures.h b/src/add-ons/kernel/file_systems/udf/DiskStructures.h
index 5fb0656cb5..b1c86c10a5 100644
--- a/src/add-ons/kernel/file_systems/udf/DiskStructures.h
+++ b/src/add-ons/kernel/file_systems/udf/DiskStructures.h
@@ -13,50 +13,25 @@
/*! \file DiskStructures.h
- UDF on-disk data structure declarations
+ \brief UDF on-disk data structure declarations
+
+ UDF is a specialization of the ECMA-167 standard. For the most part,
+ ECMA-167 structures are used by UDF with special restrictions. In a
+ few instances, UDF introduces its own structures to augment those
+ supplied by ECMA-167; those structures are clearly marked.
+
+ For UDF info: http://www.osta.org
+ For ECMA info: http://www.ecma-international.org
+
+ \todo Add in comments about max struct sizes from UDF-2.01
+
*/
namespace UDF {
-/*! \brief Header for volume structure descriptors
-
- Each descriptor consumes an entire block. All unused trailing
- bytes in the descriptor should be set to 0.
-
- The following descriptors contain no more information than
- that contained in the header:
-
- - BEA01:
- - type: 0
- - id: "BEA01"
- - version: 1
-
- - TEA01:
- - type: 0
- - id: "TEA01"
- - version: 1
-
- - NSR03:
- - type: 0
- - id: "NSR03"
- - version: 1
-*/
-struct vsd_header {
- uint8 type;
- char id[4];
- uint8 version;
-} __attribute__((packed));
-
-
-// Volume structure descriptor ids
-const char* kVSDID_BEA = "BEA01";
-const char* kVSDID_TEA = "TEA01";
-const char* kVSDID_BOOT = "BOOT2";
-const char* kVSDID_ISO = "CD001";
-const char* kVSDID_ECMA167_2 = "NSR02";
-const char* kVSDID_ECMA167_3 = "NSR03";
-const char* kVSDID_ECMA168 = "CDW02";
-
+//----------------------------------------------------------------------
+// ECMA-167 Part 1
+//----------------------------------------------------------------------
/*! \brief Character set specifications
@@ -96,16 +71,6 @@ struct timestamp {
} __attribute__((packed));
-/*! \brief Location and length of a contiguous chunk of data
-
- See also: ECMA 167 3/7.1
-*/
-struct extent_address {
- uint32 length;
- uint32 location;
-} __attribute__((packed));
-
-
/*! \brief Identifier used to designate the implementation responsible
for writing associated data structures on the medium.
@@ -118,17 +83,100 @@ struct entity_id {
} __attribute__((packed));
-/*! \brief Common tag found at the beginning of most udf descriptor structures
+//----------------------------------------------------------------------
+// ECMA-167 Part 2
+//----------------------------------------------------------------------
+
+
+/*! \brief Header for volume structure descriptors
+
+ Each descriptor consumes an entire block. All unused trailing
+ bytes in the descriptor should be set to 0.
+
+ The following descriptors contain no more information than
+ that contained in the header:
+
+ - BEA01:
+ - type: 0
+ - id: "BEA01"
+ - version: 1
+
+ - TEA01:
+ - type: 0
+ - id: "TEA01"
+ - version: 1
+
+ - NSR03:
+ - type: 0
+ - id: "NSR03"
+ - version: 1
+
+ See also: ECMA 167 2/9.1
+*/
+struct vsd_header {
+ uint8 type;
+ char id[4];
+ uint8 version;
+} __attribute__((packed));
+
+
+// Volume structure descriptor ids
+const char* kVSDID_BEA = "BEA01";
+const char* kVSDID_TEA = "TEA01";
+const char* kVSDID_BOOT = "BOOT2";
+const char* kVSDID_ISO = "CD001";
+const char* kVSDID_ECMA167_2 = "NSR02";
+const char* kVSDID_ECMA167_3 = "NSR03";
+const char* kVSDID_ECMA168 = "CDW02";
+
+
+//----------------------------------------------------------------------
+// ECMA-167 Part 3
+//----------------------------------------------------------------------
+
+
+/*! \brief Location and length of a contiguous chunk of data
+
+ See also: ECMA 167 3/7.1
+*/
+struct extent_address {
+ uint32 length;
+ uint32 location;
+} __attribute__((packed));
+
+
+/*! \brief Common tag found at the beginning of most udf descriptor structures.
+
+ For error checking, \c descriptor_tag structures have:
+ - The disk location of the tag redundantly stored in the tag itself
+ - A checksum value for the tag
+ - A CRC value and length
+
+ See also: ECMA 167 1/7.2, UDF 2.01 2.2.1, UDF 2.01 2.3.1
*/
struct descriptor_tag {
uint16 id;
uint16 version;
- uint8 checksum;
- uint8 reserved; // #00
+ uint8 checksum; //!< Sum modulo 256 of bytes 0-3 and 5-15 of this struct.
+ uint8 reserved; //!< Set to #00.
uint16 serial_number;
- uint16 crc;
+ uint16 crc; //!< May be 0 if \c crc_length field is 0.
+ /*! \brief Length of the data chunk used to calculate CRC.
+
+ If 0, no CRC was calculated, and the \c crc field must be 0.
+
+ According to UDF-2.01 2.3.1.2, the CRC shall be calculated for all descriptors
+ unless otherwise noted, and this field shall be set to:
+
+ (descriptor length) - (descriptor tag length)
+ */
uint16 crc_length;
- uint32 location; // address of udf_tag struct for error checking
+ /*! \brief Address of this tag within its partition (for error checking).
+
+ For virtually addressed structures (i.e. those accessed thru a VAT), this
+ shall be the virtual address, not the physical or logical address.
+ */
+ uint32 location;
status_t init_check(off_t diskLocation);
} __attribute__((packed));
@@ -165,7 +213,7 @@ enum {
TAGID_SPACE_BITMAP_DESCRIPTOR,
TAGID_PARTITION_INTEGRITY_ENTRY,
TAGID_EXTENDED_FILE_ENTRY,
-} udf_tag_id;
+} tag_id;
/*! \brief Primary volume descriptor
@@ -326,10 +374,14 @@ struct logical_vd {
*/
entity_id domain_id;
- /*! \brief For UDF, shall contain a \c long_address which identifies
- the location of the logical volume's first file set.
- */
- uint8 logical_volume_contents_use[16];
+ union {
+ /*! \brief For UDF, shall contain a \c long_allocation_descriptor which identifies
+ the location of the logical volume's first file set.
+ */
+ uint8 logical_volume_contents_use[16];
+ extent_address file_set_address;
+ };
+
uint32 map_table_length;
uint32 partition_map_count;
entity_id implementation_id;
@@ -345,13 +397,13 @@ struct logical_vd {
extent_address integrity_sequence_extent;
/*! \brief Restricted to maps of type 1 for normal maps and
- type 2 for virtual maps or maps on systems not supporting
+ UDF type 2 for virtual maps or maps on systems not supporting
defect management.
See UDF-2.01 2.2.8, 2.2.9
*/
uint8 partition_maps[0];
-};
+} __attribute__((packed));
/*! \brief Generic partition map
@@ -362,7 +414,8 @@ struct generic_partition_map {
uint8 type;
uint8 length;
uint8 map_data[0];
-};
+} __attribute__((packed));
+
/*! \brief Physical partition map (i.e. ECMA-167 Type 1 partition map)
@@ -373,8 +426,10 @@ struct physical_partition_map {
uint8 length;
uint16 volume_sequence_number;
uint16 partition_number;
-};
+} __attribute__((packed));
+
+/* ----UDF Specific---- */
/*! \brief Virtual partition map (i.e. UDF Type 2 partition map)
Note that this differs from the ECMA-167 type 2 partition map,
@@ -400,7 +455,8 @@ struct virtual_partition_map {
*/
uint16 partition_number;
uint8 reserved2[24];
-};
+} __attribute__((packed));
+
/*! \brief Unallocated space descriptor
@@ -451,6 +507,339 @@ enum {
LVIT_CLOSED,
};
+//----------------------------------------------------------------------
+// ECMA-167 Part 4
+//----------------------------------------------------------------------
+
+
+/*! \brief Location of a logical block within a logical volume.
+
+ See also: ECMA 167 4/7.1
+*/
+struct logical_block_address {
+ uint32 location; //!< Block location relative to start of corresponding partition
+ uint16 partition; //!< Numeric partition id within logical volume
+} __attribute__((packed));
+
+
+/*! \brief Allocation descriptor.
+
+ See also: ECMA 167 4/14.14.1
+*/
+struct short_allocation_descriptor {
+ uint32 length;
+ logical_block_address location;
+} __attribute__((packed));
+
+
+/*! \brief Allocation descriptor w/ 6 byte implementation use field.
+
+ See also: ECMA 167 4/14.14.2
+*/
+struct long_allocation_descriptor {
+ uint32 length;
+ logical_block_address location;
+ uchar implementation_use[6];
+} __attribute__((packed));
+
+
+/*! \brief File set descriptor
+
+ Contains all the pertinent info about a file set (i.e. a hierarchy of files)
+
+ According to UDF-2.01, only one file set descriptor shall be recorded,
+ except on WORM media, where the following rules apply:
+ - Multiple file sets are allowed only on WORM media
+ - The default file set shall be the one with highest value \c file_set_number field.
+ - Only the default file set may be flagged as writeable. All others shall be
+ flagged as "hard write protect".
+ - No writeable file set may reference metadata structures which are referenced
+ (directly or indirectly) by any other file set. Writeable file sets may, however,
+ reference actual file data extents that are also referenced by other file sets.
+*/
+struct file_set_descriptor {
+ descriptor_tag tag;
+ timestamp recording_date_and_time;
+ uint16 interchange_level; //!< To be set to 3 (see UDF-2.01 2.3.2.1)
+ uint16 max_interchange_level; //!< To be set to 3 (see UDF-2.01 2.3.2.2)
+ uint32 character_set_list;
+ uint32 max_character_set_list;
+ uint32 file_set_number;
+ uint32 file_set_descriptor_number;
+ charspec logical_volume_id_character_set; //!< To be set to kCSOCharspec
+ char logical_volume_id[128];
+ charspec file_set_charspec;
+ char file_set_id[32];
+ char copyright_file_id[32];
+ char abstract_file_id[32];
+ long_allocation_descriptor root_directory_icb;
+ entity_id domain_id;
+ long_allocation_descriptor next_extent;
+ long_allocation_descriptor system_stream_directory_icb;
+ uint8 reserved[32];
+} __attribute__((packed));
+
+
+/*! \brief Partition header descriptor
+
+ Contains references to unallocated and freed space data structures.
+
+ Note that unallocated space is space ready to be written with no
+ preprocessing. Freed space is space needing preprocessing (i.e.
+ a special write pass) before use.
+
+ Per UDF-2.01 2.3.3, the use of tables or bitmaps shall be consistent,
+ i.e. only one type or the other shall be used, not both.
+
+ To indicate disuse of a certain field, the fields of the allocation
+ descriptor shall all be set to 0.
+
+ See also: ECMA-167 4/14.3, UDF-2.01 2.2.3
+*/
+struct partition_header_descriptor {
+ short_allocation_descriptor unallocated_space_table;
+ short_allocation_descriptor unallocated_space_bitmap;
+ /*! Unused, per UDF-2.01 2.2.3 */
+ short_allocation_descriptor partition_integrity_table;
+ short_allocation_descriptor freed_space_table;
+ short_allocation_descriptor freed_space_bitmap;
+ uint8 reserved[88];
+} __attribute__((packed));
+
+
+/*! \brief File identifier descriptor
+
+ Identifies the name of a file entry, and the location of its corresponding
+ ICB.
+
+ See also: ECMA-167 4/14.4, UDF-2.01 2.3.4
+
+ \todo Check pointer arithmetic
+*/
+struct file_id_descriptor {
+ descriptor_tag tag;
+ /*! According to ECMA-167: 1 <= valid version_number <= 32767, 32768 <= reserved <= 65535.
+
+ However, according to UDF-2.01, there shall be exactly one version of
+ a file, and it shall be 1.
+ */
+ uint16 version_number;
+ /*! \todo Check UDF-2.01 2.3.4.2 for some more restrictions. */
+ union {
+ uint8 characteristics;
+ uint8 may_be_hidden:1,
+ is_directory:1,
+ is_deleted:1,
+ is_parent:1,
+ is_metadata_stream:1,
+ reserved_characteristics:3;
+ };
+ uint8 id_length;
+ long_allocation_descriptor icb;
+ uint8 implementation_use_length;
+
+ /*! If implementation_use_length is greater than 0, the first 32
+ bytes of implementation_use() shall be an entity_id identifying
+ the implementation that generated the rest of the data in the
+ implementation_use() field.
+ */
+ uint8* implementation_use() { return (uint8*)(this+38); }
+ char* id() { return (char*)(this+38+implementation_use_length); }
+
+} __attribute__((packed));
+
+
+/*! \brief Allocation extent descriptor
+
+ See also: ECMA-167 4/14.5
+*/
+struct allocation_extent_descriptor {
+ descriptor_tag tag;
+ uint32 previous_allocation_extent_location;
+ uint32 length_of_allocation_descriptors;
+
+ /*! \todo Check that this is really how things work: */
+ uint8* allocation_descriptors() { return (uint8*)(this+sizeof(allocation_extent_descriptor)); }
+} __attribute__((packed));
+
+
+/*! \brief icb_tag::file_type values
+
+ See also ECMA-167 4/14.6.6
+*/
+enum icb_file_types {
+ ICB_TYPE_UNSPECIFIED = 0,
+ ICB_TYPE_UNALLOCATED_SPACE_ENTRY,
+ ICB_TYPE_PARTITION_INTEGRITY_ENTRY,
+ ICB_TYPE_INDIRECT_ENTRY,
+ ICB_TYPE_DIRECTORY,
+ ICB_TYPE_REGULAR_FILE,
+ ICB_TYPE_BLOCK_SPECIAL_DEVICE,
+ ICB_TYPE_CHARACTER_SPECIAL_DEVICE,
+ ICB_TYPE_EXTENDED_ATTRIBUTES_FILE,
+ ICB_TYPE_FIFO,
+ ICB_TYPE_ISSOCK,
+ ICB_TYPE_TERMINAL,
+ ICB_TYPE_SYMLINK,
+ ICB_TYPE_STREAM_DIRECTORY,
+
+ ICB_TYPE_RESERVED_START = 14,
+ ICB_TYPE_RESERVED_END = 247,
+
+ ICB_TYPE_CUSTOM_START = 248,
+ ICB_TYPE_CUSTOM_END = 255,
+};
+
+
+/*! \brief ICB entry tag
+
+ Common tag found in all ICB entries (in addition to, and immediately following,
+ the descriptor tag).
+
+ See also: ECMA-167 4/14.6, UDF-2.01 2.3.5
+*/
+struct icb_entry_tag {
+ uint32 prior_recorded_number_of_direct_entries;
+ /*! Per UDF-2.01 2.3.5.1, only strategy types 4 and 4096 shall be supported.
+
+ \todo Describe strategy types here.
+ */
+ uint16 strategy_type;
+ uint8 strategy_parameters[2];
+ uint16 entry_count;
+ uint8 reserved;
+ /*! \brief icb_file_type value identifying the type of this icb entry */
+ uint8 file_type;
+ logical_block_address parent_icb_location;
+ union {
+ uint16 flags;
+ uint16 descriptor_flags:3,
+ if_directory_then_sort:1, //!< To be set to 0 per UDF-2.01 2.3.5.4
+ non_relocatable:1,
+ archive:1,
+ setuid:1,
+ setgid:1,
+ sticky:1,
+ contiguous:1,
+ system:1,
+ transformed:1,
+ multi_version:1, //!< To be set to 0 per UDF-2.01 2.3.5.4
+ is_stream:1,
+ reserved_icb_entry_flags:2;
+ };
+} __attribute__((packed));
+
+
+/*! \brief Indirect ICB entry
+*/
+struct indirect_icb_entry {
+ descriptor_tag tag;
+ icb_entry_tag icb_tag;
+ long_allocation_descriptor indirect_icb;
+} __attribute__((packed));
+
+
+/*! \brief Terminal ICB entry
+*/
+struct terminal_icb_entry {
+ descriptor_tag tag;
+ icb_entry_tag icb_tag;
+} __attribute__((packed));
+
+
+/*! \brief File ICB entry
+
+ See also: ECMA-167 4/14.9
+
+ \todo Check pointer math.
+*/
+struct file_icb_entry {
+ descriptor_tag tag;
+ icb_entry_tag icb_tag;
+ uint32 uid;
+ uint32 gid;
+ /*! \todo List perms in comment and add handy union thingy */
+ uint32 permissions;
+ /*! Identifies the number of file identifier descriptors referencing
+ this icb.
+ */
+ uint16 file_link_count;
+ uint8 record_format; //!< To be set to 0 per UDF-2.01 2.3.6.1
+ uint8 record_display_attributes; //!< To be set to 0 per UDF-2.01 2.3.6.2
+ uint8 record_length; //!< To be set to 0 per UDF-2.01 2.3.6.3
+ uint64 information_length;
+ uint64 logical_blocks_recorded; //!< To be 0 for files and dirs with embedded data
+ timestamp access_date_and_time;
+ timestamp modification_date_and_time;
+ timestamp attribute_date_and_time;
+ /*! \brief Initially 1, may be incremented upon user request. */
+ uint32 checkpoint;
+ long_allocation_descriptor extended_attribute_icb;
+ entity_id implementation_id;
+ /*! \brief The unique id identifying this file entry
+
+ The id of the root directory of a file set shall be 0.
+
+ \todo Detail the system specific requirements for unique ids from UDF-2.01
+ */
+ uint64 unique_id;
+ uint32 extended_attributes_length;
+ uint32 allocation_descriptors_length;
+
+ uint8* extended_attributes() { return (uint8*)(this+sizeof(file_icb_entry)); }
+ uint8* allocation_descriptors() { return (uint8*)(this+sizeof(file_icb_entry)+extended_attributes_length); }
+
+} __attribute__((packed));
+
+
+/*! \brief Extended file ICB entry
+
+ See also: ECMA-167 4/14.17
+
+ \todo Check pointer math.
+*/
+struct extended_file_icb_entry {
+ descriptor_tag tag;
+ icb_entry_tag icb_tag;
+ uint32 uid;
+ uint32 gid;
+ /*! \todo List perms in comment and add handy union thingy */
+ uint32 permissions;
+ /*! Identifies the number of file identifier descriptors referencing
+ this icb.
+ */
+ uint16 file_link_count;
+ uint8 record_format; //!< To be set to 0 per UDF-2.01 2.3.6.1
+ uint8 record_display_attributes; //!< To be set to 0 per UDF-2.01 2.3.6.2
+ uint8 record_length; //!< To be set to 0 per UDF-2.01 2.3.6.3
+ uint64 information_length;
+ uint64 logical_blocks_recorded; //!< To be 0 for files and dirs with embedded data
+ timestamp access_date_and_time;
+ timestamp modification_date_and_time;
+ timestamp creation_date_and_time;
+ timestamp attribute_date_and_time;
+ /*! \brief Initially 1, may be incremented upon user request. */
+ uint32 checkpoint;
+ uint32 reserved;
+ long_allocation_descriptor extended_attribute_icb;
+ long_allocation_descriptor stream_directory_icb;
+ entity_id implementation_id;
+ /*! \brief The unique id identifying this file entry
+
+ The id of the root directory of a file set shall be 0.
+
+ \todo Detail the system specific requirements for unique ids from UDF-2.01
+ */
+ uint64 unique_id;
+ uint32 extended_attributes_length;
+ uint32 allocation_descriptors_length;
+
+ uint8* extended_attributes() { return (uint8*)(this+sizeof(file_icb_entry)); }
+ uint8* allocation_descriptors() { return (uint8*)(this+sizeof(file_icb_entry)+extended_attributes_length); }
+
+} __attribute__((packed));
+
+
}; // namespace UDF
#endif // _UDF_DISK_STRUCTURES_H