Finished off the majority of the ECMA-167 Part 4 structures

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3179 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Tyler Dauwalder
2003-05-06 07:26:48 +00:00
parent 09c5682d91
commit edd2334c85
2 changed files with 469 additions and 71 deletions
@@ -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;
}
@@ -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: <a href='http://www.osta.org'>http://www.osta.org</a>
For ECMA info: <a href='http://www.ecma-international.org'>http://www.ecma-international.org</a>
\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:
<code>(descriptor length) - (descriptor tag length)</code>
*/
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