diff options
Diffstat (limited to 'buildstream/plugins/elements')
-rw-r--r-- | buildstream/plugins/elements/dpkg_build.py | 222 | ||||
-rw-r--r-- | buildstream/plugins/elements/dpkg_build.yaml | 77 | ||||
-rw-r--r-- | buildstream/plugins/elements/dpkg_deploy.py | 271 | ||||
-rw-r--r-- | buildstream/plugins/elements/dpkg_deploy.yaml | 27 | ||||
-rw-r--r-- | buildstream/plugins/elements/x86image.py | 69 | ||||
-rw-r--r-- | buildstream/plugins/elements/x86image.yaml | 139 |
6 files changed, 0 insertions, 805 deletions
diff --git a/buildstream/plugins/elements/dpkg_build.py b/buildstream/plugins/elements/dpkg_build.py deleted file mode 100644 index bd8402314..000000000 --- a/buildstream/plugins/elements/dpkg_build.py +++ /dev/null @@ -1,222 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2017 Codethink Limited -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Jonathan Maw <jonathan.maw@codethink.co.uk> - -"""Dpkg build element - -A :mod:`BuildElement <buildstream.buildelement>` implementation for using -dpkg elements - -Default Configuration -~~~~~~~~~~~~~~~~~~~~~ - -The dpkg default configuration: - .. literalinclude:: ../../../buildstream/plugins/elements/dpkg_build.yaml - :language: yaml - -Public data -~~~~~~~~~~~ - -This plugin writes to an element's public data. - -split-rules ------------ - -This plugin overwrites the element's split-rules with a list of its own -creation, creating a split domain for every package that it detected. -e.g. - -.. code:: yaml - - public: - split-rules: - foo: - - /sbin/foo - - /usr/bin/bar - bar: - - /etc/quux - -dpkg-data ---------- - -control -''''''' - -The control file will be written as raw text into the control field. -e.g. - -.. code:: yaml - - public: - dpkg-data: - foo: - control: | - Source: foo - Section: blah - Build-depends: bar (>= 1337), baz - ... - -name -'''' - -The name of the plugin will be written to the name field. -e.g. - -.. code:: yaml - - public: - dpkg-data: - foo: - name: foobar - -package-scripts ---------------- - -preinst, postinst, prerm and postrm scripts may be written to the -package if they are detected. They are written as raw text. e.g. - -.. code:: yaml - - public: - package-scripts: - foo: - preinst: | - #!/usr/bin/bash - /sbin/ldconfig - bar: - postinst: | - #!/usr/bin/bash - /usr/share/fonts/generate_fonts.sh - -""" - -import filecmp -import os -import re - -from buildstream import BuildElement, utils - - -# Element implementation for the 'dpkg' kind. -class DpkgElement(BuildElement): - def _get_packages(self, sandbox): - controlfile = os.path.join("debian", "control") - controlpath = os.path.join( - sandbox.get_directory(), - self.get_variable('build-root').lstrip(os.sep), - controlfile - ) - with open(controlpath) as f: - return re.findall(r"Package:\s*(.+)\n", f.read()) - - def configure(self, node): - # __original_commands is needed for cache-key generation, - # as commands can be altered during builds and invalidate the key - super().configure(node) - self.__original_commands = dict(self.commands) - - def get_unique_key(self): - key = super().get_unique_key() - # Overriding because we change self.commands mid-build, making it - # unsuitable to be included in the cache key. - for domain, cmds in self.__original_commands.items(): - key[domain] = cmds - - return key - - def assemble(self, sandbox): - # Replace <PACKAGES> if no variable was set - packages = self._get_packages(sandbox) - self.commands = dict([ - (group, [ - c.replace("<PACKAGES>", " ".join(packages)) for c in commands - ]) - for group, commands in self.commands.items() - ]) - - collectdir = super().assemble(sandbox) - - bad_overlaps = set() - new_split_rules = {} - new_dpkg_data = {} - new_package_scripts = {} - for package in packages: - package_path = os.path.join(sandbox.get_directory(), - self.get_variable('build-root').lstrip(os.sep), - 'debian', package) - - # Exclude DEBIAN files because they're pulled in as public metadata - contents = [x for x in utils.list_relative_paths(package_path) - if x != "." and not x.startswith("DEBIAN")] - new_split_rules[package] = contents - - # Check for any overlapping files that are different. - # Since we're storing all these files together, we need to warn - # because clobbering is bad! - for content_file in contents: - for split_package, split_contents in new_split_rules.items(): - for split_file in split_contents: - content_file_path = os.path.join(package_path, - content_file.lstrip(os.sep)) - split_file_path = os.path.join(os.path.dirname(package_path), - split_package, - split_file.lstrip(os.sep)) - if (content_file == split_file and - os.path.isfile(content_file_path) and - not filecmp.cmp(content_file_path, split_file_path)): - bad_overlaps.add(content_file) - - # Store /DEBIAN metadata for each package. - # DEBIAN/control goes into bst.dpkg-data.<package>.control - controlpath = os.path.join(package_path, "DEBIAN", "control") - if not os.path.exists(controlpath): - self.error("{}: package {} doesn't have a DEBIAN/control in {}!" - .format(self.name, package, package_path)) - with open(controlpath, "r") as f: - controldata = f.read() - new_dpkg_data[package] = {"control": controldata, "name": package} - - # DEBIAN/{pre,post}{inst,rm} scripts go into bst.package-scripts.<package>.<script> - scriptfiles = ["preinst", "postinst", "prerm", "postrm"] - for s in scriptfiles: - path = os.path.join(package_path, "DEBIAN", s) - if os.path.exists(path): - if package not in new_package_scripts: - new_package_scripts[package] = {} - with open(path, "r") as f: - data = f.read() - new_package_scripts[package][s] = data - - bstdata = self.get_public_data("bst") - bstdata["split-rules"] = new_split_rules - bstdata["dpkg-data"] = new_dpkg_data - if new_package_scripts: - bstdata["package-scripts"] = new_package_scripts - - self.set_public_data("bst", bstdata) - - if bad_overlaps: - self.warn("Destructive overlaps found in some files!", "\n".join(bad_overlaps)) - - return collectdir - - -# Plugin entry point -def setup(): - return DpkgElement diff --git a/buildstream/plugins/elements/dpkg_build.yaml b/buildstream/plugins/elements/dpkg_build.yaml deleted file mode 100644 index 2a164eac1..000000000 --- a/buildstream/plugins/elements/dpkg_build.yaml +++ /dev/null @@ -1,77 +0,0 @@ -# Dpkg default configurations - -variables: - - rulesfile: "debian/rules" - build: "%{rulesfile} build" - binary: "env DH_OPTIONS='--destdir=.' %{rulesfile} binary" - - # packages' default value will be automatically replaced with - # defaults calculated from debian/control. Replace this with a - # space-separated list of packages to have more control over - # what gets generated. - # - # e.g. - # packages: "foo foo-dev foo-doc" - # - packages: <PACKAGES> - install-packages: | - for pkg in %{packages}; do - cp -a debian/${pkg}/* %{install-root} - done - clear-debian: | - rm -r %{install-root}/DEBIAN - patch: | - if grep -q "3.0 (quilt)" debian/source/format; then - quilt push -a - fi - - # Set this if the sources cannot handle parallelization. - # - # notparallel: True - -config: - - # Commands for configuring the software - # - configure-commands: - - | - %{patch} - - # Commands for building the software - # - build-commands: - - | - %{build} - - | - %{binary} - - # Commands for installing the software into a - # destination folder - # - install-commands: - - | - %{install-packages} - - | - %{clear-debian} - - # Commands for stripping debugging information out of - # installed binaries - # - strip-commands: - - | - %{strip-binaries} - -# Use max-jobs CPUs for building and enable verbosity -environment: - MAKEFLAGS: -j%{max-jobs} - V: 1 - DH_VERBOSE: 1 - QUILT_PATCHES: debian/patches - -# And dont consider MAKEFLAGS or V as something which may -# effect build output. -environment-nocache: -- MAKEFLAGS -- V -- DH_VERBOSE diff --git a/buildstream/plugins/elements/dpkg_deploy.py b/buildstream/plugins/elements/dpkg_deploy.py deleted file mode 100644 index c87357cbe..000000000 --- a/buildstream/plugins/elements/dpkg_deploy.py +++ /dev/null @@ -1,271 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2017 Codethink Limited -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Jonathan Maw <jonathan.maw@codethink.co.uk> - -"""Dpkg deployment element - -A :mod:`ScriptElement <buildstream.scriptelement>` implementation for creating -debian packages - -Default Configuration -~~~~~~~~~~~~~~~~~~~~~ - -The dpkg_deploy default configuration: - .. literalinclude:: ../../../buildstream/plugins/elements/dpkg_deploy.yaml - :language: yaml - -Public Data -~~~~~~~~~~~ - -This plugin uses the public data of the element indicated by `config.input` -to generate debian packages. - -split-rules ------------ - -This plugin consumes the input element's split-rules to identify which file -goes in which package, e.g. - -.. code:: yaml - - public: - split-rules: - foo: - - /sbin/foo - - /usr/bin/bar - bar: - - /etc/quux - -dpkg-data ---------- - -control -''''''' - -The control field is used to generate the control file for each package, e.g. - -.. code:: yaml - - public: - dpkg-data: - foo: - control: | - Source: foo - Section: blah - Build-depends: bar (>= 1337), baz - ... - -name -'''' - -If the "name" field is present, the generated package will use that field to -determine its name. -If "name" is not present, the generated package will be named -<element_name>-<package_name> - -i.e. in an element named foo: - -.. code:: yaml - - public: - dpkg-data: - bar: - name: foobar - -will be named "foobar", while the following data: - -.. code:: yaml - - public: - dpkg-data: - bar: - ... - -will create a package named "foo-bar" - -package-scripts ---------------- - -preinst, postinst, prerm and postrm scripts will be generated -based on data in pacakge-scripts, if it exists. The scripts are formatted as -raw text, e.g. - -.. code:: yaml - - public: - package-scripts: - foo: - preinst: | - #!/usr/bin/bash - /sbin/ldconfig - bar: - postinst: | - #!/usr/bin/bash - /usr/share/fonts/generate_fonts.sh - -""" - -import hashlib -import os -import re -from buildstream import ScriptElement, Scope, utils - - -def md5sum_file(path): - hash_md5 = hashlib.md5() - with open(path, "rb") as f: - for chunk in iter(lambda: f.read(4096), b""): - hash_md5.update(chunk) - return hash_md5.hexdigest() - - -# Element implementation for the 'dpkg_deploy' kind. -class DpkgDeployElement(ScriptElement): - def configure(self, node): - prefixes = ["pre-", "", "post-"] - groups = ["build-commands"] - - self.node_validate(node, [ - 'pre-build-commands', 'build-commands', 'post-build-commands', - 'base', 'input' - ]) - - self.__input = self.node_subst_member(node, 'input') - self.layout_add(self.node_subst_member(node, 'base'), "/") - self.layout_add(None, '/buildstream') - self.layout_add(self.__input, - self.get_variable('build-root')) - self.unedited_cmds = {} - for group in groups: - cmds = [] - if group not in node: - raise ElementError("{}: Unexpectedly missing command group '{}'" - .format(self, group)) - for prefix in prefixes: - if prefix + group in node: - cmds += self.node_subst_list(node, prefix + group) - self.unedited_cmds[group] = cmds - - self.set_work_dir() - self.set_install_root() - self.set_root_read_only(True) - - def get_unique_key(self): - key = super().get_unique_key() - del key["commands"] - key["unedited-commands"] = self.unedited_cmds - return key - - def stage(self, sandbox): - super().stage(sandbox) - # For each package, create a subdir in build-root and copy the files to there - # then reconstitute the /DEBIAN files. - input_elm = self.search(Scope.BUILD, self.__input) - if not input_elm: - self.error("{}: Failed to find input element {} in build-depends" - .format(self.name, self.__input)) - return - bstdata = input_elm.get_public_data('bst') - if "dpkg-data" not in bstdata: - self.error("{}: input element {} does not have any bst.dpkg-data public data" - .format(self.name, self.__input)) - for package, package_data in self.node_items(bstdata['dpkg-data']): - package_name = package_data.get("name", "{}-{}".format(input_elm.normal_name, package)) - if not ("split-rules" in bstdata and - package in bstdata["split-rules"]): - self.error("{}: Input element {} does not have bst.split-rules.{}" - .format(self.name, self.__input.name, package)) - package_splits = bstdata['split-rules'][package] - src = os.path.join(sandbox.get_directory(), - self.get_variable("build-root").lstrip(os.sep)) - dst = os.path.join(src, package) - os.makedirs(dst, exist_ok=True) - utils.link_files(src, dst, package_splits) - - # Create this dir. If it already exists, - # something unexpected has happened. - debiandir = os.path.join(dst, "DEBIAN") - os.makedirs(debiandir) - - # Recreate the DEBIAN files. - # control is extracted verbatim, and is mandatory. - if "control" not in package_data: - self.error("{}: Cannot reconstitute package {}".format(self.name, package), - detail="There is no public.bst.dpkg-data.{}.control".format(package)) - controlpath = os.path.join(debiandir, "control") - controltext = package_data["control"] - # Slightly ugly way of renaming the package - controltext = re.sub(r"^Package:\s*\S+", - "Package: {}".format(package_name), - controltext) - with open(controlpath, "w") as f: - f.write(controltext) - - # Generate a DEBIAN/md5sums file from the artifact - md5sums = {} - for split in package_splits: - filepath = os.path.join(src, split.lstrip(os.sep)) - if os.path.isfile(filepath): - md5sums[split] = md5sum_file(filepath) - md5sumspath = os.path.join(debiandir, "md5sums") - with open(md5sumspath, "w") as f: - for path, md5sum in md5sums.items(): - f.write("{} {}\n".format(md5sum, path)) - - # scripts may exist - if ("package-scripts" in bstdata and - package in bstdata["package-scripts"]): - for script in ["postinst", "preinst", "postrm", "prerm"]: - if script in bstdata["package-scripts"][package]: - filepath = os.path.join(debiandir, script) - with open(filepath, "w") as f: - f.write(bstdata["package-scripts"][package][script]) - os.chmod(filepath, 0o755) - - def _packages_list(self): - input_elm = self.search(Scope.BUILD, self.__input) - if not input_elm: - detail = ("Available elements are {}" - .format("\n".join([x.name for x in self.dependencies(Scope.BUILD)]))) - self.error("{} Failed to find element {}".format(self.name, self.__input), - detail=detail) - - bstdata = input_elm.get_public_data("bst") - if "dpkg-data" not in bstdata: - self.error("{}: Can't get package list for {}, no bst.dpkg-data" - .format(self.name, self.__input)) - return " ".join([k for k, v in self.node_items(bstdata["dpkg-data"])]) - - def _sub_packages_list(self, cmdlist): - return [ - cmd.replace("<PACKAGES>", self._packages_list()) for cmd in cmdlist - ] - - def assemble(self, sandbox): - # Mangle commands here to replace <PACKAGES> with the list of packages. - # It can't be done in configure (where it was originally set) because - # we don't have access to the input element at that time. - for group, commands in self.unedited_cmds.items(): - self.add_commands(group, self._sub_packages_list(commands)) - return super().assemble(sandbox) - - -# Plugin entry point -def setup(): - return DpkgDeployElement diff --git a/buildstream/plugins/elements/dpkg_deploy.yaml b/buildstream/plugins/elements/dpkg_deploy.yaml deleted file mode 100644 index a97fb2bbf..000000000 --- a/buildstream/plugins/elements/dpkg_deploy.yaml +++ /dev/null @@ -1,27 +0,0 @@ -#dpkg_deploy default configuration - -variables: - # packages' default value will be automatically replaced with - # defaultscalculated from the input's split-rules. Replace this - # with a space-separated list of packages to have more control - # over what gets generated. - # - packages: <PACKAGES> - buildpkg: | - for package in %{packages}; do - dpkg-deb --build %{build-root}/$package %{install-root} - done - -config: - # The element that should be staged into "/". It must contain - # all the tools required to generate the image - # base: image-tools.bst - - # The element that should be staged into %{build-root}. It is - # expected to be the system that you're planning to turn into - # an image. - # input: foo-system.bst - - build-commands: - - | - %{buildpkg} diff --git a/buildstream/plugins/elements/x86image.py b/buildstream/plugins/elements/x86image.py deleted file mode 100644 index 4bd0ca91a..000000000 --- a/buildstream/plugins/elements/x86image.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2017 Codethink Limited -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Jonathan Maw <jonathan.maw@codethink.co.uk> - -"""x86 image build element - -A :mod:`ScriptElement <buildstream.scriptelement>` implementation for creating -x86 disk images - -The x86image default configuration: - .. literalinclude:: ../../../buildstream/plugins/elements/x86image.yaml - :language: yaml -""" - -from buildstream import ScriptElement - - -# Element implementation for the 'x86image' kind. -class X86ImageElement(ScriptElement): - def configure(self, node): - prefixes = ["pre-", "", "post-"] - groups = [ - "filesystem-tree-setup-commands", - "filesystem-image-creation-commands", - "partition-commands", - "final-commands" - ] - - self.node_validate(node, (prefix + group for group in groups for prefix in prefixes)) - - for group in groups: - cmds = [] - if group not in node: - raise ElementError("{}: Unexpectedly missing command group '{}'" - .format(self, group)) - for prefix in prefixes: - if prefix + group in node: - cmds += self.node_subst_list(node, prefix + group) - self.add_commands(group, cmds) - - self.layout_add(self.node_subst_member(node, 'base'), "/") - self.layout_add(None, '/buildstream') - self.layout_add(self.node_subst_member(node, 'input'), - self.get_variable('build-root')) - - self.set_work_dir() - self.set_install_root() - self.set_root_read_only(True) - - -# Plugin entry point -def setup(): - return X86ImageElement diff --git a/buildstream/plugins/elements/x86image.yaml b/buildstream/plugins/elements/x86image.yaml deleted file mode 100644 index 61224b1b0..000000000 --- a/buildstream/plugins/elements/x86image.yaml +++ /dev/null @@ -1,139 +0,0 @@ -#x86 image default configuration - -variables: - # Size of the disk to create - # - # Should be able to calculate this based on the space - # used, however it must be a multiple of (63 * 512) bytes - # as mtools wants a size that is devisable by sectors (512 bytes) - # per track (63). - boot-size: 252000K - rootfs-size: 4G - swap-size: 1G - sector-size: 512 - -config: - # The element that should be staged into "/". It must contain - # all the tools required to generate the image - # base: image-tools.bst - - # The element that should be staged into %{build-root}. It is expected - # to be the system that you're planning to turn into an image. - # input: foo-system.bst - - filesystem-tree-setup-commands: - - | - # XXX Split up the boot directory and the other - # - # This should be changed so that the /boot directory - # is created separately. - - cd /buildstream - mkdir -p /buildstream/sda1 - mkdir -p /buildstream/sda2 - - mv %{build-root}/boot/* /buildstream/sda1 - mv %{build-root}/* /buildstream/sda2 - - - | - # Generate an fstab - cat > /buildstream/sda2/etc/fstab << EOF - /dev/sda2 / ext4 defaults,rw,noatime 0 1 - /dev/sda1 /boot vfat defaults 0 2 - /dev/sda3 none swap defaults 0 0 - EOF - - - | - # Create the syslinux config - mkdir -p /buildstream/sda1/syslinux - cat > /buildstream/sda1/syslinux/syslinux.cfg << EOF - PROMPT 0 - TIMEOUT 5 - - ALLOWOPTIONS 1 - SERIAL 0 115200 - - DEFAULT boot - LABEL boot - - KERNEL /vmlinuz - INITRD /initramfs.gz - - APPEND root=/dev/sda2 rootfstype=ext4 rootdelay=20 init=/sbin/init - EOF - filesystem-image-creation-commands: - - | - # Create the vfat image - truncate -s %{boot-size} /buildstream/sda1.img - mkdosfs /buildstream/sda1.img - - - | - # Copy all that stuff into the image - mcopy -D s -i /buildstream/sda1.img -s /buildstream/sda1/* ::/ - - - | - # Install the bootloader on the image, it should get the config file - # from inside the vfat image, I think - syslinux --directory /syslinux/ /buildstream/sda1.img - - - | - # Now create the root filesys on sda2 - truncate -s %{rootfs-size} /buildstream/sda2.img - mkfs.ext4 -F -i 8192 /buildstream/sda2.img -L root -d /buildstream/sda2 - - - | - # Create swap - truncate -s %{swap-size} /buildstream/sda3.img - mkswap -L swap /buildstream/sda3.img - partition-commands: - - | - ######################################## - # Partition the disk # - ######################################## - - # First get the size in bytes - sda1size=$(stat --printf="%s" /buildstream/sda1.img) - sda2size=$(stat --printf="%s" /buildstream/sda2.img) - sda3size=$(stat --printf="%s" /buildstream/sda3.img) - - # Now convert to sectors - sda1sec=$(( ${sda1size} / %{sector-size} )) - sda2sec=$(( ${sda2size} / %{sector-size} )) - sda3sec=$(( ${sda3size} / %{sector-size} )) - - # Now get the offsets in sectors, first sector is MBR - sda1offset=1 - sda2offset=$(( ${sda1offset} + ${sda1sec} )) - sda3offset=$(( ${sda2offset} + ${sda2sec} )) - - # Get total disk size in sectors and bytes - sdasectors=$(( ${sda3offset} + ${sda3sec} )) - sdabytes=$(( ${sdasectors} * %{sector-size} )) - - # Create the main disk and do the partitioning - truncate -s ${sdabytes} /buildstream/sda.img - parted -s /buildstream/sda.img mklabel msdos - parted -s /buildstream/sda.img unit s mkpart primary fat32 ${sda1offset} $(( ${sda1offset} + ${sda1sec} - 1 )) - parted -s /buildstream/sda.img unit s mkpart primary ext2 ${sda2offset} $(( ${sda2offset} + ${sda2sec} - 1 )) - parted -s /buildstream/sda.img unit s mkpart primary linux-swap ${sda3offset} $(( ${sda3offset} + ${sda3sec} - 1 )) - - # Make partition 1 the boot partition - parted -s /buildstream/sda.img set 1 boot on - - # Now splice the existing filesystems directly into the image - dd if=/buildstream/sda1.img of=/buildstream/sda.img \ - ibs=%{sector-size} obs=%{sector-size} conv=notrunc \ - count=${sda1sec} seek=${sda1offset} - - dd if=/buildstream/sda2.img of=/buildstream/sda.img \ - ibs=%{sector-size} obs=%{sector-size} conv=notrunc \ - count=${sda2sec} seek=${sda2offset} - - dd if=/buildstream/sda3.img of=/buildstream/sda.img \ - ibs=%{sector-size} obs=%{sector-size} conv=notrunc \ - count=${sda3sec} seek=${sda3offset} - final-commands: - - | - # Move the image where it will be collected - mv /buildstream/sda.img %{install-root} - chmod 0644 %{install-root}/sda.img |