summaryrefslogtreecommitdiffstats
path: root/scripts/lib
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/lib')
-rw-r--r--scripts/lib/buildstats.py4
-rw-r--r--scripts/lib/checklayer/__init__.py11
-rw-r--r--scripts/lib/checklayer/cases/common.py2
-rw-r--r--scripts/lib/devtool/deploy.py12
-rw-r--r--scripts/lib/devtool/menuconfig.py2
-rw-r--r--scripts/lib/devtool/standard.py9
-rw-r--r--scripts/lib/recipetool/create.py18
-rw-r--r--scripts/lib/resulttool/report.py5
-rw-r--r--scripts/lib/resulttool/resultutils.py8
-rw-r--r--scripts/lib/scriptutils.py10
-rw-r--r--scripts/lib/wic/engine.py6
-rw-r--r--scripts/lib/wic/help.py4
-rw-r--r--scripts/lib/wic/misc.py17
-rw-r--r--scripts/lib/wic/partition.py40
-rw-r--r--scripts/lib/wic/pluginbase.py8
-rw-r--r--scripts/lib/wic/plugins/imager/direct.py2
-rw-r--r--scripts/lib/wic/plugins/source/bootimg-efi.py7
-rw-r--r--scripts/lib/wic/plugins/source/bootimg-pcbios.py6
18 files changed, 130 insertions, 41 deletions
diff --git a/scripts/lib/buildstats.py b/scripts/lib/buildstats.py
index c69b5bf4d7..3b76286ba5 100644
--- a/scripts/lib/buildstats.py
+++ b/scripts/lib/buildstats.py
@@ -8,7 +8,7 @@ import json
8import logging 8import logging
9import os 9import os
10import re 10import re
11from collections import namedtuple,OrderedDict 11from collections import namedtuple
12from statistics import mean 12from statistics import mean
13 13
14 14
@@ -238,7 +238,7 @@ class BuildStats(dict):
238 subdirs = os.listdir(path) 238 subdirs = os.listdir(path)
239 for dirname in subdirs: 239 for dirname in subdirs:
240 recipe_dir = os.path.join(path, dirname) 240 recipe_dir = os.path.join(path, dirname)
241 if not os.path.isdir(recipe_dir): 241 if dirname == "reduced_proc_pressure" or not os.path.isdir(recipe_dir):
242 continue 242 continue
243 name, epoch, version, revision = cls.split_nevr(dirname) 243 name, epoch, version, revision = cls.split_nevr(dirname)
244 bsrecipe = BSRecipe(name, epoch, version, revision) 244 bsrecipe = BSRecipe(name, epoch, version, revision)
diff --git a/scripts/lib/checklayer/__init__.py b/scripts/lib/checklayer/__init__.py
index fe545607bb..e69a10f452 100644
--- a/scripts/lib/checklayer/__init__.py
+++ b/scripts/lib/checklayer/__init__.py
@@ -146,7 +146,7 @@ def detect_layers(layer_directories, no_auto):
146 146
147 return layers 147 return layers
148 148
149def _find_layer_depends(depend, layers): 149def _find_layer(depend, layers):
150 for layer in layers: 150 for layer in layers:
151 if 'collections' not in layer: 151 if 'collections' not in layer:
152 continue 152 continue
@@ -156,7 +156,7 @@ def _find_layer_depends(depend, layers):
156 return layer 156 return layer
157 return None 157 return None
158 158
159def add_layer_dependencies(bblayersconf, layer, layers, logger): 159def get_layer_dependencies(layer, layers, logger):
160 def recurse_dependencies(depends, layer, layers, logger, ret = []): 160 def recurse_dependencies(depends, layer, layers, logger, ret = []):
161 logger.debug('Processing dependencies %s for layer %s.' % \ 161 logger.debug('Processing dependencies %s for layer %s.' % \
162 (depends, layer['name'])) 162 (depends, layer['name']))
@@ -166,7 +166,7 @@ def add_layer_dependencies(bblayersconf, layer, layers, logger):
166 if depend == 'core': 166 if depend == 'core':
167 continue 167 continue
168 168
169 layer_depend = _find_layer_depends(depend, layers) 169 layer_depend = _find_layer(depend, layers)
170 if not layer_depend: 170 if not layer_depend:
171 logger.error('Layer %s depends on %s and isn\'t found.' % \ 171 logger.error('Layer %s depends on %s and isn\'t found.' % \
172 (layer['name'], depend)) 172 (layer['name'], depend))
@@ -203,6 +203,11 @@ def add_layer_dependencies(bblayersconf, layer, layers, logger):
203 layer_depends = recurse_dependencies(depends, layer, layers, logger, layer_depends) 203 layer_depends = recurse_dependencies(depends, layer, layers, logger, layer_depends)
204 204
205 # Note: [] (empty) is allowed, None is not! 205 # Note: [] (empty) is allowed, None is not!
206 return layer_depends
207
208def add_layer_dependencies(bblayersconf, layer, layers, logger):
209
210 layer_depends = get_layer_dependencies(layer, layers, logger)
206 if layer_depends is None: 211 if layer_depends is None:
207 return False 212 return False
208 else: 213 else:
diff --git a/scripts/lib/checklayer/cases/common.py b/scripts/lib/checklayer/cases/common.py
index b82304e361..4495f71b24 100644
--- a/scripts/lib/checklayer/cases/common.py
+++ b/scripts/lib/checklayer/cases/common.py
@@ -14,7 +14,7 @@ class CommonCheckLayer(OECheckLayerTestCase):
14 # The top-level README file may have a suffix (like README.rst or README.txt). 14 # The top-level README file may have a suffix (like README.rst or README.txt).
15 readme_files = glob.glob(os.path.join(self.tc.layer['path'], '[Rr][Ee][Aa][Dd][Mm][Ee]*')) 15 readme_files = glob.glob(os.path.join(self.tc.layer['path'], '[Rr][Ee][Aa][Dd][Mm][Ee]*'))
16 self.assertTrue(len(readme_files) > 0, 16 self.assertTrue(len(readme_files) > 0,
17 msg="Layer doesn't contains README file.") 17 msg="Layer doesn't contain a README file.")
18 18
19 # There might be more than one file matching the file pattern above 19 # There might be more than one file matching the file pattern above
20 # (for example, README.rst and README-COPYING.rst). The one with the shortest 20 # (for example, README.rst and README-COPYING.rst). The one with the shortest
diff --git a/scripts/lib/devtool/deploy.py b/scripts/lib/devtool/deploy.py
index aaa25dda08..b4f9fbfe45 100644
--- a/scripts/lib/devtool/deploy.py
+++ b/scripts/lib/devtool/deploy.py
@@ -168,9 +168,9 @@ def deploy(args, config, basepath, workspace):
168 if args.strip and not args.dry_run: 168 if args.strip and not args.dry_run:
169 # Fakeroot copy to new destination 169 # Fakeroot copy to new destination
170 srcdir = recipe_outdir 170 srcdir = recipe_outdir
171 recipe_outdir = os.path.join(rd.getVar('WORKDIR'), 'deploy-target-stripped') 171 recipe_outdir = os.path.join(rd.getVar('WORKDIR'), 'devtool-deploy-target-stripped')
172 if os.path.isdir(recipe_outdir): 172 if os.path.isdir(recipe_outdir):
173 bb.utils.remove(recipe_outdir, True) 173 exec_fakeroot(rd, "rm -rf %s" % recipe_outdir, shell=True)
174 exec_fakeroot(rd, "cp -af %s %s" % (os.path.join(srcdir, '.'), recipe_outdir), shell=True) 174 exec_fakeroot(rd, "cp -af %s %s" % (os.path.join(srcdir, '.'), recipe_outdir), shell=True)
175 os.environ['PATH'] = ':'.join([os.environ['PATH'], rd.getVar('PATH') or '']) 175 os.environ['PATH'] = ':'.join([os.environ['PATH'], rd.getVar('PATH') or ''])
176 oe.package.strip_execs(args.recipename, recipe_outdir, rd.getVar('STRIP'), rd.getVar('libdir'), 176 oe.package.strip_execs(args.recipename, recipe_outdir, rd.getVar('STRIP'), rd.getVar('libdir'),
@@ -201,9 +201,9 @@ def deploy(args, config, basepath, workspace):
201 print(' %s' % item) 201 print(' %s' % item)
202 return 0 202 return 0
203 203
204 extraoptions = '' 204 extraoptions = '-o HostKeyAlgorithms=+ssh-rsa'
205 if args.no_host_check: 205 if args.no_host_check:
206 extraoptions += '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' 206 extraoptions += ' -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
207 if not args.show_status: 207 if not args.show_status:
208 extraoptions += ' -q' 208 extraoptions += ' -q'
209 209
@@ -274,9 +274,9 @@ def undeploy(args, config, basepath, workspace):
274 elif not args.recipename and not args.all: 274 elif not args.recipename and not args.all:
275 raise argparse_oe.ArgumentUsageError('If you don\'t specify a recipe, you must specify -a/--all', 'undeploy-target') 275 raise argparse_oe.ArgumentUsageError('If you don\'t specify a recipe, you must specify -a/--all', 'undeploy-target')
276 276
277 extraoptions = '' 277 extraoptions = '-o HostKeyAlgorithms=+ssh-rsa'
278 if args.no_host_check: 278 if args.no_host_check:
279 extraoptions += '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' 279 extraoptions += ' -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
280 if not args.show_status: 280 if not args.show_status:
281 extraoptions += ' -q' 281 extraoptions += ' -q'
282 282
diff --git a/scripts/lib/devtool/menuconfig.py b/scripts/lib/devtool/menuconfig.py
index 95384c5333..ff9227035d 100644
--- a/scripts/lib/devtool/menuconfig.py
+++ b/scripts/lib/devtool/menuconfig.py
@@ -43,7 +43,7 @@ def menuconfig(args, config, basepath, workspace):
43 return 1 43 return 1
44 44
45 check_workspace_recipe(workspace, args.component) 45 check_workspace_recipe(workspace, args.component)
46 pn = rd.getVar('PN', True) 46 pn = rd.getVar('PN')
47 47
48 if not rd.getVarFlag('do_menuconfig','task'): 48 if not rd.getVarFlag('do_menuconfig','task'):
49 raise DevtoolError("This recipe does not support menuconfig option") 49 raise DevtoolError("This recipe does not support menuconfig option")
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py
index 7b62b7e7b8..cfa88616af 100644
--- a/scripts/lib/devtool/standard.py
+++ b/scripts/lib/devtool/standard.py
@@ -357,7 +357,7 @@ def _move_file(src, dst, dry_run_outdir=None, base_outdir=None):
357 bb.utils.mkdirhier(dst_d) 357 bb.utils.mkdirhier(dst_d)
358 shutil.move(src, dst) 358 shutil.move(src, dst)
359 359
360def _copy_file(src, dst, dry_run_outdir=None): 360def _copy_file(src, dst, dry_run_outdir=None, base_outdir=None):
361 """Copy a file. Creates all the directory components of destination path.""" 361 """Copy a file. Creates all the directory components of destination path."""
362 dry_run_suffix = ' (dry-run)' if dry_run_outdir else '' 362 dry_run_suffix = ' (dry-run)' if dry_run_outdir else ''
363 logger.debug('Copying %s to %s%s' % (src, dst, dry_run_suffix)) 363 logger.debug('Copying %s to %s%s' % (src, dst, dry_run_suffix))
@@ -953,12 +953,17 @@ def modify(args, config, basepath, workspace):
953 953
954 if bb.data.inherits_class('kernel', rd): 954 if bb.data.inherits_class('kernel', rd):
955 f.write('SRCTREECOVEREDTASKS = "do_validate_branches do_kernel_checkout ' 955 f.write('SRCTREECOVEREDTASKS = "do_validate_branches do_kernel_checkout '
956 'do_fetch do_unpack do_kernel_configme do_kernel_configcheck"\n') 956 'do_fetch do_unpack do_kernel_configcheck"\n')
957 f.write('\ndo_patch[noexec] = "1"\n') 957 f.write('\ndo_patch[noexec] = "1"\n')
958 f.write('\ndo_configure_append() {\n' 958 f.write('\ndo_configure_append() {\n'
959 ' cp ${B}/.config ${S}/.config.baseline\n' 959 ' cp ${B}/.config ${S}/.config.baseline\n'
960 ' ln -sfT ${B}/.config ${S}/.config.new\n' 960 ' ln -sfT ${B}/.config ${S}/.config.new\n'
961 '}\n') 961 '}\n')
962 f.write('\ndo_kernel_configme_prepend() {\n'
963 ' if [ -e ${S}/.config ]; then\n'
964 ' mv ${S}/.config ${S}/.config.old\n'
965 ' fi\n'
966 '}\n')
962 if rd.getVarFlag('do_menuconfig','task'): 967 if rd.getVarFlag('do_menuconfig','task'):
963 f.write('\ndo_configure_append() {\n' 968 f.write('\ndo_configure_append() {\n'
964 ' if [ ! ${DEVTOOL_DISABLE_MENUCONFIG} ]; then\n' 969 ' if [ ! ${DEVTOOL_DISABLE_MENUCONFIG} ]; then\n'
diff --git a/scripts/lib/recipetool/create.py b/scripts/lib/recipetool/create.py
index 566c75369a..a2c6d052a6 100644
--- a/scripts/lib/recipetool/create.py
+++ b/scripts/lib/recipetool/create.py
@@ -435,7 +435,7 @@ def create_recipe(args):
435 if args.binary: 435 if args.binary:
436 # Assume the archive contains the directory structure verbatim 436 # Assume the archive contains the directory structure verbatim
437 # so we need to extract to a subdirectory 437 # so we need to extract to a subdirectory
438 fetchuri += ';subdir=${BP}' 438 fetchuri += ';subdir=${BPN}'
439 srcuri = fetchuri 439 srcuri = fetchuri
440 rev_re = re.compile(';rev=([^;]+)') 440 rev_re = re.compile(';rev=([^;]+)')
441 res = rev_re.search(srcuri) 441 res = rev_re.search(srcuri)
@@ -478,6 +478,9 @@ def create_recipe(args):
478 storeTagName = params['tag'] 478 storeTagName = params['tag']
479 params['nobranch'] = '1' 479 params['nobranch'] = '1'
480 del params['tag'] 480 del params['tag']
481 # Assume 'master' branch if not set
482 if scheme in ['git', 'gitsm'] and 'branch' not in params and 'nobranch' not in params:
483 params['branch'] = 'master'
481 fetchuri = bb.fetch2.encodeurl((scheme, network, path, user, passwd, params)) 484 fetchuri = bb.fetch2.encodeurl((scheme, network, path, user, passwd, params))
482 485
483 tmpparent = tinfoil.config_data.getVar('BASE_WORKDIR') 486 tmpparent = tinfoil.config_data.getVar('BASE_WORKDIR')
@@ -527,10 +530,9 @@ def create_recipe(args):
527 # Remove HEAD reference point and drop remote prefix 530 # Remove HEAD reference point and drop remote prefix
528 get_branch = [x.split('/', 1)[1] for x in get_branch if not x.startswith('origin/HEAD')] 531 get_branch = [x.split('/', 1)[1] for x in get_branch if not x.startswith('origin/HEAD')]
529 if 'master' in get_branch: 532 if 'master' in get_branch:
530 # If it is master, we do not need to append 'branch=master' as this is default.
531 # Even with the case where get_branch has multiple objects, if 'master' is one 533 # Even with the case where get_branch has multiple objects, if 'master' is one
532 # of them, we should default take from 'master' 534 # of them, we should default take from 'master'
533 srcbranch = '' 535 srcbranch = 'master'
534 elif len(get_branch) == 1: 536 elif len(get_branch) == 1:
535 # If 'master' isn't in get_branch and get_branch contains only ONE object, then store result into 'srcbranch' 537 # If 'master' isn't in get_branch and get_branch contains only ONE object, then store result into 'srcbranch'
536 srcbranch = get_branch[0] 538 srcbranch = get_branch[0]
@@ -543,8 +545,8 @@ def create_recipe(args):
543 # Since we might have a value in srcbranch, we need to 545 # Since we might have a value in srcbranch, we need to
544 # recontruct the srcuri to include 'branch' in params. 546 # recontruct the srcuri to include 'branch' in params.
545 scheme, network, path, user, passwd, params = bb.fetch2.decodeurl(srcuri) 547 scheme, network, path, user, passwd, params = bb.fetch2.decodeurl(srcuri)
546 if srcbranch: 548 if scheme in ['git', 'gitsm']:
547 params['branch'] = srcbranch 549 params['branch'] = srcbranch or 'master'
548 550
549 if storeTagName and scheme in ['git', 'gitsm']: 551 if storeTagName and scheme in ['git', 'gitsm']:
550 # Check srcrev using tag and check validity of the tag 552 # Check srcrev using tag and check validity of the tag
@@ -603,7 +605,7 @@ def create_recipe(args):
603 splitline = line.split() 605 splitline = line.split()
604 if len(splitline) > 1: 606 if len(splitline) > 1:
605 if splitline[0] == 'origin' and scriptutils.is_src_url(splitline[1]): 607 if splitline[0] == 'origin' and scriptutils.is_src_url(splitline[1]):
606 srcuri = reformat_git_uri(splitline[1]) 608 srcuri = reformat_git_uri(splitline[1]) + ';branch=master'
607 srcsubdir = 'git' 609 srcsubdir = 'git'
608 break 610 break
609 611
@@ -743,6 +745,10 @@ def create_recipe(args):
743 for handler in handlers: 745 for handler in handlers:
744 handler.process(srctree_use, classes, lines_before, lines_after, handled, extravalues) 746 handler.process(srctree_use, classes, lines_before, lines_after, handled, extravalues)
745 747
748 # native and nativesdk classes are special and must be inherited last
749 # If present, put them at the end of the classes list
750 classes.sort(key=lambda c: c in ("native", "nativesdk"))
751
746 extrafiles = extravalues.pop('extrafiles', {}) 752 extrafiles = extravalues.pop('extrafiles', {})
747 extra_pn = extravalues.pop('PN', None) 753 extra_pn = extravalues.pop('PN', None)
748 extra_pv = extravalues.pop('PV', None) 754 extra_pv = extravalues.pop('PV', None)
diff --git a/scripts/lib/resulttool/report.py b/scripts/lib/resulttool/report.py
index f0ca50ebe2..a349510ab8 100644
--- a/scripts/lib/resulttool/report.py
+++ b/scripts/lib/resulttool/report.py
@@ -176,7 +176,10 @@ class ResultsTextReport(object):
176 vals['sort'] = line['testseries'] + "_" + line['result_id'] 176 vals['sort'] = line['testseries'] + "_" + line['result_id']
177 vals['failed_testcases'] = line['failed_testcases'] 177 vals['failed_testcases'] = line['failed_testcases']
178 for k in cols: 178 for k in cols:
179 vals[k] = "%d (%s%%)" % (line[k], format(line[k] / total_tested * 100, '.0f')) 179 if total_tested:
180 vals[k] = "%d (%s%%)" % (line[k], format(line[k] / total_tested * 100, '.0f'))
181 else:
182 vals[k] = "0 (0%)"
180 for k in maxlen: 183 for k in maxlen:
181 if k in vals and len(vals[k]) > maxlen[k]: 184 if k in vals and len(vals[k]) > maxlen[k]:
182 maxlen[k] = len(vals[k]) 185 maxlen[k] = len(vals[k])
diff --git a/scripts/lib/resulttool/resultutils.py b/scripts/lib/resulttool/resultutils.py
index 8917022d36..c5521d81bd 100644
--- a/scripts/lib/resulttool/resultutils.py
+++ b/scripts/lib/resulttool/resultutils.py
@@ -58,7 +58,11 @@ def append_resultsdata(results, f, configmap=store_map, configvars=extra_configv
58 testseries = posixpath.basename(posixpath.dirname(url.path)) 58 testseries = posixpath.basename(posixpath.dirname(url.path))
59 else: 59 else:
60 with open(f, "r") as filedata: 60 with open(f, "r") as filedata:
61 data = json.load(filedata) 61 try:
62 data = json.load(filedata)
63 except json.decoder.JSONDecodeError:
64 print("Cannot decode {}. Possible corruption. Skipping.".format(f))
65 data = ""
62 testseries = os.path.basename(os.path.dirname(f)) 66 testseries = os.path.basename(os.path.dirname(f))
63 else: 67 else:
64 data = f 68 data = f
@@ -142,7 +146,7 @@ def generic_get_log(sectionname, results, section):
142 return decode_log(ptest['log']) 146 return decode_log(ptest['log'])
143 147
144def ptestresult_get_log(results, section): 148def ptestresult_get_log(results, section):
145 return generic_get_log('ptestresuls.sections', results, section) 149 return generic_get_log('ptestresult.sections', results, section)
146 150
147def generic_get_rawlogs(sectname, results): 151def generic_get_rawlogs(sectname, results):
148 if sectname not in results: 152 if sectname not in results:
diff --git a/scripts/lib/scriptutils.py b/scripts/lib/scriptutils.py
index f92255d8dc..47a08194d0 100644
--- a/scripts/lib/scriptutils.py
+++ b/scripts/lib/scriptutils.py
@@ -18,7 +18,8 @@ import sys
18import tempfile 18import tempfile
19import threading 19import threading
20import importlib 20import importlib
21from importlib import machinery 21import importlib.machinery
22import importlib.util
22 23
23class KeepAliveStreamHandler(logging.StreamHandler): 24class KeepAliveStreamHandler(logging.StreamHandler):
24 def __init__(self, keepalive=True, **kwargs): 25 def __init__(self, keepalive=True, **kwargs):
@@ -82,7 +83,9 @@ def load_plugins(logger, plugins, pluginpath):
82 logger.debug('Loading plugin %s' % name) 83 logger.debug('Loading plugin %s' % name)
83 spec = importlib.machinery.PathFinder.find_spec(name, path=[pluginpath] ) 84 spec = importlib.machinery.PathFinder.find_spec(name, path=[pluginpath] )
84 if spec: 85 if spec:
85 return spec.loader.load_module() 86 mod = importlib.util.module_from_spec(spec)
87 spec.loader.exec_module(mod)
88 return mod
86 89
87 def plugin_name(filename): 90 def plugin_name(filename):
88 return os.path.splitext(os.path.basename(filename))[0] 91 return os.path.splitext(os.path.basename(filename))[0]
@@ -215,7 +218,8 @@ def fetch_url(tinfoil, srcuri, srcrev, destdir, logger, preserve_tmp=False, mirr
215 pathvars = ['T', 'RECIPE_SYSROOT', 'RECIPE_SYSROOT_NATIVE'] 218 pathvars = ['T', 'RECIPE_SYSROOT', 'RECIPE_SYSROOT_NATIVE']
216 for pathvar in pathvars: 219 for pathvar in pathvars:
217 path = rd.getVar(pathvar) 220 path = rd.getVar(pathvar)
218 shutil.rmtree(path) 221 if os.path.exists(path):
222 shutil.rmtree(path)
219 finally: 223 finally:
220 if fetchrecipe: 224 if fetchrecipe:
221 try: 225 try:
diff --git a/scripts/lib/wic/engine.py b/scripts/lib/wic/engine.py
index 9ff4394757..7dbde85696 100644
--- a/scripts/lib/wic/engine.py
+++ b/scripts/lib/wic/engine.py
@@ -19,10 +19,10 @@ import os
19import tempfile 19import tempfile
20import json 20import json
21import subprocess 21import subprocess
22import shutil
22import re 23import re
23 24
24from collections import namedtuple, OrderedDict 25from collections import namedtuple, OrderedDict
25from distutils.spawn import find_executable
26 26
27from wic import WicError 27from wic import WicError
28from wic.filemap import sparse_copy 28from wic.filemap import sparse_copy
@@ -245,7 +245,7 @@ class Disk:
245 for path in pathlist.split(':'): 245 for path in pathlist.split(':'):
246 self.paths = "%s%s:%s" % (native_sysroot, path, self.paths) 246 self.paths = "%s%s:%s" % (native_sysroot, path, self.paths)
247 247
248 self.parted = find_executable("parted", self.paths) 248 self.parted = shutil.which("parted", path=self.paths)
249 if not self.parted: 249 if not self.parted:
250 raise WicError("Can't find executable parted") 250 raise WicError("Can't find executable parted")
251 251
@@ -283,7 +283,7 @@ class Disk:
283 "resize2fs", "mkswap", "mkdosfs", "debugfs"): 283 "resize2fs", "mkswap", "mkdosfs", "debugfs"):
284 aname = "_%s" % name 284 aname = "_%s" % name
285 if aname not in self.__dict__: 285 if aname not in self.__dict__:
286 setattr(self, aname, find_executable(name, self.paths)) 286 setattr(self, aname, shutil.which(name, path=self.paths))
287 if aname not in self.__dict__ or self.__dict__[aname] is None: 287 if aname not in self.__dict__ or self.__dict__[aname] is None:
288 raise WicError("Can't find executable '{}'".format(name)) 288 raise WicError("Can't find executable '{}'".format(name))
289 return self.__dict__[aname] 289 return self.__dict__[aname]
diff --git a/scripts/lib/wic/help.py b/scripts/lib/wic/help.py
index 62a2a90e79..fcace95ff4 100644
--- a/scripts/lib/wic/help.py
+++ b/scripts/lib/wic/help.py
@@ -840,8 +840,8 @@ DESCRIPTION
840 meanings. The commands are based on the Fedora kickstart 840 meanings. The commands are based on the Fedora kickstart
841 documentation but with modifications to reflect wic capabilities. 841 documentation but with modifications to reflect wic capabilities.
842 842
843 http://fedoraproject.org/wiki/Anaconda/Kickstart#part_or_partition 843 https://pykickstart.readthedocs.io/en/latest/kickstart-docs.html#part-or-partition
844 http://fedoraproject.org/wiki/Anaconda/Kickstart#bootloader 844 https://pykickstart.readthedocs.io/en/latest/kickstart-docs.html#bootloader
845 845
846 Commands 846 Commands
847 847
diff --git a/scripts/lib/wic/misc.py b/scripts/lib/wic/misc.py
index e4b5a0d519..3e11822996 100644
--- a/scripts/lib/wic/misc.py
+++ b/scripts/lib/wic/misc.py
@@ -16,9 +16,9 @@ import logging
16import os 16import os
17import re 17import re
18import subprocess 18import subprocess
19import shutil
19 20
20from collections import defaultdict 21from collections import defaultdict
21from distutils import spawn
22 22
23from wic import WicError 23from wic import WicError
24 24
@@ -26,6 +26,7 @@ logger = logging.getLogger('wic')
26 26
27# executable -> recipe pairs for exec_native_cmd 27# executable -> recipe pairs for exec_native_cmd
28NATIVE_RECIPES = {"bmaptool": "bmap-tools", 28NATIVE_RECIPES = {"bmaptool": "bmap-tools",
29 "dumpe2fs": "e2fsprogs",
29 "grub-mkimage": "grub-efi", 30 "grub-mkimage": "grub-efi",
30 "isohybrid": "syslinux", 31 "isohybrid": "syslinux",
31 "mcopy": "mtools", 32 "mcopy": "mtools",
@@ -45,7 +46,8 @@ NATIVE_RECIPES = {"bmaptool": "bmap-tools",
45 "parted": "parted", 46 "parted": "parted",
46 "sfdisk": "util-linux", 47 "sfdisk": "util-linux",
47 "sgdisk": "gptfdisk", 48 "sgdisk": "gptfdisk",
48 "syslinux": "syslinux" 49 "syslinux": "syslinux",
50 "tar": "tar"
49 } 51 }
50 52
51def runtool(cmdln_or_args): 53def runtool(cmdln_or_args):
@@ -112,6 +114,15 @@ def exec_cmd(cmd_and_args, as_shell=False):
112 """ 114 """
113 return _exec_cmd(cmd_and_args, as_shell)[1] 115 return _exec_cmd(cmd_and_args, as_shell)[1]
114 116
117def find_executable(cmd, paths):
118 recipe = cmd
119 if recipe in NATIVE_RECIPES:
120 recipe = NATIVE_RECIPES[recipe]
121 provided = get_bitbake_var("ASSUME_PROVIDED")
122 if provided and "%s-native" % recipe in provided:
123 return True
124
125 return shutil.which(cmd, path=paths)
115 126
116def exec_native_cmd(cmd_and_args, native_sysroot, pseudo=""): 127def exec_native_cmd(cmd_and_args, native_sysroot, pseudo=""):
117 """ 128 """
@@ -140,7 +151,7 @@ def exec_native_cmd(cmd_and_args, native_sysroot, pseudo=""):
140 logger.debug("exec_native_cmd: %s", native_cmd_and_args) 151 logger.debug("exec_native_cmd: %s", native_cmd_and_args)
141 152
142 # If the command isn't in the native sysroot say we failed. 153 # If the command isn't in the native sysroot say we failed.
143 if spawn.find_executable(args[0], native_paths): 154 if find_executable(args[0], native_paths):
144 ret, out = _exec_cmd(native_cmd_and_args, True) 155 ret, out = _exec_cmd(native_cmd_and_args, True)
145 else: 156 else:
146 ret = 127 157 ret = 127
diff --git a/scripts/lib/wic/partition.py b/scripts/lib/wic/partition.py
index e574f40c47..792bb3dcd3 100644
--- a/scripts/lib/wic/partition.py
+++ b/scripts/lib/wic/partition.py
@@ -104,7 +104,7 @@ class Partition():
104 extra_blocks = self.extra_space 104 extra_blocks = self.extra_space
105 105
106 rootfs_size = actual_rootfs_size + extra_blocks 106 rootfs_size = actual_rootfs_size + extra_blocks
107 rootfs_size *= self.overhead_factor 107 rootfs_size = int(rootfs_size * self.overhead_factor)
108 108
109 logger.debug("Added %d extra blocks to %s to get to %d total blocks", 109 logger.debug("Added %d extra blocks to %s to get to %d total blocks",
110 extra_blocks, self.mountpoint, rootfs_size) 110 extra_blocks, self.mountpoint, rootfs_size)
@@ -298,6 +298,8 @@ class Partition():
298 mkfs_cmd = "fsck.%s -pvfD %s" % (self.fstype, rootfs) 298 mkfs_cmd = "fsck.%s -pvfD %s" % (self.fstype, rootfs)
299 exec_native_cmd(mkfs_cmd, native_sysroot, pseudo=pseudo) 299 exec_native_cmd(mkfs_cmd, native_sysroot, pseudo=pseudo)
300 300
301 self.check_for_Y2038_problem(rootfs, native_sysroot)
302
301 def prepare_rootfs_btrfs(self, rootfs, cr_workdir, oe_builddir, rootfs_dir, 303 def prepare_rootfs_btrfs(self, rootfs, cr_workdir, oe_builddir, rootfs_dir,
302 native_sysroot, pseudo): 304 native_sysroot, pseudo):
303 """ 305 """
@@ -388,6 +390,8 @@ class Partition():
388 (self.fstype, extraopts, label_str, self.fsuuid, rootfs) 390 (self.fstype, extraopts, label_str, self.fsuuid, rootfs)
389 exec_native_cmd(mkfs_cmd, native_sysroot) 391 exec_native_cmd(mkfs_cmd, native_sysroot)
390 392
393 self.check_for_Y2038_problem(rootfs, native_sysroot)
394
391 def prepare_empty_partition_btrfs(self, rootfs, oe_builddir, 395 def prepare_empty_partition_btrfs(self, rootfs, oe_builddir,
392 native_sysroot): 396 native_sysroot):
393 """ 397 """
@@ -449,3 +453,37 @@ class Partition():
449 453
450 mkswap_cmd = "mkswap %s -U %s %s" % (label_str, self.fsuuid, path) 454 mkswap_cmd = "mkswap %s -U %s %s" % (label_str, self.fsuuid, path)
451 exec_native_cmd(mkswap_cmd, native_sysroot) 455 exec_native_cmd(mkswap_cmd, native_sysroot)
456
457 def check_for_Y2038_problem(self, rootfs, native_sysroot):
458 """
459 Check if the filesystem is affected by the Y2038 problem
460 (Y2038 problem = 32 bit time_t overflow in January 2038)
461 """
462 def get_err_str(part):
463 err = "The {} filesystem {} has no Y2038 support."
464 if part.mountpoint:
465 args = [part.fstype, "mounted at %s" % part.mountpoint]
466 elif part.label:
467 args = [part.fstype, "labeled '%s'" % part.label]
468 elif part.part_name:
469 args = [part.fstype, "in partition '%s'" % part.part_name]
470 else:
471 args = [part.fstype, "in partition %s" % part.num]
472 return err.format(*args)
473
474 # ext2 and ext3 are always affected by the Y2038 problem
475 if self.fstype in ["ext2", "ext3"]:
476 logger.warn(get_err_str(self))
477 return
478
479 ret, out = exec_native_cmd("dumpe2fs %s" % rootfs, native_sysroot)
480
481 # if ext4 is affected by the Y2038 problem depends on the inode size
482 for line in out.splitlines():
483 if line.startswith("Inode size:"):
484 size = int(line.split(":")[1].strip())
485 if size < 256:
486 logger.warn("%s Inodes (of size %d) are too small." %
487 (get_err_str(self), size))
488 break
489
diff --git a/scripts/lib/wic/pluginbase.py b/scripts/lib/wic/pluginbase.py
index d9b4e57747..b64568339b 100644
--- a/scripts/lib/wic/pluginbase.py
+++ b/scripts/lib/wic/pluginbase.py
@@ -9,9 +9,11 @@ __all__ = ['ImagerPlugin', 'SourcePlugin']
9 9
10import os 10import os
11import logging 11import logging
12import types
12 13
13from collections import defaultdict 14from collections import defaultdict
14from importlib.machinery import SourceFileLoader 15import importlib
16import importlib.util
15 17
16from wic import WicError 18from wic import WicError
17from wic.misc import get_bitbake_var 19from wic.misc import get_bitbake_var
@@ -54,7 +56,9 @@ class PluginMgr:
54 mname = fname[:-3] 56 mname = fname[:-3]
55 mpath = os.path.join(ppath, fname) 57 mpath = os.path.join(ppath, fname)
56 logger.debug("loading plugin module %s", mpath) 58 logger.debug("loading plugin module %s", mpath)
57 SourceFileLoader(mname, mpath).load_module() 59 spec = importlib.util.spec_from_file_location(mname, mpath)
60 module = importlib.util.module_from_spec(spec)
61 spec.loader.exec_module(module)
58 62
59 return PLUGINS.get(ptype) 63 return PLUGINS.get(ptype)
60 64
diff --git a/scripts/lib/wic/plugins/imager/direct.py b/scripts/lib/wic/plugins/imager/direct.py
index 7e1c1c03ab..42704d1e10 100644
--- a/scripts/lib/wic/plugins/imager/direct.py
+++ b/scripts/lib/wic/plugins/imager/direct.py
@@ -115,7 +115,7 @@ class DirectPlugin(ImagerPlugin):
115 updated = False 115 updated = False
116 for part in self.parts: 116 for part in self.parts:
117 if not part.realnum or not part.mountpoint \ 117 if not part.realnum or not part.mountpoint \
118 or part.mountpoint == "/": 118 or part.mountpoint == "/" or not (part.mountpoint.startswith('/') or part.mountpoint == "swap"):
119 continue 119 continue
120 120
121 if part.use_uuid: 121 if part.use_uuid:
diff --git a/scripts/lib/wic/plugins/source/bootimg-efi.py b/scripts/lib/wic/plugins/source/bootimg-efi.py
index 2cfdc10ecd..05e8471116 100644
--- a/scripts/lib/wic/plugins/source/bootimg-efi.py
+++ b/scripts/lib/wic/plugins/source/bootimg-efi.py
@@ -277,6 +277,13 @@ class BootimgEFIPlugin(SourcePlugin):
277 logger.debug("Added %d extra blocks to %s to get to %d total blocks", 277 logger.debug("Added %d extra blocks to %s to get to %d total blocks",
278 extra_blocks, part.mountpoint, blocks) 278 extra_blocks, part.mountpoint, blocks)
279 279
280 # required for compatibility with certain devices expecting file system
281 # block count to be equal to partition block count
282 if blocks < part.fixed_size:
283 blocks = part.fixed_size
284 logger.debug("Overriding %s to %d total blocks for compatibility",
285 part.mountpoint, blocks)
286
280 # dosfs image, created by mkdosfs 287 # dosfs image, created by mkdosfs
281 bootimg = "%s/boot.img" % cr_workdir 288 bootimg = "%s/boot.img" % cr_workdir
282 289
diff --git a/scripts/lib/wic/plugins/source/bootimg-pcbios.py b/scripts/lib/wic/plugins/source/bootimg-pcbios.py
index f2639e7004..32e47f1831 100644
--- a/scripts/lib/wic/plugins/source/bootimg-pcbios.py
+++ b/scripts/lib/wic/plugins/source/bootimg-pcbios.py
@@ -186,8 +186,10 @@ class BootimgPcbiosPlugin(SourcePlugin):
186 # dosfs image, created by mkdosfs 186 # dosfs image, created by mkdosfs
187 bootimg = "%s/boot%s.img" % (cr_workdir, part.lineno) 187 bootimg = "%s/boot%s.img" % (cr_workdir, part.lineno)
188 188
189 dosfs_cmd = "mkdosfs -n boot -i %s -S 512 -C %s %d" % \ 189 label = part.label if part.label else "boot"
190 (part.fsuuid, bootimg, blocks) 190
191 dosfs_cmd = "mkdosfs -n %s -i %s -S 512 -C %s %d" % \
192 (label, part.fsuuid, bootimg, blocks)
191 exec_native_cmd(dosfs_cmd, native_sysroot) 193 exec_native_cmd(dosfs_cmd, native_sysroot)
192 194
193 mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir) 195 mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir)