Beispiel #1
0
    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]
Beispiel #2
0
    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]
Beispiel #3
0
    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"
            )
Beispiel #4
0
    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]
Beispiel #5
0
    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]