xref: /openbmc/u-boot/tools/patman/tools.py (revision afaea1f5)
1# SPDX-License-Identifier: GPL-2.0+
2#
3# Copyright (c) 2016 Google, Inc
4#
5
6import command
7import os
8import shutil
9import tempfile
10
11import tout
12
13# Output directly (generally this is temporary)
14outdir = None
15
16# True to keep the output directory around after exiting
17preserve_outdir = False
18
19# Path to the Chrome OS chroot, if we know it
20chroot_path = None
21
22# Search paths to use for Filename(), used to find files
23search_paths = []
24
25
26def PrepareOutputDir(dirname, preserve=False):
27    """Select an output directory, ensuring it exists.
28
29    This either creates a temporary directory or checks that the one supplied
30    by the user is valid. For a temporary directory, it makes a note to
31    remove it later if required.
32
33    Args:
34        dirname: a string, name of the output directory to use to store
35                intermediate and output files. If is None - create a temporary
36                directory.
37        preserve: a Boolean. If outdir above is None and preserve is False, the
38                created temporary directory will be destroyed on exit.
39
40    Raises:
41        OSError: If it cannot create the output directory.
42    """
43    global outdir, preserve_outdir
44
45    preserve_outdir = dirname or preserve
46    if dirname:
47        outdir = dirname
48        if not os.path.isdir(outdir):
49            try:
50                os.makedirs(outdir)
51            except OSError as err:
52                raise CmdError("Cannot make output directory '%s': '%s'" %
53                                (outdir, err.strerror))
54        tout.Debug("Using output directory '%s'" % outdir)
55    else:
56        outdir = tempfile.mkdtemp(prefix='binman.')
57        tout.Debug("Using temporary directory '%s'" % outdir)
58
59def _RemoveOutputDir():
60    global outdir
61
62    shutil.rmtree(outdir)
63    tout.Debug("Deleted temporary directory '%s'" % outdir)
64    outdir = None
65
66def FinaliseOutputDir():
67    global outdir, preserve_outdir
68
69    """Tidy up: delete output directory if temporary and not preserved."""
70    if outdir and not preserve_outdir:
71        _RemoveOutputDir()
72
73def GetOutputFilename(fname):
74    """Return a filename within the output directory.
75
76    Args:
77        fname: Filename to use for new file
78
79    Returns:
80        The full path of the filename, within the output directory
81    """
82    return os.path.join(outdir, fname)
83
84def _FinaliseForTest():
85    """Remove the output directory (for use by tests)"""
86    global outdir
87
88    if outdir:
89        _RemoveOutputDir()
90
91def SetInputDirs(dirname):
92    """Add a list of input directories, where input files are kept.
93
94    Args:
95        dirname: a list of paths to input directories to use for obtaining
96                files needed by binman to place in the image.
97    """
98    global indir
99
100    indir = dirname
101    tout.Debug("Using input directories %s" % indir)
102
103def GetInputFilename(fname):
104    """Return a filename for use as input.
105
106    Args:
107        fname: Filename to use for new file
108
109    Returns:
110        The full path of the filename, within the input directory
111    """
112    if not indir:
113        return fname
114    for dirname in indir:
115        pathname = os.path.join(dirname, fname)
116        if os.path.exists(pathname):
117            return pathname
118
119    raise ValueError("Filename '%s' not found in input path (%s) (cwd='%s')" %
120                     (fname, ','.join(indir), os.getcwd()))
121
122def Align(pos, align):
123    if align:
124        mask = align - 1
125        pos = (pos + mask) & ~mask
126    return pos
127
128def NotPowerOfTwo(num):
129    return num and (num & (num - 1))
130
131def Run(name, *args):
132    command.Run(name, *args, cwd=outdir)
133
134def Filename(fname):
135    """Resolve a file path to an absolute path.
136
137    If fname starts with ##/ and chroot is available, ##/ gets replaced with
138    the chroot path. If chroot is not available, this file name can not be
139    resolved, `None' is returned.
140
141    If fname is not prepended with the above prefix, and is not an existing
142    file, the actual file name is retrieved from the passed in string and the
143    search_paths directories (if any) are searched to for the file. If found -
144    the path to the found file is returned, `None' is returned otherwise.
145
146    Args:
147      fname: a string,  the path to resolve.
148
149    Returns:
150      Absolute path to the file or None if not found.
151    """
152    if fname.startswith('##/'):
153      if chroot_path:
154        fname = os.path.join(chroot_path, fname[3:])
155      else:
156        return None
157
158    # Search for a pathname that exists, and return it if found
159    if fname and not os.path.exists(fname):
160        for path in search_paths:
161            pathname = os.path.join(path, os.path.basename(fname))
162            if os.path.exists(pathname):
163                return pathname
164
165    # If not found, just return the standard, unchanged path
166    return fname
167
168def ReadFile(fname):
169    """Read and return the contents of a file.
170
171    Args:
172      fname: path to filename to read, where ## signifiies the chroot.
173
174    Returns:
175      data read from file, as a string.
176    """
177    with open(Filename(fname), 'rb') as fd:
178        data = fd.read()
179    #self._out.Info("Read file '%s' size %d (%#0x)" %
180                   #(fname, len(data), len(data)))
181    return data
182
183def WriteFile(fname, data):
184    """Write data into a file.
185
186    Args:
187        fname: path to filename to write
188        data: data to write to file, as a string
189    """
190    #self._out.Info("Write file '%s' size %d (%#0x)" %
191                   #(fname, len(data), len(data)))
192    with open(Filename(fname), 'wb') as fd:
193        fd.write(data)
194