def _transfer_output_files(
        self, tool_output_dir, working_dir, output_dir, patterns
    ):
        """Transfer files created by the tool in the container to the output directory.
        @param tool_output_dir:
            The directory under which all tool output files are created.
        @param working_dir: The absolute working directory of the tool in the container.
        @param output_dir: the directory where to write result files
        @param patterns: a list of patterns of files to retrieve as result files
        """
        assert output_dir and patterns
        if any(os.path.isabs(pattern) for pattern in patterns):
            base_dir = tool_output_dir
        else:
            base_dir = tool_output_dir + working_dir

        def transfer_file(abs_file):
            assert abs_file.startswith(base_dir)

            # We ignore (empty) directories, because we create them for hidden dirs etc.
            # We ignore device nodes, because overlayfs creates them.
            # We also ignore all other files (symlinks, fifos etc.),
            # because they are probably irrelevant, and just handle regular files.
            file = os.path.join("/", os.path.relpath(abs_file, base_dir))
            if (
                os.path.isfile(abs_file)
                and not os.path.islink(abs_file)
                and not container.is_container_system_config_file(file)
            ):
                target = output_dir + file
                logging.debug("Transferring output file %s to %s", abs_file, target)
                try:
                    os.makedirs(os.path.dirname(target))
                except EnvironmentError:
                    pass  # exist_ok=True not supported on Python 2
                try:
                    # move is more efficient than copy in case both abs_file and target
                    # are on the same filesystem, and it avoids matching the file again
                    # with the next pattern.
                    shutil.move(abs_file, target)
                except EnvironmentError as e:
                    logging.warning("Could not retrieve output file '%s': %s", file, e)

        for pattern in patterns:
            if os.path.isabs(pattern):
                pattern = tool_output_dir + pattern
            else:
                pattern = tool_output_dir + os.path.join(working_dir, pattern)
            # normalize pattern for preventing directory traversal attacks:
            for abs_file in util.maybe_recursive_iglob(
                os.path.normpath(pattern), recursive=True
            ):
                # Recursive matching is only supported starting with Python 3.5, so we
                # allow the user to match directories and transfer them recursively.
                if os.path.isdir(abs_file):
                    for root, unused_dirs, files in os.walk(abs_file):
                        for file in files:
                            transfer_file(os.path.join(root, file))
                else:
                    transfer_file(abs_file)
示例#2
0
    def _transfer_output_files(self, temp_dir, working_dir, output_dir, patterns):
        """Transfer files created by the tool in the container to the output directory.
        @param temp_dir: The base directory under which all our directories are created.
        @param working_dir: The absolute working directory of the tool in the container.
        @param output_dir: the directory where to write result files
        @param patterns: a list of patterns of files to retrieve as result files
        """
        assert output_dir and patterns
        tool_output_dir = os.path.join(temp_dir, "temp")
        if any(os.path.isabs(pattern) for pattern in patterns):
            base_dir = tool_output_dir
        else:
            base_dir = tool_output_dir + working_dir

        def transfer_file(abs_file):
            assert abs_file.startswith(base_dir)

            # We ignore (empty) directories, because we create them for hidden dirs etc.
            # We ignore device nodes, because overlayfs creates them.
            # We also ignore all other files (symlinks, fifos etc.),
            # because they are probably irrelevant, and just handle regular files.
            file = os.path.join("/", os.path.relpath(abs_file, base_dir))
            if (
                os.path.isfile(abs_file)
                and not os.path.islink(abs_file)
                and not container.is_container_system_config_file(file)
            ):
                target = output_dir + file
                try:
                    os.makedirs(os.path.dirname(target))
                except EnvironmentError:
                    pass  # exist_ok=True not supported on Python 2
                try:
                    # move is more efficient than copy in case both abs_file and target
                    # are on the same filesystem, and it avoids matching the file again
                    # with the next pattern.
                    shutil.move(abs_file, target)
                except EnvironmentError as e:
                    logging.warning("Could not retrieve output file '%s': %s", file, e)

        for pattern in patterns:
            if os.path.isabs(pattern):
                pattern = tool_output_dir + pattern
            else:
                pattern = tool_output_dir + os.path.join(working_dir, pattern)
            # normalize pattern for preventing directory traversal attacks:
            for abs_file in util.maybe_recursive_iglob(os.path.normpath(pattern)):
                # Recursive matching is only supported starting with Python 3.5,
                # so we allow the user to match directories and transfer them recursively.
                if os.path.isdir(abs_file):
                    for root, unused_dirs, files in os.walk(abs_file):
                        for file in files:
                            transfer_file(os.path.join(root, file))
                else:
                    transfer_file(abs_file)