]> git.wh0rd.org - home.git/blob - .bin/custom-chroot
custom-chroot: overhaul to clean up and add read-only chroot support
[home.git] / .bin / custom-chroot
1 #!/bin/bash -e
2
3 bootstrap() {
4 [[ -w / ]] || exec sudo env -uUNSHARE HOME="$HOME" "$0" "$@"
5
6 if [[ -z ${UNSHARE} ]] ; then
7 mount_args=
8 if type -P unshare >&/dev/null ; then
9 UNSHARE=true exec unshare -m -- "$0" "$@"
10 fi
11 else
12 mount_args='-n'
13 fi
14 unset UNSHARE
15 }
16
17 maybe_mount() {
18 local src=/$1 dst=${chroot}/${2:-$1}
19 [[ -d ${src} ]] || return 0
20 if ! mkdir -p "${dst}" ; then
21 [[ -w ${chroot} ]] && exit 1 || return 0
22 fi
23 grep -sq "${dst}" /proc/mounts || mount ${mount_args} --bind "${src}" "${dst}"
24 }
25
26 get_type() {
27 case $(file "$1") in
28 *x86-64*) echo x86_64;;
29 *"Intel 80386"*) echo i386;;
30 *32-bit*PowerPC*) echo ppc;;
31 *64-bit*PowerPC*) echo ppc64;;
32 *32-bit*S/390*) echo s390;;
33 *64-bit*S/390*) echo s390x;;
34 esac
35 }
36
37 init_chroot() {
38 [[ -w . ]] || return 0
39
40 if [[ ! -L etc/mtab ]] ; then
41 rm -f etc/mtab
42 ln -sf /proc/mounts etc/mtab
43 fi
44 local f
45 local etc=(
46 hosts
47 locale.gen
48 localtime
49 resolv.conf
50 )
51 local home=(
52 .inputrc
53 .gdbinit
54 .gitconfig
55 .nanorc
56 )
57 for f in \
58 $(printf 'etc/%s ' "${etc[@]}") \
59 ; do
60 if [ -e "/${f}" ] ; then
61 cp /${f} ${f}
62 fi
63 done
64 for f in "${home[@]}" ; do
65 cp "${HOME}/${f}" "root/${f}"
66 done
67 }
68
69 usage() {
70 cat <<-EOF
71 Usage: ${0##*/} [options] [program to run]
72
73 Sets up common mount points and then chroots in and runs a program.
74 If no program is specified, then launch a login shell.
75
76 Options:
77 -u Unmount all paths in the chroot
78 -m <path> Add path to mount list
79 -d <dir> Use <dir> as chroot (defaults to ${0%/*})
80 -h This help screen
81 EOF
82 exit
83 }
84
85 main() {
86 bootstrap "$@"
87
88 local mounts=( proc sys tmp dev dev/pts usr/portage usr/portage/distfiles usr/local/src )
89
90 local chroot=${0%/*}
91 case ${chroot} in
92 .) chroot=${PWD} ;;
93 ./*) chroot=${PWD}/${chroot#./} ;;
94 esac
95
96 local cmd
97 while [[ -n $1 ]] ; do
98 case $1 in
99 -u) cmd='umount' ;;
100 -m) mounts+=( "$2" ); shift ;;
101 -d) chroot=$(realpath "$2"); shift ;;
102 -h) usage ;;
103 -*) echo "${0##*/}: unknown option $1"; exit 1 ;;
104 *) break ;;
105 esac
106 shift
107 done
108 cd "${chroot}"
109
110 case ${cmd} in
111 umount) exec "${0%/*}/umount-tree" -y "${chroot}" ;;
112 esac
113
114 local m
115 for m in "${mounts[@]}" ; do
116 maybe_mount ${m}
117 done
118
119 init_chroot
120
121 local setarch
122 if type -P setarch &>/dev/null ; then
123 local bin_dst=$(get_type bin/bash)
124 if [[ -n ${bin_dst} ]] ; then
125 setarch="setarch ${bin_dst}"
126 fi
127 fi
128
129 unset LS_COLORS # format changes over time
130 [[ $# -eq 0 ]] && set -- env HOME=/root /bin/bash -l
131 exec \
132 ${setarch} \
133 chroot "${chroot}" \
134 "$@"
135 }
136
137 main "$@"