Exemple #1
0
    def _get_vss_store_identifiers(self, scan_node, interactive):
        """Determines the VSS store identifiers.
        Args:
            scan_node: the scan node (instance of dfvfs.ScanNode).
        Returns:
            A list of VSS store identifiers.
        Raises:
            RuntimeError: if the format of or within the source
                                        is not supported or the the scan node is invalid.
        """
        if not scan_node or not scan_node.path_spec:
            raise RuntimeError(u'Invalid scan node.')

        volume_system = vshadow_volume_system.VShadowVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not volume_identifiers:
            return []

        try:
            selected_store_identifiers = self._prompt_user_for_vss_store_identifiers(
                volume_system, volume_identifiers, interactive)
        except KeyboardInterrupt:
            raise errors.UserAbort(u'File system scan aborted.')

        return selected_store_identifiers
Exemple #2
0
    def _GetVSSStoreIdentifiers(self, scan_node, vss_stores=None):
        """Determines the VSS store identifiers.

    Args:
      scan_node: the scan node (instance of dfvfs.ScanNode).
      vss_stores: Optional list of preferred VSS store identifiers. The
                  default is None.

    Returns:
      A list of VSS store identifiers.

    Raises:
      SourceScannerError: if the format of or within the source
                          is not supported or the the scan node is invalid.
    """
        if not scan_node or not scan_node.path_spec:
            raise errors.SourceScannerError(u'Invalid scan node.')

        volume_system = vshadow_volume_system.VShadowVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not volume_identifiers:
            return []

        try:
            selected_store_identifiers = self._PromptUserForVSSStoreIdentifiers(
                volume_system, volume_identifiers, vss_stores=vss_stores)
        except KeyboardInterrupt:
            raise errors.UserAbort(u'File system scan aborted.')

        return selected_store_identifiers
Exemple #3
0
    def testGetNormalizedVShadowVolumeIdentifiers(self):
        """Tests the _GetNormalizedVShadowVolumeIdentifiers function."""
        test_tool = storage_media_tool.StorageMediaTool()

        test_path = self._GetTestFilePath(['vsstest.qcow2'])
        os_path_spec = path_spec_factory.Factory.NewPathSpec(
            dfvfs_definitions.TYPE_INDICATOR_OS, location=test_path)
        qcow_path_spec = path_spec_factory.Factory.NewPathSpec(
            dfvfs_definitions.TYPE_INDICATOR_QCOW, parent=os_path_spec)
        vss_path_spec = path_spec_factory.Factory.NewPathSpec(
            dfvfs_definitions.TYPE_INDICATOR_VSHADOW, parent=qcow_path_spec)

        volume_system = vshadow_volume_system.VShadowVolumeSystem()
        volume_system.Open(vss_path_spec)

        volume_identifiers = test_tool._GetNormalizedVShadowVolumeIdentifiers(
            volume_system, ['vss1', 'vss2'])
        self.assertEqual(volume_identifiers, [1, 2])

        with self.assertRaises(KeyError):
            test_tool._GetNormalizedTSKVolumeIdentifiers(volume_system, [1, 2])

        with self.assertRaises(KeyError):
            test_tool._GetNormalizedTSKVolumeIdentifiers(
                volume_system, ['vss3'])
Exemple #4
0
  def _GetVolumeVssStoreIdentifiers(self, scan_context, vss_stores=None):
    """Determines the VSS store identifiers.

    Args:
      scan_context: the scan context (instance of dfvfs.ScanContext).
      vss_stores: Optional list of preferred VSS stored identifiers. The
                  default is None.

    Raises:
      SourceScannerError: if the format of or within the source
                          is not supported or the the scan context
                          is invalid.
    """
    if (not scan_context or not scan_context.last_scan_node or
        not scan_context.last_scan_node.path_spec):
      raise errors.SourceScannerError(u'Invalid scan context.')

    volume_system = vshadow_volume_system.VShadowVolumeSystem()
    volume_system.Open(scan_context.last_scan_node.path_spec)

    volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
        volume_system)
    if not volume_identifiers:
      return

    try:
      self.vss_stores = self._GetVssStoreIdentifiersFromUser(
          volume_system, volume_identifiers, vss_stores=vss_stores)
    except KeyboardInterrupt:
      raise errors.UserAbort(u'File system scan aborted.')

    return
Exemple #5
0
    def _GetVSSStoreIdentifiers(self, scan_node):
        """Determines the VSS store identifiers.

    Args:
      scan_node: the scan node (instance of dfvfs.ScanNode).

    Returns:
      A list of VSS store identifiers.

    Raises:
      ScannerError: if the format of or within the source is not supported,
                    the the scan node is invalid or no mediator is provided
                    and VSS store identifiers are found.
    """
        if not scan_node or not scan_node.path_spec:
            raise errors.ScannerError(u'Invalid scan node.')

        volume_system = vshadow_volume_system.VShadowVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not self._mediator and not volume_identifiers:
            return []

        if not self._mediator:
            raise errors.ScannerError(
                u'Unable to proceed VSS. Identifiers found but no mediator to '
                u'determine how they should be used.')

        try:
            return self._mediator.GetVSSStoreIdentifiers(
                volume_system, volume_identifiers)
        except KeyboardInterrupt:
            raise errors.UserAbort(u'File system scan aborted.')
    def _GetVSSStoreIdentifiers(self, scan_node):

        if not scan_node or not scan_node.path_spec:
            raise errors.SourceScannerError('Invalid scan node.')

        volume_system = vshadow_volume_system.VShadowVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not volume_identifiers:
            return []

        # TODO: refactor to use scan options.
        if self._vss_stores:
            if self._vss_stores == 'all':
                vss_stores = range(1, volume_system.number_of_volumes + 1)
            else:
                vss_stores = self._ParseVolumeIdentifiersString(
                    self._vss_stores, prefix='vss')

            selected_volume_identifiers = self._NormalizedVolumeIdentifiers(
                volume_system, vss_stores, prefix='vss')

            if not set(selected_volume_identifiers).difference(
                    volume_identifiers):
                return selected_volume_identifiers

        return self._NormalizedVolumeIdentifiers(volume_system,
                                                 volume_identifiers,
                                                 prefix='vss')
Exemple #7
0
    def testNormalizedVolumeIdentifiersVSS(self):
        """Tests the _NormalizedVolumeIdentifiers function on a VSS."""
        test_mediator = TestVolumeScannerMediator()
        test_scanner = volume_scanner.VolumeScanner(mediator=test_mediator)

        test_path = self._GetTestFilePath(['vsstest.qcow2'])
        self._SkipIfPathNotExists(test_path)

        test_os_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_OS, location=test_path)
        test_qcow_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_QCOW, parent=test_os_path_spec)
        test_vss_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_VSHADOW, parent=test_qcow_path_spec)

        volume_system = vshadow_volume_system.VShadowVolumeSystem()
        volume_system.Open(test_vss_path_spec)

        volume_identifiers = test_scanner._NormalizedVolumeIdentifiers(
            volume_system, ['vss1', 'vss2'], prefix='vss')
        self.assertEqual(volume_identifiers, ['vss1', 'vss2'])

        volume_identifiers = test_scanner._NormalizedVolumeIdentifiers(
            volume_system, [1, 2], prefix='vss')
        self.assertEqual(volume_identifiers, ['vss1', 'vss2'])

        # Test error conditions.
        with self.assertRaises(errors.ScannerError):
            test_scanner._NormalizedVolumeIdentifiers(volume_system, ['vss3'],
                                                      prefix='vss')
Exemple #8
0
    def _GetVSSStoreIdentifiers(self, scan_node, options):
        """Determines the VSS store identifiers.

    Args:
      scan_node (SourceScanNode): scan node.
      options (VolumeScannerOptions): volume scanner options.

    Returns:
      list[str]: VSS store identifiers.

    Raises:
      ScannerError: if the format the scan node is invalid or no mediator
          is provided and VSS store identifiers are found.
      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 = vshadow_volume_system.VShadowVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not volume_identifiers:
            return []

        if options.snapshots:
            if options.snapshots == ['all']:
                snapshots = range(1, volume_system.number_of_volumes + 1)
            elif options.snapshots == ['none']:
                snapshots = []
            else:
                snapshots = options.snapshots

            try:
                selected_volumes = self._NormalizedVolumeIdentifiers(
                    volume_system, snapshots, prefix='vss')

                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 not self._mediator:
            raise errors.ScannerError(
                'Unable to proceed. VSS stores found but no mediator to determine '
                'how they should be used.')

        try:
            volume_identifiers = self._mediator.GetVSSStoreIdentifiers(
                volume_system, volume_identifiers)

        except KeyboardInterrupt:
            raise errors.UserAbort('File system scan aborted.')

        return self._NormalizedVolumeIdentifiers(volume_system,
                                                 volume_identifiers,
                                                 prefix='vss')
Exemple #9
0
    def _GetVSSStoreIdentifiers(self, scan_node):
        """Determines the VSS store identifiers.

    Args:
      scan_node (dfvfs.SourceScanNode): scan node.

    Returns:
      list[str]: VSS store identifiers.

    Raises:
      SourceScannerError: if the format of or within the source is not
          supported or 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 = vshadow_volume_system.VShadowVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not volume_identifiers:
            return []

        # TODO: refactor to use scan options.
        if self._vss_stores:
            if self._vss_stores == 'all':
                vss_stores = range(1, volume_system.number_of_volumes + 1)
            else:
                vss_stores = self._ParseVolumeIdentifiersString(
                    self._vss_stores, prefix='vss')

            selected_volume_identifiers = self._NormalizedVolumeIdentifiers(
                volume_system, vss_stores, prefix='vss')

            if not set(selected_volume_identifiers).difference(
                    volume_identifiers):
                return selected_volume_identifiers

        if self._unattended_mode:
            return []

        try:
            volume_identifiers = self._PromptUserForVSSStoreIdentifiers(
                volume_system, volume_identifiers)

        except KeyboardInterrupt:
            raise errors.UserAbort('File system scan aborted.')

        return self._NormalizedVolumeIdentifiers(volume_system,
                                                 volume_identifiers,
                                                 prefix='vss')
Exemple #10
0
    def _GetVSSStoreIdentifiers(self, scan_node):
        if not scan_node or not scan_node.path_spec:
            raise RuntimeError(u'Invalid scan node.')

        volume_system = vshadow_volume_system.VShadowVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)

        if not volume_identifiers:
            return []

        return list(range(1, volume_system.number_of_volumes + 1))
Exemple #11
0
    def __init__(self, node):
        if node.path_spec.store_index is None:
            # VSS Root
            vss = vshadow_volume_system.VShadowVolumeSystem()
            vss.Open(node.path_spec)

            for shadow_volume in vss.volumes:
                self.append(
                    wx.propgrid.PropertyCategory(u'{}'.format(
                        shadow_volume.identifier)))
                for attribute in shadow_volume.attributes:
                    self.append(
                        wx.propgrid.StringProperty(
                            u'{} {}'.format(shadow_volume.identifier,
                                            attribute.identifier),
                            value=u'{}'.format(attribute.value)))
        else:
            # VSS Index
            vss = vshadow_volume_system.VShadowVolumeSystem()
            vss.Open(node.path_spec)

            vss_index = node.path_spec.store_index
            vss_label = node.path_spec.location[1:]

            _vss_cnt = 0
            for shadow_volume in vss.volumes:
                if vss_label == shadow_volume.identifier:
                    self.append(
                        wx.propgrid.PropertyCategory(u'{}'.format(
                            shadow_volume.identifier)))
                    for attribute in shadow_volume.attributes:
                        self.append(
                            wx.propgrid.StringProperty(
                                u'{} {}'.format(shadow_volume.identifier,
                                                attribute.identifier),
                                value=u'{}'.format(attribute.value)))
                    _vss_cnt += 1
Exemple #12
0
  def testPrintVSSStoreIdentifiersOverview(self):
    """Tests the _PrintVSSStoreIdentifiersOverview function."""
    test_file_path = self._GetTestFilePath(['vsstest.qcow2'])
    self._SkipIfPathNotExists(test_file_path)

    test_os_path_spec = path_spec_factory.Factory.NewPathSpec(
        dfvfs_definitions.TYPE_INDICATOR_OS, location=test_file_path)
    test_qcow_path_spec = path_spec_factory.Factory.NewPathSpec(
        dfvfs_definitions.TYPE_INDICATOR_QCOW, parent=test_os_path_spec)
    test_vss_path_spec = path_spec_factory.Factory.NewPathSpec(
        dfvfs_definitions.TYPE_INDICATOR_VSHADOW, parent=test_qcow_path_spec)

    volume_system = vshadow_volume_system.VShadowVolumeSystem()
    volume_system.Open(test_vss_path_spec)

    file_object = io.BytesIO()
    test_output_writer = tools.FileObjectOutputWriter(file_object)

    test_mediator = storage_media_tool.StorageMediaToolMediator(
        output_writer=test_output_writer)

    test_mediator._PrintVSSStoreIdentifiersOverview(
        volume_system, ['vss1', 'vss2'])

    file_object.seek(0, os.SEEK_SET)
    output_data = file_object.read()

    expected_output_data = [
        b'The following Volume Shadow Snapshots (VSS) were found:',
        b'',
        b'Identifier      Creation Time',
        b'vss1            2013-12-03 06:35:09.7363787',
        b'vss2            2013-12-03 06:37:48.9190583',
        b'',
        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)
Exemple #13
0
    def _GetVSSStoreIdentifiers(self, scan_node):
        """Determines the VSS store identifiers.

    Args:
      scan_node (SourceScanNode): scan node.

    Returns:
      list[str]: VSS store identifiers.

    Raises:
      ScannerError: if the format the scan node is invalid or no mediator
          is provided and VSS store identifiers are found.
      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 = vshadow_volume_system.VShadowVolumeSystem()
        volume_system.Open(scan_node.path_spec)

        volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
            volume_system)
        if not volume_identifiers:
            return []

        if not self._mediator:
            raise errors.ScannerError(
                'Unable to proceed. VSS stores found but no mediator to determine '
                'how they should be used.')

        try:
            volume_identifiers = self._mediator.GetVSSStoreIdentifiers(
                volume_system, volume_identifiers)

        except KeyboardInterrupt:
            raise errors.UserAbort('File system scan aborted.')

        return self._NormalizedVolumeIdentifiers(volume_system,
                                                 volume_identifiers,
                                                 prefix='vss')
Exemple #14
0
    def testIterateVolumes(self):
        """Test the iterate volumes functionality."""
        volume_system = vshadow_volume_system.VShadowVolumeSystem()

        volume_system.Open(self._vshadow_path_spec)

        self.assertEqual(volume_system.number_of_volumes, 2)

        volume = volume_system.GetVolumeByIndex(1)
        self.assertIsNotNone(volume)

        self.assertEqual(volume.number_of_extents, 1)
        self.assertEqual(volume.number_of_attributes, 4)
        self.assertEqual(volume.identifier, u'vss2')

        expected_value = u'600f0b6d-5bdf-11e3-9d6c-005056c00008'
        volume_attribute = volume.GetAttribute(u'identifier')
        self.assertIsNotNone(volume_attribute)
        self.assertEqual(volume_attribute.value, expected_value)

        expected_value = u'18f1ac6e-959d-436f-bdcc-e797a729e290'
        volume_attribute = volume.GetAttribute(u'copy_identifier')
        self.assertIsNotNone(volume_attribute)
        self.assertEqual(volume_attribute.value, expected_value)

        expected_value = u'8438a0ee-0f06-443b-ac0c-2905647ca5d6'
        volume_attribute = volume.GetAttribute(u'copy_set_identifier')
        self.assertIsNotNone(volume_attribute)
        self.assertEqual(volume_attribute.value, expected_value)

        expected_value = 130305262689190583
        volume_attribute = volume.GetAttribute(u'creation_time')
        self.assertIsNotNone(volume_attribute)
        self.assertEqual(volume_attribute.value, expected_value)

        volume = volume_system.GetVolumeByIndex(7)
        self.assertIsNone(volume)
Exemple #15
0
    def testGetVSSStoreIdentifiers(self):
        """Tests the GetVSSStoreIdentifiers function."""
        test_path = self._GetTestFilePath(['vsstest.qcow2'])
        test_os_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_OS, location=test_path)
        test_qcow_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_QCOW, parent=test_os_path_spec)
        test_vss_path_spec = path_spec_factory.Factory.NewPathSpec(
            definitions.TYPE_INDICATOR_VSHADOW, parent=test_qcow_path_spec)

        volume_system = vshadow_volume_system.VShadowVolumeSystem()
        volume_system.Open(test_vss_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 selection of single store.
        input_file_object = io.BytesIO(b'2\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.GetVSSStoreIdentifiers(
            volume_system, ['vss1', 'vss2'])

        self.assertEqual(volume_identifiers, ['vss2'])

        # Test selection of single store.
        input_file_object = io.BytesIO(b'vss2\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.GetVSSStoreIdentifiers(
            volume_system, ['vss1', 'vss2'])

        self.assertEqual(volume_identifiers, ['vss2'])

        # Test selection of single store with invalid input on first attempt.
        input_file_object = io.BytesIO(b'bogus\nvss2\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.GetVSSStoreIdentifiers(
            volume_system, ['vss1', 'vss2'])

        self.assertEqual(volume_identifiers, ['vss2'])

        # Test selection of all stores.
        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.GetVSSStoreIdentifiers(
            volume_system, ['vss1', 'vss2'])

        self.assertEqual(volume_identifiers, ['vss1', 'vss2'])

        # Test selection of no stores.
        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.GetVSSStoreIdentifiers(
            volume_system, ['vss1', 'vss2'])

        self.assertEqual(volume_identifiers, [])
Exemple #16
0
    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)