# This file is part of the src2pkg program: # Copyright 2005-2010 Gilbert Ashley # src2pkg is released under the GNU General Public License Version 2 # This method installs all files into a 'false root' directory, the PKG_DIR, # but uses unionfs and chroot rather than sentry. This usually works when # using DESTDIR and JAIL is not supported by the Makefiles and is less # intrusive than installing to the real root directory, backing up overwritten # files and then restoring them ## free_union free_union() { umount -l "$UNION_DIR/OBJ_DIR" &> /dev/null umount -l "$UNION_DIR"/tmp &> /dev/null umount -l "$UNION_DIR"/var/tmp &> /dev/null umount -l "$UNION_DIR"/sys &> /dev/null umount -l "$UNION_DIR"/proc &> /dev/null umount -l "$UNION_DIR"/dev &> /dev/null umount -l "$UNION_DIR" &> /dev/null fusermount -u "$UNION_DIR" &> /dev/null } ## User cancelled at a 'sensitive' spot, so scold them! trap_union_int() { echo echo $RED" *** OUCH!!! *** "$NORMAL"Dangerous cancellation" echo " Please don't cancel while fake_install is running." echo " Cleaning up hanging mounts on unionfs." free_union rmdir "$UNION_DIR" || echo $YELLOW"Warning - "$NORMAL"Unable to remove UNION_DIR!" ( cd "$PKG_BUILDS_DIR" (cd $EXCL_DIR_NAME/var && rmdir tmp) (cd $EXCL_DIR_NAME && rmdir *) rmdir $EXCL_DIR_NAME ) FAILED="CANCELLED" case $AUDIO_NOTIFICATION in BEEP) echo -ne '\a';sleep .5;echo -ne '\a' ;; SAY) case $TTS_ENGINE in flite) flite "Dangerous cancellation" 2> /dev/null ;; festival) echo "Dangerous cancellation" |festival --tts 2> /dev/null ;; esac ;; PLAY) play /usr/share/src2pkg/sounds/ouch &> /dev/null ;; esac exit } install_to_union_root() { echo $BLUE"Installing in UNION chroot - "$NORMAL"Using: '$INSTALL_COMMAND $INSTALL_RULE'"$NORMAL UNION_DIR_NAME=$NAME-$VERSION-union-$BUILD$SIG UNION_DIR="$PKG_BUILDS_DIR"/$UNION_DIR_NAME EXCL_DIR_NAME=$NAME-$VERSION-excl-$BUILD$SIG EXCL_DIR="$PKG_BUILDS_DIR"/$EXCL_DIR_NAME mkdir -p "$PKG_DIR" # don't do full recursive delete - losing important files if one of the # excludes doesn't properly umount is a Very Bad Thing. rmdir "$UNION_DIR" 2> /dev/null rm -rf "$EXCL_DIR" mkdir -p "$UNION_DIR" mkdir -p "$EXCL_DIR" # create mount-points for dirs we will be binding mkdir -p "$EXCL_DIR"/dev mkdir -p "$EXCL_DIR"/proc mkdir -p "$EXCL_DIR"/sys mkdir -p "$EXCL_DIR"/var/tmp mkdir -p "$EXCL_DIR"/tmp case "$UNIONFS_TYPE" in "unionfs") mount -t unionfs -o dirs="$PKG_DIR"=rw:/=ro:"$EXCL_DIR"=ro unionfs "$UNION_DIR" ;; "unionfs-fuse") unionfs -o cow "$PKG_DIR"=RW:/=RO:"$EXCL_DIR"=RO "$UNION_DIR" ;; esac # set the trap_union_int to be sure we don't leave mounts hanging if interrupted trap trap_union_int 2 # bind the system dirs in the union root mount --bind /dev "$UNION_DIR"/dev mount --bind /proc "$UNION_DIR"/proc mount --bind /sys "$UNION_DIR"/sys mount --bind /var/tmp "$UNION_DIR"/var/tmp mount --bind /tmp "$UNION_DIR"/tmp # create an explicit and uniquely-named OBJ_DIR under the UNION_DIR. We need to do this because if the # original OBJ_DIR is on a separate filesystem it won't be there under the UNION_DIR unless it is explicitly # bind-mounted. We create a unique directory so we can safely and easily remove it afterwards. # We do this in the UNION_DIR because it is RW -sometimes install create new files so we need OBJ_DIR writable #mkdir -p "$EXCL_DIR"/OBJ_DIR mkdir -p "$UNION_DIR"/OBJ_DIR # bind the $OBJ_DIR in the union root mount --bind "$OBJ_DIR" "$UNION_DIR"/OBJ_DIR # we could use fakeroot for this step, but we'll need to also use it later when checking and correcting ownerships and perms if [[ $LOG_COMMANDS = "YES" ]] ; then # if ! [[ $LOG_DIR ]] ; then LOG_DIR="$OBJ_DIR" elif [[ "$LOG_DIR" != "$CWD" ]] && [[ "${LOG_DIR:0:1}" != "/" ]] ; then echo $YELLOW"Warning! "$NORMAL"LOG_DIR is set to an invalid path." echo " It must be set to \$CWD or an absolute path." fi echo $BLUE"Logging output to: "$NORMAL"LOG_DIR/$NAME-make-install.log" ( chroot "$UNION_DIR" /bin/sh -c "cd OBJ_DIR && ${INSTALL_COMMAND} ${INSTALL_RULE} &> $NAME-make-install.log ; exit" ) if ! [[ -f "$LOG_DIR"/$NAME-make-install.log ]] ; then cp "$OBJ_DIR"/$NAME-make-install.log "$LOG_DIR"/ fi elif [[ $QUIET = "YES" ]] ; then ( chroot "$UNION_DIR" /bin/sh -c "cd OBJ_DIR && ${INSTALL_COMMAND} ${INSTALL_RULE} &> /dev/null ; exit" ) else ( chroot "$UNION_DIR" /bin/sh -c "cd OBJ_DIR && ${INSTALL_COMMAND} ${INSTALL_RULE} ; exit" ) fi RETVAL=$? # unmount the OBJ_DIR umount -l "$UNION_DIR/OBJ_DIR" # after unmounting the $UNION_DIR/OBJ_DIR, remove # the dir so it doesn't get included in the package # ( cd "$UNION_DIR" && rm -rf OBJ_DIR ) rmdir "$UNION_DIR"/OBJ_DIR || echo $YELLOW"Warning - "$NORMAL"Unable to remove OBJ_DIR!" # unmount the system dirs from the union root umount -l "$UNION_DIR"/tmp umount -l "$UNION_DIR"/var/tmp umount -l "$UNION_DIR"/sys umount -l "$UNION_DIR"/proc umount -l "$UNION_DIR"/dev if fusermount -u "$UNION_DIR" ; then true else echo $YELLOW"Warning - "$NORMAL"Forcing umount of UNION_DIR!" umount -l "$UNION_DIR" fi rmdir "$UNION_DIR" || echo $YELLOW"Warning - "$NORMAL"Unable to remove UNION_DIR!" ( cd "$PKG_BUILDS_DIR" && rm -rf $EXCL_DIR_NAME ) # Delete all metadata - really shouldn't be thrown away like this case "$UNIONFS_TYPE" in "unionfs") find "$PKG_DIR" -name ".wh.*" -exec rm "{}" ";" ;; "unionfs-fuse") rm -rf "$PKG_DIR/.unionfs/" ;; esac # some tentative error handling if [ $RETVAL -gt 0 ] ; then # FIXME: what post-processing needs to happen? echo "Failed" FAILED="CHROOT install in $FUNCNAME" fi }