org_fedora_oscap.utils   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 187
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 23
eloc 59
dl 0
loc 187
rs 10
c 0
b 0
f 0

6 Functions

Rating   Name   Duplication   Size   Complexity  
A universal_copy() 0 30 5
A join_paths() 0 19 1
A ensure_dir_exists() 0 16 3
A get_file_fingerprint() 0 22 3
A get_hashing_algorithm() 0 26 4
B keep_type_map() 0 34 7
1
#
2
# Copyright (C) 2013  Red Hat, Inc.
3
#
4
# This copyrighted material is made available to anyone wishing to use,
5
# modify, copy, or redistribute it subject to the terms and conditions of
6
# the GNU General Public License v.2, or (at your option) any later version.
7
# This program is distributed in the hope that it will be useful, but WITHOUT
8
# ANY WARRANTY expressed or implied, including the implied warranties of
9
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
10
# Public License for more details.  You should have received a copy of the
11
# GNU General Public License along with this program; if not, write to the
12
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
13
# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
14
# source code or documentation are not subject to the GNU General Public
15
# License and may only be used or replicated with the express permission of
16
# Red Hat, Inc.
17
#
18
# Red Hat Author(s): Vratislav Podzimek <[email protected]>
19
#
20
21
"""Module with various utility functions used by the addon."""
22
23
import os
24
import os.path
25
import shutil
26
import glob
27
import hashlib
28
29
30
def ensure_dir_exists(dirpath):
31
    """
32
    Checks if a given directory exists and if not, it creates the directory as
33
    well as all the nonexisting directories in its path.
34
35
    :param dirpath: path to the directory to be checked/created
36
    :type dirpath: str
37
38
    """
39
40
    if not dirpath:
41
        # nothing can be done for an empty string
42
        return
43
44
    if not os.path.isdir(dirpath):
45
        os.makedirs(dirpath)
46
47
48
def universal_copy(src, dst):
49
    """
50
    Function that copies the files or directories specified by the src argument
51
    to the destination given by the dst argument. It should follow the same
52
    rules as the standard 'cp' utility.
53
54
    :param src: source to copy -- may be a glob, file path or a directory path
55
    :type src: str
56
    :param dst: destination to copy to
57
    :type src: str
58
59
    """
60
61
    if glob.has_magic(src):
62
        # src is a glob
63
        sources = glob.glob(src)
64
    else:
65
        # not a glob
66
        sources = [src]
67
68
    for item in sources:
69
        if os.path.isdir(item):
70
            if os.path.isdir(dst):
71
                item = item.rstrip("/")
72
                dirname = item.rsplit("/", 1)[-1]
73
                shutil.copytree(item, join_paths(dst, dirname))
74
            else:
75
                shutil.copytree(item, dst)
76
        else:
77
            shutil.copy2(item, dst)
78
79
80
def keep_type_map(func, iterable):
81
    """
82
    Function that maps the given function to items in the given iterable
83
    keeping the type of the iterable.
84
85
    :param func: function to be mapped on the items in the iterable
86
    :type func: in_item -> out_item
87
    :param iterable: iterable providing the items the function should be mapped
88
                     on
89
    :type iterable: iterable
90
    :return: iterable providing items produced by the function mapped on the
91
             input items
92
    :rtype: the same type as input iterable or generator if the iterable is not
93
            of any basic Python types
94
95
    """
96
97
    if isinstance(iterable, dict):
98
        return dict((func(key), iterable[key]) for key in iterable)
99
100
    items_gen = (func(item) for item in iterable)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable item does not seem to be defined.
Loading history...
101
    if isinstance(iterable, list):
102
        return list(items_gen)
103
    elif isinstance(iterable, tuple):
104
        if iterable.__class__ is tuple:
105
            return tuple(items_gen)
106
        else:
107
            return iterable.__class__(*items_gen)
108
    elif isinstance(iterable, set):
109
        return set(items_gen)
110
    elif isinstance(iterable, str):
111
        return "".join(items_gen)
112
    else:
113
        return items_gen
114
115
116
def join_paths(path1, path2):
117
    """
118
    Joins two paths as one would expect -- i.e. just like the os.path.join
119
    function except for doing crazy things when the second argument is an
120
    absolute path.
121
122
    :param path1: first path
123
    :type path1: str
124
    :param path2: second path
125
    :type path2: str
126
    :return: path1 and path2 joined with the file separator
127
    :rtype: str
128
129
    """
130
131
    # os.path.normpath doesn't squash two starting slashes
132
    path1.replace("//", "/")
133
134
    return os.path.normpath(path1 + os.path.sep + path2)
135
136
137
def get_hashing_algorithm(fingerprint):
138
    """
139
    Get hashing algorithm for the given fingerprint or None if fingerprint of
140
    unsupported length is given.
141
142
    :param fingerprint: hexa fingerprint to get the hashing algorithm for
143
    :type fingerprint: hexadecimal str
144
    :return: one of the hashlib.* hash objects
145
    :rtype: hashlib.HASH object
146
147
    """
148
149
    hashes = (hashlib.md5(), hashlib.sha1(), hashlib.sha224(),
150
              hashlib.sha256(), hashlib.sha384(), hashlib.sha512())
151
152
    if len(fingerprint) % 2 == 1:
153
        return None
154
155
    num_bytes = len(fingerprint) / 2
156
157
    for hash_obj in hashes:
158
        # pylint: disable-msg=E1103
159
        if hash_obj.digest_size == num_bytes:
160
            return hash_obj
161
162
    return None
163
164
165
def get_file_fingerprint(fpath, hash_obj):
166
    """
167
    Get fingerprint of the given file with the given hashing algorithm.
168
169
    :param fpath: path to the file to get fingerprint for
170
    :type fpath: str
171
    :param hash_obj: hashing algorithm to get fingerprint with
172
    :type hash_obj: hashlib.HASH
173
    :return: fingerprint of the given file with the given algorithm
174
    :rtype: hexadecimal str
175
176
    """
177
178
    with open(fpath, "rb") as fobj:
179
        bsize = 4 * 1024
180
        # process file as 4 KB blocks
181
        buf = fobj.read(bsize)
182
        while buf:
183
            hash_obj.update(buf)
184
            buf = fobj.read(bsize)
185
186
    return hash_obj.hexdigest()
187