#!/bin/bash # vim: set sw=4 sts=4 et : # Directory from which we will rsync portage to chroot PORTAGE_DIR=/usr/portage # stage tarball path STAGE_TARBALL="" # ================================================================== # CODE # =================================================================== help() { echo "Usage: `basename $0` OPTIONS BASE_CHROOT_DIR WORK_CHROOT_DIR" echo echo " -c force clean BASE_CHROOT if it exists and start over from scratch" echo " -p PORTAGE_DIR directory where portage is (default is /usr/portage)" echo " -s STAGE_FILE stage file used to create base chroot directory" echo " -m prepare mounts and chroot to BASE_CHROOT for its modification (update)" exit 1 } clean_work_chroot() { echo -n "Cleaning work chroot..." if [ -d $WORK_CHROOT ];then umount_all_dirs $WORK_CHROOT rm -rf --one-file-system "$WORK_CHROOT" fi echo Done } clean_base_chroot() { echo -n "Cleaning base chroot..." if [ -d "$BASE_CHROOT" ];then rm -rf --one-file-system "$BASE_CHROOT" fi if [ -f "$BASE_CHROOT.tar" ];then rm -f "$BASE_CHROOT.tar" fi echo Done } mount_all_dirs() { ROOTDIR=$1 echo -n "Mounting filesystems..." mount -t proc none "$ROOTDIR/proc" mount -o bind /dev "$ROOTDIR/dev" mount -o bind /sys "$ROOTDIR/sys" mkdir -p "$ROOTDIR/$PORTAGE_DIR" mount -o bind "$PORTAGE_DIR" "$ROOTDIR/$PORTAGE_DIR" # this is bug/issue with current kernels, ro binds don't work so we have to remount mount -o remount,ro "$ROOTDIR/usr/portage" mount_dir "DISTDIR" $ROOTDIR mount_dir "PKGDIR" $ROOTDIR echo Done } umount_all_dirs() { ROOTDIR=$1 for dir in {"PKGDIR","DISTDIR"};do umount_dir $dir $ROOTDIR done for dir in $ROOTDIR/{"/dev","/proc","/sys","$PORTAGE_DIR"};do umount "$dir" || umount -l "$dir" done } GPSRET="" get_portage_setting() { setting=`grep $1 "$BASE_CHROOT/etc/make.conf" | sed -e "s/.*$1[[:space:]]*=[[:space:]]*//;s/\"//g;"` if [ "y$setting" == "y" ];then case $1 in "PORTDIR" ) GPSRET=`portageq portdir` return 0;; "DISTDIR" ) GPSRET=`portageq distdir` return 0;; "PKGDIR" ) GPSRET=`portageq pkgdir` return 0;; * ) return 1;; esac fi GPSRET=$setting return 0; } mount_dir() { ROOTDIR=$2 get_portage_setting $1 if [ $? -eq 0 ];then if [ ! -e "$GPSRET" ];then mkdir -p "$GPSRET" fi mkdir -p "$ROOTDIR/$GPSRET" mount -o bind "$GPSRET" "$ROOTDIR/$GPSRET" else echo "Unable to get setting for $1 variable" exit 1 fi } umount_dir() { ROOTDIR=$2 get_portage_setting $1 umount "$ROOTDIR/$GPSRET" || umount -l "$ROOTDIR/$GPSRET" } FORCE_CLEAN_BASE=0 while getopts "p:s:cm" Option do case $Option in p ) PORTAGE_DIR="$OPTARG";; s ) STAGE_TARBALL="$OPTARG";; c ) FORCE_CLEAN_BASE=1;; m ) MODIFY_BASE_CHROOT=1;; * ) echo "Unimplemented option chosen.";; # DEFAULT esac done shift $(($OPTIND - 1)) if [ $# -ne 2 ];then echo "Wrong number of arguments" help fi BASE_CHROOT="$1" WORK_CHROOT="$2" echo "Using settings:" echo "base chroot directory: $BASE_CHROOT" echo "work chroot directory: $WORK_CHROOT" echo "portage directory: $PORTAGE_DIR" echo "stage tarball: $STAGE_TARBALL" if [ $FORCE_CLEAN_BASE -eq 1 ];then clean_base_chroot fi if [ -d "$BASE_CHROOT" ];then echo "We found $BASE_CHROOT directory, assuming it's ready" else if [ -z "$STAGE_TARBALL" ];then echo "We need stage tarball to create base chroot!! (option -s)" help fi # we will need to create usr/ anyway so why not do it at once mkdir -p "$BASE_CHROOT/usr" echo -n "Unpacking stage tarball..." tar xf "$STAGE_TARBALL" -C "$BASE_CHROOT" if [ $? -ne 0 ];then echo "Errors unpacking stage tarball, bailing out!!!" rm -rf "$BASE_CHROOT" exit 1 fi echo Done rm -rf --one-file-system "$BASE_CHROOT/etc/portage/" mkdir -p "$BASE_CHROOT/etc/portage" echo -n "Copying settings..." cp -L /etc/resolv.conf "$BASE_CHROOT/etc" cp -L /etc/make.conf "$BASE_CHROOT/etc" cp -RL /etc/portage "$BASE_CHROOT/etc" echo Done fi if [ $MODIFY_BASE_CHROOT -eq 1 ];then mount_all_dirs $BASE_CHROOT chroot $BASE_CHROOT /bin/bash umount_all_dirs $BASE_CHROOT rm "$BASE_CHROOT.tar" exit 0; fi if [ ! -f "$BASE_CHROOT.tar" ];then echo -n "Creating tar from $BASE_CHROOT..." tar cf "$BASE_CHROOT.tar" -C "$BASE_CHROOT" . if [ $? -ne 0 ];then echo "Creating tar from $BASE_CHROOT failed, bailing out!!!" rm -rf "$BASE_CHROOT" exit 1 fi echo Done fi clean_work_chroot echo -n "Untaring base chroot to work chroot now" mkdir -p "$WORK_CHROOT" tar pxf "$BASE_CHROOT.tar" -C "$WORK_CHROOT" if [ $? -ne 0 ];then echo "There were problems unpacking base chroot to work chroot!!" exit 1 fi echo Done mount_all_dirs $WORK_CHROOT echo -n "Chrooting and updating env..." # so that we can run env-update chroot "$WORK_CHROOT" /usr/sbin/env-update echo Done exit 0