diff --git a/src/add-ons/kernel/file_systems/udf/DiskStructures.cpp b/src/add-ons/kernel/file_systems/udf/DiskStructures.cpp index 6fabf74f96..673e869270 100644 --- a/src/add-ons/kernel/file_systems/udf/DiskStructures.cpp +++ b/src/add-ons/kernel/file_systems/udf/DiskStructures.cpp @@ -20,11 +20,11 @@ using namespace UDF; // Constants //---------------------------------------------------------------------- -const charspec kCS0Charspec = { character_set_type: 0, - character_set_info: "OSTA Compressed Unicode" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - }; +//const charspec kCS0Charspec = { fCharacterSetType: 0, +// fCharacterSetInfo: "OSTA Compressed Unicode" +// "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" +// "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" +// }; // Volume structure descriptor ids const char* UDF::kVSDID_BEA = "BEA01"; @@ -47,19 +47,98 @@ volume_structure_descriptor_header::id_matches(const char *id) return strncmp(this->id, id, 5) == 0; } + +//---------------------------------------------------------------------- +// charspec +//---------------------------------------------------------------------- + +void +charspec::dump() +{ + DUMP_INIT(CF_PUBLIC | CF_DUMP, "extent_address"); + PRINT(("character_set_type: %d\n", character_set_type())); + PRINT(("character_set_info: `%s'\n", character_set_info())); +} + + +//---------------------------------------------------------------------- +// timestamp +//---------------------------------------------------------------------- + +void +timestamp::dump() +{ + DUMP_INIT(CF_PUBLIC | CF_DUMP, "timestamp"); + PRINT(("type: %d\n", type())); + PRINT(("timezone: %d\n", timezone())); + PRINT(("year: %d\n", year())); + PRINT(("month: %d\n", month())); + PRINT(("day: %d\n", day())); + PRINT(("hour: %d\n", hour())); + PRINT(("minute: %d\n", minute())); + PRINT(("second: %d\n", second())); + PRINT(("centisecond: %d\n", centisecond())); + PRINT(("hundred_microsecond: %d\n", hundred_microsecond())); + PRINT(("microsecond: %d\n", microsecond())); +} + +//---------------------------------------------------------------------- +// entity_id +//---------------------------------------------------------------------- + +void +entity_id::dump() +{ + DUMP_INIT(CF_PUBLIC | CF_DUMP, "entity_id"); + PRINT(("flags: %d\n", flags())); + PRINT(("identifier: `%s'\n", identifier())); + PRINT(("identifier_suffix: `%s'\n", identifier_suffix())); +} + + +//---------------------------------------------------------------------- +// extent_address +//---------------------------------------------------------------------- + +void +extent_address::dump() +{ + DUMP_INIT(CF_PUBLIC | CF_DUMP, "extent_address"); + PRINT(("length: %ld\n", length())); + PRINT(("location: %ld\n", location())); +} + + //---------------------------------------------------------------------- // udf_tag //---------------------------------------------------------------------- +void +descriptor_tag::dump() +{ + DUMP_INIT(CF_PUBLIC | CF_VOLUME_OPS | CF_DUMP, "descriptor_tag"); + PRINT(("id: %d\n", id())); + PRINT(("version: %d\n", version())); + PRINT(("checksum: %d\n", checksum())); + PRINT(("serial_number: %d\n", serial_number())); + PRINT(("crc: %d\n", crc())); + PRINT(("crc_length: %d\n", crc_length())); + PRINT(("location: %ld\n", location())); +} + + /*! \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) +descriptor_tag::init_check(uint32 diskBlock) { - status_t err = (diskLocation == (off_t)location) ? B_OK : B_NO_INIT; + DEBUG_INIT(CF_PUBLIC | CF_VOLUME_OPS, "descriptor_tag"); + PRINT(("diskLocation == %ld\n", diskBlock)); + PRINT(("location() == %ld\n", location())); + status_t err = (diskBlock == location()) ? B_OK : B_NO_INIT; // checksum if (!err) { uint32 sum = 0; @@ -67,10 +146,51 @@ descriptor_tag::init_check(off_t diskLocation) sum += ((uint8*)this)[i]; for (int i = 5; i <= 15; i++) sum += ((uint8*)this)[i]; - err = sum % 256 == checksum ? B_OK : B_NO_INIT; + err = sum % 256 == checksum() ? B_OK : B_NO_INIT; } - return err; + RETURN(err); } +//---------------------------------------------------------------------- +// primary_vd +//---------------------------------------------------------------------- + +void +primary_vd::dump() +{ + DUMP_INIT(CF_PUBLIC | CF_VOLUME_OPS | CF_DUMP, "primary_vd"); + PRINT(("tag:\n")); + tag().dump(); + PRINT(("volume_descriptor_sequence_number: %ld\n", volume_descriptor_sequence_number())); + PRINT(("primary_volume_descriptor_number: %ld\n", primary_volume_descriptor_number())); + PRINT(("volume_identifier: `%s'\n", volume_identifier())); + PRINT(("volume_sequence_number: %d\n", volume_sequence_number())); + PRINT(("max_volume_sequence_number: %d\n", max_volume_sequence_number())); + PRINT(("interchange_level: %d\n", interchange_level())); + PRINT(("max_interchange_level: %d\n", max_interchange_level())); + PRINT(("character_set_list: %ld\n", character_set_list())); + PRINT(("max_character_set_list: %ld\n", max_character_set_list())); + PRINT(("volume_set_identifier: `%s'\n", volume_set_identifier())); + PRINT(("descriptor_character_set:\n")); + descriptor_character_set().dump(); + PRINT(("explanatory_character_set:\n")); + explanatory_character_set().dump(); + PRINT(("volume_abstract:\n")); + volume_abstract().dump(); + PRINT(("volume_copyright_notice:\n")); + volume_copyright_notice().dump(); + PRINT(("application_id:\n")); + application_id().dump(); + PRINT(("recording_date_and_time:\n")); + recording_date_and_time().dump(); + PRINT(("implementation_id:\n")); + implementation_id().dump(); + PRINT(("implementation_use:\n")); +// for (int i = 0; i < 64/4; i++) { +// SIMPLE_PRINT(("%.2x,", implementation_use()[i])); +// if (i % 16 == 0) +// SIMPLE_PRINT(("\n")); +// } +} diff --git a/src/add-ons/kernel/file_systems/udf/DiskStructures.h b/src/add-ons/kernel/file_systems/udf/DiskStructures.h index 71d77130d0..aaf9aba1f6 100644 --- a/src/add-ons/kernel/file_systems/udf/DiskStructures.h +++ b/src/add-ons/kernel/file_systems/udf/DiskStructures.h @@ -7,9 +7,13 @@ #ifndef _UDF_DISK_STRUCTURES_H #define _UDF_DISK_STRUCTURES_H +#include + +#include #include #include "cpp.h" +#include "UdfDebug.h" /*! \file DiskStructures.h @@ -23,7 +27,7 @@ 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 + \todo Add in comments about max struct sizes from UDF-2.01 5.1 */ @@ -40,9 +44,18 @@ namespace UDF { See also: ECMA 167 1/7.2.1, UDF-2.01 2.1.2 */ -struct charspec { - uint8 character_set_type; //!< to be set to 0 to indicate CS0 - char character_set_info[63]; //!< "OSTA Compressed Unicode" +class charspec { +public: + void dump(); + + uint8 character_set_type() const { return _character_set_type; } + const char* character_set_info() const { return _character_set_info; } + char* character_set_info() { return _character_set_info; } + + void set_character_set_type(uint8 type) { _character_set_type = type; } +private: + uint8 _character_set_type; //!< to be set to 0 to indicate CS0 + char _character_set_info[63]; //!< "OSTA Compressed Unicode" } __attribute__((packed)); @@ -52,22 +65,79 @@ extern const charspec kCS0Charspec; /*! \brief Date and time stamp See also: ECMA 167 1/7.3, UDF-2.01 2.1.4 + + \todo Check neat-o bitmasking trick endianness */ -struct timestamp { - union { +class timestamp { +private: + union type_and_timezone_accessor { uint16 type_and_timezone; - uint16 type:4, - timezone:12; + struct { + uint16 timezone:12, + type:4; + } bits; }; - uint16 year; - uint8 month; - uint8 day; - uint8 hour; - uint8 minute; - uint8 second; - uint8 centisecond; - uint8 hundred_microsecond; - uint8 microsecond; + +public: + void dump(); + + // Get functions + uint16 type_and_timezone() const { return B_LENDIAN_TO_HOST_INT16(_type_and_timezone); } + uint8 type() const { + type_and_timezone_accessor t; + t.type_and_timezone = type_and_timezone(); + return t.bits.type; + } + uint16 timezone() const { + type_and_timezone_accessor t; + t.type_and_timezone = type_and_timezone(); + return t.bits.timezone; + } + uint16 year() const { return B_LENDIAN_TO_HOST_INT16(_year); } + uint8 month() const { return _month; } + uint8 day() const { return _day; } + uint8 hour() const { return _hour; } + uint8 minute() const { return _minute; } + uint8 second() const { return _second; } + uint8 centisecond() const { return _centisecond; } + uint8 hundred_microsecond() const { return _hundred_microsecond; } + uint8 microsecond() const { return _microsecond; } + + // Set functions + void set_type_and_timezone(uint16 type_and_timezone) { _type_and_timezone = B_HOST_TO_LENDIAN_INT16(type_and_timezone); } + void set_type(uint8 type) { + type_and_timezone_accessor t; + t.type_and_timezone = type_and_timezone(); + t.bits.type = type; + set_type_and_timezone(t.type_and_timezone); + } + void set_timezone(uint8 timezone) { + type_and_timezone_accessor t; + t.type_and_timezone = type_and_timezone(); + t.bits.timezone = timezone; + set_type_and_timezone(t.type_and_timezone); + } + void set_year(uint16 year) { _year = B_HOST_TO_LENDIAN_INT16(year); } + void set_month(uint8 month) { _month = month; } + void set_day(uint8 day) { _day = day; } + void set_hour(uint8 hour) { _hour = hour; } + void set_minute(uint8 minute) { _minute = minute; } + void set_second(uint8 second) { _second = second; } + void set_centisecond(uint8 centisecond) { _centisecond = centisecond; } + void set_hundred_microsecond(uint8 hundred_microsecond) { _hundred_microsecond = hundred_microsecond; } + void set_microsecond(uint8 microsecond) { _microsecond = microsecond; } +private: + uint16 _type_and_timezone; + uint16 _year; + uint8 _month; + uint8 _day; + uint8 _hour; + uint8 _minute; + uint8 _second; + uint8 _centisecond; + uint8 _hundred_microsecond; + uint8 _microsecond; + } __attribute__((packed)); @@ -77,9 +147,22 @@ struct timestamp { See also: ECMA 167 1/7.4, UDF 2.01 2.1.5 */ struct entity_id { - uint8 flags; - char identifier[23]; - char identifier_suffix[8]; +public: + void dump(); + + // Get functions + uint8 flags() const { return _flags; } + const char* identifier() const { return _identifier; } + char* identifier() { return _identifier; } + const char* identifier_suffix() const { return _identifier_suffix; } + char* identifier_suffix() { return _identifier_suffix; } + + // Set functions + void set_flags(uint8 flags) { _flags = flags; } +private: + uint8 _flags; + char _identifier[23]; + char _identifier_suffix[8]; } __attribute__((packed)); @@ -142,8 +225,17 @@ extern const char* kVSDID_ECMA168; See also: ECMA 167 3/7.1 */ struct extent_address { - uint32 length; - uint32 location; +public: + void dump(); + + uint32 length() { return B_LENDIAN_TO_HOST_INT32(_length); } + uint32 location() { return B_LENDIAN_TO_HOST_INT32(_location); } + + void set_length(int32 length) { _length = B_HOST_TO_LENDIAN_INT32(length); } + void set_location(int32 location) { _location = B_HOST_TO_LENDIAN_INT32(location); } +private: + uint32 _length; + uint32 _location; } __attribute__((packed)); @@ -157,12 +249,34 @@ struct extent_address { 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; //!< Sum modulo 256 of bytes 0-3 and 5-15 of this struct. - uint8 reserved; //!< Set to #00. - uint16 serial_number; - uint16 crc; //!< May be 0 if \c crc_length field is 0. +public: + void dump(); + + status_t init_check(uint32 diskBlock); + + uint16 id() { return B_LENDIAN_TO_HOST_INT16(_id); } + uint16 version() { return B_LENDIAN_TO_HOST_INT16(_version); } + uint8 checksum() { return _checksum; } + uint16 serial_number() { return B_LENDIAN_TO_HOST_INT16(_serial_number); } + uint16 crc() { return B_LENDIAN_TO_HOST_INT16(_crc); } + uint16 crc_length() { return B_LENDIAN_TO_HOST_INT16(_crc_length); } + uint32 location() { return B_LENDIAN_TO_HOST_INT32(_location); } + + void set_id(uint16 id) { _id = B_HOST_TO_LENDIAN_INT16(id); } + void set_version(uint16 version) { _version = B_HOST_TO_LENDIAN_INT16(version); } + void set_checksum(uint8 checksum) { _checksum = checksum; } + void set_serial_number(uint16 serial_number) { _serial_number = B_HOST_TO_LENDIAN_INT16(serial_number); } + void set_crc(uint16 crc) { _crc = B_HOST_TO_LENDIAN_INT16(crc); } + void set_crc_length(uint16 crc_length) { _crc_length = B_HOST_TO_LENDIAN_INT16(crc_length); } + void set_location(uint32 location) { _location = B_HOST_TO_LENDIAN_INT32(location); } + +private: + uint16 _id; + uint16 _version; + 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; //!< 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. @@ -172,15 +286,14 @@ struct descriptor_tag { (descriptor length) - (descriptor tag length) */ - uint16 crc_length; + uint16 _crc_length; /*! \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; + uint32 _location; - status_t init_check(off_t diskLocation); } __attribute__((packed)); @@ -221,42 +334,115 @@ enum tag_id { /*! \brief Primary volume descriptor */ struct primary_vd { - descriptor_tag tag; - uint32 vds_number; - uint32 primary_volume_descriptor_number; - char volume_identifier[32]; - uint16 volume_sequence_number; - uint16 max_volume_sequence_number; - uint16 interchange_level; //!< to be set to 3 if part of multivolume set, 2 otherwise - uint16 max_interchange_level; //!< to be set to 3 unless otherwise directed by user - uint32 character_set_list; - uint32 max_character_set_list; - char volume_set_identifier[128]; +public: + void dump(); + + // Get functions + const descriptor_tag& tag() const { return _tag; } + descriptor_tag& tag() { return _tag; } + + uint32 volume_descriptor_sequence_number() const { return B_LENDIAN_TO_HOST_INT32(_volume_descriptor_sequence_number); } + uint32 primary_volume_descriptor_number() const { return B_LENDIAN_TO_HOST_INT32(_primary_volume_descriptor_number); } + + const char* volume_identifier() const { return _volume_identifier; } + char* volume_identifier() { return _volume_identifier; } + + uint16 volume_sequence_number() const { return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); } + uint16 max_volume_sequence_number() const { return B_LENDIAN_TO_HOST_INT16(_max_volume_sequence_number); } + uint16 interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_interchange_level); } + uint16 max_interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_max_interchange_level); } + uint32 character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_character_set_list); } + uint32 max_character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_max_character_set_list); } + + const char* volume_set_identifier() const { return _volume_set_identifier; } + char* volume_set_identifier() { return _volume_set_identifier; } + + const charspec& descriptor_character_set() const { return _descriptor_character_set; } + charspec& descriptor_character_set() { return _descriptor_character_set; } + + const charspec& explanatory_character_set() const { return _explanatory_character_set; } + charspec& explanatory_character_set() { return _explanatory_character_set; } + + const extent_address& volume_abstract() const { return _volume_abstract; } + extent_address& volume_abstract() { return _volume_abstract; } + const extent_address& volume_copyright_notice() const { return _volume_copyright_notice; } + extent_address& volume_copyright_notice() { return _volume_copyright_notice; } + + const entity_id& application_id() const { return _application_id; } + entity_id& application_id() { return _application_id; } + + const timestamp& recording_date_and_time() const { return _recording_date_and_time; } + timestamp& recording_date_and_time() { return _recording_date_and_time; } + + const entity_id& implementation_id() const { return _implementation_id; } + entity_id& implementation_id() { return _implementation_id; } + + const uint8* implementation_use() const { return _implementation_use; } + uint8* implementation_use() { return _implementation_use; } + + uint32 predecessor_volume_descriptor_sequence_location() const + { return B_LENDIAN_TO_HOST_INT32(_predecessor_volume_descriptor_sequence_location); } + uint16 flags() const { return B_LENDIAN_TO_HOST_INT16(_flags); } + + // Set functions + void set_volume_descriptor_sequence_number(uint32 number) + { _volume_descriptor_sequence_number = B_HOST_TO_LENDIAN_INT32(number); } + void set_primary_volume_descriptor_number(uint32 number) + { _primary_volume_descriptor_number = B_HOST_TO_LENDIAN_INT32(number); } + void set_volume_sequence_number(uint16 number) + { _volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); } + void set_max_volume_sequence_number(uint16 number) + { _max_volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); } + void set_interchange_level(uint16 level) + { _interchange_level = B_HOST_TO_LENDIAN_INT16(level); } + void set_max_interchange_level(uint16 level) + { _max_interchange_level = B_HOST_TO_LENDIAN_INT16(level); } + void set_character_set_list(uint32 list) + { _character_set_list = B_HOST_TO_LENDIAN_INT32(list); } + void set_max_character_set_list(uint32 list) + { _max_character_set_list = B_HOST_TO_LENDIAN_INT32(list); } + void set_predecessor_volume_descriptor_sequence_location(uint32 location) + { _predecessor_volume_descriptor_sequence_location = B_HOST_TO_LENDIAN_INT32(location); } + void set_flags(uint16 flags) + { _flags = B_HOST_TO_LENDIAN_INT16(flags); } + +private: + descriptor_tag _tag; + uint32 _volume_descriptor_sequence_number; + uint32 _primary_volume_descriptor_number; + char _volume_identifier[32]; + uint16 _volume_sequence_number; + uint16 _max_volume_sequence_number; + uint16 _interchange_level; //!< to be set to 3 if part of multivolume set, 2 otherwise + uint16 _max_interchange_level; //!< to be set to 3 unless otherwise directed by user + uint32 _character_set_list; + uint32 _max_character_set_list; + char _volume_set_identifier[128]; /*! \brief Identifies the character set for the \c volume_identifier and \c volume_set_identifier fields. To be set to CS0. */ - charspec descriptor_character_set; + charspec _descriptor_character_set; /*! \brief Identifies the character set used in the \c volume_abstract and \c volume_copyright_notice extents. To be set to CS0. */ - charspec explanatory_character_set; + charspec _explanatory_character_set; - extent_address volume_abstract; - extent_address volume_copyright_notice; + extent_address _volume_abstract; + extent_address _volume_copyright_notice; - entity_id application_id; - timestamp recording_data_and_time; - entity_id implementation_id; - char implementation_use[64]; - uint32 predecessor_vds_location; - uint16 flags; - char reserved[22]; + entity_id _application_id; + timestamp _recording_date_and_time; + entity_id _implementation_id; + uint8 _implementation_use[64]; + uint32 _predecessor_volume_descriptor_sequence_location; + uint16 _flags; + char _reserved[22]; } __attribute__((packed)); @@ -275,11 +461,16 @@ struct primary_vd { See also: ECMA 167 3/10.2, UDF-2.01 2.2.3 */ -struct anchor_vd_pointer { - descriptor_tag tag; - extent_address main_vds; //!< min length of 16 sectors - extent_address reserve_vds; //!< min length of 16 sectors - char reserved[480]; +struct anchor_volume_descriptor_pointer { +public: + descriptor_tag& tag() { return _tag; } + extent_address& main_vds() { return _main_vds; } + extent_address& reserve_vds() { return _reserve_vds; } +private: + descriptor_tag _tag; + extent_address _main_vds; //!< min length of 16 sectors + extent_address _reserve_vds; //!< min length of 16 sectors + char _reserved[480]; } __attribute__((packed)); @@ -320,10 +511,10 @@ struct partition_descriptor { */ union { uint16 partition_flags; - struct flags { + struct { uint16 allocated:1, reserved:15; - }; + } flags; }; uint16 partition_number; @@ -628,13 +819,15 @@ struct file_id_descriptor { 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 all_characteristics; + struct { + uint8 may_be_hidden:1, + is_directory:1, + is_deleted:1, + is_parent:1, + is_metadata_stream:1, + reserved_characteristics:3; + } characteristics; }; uint8 id_length; long_allocation_descriptor icb; @@ -714,20 +907,22 @@ struct icb_entry_tag { 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; + uint16 all_flags; + struct { + uint16 descriptor_flags:3, + if_directory_then_sort:1, //!< To be set to 0 per UDF-2.01 2.3.5.4 + non_relocatable:1, + archive:1, + setuid:1, + setgid:1, + sticky:1, + contiguous:1, + system:1, + transformed:1, + multi_version:1, //!< To be set to 0 per UDF-2.01 2.3.5.4 + is_stream:1, + reserved_icb_entry_flags:2; + } flags; }; } __attribute__((packed));