Advertisement
Mr_Green

pacstrap

Jul 17th, 2012
289
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 5.37 KB | None | 0 0
  1. #!/bin/bash
  2.  
  3. #
  4. # Assumptions:
  5. #  1) User has partitioned, formatted, and mounted partitions on /mnt
  6. #  2) Network is functional
  7. #  3) Arguments passed to the script are valid pacman targets
  8. #  4) A valid mirror appears in /etc/pacman.d/mirrorlist
  9. #
  10.  
  11. shopt -s extglob
  12.  
  13. out() { printf "$1 $2\n" "${@:3}"; }
  14. error() { out "==> ERROR:" "$@"; } >&2
  15. msg() { out "==>" "$@"; }
  16. msg2() { out "  ->" "$@";}
  17. die() { error "$@"; exit 1; }
  18.  
  19. in_array() {
  20.   local i
  21.   for i in "${@:2}"; do
  22.     [[ $1 = "$i" ]] && return
  23.   done
  24. }
  25.  
  26. api_fs_mount() {
  27.   if ! mountpoint -q "$1"; then
  28.     mount -B "$1" "$1" && ROOT_IS_BIND=1
  29.   fi &&
  30.   mount -t proc proc "$1/proc" -o nosuid,noexec,nodev &&
  31.   mount -t sysfs sys "$1/sys" -o nosuid,noexec,nodev &&
  32.   mount -t devtmpfs udev "$1/dev" -o mode=0755,nosuid &&
  33.   mount -t devpts devpts "$1/dev/pts" -o mode=0620,gid=5,nosuid,noexec &&
  34.   mount -t tmpfs shm "$1/dev/shm" -o mode=1777,nosuid,nodev &&
  35.   mount -t tmpfs run "$1/run" -o nosuid,nodev,mode=0755 &&
  36.   mount -t tmpfs tmp "$1/tmp" -o mode=1777,strictatime,nodev,nosuid,size=50M
  37. }
  38.  
  39. api_fs_umount() {
  40.   umount \
  41.     "$1/tmp" \
  42.     "$1/run" \
  43.     "$1/dev/shm" \
  44.     "$1/dev/pts" \
  45.     "$1/dev" \
  46.     "$1/sys" \
  47.     "$1/proc"
  48.  
  49.   (( ROOT_IS_BIND )) && umount "$1"
  50. }
  51.  
  52. valid_number_of_base() {
  53.   local base=$1 len=${#2} i=
  54.  
  55.   for (( i = 0; i < len; i++ )); do
  56.     (( (${2:i:1} & ~(base - 1)) == 0 )) || return
  57.   done
  58. }
  59.  
  60. mangle() {
  61.   local i= chr= out=
  62.  
  63.   unset {a..f} {A..F}
  64.  
  65.   for (( i = 0; i < ${#1}; i++ )); do
  66.     chr=${1:i:1}
  67.     case $chr in
  68.       [[:space:]\\])
  69.         printf -v chr '%03o' "'$chr"
  70.         out+=\\
  71.         ;;&
  72.         # fallthrough
  73.       *)
  74.         out+=$chr
  75.         ;;
  76.     esac
  77.   done
  78.  
  79.   printf '%s' "$out"
  80. }
  81.  
  82. unmangle() {
  83.   local i= chr= out= len=$(( ${#1} - 4 ))
  84.  
  85.   unset {a..f} {A..F}
  86.  
  87.   for (( i = 0; i < len; i++ )); do
  88.     chr=${1:i:1}
  89.     case $chr in
  90.       \\)
  91.         if valid_number_of_base 8 "${1:i+1:3}" ||
  92.             valid_number_of_base 16 "${1:i+1:3}"; then
  93.           printf -v chr '%b' "${1:i:4}"
  94.           (( i += 3 ))
  95.         fi
  96.         ;;&
  97.         # fallthrough
  98.       *)
  99.         out+=$chr
  100.     esac
  101.   done
  102.  
  103.   printf '%s' "$out${1:i}"
  104. }
  105.  
  106. fstype_is_pseudofs() {
  107.   # list taken from util-linux source: libmount/src/utils.c
  108.   local pseudofs_types=('anon_inodefs'
  109.                         'autofs'
  110.                         'bdev'
  111.                         'binfmt_misc'
  112.                         'cgroup'
  113.                         'configfs'
  114.                         'cpuset'
  115.                         'debugfs'
  116.                         'devfs'
  117.                         'devpts'
  118.                         'devtmpfs'
  119.                         'dlmfs'
  120.                         'fuse.gvfs-fuse-daemon'
  121.                         'fusectl'
  122.                         'hugetlbfs'
  123.                         'mqueue'
  124.                         'nfsd'
  125.                         'none'
  126.                         'pipefs'
  127.                         'proc'
  128.                         'pstore'
  129.                         'ramfs'
  130.                         'rootfs'
  131.                         'rpc_pipefs'
  132.                         'securityfs'
  133.                         'sockfs'
  134.                         'spufs'
  135.                         'sysfs'
  136.                         'tmpfs')
  137.   in_array "$1" "${pseudofs_types[@]}"
  138. }
  139.  
  140.  
  141.  
  142. newroot=/mnt
  143. hostcache=1
  144.  
  145. usage() {
  146.   cat <<EOF
  147. usage: ${0##*/} [options]
  148.  
  149.   Options:
  150.     -r root        Install to 'root' (default: /mnt)
  151.     -d             Allow installation to a non-mountpoint directory
  152.     -c             Use the package cache on the host, rather than the target
  153.  
  154. EOF
  155. }
  156.  
  157. if [[ -z $1 || $1 = @(-h|--help) ]]; then
  158.   usage
  159.   exit $(( $# ? 0 : 1 ))
  160. fi
  161.  
  162. (( EUID == 0 )) || die 'This script must be run with root privileges'
  163.  
  164. while getopts ':cdr:' flag; do
  165.   case $flag in
  166.     d)
  167.       directory=1
  168.       ;;
  169.     r)
  170.       newroot=$OPTARG
  171.       ;;
  172.     c)
  173.       hostcache=0
  174.       ;;
  175.     :)
  176.       die '%s: option requires an argument -- '\''%s'\' "${0##*/}" "$OPTARG"
  177.       ;;
  178.     ?)
  179.       die '%s: invalid option -- '\''%s'\' "${0##*/}" "$OPTARG"
  180.       ;;
  181.   esac
  182. done
  183. shift $(( OPTIND - 1 ))
  184.  
  185. if (( $# )); then
  186.   pacman_args=("$@")
  187. else
  188.   pacman_args=('base' 'base-devel')
  189. fi
  190.  
  191. if (( ! hostcache )); then
  192.   pacman_args+=(--cachedir="$newroot/var/cache/pacman/pkg")
  193. fi
  194.  
  195. [[ -d $newroot ]] || die "%s is not a directory" "$newroot"
  196. if ! mountpoint -q "$newroot" && (( ! directory )); then
  197.   die '%s is not a mountpoint!' "$newroot"
  198. fi
  199.  
  200. # create obligatory directories
  201. msg 'Creating install root at %s' "$newroot"
  202. mkdir -p "$newroot/var/lib/pacman" "$newroot"/{dev,proc,sys,run,tmp,etc}
  203.  
  204. # always call umount on quit after this point
  205. trap 'api_fs_umount "$newroot" 2>/dev/null' EXIT
  206.  
  207. # mount API filesystems
  208. api_fs_mount "$newroot" || die "failed to setup API filesystems in new root"
  209.  
  210. msg 'Installing packages to %s' "$newroot"
  211. if ! pacman -r "$newroot" -Sy --noconfirm "${pacman_args[@]}"; then
  212.   die 'Failed to install packages to new root'
  213. fi
  214.  
  215. # if there's a keyring on the host, copy it into the new root, unless it exists already
  216. if [[ -d /etc/pacman.d/gnupg && ! -d $newroot/etc/pacman.d/gnupg ]]; then
  217.   cp -a /etc/pacman.d/gnupg "$newroot/etc/pacman.d/"
  218. fi
  219.  
  220. # install the host's mirrorlist onto the new root
  221. cp -a /etc/pacman.d/mirrorlist "$newroot/etc/pacman.d/"
  222.  
  223. # vim: et ts=2 sw=2 ft=sh:
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement