Ver Fonte

Factor out chroot helpers to lib.sh

This commit removes all of the chroot refactor to a seperate file.
This paves the way to use these functions in all other scripts.
Michael Aldridge há 7 anos atrás
pai
commit
34bffe1e2a
2 ficheiros alterados com 203 adições e 184 exclusões
  1. 189 0
      lib.sh.in
  2. 14 184
      mkrootfs.sh.in

+ 189 - 0
lib.sh.in

@@ -0,0 +1,189 @@
+info_msg() {
+    # This function handles the printing that is bold within all
+    # scripts.  This is a convenience function so that the rather ugly
+    # looking ASCII escape codes live in only one place.
+    printf "\033[1m%s\n\033[m" "$@"
+}
+
+die() {
+    # This function is registered in all the scripts to make sure that
+    # the important mounts get cleaned up and the $ROOTFS location is
+    # removed.
+    printf "FATAL: %s\n" "$@"
+    umount_pseudofs
+    [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
+    exit 1
+}
+
+mount_pseudofs() {
+    # This function ensures that the psuedofs mountpoints are present
+    # in the chroot.  Strictly they are not necessary to have for many
+    # commands, but bind-mounts are cheap and it isn't too bad to just
+    # mount them all the time.
+    for f in dev proc sys; do
+        # In a naked chroot there is nothing to bind the mounts to, so
+        # we need to create directories for these first.
+        [ ! -d "$ROOTFS/$f" ] && mkdir -p "$ROOTFS/$f"
+        if ! mountpoint -q "$ROOTFS/$f" ; then
+            # It is VERY important that this only happen if the
+            # pseudofs isn't already mounted.  If it already is then
+            # this is virtually impossible to troubleshoot because it
+            # looks like the subsequent umount just isn't working.
+            mount -r --bind /$f "$ROOTFS/$f"
+        fi
+    done
+}
+
+umount_pseudofs() {
+    # This function cleans up the mounts in the chroot.  Failure to
+    # clean up these mounts will prevent the tmpdir from being
+    # deletable instead throwing the error "Device or Resource Busy".
+    # The '-f' option is passed to umount to account for the
+    # contingency where the psuedofs mounts are not present.
+    if [ -d "${ROOTFS}" ]; then
+        for f in dev proc sys; do
+            umount -f "$ROOTFS/$f" >/dev/null 2>&1
+        done
+    fi
+}
+
+run_cmd_target() {
+    info_msg "Running $* for target $XBPS_TARGET_ARCH ..."
+    if [ "$XBPS_TARGET_ARCH" = "$(xbps-uhelper arch)" ] ; then
+        # This is being run on the same architecture as the host,
+        # therefore we should set XBPS_ARCH.
+        if ! eval XBPS_ARCH="$XBPS_TARGET_ARCH" "$@" ; then
+            die "Could not run command $*"
+        fi
+    else
+        # This is being run on a foriegn arch, therefore we should set
+        # XBPS_TARGET_ARCH.  In this case XBPS will not attempt
+        # certain actions and will require reconfiguration later.
+        if ! eval XBPS_TARGET_ARCH="$XBPS_TARGET_ARCH" "$@" ; then
+            die "Could not run command $*"
+        fi
+    fi
+}
+
+run_cmd() {
+    # This is a general purpose function to run commands that a user
+    # may wish to see.  For example its useful to see the tar/xz
+    # pipeline to not need to delve into the scripts to see what
+    # options its set up with.
+    info_msg "Running $*"
+    eval "$@"
+}
+
+run_cmd_chroot() {
+    # General purpose chroot function which makes sure the chroot is
+    # prepared.  This function takes 2 arguments, the location to
+    # chroot to and the command to run.
+
+    # This is an idempotent function, it is safe to call every time
+    # before entering the chroot.  This has the advantage of making
+    # execution in the chroot appear as though it "Just Works(tm)".
+    register_binfmt
+
+    # Before we step into the chroot we need to make sure the
+    # pseudo-filesystems are ready to go.  Not all commands will need
+    # this, but its still a good idea to call it here anyway.
+    mount_pseudofs
+
+    # With assurance that things will run now we can jump into the
+    # chroot and run stuff!
+    chroot "$1" sh -c "$2"
+}
+
+cleanup_chroot() {
+    # This function cleans up the chroot shims that are used by QEMU
+    # to allow builds on alien platforms.  It takes no arguments but
+    # expects the global $ROOTFS variable to be set.
+
+    # Un-Mount the pseudofs mounts if they were mounted
+    umount_pseudofs
+
+    # If a QEMU binary was copied in, remove that as well
+    if [ -x "$ROOTFS/usr/bin/$QEMU_BIN" ] ; then
+        rm "$ROOTFS/usr/bin/$QEMU_BIN"
+    fi
+}
+
+# TODO: Figure out how to register the binfmt for x86_64 and for i686
+# to facilitate building on alien build systems.
+register_binfmt() {
+    # This function sets up everything that is needed to be able to
+    # chroot into a ROOTFS and be able to run commands there.  This
+    # really matters on platforms where the host architecture is
+    # different from the target, and you wouldn't be able to run
+    # things like xbps-reconfigure -a.  This function is idempotent
+    # (You can run it multiple times without modifying state).  This
+    # function takes no arguments, but does expect the global variable
+    # $XBPS_TARGET_ARCH to be set.
+
+    # This select sets up the "magic" bytes in /proc that let the
+    # kernel select an alternate interpreter.  More values for this
+    # map can be obtained from here:
+    # https://github.com/qemu/qemu/blob/master/scripts/qemu-binfmt-conf.sh
+    case "${XBPS_TARGET_ARCH}" in
+        armv*)
+            _cpu=arm
+            _magic="\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00"
+            _mask="\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff"
+            QEMU_BIN=qemu-arm-static
+            ;;
+        aarch64*)
+            _cpu=aarch64
+            _magic="\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7"
+            _mask="\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff"
+            QEMU_BIN=qemu-aarch64-static
+            ;;
+        mipsel*)
+            _cpu=mipsel
+            _magic="\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00"
+            _mask="\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff"
+            QEMU_BIN=qemu-mipsel-static
+            ;;
+        *86*)
+            info_msg "FIXME: Assuming that x86 instructions are native"
+            QEMU_BIN=NATIVE
+            ;;
+        *)
+            die "Unknown target architecture!"
+            ;;
+    esac
+
+    # In the special case where the build is native we can return
+    # without doing anything else
+    if [ "$QEMU_BIN" = "NATIVE" ] ; then
+        return
+    fi
+    
+    # For builds that do not match the host architecture, the correct
+    # qemu binary will be required.
+    if ! $QEMU_BIN -version >/dev/null 2>&1; then
+        die "$QEMU_BIN binary is missing in your system, exiting."
+    fi
+
+    # In order to use the binfmt system the binfmt_misc mountpoint
+    # must exist inside of proc
+    if ! mountpoint -q /proc/sys/fs/binfmt_misc ; then
+        modprobe -q binfmt_misc
+        mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc 2>/dev/null
+    fi
+
+    # Only register if the map is incomplete
+    if [ ! -f /proc/sys/fs/binfmt_misc/qemu-$_cpu ] ; then
+        echo ":qemu-$_cpu:M::$_magic:$_mask:$QEMU_BIN:" > /proc/sys/fs/binfmt_misc/register 2>/dev/null
+    fi
+
+    # If the static binary isn't in the chroot then the chroot will
+    # fail.  The kernel knows about the map but without the static
+    # version there's no interpreter in the chroot, only the
+    # dynamically linked one in the host.  To simplify things we just
+    # use the static one always and make sure it shows up at the same
+    # place in the host and the chroot.
+    if [ ! -x "$ROOTFS/usr/bin/$QEMU_BIN" ] ; then
+        cp -f "$(which "$QEMU_BIN")" "$ROOTFS/usr/bin" ||
+            die "Could not install $QEMU_BIN to $ROOTFS/usr/bin/"
+    fi
+}

+ 14 - 184
mkrootfs.sh.in

@@ -28,21 +28,17 @@
 readonly PROGNAME=$(basename "$0")
 readonly ARCH=$(uname -m)
 
+# This source pulls in all the functions from lib.sh.  This set of
+# functions makes it much easier to work with chroots and abstracts
+# away all the problems with running binaries with QEMU.
+# shellcheck source=./lib.sh
+. ./lib.sh
+
+# Die is a function provided in lib.sh which handles the cleanup of
+# the mounts and removal of temporary directories if the running
+# program exists unexpectedly.
 trap 'die "Interrupted! exiting..."' INT TERM HUP
 
-
-info_msg() {
-    printf "\033[1m%s\n\033[m" "$@"
-}
-
-die() {
-    printf "FATAL: %s\n" "$@"
-    umount_pseudofs
-    [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
-    exit 1
-}
-
-
 # Even though we only support really one target for most of these
 # architectures this lets us refer to these quickly and easily by
 # XBPS_ARCH.  This makes it a lot more obvious what is happening later
@@ -68,178 +64,12 @@ Options
 _EOF
 }
 
-mount_pseudofs() {
-    # This function ensures that the psuedofs mountpoints are present
-    # in the chroot.  Strictly they are not necessary to have for many
-    # commands, but bind-mounts are cheap and it isn't too bad to just
-    # mount them all the time.
-    for f in dev proc sys; do
-        # In a naked chroot there is nothing to bind the mounts to, so
-        # we need to create directories for these first.
-        [ ! -d "$ROOTFS/$f" ] && mkdir -p "$ROOTFS/$f"
-        if ! mountpoint -q "$ROOTFS/$f" ; then
-            # It is VERY important that this only happen if the
-            # pseudofs isn't already mounted.  If it already is then
-            # this is virtually impossible to troubleshoot because it
-            # looks like the subsequent umount just isn't working.
-            mount -r --bind /$f "$ROOTFS/$f"
-        fi
-    done
-}
-
-umount_pseudofs() {
-    # This function cleans up the mounts in the chroot.  Failure to
-    # clean up these mounts will prevent the tmpdir from being
-    # deletable instead throwing the error "Device or Resource Busy".
-    # The '-f' option is passed to umount to account for the
-    # contingency where the psuedofs mounts are not present.
-    if [ -d "${ROOTFS}" ]; then
-        for f in dev proc sys; do
-            umount -f "$ROOTFS/$f" >/dev/null 2>&1
-        done
-    fi
-}
-
-run_cmd_target() {
-    info_msg "Running $* for target $XBPS_TARGET_ARCH ..."
-    if [ "$XBPS_TARGET_ARCH" = "$(xbps-uhelper arch)" ] ; then
-        # This is being run on the same architecture as the host,
-        # therefore we should set XBPS_ARCH.
-        if ! eval XBPS_ARCH="$XBPS_TARGET_ARCH" "$@" ; then
-            die "Could not run command $*"
-        fi
-    else
-        # This is being run on a foriegn arch, therefore we should set
-        # XBPS_TARGET_ARCH.  In this case XBPS will not attempt
-        # certain actions and will require reconfiguration later.
-        if ! eval XBPS_TARGET_ARCH="$XBPS_TARGET_ARCH" "$@" ; then
-            die "Could not run command $*"
-        fi
-    fi
-}
-
-run_cmd() {
-    info_msg "Running $*"
-    eval "$@"
-}
-
-run_cmd_chroot() {
-    # General purpose chroot function which makes sure the chroot is
-    # prepared.  This function takes 2 arguments, the location to
-    # chroot to and the command to run.
-
-    # This is an idempotent function, it is safe to call every time
-    # before entering the chroot.  This has the advantage of making
-    # execution in the chroot appear as though it "Just Works(tm)".
-    register_binfmt
-
-    # Before we step into the chroot we need to make sure the
-    # pseudo-filesystems are ready to go.  Not all commands will need
-    # this, but its still a good idea to call it here anyway.
-    mount_pseudofs
-
-    # With assurance that things will run now we can jump into the
-    # chroot and run stuff!
-    chroot "$1" sh -c "$2"
-}
-
-cleanup_chroot() {
-    # This function cleans up the chroot shims that are used by QEMU
-    # to allow builds on alien platforms.  It takes no arguments but
-    # expects the global $ROOTFS variable to be set.
-
-    # Un-Mount the pseudofs mounts if they were mounted
-    umount_pseudofs
-
-    # If a QEMU binary was copied in, remove that as well
-    if [ -x "$ROOTFS/usr/bin/$QEMU_BIN" ] ; then
-        rm "$ROOTFS/usr/bin/$QEMU_BIN"
-    fi
-}
-
-# TODO: Figure out how to register the binfmt for x86_64 and for i686
-# to facilitate building on alien build systems.
-register_binfmt() {
-    # This function sets up everything that is needed to be able to
-    # chroot into a ROOTFS and be able to run commands there.  This
-    # really matters on platforms where the host architecture is
-    # different from the target, and you wouldn't be able to run
-    # things like xbps-reconfigure -a.  This function is idempotent
-    # (You can run it multiple times without modifying state).  This
-    # function takes no arguments, but does expect the global variable
-    # $XBPS_TARGET_ARCH to be set.
-
-    # This select sets up the "magic" bytes in /proc that let the
-    # kernel select an alternate interpreter.  More values for this
-    # map can be obtained from here:
-    # https://github.com/qemu/qemu/blob/master/scripts/qemu-binfmt-conf.sh
-    case "${XBPS_TARGET_ARCH}" in
-        armv*)
-            _cpu=arm
-            _magic="\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00"
-            _mask="\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff"
-            QEMU_BIN=qemu-arm-static
-            ;;
-        aarch64*)
-            _cpu=aarch64
-            _magic="\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7"
-            _mask="\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff"
-            QEMU_BIN=qemu-aarch64-static
-            ;;
-        mipsel*)
-            _cpu=mipsel
-            _magic="\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00"
-            _mask="\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff"
-            QEMU_BIN=qemu-mipsel-static
-            ;;
-        *86*)
-            info_msg "FIXME: Assuming that x86 instructions are native"
-            QEMU_BIN=NATIVE
-            ;;
-        *)
-            die "Unknown target architecture!"
-            ;;
-    esac
-
-    # In the special case where the build is native we can return
-    # without doing anything else
-    if [ "$QEMU_BIN" = "NATIVE" ] ; then
-        return
-    fi
-    
-    # For builds that do not match the host architecture, the correct
-    # qemu binary will be required.
-    if ! $QEMU_BIN -version >/dev/null 2>&1; then
-        die "$QEMU_BIN binary is missing in your system, exiting."
-    fi
-
-    # In order to use the binfmt system the binfmt_misc mountpoint
-    # must exist inside of proc
-    if ! mountpoint -q /proc/sys/fs/binfmt_misc ; then
-        modprobe -q binfmt_misc
-        mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc 2>/dev/null
-    fi
-
-    # Only register if the map is incomplete
-    if [ ! -f /proc/sys/fs/binfmt_misc/qemu-$_cpu ] ; then
-        echo ":qemu-$_cpu:M::$_magic:$_mask:$QEMU_BIN:" > /proc/sys/fs/binfmt_misc/register 2>/dev/null
-    fi
-
-    # If the static binary isn't in the chroot then the chroot will
-    # fail.  The kernel knows about the map but without the static
-    # version there's no interpreter in the chroot, only the
-    # dynamically linked one in the host.  To simplify things we just
-    # use the static one always and make sure it shows up at the same
-    # place in the host and the chroot.
-    if [ ! -x "$ROOTFS/usr/bin/$QEMU_BIN" ] ; then
-        cp -f "$(which "$QEMU_BIN")" "$ROOTFS/usr/bin" ||
-            die "Could not install $QEMU_BIN to $ROOTFS/usr/bin/"
-    fi
-}
+# ########################################
+#      SCRIPT EXECUTION STARTS HERE
+# ########################################
 
-#
-# main()
-#
+# Boilerplate option parsing.  This script supports the bare minimum
+# needed to build an image.
 while getopts "C:c:h:r:V" opt; do
     case $opt in
         C) XBPS_CONFFILE="-C $OPTARG";;