#! /bin/bash # common modules for pbuilder. # pbuilder -- personal Debian package builder # Copyright (C) 2001-2007 Junichi Uekawa # # 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; either version 2 of the License, or # (at your option) any later version. # # 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; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA function showhelp () { cat <&2 return 1 fi if ! [ -d "$BUILDPLACE/$mountpoint" ]; then echo "W: $mountpoint isn't a directory" >&2 return 1 fi if [ -r "$BUILDPLACE/proc/mounts" ] && grep -q "^[^ ]* $mountpoint " "$BUILDPLACE/proc/mounts"; then echo "W: $mountpoint is mounted according to build place's /proc/mounts" >&2 return 1 fi if [ -r "/proc/mounts" ] && grep -q "^[^ ]* $BUILDPLACE/$mountpoint " "/proc/mounts"; then echo "W: $mountpoint is mounted according to system's /proc/mounts" >&2 return 1 fi if ! is_empty_dir "$BUILDPLACE/$mountpoint"; then echo "W: $mountpoint not empty" >&2 return 1 fi return 0 } function umount_one () { if [ "${IGNORE_UMOUNT}" = "yes" ]; then # support ignore umount option. echo " -> ignoring umount of $1 filesystem" return fi echo " -> unmounting $1 filesystem" local UMOUNT_OUTPUT if ! UMOUNT_OUTPUT="$(LC_ALL=C umount "$BUILDPLACE/$1" 2>&1)"; then echo "W: Could not unmount $1: $UMOUNT_OUTPUT" >&2 local ignore_umount_error="no" case $UMOUNT_OUTPUT in "umount: "*": not found"|"umount:"*": not mounted") # run an additional set of sanity checks if seems_truly_unmounted "$1"; then ignore_umount_error="yes" else echo "W: Tried ignoring error in unmount, but sanity check failed: $1 might still be mounted" >&2 fi ;; *) : ;; esac if [ "$ignore_umount_error" != "yes" ]; then echo "W: Retrying to unmount $1 in 5s" >&2 sleep 5s while ! umount "$BUILDPLACE/$1"; do sleep 5s cat <&2 fi fi } function umountproc () { # push arguments on a stack to reverse direction. local reversed reversed= for mnt in $BINDMOUNTS; do reversed="$mnt $reversed" done for mnt in $reversed; do umount_one "$mnt" done if [ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then umount_one "selinux" fi if [ "$USEDEVPTS" = "yes" ]; then umount_one "dev/pts" fi if [ "$USEDEVFS" = "yes" ]; then umount_one "dev" fi if [ "$USEPROC" = "yes" ]; then if [ -e $BUILDPLACE/proc/sys/fs/binfmt_misc/status ]; then umount_one "proc/sys/fs/binfmt_misc" fi umount_one "proc" fi } # Mount /proc /dev/pts /dev and bind-mount points # Also create a policy-rc.d script if it doesn't already exist. function mountproc () { if [ "$USEPROC" = "yes" ]; then echo " -> mounting /proc filesystem" mkdir -p $BUILDPLACE/proc mount -t proc /proc "$BUILDPLACE/proc" ln -s ../proc/mounts $BUILDPLACE/etc/mtab 2> /dev/null || true fi if [ "$USEDEVFS" = "yes" ]; then echo " -> mounting /dev filesystem" mkdir -p $BUILDPLACE/dev || true mount -t devfs /dev "$BUILDPLACE/dev" fi if [ "$USEDEVPTS" = "yes" ]; then echo " -> mounting /dev/pts filesystem" mkdir -p $BUILDPLACE/dev/pts || true mount -t devpts /dev/pts "$BUILDPLACE/dev/pts" fi if [ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then echo " -> mounting selinux filesystem" mkdir -p $BUILDPLACE/selinux mount -t selinuxfs /selinux "$BUILDPLACE/selinux" fi for mnt in $BINDMOUNTS; do echo "-> Mounting $mnt" mkdir -p "$BUILDPLACE/$mnt" mount -obind "$mnt" "$BUILDPLACE/$mnt" done if [ -f "$BUILDPLACE/usr/sbin/policy-rc.d" ]; then echo " -> policy-rc.d already exists" else echo " -> installing dummy policy-rc.d" echo "\ #!/bin/sh while true; do case "\$1" in -*) shift ;; makedev) exit 0;; x11-common) exit 0;; *) exit 101;; esac done " > "$BUILDPLACE/usr/sbin/policy-rc.d" chmod a+x "$BUILDPLACE/usr/sbin/policy-rc.d" fi } ## function to clean subdirs, use instead of rm -r function clean_subdirectories () { if [ -z "$1" ]; then echo "Fatal internal error in clean_subdirectories" exit 1; fi if [ ! -d "$1" ]; then echo "Warning: directory $1 does not exist in clean_subdirectories" return; fi echo " -> removing directory $1 and its subdirectories" find "$1" -xdev \( \! -type d \) -print0 |xargs -0 rm -f find "$1" -xdev -depth -type d -print0 | \ (xargs -0 rmdir || true) } function cleanbuildplace () { if [ "$?" -ne 0 ]; then echo " -> Aborting with an error"; fi if [ "${INTERNAL_BUILD_UML}" != "yes" ]; then if [ -d "$BUILDPLACE" ]; then echo " -> cleaning the build env " clean_subdirectories "$BUILDPLACE" fi; fi } function umountproc_cleanbuildplace () { # rolling back to abort. if [ "$?" -ne 0 ]; then echo " -> Aborting with an error"; fi umountproc cleanbuildplace } function saveaptcache_umountproc_cleanbuildplace () { # save the apt cache, and call umountproc_cleanbuildplace save_aptcache umountproc_cleanbuildplace } function installaptlines (){ echo " -> Installing apt-lines" rm -f "$BUILDPLACE"/etc/apt/sources.list if [ -z "$DISTRIBUTION" ]; then echo "Distribution not specified, please specify" >&2 exit 1 fi if [ -z "$COMPONENTS" ] ; then COMPONENTS="main" fi if [ -n "$OTHERMIRROR" ]; then echo "$OTHERMIRROR" | tr "|" "\n" >> "$BUILDPLACE"/etc/apt/sources.list fi if [ -n "$MIRRORSITE" ] ; then cat >> "$BUILDPLACE"/etc/apt/sources.list << EOF deb $MIRRORSITE $DISTRIBUTION $COMPONENTS #deb-src $MIRRORSITE $DISTRIBUTION $COMPONENTS EOF fi if [ -n "$APTCONFDIR" ]; then echo " -> Copy " "$APTCONFDIR"/* " to chroot" cp -a "$APTCONFDIR/"* "$BUILDPLACE"/etc/apt fi if [ -n "$EXPERIMENTAL" ]; then echo " -> Installing apt-lines and pinning for experimental" if [ -n "$MIRRORSITE" ] ; then echo "deb $MIRRORSITE experimental main" >> "$BUILDPLACE"/etc/apt/sources.list echo "#deb-src $MIRRORSITE experimental main" >> "$BUILDPLACE"/etc/apt/sources.list fi cat >> "$BUILDPLACE"/etc/apt/apt.conf << EOF APT::Default-Release "experimental"; EOF fi } function copy_local_configuration () { echo " -> copying local configuration" for a in hosts hostname resolv.conf; do if [ -f "/etc/$a" ]; then rm -f "$BUILDPLACE/etc/$a" cp $( readlink -f "/etc/$a" ) "$BUILDPLACE/etc/$a"; else echo "W: No local /etc/$a to copy, relying on $BUILDPLACE/etc/$a to be correct" >&2 fi done } function extractbuildplace () { # after calling this function, umountproc, and cleanbuildplace # needs to be called. Please trap it after calling this function. if [ "${INTERNAL_BUILD_UML}" != "yes" -a ! \( "${PRESERVE_BUILDPLACE}" = "yes" -a -d "$BUILDPLACE" \) ]; then cleanbuildplace echo "Building the build Environment" if ! mkdir -p "$BUILDPLACE"; then echo "E: failed to build the directory to chroot" >&2 exit 1 fi echo " -> extracting base tarball [${BASETGZ}]" if [ ! -f "$BASETGZ" ]; then echo "E: failed to find $BASETGZ, have you done to create your base tarball yet?" >&2 exit 1 fi if ! (cd "$BUILDPLACE" && tar xfzp "$BASETGZ"); then echo "E: failed to extract $BASETGZ to $BUILDPLACE" >&2 exit 1 fi echo " -> creating local configuration" hostname -f > "$BUILDPLACE/etc/mailname" fi copy_local_configuration # installaptlines may fail with exit 1, do it earlier than mountproc. if [ "$OVERRIDE_APTLINES" = "yes" ]; then installaptlines fi mountproc mkdir -p "$BUILDPLACE/tmp/buildd" } function recover_aptcache() { local doit # recover the aptcache archive if [ -n "$APTCACHE" ]; then if [ "$APTCACHEHARDLINK" = "yes" ]; then doit=ln else doit=cp fi echo "Obtaining the cached apt archive contents" find "$APTCACHE" -maxdepth 1 -name \*.deb | \ while read A ; do $doit "$A" "$BUILDPLACE/var/cache/apt/archives/" || true done fi } function save_aptcache() { # save the current aptcache archive # it is safe to call this function several times. local doit if [ -n "$APTCACHE" ]; then echo "Copying back the cached apt archive contents" mkdir -p "$APTCACHE" ; if [ "$APTCACHEHARDLINK" = "yes" ]; then doit=ln else doit=cp fi find "$BUILDPLACE/var/cache/apt/archives/" -maxdepth 1 -name \*.deb | \ while read A ;do if [ ! -f "$APTCACHE/"$(basename "$A") -a -f "$A" ]; then echo " -> new cache content "$(basename "$A")" added" $doit "$A" "$APTCACHE/" || true fi done fi } function create_basetgz() { # create base.tgz ( if ! cd "$BUILDPLACE"; then echo "Error: unexpected error in chdir to $BUILDPLACE" >&2 exit 1; fi while test -f "${BASETGZ}.tmp"; do echo " -> Someone else has lock over ${BASETGZ}.tmp, waiting" sleep 10s done echo " -> creating base tarball [${BASETGZ}]" if ! tar cfz "${BASETGZ}.tmp" * ; then echo " -> failed building base tarball" rm -f "${BASETGZ}.tmp" exit 1; fi mv "${BASETGZ}.tmp" "${BASETGZ}" ) } # all trap hooks that should lead to 'exit'; and error exit. function cleanbuildplace_trap () { cleanbuildplace trap - exit sighup exit 1 } function saveaptcache_umountproc_cleanbuildplace_trap () { saveaptcache_umountproc_cleanbuildplace trap - exit sighup exit 1 } function umountproc_cleanbuildplace_trap () { umountproc_cleanbuildplace trap - exit sighup exit 1 } function umountproc_trap () { umountproc trap - exit sighup exit 1 } #Setting environmental variables that are really required: #required for some packages to install... export LANG=C export LC_ALL=C