Blame org_fedora_oscap/utils.py

Packit 792a06
#
Packit 792a06
# Copyright (C) 2013  Red Hat, Inc.
Packit 792a06
#
Packit 792a06
# This copyrighted material is made available to anyone wishing to use,
Packit 792a06
# modify, copy, or redistribute it subject to the terms and conditions of
Packit 792a06
# the GNU General Public License v.2, or (at your option) any later version.
Packit 792a06
# This program is distributed in the hope that it will be useful, but WITHOUT
Packit 792a06
# ANY WARRANTY expressed or implied, including the implied warranties of
Packit 792a06
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
Packit 792a06
# Public License for more details.  You should have received a copy of the
Packit 792a06
# GNU General Public License along with this program; if not, write to the
Packit 792a06
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit 792a06
# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
Packit 792a06
# source code or documentation are not subject to the GNU General Public
Packit 792a06
# License and may only be used or replicated with the express permission of
Packit 792a06
# Red Hat, Inc.
Packit 792a06
#
Packit 792a06
# Red Hat Author(s): Vratislav Podzimek <vpodzime@redhat.com>
Packit 792a06
#
Packit 792a06
Packit 792a06
"""Module with various utility functions used by the addon."""
Packit 792a06
Packit 792a06
import os
Packit 792a06
import os.path
Packit 792a06
import shutil
Packit 792a06
import glob
Packit 792a06
import hashlib
Packit 792a06
Packit 792a06
Packit 792a06
def ensure_dir_exists(dirpath):
Packit 792a06
    """
Packit 792a06
    Checks if a given directory exists and if not, it creates the directory as
Packit 792a06
    well as all the nonexisting directories in its path.
Packit 792a06
Packit 792a06
    :param dirpath: path to the directory to be checked/created
Packit 792a06
    :type dirpath: str
Packit 792a06
Packit 792a06
    """
Packit 792a06
Packit 792a06
    if not dirpath:
Packit 792a06
        # nothing can be done for an empty string
Packit 792a06
        return
Packit 792a06
Packit 792a06
    if not os.path.isdir(dirpath):
Packit 792a06
        os.makedirs(dirpath)
Packit 792a06
Packit 792a06
Packit 792a06
def universal_copy(src, dst):
Packit 792a06
    """
Packit 792a06
    Function that copies the files or directories specified by the src argument
Packit 792a06
    to the destination given by the dst argument. It should follow the same
Packit 792a06
    rules as the standard 'cp' utility.
Packit 792a06
Packit 792a06
    :param src: source to copy -- may be a glob, file path or a directory path
Packit 792a06
    :type src: str
Packit 792a06
    :param dst: destination to copy to
Packit 792a06
    :type src: str
Packit 792a06
Packit 792a06
    """
Packit 792a06
Packit 792a06
    if glob.has_magic(src):
Packit 792a06
        # src is a glob
Packit 792a06
        sources = glob.glob(src)
Packit 792a06
    else:
Packit 792a06
        # not a glob
Packit 792a06
        sources = [src]
Packit 792a06
Packit 792a06
    for item in sources:
Packit 792a06
        if os.path.isdir(item):
Packit 792a06
            if os.path.isdir(dst):
Packit 792a06
                item = item.rstrip("/")
Packit 792a06
                dirname = item.rsplit("/", 1)[-1]
Packit 792a06
                shutil.copytree(item, join_paths(dst, dirname))
Packit 792a06
            else:
Packit 792a06
                shutil.copytree(item, dst)
Packit 792a06
        else:
Packit 792a06
            shutil.copy2(item, dst)
Packit 792a06
Packit 792a06
Packit 792a06
def keep_type_map(func, iterable):
Packit 792a06
    """
Packit 792a06
    Function that maps the given function to items in the given iterable
Packit 792a06
    keeping the type of the iterable.
Packit 792a06
Packit 792a06
    :param func: function to be mapped on the items in the iterable
Packit 792a06
    :type func: in_item -> out_item
Packit 792a06
    :param iterable: iterable providing the items the function should be mapped
Packit 792a06
                     on
Packit 792a06
    :type iterable: iterable
Packit 792a06
    :return: iterable providing items produced by the function mapped on the
Packit 792a06
             input items
Packit 792a06
    :rtype: the same type as input iterable or generator if the iterable is not
Packit 792a06
            of any basic Python types
Packit 792a06
Packit 792a06
    """
Packit 792a06
Packit 792a06
    if isinstance(iterable, dict):
Packit 792a06
        return dict((func(key), iterable[key]) for key in iterable)
Packit 792a06
Packit 792a06
    items_gen = (func(item) for item in iterable)
Packit 792a06
    if isinstance(iterable, list):
Packit 792a06
        return list(items_gen)
Packit 792a06
    elif isinstance(iterable, tuple):
Packit 792a06
        if iterable.__class__ is tuple:
Packit 792a06
            return tuple(items_gen)
Packit 792a06
        else:
Packit 792a06
            return iterable.__class__(*items_gen)
Packit 792a06
    elif isinstance(iterable, set):
Packit 792a06
        return set(items_gen)
Packit 792a06
    elif isinstance(iterable, str):
Packit 792a06
        return "".join(items_gen)
Packit 792a06
    else:
Packit 792a06
        return items_gen
Packit 792a06
Packit 792a06
Packit 792a06
def join_paths(path1, path2):
Packit 792a06
    """
Packit 792a06
    Joins two paths as one would expect -- i.e. just like the os.path.join
Packit 792a06
    function except for doing crazy things when the second argument is an
Packit 792a06
    absolute path.
Packit 792a06
Packit 792a06
    :param path1: first path
Packit 792a06
    :type path1: str
Packit 792a06
    :param path2: second path
Packit 792a06
    :type path2: str
Packit 792a06
    :return: path1 and path2 joined with the file separator
Packit 792a06
    :rtype: str
Packit 792a06
Packit 792a06
    """
Packit 792a06
Packit 792a06
    # os.path.normpath doesn't squash two starting slashes
Packit 792a06
    path1.replace("//", "/")
Packit 792a06
Packit 792a06
    return os.path.normpath(path1 + os.path.sep + path2)
Packit 792a06
Packit 792a06
Packit 792a06
def get_hashing_algorithm(fingerprint):
Packit 792a06
    """
Packit 792a06
    Get hashing algorithm for the given fingerprint or None if fingerprint of
Packit 792a06
    unsupported length is given.
Packit 792a06
Packit 792a06
    :param fingerprint: hexa fingerprint to get the hashing algorithm for
Packit 792a06
    :type fingerprint: hexadecimal str
Packit 792a06
    :return: one of the hashlib.* hash objects
Packit 792a06
    :rtype: hashlib.HASH object
Packit 792a06
Packit 792a06
    """
Packit 792a06
Packit 792a06
    hashes = (hashlib.md5(), hashlib.sha1(), hashlib.sha224(),
Packit 792a06
              hashlib.sha256(), hashlib.sha384(), hashlib.sha512())
Packit 792a06
Packit 792a06
    if len(fingerprint) % 2 == 1:
Packit 792a06
        return None
Packit 792a06
Packit 792a06
    num_bytes = len(fingerprint) / 2
Packit 792a06
Packit 792a06
    for hash_obj in hashes:
Packit 792a06
        # pylint: disable-msg=E1103
Packit 792a06
        if hash_obj.digest_size == num_bytes:
Packit 792a06
            return hash_obj
Packit 792a06
Packit 792a06
    return None
Packit 792a06
Packit 792a06
Packit 792a06
def get_file_fingerprint(fpath, hash_obj):
Packit 792a06
    """
Packit 792a06
    Get fingerprint of the given file with the given hashing algorithm.
Packit 792a06
Packit 792a06
    :param fpath: path to the file to get fingerprint for
Packit 792a06
    :type fpath: str
Packit 792a06
    :param hash_obj: hashing algorithm to get fingerprint with
Packit 792a06
    :type hash_obj: hashlib.HASH
Packit 792a06
    :return: fingerprint of the given file with the given algorithm
Packit 792a06
    :rtype: hexadecimal str
Packit 792a06
Packit 792a06
    """
Packit 792a06
Packit 792a06
    with open(fpath, "rb") as fobj:
Packit 792a06
        bsize = 4 * 1024
Packit 792a06
        # process file as 4 KB blocks
Packit 792a06
        buf = fobj.read(bsize)
Packit 792a06
        while buf:
Packit 792a06
            hash_obj.update(buf)
Packit 792a06
            buf = fobj.read(bsize)
Packit 792a06
Packit 792a06
    return hash_obj.hexdigest()