#!/bin/bash ### CONFIGURATION archlinux_mirror="https://mirrors.kernel.org/archlinux/" preserve_home_directories=true set -eu set -o pipefail shopt -s nullglob shopt -s dotglob export LC_ALL=C export LANG=C unset LANGUAGE stdin_symlink="$(readlink /dev/fd/0)" if [ "${stdin_symlink#pipe:}" != "${stdin_symlink}" ]; then echo "This script must be run from a file. Exiting." >&2 exit 1 fi if [ -n "${POSIXLY_CORRECT}" ] || [ -z "${BASH_VERSION}" ]; then unset POSIXLY_CORRECT exec bash "$0" "$@" fi declare -A dependencies dependencies[pacman]=x log() { echo "[$(date)]" "$@" >&2 } clean_archroot() { local file local prompted=false local lsfd while read file <&${lsfd}; do if [ "${file}" = "installer" ] || [ "${file}" = "packages" ]; then continue fi if ! $prompted; then log "Your /archroot directory contains a stale installation or other data." log "Remove it?" local response read -p '(yes or [no]) ' response if [ "${response}" = "yes" ]; then prompted=true else break fi fi rm -rf "/archroot/${file}" done {lsfd}< <(ls /archroot) } initialize_coredb() { log "Downloading package database ..." wget "${archlinux_mirror}/core/os/x86_64/core.db" log "Unpacking package database ..." mkdir core tar -zxf core.db -C core } remove_version() { echo "${1}" | grep -o '^[A-Za-z0-9_-]*' } get_package_directory() { local dir pkg for dir in core/${1}-*; do if [ "$(get_package_value ${dir}/desc NAME)" = "${1}" ]; then echo "${dir}" return fi done for dir in core/*; do while read pkg; do pkg=$(remove_version "${pkg}") if [ "${pkg}" = "${1}" ]; then echo "${dir}" return fi done < <(get_package_array ${dir}/depends PROVIDES) done log "Package '${1}' not found." } get_package_value() { local infofile=${1} local infokey=${2} get_package_array ${infofile} ${infokey} | ( local value read value echo "${value}" ) } get_package_array() { local infofile=${1} local infokey=${2} local line while read line; do if [ "${line}" = "%${infokey}%" ]; then while read line; do if [ -z "${line}" ]; then return fi echo "${line}" done fi done < ${infofile} } calculate_dependencies() { log "Calculating dependencies ..." local dirty=true local pkg dir dep while $dirty; do dirty=false for pkg in "${!dependencies[@]}"; do dir=$(get_package_directory $pkg) while read line; do dep=$(remove_version "${line}") if [ -z "${dependencies[$dep]:-}" ]; then dependencies[$dep]=x dirty=true fi done < <(get_package_array ${dir}/depends DEPENDS) done done } download_packages() { log "Downloading packages ..." mkdir -p /archroot/packages local pkg dir filename sha256 localfn for pkg in "${!dependencies[@]}"; do dir=$(get_package_directory ${pkg}) filename=$(get_package_value ${dir}/desc FILENAME) sha256=$(get_package_value ${dir}/desc SHA256SUM) localfn=/archroot/packages/${filename} if [ -e "${localfn}" ] && ( echo "${sha256} ${localfn}" | sha256sum -c ); then continue fi wget "${archlinux_mirror}/core/os/x86_64/${filename}" -O "${localfn}" if [ -e "${localfn}" ] && ( echo "${sha256} ${localfn}" | sha256sum -c ); then continue fi log "Couldn't download package '${pkg}'." false done } extract_packages() { log "Extracting packages ..." local dir filename for pkg in "${!dependencies[@]}"; do dir=$(get_package_directory ${pkg}) filename=$(get_package_value ${dir}/desc FILENAME) xz -dc /archroot/packages/${filename} | tar -C /archroot -xf - done } mount_virtuals() { log "Mounting virtual filesystems ..." mount -t proc proc /archroot/proc mount -t sysfs sys /archroot/sys mount --bind /dev /archroot/dev mount -t devpts pts /archroot/dev/pts } prebootstrap_configuration() { log "Doing pre-bootstrap configuration ..." rmdir /archroot/var/cache/pacman/pkg ln -s ../../../packages /archroot/var/cache/pacman/pkg chroot /archroot /usr/bin/update-ca-certificates --fresh } bootstrap_system() { local shouldbootstrap=false isbootstrapped=false while ! $isbootstrapped; do if $shouldbootstrap; then log "Bootstrapping system ..." chroot /archroot pacman-key --init chroot /archroot pacman-key --populate archlinux chroot /archroot pacman -Sy --force --noconfirm base openssh kexec-tools isbootstrapped=true else shouldbootstrap=true fi # config overwritten by pacman rm -f /archroot/etc/resolv.conf.pacorig cp /etc/resolv.conf /archroot/etc/resolv.conf rm -f /archroot/etc/pacman.d/mirrorlist.pacorig echo "Server = ${archlinux_mirror}"'/$repo/os/$arch' \ >> /archroot/etc/pacman.d/mirrorlist done } postbootstrap_configuration() { log "Doing post-bootstrap configuration ..." # set up fstab echo "LABEL=DOROOT / ext4 defaults 0 1" >> /archroot/etc/fstab # set up shadow ( umask 077 ( grep '^root:' /etc/shadow grep -v '^root:' /archroot/etc/shadow ) > /archroot/etc/shadow.new cat /archroot/etc/shadow.new > /archroot/etc/shadow rm /archroot/etc/shadow.new ) # set up network local grepfd local ipaddr netmask gateway prefixlen=24 local eni=/etc/network/interfaces exec {grepfd}< <( grep -o 'address [0-9.]\+' ${eni} grep -o 'netmask [0-9.]\+' ${eni} grep -o 'gateway [0-9.]\+' ${eni} ) read ignored ipaddr <&${grepfd} read ignored netmask <&${grepfd} read ignored gateway <&${grepfd} exec {grepfd}<&- case ${netmask} in 255.255.255.0) prefixlen=24 ;; 255.255.240.0) prefixlen=20 ;; 255.255.0.0) prefixlen=16 ;; esac cat > /archroot/etc/systemd/network/internet.network < ${unitdir}/installer-cleanup.service < ${unitdir}/arch-kernel.service <