diff --git a/manual-build/archos-bootstrap b/manual-build/archos-bootstrap new file mode 100644 index 0000000..01f8f97 --- /dev/null +++ b/manual-build/archos-bootstrap @@ -0,0 +1,166 @@ +#!/bin/bash + +chroot_add_mount() { + mount "$@" && CHROOT_ACTIVE_MOUNTS=("$2" "${CHROOT_ACTIVE_MOUNTS[@]}") +} + +chroot_setup() { + CHROOT_ACTIVE_MOUNTS=() + [[ $(trap -p EXIT) ]] && die '(BUG): attempting to overwrite existing EXIT trap' + trap 'chroot_teardown' EXIT + + chroot_add_mount proc "$1/proc" -t proc -o nosuid,noexec,nodev && + chroot_add_mount sys "$1/sys" -t sysfs -o nosuid,noexec,nodev,ro && + ignore_error chroot_maybe_add_mount "[[ -d '$1/sys/firmware/efi/efivars' ]]" \ + efivarfs "$1/sys/firmware/efi/efivars" -t efivarfs -o nosuid,noexec,nodev && + chroot_add_mount udev "$1/dev" -t devtmpfs -o mode=0755,nosuid && + chroot_add_mount devpts "$1/dev/pts" -t devpts -o mode=0620,gid=5,nosuid,noexec && + chroot_add_mount shm "$1/dev/shm" -t tmpfs -o mode=1777,nosuid,nodev && + chroot_add_mount /run "$1/run" --bind --make-private && + chroot_add_mount tmp "$1/tmp" -t tmpfs -o mode=1777,strictatime,nodev,nosuid +} + +chroot_teardown() { + if (( ${#CHROOT_ACTIVE_MOUNTS[@]} )); then + umount "${CHROOT_ACTIVE_MOUNTS[@]}" + fi + unset CHROOT_ACTIVE_MOUNTS +} + +pid_unshare="unshare --fork --pid" + +hostcache=0 +copykeyring=1 +initkeyring=0 +copymirrorlist=1 +pacman_args=() +pacmode=-Sy +copyconf=0 +pacman_config=/etc/pacman.conf + +usage() { + cat < Use an alternate config file for pacman + -c Use the package cache on the host, rather than the target + -D Skip pacman dependency checks + -G Avoid copying the host's pacman keyring to the target + -i Prompt for package confirmation when needed (run interactively) + -K Initialize an empty pacman keyring in the target (implies '-G') + -M Avoid copying the host's mirrorlist to the target + -P Copy the host's pacman config to the target + -U Use pacman -U to install packages + + -h Print this help message + +$(basename "$0") installs packages to the specified new root directory. If no packages +are given, $(basename "$0") defaults to the "base" group. + +EOF +} + +pacstrap() { + (( EUID == 0 )) || die 'This script must be run with root privileges' + + # create obligatory directories + msg 'Creating install root at %s' "$newroot" + # shellcheck disable=SC2174 # permissions are perfectly fine here + mkdir -m 0755 -p "$newroot"/var/{cache/pacman/pkg,lib/pacman,log} "$newroot"/{dev,run,etc/pacman.d} + # shellcheck disable=SC2174 # permissions are perfectly fine here + mkdir -m 1777 -p "$newroot"/tmp + # shellcheck disable=SC2174 # permissions are perfectly fine here + mkdir -m 0555 -p "$newroot"/{sys,proc} + + # mount API filesystems + $setup "$newroot" || die "failed to setup chroot %s" "$newroot" + + if [[ ! -d $newroot/etc/pacman.d/gnupg ]]; then + if (( initkeyring )); then + pacman-key --gpgdir "$newroot"/etc/pacman.d/gnupg --init + elif (( copykeyring )) && [[ -d /etc/pacman.d/gnupg ]]; then + # if there's a keyring on the host, copy it into the new root + cp -a --no-preserve=ownership /etc/pacman.d/gnupg "$newroot/etc/pacman.d/" + fi + fi + + ######################## + msg 'Installing packages to %s' "$newroot" + if ! $pid_unshare pacman -r "$newroot" "${pacman_args[@]}"; then + die 'Failed to install packages to new root' + fi + ######################## + + if (( copymirrorlist )); then + # install the host's mirrorlist onto the new root + cp -a /etc/pacman.d/mirrorlist "$newroot/etc/pacman.d/" + fi + + if (( copyconf )); then + cp -a "$pacman_config" "$newroot/etc/pacman.conf" + fi +} + +if [[ -z $1 || $1 = @(-h|--help) ]]; then + usage + exit $(( $# ? 0 : 1 )) +fi + +while getopts ':C:cDGiKMNPU' flag; do + case $flag in + C) + pacman_config=$OPTARG + ;; + D) + pacman_args+=(-dd) + ;; + c) + hostcache=1 + ;; + i) + interactive=1 + ;; + G) + copykeyring=0 + ;; + K) + initkeyring=1 + ;; + M) + copymirrorlist=0 + ;; + P) + copyconf=1 + ;; + U) + pacmode=-U + ;; + :) + die '%s: option requires an argument -- '\''%s'\' "${0##*/}" "$OPTARG" + ;; + ?) + die '%s: invalid option -- '\''%s'\' "${0##*/}" "$OPTARG" + ;; + esac +done +shift $(( OPTIND - 1 )) + +(( $# )) || die "No root directory specified" +newroot=$1 +shift + +[[ -d $newroot ]] || die "%s is not a directory" "$newroot" + +pacman_args+=("$pacmode" "${@:-base}" --config="$pacman_config") + +if (( ! hostcache )); then + pacman_args+=(--cachedir="$newroot/var/cache/pacman/pkg") +fi + +if (( ! interactive )); then + pacman_args+=(--noconfirm) +fi + +setup=chroot_setup +pacstrap \ No newline at end of file