From: Mike Frysinger Date: Sun, 7 Apr 2013 21:40:44 +0000 (-0400) Subject: custom-chroot: overhaul to clean up and add read-only chroot support X-Git-Url: https://git.wh0rd.org/?a=commitdiff_plain;h=35fd42a7cb626bb70a33b3b1250e2006bdf518d9;p=home.git custom-chroot: overhaul to clean up and add read-only chroot support --- diff --git a/.bin/custom-chroot b/.bin/custom-chroot index 878a8ff..a32a75f 100755 --- a/.bin/custom-chroot +++ b/.bin/custom-chroot @@ -1,102 +1,137 @@ #!/bin/bash -e -[[ -w / ]] || exec sudo env HOME="$HOME" "$0" "$@" +bootstrap() { + [[ -w / ]] || exec sudo env -uUNSHARE HOME="$HOME" "$0" "$@" -if [[ -z ${UNSHARE} ]] ; then - mount_args= - if type -P unshare >&/dev/null ; then - UNSHARE=true exec unshare -m -- "$0" "$@" + if [[ -z ${UNSHARE} ]] ; then + mount_args= + if type -P unshare >&/dev/null ; then + UNSHARE=true exec unshare -m -- "$0" "$@" + fi + else + mount_args='-n' fi -else - mount_args='-n' -fi -unset UNSHARE - -mounts="proc sys tmp dev dev/pts usr/portage usr/portage/distfiles usr/local/src" - -chroot=${0%/*} -case ${chroot} in - .) chroot=${PWD} ;; - ./*) chroot=${PWD}/${chroot#./} ;; -esac -cd "${chroot}" - -do_umount() { - local m mounts=$(mount | grep ${chroot} | awk '{print $3}' | tac) - for m in ${mounts} ; do - echo "unmounting ${m}" - umount "${m}" - done - if [[ -z ${mounts} ]] ; then - echo "nothing mounted in ${chroot}" - fi - exit 0 + unset UNSHARE } -while [[ -n $1 ]] ; do - case $1 in - -u) do_umount ;; - -m) mounts+=" $2"; shift ;; - -*) echo "unknown option $1"; exit 1 ;; - *) break ;; - esac - shift -done - maybe_mount() { local src=/$1 dst=${chroot}/${2:-$1} [[ -d ${src} ]] || return 0 - mkdir -p "${dst}" + if ! mkdir -p "${dst}" ; then + [[ -w ${chroot} ]] && exit 1 || return 0 + fi grep -sq "${dst}" /proc/mounts || mount ${mount_args} --bind "${src}" "${dst}" } -for m in ${mounts} ; do - maybe_mount ${m} -done get_type() { case $(file "$1") in - *x86-64*) echo x86_64;; - *"Intel 80386"*) echo i386;; - *32-bit*PowerPC*) echo ppc;; - *64-bit*PowerPC*) echo ppc64;; + *x86-64*) echo x86_64;; + *"Intel 80386"*) echo i386;; + *32-bit*PowerPC*) echo ppc;; + *64-bit*PowerPC*) echo ppc64;; + *32-bit*S/390*) echo s390;; + *64-bit*S/390*) echo s390x;; esac } -bin_dst=$(get_type bin/bash) -setarch= -if [[ -n ${bin_dst} ]] && type -P setarch &>/dev/null ; then - setarch="setarch ${bin_dst}" -fi - -if [[ ! -L etc/mtab ]] ; then - rm -f etc/mtab - ln -sf /proc/mounts etc/mtab -fi -etc=" - hosts - locale.gen - localtime - resolv.conf -" -home=" - .inputrc - .gdbinit - .gitconfig - .nanorc -" -for f in \ - $(printf 'etc/%s ' ${etc}) \ -; do - if [ -e "/${f}" ] ; then - cp /${f} ${f} + +init_chroot() { + [[ -w . ]] || return 0 + + if [[ ! -L etc/mtab ]] ; then + rm -f etc/mtab + ln -sf /proc/mounts etc/mtab + fi + local f + local etc=( + hosts + locale.gen + localtime + resolv.conf + ) + local home=( + .inputrc + .gdbinit + .gitconfig + .nanorc + ) + for f in \ + $(printf 'etc/%s ' "${etc[@]}") \ + ; do + if [ -e "/${f}" ] ; then + cp /${f} ${f} + fi + done + for f in "${home[@]}" ; do + cp "${HOME}/${f}" "root/${f}" + done +} + +usage() { + cat <<-EOF + Usage: ${0##*/} [options] [program to run] + + Sets up common mount points and then chroots in and runs a program. + If no program is specified, then launch a login shell. + + Options: + -u Unmount all paths in the chroot + -m Add path to mount list + -d Use as chroot (defaults to ${0%/*}) + -h This help screen + EOF + exit +} + +main() { + bootstrap "$@" + + local mounts=( proc sys tmp dev dev/pts usr/portage usr/portage/distfiles usr/local/src ) + + local chroot=${0%/*} + case ${chroot} in + .) chroot=${PWD} ;; + ./*) chroot=${PWD}/${chroot#./} ;; + esac + + local cmd + while [[ -n $1 ]] ; do + case $1 in + -u) cmd='umount' ;; + -m) mounts+=( "$2" ); shift ;; + -d) chroot=$(realpath "$2"); shift ;; + -h) usage ;; + -*) echo "${0##*/}: unknown option $1"; exit 1 ;; + *) break ;; + esac + shift + done + cd "${chroot}" + + case ${cmd} in + umount) exec "${0%/*}/umount-tree" -y "${chroot}" ;; + esac + + local m + for m in "${mounts[@]}" ; do + maybe_mount ${m} + done + + init_chroot + + local setarch + if type -P setarch &>/dev/null ; then + local bin_dst=$(get_type bin/bash) + if [[ -n ${bin_dst} ]] ; then + setarch="setarch ${bin_dst}" + fi fi -done -for f in ${home} ; do - cp ~/${f} root/${f} -done - -unset LS_COLORS # format changes over time -[[ $# -eq 0 ]] && set -- env HOME=/root /bin/bash -l -exec \ - ${setarch} \ - chroot "${chroot}" \ - "$@" + + unset LS_COLORS # format changes over time + [[ $# -eq 0 ]] && set -- env HOME=/root /bin/bash -l + exec \ + ${setarch} \ + chroot "${chroot}" \ + "$@" +} + +main "$@"