diff options
-rwxr-xr-x | common_functions | 47 | ||||
-rwxr-xr-x | init_buildsystem | 116 | ||||
-rw-r--r-- | initvm.c | 56 |
3 files changed, 144 insertions, 75 deletions
diff --git a/common_functions b/common_functions index f0084f8..54a1573 100755 --- a/common_functions +++ b/common_functions @@ -88,20 +88,27 @@ check_exit() { fi } -check_use_emulator() { - INITVM_NAME= - # check if the extended host arch contains the build arch +check_native_arch() { + local arch="$1" local old_build_arch="$BUILD_ARCH" - local arch="${BUILD_ARCH%%:*}" BUILD_ARCH="$BUILD_HOST_ARCH" extend_build_arch BUILD_ARCH=":$BUILD_ARCH:" if test "$BUILD_ARCH" != "${BUILD_ARCH/:$arch:/}" ; then - # native supported arch, no emulator BUILD_ARCH="$old_build_arch" - return 1 + return 0 fi BUILD_ARCH="$old_build_arch" + return 1 +} + +check_use_emulator() { + INITVM_NAME= + # check if the extended host arch contains the build arch + if check_native_arch "${BUILD_ARCH%%:*}" ; then + # native supported arch, no emulator needed + return 1 + fi # to run the qemu initialization in the vm, we need to # register it with a static program or shell script @@ -158,4 +165,32 @@ buildroot_umount() { LOOP_CNT=$((LOOP_CNT+1)) done } +# rm that makes sure the file is gone +buildroot_rm() { + rm -rf "$BUILD_ROOT/$1" + test -e "$BUILD_ROOT/$1" && cleanup_and_exit 1 "could not remove $BUILD_ROOT/$1" +} + +assert_dirs() { + local d rl + if test -z "$1" ; then + set usr sbin usr/bin usr/sbin etc .build .build.oldpackages .init_b_cache .init_b_cache/scripts .init_b_cache/rpms .preinstall_image proc proc/sys proc/sys/fs proc/sys/fs/binfmt_misc sys dev dev/pts dev/shm mnt + fi + for d in "$@" ; do + if test -L "$BUILD_ROOT/$d" ; then + rl="$(readlink "$BUILD_ROOT/$d")" + test "$d" = sbin -a "x$rl" = "xusr/sbin" && continue + test "$d" = sbin -a "x$rl" = "xusr/bin" && continue + test "$d" = usr/sbin -a "x$rl" = "xbin" && continue + cleanup_and_exit 1 "$d: illegal symlink to $rl" + else + test -e "$BUILD_ROOT/$d" -a ! -d "$BUILD_ROOT/$d" && cleanup_and_exit 1 "$d: not a directory" + fi + done +} + +assert_dir_path() { + test "$1" != "${1%/*}" && assert_dir_path "${1%/*}" + assert_dirs "$1" +} diff --git a/init_buildsystem b/init_buildsystem index 30f4132..6876514 100755 --- a/init_buildsystem +++ b/init_buildsystem @@ -152,45 +152,60 @@ TMPFILE="$BUILD_ROOT"/tmpfile # # needed functions # - -cleanup_and_exit() { - trap EXIT - test "$BUILD_ROOT" = / -a -n "$browner" && chown "$browner" "$BUILD_ROOT" - # umount so init_buildsystem can be used standalone -# XXX: use stat -f /dev/pts/ -c %T to check whether it's mounted and not suppress errors then? - buildroot_umount "/proc/sys/fs/binfmt_misc" - buildroot_umount "/proc" - buildroot_umount "/sys" - buildroot_umount "/dev/pts" - buildroot_umount "/dev/shm" - buildroot_umount "/mnt" - exit ${1:-0} +mount_stuff() { + if test "$UID" = 0 -a -n "$BUILD_ROOT" -a "$BUILD_ROOT" != / ; then + mount -n -tproc none "$BUILD_ROOT/proc" + test -e "$BUILD_ROOT/proc/self" || cleanup_and_exit 1 "Could not mount /proc, is this a container with missing capabilities?" + mount -n -tdevpts -omode=0620,gid=5 none "$BUILD_ROOT/dev/pts" + fi } -clean_build_root() { - if test -n "$BUILD_ROOT" ; then +umount_stuff() { + if test -n "$BUILD_ROOT" -a "$BUILD_ROOT" != / ; then buildroot_umount "/proc/sys/fs/binfmt_misc" buildroot_umount "/proc" buildroot_umount "/sys" buildroot_umount "/dev/pts" buildroot_umount "/dev/shm" buildroot_umount "/mnt" + fi +} + +cleanup_and_exit() { + trap EXIT + test -z "$1" && set 0 + if test -n "$2" ; then + if test "$1" -ne 0 ; then + echo "$2" >&2 + else + echo "$2" + fi + fi + test "$BUILD_ROOT" = / -a -n "$browner" && chown "$browner" "$BUILD_ROOT" + # umount so init_buildsystem can be used standalone + umount_stuff + # never report a fatal error when the job got killed from outside + test "$1" = 4 -a -e "$BUILD_ROOT/exit" && exit 1 + exit $1 +} + +clean_build_root() { + if test -n "$BUILD_ROOT" -a "$BUILD_ROOT" != / ; then + umount_stuff rm -rf -- "$BUILD_ROOT"/* 2> /dev/null || true - chattr -a -A -i -R -- "$BUILD_ROOT" 2> /dev/null || true + chattr -a -A -i -R -- "$BUILD_ROOT" 2> /dev/null || true # does not follow symlinks rm -rf -- "$BUILD_ROOT"/* rm -rf -- "$BUILD_ROOT/.build" + rm -rf -- "$BUILD_ROOT"/.build.console.* + rm -rf -- "$BUILD_ROOT"/.build.hostarch.* rm -rf -- "$BUILD_ROOT"/.build.kernel.* rm -rf -- "$BUILD_ROOT"/.build.initrd.* + rm -rf -- "$BUILD_ROOT"/.build.sysroot rm -rf -- "$BUILD_ROOT/.root" rm -rf -- "$BUILD_ROOT/.init_b_cache" + test -L "$BUILD_ROOT/.preinstall_image" && rm -f -- "$BUILD_ROOT/.preinstall_image" rm -rf -- "$BUILD_ROOT"/.preinstall_image/* rm -rf -- "$BUILD_ROOT"/.preinstallimage* - mkdir -p "$BUILD_ROOT/proc" - mkdir -p "$BUILD_ROOT/dev/pts" - if test "$UID" = 0 ; then - mount -n -tproc none "$BUILD_ROOT/proc" - mount -n -tdevpts -omode=0620,gid=5 none "$BUILD_ROOT/dev/pts" - fi fi } @@ -281,7 +296,7 @@ create_devs() { done << DEVLIST mknod null 666 c 1 3 mknod zero 666 c 1 5 - mknod full 622 c 1 7 + mknod full 666 c 1 7 mknod random 666 c 1 8 mknod urandom 644 c 1 9 mknod tty 666 c 5 0 @@ -572,10 +587,7 @@ fi if test -e "$BUILD_IS_RUNNING" ; then echo "It seems that there was an incomplete setup of $BUILD_ROOT." echo "To be sure, we will build it again completely..." - umount -n "$BUILD_ROOT"/proc/sys/fs/binfmt_misc 2> /dev/null || true - umount -n "$BUILD_ROOT"/proc 2> /dev/null - umount -n "$BUILD_ROOT"/dev/pts 2> /dev/null - umount -n "$BUILD_ROOT"/mnt 2> /dev/null + umount_stuff echo "Your build system is broken!! Shall I execute" echo echo " rm -rf -- $BUILD_ROOT/*" @@ -595,11 +607,21 @@ if test -e "$BUILD_IS_RUNNING" ; then esac fi +# check for surprises +if test -z "$CLEAN_BUILD" -a -n "$BUILD_ROOT" -a "$BUILD_ROOT" != / ; then + assert_dirs +fi + +# umount stuff if mounted +if test -n "$BUILD_ROOT" -a "$BUILD_ROOT" != / -a -e "$BUILD_ROOT/proc/self" ; then + umount_stuff +fi + # -# store that we start to build system +# store that we start to build the system # -mkdir -p "$BUILD_ROOT" -mkdir -p "$BUILD_ROOT"/.build +mkdir -p -- "$BUILD_ROOT" "$BUILD_ROOT/.build" "$BUILD_ROOT/proc" "$BUILD_ROOT/sys" "$BUILD_ROOT/dev/pts" || cleanup_and_exit 4 + touch $BUILD_IS_RUNNING if test -n "$PREPARE_VM" ; then @@ -607,14 +629,8 @@ if test -n "$PREPARE_VM" ; then fi if test -e "$BUILD_ROOT"/.build/init_buildsystem.data ; then - # vm continuation + # vm continuation, read old config . "$BUILD_ROOT"/.build/init_buildsystem.data - if ! test -e "$BUILD_ROOT"/.init_b_cache/preinstall_finished ; then - # finish preinstall - run_pkg_scripts - pkg_initdb - touch "$BUILD_ROOT"/.init_b_cache/preinstall_finished - fi else # # now make sure that all the packages are installed. @@ -661,7 +677,7 @@ else # register the QEMU emulator if needed # (we do not need this for the prepare step, as we do not run scripts in this case) # - copy_qemu + copy_qemu if test -z "$PREPARE_VM" ; then if check_use_emulator ; then echo "registering binfmt handlers for cross build" @@ -884,6 +900,7 @@ if test ! -e "$BUILD_ROOT"/installed-pkg -a ! -e "$BUILD_ROOT"/.build/init_build test -e "$BUILD_ROOT"/etc/fstab || touch "$BUILD_ROOT"/etc/fstab test ! -e "$BUILD_ROOT"/etc/ld.so.conf -a -e "$BUILD_ROOT"/etc/ld.so.conf.in && cp "$BUILD_ROOT"/etc/ld.so.conf.in "$BUILD_ROOT"/etc/ld.so.conf if test -z "$PREPARE_VM" ; then + mount_stuff run_pkg_scripts pkg_initdb touch "$BUILD_ROOT"/.init_b_cache/preinstall_finished @@ -891,6 +908,11 @@ if test ! -e "$BUILD_ROOT"/installed-pkg -a ! -e "$BUILD_ROOT"/.build/init_build # mark as preinstalled no longer needed rm -rf "$BUILD_ROOT/installed-pkg" mkdir -p "$BUILD_ROOT/installed-pkg" +else + # preinstall was already done + if test -z "$PREPARE_VM" ; then + mount_stuff + fi fi if test -n "$PREPARE_VM" ; then @@ -917,11 +939,15 @@ if test -n "$PREPARE_VM" ; then cleanup_and_exit 0 fi +# +# finish preinstall if this is a vm continuation +# +if test -e "$BUILD_ROOT/.build/init_buildsystem.data" -a ! -e "$BUILD_ROOT/.init_b_cache/preinstall_finished" ; then + run_pkg_scripts + pkg_initdb + touch "$BUILD_ROOT/.init_b_cache/preinstall_finished" +fi -mkdir -p "$BUILD_ROOT"/proc -mkdir -p "$BUILD_ROOT"/dev/pts -mount -n -tproc none "$BUILD_ROOT"/proc 2>/dev/null || true -mount -n -tdevpts -omode=0620,gid=5 none "$BUILD_ROOT"/dev/pts 2>/dev/null || true # # create .build.binaries directory if requested @@ -1111,9 +1137,9 @@ cd "$BUILD_ROOT" || cleanup_and_exit 1 # # setup /etc/mtab # -rm -f "$BUILD_ROOT"/etc/mtab -cp /proc/mounts "$BUILD_ROOT"/etc/mtab -chmod 644 "$BUILD_ROOT"/etc/mtab +#init_buildsystem: make /etc/mtab a symlink +#from patch:https://github.com/openSUSE/obs-build/commit/f0e7d37c811dbde49fcd5b9c8779063f4e87cb74 +ln -sf ../proc/self/mounts $BUILD_ROOT/etc/mtab # # make sure, that our nis is not present in the chroot system @@ -20,7 +20,7 @@ * * AUTHOR * Copyright (c) 2012 James Perkins <james.perkins@linuxfoundation.org> - * i Adrian Schroeter <adrian@suse.de> + * Adrian Schroeter <adrian@suse.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 or 3 as @@ -45,6 +45,7 @@ #include <string.h> #include <errno.h> #include <stdio.h> +#include <unistd.h> /* to enable debugging, compile with -DDEBUG */ #ifdef DEBUG @@ -273,7 +274,7 @@ enum okfail binfmt_register(char *datafile, char *regfile) f[name]); #endif /* DEBUG */ - /* Does the interpreter exists? */ + /* Does the interpreter exists? */ ret=access(f[interpreter], X_OK); if (ret != 0) { #ifdef DEBUG @@ -316,29 +317,34 @@ enum okfail binfmt_register(char *datafile, char *regfile) int main(int argc, char* argv[], char* env[]) { int retval; - char buf[BUFSIZ]; + char buf[BUFSIZ], *build_dir; - /* mount proc filesystem if it isn't already */ - if (mount("proc", "/proc", "proc", MS_MGC_VAL, NULL) == -1) { - if (errno != EBUSY) { - perror("mount: /proc"); - exit(1); + if (system("mount | grep 'proc on /proc type proc' >/dev/null") != 0) { + /* mount proc filesystem if it isn't already. */ + if (mount("proc", "/proc", "proc", MS_MGC_VAL, NULL) == -1) { + if (errno != EBUSY) { + perror("mount: /proc"); + exit(1); + } + } + } + + /* need to have binfmt_misc loaded already */ + if (system("mount | grep 'binfmt_misc on /proc/sys/fs/binfmt_misc' >/dev/null") != 0) { + /* try to load binfmt module if present, no big deal if it fails */ + if ((retval = system("/sbin/modprobe binfmt_misc")) != 0) { + DBG(fprintf(stderr, "modprobe binfmt_misc exit code %d\n", + retval)); } - } - - /* try to load binfmt module if present, no big deal if it fails */ - if ((retval = system("/sbin/modprobe binfmt_misc")) != 0) { - DBG(fprintf(stderr, "modprobe binfmt_misc exit code %d\n", - retval)); - } - /* mount binfmt filesystem */ - if (mount("binfmt_misc", SYSFS_BINFMT_MISC, "binfmt_misc", MS_MGC_VAL, - NULL) == -1) { - if (errno != EBUSY) { - perror("mount: binfmt_misc, " SYSFS_BINFMT_MISC); + /* mount binfmt filesystem */ + if (mount("binfmt_misc", SYSFS_BINFMT_MISC, "binfmt_misc", MS_MGC_VAL, + NULL) == -1) { + if (errno != EBUSY) { + perror("mount: binfmt_misc, " SYSFS_BINFMT_MISC); + } } - } + } /* verify all paths resulting from this are OK */ if (!test_access_files(rx_files, R_OK|X_OK, "read/search")) { @@ -361,10 +367,12 @@ int main(int argc, char* argv[], char* env[]) exit(1); } - if (getenv("BUILD_DIR")) - sprintf(buf, "%s/qemu-reg", getenv("BUILD_DIR")); + *buf = 0; + build_dir = getenv("BUILD_DIR"); + if (build_dir && strlen(build_dir) < sizeof(buf) - 10) + sprintf(buf, "%s/qemu-reg", build_dir); - if (!buf || !binfmt_register(buf, SYSFS_BINFMT_MISC_REG)) { + if (!*buf || !binfmt_register(buf, SYSFS_BINFMT_MISC_REG)) { /* setup all done, do the registration */ if (!binfmt_register(BINFMT_REGF_0, SYSFS_BINFMT_MISC_REG)) { fprintf(stderr, "%s: failed. Trying alternate binfmt file\n", |