Source code for dfvfs.lib.tsk_partition

# -*- coding: utf-8 -*-
"""Helper functions for SleuthKit (TSK) partition support."""

import pytsk3


[docs] def GetTSKVsPartByPathSpec(tsk_volume, path_spec): """Retrieves the TSK volume system part object from the TSK volume object. Args: tsk_volume (pytsk3.Volume_Info): TSK volume information. path_spec (PathSpec): path specification. Returns: tuple: containing: pytsk3.TSK_VS_PART_INFO: TSK volume system part information or None on error. int: partition index or None if not available. """ location = getattr(path_spec, 'location', None) part_index = getattr(path_spec, 'part_index', None) start_offset = getattr(path_spec, 'start_offset', None) partition_index = None if part_index is None: if location is not None: if location.startswith('/p'): try: partition_index = int(location[2:], 10) - 1 except ValueError: pass if partition_index is None or partition_index < 0: location = None if location is None and start_offset is None: return None, None bytes_per_sector = TSKVolumeGetBytesPerSector(tsk_volume) current_part_index = 0 current_partition_index = 0 tsk_vs_part = None # pytsk3 does not handle the Volume_Info iterator correctly therefore # the explicit cast to list is needed to prevent the iterator terminating # too soon or looping forever. tsk_vs_part_list = list(tsk_volume) number_of_tsk_vs_parts = len(tsk_vs_part_list) if number_of_tsk_vs_parts > 0: if (part_index is not None and (part_index < 0 or part_index >= number_of_tsk_vs_parts)): return None, None for tsk_vs_part in tsk_vs_part_list: if TSKVsPartIsAllocated(tsk_vs_part): if partition_index is not None: if partition_index == current_partition_index: break current_partition_index += 1 if part_index is not None and part_index == current_part_index: break if start_offset is not None: start_sector = TSKVsPartGetStartSector(tsk_vs_part) if start_sector is not None: start_sector *= bytes_per_sector if start_sector == start_offset: break current_part_index += 1 # Note that here we cannot solely rely on testing if tsk_vs_part is set # since the for loop will exit with tsk_vs_part set. if tsk_vs_part is None or current_part_index >= number_of_tsk_vs_parts: return None, None if not TSKVsPartIsAllocated(tsk_vs_part): current_partition_index = None return tsk_vs_part, current_partition_index
[docs] def TSKVolumeGetBytesPerSector(tsk_volume): """Retrieves the number of bytes per sector from a TSK volume object. Args: tsk_volume (pytsk3.Volume_Info): TSK volume information. Returns: int: number of bytes per sector or 512 by default. """ # Note that because pytsk3.Volume_Info does not explicitly defines info # we need to check if the attribute exists and has a value other # than None. Default to 512 otherwise. if hasattr(tsk_volume, 'info') and tsk_volume.info is not None: block_size = getattr(tsk_volume.info, 'block_size', 512) else: block_size = 512 return block_size
[docs] def TSKVsPartGetNumberOfSectors(tsk_vs_part): """Retrieves the number of sectors of a TSK volume system part object. Args: tsk_vs_part (pytsk3.TSK_VS_PART_INFO): TSK volume system part information. Returns: int: number of sectors or None. """ # Note that because pytsk3.TSK_VS_PART_INFO does not explicitly defines # len we need to check if the attribute exists. return getattr(tsk_vs_part, 'len', None)
[docs] def TSKVsPartGetStartSector(tsk_vs_part): """Retrieves the start sector of a TSK volume system part object. Args: tsk_vs_part (pytsk3.TSK_VS_PART_INFO): TSK volume system part information. Returns: int: start sector or None. """ # Note that because pytsk3.TSK_VS_PART_INFO does not explicitly defines # start we need to check if the attribute exists. return getattr(tsk_vs_part, 'start', None)
[docs] def TSKVsPartIsAllocated(tsk_vs_part): """Determines if the TSK volume system part object is allocated. Args: tsk_vs_part (pytsk3.TSK_VS_PART_INFO): TSK volume system part information. Returns: bool: True if the volume system part is allocated, False otherwise. """ # Note that because pytsk3.TSK_VS_PART_INFO does not explicitly defines # flags need to check if the attribute exists. # The flags are an instance of TSK_VS_PART_FLAG_ENUM. tsk_vs_part_flags = getattr(tsk_vs_part, 'flags', None) is_allocated = (tsk_vs_part_flags is not None and tsk_vs_part_flags == pytsk3.TSK_VS_PART_FLAG_ALLOC) tsk_vs_vstype = getattr(tsk_vs_part.vs, 'vstype', pytsk3.TSK_VS_TYPE_UNSUPP) # For BSD disklabel consider c and d partitions (slot 2 and 3) as metadata # part of the disklabel volume itself and not a partition of the volume. if tsk_vs_vstype == pytsk3.TSK_VS_TYPE_BSD: tsk_vs_part_slot_num = getattr(tsk_vs_part, 'slot_num', None) if tsk_vs_part_slot_num in (None, 2, 3): is_allocated = False # For APM partition tables the description needs to be checked to determine # the usage of the part. elif tsk_vs_vstype == pytsk3.TSK_VS_TYPE_MAC: tsk_vs_part_desc = getattr(tsk_vs_part, 'desc', None) return is_allocated and tsk_vs_part_desc not in ( b'Apple_partition_map', b'Apple_Free') return is_allocated