Guest User

arch-chroot

a guest
Mar 10th, 2015
308
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 7.52 KB | None | 0 0
  1. #!/bin/bash
  2.  
  3. shopt -s extglob
  4.  
  5. # generated from util-linux source: libmount/src/utils.c
  6. declare -A pseudofs_types=([anon_inodefs]=1
  7.                            [autofs]=1
  8.                            [bdev]=1
  9.                            [binfmt_misc]=1
  10.                            [cgroup]=1
  11.                            [configfs]=1
  12.                            [cpuset]=1
  13.                            [debugfs]=1
  14.                            [devfs]=1
  15.                            [devpts]=1
  16.                            [devtmpfs]=1
  17.                            [dlmfs]=1
  18.                            [fuse.gvfs-fuse-daemon]=1
  19.                            [fusectl]=1
  20.                            [hugetlbfs]=1
  21.                            [mqueue]=1
  22.                            [nfsd]=1
  23.                            [none]=1
  24.                            [pipefs]=1
  25.                            [proc]=1
  26.                            [pstore]=1
  27.                            [ramfs]=1
  28.                            [rootfs]=1
  29.                            [rpc_pipefs]=1
  30.                            [securityfs]=1
  31.                            [sockfs]=1
  32.                            [spufs]=1
  33.                            [sysfs]=1
  34.                            [tmpfs]=1)
  35.  
  36. # generated from: pkgfile -vbr '/fsck\..+' | awk -F. '{ print $NF }' | sort
  37. declare -A fsck_types=([cramfs]=1
  38.                        [exfat]=1
  39.                        [ext2]=1
  40.                        [ext3]=1
  41.                        [ext4]=1
  42.                        [ext4dev]=1
  43.                        [jfs]=1
  44.                        [minix]=1
  45.                        [msdos]=1
  46.                        [reiserfs]=1
  47.                        [vfat]=1
  48.                        [xfs]=1)
  49.  
  50. out() { printf "$1 $2\n" "${@:3}"; }
  51. error() { out "==> ERROR:" "$@"; } >&2
  52. msg() { out "==>" "$@"; }
  53. msg2() { out "  ->" "$@";}
  54. die() { error "$@"; exit 1; }
  55.  
  56. ignore_error() {
  57.   "$@" 2>/dev/null
  58.   return 0
  59. }
  60.  
  61. in_array() {
  62.   local i
  63.   for i in "${@:2}"; do
  64.     [[ $1 = "$i" ]] && return 0
  65.   done
  66.   return 1
  67. }
  68.  
  69. chroot_add_mount() {
  70.   mount "$@" && CHROOT_ACTIVE_MOUNTS=("$2" "${CHROOT_ACTIVE_MOUNTS[@]}")
  71. }
  72.  
  73. chroot_maybe_add_mount() {
  74.   local cond=$1; shift
  75.   if eval "$cond"; then
  76.     chroot_add_mount "$@"
  77.   fi
  78. }
  79.  
  80. chroot_setup() {
  81.   CHROOT_ACTIVE_MOUNTS=()
  82.   [[ $(trap -p EXIT) ]] && die '(BUG): attempting to overwrite existing EXIT trap'
  83.   trap 'chroot_teardown' EXIT
  84.  
  85.   chroot_maybe_add_mount "! mountpoint -q '$1'" "$1" "$1" --bind &&
  86.   chroot_add_mount proc "$1/proc" -t proc -o nosuid,noexec,nodev &&
  87.   chroot_add_mount sys "$1/sys" -t sysfs -o nosuid,noexec,nodev,ro &&
  88.   ignore_error chroot_maybe_add_mount "[[ -d '$1/sys/firmware/efi/efivars' ]]" \
  89.       efivarfs "$1/sys/firmware/efi/efivars" -t efivarfs -o nosuid,noexec,nodev &&
  90.   chroot_add_mount udev "$1/dev" -t devtmpfs -o mode=0755,nosuid &&
  91.   chroot_add_mount devpts "$1/dev/pts" -t devpts -o mode=0620,gid=5,nosuid,noexec &&
  92.   chroot_add_mount shm "$1/dev/shm" -t tmpfs -o mode=1777,nosuid,nodev &&
  93.   chroot_add_mount run "$1/run" -t tmpfs -o nosuid,nodev,mode=0755 &&
  94.   chroot_add_mount tmp "$1/tmp" -t tmpfs -o mode=1777,strictatime,nodev,nosuid
  95. }
  96.  
  97. chroot_teardown() {
  98.   umount "${CHROOT_ACTIVE_MOUNTS[@]}"
  99.   unset CHROOT_ACTIVE_MOUNTS
  100. }
  101.  
  102. try_cast() (
  103.   _=$(( $1#$2 ))
  104. ) 2>/dev/null
  105.  
  106. valid_number_of_base() {
  107.   local base=$1 len=${#2} i=
  108.  
  109.   for (( i = 0; i < len; i++ )); do
  110.     try_cast "$base" "${2:i:1}" || return 1
  111.   done
  112.  
  113.   return 0
  114. }
  115.  
  116. mangle() {
  117.   local i= chr= out=
  118.  
  119.   unset {a..f} {A..F}
  120.  
  121.   for (( i = 0; i < ${#1}; i++ )); do
  122.     chr=${1:i:1}
  123.     case $chr in
  124.       [[:space:]\\])
  125.         printf -v chr '%03o' "'$chr"
  126.         out+=\\
  127.         ;;
  128.     esac
  129.     out+=$chr
  130.   done
  131.  
  132.   printf '%s' "$out"
  133. }
  134.  
  135. unmangle() {
  136.   local i= chr= out= len=$(( ${#1} - 4 ))
  137.  
  138.   unset {a..f} {A..F}
  139.  
  140.   for (( i = 0; i < len; i++ )); do
  141.     chr=${1:i:1}
  142.     case $chr in
  143.       \\)
  144.         if valid_number_of_base 8 "${1:i+1:3}" ||
  145.             valid_number_of_base 16 "${1:i+1:3}"; then
  146.           printf -v chr '%b' "${1:i:4}"
  147.           (( i += 3 ))
  148.         fi
  149.         ;;
  150.     esac
  151.     out+=$chr
  152.   done
  153.  
  154.   printf '%s' "$out${1:i}"
  155. }
  156.  
  157. optstring_match_option() {
  158.   local candidate pat patterns
  159.  
  160.   IFS=, read -ra patterns <<<"$1"
  161.   for pat in "${patterns[@]}"; do
  162.     if [[ $pat = *=* ]]; then
  163.       # "key=val" will only ever match "key=val"
  164.       candidate=$2
  165.     else
  166.       # "key" will match "key", but also "key=anyval"
  167.       candidate=${2%%=*}
  168.     fi
  169.  
  170.     [[ $pat = "$candidate" ]] && return 0
  171.   done
  172.  
  173.   return 1
  174. }
  175.  
  176. optstring_remove_option() {
  177.   local o options_ remove=$2 IFS=,
  178.  
  179.   read -ra options_ <<<"${!1}"
  180.  
  181.   for o in "${!options_[@]}"; do
  182.     optstring_match_option "$remove" "${options_[o]}" && unset 'options_[o]'
  183.   done
  184.  
  185.   declare -g "$1=${options_[*]}"
  186. }
  187.  
  188. optstring_normalize() {
  189.   local o options_ norm IFS=,
  190.  
  191.   read -ra options_ <<<"${!1}"
  192.  
  193.   # remove empty fields
  194.   for o in "${options_[@]}"; do
  195.     [[ $o ]] && norm+=("$o")
  196.   done
  197.  
  198.   # avoid empty strings, reset to "defaults"
  199.   declare -g "$1=${norm[*]:-defaults}"
  200. }
  201.  
  202. optstring_append_option() {
  203.   if ! optstring_has_option "$1" "$2"; then
  204.     declare -g "$1=${!1},$2"
  205.   fi
  206.  
  207.   optstring_normalize "$1"
  208. }
  209.  
  210. optstring_prepend_option() {
  211.   local options_=$1
  212.  
  213.   if ! optstring_has_option "$1" "$2"; then
  214.     declare -g "$1=$2,${!1}"
  215.   fi
  216.  
  217.   optstring_normalize "$1"
  218. }
  219.  
  220. optstring_get_option() {
  221.   local opts o
  222.  
  223.   IFS=, read -ra opts <<<"${!1}"
  224.   for o in "${opts[@]}"; do
  225.     if optstring_match_option "$2" "$o"; then
  226.       declare -g "$o"
  227.       return 0
  228.     fi
  229.   done
  230.  
  231.   return 1
  232. }
  233.  
  234. optstring_has_option() {
  235.   local "${2%%=*}"
  236.  
  237.   optstring_get_option "$1" "$2"
  238. }
  239.  
  240. dm_name_for_devnode() {
  241.   read dm_name <"/sys/class/block/${1#/dev/}/dm/name"
  242.   if [[ $dm_name ]]; then
  243.     printf '/dev/mapper/%s' "$dm_name"
  244.   else
  245.     # don't leave the caller hanging, just print the original name
  246.     # along with the failure.
  247.     print '%s' "$1"
  248.     error 'Failed to resolve device mapper name for: %s' "$1"
  249.   fi
  250. }
  251.  
  252. fstype_is_pseudofs() {
  253.   (( pseudofs_types["$1"] ))
  254. }
  255.  
  256. fstype_has_fsck() {
  257.   (( fsck_types["$1"] ))
  258. }
  259.  
  260.  
  261. usage() {
  262.   cat <<EOF
  263. usage: ${0##*/} chroot-dir [command]
  264.  
  265.     -h             Print this help message
  266.  
  267. If 'command' is unspecified, ${0##*/} will launch /bin/sh.
  268.  
  269. EOF
  270. }
  271.  
  272. chroot_add_resolv_conf() {
  273.   local chrootdir=$1 resolv_conf=$1/etc/resolv.conf
  274.  
  275.   # Handle resolv.conf as a symlink to somewhere else.
  276.   if [[ -L $chrootdir/etc/resolv.conf ]]; then
  277.     # readlink(1) should always give us *something* since we know at this point
  278.     # it's a symlink. For simplicity, ignore the case of nested symlinks.
  279.     resolv_conf=$(readlink "$chrootdir/etc/resolv.conf")
  280.     if [[ $resolv_conf = /* ]]; then
  281.       resolv_conf=$chrootdir$resolv_conf
  282.     else
  283.       resolv_conf=$chrootdir/etc/$resolv_conf
  284.     fi
  285.  
  286.     # ensure file exists to bind mount over
  287.     if [[ ! -f $resolv_conf ]]; then
  288.       install -Dm644 /dev/null "$resolv_conf" || return 1
  289.     fi
  290.   fi
  291.  
  292.   chroot_add_mount /etc/resolv.conf "$resolv_conf" --bind
  293. }
  294.  
  295. if [[ -z $1 || $1 = @(-h|--help) ]]; then
  296.   usage
  297.   exit $(( $# ? 0 : 1 ))
  298. fi
  299.  
  300. (( EUID == 0 )) || die 'This script must be run with root privileges'
  301. chrootdir=$1
  302. shift
  303.  
  304. [[ -d $chrootdir ]] || die "Can't create chroot on non-directory %s" "$chrootdir"
  305.  
  306. chroot_setup "$chrootdir" || die "failed to setup chroot %s" "$chrootdir"
  307. chroot_add_resolv_conf "$chrootdir" || die "failed to setup resolv.conf"
  308.  
  309. SHELL=/bin/sh unshare --fork --pid chroot "$chrootdir" "$@"
Advertisement
Add Comment
Please, Sign In to add comment