1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# Copyright (c) 2016 Google, Inc 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0+ 5*4882a593Smuzhiyun# 6*4882a593Smuzhiyun 7*4882a593Smuzhiyunimport os 8*4882a593Smuzhiyunimport shutil 9*4882a593Smuzhiyunimport tempfile 10*4882a593Smuzhiyun 11*4882a593Smuzhiyunimport tout 12*4882a593Smuzhiyun 13*4882a593Smuzhiyunoutdir = None 14*4882a593Smuzhiyunindirs = None 15*4882a593Smuzhiyunpreserve_outdir = False 16*4882a593Smuzhiyun 17*4882a593Smuzhiyundef PrepareOutputDir(dirname, preserve=False): 18*4882a593Smuzhiyun """Select an output directory, ensuring it exists. 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun This either creates a temporary directory or checks that the one supplied 21*4882a593Smuzhiyun by the user is valid. For a temporary directory, it makes a note to 22*4882a593Smuzhiyun remove it later if required. 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun Args: 25*4882a593Smuzhiyun dirname: a string, name of the output directory to use to store 26*4882a593Smuzhiyun intermediate and output files. If is None - create a temporary 27*4882a593Smuzhiyun directory. 28*4882a593Smuzhiyun preserve: a Boolean. If outdir above is None and preserve is False, the 29*4882a593Smuzhiyun created temporary directory will be destroyed on exit. 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun Raises: 32*4882a593Smuzhiyun OSError: If it cannot create the output directory. 33*4882a593Smuzhiyun """ 34*4882a593Smuzhiyun global outdir, preserve_outdir 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun preserve_outdir = dirname or preserve 37*4882a593Smuzhiyun if dirname: 38*4882a593Smuzhiyun outdir = dirname 39*4882a593Smuzhiyun if not os.path.isdir(outdir): 40*4882a593Smuzhiyun try: 41*4882a593Smuzhiyun os.makedirs(outdir) 42*4882a593Smuzhiyun except OSError as err: 43*4882a593Smuzhiyun raise CmdError("Cannot make output directory '%s': '%s'" % 44*4882a593Smuzhiyun (outdir, err.strerror)) 45*4882a593Smuzhiyun tout.Debug("Using output directory '%s'" % outdir) 46*4882a593Smuzhiyun else: 47*4882a593Smuzhiyun outdir = tempfile.mkdtemp(prefix='binman.') 48*4882a593Smuzhiyun tout.Debug("Using temporary directory '%s'" % outdir) 49*4882a593Smuzhiyun 50*4882a593Smuzhiyundef _RemoveOutputDir(): 51*4882a593Smuzhiyun global outdir 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun shutil.rmtree(outdir) 54*4882a593Smuzhiyun tout.Debug("Deleted temporary directory '%s'" % outdir) 55*4882a593Smuzhiyun outdir = None 56*4882a593Smuzhiyun 57*4882a593Smuzhiyundef FinaliseOutputDir(): 58*4882a593Smuzhiyun global outdir, preserve_outdir 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun """Tidy up: delete output directory if temporary and not preserved.""" 61*4882a593Smuzhiyun if outdir and not preserve_outdir: 62*4882a593Smuzhiyun _RemoveOutputDir() 63*4882a593Smuzhiyun 64*4882a593Smuzhiyundef GetOutputFilename(fname): 65*4882a593Smuzhiyun """Return a filename within the output directory. 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun Args: 68*4882a593Smuzhiyun fname: Filename to use for new file 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun Returns: 71*4882a593Smuzhiyun The full path of the filename, within the output directory 72*4882a593Smuzhiyun """ 73*4882a593Smuzhiyun return os.path.join(outdir, fname) 74*4882a593Smuzhiyun 75*4882a593Smuzhiyundef _FinaliseForTest(): 76*4882a593Smuzhiyun """Remove the output directory (for use by tests)""" 77*4882a593Smuzhiyun global outdir 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun if outdir: 80*4882a593Smuzhiyun _RemoveOutputDir() 81*4882a593Smuzhiyun 82*4882a593Smuzhiyundef SetInputDirs(dirname): 83*4882a593Smuzhiyun """Add a list of input directories, where input files are kept. 84*4882a593Smuzhiyun 85*4882a593Smuzhiyun Args: 86*4882a593Smuzhiyun dirname: a list of paths to input directories to use for obtaining 87*4882a593Smuzhiyun files needed by binman to place in the image. 88*4882a593Smuzhiyun """ 89*4882a593Smuzhiyun global indir 90*4882a593Smuzhiyun 91*4882a593Smuzhiyun indir = dirname 92*4882a593Smuzhiyun tout.Debug("Using input directories %s" % indir) 93*4882a593Smuzhiyun 94*4882a593Smuzhiyundef GetInputFilename(fname): 95*4882a593Smuzhiyun """Return a filename for use as input. 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun Args: 98*4882a593Smuzhiyun fname: Filename to use for new file 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun Returns: 101*4882a593Smuzhiyun The full path of the filename, within the input directory 102*4882a593Smuzhiyun """ 103*4882a593Smuzhiyun if not indir: 104*4882a593Smuzhiyun return fname 105*4882a593Smuzhiyun for dirname in indir: 106*4882a593Smuzhiyun pathname = os.path.join(dirname, fname) 107*4882a593Smuzhiyun if os.path.exists(pathname): 108*4882a593Smuzhiyun return pathname 109*4882a593Smuzhiyun 110*4882a593Smuzhiyun raise ValueError("Filename '%s' not found in input path (%s)" % 111*4882a593Smuzhiyun (fname, ','.join(indir))) 112*4882a593Smuzhiyun 113*4882a593Smuzhiyundef Align(pos, align): 114*4882a593Smuzhiyun if align: 115*4882a593Smuzhiyun mask = align - 1 116*4882a593Smuzhiyun pos = (pos + mask) & ~mask 117*4882a593Smuzhiyun return pos 118*4882a593Smuzhiyun 119*4882a593Smuzhiyundef NotPowerOfTwo(num): 120*4882a593Smuzhiyun return num and (num & (num - 1)) 121