Source code for dfvfs.lib.ewf_helper

"""Helper functions for EWF image support."""

from dfvfs.lib import errors
from dfvfs.path import factory as path_spec_factory


[docs] def EWFGlobPathSpec(file_system, path_spec): """Globs for path specifications according to the EWF naming schema. Args: file_system (FileSystem): file system. path_spec (PathSpec): path specification. Returns: list[PathSpec]: path specifications that match the glob. Raises: PathSpecError: if the path specification is invalid. RuntimeError: if the maximum number of supported segment files is reached. """ if not path_spec.HasParent(): raise errors.PathSpecError("Unsupported path specification without parent.") parent_path_spec = path_spec.parent parent_location = getattr(parent_path_spec, "location", None) if not parent_location: raise errors.PathSpecError( "Unsupported parent path specification without location." ) parent_location, _, segment_extension = parent_location.rpartition(".") segment_extension_start = segment_extension[0] segment_extension_length = len(segment_extension) if ( segment_extension_length not in [3, 4] or not segment_extension.endswith("01") or ( segment_extension_length == 3 and segment_extension_start not in ["E", "e", "s"] ) or (segment_extension_length == 4 and not segment_extension.startswith("Ex")) ): raise errors.PathSpecError( ( f"Unsupported parent path specification invalid segment file " f"extension: {segment_extension:s}" ) ) segment_number = 1 segment_files = [] while True: segment_location = f"{parent_location:s}.{segment_extension:s}" # Note that we don't want to set the keyword arguments when not used # because the path specification base class will check for unused # keyword arguments and raise. kwargs = path_spec_factory.Factory.GetProperties(parent_path_spec) kwargs["location"] = segment_location if parent_path_spec.parent is not None: kwargs["parent"] = parent_path_spec.parent segment_path_spec = path_spec_factory.Factory.NewPathSpec( parent_path_spec.type_indicator, **kwargs ) if not file_system.FileEntryExistsByPathSpec(segment_path_spec): break segment_files.append(segment_path_spec) segment_number += 1 if segment_number <= 99: if segment_extension_length == 3: segment_extension = f"{segment_extension_start:s}{segment_number:02d}" elif segment_extension_length == 4: segment_extension = f"{segment_extension_start:s}x{segment_number:02d}" else: segment_index = segment_number - 100 if segment_extension_start in ["e", "s"]: letter_offset = ord("a") else: letter_offset = ord("A") segment_index, remainder = divmod(segment_index, 26) third_letter = chr(letter_offset + remainder) segment_index, remainder = divmod(segment_index, 26) second_letter = chr(letter_offset + remainder) first_letter = chr(ord(segment_extension_start) + segment_index) if first_letter in ["[", "{"]: raise RuntimeError("Unsupported number of segment files.") if segment_extension_length == 3: segment_extension = f"{first_letter:s}{second_letter:s}{third_letter:s}" elif segment_extension_length == 4: segment_extension = ( f"{first_letter:s}x{second_letter:s}{third_letter:s}" ) return segment_files