#!/bin/bash # Script to create a complete system to build packages in a chroot # environment. This script ensures, that all packages given as # parameter are installed. All other packges will be deleted. # # BUILD_ROOT here the packages will be installed/deleted # BUILD_RPMS here we get our packages to install # BUILD_ARCH path of the architectures we try # ################################################################ # # Copyright (c) 1997-2014 SUSE Linux Products GmbH # # 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 # published by the Free Software Foundation. # # 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program (see the file COPYING); if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # ################################################################ # # needed globals variables # export SRC export BUILD_DIR=${BUILD_DIR:-/usr/lib/build} PATH="$BUILD_DIR:$PATH" export YAST_IS_RUNNING=instsys # slurp in package binary support . "$BUILD_DIR/build-pkg" # need to restore build root owner for non-root builds browner=0 definesnstuff=() repos=() . $BUILD_DIR/common_functions || exit 1 BUILD_IS_RUNNING="$BUILD_ROOT"/not-ready TMPFILE="$BUILD_ROOT"/tmpfile RPMIDFMT="%{NAME}-%{VERSION}-%{RELEASE} %{BUILDTIME}-%{ARCH}\n" RPMCHECKOPTS_HOST= test -x /usr/bin/rpmquery && RPMCHECKOPTS_HOST="--nodigest --nosignature" # should RPMs be installed with --force ? USE_FORCE=false PREPARE_VM= KEEP_PACKS= USEUSEDFORBUILD= LIST_STATE= RPMLIST= CLEAN_BUILD= CREATE_BUILD_BINARIES= DLNOSIGNATURE= CACHE_DIR=/var/cache/build USEHIGHERDEPS= test -z "$CONFIG_DIR" && CONFIG_DIR="$BUILD_DIR/configs" while test -n "$1" ; do case "$1" in --prepare) shift PREPARE_VM=true ;; --keep-packs) shift KEEP_PACKS=true ;; --create-build-binaries) shift CREATE_BUILD_BINARIES=true ;; --useusedforbuild) shift USEUSEDFORBUILD=--useusedforbuild ;; --list-state) shift LIST_STATE=true ;; --rpmlist) shift RPMLIST=$1 shift ;; --define|--with|--without) definesnstuff[${#definesnstuff[@]}]="$1"; definesnstuff[${#definesnstuff[@]}]="$2"; shift 2 ;; --repository|--repo) repos[${#repos[@]}]="$2"; shift 2 ;; --clean) CLEAN_BUILD="$1" shift ;; --cachedir) CACHE_DIR="$2" shift 2 ;; --configdir) CONFIG_DIR="$2" shift 2 ;; --nosignature) shift DLNOSIGNATURE="--nosignature" ;; --use-higher-deps) shift USEHIGHERDEPS="--usehigherdeps" ;; --root) BUILD_ROOT="$2" shift 2 ;; --arch) BUILD_ARCH="$2" shift 2 ;; --dist) BUILD_DIST="$2" shift 2 ;; *) break ;; esac done PKGS=("$@") if test -z "$BUILD_ROOT" ; then echo "Please specify a build root!" exit 1 fi BUILD_IS_RUNNING="$BUILD_ROOT"/not-ready 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? umount -n "$BUILD_ROOT/proc/sys/fs/binfmt_misc" 2> /dev/null || true umount -n "$BUILD_ROOT/proc" 2> /dev/null || true umount -n "$BUILD_ROOT/dev/pts" 2> /dev/null || true umount -n "$BUILD_ROOT/mnt" 2> /dev/null || true exit ${1:-0} } clean_build_root() { if test -n "$BUILD_ROOT" ; then umount -n "$BUILD_ROOT/proc/sys/fs/binfmt_misc" 2> /dev/null || true umount -n "$BUILD_ROOT/proc" 2> /dev/null || true umount -n "$BUILD_ROOT/dev/pts" 2> /dev/null || true umount -n "$BUILD_ROOT/dev/shm" 2> /dev/null || true umount -n "$BUILD_ROOT/mnt" 2> /dev/null || true rm -rf -- "$BUILD_ROOT"/* 2> /dev/null || true chattr -a -A -i -R -- "$BUILD_ROOT" 2> /dev/null || true rm -rf -- "$BUILD_ROOT"/* rm -rf -- "$BUILD_ROOT/.build" rm -rf -- "$BUILD_ROOT"/.build.kernel.* rm -rf -- "$BUILD_ROOT"/.build.initrd.* rm -rf -- "$BUILD_ROOT/.root" rm -rf -- "$BUILD_ROOT/.init_b_cache" 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 } unsafe_preinstall_check() { # cpio isn't safe so we require bsdtar for VMs. chroot is # unsafe anyways so it's ok for that. if test -n "$PREPARE_VM" ; then echo "Error: setting up a VM requires bsdtar for security reasons." echo "Please install bsdtar." cleanup_and_exit 1 fi } preinstall_image_filter() { for PKG in "$@" ; do test -e "$BUILD_ROOT/.preinstall_image/$PKG" && continue echo $PKG done } preinstall_image() { check_exit echo "unpacking preinstall image${2:+ $2}" cd "$BUILD_ROOT" || cleanup_and_exit 1 if test -x /usr/bin/bsdtar ; then TAR="/usr/bin/bsdtar -P --chroot --numeric-owner -x" else unsafe_preinstall_check TAR="tar -x" fi # pipe output through perl to print a dot every 1000 lines if ! $TAR -z --exclude .build --exclude .init_b_cache -f "$BUILD_ROOT/.init_b_cache/rpms/$1" -v > >(tee "$BUILD_ROOT/.preinstallimage.unpack" | perl -e '$|=1; my $done=0; $done++ % 1000 or print "." while ; print "\n";') 2>&1 ; then echo "unpack failed." test -e "$BUILD_ROOT/.preinstallimage.unpack" && cat "$BUILD_ROOT/.preinstallimage.unpack" cleanup_and_exit 1 fi rm -f "$BUILD_ROOT/.preinstallimage.unpack" } preinstall() { local PKG="$1" check_exit echo "preinstalling $PKG..." cd "$BUILD_ROOT" || cleanup_and_exit 1 if test -x /usr/bin/bsdtar ; then CPIO="/usr/bin/bsdtar -P --chroot -o --numeric-owner -x -f-" TAR="/usr/bin/bsdtar -P --chroot -o --numeric-owner -x" else unsafe_preinstall_check CPIO="cpio --extract --unconditional --preserve-modification-time --make-directories --no-absolute-filenames --quiet" cpio --help 2>/dev/null | grep -q -e --extract-over-symlinks && CPIO="$CPIO --extract-over-symlinks" TAR="tar -x" fi pkg_preinstall } run_pkg_scripts() { chroot "$BUILD_ROOT" /sbin/ldconfig 2>/dev/null for PKG in $PACKAGES_TO_RUNSCRIPTS ; do pkg_runscripts check_exit done } reorder() { test -z "$*" && return rm -f "$BUILD_ROOT"/.init_b_cache/order.manifest for PKG in "$@" ; do echo "$PKG" >> "$BUILD_ROOT"/.init_b_cache/order.manifest done $BUILD_DIR/order --dist "$BUILD_DIST" --archpath "$BUILD_ARCH" --configdir $CONFIG_DIR --manifest "$BUILD_ROOT"/.init_b_cache/order.manifest "$BUILD_ROOT"/.init_b_cache/rpms || touch "$BUILD_ROOT"/exit rm -f "$BUILD_ROOT"/.init_b_cache/order.manifest } create_devs() { local com file mode arg mkdir -m 755 -p "$BUILD_ROOT"/dev/pts test -d "$BUILD_ROOT"/dev/shm || rm -f "$BUILD_ROOT"/dev/shm mkdir -m 755 -p "$BUILD_ROOT"/dev/shm while read com file mode arg ; do rm -f "$BUILD_ROOT"/dev/$file if test $com = ln ; then ln -s $arg "$BUILD_ROOT"/dev/$file continue fi $com -m $mode "$BUILD_ROOT"/dev/$file $arg done << DEVLIST mknod null 666 c 1 3 mknod zero 666 c 1 5 mknod full 622 c 1 7 mknod random 666 c 1 8 mknod urandom 644 c 1 9 mknod tty 666 c 5 0 mknod ptmx 666 c 5 2 mknod loop-control 600 c 10 237 mknod loop0 640 b 7 0 mknod loop1 640 b 7 1 mknod loop2 640 b 7 2 mknod loop3 640 b 7 3 ln fd 777 /proc/self/fd ln stdin 777 fd/0 ln stdout 777 fd/1 ln stderr 777 fd/2 DEVLIST } # check whether the repo list contains a plain "zypp://". Add all # enabled zypp repos in this case expand_plain_zypp_repo() { local i j r=() for i in "${repos[@]}"; do if test "$i" = "zypp://" ; then for j in $($BUILD_DIR/createzyppdeps --listrepos) ; do r=("${r[@]}" "zypp://$j") done else r=("${r[@]}" "$i") fi done repos=("${r[@]}") } create_cache_file() { local findonly= expand_plain_zypp_repo if ! test -f $CACHE_FILE || ! test -f $CACHE_FILE.id || \ test "${repos[*]} ${BUILD_RPMS//:/ /}" != "$(cat $CACHE_FILE.id 2>/dev/null)"; then rm -f $CACHE_FILE.id else for SRC in "${repos[@]}" ${BUILD_RPMS//:/ /}; do test -n "$SRC" || SRC=. if test "${SRC#zypp://}" != "$SRC" ; then SRC="/var/cache/zypp/raw/${SRC#zypp://}" fi if test "$SRC" -nt $CACHE_FILE; then rm -f $CACHE_FILE.id break fi # always rebuild if we have remote repositories and --clean is given if test -n "$CLEAN_BUILD" -a "$SRC" != "${SRC#*://}" -a "${SRC#zypp://}" = "$SRC" ; then rm -f $CACHE_FILE.id break fi done fi if ! test -f $CACHE_FILE.id ; then test -z "$LIST_STATE" && echo initializing $CACHE_FILE ... REPOTYPE= if test -n "$BUILD_DIST" ; then for i in `queryconfig repotype --dist "$BUILD_DIST" --configdir "$CONFIG_DIR" --archpath "$BUILD_ARCH"` ; do case $i in arch|debian|hdlist2|rpm-md) REPOTYPE=$i esac test -n "$REPOTYPE" && break done if test -z "$REPOTYPE"; then BINTYPE=`queryconfig binarytype --dist "$BUILD_DIST" --configdir "$CONFIG_DIR" --archpath "$BUILD_ARCH"` case "$BINTYPE" in arch) REPOTYPE=arch ;; deb) REPOTYPE=debian ;; esac fi fi if test -z "$REPOTYPE" ; then # check the first init_buildsystem arg, maybe it is a recipe case ${PKGS[0]} in *.spec) REPOTYPE=rpm-md ;; *.dsc) REPOTYPE=debian ;; */PKGBUILD|PKGBUILD) REPOTYPE=arch ;; esac fi for SRC in "${repos[@]}" -- ${BUILD_RPMS//:/ /}; do if test "$SRC" = '--' ; then findonly=1 continue fi test -z "$SRC" && SRC=`pwd` if test "${SRC#http://}" != "$SRC" -o "${SRC#https://}" != "$SRC" -o "${SRC#ftp://}" != "$SRC" -o "${SRC#ftps://}" != "$SRC" ; then # remote repo, cache binary packages mkdir -p "$(getcachedir "$SRC")" if test "$REPOTYPE" = arch ; then set -- $BUILD_DIR/createarchdeps --cachedir="$CACHE_DIR" "$SRC" elif test "$REPOTYPE" = debian ; then set -- $BUILD_DIR/createdebdeps --cachedir="$CACHE_DIR" --archpath "$BUILD_ARCH" "$SRC" elif test "$REPOTYPE" = hdlist2 ; then set -- $BUILD_DIR/createmdkdeps --cachedir="$CACHE_DIR" "$SRC" else set -- $BUILD_DIR/createrepomddeps --cachedir="$CACHE_DIR" "$SRC" fi elif test "${SRC#zypp://}" != "$SRC" ; then # special zypp repo set -- $BUILD_DIR/createzyppdeps --cachedir="$CACHE_DIR" "$SRC" elif test ! -e "$SRC" ; then echo "*** $SRC does not exist" >&2 cleanup_and_exit 1 elif test -z "$findonly" -a \( -e "$SRC"/suse/setup/descr/packages -o -e "$SRC"/suse/setup/descr/packages.gz \) ; then set -- $BUILD_DIR/createyastdeps "$SRC" elif test -z "$findonly" -a -e "$SRC"/repodata/repomd.xml ; then set -- $BUILD_DIR/createrepomddeps "$SRC" else set -- $BUILD_DIR/createdirdeps --oldfile "$CACHE_FILE" "$SRC" fi echo "$@" >&2 "$@" || cleanup_and_exit 1 echo D: done > $CACHE_FILE.new mv $CACHE_FILE.new $CACHE_FILE echo "${repos[*]} ${BUILD_RPMS//:/ /}" > $CACHE_FILE.id fi } fail_exit() { cleanup_and_exit 1 } # modifies $SRC downloadpkg() { local url="$1" local cachedir if test "${url:0:7}" == "zypp://" -o "${url:0:7}" == "http://" -o "${url:0:8}" == "https://" -o "${url:0:6}" == "ftp://" -o "${url:0:7}" == "ftps://" ; then cachedir="$(getcachedir "$url")" local name="$(basename "$url")" name=${name/%.pkg.tar.?z/.arch} SRC="$cachedir/$name" else echo "Invalid url: $url" cleanup_and_exit 1 fi local destdir="$cachedir/tmp_$$" mkdir -p "$destdir" echo "downloading $url ... "; $BUILD_DIR/download "$destdir" "$url" || cleanup_and_exit 1 local destfile="$destdir/${url##*/}" if test ! -e "$destfile" ; then echo "expected $destfile after download but it's missing" >&2 cleanup_and_exit 1 fi # for rpm check integrity and the signature case $destfile in *.rpm) rpm -K $DLNOSIGNATURE "$destfile" > $destfile.v || { echo "rpm verify failed" >&2; rm -rf "$destdir"; cleanup_and_exit 1; } if grep "NOT OK" $destfile.v; then rm -rf "$destdir" cleanup_and_exit 1 fi rm -f "$destfile.v" ;; esac mv "$destfile" "$SRC" || cleanup_and_exit 1 rm -rf $destdir } getcachedir() { local url=$1 for repo in "${repos[@]}" ; do if test "${url:0:${#repo}}" == "$repo" ; then read repoid dummy < <(echo -n "$repo" | md5sum) echo "$CACHE_DIR/$repoid" break fi done } can_reuse_cached_package() { local cachepkgid pkgid xpkgid test -s "$1" || return 1 if test -s "$BUILD_ROOT/.init_b_cache/rpms/$PKG.id" ; then local ep=$(rpm -qp --qf "%{EPOCH}" "'${1}'") if test "$ep" != "(none)"; then RPMIDFMT_EP="%{NAME}-%{EPOCH}:%{VERSION}-%{RELEASE} %{BUILDTIME}-%{ARCH}\n" pkgid=`rpm -qp --qf "${RPMIDFMT_EP}" $RPMCHECKOPTS_HOST "'${1}'"` else pkgid=`rpm -qp --qf "${RPMIDFMT}" $RPMCHECKOPTS_HOST "'${1}'"` fi read cachepkgid < "$BUILD_ROOT"/.init_b_cache/rpms/$PKG.id # check if the build time is zero case $cachepkgid in *" 0-"*) xpkgid="${pkgid##* }"; pkgid="${pkgid% *} 0-${xpkgid#*-}" ;; esac test "$cachepkgid" = "$pkgid" || return 1 fi return 0 } check_copy_qemu() { local arch for arch in $EMULATOR_DEVS; do if test -e $BUILD_DIR/qemu-$arch; then return 0 fi done return 1 } copy_qemu() { local path dest echo "copying qemu" mkdir -p "$BUILD_ROOT"/usr/bin if check_copy_qemu; then for path in $BUILD_DIR/qemu-*; do if file $path | grep -q static; then dest="$BUILD_ROOT/usr/bin/${path##*/}" if [ -f "$path" -a ! -x "$dest" ]; then echo -n " $path" # report copy #echo install -m755 "$path" "$dest" install -m755 "$path" "$dest" fi fi done else for path in /usr/bin/qemu-*; do if file $path | grep -q static; then dest="$BUILD_ROOT/usr/bin/${path##*/}" if [ -f "$path" -a ! -x "$dest" ]; then echo -n " $path" # report copy #echo install -m755 "$path" "$dest" install -m755 "$path" "$dest" fi fi done if [ -e /usr/sbin/qemu-binfmt-conf.sh \ -a ! -e "$BUILD_ROOT"/usr/sbin/qemu-binfmt-conf.sh ]; then echo " /usr/sbin/qemu-binfmt-conf.sh" # report copy mkdir -p "$BUILD_ROOT"/usr/sbin install -m755 /usr/sbin/qemu-binfmt-conf.sh "$BUILD_ROOT"/usr/sbin fi fi echo "" # Below for backward compatibility when /.build/initvm is not present if [ -n "$PREPARE_VM" ]; then if [ -x /bin/bash-static -a -x /bin/mount-static ]; then echo " /bin/bash-static /bin/mount-static" # report copy mkdir -p "$BUILD_ROOT"/bin install -m755 /bin/bash-static "$BUILD_ROOT"/bin install -m755 /bin/mount-static "$BUILD_ROOT"/bin fi fi } set_build_arch trap fail_exit EXIT if test "$BUILD_ROOT" = / ; then browner="$(stat -c %u /)" fi if test -n "$CLEAN_BUILD" ; then clean_build_root fi # # now test if there was an incomplete run # 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 echo "Your build system is broken!! Shall I execute" echo echo " rm -rf -- $BUILD_ROOT/*" echo echo "y - yes, cleanup the build root" echo "N - No, abort build (default on enter)" echo "c - Continue anyway with this build root" echo -n "[y/N/c] " read ANSWER case "$ANSWER" in c|C) rm -f $BUILD_IS_RUNNING "$BUILD_ROOT"/exit ;; y|Y) clean_build_root ;; *) cleanup_and_exit 1 ;; esac fi # # store that we start to build system # mkdir -p "$BUILD_ROOT" mkdir -p "$BUILD_ROOT"/.build touch $BUILD_IS_RUNNING if test -n "$PREPARE_VM" ; then rm -f "$BUILD_ROOT"/.build/init_buildsystem.data fi if test -e "$BUILD_ROOT"/.build/init_buildsystem.data ; then # vm continuation . "$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. # rm -rf "$BUILD_ROOT/.init_b_cache" mkdir -p "$BUILD_ROOT/.init_b_cache/scripts" if test -z "$RPMLIST" ; then # # create rpmdeps file # CACHE_FILE="$BUILD_ROOT"/.srcfiles.cache create_cache_file # # select and expand packages # RPMLIST="$BUILD_ROOT"/.init_b_cache/rpmlist test -z "$LIST_STATE" && echo "expanding package dependencies..." VMOPT= test -z "$PREPARE_VM" || VMOPT=--vm if ! $BUILD_DIR/expanddeps $USEUSEDFORBUILD $USEHIGHERDEPS "${definesnstuff[@]}" --dist "$BUILD_DIST" --depfile "$CACHE_FILE" --archpath "$BUILD_ARCH" --configdir $CONFIG_DIR "${PKGS[@]}" > $RPMLIST ; then rm -f $BUILD_IS_RUNNING cleanup_and_exit 1 fi fi if test -n "$LIST_STATE" ; then rm -f $BUILD_IS_RUNNING while read PKG SRC ; do test "$PKG" = "preinstall:" && continue test "$PKG" = "runscripts:" && continue test "$PKG" = "cbpreinstall:" && continue test "$PKG" = "vminstall:" && continue test "$PKG" = "dist:" && continue test "$PKG" = "rpmid:" && continue echo "${SRC##*/}" done < "$BUILD_ROOT"/.init_b_cache/rpmlist rm -rf "$BUILD_ROOT/.init_b_cache" cleanup_and_exit 0 fi # # 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 if test -z "$PREPARE_VM" ; then if check_use_emulator ; then echo "registering binfmt handlers for cross build" "$BUILD_DIR/$INITVM_NAME" echo 0 > /proc/sys/vm/mmap_min_addr read mmap_min_addr < /proc/sys/vm/mmap_min_addr if test "$mmap_min_addr" != 0 ; then echo "Warning: mmap_min_addr is != 0. If programs fail at mmap this could be the reason." fi fi fi # # extract the data from the (generated) rpm list # PACKAGES_TO_INSTALL= PACKAGES_TO_PREINSTALL= PACKAGES_TO_RUNSCRIPTS= PACKAGES_TO_VMINSTALL= PACKAGES_TO_INSTALLONLY= PACKAGES_TO_NOINSTALL= PREINSTALL_IMAGE= PREINSTALL_IMAGE_SOURCE= RUNSCRIPTS_SEEN= PACKAGES_FROM_PREINSTALLIMAGE= GUESSED_DIST=unknown mkdir -p "$BUILD_ROOT"/.init_b_cache/rpms rm -f "$BUILD_ROOT"/.init_b_cache/rpmlist.download while read PKG SRC ; do if test "$PKG" = "preinstall:" ; then PACKAGES_TO_PREINSTALL=$SRC continue fi if test "$PKG" = "vminstall:" ; then PACKAGES_TO_VMINSTALL=$SRC continue fi if test "$PKG" = "installonly:" ; then PACKAGES_TO_INSTALLONLY=$SRC continue fi if test "$PKG" = "noinstall:" ; then PACKAGES_TO_NOINSTALL=$SRC continue fi if test "$PKG" = "preinstallimage:" ; then PREINSTALL_IMAGE=${SRC##*/} ln -s "$SRC" "$BUILD_ROOT/.init_b_cache/rpms/${SRC##*/}" continue fi if test "$PKG" = "preinstallimagesource:" ; then PREINSTALL_IMAGE_SOURCE="$SRC" continue fi if test "$PKG" = "runscripts:" ; then RUNSCRIPTS_SEEN=true PACKAGES_TO_RUNSCRIPTS=$SRC continue fi if test "$PKG" = "dist:" ; then GUESSED_DIST=$SRC continue fi if test "$PKG" = "rpmid:" ; then echo "${SRC#*:}" > "$BUILD_ROOT"/.init_b_cache/rpms/${SRC%%:*}.id continue fi if test "$PKG" != "${PKG%:}"; then echo "Warning: ignoring unsupported tag '$PKG'" >&2 continue fi if test "$SRC" = "preinstallimage" ; then PACKAGES_FROM_PREINSTALLIMAGE="$PACKAGES_FROM_PREINSTALLIMAGE $PKG" PACKAGES_TO_INSTALL="$PACKAGES_TO_INSTALL $PKG" continue fi PACKAGES_TO_INSTALL="$PACKAGES_TO_INSTALL $PKG" if test "${SRC#/}" = "$SRC" ; then case "$SRC" in zypp://* | http://* | https://* | ftp://* | ftps://*) echo "$PKG $SRC" >>"$BUILD_ROOT"/.init_b_cache/rpmlist.download continue ;; *) echo "unsupported url for '$PKG': $SRC" >&2 cleanup_and_exit 1 ;; esac fi SRCSUF=${SRC/%.pkg.tar.?z/.arch} ln -s "$SRC" "$BUILD_ROOT/.init_b_cache/rpms/$PKG.${SRCSUF##*.}" done < $RPMLIST PACKAGES_TO_ALL="$PACKAGES_TO_INSTALL" PACKAGES_TO_AVAILABLE="$PACKAGES_TO_INSTALL" # subtract noinstall packages from PACKAGES_TO_INSTALL if test -n "$PACKAGES_TO_NOINSTALL" ; then settest=" $PACKAGES_TO_NOINSTALL " PACKAGES_TO_INSTALL= for PKG in $PACKAGES_TO_ALL ; do test "$settest" = "${settest/ $PKG /}" && PACKAGES_TO_INSTALL="$PACKAGES_TO_INSTALL $PKG" done fi # subtract installonly packages from PACKAGES_TO_AVAILABLE if test -n "$PACKAGES_TO_INSTALLONLY" ; then settest=" $PACKAGES_TO_INSTALLONLY " PACKAGES_TO_AVAILABLE= for PKG in $PACKAGES_TO_ALL ; do test "$settest" = "${settest/ $PKG /}" && PACKAGES_TO_AVAILABLE="$PACKAGES_TO_AVAILABLE $PKG" done fi # check if we really can use cached versions for packages on the download list if test -s "$BUILD_ROOT"/.init_b_cache/rpmlist.download ; then echo "calculating packages to download..." rm -f "$BUILD_ROOT"/.init_b_cache/rpmlist.download2 while read PKG SRC ; do cachepkg="${SRC##*/}" cachepkg="${cachepkg/%.pkg.tar.?z/.arch}" if test "$SRC" != "${SRC#zypp://}" ; then # for zypp packages also look in the zypp cache cachedir="/var/cache/zypp/packages/${SRC#zypp://}" cachedir="${cachedir%/*}" if can_reuse_cached_package "$cachedir/$cachepkg" ; then SRCSUF=${SRC/%.pkg.tar.?z/.arch} ln -s "$cachedir/$cachepkg" "$BUILD_ROOT/.init_b_cache/rpms/$PKG.${SRCSUF##*.}" continue fi fi cachedir="$(getcachedir "$SRC")" if can_reuse_cached_package "$cachedir/$cachepkg" ; then SRCSUF=${SRC/%.pkg.tar.?z/.arch} ln -s "$cachedir/$cachepkg" "$BUILD_ROOT/.init_b_cache/rpms/$PKG.${SRCSUF##*.}" continue fi # not found in cache or cache has different package rm -f "$cachedir/$cachepkg" echo "$PKG $SRC" >>"$BUILD_ROOT"/.init_b_cache/rpmlist.download2 done < "$BUILD_ROOT"/.init_b_cache/rpmlist.download rm -f "$BUILD_ROOT"/.init_b_cache/rpmlist.download test -s "$BUILD_ROOT"/.init_b_cache/rpmlist.download2 && mv "$BUILD_ROOT"/.init_b_cache/rpmlist.download2 "$BUILD_ROOT"/.init_b_cache/rpmlist.download fi # now do the download of missing packages if test -s "$BUILD_ROOT"/.init_b_cache/rpmlist.download ; then PACKAGES_TO_DOWNLOAD=`cat ${RPMLIST}.download|awk '{print $2}'` progress_setup PACKAGES_TO_DOWNLOAD while read PKG SRC ; do progress_step PACKAGES_TO_DOWNLOAD downloadpkg "$SRC" # downloadpkg modified $SRC, so it has a right name for use SRCSUF=${SRC/%.pkg.tar.?z/.arch} ln -s "$SRC" "$BUILD_ROOT/.init_b_cache/rpms/$PKG.${SRCSUF##*.}" done < "$BUILD_ROOT"/.init_b_cache/rpmlist.download rm -f "$BUILD_ROOT"/.init_b_cache/rpmlist.download echo fi # compatibility... test -z "$RUNSCRIPTS_SEEN" && PACKAGES_TO_RUNSCRIPTS="$PACKAGES_TO_PREINSTALL" echo "$GUESSED_DIST" > "$BUILD_ROOT"/.guessed_dist test -n "$BUILD_DIST" || BUILD_DIST="$GUESSED_DIST" pkg_set_type if test -n "$PREINSTALL_IMAGE" ; then for PKG in $PACKAGES_FROM_PREINSTALLIMAGE ; do # touch the file so that the copying works touch "$BUILD_ROOT"/.init_b_cache/rpms/"$PKG.$PSUF" done fi fi # # test if we need to preinstall # if test ! -e "$BUILD_ROOT"/installed-pkg -a ! -e "$BUILD_ROOT"/.build/init_buildsystem.data ; then mkdir -p "$BUILD_ROOT"/etc || cleanup_and_exit 1 mkdir -p "$BUILD_ROOT"/proc || cleanup_and_exit 1 test -f "$BUILD_ROOT"/etc/HOSTNAME || hostname -f > "$BUILD_ROOT"/etc/HOSTNAME for PKG in $PACKAGES_TO_RUNSCRIPTS ; do : > "$BUILD_ROOT"/.init_b_cache/scripts/$PKG.run done PACKAGES_TO_PREINSTALL_FILTERED="$PACKAGES_TO_PREINSTALL" PACKAGES_TO_VMINSTALL_FILTERED="$PACKAGES_TO_VMINSTALL" rm -f "$BUILD_ROOT/.preinstall_image"/* if test -n "$PREINSTALL_IMAGE" ; then preinstall_image "$PREINSTALL_IMAGE" "$PREINSTALL_IMAGE_SOURCE" PACKAGES_TO_PREINSTALL_FILTERED=`preinstall_image_filter $PACKAGES_TO_PREINSTALL_FILTERED` PACKAGES_TO_VMINSTALL_FILTERED=`preinstall_image_filter $PACKAGES_TO_VMINSTALL_FILTERED` fi PACKAGES_TO_PREINSTALL_FILTERED=`reorder $PACKAGES_TO_PREINSTALL_FILTERED` progress_setup PACKAGES_TO_PREINSTALL_FILTERED for PKG in $PACKAGES_TO_PREINSTALL_FILTERED ; do progress_step PACKAGES_TO_PREINSTALL_FILTERED preinstall ${PKG##*/} done echo if test -n "$PREPARE_VM" ; then PACKAGES_TO_VMINSTALL_FILTERED=`reorder $PACKAGES_TO_VMINSTALL_FILTERED` progress_setup PACKAGES_TO_VMINSTALL_FILTERED for PKG in $PACKAGES_TO_VMINSTALL_FILTERED ; do progress_step PACKAGES_TO_VMINSTALL_FILTERED preinstall ${PKG##*/} done fi # for reorder check_exit if test -w /root ; then test -c "$BUILD_ROOT"/dev/null || create_devs fi 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 run_pkg_scripts pkg_initdb touch "$BUILD_ROOT"/.init_b_cache/preinstall_finished fi # mark as preinstalled no longer needed rm -rf "$BUILD_ROOT/installed-pkg" mkdir -p "$BUILD_ROOT/installed-pkg" fi if test -n "$PREPARE_VM" ; then echo "copying packages..." for PKG in $PACKAGES_TO_ALL ; do rm -f "$BUILD_ROOT"/.init_b_cache/$PKG.$PSUF cp "$BUILD_ROOT"/.init_b_cache/rpms/$PKG.$PSUF "$BUILD_ROOT"/.init_b_cache/$PKG.$PSUF || cleanup_and_exit 1 ln -s -f ../$PKG.$PSUF "$BUILD_ROOT"/.init_b_cache/rpms/$PKG.$PSUF check_exit done # alreadyinstalled check will not work, but we have to live with that... echo -n 'reordering...' PACKAGES_TO_INSTALL=`reorder $PACKAGES_TO_INSTALL` check_exit echo 'done' Q="'\''" echo "PACKAGES_TO_INSTALL='${PACKAGES_TO_INSTALL//"'"/$Q}'" > "$BUILD_ROOT"/.build/init_buildsystem.data echo "PACKAGES_TO_RUNSCRIPTS='${PACKAGES_TO_RUNSCRIPTS//"'"/$Q}'" >> "$BUILD_ROOT"/.build/init_buildsystem.data # needed for continuation in xen/kvm with rpm-x86 echo "PACKAGES_TO_PREINSTALL='${PACKAGES_TO_PREINSTALL//"'"/$Q}'" >> "$BUILD_ROOT"/.build/init_buildsystem.data echo "PACKAGES_TO_AVAILABLE='${PACKAGES_TO_AVAILABLE//"'"/$Q}'" >> "$BUILD_ROOT"/.build/init_buildsystem.data echo "PSUF='$PSUF'" >> "$BUILD_ROOT"/.build/init_buildsystem.data rm -f $BUILD_IS_RUNNING cleanup_and_exit 0 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 # rm -rf "$BUILD_ROOT/.build.binaries" if test -n "$CREATE_BUILD_BINARIES" ; then echo "creating .build.binaries directory..." mkdir -p "$BUILD_ROOT/.build.binaries" for PKG in $PACKAGES_TO_AVAILABLE ; do test -L "$BUILD_ROOT/.init_b_cache/rpms/$PKG.$PSUF" || continue LPKG=`readlink -f "$BUILD_ROOT/.init_b_cache/rpms/$PKG.$PSUF"` ln "$LPKG" "$BUILD_ROOT/.build.binaries/$PKG.$PSUF" 2>/dev/null test -f "$BUILD_ROOT/.build.binaries/$PKG.$PSUF" && continue cp "$LPKG" "$BUILD_ROOT/.build.binaries/$PKG.$PSUF" check_exit done fi # # reorder packages (already done in vm continuation) # if ! test -e "$BUILD_ROOT"/.build/init_buildsystem.data ; then echo -n 'reordering...' PACKAGES_TO_INSTALL=`reorder $PACKAGES_TO_INSTALL` check_exit echo 'done' fi # # get list and ids of already installed packages # mkdir -p "$BUILD_ROOT"/.init_b_cache/alreadyinstalled listinstalled --root "$BUILD_ROOT" --type "$PSUF" --extraname | ( while read id name buildid; do echo "$buildid" > "$BUILD_ROOT/.init_b_cache/alreadyinstalled/$name" done ) # do pre-installation work pkg_prepare # # delete all packages we don't want # if [ -z "$KEEP_PACKS" ]; then mkdir -p "$BUILD_ROOT"/.init_b_cache/todelete for PKG in "$BUILD_ROOT"/.init_b_cache/alreadyinstalled/* ; do PKG=${PKG##*/} test "$PKG" = "*" && continue ln "$BUILD_ROOT"/.init_b_cache/alreadyinstalled/$PKG "$BUILD_ROOT"/.init_b_cache/todelete/$PKG done for PKG in $PACKAGES_TO_INSTALL; do rm -f "$BUILD_ROOT"/.init_b_cache/todelete/$PKG done for PKG in "$BUILD_ROOT"/.init_b_cache/todelete/* ; do PKG=${PKG##*/} test "$PKG" = "*" && continue echo "deleting $PKG" pkg_erase check_exit done rm -rf "$BUILD_ROOT/.init_b_cache/todelete" fi rm -rf "$BUILD_ROOT/.init_b_cache/preinstalls" mkdir -p "$BUILD_ROOT/.init_b_cache/preinstalls" for PKG in $PACKAGES_TO_PREINSTALL; do touch "$BUILD_ROOT/.init_b_cache/preinstalls/$PKG" done rm -rf "$BUILD_ROOT/installed-pkg" mkdir -p "$BUILD_ROOT/installed-pkg" test -x "$BUILD_ROOT"/sbin/ldconfig && chroot "$BUILD_ROOT" /sbin/ldconfig 2>&1 MAIN_LIST="$PACKAGES_TO_INSTALL" progress_setup MAIN_LIST for PKG in $MAIN_LIST ; do test -f "$BUILD_ROOT"/installed-pkg/$PKG && continue progress_step MAIN_LIST if test -e "$BUILD_ROOT/.init_b_cache/rpms/$PKG.$PSUF" -a ! -s "$BUILD_ROOT/.init_b_cache/rpms/$PKG.$PSUF" ; then # preinstallimage package, make sure it's in the image if ! test -e "$BUILD_ROOT"/.preinstall_image/$PKG ; then echo "Package $PKG is missing from the preinstall image" cleanup_and_exit 1 fi read PKG_HDRMD5 PKGID < "$BUILD_ROOT"/.preinstall_image/$PKG echo "preinstalled ${PKGID%% *}" echo "$PKGID" > "$BUILD_ROOT"/installed-pkg/$PKG continue fi # get the hdrmd5 if we want to create a preinstall image PKG_HDRMD5= if test -d "$BUILD_ROOT"/.preinstall_image -a ! -e "$BUILD_ROOT"/.preinstall_image/$PKG ; then PKG_HDRMD5=`perl -I$BUILD_DIR -MBuild -e 'print Build::queryhdrmd5($ARGV[0])' "$BUILD_ROOT"/.init_b_cache/rpms/$PKG.$PSUF` test -n "$PKG_HDRMD5" || cleanup_and_exit 1 fi test -L "$BUILD_ROOT"/.init_b_cache/rpms/$PKG.$PSUF || continue # check if we can keep an already installed package if test "$VERIFY_BUILD_SYSTEM" != true -a -f "$BUILD_ROOT"/.init_b_cache/rpms/$PKG.id -a -f "$BUILD_ROOT"/.init_b_cache/alreadyinstalled/$PKG ; then read PKGID < "$BUILD_ROOT"/.init_b_cache/rpms/$PKG.id read OLDPKGID < "$BUILD_ROOT"/.init_b_cache/alreadyinstalled/$PKG if test "$PKGID" = "$OLDPKGID" ; then echo "keeping ${PKGID%% *}" rm -f "$BUILD_ROOT"/.init_b_cache/$PKG.$PSUF echo "$PKGID" > "$BUILD_ROOT"/installed-pkg/$PKG test -n "$PKG_HDRMD5" && echo "$PKG_HDRMD5 $PKGID" > "$BUILD_ROOT"/.preinstall_image/$PKG continue fi fi # revert use rpm to query pkgid if building rpm package if test "$PSUF" != "rpm" ; then PKGID=$(perl -I$BUILD_DIR -MBuild -e Build::showquery "$BUILD_ROOT/.init_b_cache/rpms/$PKG.$PSUF" buildid) else ep=$(rpm -qp --qf "%{EPOCH}" "'$BUILD_ROOT'/.init_b_cache/rpms/$PKG.$PSUF") if test "$ep" != "(none)"; then RPMIDFMT_EP="%{NAME}-%{EPOCH}:%{VERSION}-%{RELEASE} %{BUILDTIME}-%{ARCH}\n" PKGID=`rpm -qp --qf "${RPMIDFMT_EP}" $RPMCHECKOPTS_HOST "'$BUILD_ROOT'/.init_b_cache/rpms/$PKG.$PSUF"` else PKGID=`rpm -qp --qf "${RPMIDFMT}" $RPMCHECKOPTS_HOST "'$BUILD_ROOT'/.init_b_cache/rpms/$PKG.$PSUF"` fi fi if test -f "$BUILD_ROOT"/.init_b_cache/alreadyinstalled/$PKG ; then read OLDPKGID < "$BUILD_ROOT"/.init_b_cache/alreadyinstalled/$PKG if test "$PKGID" != "$OLDPKGID" ; then echo "deleting unwanted ${OLDPKGID%% *}" pkg_erase else if test "$VERIFY_BUILD_SYSTEM" != true || pkg_verify_installed ; then echo "keeping ${PKGID%% *}" echo "$PKGID" > "$BUILD_ROOT"/installed-pkg/$PKG test -n "$PKG_HDRMD5" && echo "$PKG_HDRMD5 $PKGID" > "$BUILD_ROOT"/.preinstall_image/$PKG continue fi echo "deleting incomplete ${OLDPKGID%% *}" pkg_erase fi if test -e "$BUILD_ROOT/.init_b_cache/preinstalls/$PKG" ; then preinstall "$PKG" fi check_exit fi export ADDITIONAL_PARAMS= if test "$USE_FORCE" = true ; then export ADDITIONAL_PARAMS="$ADDITIONAL_PARAMS --force" fi # work around for cross-build installs, we must not overwrite the running rpm if test "$PKG" = rpm ; then for i in "$BUILD_ROOT"/.init_b_cache/preinstalls/rpm-x86-* ; do test -e "$i" && ADDITIONAL_PARAMS="$ADDITIONAL_PARAMS --justdb" done fi if pkg_cumulate ; then echo "cumulate ${PKGID%% *}" continue fi # install the package echo "installing ${PKGID%% *}" if ! test "$BUILD_ROOT/.init_b_cache/rpms/$PKG.$PSUF" -ef "$BUILD_ROOT/.init_b_cache/$PKG.$PSUF" ; then rm -f "$BUILD_ROOT"/.init_b_cache/$PKG.$PSUF cp "$BUILD_ROOT"/.init_b_cache/rpms/$PKG.$PSUF "$BUILD_ROOT"/.init_b_cache/$PKG.$PSUF || cleanup_and_exit 1 fi pkg_install check_exit rm -f "$BUILD_ROOT"/.init_b_cache/$PKG.$PSUF echo "$PKGID" > "$BUILD_ROOT"/installed-pkg/$PKG test -n "$PKG_HDRMD5" && echo "$PKG_HDRMD5 $PKGID" > "$BUILD_ROOT"/.preinstall_image/$PKG done # do post-installation work pkg_finalize # devices can vanish if devs got uninstalled test -c "$BUILD_ROOT"/dev/null || create_devs 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 # # make sure, that our nis is not present in the chroot system # test -e "$BUILD_ROOT"/etc/nsswitch.conf && { echo "removing nis flags from $BUILD_ROOT/etc/nsswitch.conf..." cat "$BUILD_ROOT"/etc/nsswitch.conf | sed -e"s:nis::g" > "$BUILD_ROOT"/etc/nsswitch.conf.tmp mv "$BUILD_ROOT"/etc/nsswitch.conf.tmp "$BUILD_ROOT"/etc/nsswitch.conf } # # create some default directories and files # for DIR in /usr/share/doc/packages \ /usr/X11R6/include/X11/pixmaps \ /usr/X11R6/include/X11/bitmaps ; do mkdir -p "$BUILD_ROOT"/$DIR done for FILE in /var/run/utmp /var/log/wtmp /etc/fstab ; do mkdir -p "$BUILD_ROOT"/${FILE%/*} touch "$BUILD_ROOT"/$FILE done echo now finalizing build dir... if test -x "$BUILD_ROOT"/sbin/ldconfig ; then CHROOT_RETURN="`chroot "$BUILD_ROOT" /sbin/ldconfig 2>&1`" case "$CHROOT_RETURN" in *warning:*) chroot "$BUILD_ROOT" /sbin/ldconfig echo echo chroot "$BUILD_ROOT" /sbin/ldconfig echo echo "$CHROOT_RETURN" echo echo "Problem with ldconfig. It's better to reinit the build system..." echo cleanup_and_exit 1 ;; esac fi if test -x "$BUILD_ROOT"/usr/sbin/Check && ! grep -q "/usr/sbin/Check is obsolete" "$BUILD_ROOT"/usr/sbin/Check ; then chroot "$BUILD_ROOT" /usr/sbin/Check fi mkdir -p "$BUILD_ROOT"/var/adm/packages touch "$BUILD_ROOT"/var/adm/packages if test -x "$BUILD_ROOT"/sbin/SuSEconfig ; then if grep norestarts "$BUILD_ROOT"/sbin/SuSEconfig > /dev/null ; then chroot "$BUILD_ROOT" /sbin/SuSEconfig --norestarts --force else chroot "$BUILD_ROOT" /sbin/SuSEconfig --force fi fi if test -x "$BUILD_ROOT"/usr/X11R6/bin/switch2mesasoft ; then chroot "$BUILD_ROOT" /usr/X11R6/bin/switch2mesasoft fi for PROG in /usr/bin/TeX/texhash /usr/bin/texhash ; do test -x "$BUILD_ROOT"/$PROG && \ chroot "$BUILD_ROOT" bash -c ". /etc/profile ; $PROG" done if test -e "$BUILD_ROOT"/usr/share/zoneinfo/UTC ; then for PROG in /usr/sbin/zic /usr/bin/zic /bin/zic /sbin/zic ; do test -x "$BUILD_ROOT"/$PROG && chroot "$BUILD_ROOT" bash -c "$PROG -l \$(readlink -f /usr/share/zoneinfo/UTC)" done fi test -e "$BUILD_ROOT"/.build/init_buildsystem.data || HOST=`hostname` test -e "$BUILD_ROOT"/etc/hosts || echo "127.0.0.1 localhost" > "$BUILD_ROOT"/etc/hosts if ! grep -F "127.0.0.1 $HOST" "$BUILD_ROOT"/etc/hosts > /dev/null ; then # this makes a reverse lookup on 127.0.0.1 return the host name, # which is bad, but 127.0.0.2 does not work on all unix systems echo "127.0.0.1 $HOST" > "$BUILD_ROOT"/etc/hosts.new test -f "$BUILD_ROOT"/etc/hosts && cat "$BUILD_ROOT"/etc/hosts >> "$BUILD_ROOT"/etc/hosts.new mv "$BUILD_ROOT"/etc/hosts.new "$BUILD_ROOT"/etc/hosts fi # XXX: still needed? if test -x "$BUILD_ROOT"/bin/rpm -a ! -f "$BUILD_ROOT"/var/lib/rpm/packages.rpm -a ! -f "$BUILD_ROOT"/var/lib/rpm/Packages ; then pkg_initdb_rpm chroot "$BUILD_ROOT" rpm -q --whatprovides rpm >/dev/null 2>&1 # create provides index fi rm -f "$BUILD_ROOT"/.rpmmacros "$BUILD_ROOT"/root/.rpmmacros rm -rf "$BUILD_ROOT/.init_b_cache" rm -f $BUILD_IS_RUNNING rm -f $TMPFILE cleanup_and_exit 0 # vim: set tabstop=8 softtabstop=4 shiftwidth=4 noexpandtab: