# -*- coding: utf-8 -*- # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Library General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . from kobo import shortcuts import os import productmd import tempfile from six.moves import shlex_quote from pungi import util from pungi.phases.buildinstall import tweak_configs from pungi.wrappers import iso def sh(log, cmd, *args, **kwargs): log.info("Running: %s", " ".join(shlex_quote(x) for x in cmd)) ret, out = shortcuts.run(cmd, *args, universal_newlines=True, **kwargs) if out: log.debug("%s", out) return ret, out def get_lorax_dir(default="/usr/share/lorax"): try: _, out = shortcuts.run( ["python3", "-c" "import pylorax; print(pylorax.find_templates())"], universal_newlines=True, ) return out.strip() except Exception: return default def as_bool(arg): if arg == "true": return True elif arg == "false": return False else: return arg def get_arch(log, iso_dir): di_path = os.path.join(iso_dir, ".discinfo") if os.path.exists(di_path): di = productmd.discinfo.DiscInfo() di.load(di_path) log.info("Detected bootable ISO for %s (based on .discinfo)", di.arch) return di.arch ti_path = os.path.join(iso_dir, ".treeinfo") if os.path.exists(ti_path): ti = productmd.treeinfo.TreeInfo() ti.load(ti_path) log.info("Detected bootable ISO for %s (based on .treeinfo)", ti.tree.arch) return ti.tree.arch # There is no way to tell the architecture of an ISO file without guessing. # Let's print a warning and continue with assuming unbootable ISO. log.warning("Failed to detect arch for ISO, assuming unbootable one.") log.warning("If this is incorrect, use the --force-arch option.") return None def run(log, opts): # mount source iso log.info("Mounting %s", opts.source) target = os.path.abspath(opts.target) with util.temp_dir(prefix="patch-iso-", dir=opts.work_dir) as work_dir: with iso.mount(opts.source) as source_iso_dir: util.copy_all(source_iso_dir, work_dir) # Make everything writable for root, dirs, files in os.walk(work_dir): for name in files: os.chmod(os.path.join(root, name), 0o640) for name in dirs: os.chmod(os.path.join(root, name), 0o755) # volume id is copied from source iso unless --label is specified volume_id = opts.volume_id or iso.get_volume_id(opts.source) # create graft points from mounted source iso + overlay dir graft_points = iso.get_graft_points(work_dir, [work_dir] + opts.dirs) # if ks.cfg is detected, patch syslinux + grub to use it if "ks.cfg" in graft_points: log.info("Adding ks.cfg to boot configs") tweak_configs(work_dir, volume_id, graft_points["ks.cfg"], logger=log) arch = opts.force_arch or get_arch(log, work_dir) with tempfile.NamedTemporaryFile(prefix="graft-points-") as graft_file: iso.write_graft_points( graft_file.name, graft_points, exclude=["*/TRANS.TBL", "*/boot.cat"] ) # make the target iso bootable if source iso is bootable boot_args = input_charset = None if arch: boot_args = iso.get_boot_options( arch, os.path.join(get_lorax_dir(), "config_files/ppc") ) input_charset = "utf-8" if "ppc" not in arch else None # Create the target ISO mkisofs_cmd = iso.get_mkisofs_cmd( target, None, volid=volume_id, exclude=["./lost+found"], graft_points=graft_file.name, input_charset=input_charset, boot_args=boot_args, ) sh(log, mkisofs_cmd, workdir=work_dir) # isohybrid support if arch in ["x86_64", "i386"]: isohybrid_cmd = iso.get_isohybrid_cmd(target, arch) sh(log, isohybrid_cmd) supported = as_bool( opts.supported or iso.get_checkisomd5_data(opts.source)["Supported ISO"] ) # implantmd5 + supported bit (use the same as on source iso, unless # overridden by --supported option) isomd5sum_cmd = iso.get_implantisomd5_cmd(target, supported) sh(log, isomd5sum_cmd)