X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=mic%2Futils%2Fmisc.py;h=399fd4e7ff0d4e87f0abd4bab6006a482004fdec;hb=ebeb61e2032932e84aa2b93cb5c40b3cab3756cd;hp=e7a3f5ccac441fccde35c3008a7e144c71b33ee9;hpb=cfdd9d271435157ae6a10b7768f96f29792cc9de;p=tools%2Fmic.git diff --git a/mic/utils/misc.py b/mic/utils/misc.py old mode 100644 new mode 100755 index e7a3f5c..399fd4e --- a/mic/utils/misc.py +++ b/mic/utils/misc.py @@ -18,6 +18,7 @@ from __future__ import with_statement import os import sys +import time import tempfile import re import shutil @@ -25,12 +26,8 @@ import glob import hashlib import subprocess import platform -import rpmmisc +import traceback -try: - from hashlib import md5 -except ImportError: - from md5 import md5 try: import sqlite3 as sqlite @@ -43,18 +40,60 @@ except ImportError: import cElementTree xmlparse = cElementTree.parse -from errors import * -from fs_related import * -from rpmmisc import myurlgrab -from proxy import get_proxy_for -import runner - from mic import msger +from mic.archive import get_archive_suffixes +from mic.utils.errors import CreatorError, SquashfsError +from mic.utils.fs_related import find_binary_path, makedirs +from mic.utils.grabber import myurlgrab +from mic.utils.proxy import get_proxy_for +from mic.utils import runner +from mic.utils import rpmmisc +from mic.utils.safeurl import SafeURL + RPM_RE = re.compile("(.*)\.(.*) (.*)-(.*)") -RPM_FMT = "%(name)s.%(arch)s %(ver_rel)s" +RPM_FMT = "%(name)s.%(arch)s %(version)s-%(release)s" SRPM_RE = re.compile("(.*)-(\d+.*)-(\d+\.\d+).src.rpm") + +def build_name(kscfg, release=None, prefix = None, suffix = None): + """Construct and return an image name string. + + This is a utility function to help create sensible name and fslabel + strings. The name is constructed using the sans-prefix-and-extension + kickstart filename and the supplied prefix and suffix. + + kscfg -- a path to a kickstart file + release -- a replacement to suffix for image release + prefix -- a prefix to prepend to the name; defaults to None, which causes + no prefix to be used + suffix -- a suffix to append to the name; defaults to None, which causes + a YYYYMMDDHHMM suffix to be used + + Note, if maxlen is less then the len(suffix), you get to keep both pieces. + + """ + name = os.path.basename(kscfg) + idx = name.rfind('.') + if idx >= 0: + name = name[:idx] + + if release is not None: + suffix = "" + if prefix is None: + prefix = "" + if suffix is None: + suffix = time.strftime("%Y%m%d%H%M") + + if name.startswith(prefix): + name = name[len(prefix):] + + prefix = "%s-" % prefix if prefix else "" + suffix = "-%s" % suffix if suffix else "" + + ret = prefix + name + suffix + return ret + def get_distro(): """Detect linux distribution, support "meego" """ @@ -76,18 +115,42 @@ def get_distro(): return (dist, ver, id) -def get_distro_str(): +def get_hostname(): + """Get hostname + """ + return platform.node() + +def get_hostname_distro_str(): """Get composited string for current linux distribution """ (dist, ver, id) = get_distro() + hostname = get_hostname() if not dist: - return 'Unknown Linux Distro' + return "%s(Unknown Linux Distribution)" % hostname else: - return ' '.join(map(str.strip, (dist, ver, id))) + distro_str = ' '.join(map(str.strip, (hostname, dist, ver, id))) + return distro_str.strip() + +_LOOP_RULE_PTH = None -_LOOP_RULE_PTH = "/etc/udev/rules.d/80-prevent-loop-present.rules" def hide_loopdev_presentation(): + udev_rules = "80-prevent-loop-present.rules" + udev_rules_dir = [ + '/usr/lib/udev/rules.d/', + '/lib/udev/rules.d/', + '/etc/udev/rules.d/' + ] + + global _LOOP_RULE_PTH + + for rdir in udev_rules_dir: + if os.path.exists(rdir): + _LOOP_RULE_PTH = os.path.join(rdir, udev_rules) + + if not _LOOP_RULE_PTH: + return + try: with open(_LOOP_RULE_PTH, 'w') as wf: wf.write('KERNEL=="loop*", ENV{UDISKS_PRESENTATION_HIDE}="1"') @@ -97,6 +160,11 @@ def hide_loopdev_presentation(): pass def unhide_loopdev_presentation(): + #global _LOOP_RULE_PTH + + if not _LOOP_RULE_PTH: + return + try: os.unlink(_LOOP_RULE_PTH) runner.quiet('udevadm trigger') @@ -114,88 +182,12 @@ def extract_rpm(rpmfile, targetdir): p1 = subprocess.Popen([rpm2cpio, rpmfile], stdout=subprocess.PIPE) p2 = subprocess.Popen([cpio, "-idv"], stdin=p1.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + p1.stdout.close() (sout, serr) = p2.communicate() msger.verbose(sout or serr) os.chdir(olddir) -def compressing(fpath, method): - comp_map = { - "gz": "gzip", - "bz2": "bzip2" - } - if method not in comp_map: - raise CreatorError("Unsupport compress format: %s, valid values: %s" - % (method, ','.join(comp_map.keys()))) - cmd = find_binary_path(comp_map[method]) - rc = runner.show([cmd, "-f", fpath]) - if rc: - raise CreatorError("Failed to %s file: %s" % (comp_map[method], fpath)) - -def taring(dstfile, target): - import tarfile - basen, ext = os.path.splitext(dstfile) - comp = {".tar": None, - ".gz": "gz", # for .tar.gz - ".bz2": "bz2", # for .tar.bz2 - ".tgz": "gz", - ".tbz": "bz2"}[ext] - - # specify tarball file path - if not comp: - tarpath = dstfile - elif basen.endswith(".tar"): - tarpath = basen - else: - tarpath = basen + ".tar" - wf = tarfile.open(tarpath, 'w') - - if os.path.isdir(target): - for item in os.listdir(target): - wf.add(os.path.join(target, item), item) - else: - wf.add(target, os.path.basename(target)) - wf.close() - - if comp: - compressing(tarpath, comp) - # when dstfile ext is ".tgz" and ".tbz", should rename - if not basen.endswith(".tar"): - shutil.move("%s.%s" % (tarpath, comp), dstfile) - -def ziping(dstfile, target): - import zipfile - wf = zipfile.ZipFile(dstfile, 'w', compression=zipfile.ZIP_DEFLATED) - if os.path.isdir(target): - for item in os.listdir(target): - fpath = os.path.join(target, item) - if not os.path.isfile(fpath): - continue - wf.write(fpath, item, zipfile.ZIP_DEFLATED) - else: - wf.write(target, os.path.basename(target), zipfile.ZIP_DEFLATED) - wf.close() - -pack_formats = { - ".tar": taring, - ".tar.gz": taring, - ".tar.bz2": taring, - ".tgz": taring, - ".tbz": taring, - ".zip": ziping, -} - -def packing(dstfile, target): - (base, ext) = os.path.splitext(dstfile) - if ext in (".gz", ".bz2") and base.endswith(".tar"): - ext = ".tar" + ext - if ext not in pack_formats: - raise CreatorError("Unsupport pack format: %s, valid values: %s" - % (ext, ','.join(pack_formats.keys()))) - func = pack_formats[ext] - # func should be callable - func(dstfile, target) - def human_size(size): """Return human readable string for Bytes size """ @@ -208,6 +200,18 @@ def human_size(size): mant = float(size/math.pow(1024, expo)) return "{0:.1f}{1:s}".format(mant, measure[expo]) +def get_block_size(file_obj): + """ Returns block size for file object 'file_obj'. Errors are indicated by + the 'IOError' exception. """ + + from fcntl import ioctl + import struct + + # Get the block size of the host file-system for the image file by calling + # the FIGETBSZ ioctl (number 2). + binary_data = ioctl(file_obj, 2, struct.pack('I', 0)) + return struct.unpack('I', binary_data)[0] + def check_space_pre_cp(src, dst): """Check whether disk space is enough before 'cp' like operations, else exception will be raised. @@ -219,27 +223,60 @@ def check_space_pre_cp(src, dst): raise CreatorError("space on %s(%s) is not enough for about %s files" % (dst, human_size(freesize), human_size(srcsize))) +def calc_hashes(file_path, hash_names, start = 0, end = None): + """ Calculate hashes for a file. The 'file_path' argument is the file + to calculate hash functions for, 'start' and 'end' are the starting and + ending file offset to calculate the has functions for. The 'hash_names' + argument is a list of hash names to calculate. Returns the the list + of calculated hash values in the hexadecimal form in the same order + as 'hash_names'. + """ + if end == None: + end = os.path.getsize(file_path) + + chunk_size = 65536 + to_read = end - start + read = 0 + + hashes = [] + for hash_name in hash_names: + hashes.append(hashlib.new(hash_name)) + + with open(file_path, "rb") as f: + f.seek(start) + + while read < to_read: + if read + chunk_size > to_read: + chunk_size = to_read - read + chunk = f.read(chunk_size) + for hash_obj in hashes: + hash_obj.update(chunk) + read += chunk_size + + result = [] + for hash_obj in hashes: + result.append(hash_obj.hexdigest()) + + return result + def get_md5sum(fpath): - blksize = 65536 # should be optimized enough + return calc_hashes(fpath, ('md5', ))[0] - md5sum = md5() - with open(fpath, 'rb') as f: - while True: - data = f.read(blksize) - if not data: - break - md5sum.update(data) - return md5sum.hexdigest() +def get_sha1sum(fpath): + return calc_hashes(fpath, ('sha1', ))[0] + +def get_sha256sum(fpath): + return calc_hashes(fpath, ('sha256', ))[0] def normalize_ksfile(ksconf, release, arch): - def _clrtempks(): - try: - os.unlink(ksconf) - except: - pass + ''' + Return the name of a normalized ks file in which macro variables + @BUILD_ID@ and @ARCH@ are replace with real values. - if not os.path.exists(ksconf): - return + The original ks file is returned if no special macro is used, otherwise + a temp file is created and returned, which will be deleted when program + exits normally. + ''' if not release: release = "latest" @@ -249,30 +286,44 @@ def normalize_ksfile(ksconf, release, arch): with open(ksconf) as f: ksc = f.read() - if "@ARCH@" in ksc or "@BUILD_ID@" in ksc: - msger.info("Substitute macro variable @BUILD_ID@/@ARCH in ks: %s" % ksconf) - ksc = ksc.replace("@ARCH@", arch) - ksc = ksc.replace("@BUILD_ID@", release) - fd, ksconf = tempfile.mkstemp(prefix=os.path.basename(ksconf), dir="/tmp/") - os.write(fd, ksc) - os.close(fd) + if "@ARCH@" not in ksc and "@BUILD_ID@" not in ksc: + return ksconf + + msger.info("Substitute macro variable @BUILD_ID@/@ARCH@ in ks: %s" % ksconf) + ksc = ksc.replace("@ARCH@", arch) + ksc = ksc.replace("@BUILD_ID@", release) - msger.debug('new ks path %s' % ksconf) + fd, ksconf = tempfile.mkstemp(prefix=os.path.basename(ksconf)) + os.write(fd, ksc) + os.close(fd) - import atexit - atexit.register(_clrtempks) + msger.debug('normalized ks file:%s' % ksconf) + + def remove_temp_ks(): + try: + os.unlink(ksconf) + except OSError as err: + msger.warning('Failed to remove temp ks file:%s:%s' % (ksconf, err)) + + import atexit + atexit.register(remove_temp_ks) return ksconf -def _check_meego_chroot(rootdir): - if not os.path.exists(rootdir + "/etc/moblin-release") and \ - not os.path.exists(rootdir + "/etc/meego-release") and \ - not os.path.exists(rootdir + "/etc/tizen-release"): - raise CreatorError("Directory %s is not a MeeGo/Tizen chroot env"\ - % rootdir) + +def _check_mic_chroot(rootdir): + def _path(path): + return rootdir.rstrip('/') + path + + release_files = map(_path, [ "/etc/moblin-release", + "/etc/meego-release", + "/etc/tizen-release"]) + + if not any(map(os.path.exists, release_files)): + msger.warning("Dir %s is not a MeeGo/Tizen chroot env" % rootdir) if not glob.glob(rootdir + "/boot/vmlinuz-*"): - raise CreatorError("Failed to find kernel module under %s" % rootdir) + msger.warning("Failed to find kernel module under %s" % rootdir) return @@ -301,7 +352,7 @@ def get_image_type(path): return None if os.path.isdir(path): - _check_meego_chroot(path) + _check_mic_chroot(path) return "fs" maptab = { @@ -349,22 +400,23 @@ def get_image_type(path): else: raise CreatorError("Cannot detect the type of image: %s" % path) -def get_file_size(file): + +def get_file_size(filename): """ Return size in MB unit """ - rc, duOutput = runner.runtool(['du', "-s", "-b", "-B", "1M", file]) + cmd = ['du', "-s", "-b", "-B", "1M", filename] + rc, duOutput = runner.runtool(cmd) if rc != 0: - raise CreatorError("Failed to run %s" % du) - + raise CreatorError("Failed to run: %s" % ' '.join(cmd)) size1 = int(duOutput.split()[0]) - rc, duOutput = runner.runtool(['du', "-s", "-B", "1M", file]) + + cmd = ['du', "-s", "-B", "1M", filename] + rc, duOutput = runner.runtool(cmd) if rc != 0: - raise CreatorError("Failed to run %s" % du) + raise CreatorError("Failed to run: %s" % ' '.join(cmd)) size2 = int(duOutput.split()[0]) - if size1 > size2: - return size1 - else: - return size2 + return max(size1, size2) + def get_filesystem_avail(fs): vfstat = os.statvfs(fs) @@ -435,13 +487,17 @@ def get_repostrs_from_ks(ks): if 'name' not in repo: repo['name'] = _get_temp_reponame(repodata.baseurl) + if hasattr(repodata, 'baseurl') and getattr(repodata, 'baseurl'): + repo['baseurl'] = SafeURL(getattr(repodata, 'baseurl'), + getattr(repodata, 'user', None), + getattr(repodata, 'passwd', None)) kickstart_repos.append(repo) return kickstart_repos def _get_uncompressed_data_from_url(url, filename, proxies): - filename = myurlgrab(url, filename, proxies) + filename = myurlgrab(url.full, filename, proxies) suffix = None if filename.endswith(".gz"): suffix = ".gz" @@ -455,7 +511,7 @@ def _get_uncompressed_data_from_url(url, filename, proxies): def _get_metadata_from_repo(baseurl, proxies, cachedir, reponame, filename, sumtype=None, checksum=None): - url = os.path.join(baseurl, filename) + url = baseurl.join(filename) filename_tmp = str("%s/%s/%s" % (cachedir, reponame, os.path.basename(filename))) if os.path.splitext(filename_tmp)[1] in (".gz", ".bz2"): filename = os.path.splitext(filename_tmp)[0] @@ -477,23 +533,22 @@ def _get_metadata_from_repo(baseurl, proxies, cachedir, reponame, filename, def get_metadata_from_repos(repos, cachedir): my_repo_metadata = [] for repo in repos: - reponame = repo['name'] - baseurl = repo['baseurl'] - + reponame = repo.name + baseurl = repo.baseurl - if 'proxy' in repo: - proxy = repo['proxy'] + if hasattr(repo, 'proxy'): + proxy = repo.proxy else: proxy = get_proxy_for(baseurl) proxies = None if proxy: - proxies = {str(baseurl.split(":")[0]):str(proxy)} + proxies = {str(baseurl.split(":")[0]): str(proxy)} makedirs(os.path.join(cachedir, reponame)) - url = os.path.join(baseurl, "repodata/repomd.xml") + url = baseurl.join("repodata/repomd.xml") filename = os.path.join(cachedir, reponame, 'repomd.xml') - repomd = myurlgrab(url, filename, proxies) + repomd = myurlgrab(url.full, filename, proxies) try: root = xmlparse(repomd) except SyntaxError: @@ -514,7 +569,8 @@ def get_metadata_from_repos(repos, cachedir): break for elm in root.getiterator("%sdata" % ns): - if elm.attrib["type"] in ("group_gz", "group"): + #"group" type has no "open-checksum" filed, remove it. + if elm.attrib["type"] == "group_gz": filepaths['comps'] = elm.find("%slocation" % ns).attrib['href'] checksums['comps'] = elm.find("%sopen-checksum" % ns).text sumtypes['comps'] = elm.find("%sopen-checksum" % ns).attrib['type'] @@ -565,7 +621,8 @@ def get_metadata_from_repos(repos, cachedir): "proxies":proxies, "patterns":filepaths['patterns'], "comps":filepaths['comps'], - "repokey":repokey}) + "repokey":repokey, + "priority":repo.priority}) return my_repo_metadata @@ -643,45 +700,79 @@ def get_arch(repometadata): def get_package(pkg, repometadata, arch = None): ver = "" + priority = 99 target_repo = None + if not arch: + arches = [] + elif arch not in rpmmisc.archPolicies: + arches = [arch] + else: + arches = rpmmisc.archPolicies[arch].split(':') + arches.append('noarch') + for repo in repometadata: if repo["primary"].endswith(".xml"): root = xmlparse(repo["primary"]) ns = root.getroot().tag ns = ns[0:ns.rindex("}")+1] for elm in root.getiterator("%spackage" % ns): - if elm.find("%sname" % ns).text == pkg: - if elm.find("%sarch" % ns).text != "src": - version = elm.find("%sversion" % ns) - tmpver = "%s-%s" % (version.attrib['ver'], version.attrib['rel']) - if tmpver > ver: - ver = tmpver + if elm.find("%sname" % ns).text == pkg and elm.find("%sarch" % ns).text in arches: + if repo["priority"] != None: + tmpprior = int(repo["priority"]) + if tmpprior < priority: + priority = tmpprior location = elm.find("%slocation" % ns) pkgpath = "%s" % location.attrib['href'] target_repo = repo - break + break + elif tmpprior > priority: + break + version = elm.find("%sversion" % ns) + tmpver = "%s-%s" % (version.attrib['ver'], version.attrib['rel']) + if tmpver > ver: + ver = tmpver + location = elm.find("%slocation" % ns) + pkgpath = "%s" % location.attrib['href'] + target_repo = repo + break if repo["primary"].endswith(".sqlite"): con = sqlite.connect(repo["primary"]) - if not arch: - for row in con.execute("select version, release,location_href from packages where name = \"%s\" and arch != \"src\"" % pkg): + if arch: + sql = 'select version, release, location_href from packages ' \ + 'where name = "%s" and arch IN ("%s")' % \ + (pkg, '","'.join(arches)) + for row in con.execute(sql): tmpver = "%s-%s" % (row[0], row[1]) if tmpver > ver: + ver = tmpver pkgpath = "%s" % row[2] target_repo = repo break else: - for row in con.execute("select version, release,location_href from packages where name = \"%s\"" % pkg): + sql = 'select version, release, location_href from packages ' \ + 'where name = "%s"' % pkg + for row in con.execute(sql): tmpver = "%s-%s" % (row[0], row[1]) if tmpver > ver: + ver = tmpver pkgpath = "%s" % row[2] target_repo = repo break con.close() if target_repo: - makedirs("%s/%s/packages" % (target_repo["cachedir"], target_repo["name"])) - url = os.path.join(target_repo["baseurl"], pkgpath) - filename = str("%s/%s/packages/%s" % (target_repo["cachedir"], target_repo["name"], os.path.basename(pkgpath))) - pkg = myurlgrab(str(url), filename, target_repo["proxies"]) + makedirs("%s/packages/%s" % (target_repo["cachedir"], target_repo["name"])) + url = target_repo["baseurl"].join(pkgpath) + filename = str("%s/packages/%s/%s" % (target_repo["cachedir"], target_repo["name"], os.path.basename(pkgpath))) + if os.path.exists(filename): + ret = rpmmisc.checkRpmIntegrity('rpm', filename) + if ret == 0: + return filename + + msger.warning("package %s is damaged: %s" % + (os.path.basename(filename), filename)) + os.unlink(filename) + + pkg = myurlgrab(url.full, filename, target_repo["proxies"]) return pkg else: return None @@ -807,7 +898,38 @@ def get_pkglist_in_comps(group, comps): def is_statically_linked(binary): return ", statically linked, " in runner.outs(['file', binary]) +def get_qemu_arm_binary(arch): + if arch == "aarch64": + node = "/proc/sys/fs/binfmt_misc/aarch64" + if os.path.exists("/usr/bin/qemu-arm64") and is_statically_linked("/usr/bin/qemu-arm64"): + arm_binary = "qemu-arm64" + elif os.path.exists("/usr/bin/qemu-aarch64") and is_statically_linked("/usr/bin/qemu-aarch64"): + arm_binary = "qemu-aarch64" + elif os.path.exists("/usr/bin/qemu-arm64-static"): + arm_binary = "qemu-arm64-static" + elif os.path.exists("/usr/bin/qemu-aarch64-static"): + arm_binary = "qemu-aarch64-static" + else: + raise CreatorError("Please install a statically-linked %s" % arm_binary) + elif arch == "mipsel": + node = "/proc/sys/fs/binfmt_misc/mipsel" + arm_binary = "qemu-mipsel" + if not os.path.exists("/usr/bin/%s" % arm_binary) or not is_statically_linked("/usr/bin/%s"): + arm_binary = "qemu-mipsel-static" + if not os.path.exists("/usr/bin/%s" % arm_binary): + raise CreatorError("Please install a statically-linked %s" % arm_binary) + else: + node = "/proc/sys/fs/binfmt_misc/arm" + arm_binary = "qemu-arm" + if not os.path.exists("/usr/bin/qemu-arm") or not is_statically_linked("/usr/bin/qemu-arm"): + arm_binary = "qemu-arm-static" + if not os.path.exists("/usr/bin/%s" % arm_binary): + raise CreatorError("Please install a statically-linked %s" % arm_binary) + + return (arm_binary, node) + def setup_qemu_emulator(rootdir, arch): + qemu_emulators = [] # mount binfmt_misc if it doesn't exist if not os.path.exists("/proc/sys/fs/binfmt_misc"): modprobecmd = find_binary_path("modprobe") @@ -818,52 +940,50 @@ def setup_qemu_emulator(rootdir, arch): # qemu_emulator is a special case, we can't use find_binary_path # qemu emulator should be a statically-linked executable file - qemu_emulator = "/usr/bin/qemu-arm" - if not os.path.exists(qemu_emulator) or not is_statically_linked(qemu_emulator): - qemu_emulator = "/usr/bin/qemu-arm-static" - if not os.path.exists(qemu_emulator): - raise CreatorError("Please install a statically-linked qemu-arm") - - # qemu emulator version check - armv7_list = [arch for arch in rpmmisc.archPolicies.keys() if arch.startswith('armv7')] - if arch in armv7_list: # need qemu (>=0.13.0) - qemuout = runner.outs([qemu_emulator, "-h"]) - m = re.search("version\s*([.\d]+)", qemuout) - if m: - qemu_version = m.group(1) - if qemu_version < "0.13": - raise CreatorError("Requires %s version >=0.13 for %s" % (qemu_emulator, arch)) - else: - msger.warning("Can't get version info of %s, please make sure it's higher than 0.13.0" % qemu_emulator) + arm_binary, node = get_qemu_arm_binary(arch) + qemu_emulator = "/usr/bin/%s" % arm_binary if not os.path.exists(rootdir + "/usr/bin"): makedirs(rootdir + "/usr/bin") shutil.copy(qemu_emulator, rootdir + qemu_emulator) + qemu_emulators.append(qemu_emulator) # disable selinux, selinux will block qemu emulator to run if os.path.exists("/usr/sbin/setenforce"): msger.info('Try to disable selinux') runner.show(["/usr/sbin/setenforce", "0"]) - node = "/proc/sys/fs/binfmt_misc/arm" - if is_statically_linked(qemu_emulator) and os.path.exists(node): - return qemu_emulator - - # unregister it if it has been registered and is a dynamically-linked executable - if not is_statically_linked(qemu_emulator) and os.path.exists(node): - qemu_unregister_string = "-1\n" - fd = open("/proc/sys/fs/binfmt_misc/arm", "w") - fd.write(qemu_unregister_string) - fd.close() - # register qemu emulator for interpreting other arch executable file if not os.path.exists(node): - qemu_arm_string = ":arm:M::\\x7fELF\\x01\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x28\\x00:\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xfa\\xff\\xff\\xff:%s:\n" % qemu_emulator - fd = open("/proc/sys/fs/binfmt_misc/register", "w") - fd.write(qemu_arm_string) - fd.close() + if arch == "aarch64": + qemu_arm_string = ":aarch64:M::\\x7fELF\\x02\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\xb7:\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xfe\\xff\\xff:%s:\n" % qemu_emulator + elif arch == "mipsel": + qemu_arm_string = ":mipsel:M::\\x7fELF\\x01\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x08\\x00:\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\xfe\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xfe\\xff\\xff\\xff:%s:\n" % qemu_emulator + else: + qemu_arm_string = ":arm:M::\\x7fELF\\x01\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x28\\x00:\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xfa\\xff\\xff\\xff:%s:\n" % qemu_emulator - return qemu_emulator + with open("/proc/sys/fs/binfmt_misc/register", "w") as fd: + fd.write(qemu_arm_string) + else: + flags = "" + interpreter = "" + with open(node, "r") as fd: + for line in fd.readlines(): + if line.startswith("flags:"): + flags = line[len("flags:"):].strip() + elif line.startswith("interpreter"): + interpreter = line[len("interpreter"):].strip() + + if flags == "P" and interpreter.endswith("-binfmt"): + # copy binfmt wrapper when preserve-argv[0] flag is enabled + shutil.copy(os.path.realpath(interpreter), rootdir + interpreter) + qemu_emulators.append(interpreter) + elif not flags and interpreter != qemu_emulator: + # create symlink as registered qemu emulator + os.symlink(qemu_emulator, rootdir + interpreter) + qemu_emulators.append(interpreter) + + return qemu_emulators def SrcpkgsDownload(pkgs, repometadata, instroot, cachedir): def get_source_repometadata(repometadata): @@ -929,3 +1049,11 @@ def strip_end(text, suffix): if not text.endswith(suffix): return text return text[:-len(suffix)] + +def strip_archive_suffix(filename): + for suffix in get_archive_suffixes(): + if filename.endswith(suffix): + return filename[:-len(suffix)] + else: + msger.warning("Not supported archive file format: %s" % filename) + return None