def __init__(self, data: bytes): super().__init__(data) #: Boot System Identifier (ID of the system capable of booting from this boot record) self.boot_system_identifier: str = unpack_str_a(data[7:39]) #: Boot Identifier (Identification the the boot system defined in the rest of this descriptor) self.boot_identifier: str = unpack_str_a(data[39:71]) #: Boot System Use (Data used by the boot system) self.boot_system_use: bytes = data[71:2048]
def __init__(self, data: bytes): super().__init__(data) #: Unused Field (Always 0x00) self.unused_1: int = data[7] if self.unused_1 != 0x00: raise InvalidISOException( f"Unused field at index 7 should always be 0x00. Instead it is {hex(self.unused_1)}." ) #: The System Identifier self.system_identifier: str = unpack_str_a(data[8:40]) #: The Volume Identifier self.volume_identifier: str = unpack_str_d(data[40:72]) #: Volume Partition Location self.volume_partition_location: int = unpack_both_endian_i32( data[72:80]) #: Volume Partition Size self.volume_partition_size: int = unpack_both_endian_i32(data[80:88]) #: System Use self.system_use: bytes = data[88:2048]
def __init__(self, data: bytes): #: Directory Record Length self.length: int = unpack_u8(data[0:1]) #: Extended Attribute Record Length self.extended_attribute_record_length: int = unpack_u8(data[1:2]) #: Location of LBA LSB&MSB self.lba_location: int = unpack_both_endian_u32(data[2:10]) #: Data Length LSB&MSB self.data_length: int = unpack_both_endian_u32(data[10:18]) #: Recording Date and Time self.recording_datetime: datetime = unpack_directory_record_datetime( data[18:25]) #: File Flags self.file_flags: FileFlags = FileFlags(data[25]) #: File Unit Size self.file_unit_size: int = unpack_u8(data[26:27]) #: Interleave gap size for files recorded in interleaved mode, 0x00 otherwise self.interleave_gap: int = unpack_u8(data[27:28]) #: Volume Sequence Number (Number of Disk this is recorded on) LSB & MSB self.volume_sequence_number: int = unpack_both_endian_u16(data[28:32]) #: File Identifier Length (File Name) self.file_identifier_length: int = unpack_u8(data[32:33]) file_identifier_end_offset: int = 33 + self.file_identifier_length #: File Identifier self.file_identifier: str = unpack_str_a( data[33:33 + self.file_identifier_length]) #: Padding (None if file identifier length even, the field does not exist in that case) self.padding: int if self.file_identifier_length % 2 == 0 or self.file_identifier == b'\x00'.decode( 'ASCII'): self.padding = None else: self.padding = data[file_identifier_end_offset] if self.padding is not None and self.padding != 0x00: raise InvalidISOException( "Directory Record Padding is {hex(self.padding)} instead of 0x00 or None" )
def __init__(self, data: bytes): self.data: bytes = data self.descriptor_type: DescriptorType = DescriptorType(self.data[0]) self.standard_identifier: str = unpack_str_a(self.data[1:6]) self.version: int = self.data[6]
def __init__(self, data: bytes): super().__init__(data) #: Volume Flags self.volume_flags: VolumeFlags = VolumeFlags(data[7]) #: The System Identifier self.system_identifier: str = unpack_str_a(data[8:40]) #: The Volume Identifier self.volume_identifier: str = unpack_str_d(data[40:72]) #: Unused Field (8 x 0x00) self.unused_2: bytes = data[72:80] if self.unused_2 != bytes([0x00] * 8): raise InvalidISOException( f"Unused field at index 72 should always be 8 x 0x00. Instead it is {hexlify(self.unused_2)}." ) #: Volume Space Size (Number of Logical Blocks) LSB & MSB self.volume_space_size: int = unpack_both_endian_i32(data[80:88]) #: Escape Sequences self.escape_sequences: bytes = data[88:120] #: Volume Set Size (Number of Disks) LSB & MSB self.volume_set_size: int = unpack_both_endian_i16(data[120:124]) #: Volume Sequence Number (Number of this Disk) LSB & MSB self.volume_sequence_number: int = unpack_both_endian_i16( data[124:128]) #: Logical Block Size LSB & MSB self.logical_block_size: int = unpack_both_endian_i16(data[128:132]) #: Path Table Size LSB & MSB self.path_table_size: int = unpack_both_endian_i32(data[132:140]) #: Location of Type-L Path Table self.l_path_table_location: int = unpack_i32( data[140:144], endianess=Endianess.LITTLE_ENDIAN) #: Location of Optional Type-L Path Table self.optional_l_path_table_location: int = unpack_i32( data[144:148], endianess=Endianess.LITTLE_ENDIAN) #: Location of Type-M Path Table self.m_path_table_location: int = unpack_i32( data[148:152], endianess=Endianess.BIG_ENDIAN) #: Location of Optional Type-M Path Table self.optional_m_path_table_location: int = unpack_i32( data[152:156], endianess=Endianess.BIG_ENDIAN) #: The Root Directory Record self.root_directory_record: DirectoryRecord = DirectoryRecord( data[156:190]) #: Volume Set Identifier self.volume_set_identifier: str = unpack_str_d(data[190:318]) #: Publisher Identifier self.publisher_identifier: Optional[str] publisher_identifier_data: bytes = data[318:446] if publisher_identifier_data[0] == 0x5F: # If first byte is 0x5F, self.publisher_identifier contains file name of data in the root directory self.publisher_identifier = unpack_str_a( publisher_identifier_data[1:128]) elif publisher_identifier_data == bytes( [0x20] * 128) or publisher_identifier_data == bytes([0x00] * 128): # TODO: Remove this hack or see why it is used # If all bytes are 0x20, self.publisher_identifier is None since there is no data provided self.publisher_identifier = None else: raise InvalidISOException( f"Publisher Identifier data neither starts with 0x5F or is " f"128 x 0x20, instead it is: {hexlify(publisher_identifier_data)}." ) #: Data Preparer Identifier self.data_preparer_identifier: Optional[str] data_preparer_identifier_data: bytes = data[446:574] if data_preparer_identifier_data[0] == 0x5F: # If first byte is 0x5F, self.data_preparer_identifier contains file name of data in the root directory self.data_preparer_identifier = unpack_str_a( data_preparer_identifier_data[1:128]) elif data_preparer_identifier_data == bytes( [0x20] * 128) or data_preparer_identifier_data == bytes( [0x00] * 128): # TODO: Remove this hack or see why it is used # If all bytes are 0x20, self.data_preparer_identifier is None since there is no data provided self.data_preparer_identifier = None else: raise InvalidISOException( f"Data Preparer Identifier data neither starts with 0x5F or is " f"128 x 0x20, instead it is: {hexlify(data_preparer_identifier_data)}." ) #: Application Identifier self.application_identifier: Optional[str] application_identifier_data: bytes = data[574:702] if application_identifier_data[0] == 0x5F: # If first byte is 0x5F, self.application_identifier contains file name of data in the root directory self.application_identifier = unpack_str_a( application_identifier_data[1:128]) elif application_identifier_data == bytes( [0x20] * 128) or application_identifier_data == bytes( [0x00] * 128): # TODO: Remove this hack or see why it is used # If all bytes are 0x20, self.application_identifier is None since there is no data provided self.application_identifier = None else: raise InvalidISOException( f"Application Identifier data neither starts with 0x5F or is " f"128 x 0x20, instead it is: {hexlify(application_identifier_data)}." ) #: Copyright File Identifier self.copyright_file_identifier: Optional[str] copyright_file_identifier_data: bytes = data[702:740] if copyright_file_identifier_data == bytes([0x20] * 38): #: If all bytes are 0x20, self.copyright_file_identifier is None since there is no data provided self.copyright_file_identifier = None else: self.copyright_file_identifier = unpack_str_d( copyright_file_identifier_data) #: Abstract File Identifier self.abstract_file_identifier: Optional[str] abstract_file_identifier_data: bytes = data[740:776] if abstract_file_identifier_data == bytes([0x20] * 36): #: If all bytes are 0x20, self.abstract_file_identifier is None since there is no data provided self.abstract_file_identifier = None else: self.abstract_file_identifier = unpack_str_d( abstract_file_identifier_data) #: Copyright File Identifier self.bibliographic_file_identifier: Optional[str] bibliographic_file_identifier_data: bytes = data[776:813] if copyright_file_identifier_data == bytes([0x20] * 37): #: If all bytes are 0x20, self.bibliographic_file_identifier is None since there is no data provided self.bibliographic_file_identifier = None else: self.bibliographic_file_identifier = unpack_str_d( bibliographic_file_identifier_data) #: Volume Creation Date and Time self.volume_creation_datetime: datetime = unpack_iso_volume_datetime( data[813:830]) #: Volume Modification Date and Time self.volume_modification_datetime: datetime = unpack_iso_volume_datetime( data[830:847]) #: Volume Expiration Date and Time (when is the volume considered obsolete) #: If not specified, then the volume is never considered obsolete self.volume_expiration_datetime: datetime = unpack_iso_volume_datetime( data[847:864]) #: Volume Effective Date and Time (when may the volume start being used) #: If not specified, the volume may be used immediately self.volume_effective_datetime: datetime = unpack_iso_volume_datetime( data[864:881]) #: File structure version (always 0x01) self.file_structure_version: int = data[881] if self.file_structure_version != 0x01: raise InvalidISOException( f"File Structure Version is {self.file_structure_version} instead of 0x01." ) #: Unused field (always 0x00) self.unused_4: int = data[882] if self.unused_4 != 0x00: raise InvalidISOException( f"Unused field at index 882 should always be 0x00. Instead it is {hex(self.unused_4)}." ) #: Application Specific Data self.application_data: bytes = data[883:1395] #: Reserved by ISO self.reserved: bytes = data[1395:2048]
def __init__(self, data: bytes): #: Owner Identification (if 0 no owner identification specified) self.owner_id: int = unpack_both_endian_u16(data[0:4]) #: Group Identification (if 0 no group identification specified) self.group_id: int = unpack_both_endian_u16(data[4:8]) if xor(self.owner_id == 0, self.group_id == 0): raise InvalidISOException( f"If either group id, or owner id is zero, both have to be zero. " f"In this case owner={self.owner_id}, group={self.group_id}.") permissions: int = unpack_u16(data[8:10]) #: Permissions self.permission_flags: PermissionFlags = PermissionFlags(permissions) #: File Creation Date and Time self.file_creation_datetime: datetime = unpack_iso_volume_datetime( data[10:27]) #: File Modification Date and Time self.file_modification_datetime: datetime = unpack_iso_volume_datetime( data[27:44]) #: File Expiration Date and Time self.file_expiration_datetime: datetime = unpack_iso_volume_datetime( data[44:61]) #: File Effective Date and Time self.file_effective_datetime: datetime = unpack_iso_volume_datetime( data[61:78]) #: Record Format self.record_format: RecordFormat = RecordFormat(unpack_u8(data[78:79])) #: Record Attributes self.record_attributes: RecordAttribute = RecordAttribute( unpack_u8(data[79:80])) #: Record Length self.record_length: int = unpack_both_endian_u16(data[80:84]) if self.record_format == RecordFormat.NOT_SPECIFIED and self.record_length != 0: raise InvalidISOException( f"If record format is 0, record length has to be 0 too. Record length: {self.record_length}" ) #: System Identifier self.system_identifier: str = unpack_str_a(data[84:116]) #: System Used self.system_used: bytes = data[116:180] #: Extended Attribute Record Version (Always 0x01) self.extended_attribute_record_version: int = unpack_u8(data[180:181]) if self.extended_attribute_record_version != 0x01: raise InvalidISOException( f"Extended Attribute Record Version is {self.extended_attribute_record_version} instead of 0x01." ) #: Length of Escape Sequences self.escape_sequence_length: int = unpack_u8(data[181:182]) #: Reserved for Future Standardization self.reserved: bytes = data[182:246] if self.reserved != bytes([0x00] * 64): raise InvalidISOException( f"Reserved bytes should be all 0x00, instead they are: {hexlify(self.reserved)}" ) #: Length of Application Use self.application_use_length: int = unpack_both_endian_u16( data[246:250]) #: Application Use self.application_use: bytes = data[250:250 + self.application_use_length] #: Escape Sequences self.escape_sequences: bytes = \ data[250 + self.application_use_length: 250 + self.application_use_length + self.escape_sequence_length]