def testIterateVolumes(self): """Test the iterate volumes functionality.""" volume_system = apfs_volume_system.APFSVolumeSystem() volume_system.Open(self._apfs_container_path_spec) self.assertEqual(volume_system.number_of_volumes, 1) volume = volume_system.GetVolumeByIndex(0) self.assertIsNotNone(volume) self.assertEqual(volume.number_of_attributes, 2) self.assertEqual(volume.identifier, 'apfs1') expected_value = '44b5f357-e9b3-483d-893c-3802306b5132' volume_attribute = volume.GetAttribute('identifier') self.assertIsNotNone(volume_attribute) self.assertEqual(volume_attribute.value, expected_value) volume_attribute = volume.GetAttribute('name') self.assertIsNotNone(volume_attribute) self.assertEqual(volume_attribute.value, 'SingleVolume') volume = volume_system.GetVolumeByIndex(99) self.assertIsNone(volume)
def testIterateVolumes(self): """Test the iterate volumes functionality.""" volume_system = apfs_volume_system.APFSVolumeSystem() volume_system.Open(self._apfs_container_path_spec) self.assertEqual(volume_system.number_of_volumes, 1) volume = volume_system.GetVolumeByIndex(0) self.assertIsNotNone(volume) self.assertEqual(volume.number_of_attributes, 2) self.assertEqual(volume.identifier, 'apfs1') expected_value = '5a4d7f50-726e-4fe9-8c57-8898f0cbaf72' volume_attribute = volume.GetAttribute('identifier') self.assertIsNotNone(volume_attribute) self.assertEqual(volume_attribute.value, expected_value) volume_attribute = volume.GetAttribute('name') self.assertIsNotNone(volume_attribute) self.assertEqual(volume_attribute.value, 'apfs_test') volume = volume_system.GetVolumeByIndex(99) self.assertIsNone(volume)
def _GetAPFSVolumeIdentifiers(self, scan_node, options): """Determines the APFS volume identifiers. Args: scan_node (SourceScanNode): scan node. options (VolumeScannerOptions): volume scanner options. Returns: list[str]: APFS volume identifiers. Raises: ScannerError: if the format of or within the source is not supported or the the scan node is invalid. UserAbort: if the user requested to abort. """ if not scan_node or not scan_node.path_spec: raise errors.ScannerError('Invalid scan node.') volume_system = apfs_volume_system.APFSVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._source_scanner.GetVolumeIdentifiers( volume_system) if not volume_identifiers: return [] if options.volumes: if options.volumes == ['all']: volumes = range(1, volume_system.number_of_volumes + 1) else: volumes = options.volumes try: selected_volumes = self._NormalizedVolumeIdentifiers( volume_system, volumes, prefix='apfs') if not set(selected_volumes).difference(volume_identifiers): return selected_volumes except errors.ScannerError as exception: if self._mediator: self._mediator.PrintWarning('{0!s}'.format(exception)) if len(volume_identifiers) > 1: if not self._mediator: raise errors.ScannerError( 'Unable to proceed. APFS volumes found but no mediator to ' 'determine how they should be used.') try: volume_identifiers = self._mediator.GetAPFSVolumeIdentifiers( volume_system, volume_identifiers) except KeyboardInterrupt: raise errors.UserAbort('File system scan aborted.') return self._NormalizedVolumeIdentifiers(volume_system, volume_identifiers, prefix='apfs')
def _GetAPFSVolumeIdentifiers(self, scan_node): """Determines the APFS volume identifiers. Args: scan_node (dfvfs.SourceScanNode): scan node. Returns: list[str]: APFS volume identifiers. Raises: SourceScannerError: if the format of or within the source is not supported or the the scan node is invalid. UserAbort: if the user requested to abort. """ if not scan_node or not scan_node.path_spec: raise errors.SourceScannerError('Invalid scan node.') volume_system = apfs_volume_system.APFSVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._source_scanner.GetVolumeIdentifiers( volume_system) if not volume_identifiers: return [] # TODO: refactor self._volumes to use scan options. if self._volumes: if self._volumes == 'all': volumes = range(1, volume_system.number_of_volumes + 1) else: volumes = self._ParseVolumeIdentifiersString(self._volumes, prefix='apfs') selected_volume_identifiers = self._NormalizedVolumeIdentifiers( volume_system, volumes, prefix='apfs') if not set(selected_volume_identifiers).difference( volume_identifiers): return selected_volume_identifiers if len(volume_identifiers) > 1: if self._unattended_mode: raise errors.SourceScannerError( 'More than 1 volume found but no volumes specified.') try: volume_identifiers = self._PromptUserForAPFSVolumeIdentifiers( volume_system, volume_identifiers) except KeyboardInterrupt: raise errors.UserAbort('File system scan aborted.') return self._NormalizedVolumeIdentifiers(volume_system, volume_identifiers, prefix='apfs')
def testPrintAPFSVolumeIdentifiersOverview(self): """Tests the _PrintAPFSVolumeIdentifiersOverview function.""" test_path = self._GetTestFilePath(['apfs.dmg']) self._SkipIfPathNotExists(test_path) test_os_path_spec = path_spec_factory.Factory.NewPathSpec( definitions.TYPE_INDICATOR_OS, location=test_path) test_raw_path_spec = path_spec_factory.Factory.NewPathSpec( definitions.TYPE_INDICATOR_RAW, parent=test_os_path_spec) test_tsk_partition_path_spec = path_spec_factory.Factory.NewPathSpec( definitions.TYPE_INDICATOR_TSK_PARTITION, location='/p1', parent=test_raw_path_spec) test_apfs_container_path_spec = path_spec_factory.Factory.NewPathSpec( definitions.TYPE_INDICATOR_APFS_CONTAINER, location='/', parent=test_tsk_partition_path_spec) volume_system = apfs_volume_system.APFSVolumeSystem() volume_system.Open(test_apfs_container_path_spec) file_object = io.BytesIO() test_output_writer = command_line.FileObjectOutputWriter(file_object) test_mediator = command_line.CLIVolumeScannerMediator( output_writer=test_output_writer) test_mediator._PrintAPFSVolumeIdentifiersOverview( volume_system, ['apfs1']) file_object.seek(0, os.SEEK_SET) output_data = file_object.read() expected_output_data = [ b'The following Apple File System (APFS) volumes were found:', b'', b'Identifier Name', b'apfs1 SingleVolume', b'' ] if not win32console: # Using join here since Python 3 does not support format of bytes. expected_output_data[2] = b''.join( [b'\x1b[1m', expected_output_data[2], b'\x1b[0m']) self.assertEqual(output_data.split(b'\n'), expected_output_data)
def _GetAPFSVolumeIdentifiers(self, scan_node): """Determines the APFS volume identifiers. Args: scan_node (SourceScanNode): scan node. Returns: list[str]: APFS volume identifiers. Raises: ScannerError: if the format of or within the source is not supported or the the scan node is invalid. UserAbort: if the user requested to abort. """ if not scan_node or not scan_node.path_spec: raise errors.ScannerError('Invalid scan node.') volume_system = apfs_volume_system.APFSVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._source_scanner.GetVolumeIdentifiers( volume_system) if not volume_identifiers: return [] if len(volume_identifiers) > 1: if not self._mediator: raise errors.ScannerError( 'Unable to proceed. APFS volumes found but no mediator to ' 'determine how they should be used.') try: volume_identifiers = self._mediator.GetAPFSVolumeIdentifiers( volume_system, volume_identifiers) except KeyboardInterrupt: raise errors.UserAbort('File system scan aborted.') return self._NormalizedVolumeIdentifiers(volume_system, volume_identifiers, prefix='apfs')
def testGetAPFSVolumeIdentifiers(self): """Tests the GetAPFSVolumeIdentifiers function.""" test_path = self._GetTestFilePath(['apfs.dmg']) test_os_path_spec = path_spec_factory.Factory.NewPathSpec( definitions.TYPE_INDICATOR_OS, location=test_path) test_raw_path_spec = path_spec_factory.Factory.NewPathSpec( definitions.TYPE_INDICATOR_RAW, parent=test_os_path_spec) test_tsk_partition_path_spec = path_spec_factory.Factory.NewPathSpec( definitions.TYPE_INDICATOR_TSK_PARTITION, location='/p1', parent=test_raw_path_spec) test_apfs_container_path_spec = path_spec_factory.Factory.NewPathSpec( definitions.TYPE_INDICATOR_APFS_CONTAINER, location='/', parent=test_tsk_partition_path_spec) volume_system = apfs_volume_system.APFSVolumeSystem() volume_system.Open(test_apfs_container_path_spec) # Test selection of single volume. input_file_object = io.BytesIO(b'1\n') test_input_reader = command_line.FileObjectInputReader( input_file_object) output_file_object = io.BytesIO() test_output_writer = command_line.FileObjectOutputWriter( output_file_object) test_mediator = command_line.CLIVolumeScannerMediator( input_reader=test_input_reader, output_writer=test_output_writer) volume_identifiers = test_mediator.GetAPFSVolumeIdentifiers( volume_system, ['apfs1']) self.assertEqual(volume_identifiers, ['apfs1']) # Test selection of single volume. input_file_object = io.BytesIO(b'apfs1\n') test_input_reader = command_line.FileObjectInputReader( input_file_object) output_file_object = io.BytesIO() test_output_writer = command_line.FileObjectOutputWriter( output_file_object) test_mediator = command_line.CLIVolumeScannerMediator( input_reader=test_input_reader, output_writer=test_output_writer) volume_identifiers = test_mediator.GetAPFSVolumeIdentifiers( volume_system, ['apfs1']) self.assertEqual(volume_identifiers, ['apfs1']) # Test selection of single volume with invalid input on first attempt. input_file_object = io.BytesIO(b'bogus\napfs1\n') test_input_reader = command_line.FileObjectInputReader( input_file_object) output_file_object = io.BytesIO() test_output_writer = command_line.FileObjectOutputWriter( output_file_object) test_mediator = command_line.CLIVolumeScannerMediator( input_reader=test_input_reader, output_writer=test_output_writer) volume_identifiers = test_mediator.GetAPFSVolumeIdentifiers( volume_system, ['apfs1']) self.assertEqual(volume_identifiers, ['apfs1']) # Test selection of all volumes. input_file_object = io.BytesIO(b'all\n') test_input_reader = command_line.FileObjectInputReader( input_file_object) output_file_object = io.BytesIO() test_output_writer = command_line.FileObjectOutputWriter( output_file_object) test_mediator = command_line.CLIVolumeScannerMediator( input_reader=test_input_reader, output_writer=test_output_writer) volume_identifiers = test_mediator.GetAPFSVolumeIdentifiers( volume_system, ['apfs1']) self.assertEqual(volume_identifiers, ['apfs1']) # Test selection of no volumes. input_file_object = io.BytesIO(b'\n') test_input_reader = command_line.FileObjectInputReader( input_file_object) output_file_object = io.BytesIO() test_output_writer = command_line.FileObjectOutputWriter( output_file_object) test_mediator = command_line.CLIVolumeScannerMediator( input_reader=test_input_reader, output_writer=test_output_writer) volume_identifiers = test_mediator.GetAPFSVolumeIdentifiers( volume_system, ['apfs1']) self.assertEqual(volume_identifiers, [])
def _ScanVolumeSystemRoot(self, scan_context, scan_node, options, base_path_specs): """Scans a volume system root scan node for volume and file systems. Args: scan_context (SourceScannerContext): source scanner context. scan_node (SourceScanNode): volume system root scan node. options (VolumeScannerOptions): volume scanner options. base_path_specs (list[PathSpec]): file system base path specifications. Raises: dfvfs.ScannerError: if the scan node is invalid, the scan node type is not supported or if a sub scan node cannot be retrieved. """ if not scan_node or not scan_node.path_spec: raise dfvfs_errors.ScannerError('Invalid scan node.') if scan_node.type_indicator == ( dfvfs_definitions.TYPE_INDICATOR_APFS_CONTAINER): volume_system = apfs_volume_system.APFSVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._GetVolumeIdentifiers( volume_system, options) elif scan_node.type_indicator == dfvfs_definitions.TYPE_INDICATOR_GPT: volume_identifiers = self._GetPartitionIdentifiers( scan_node, options) elif scan_node.type_indicator == dfvfs_definitions.TYPE_INDICATOR_LVM: volume_system = lvm_volume_system.LVMVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._GetVolumeIdentifiers( volume_system, options) elif scan_node.type_indicator == dfvfs_definitions.TYPE_INDICATOR_VSHADOW: volume_system = vshadow_volume_system.VShadowVolumeSystem() volume_system.Open(scan_node.path_spec) volume_identifiers = self._GetVolumeSnapshotIdentifiers( volume_system, options) # Process VSS stores (snapshots) starting with the most recent one. volume_identifiers.reverse() # TODO: difference with dfVFS for current VSS volume support. if not options.snapshots_only and self._mediator and volume_identifiers: snapshots_only = not self._mediator.PromptUserForVSSCurrentVolume( ) options.snapshots_only = snapshots_only self._snapshots_only = snapshots_only else: raise dfvfs_errors.ScannerError( 'Unsupported volume system type: {0:s}.'.format( scan_node.type_indicator)) for volume_identifier in volume_identifiers: location = '/{0:s}'.format(volume_identifier) sub_scan_node = scan_node.GetSubNodeByLocation(location) if not sub_scan_node: raise dfvfs_errors.ScannerError( 'Scan node missing for volume identifier: {0:s}.'.format( volume_identifier)) self._ScanVolume(scan_context, sub_scan_node, options, base_path_specs)
def testGetAPFSVolumeIdentifiers(self): """Tests the GetAPFSVolumeIdentifiers function.""" test_file_path = self._GetTestFilePath(['apfs.dmg']) self._SkipIfPathNotExists(test_file_path) test_os_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_OS, location=test_file_path) test_raw_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_RAW, parent=test_os_path_spec) test_tsk_partition_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.PREFERRED_GPT_BACK_END, location='/p1', parent=test_raw_path_spec) test_apfs_container_path_spec = path_spec_factory.Factory.NewPathSpec( dfvfs_definitions.TYPE_INDICATOR_APFS_CONTAINER, location='/', parent=test_tsk_partition_path_spec) volume_system = apfs_volume_system.APFSVolumeSystem() volume_system.Open(test_apfs_container_path_spec) # Test selection of single volume. input_file_object = io.BytesIO(b'1\n') test_input_reader = tools.FileObjectInputReader(input_file_object) output_file_object = io.BytesIO() test_output_writer = tools.FileObjectOutputWriter(output_file_object) test_mediator = storage_media_tool.StorageMediaToolMediator( input_reader=test_input_reader, output_writer=test_output_writer) volume_identifiers = test_mediator.GetAPFSVolumeIdentifiers( volume_system, ['apfs1']) self.assertEqual(volume_identifiers, ['apfs1']) # Test selection of single volume. input_file_object = io.BytesIO(b'apfs1\n') test_input_reader = tools.FileObjectInputReader(input_file_object) output_file_object = io.BytesIO() test_output_writer = tools.FileObjectOutputWriter(output_file_object) test_mediator = storage_media_tool.StorageMediaToolMediator( input_reader=test_input_reader, output_writer=test_output_writer) volume_identifiers = test_mediator.GetAPFSVolumeIdentifiers( volume_system, ['apfs1']) self.assertEqual(volume_identifiers, ['apfs1']) # Test selection of single volume with invalid input on first attempt. input_file_object = io.BytesIO(b'bogus\napfs1\n') test_input_reader = tools.FileObjectInputReader(input_file_object) output_file_object = io.BytesIO() test_output_writer = tools.FileObjectOutputWriter(output_file_object) test_mediator = storage_media_tool.StorageMediaToolMediator( input_reader=test_input_reader, output_writer=test_output_writer) volume_identifiers = test_mediator.GetAPFSVolumeIdentifiers( volume_system, ['apfs1']) self.assertEqual(volume_identifiers, ['apfs1']) # Test selection of all volumes. input_file_object = io.BytesIO(b'all\n') test_input_reader = tools.FileObjectInputReader(input_file_object) output_file_object = io.BytesIO() test_output_writer = tools.FileObjectOutputWriter(output_file_object) test_mediator = storage_media_tool.StorageMediaToolMediator( input_reader=test_input_reader, output_writer=test_output_writer) volume_identifiers = test_mediator.GetAPFSVolumeIdentifiers( volume_system, ['apfs1']) self.assertEqual(volume_identifiers, ['apfs1']) # Test selection of no volumes. input_file_object = io.BytesIO(b'\n') test_input_reader = tools.FileObjectInputReader(input_file_object) output_file_object = io.BytesIO() test_output_writer = tools.FileObjectOutputWriter(output_file_object) test_mediator = storage_media_tool.StorageMediaToolMediator( input_reader=test_input_reader, output_writer=test_output_writer) volume_identifiers = test_mediator.GetAPFSVolumeIdentifiers( volume_system, ['apfs1']) self.assertEqual(volume_identifiers, [])