def CloseStream(self): """Closes the file-like object. Returns: str: a return message for the report. Raises: errors.RecipeException: if the dcfldd process returns with an error. IOError: if CloseStream() is called before GetStream(). """ if not self._ddprocess: raise IOError('Illegal call to CloseStream() before GetStream()') # If there is anything still to read from the subprocess then CloseStream # has been called early, terminate the child process to avoid deadlock. c = self._ddprocess.stdout.read(1) if c: # TODO log this self._ddprocess.terminate() raise errors.RecipeException( 'CloseStream() called but stdout still had data') self._ddprocess.wait() code = self._ddprocess.returncode error = self._ddprocess.stderr.read() if code > 0: raise errors.RecipeException( 'Command dcfldd returned non-zero exit status {0:d}, with error: "{1:s}"' .format(code, error.decode())) return error
def _RunCommand(self): """Run a command. Returns: bytes: the command output, or an error if it failed to run. """ command_output = '' process = subprocess.Popen(self._command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) self._logger.info('Running command \'%s\'', self._command) output, error = process.communicate() if process.returncode == 0: command_output = output self._logger.info('Command %s terminated.', self._command) self._logger.debug('stderr : \'%s\'', error.strip()) else: command_output = ( 'Command \'{0!s}\' failed with \'{1!s}\' return code {2:d})'. format(self._command, error.strip(), process.returncode)) self._logger.error(command_output) command_output = command_output.encode() raise errors.RecipeException( 'Error running ProcessOutputArtifact command') return command_output
def _GenerateCopyCommand(self): """Builds the command to run on the directory. Returns: list: the argument list for the dd command """ if self._method == 'tar': return self._GenerateTarCopyCommand() else: raise errors.RecipeException('Unsupported method ' + self._method)
def _GenerateDDCommand(self): """Builds the DD command to run on the disk. Returns: list: the argument list for the dd command """ dd_binary = hostinfo.Which(self._DD_BINARY) if not dd_binary: raise errors.RecipeException( 'Could not find \'{0:s}\''.format(self._DD_BINARY)) command = [ dd_binary, 'if={0:s}'.format(self._path), 'hashlog={0:s}'.format(self.hashlog_filename)] command.extend(self._DD_OPTIONS) return command
def GetArtifacts(self): """Selects the Artifacts to acquire. This tries to return as many Artifacts as possible even if some collection raised an exception. Returns: list(DiskArtifact): the artifacts corresponding to copy. Raises: errors.RecipeException: when no disk is to be collected. """ artifacts = [] disks_to_collect = [] if getattr(self._options, 'select_disks', None): all_disks = self._ListDisks(all_devices=True) if getattr(self._options, 'no_zenity', False): disks_to_collect = cli.AskDiskList(all_disks) else: disks_to_collect = gui.AskDiskList(all_disks) elif getattr(self._options, 'disk', None): disks_to_collect = self._ListDisks(names=self._options.disk) else: disks_to_collect = self._ListDisks() if not disks_to_collect: raise errors.RecipeException('No disk to collect') disk_list_artifact = self._GetListDisksArtifact() artifacts.append(disk_list_artifact) for disk in disks_to_collect: hashlog_artifact = base.FileArtifact(disk.hashlog_filename) hashlog_artifact.remote_path = 'Disks/{0:s}'.format( hashlog_artifact.name) # It is necessary for the DiskArtifact to be appended before the # hashlog, as the hashlog is generated when dcfldd completes. disk_info_artifact = self._GetDiskInfoArtifact(disk) if disk_info_artifact: artifacts.append(disk_info_artifact) artifacts.append(disk) artifacts.append(hashlog_artifact) return artifacts
def GetArtifacts(self): """Selects the Artifacts to acquire. This tries to return as many Artifacts as possible even if some collection raised an exception. Returns: list(DiskArtifact): the artifacts corresponding to copy. Raises: errors.RecipeException: when no disk is to be collected. """ artifacts = [] disks_to_collect = [] if getattr(self._options, 'select_disks', None): all_disks = self._ListDisks(all_devices=True) disks_to_collect = gui.AskDiskList(all_disks) elif getattr(self._options, 'disk', None): disks_to_collect = self._ListDisks(names=self._options.disk) else: disks_to_collect = self._ListDisks() if not disks_to_collect: raise errors.RecipeException('No disk to collect') lsblk_artifact = base.StringArtifact('Disks/lsblk.txt', json.dumps(self._GetLsblkDict())) for disk in disks_to_collect: udevadm_artifact = base.StringArtifact( 'Disks/{0:s}.udevadm.txt'.format(disk.name), disk.GetUdevadmProperty('udevadm_text_output')) hashlog_artifact = base.FileArtifact(disk.hashlog_filename) hashlog_artifact.remote_path = 'Disks/{0:s}'.format( hashlog_artifact.name) # It is necessary for the DiskArtifact to be appended before the # hashlog, as the hashlog is generated when dcfldd completes. artifacts.append(udevadm_artifact) artifacts.append(lsblk_artifact) artifacts.append(disk) artifacts.append(hashlog_artifact) return artifacts
def GetArtifacts(self): raise errors.RecipeException('Everything is terrible.')
def GetArtifacts(self): """Returns a list of DirectoryArtifacts to acquire. Returns: list(DirectoryArtifacts): the artifacts to acquire. """ more_to_copy = True path_list = [] while more_to_copy: if getattr(self._options, 'no_zenity', False): path = cli.AskText( 'Specify the path to the directory you wish to copy') if not os.path.isdir(path): print( 'The following path does not exist or is not a directory:' '{0:s}'.format(path)) continue path_list.append(path) more_to_copy = cli.Confirm( 'Do you wish to copy another folder?') else: path = gui.AskText( 'Specify the path to the directory you wish to copy') if not os.path.isdir(path): # TODO: display an GUI error message continue path_list.append(path) more_to_copy = gui.Confirm( 'Do you wish to copy another folder?') if not path_list: raise errors.RecipeException('No directory to collect') artifacts = [] # Deduplicating paths, as they would cause the code to upload the same file # multiple times, which might not be allowed by the uploading process. for directory in list(set(path_list)): # 'tar' will not save some metadata such as access time. We generate # a 'timeline' with the find(1) command to keep this information timeline_artifact = None dir_artifact = None if self._platform == 'darwin': timeline_artifact = base.ProcessOutputArtifact([ 'find', directory, '-exec', 'stat', '-f', '0|%N|%i|%p|%u|%u|%z|%a.0|%m.0|%c.0|%B.0', '-t', '%s', '{}', ';' ], 'Directories/{0:s}.timeline'.format(FullPathToName(path))) dir_artifact = MacDirectoryArtifact( directory, method=self._options.method, compress=self._options.compress) elif self._platform == 'linux': timeline_artifact = base.ProcessOutputArtifact([ 'find', directory, '-xdev', '-printf', '0|%p|%i|%M|%U|%G|%s|%A@|%T@|%C@|0\n' ], 'Directores/{0:s}.timeline'.format(FullPathToName(path))) dir_artifact = LinuxDirectoryArtifact( directory, method=self._options.method, compress=self._options.compress) else: raise ValueError('Unsupported platform: {0:s}'.format( self._platform)) artifacts.append(timeline_artifact) artifacts.append(dir_artifact) return artifacts
def __init__(self, path, method='tar', compress=False): """Initializes a MacDirectoryArtifact object.""" if method not in self._SUPPORTED_METHODS: raise errors.RecipeException( 'Unsupported acquisition method on Darwin: ' + method) super().__init__(path, method=method, compress=compress)