libdevuansdk

common library for devuan's simple distro kits
git clone https://git.parazyd.org/libdevuansdk
Log | Files | Refs | Submodules | README | LICENSE

bootstrap (7442B)


      1 #!/usr/bin/env zsh
      2 # shellcheck shell=bash
      3 # Copyright (c) 2016-2021 Ivan J. <parazyd@dyne.org>
      4 # This file is part of libdevuansdk
      5 #
      6 # This source code is free software: you can redistribute it and/or modify
      7 # it under the terms of the GNU General Public License as published by
      8 # the Free Software Foundation, either version 3 of the License, or
      9 # (at your option) any later version.
     10 #
     11 # This software is distributed in the hope that it will be useful,
     12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 # GNU General Public License for more details.
     15 #
     16 # You should have received a copy of the GNU General Public License
     17 # along with this source code. If not, see <http://www.gnu.org/licenses/>.
     18 
     19 vars+=(bootstrap_cpio_stage3 bootstrap_cpio_stage4 CPIO_STAGE4)
     20 
     21 bootstrap_complete_base()
     22 {
     23 	fn bootstrap_complete_base "$*"
     24 	req=(R os arch strapdir LIBPATH release mirror)
     25 	ckreq || return 1
     26 
     27 	notice "Bootstrapping: ${os}:${arch} base"
     28 
     29 	export LANG=C
     30 	export LC_ALL=C
     31 	export DEBIAN_FRONTEND=noninteractive
     32 	export SOURCE_DATE_EPOCH=1610550434
     33 
     34 	bootstrap_cpio_stage3="$R/tmp/bootstrap-${os}-${arch}-stage3.cpio.gz"
     35 	bootstrap_cpio_stage4="$R/tmp/bootstrap-${os}-${arch}-stage4.cpio.gz"
     36 
     37 	if [[ -n "$CPIO_STAGE4" && -f "$bootstrap_cpio_stage4" ]]; then
     38 		act "Using the existing stage4 bootstrap cpio archive..."
     39 		bootstrap_cpio_unpack "$bootstrap_cpio_stage4" "$strapdir" || {
     40 			die "Failed to extract cpio archive"
     41 			return 1
     42 		}
     43 		bootstrap_stage4
     44 		return
     45 	elif [[ -f "$bootstrap_cpio_stage3" ]]; then
     46 		act "Using the existing stage3 bootstrap cpio archive..."
     47 		bootstrap_cpio_unpack "$bootstrap_cpio_stage3" "$strapdir" || {
     48 			die "Failed to extract cpio archive"
     49 			return 1
     50 		}
     51 		bootstrap_stage4 || { zerr; return 1; }
     52 		if [[ -n "$CPIO_STAGE4" ]]; then
     53 			bootstrap_cpio_pack "$bootstrap_cpio_stage4" || { zerr; return 1; }
     54 		fi
     55 		return
     56 	fi
     57 
     58 	notice "Running stage1 debootstrap"
     59 
     60 	sudo debootstrap \
     61 		--keyring="$LIBPATH/extra/devuan-keyring/keyrings/devuan-archive-keyring.gpg" \
     62 		--include=devuan-keyring,wget,ca-certificates \
     63 		--foreign \
     64 		--arch "$arch" "$release" "$strapdir" "$mirror" || { zerr; return 1; }
     65 
     66 	if [[ "$arch" =~ "^arm.." ]]; then
     67 		qemu_install_user "$strapdir" || { zerr; return 1; }
     68 	fi
     69 
     70 	notice "Running stage2 debootstrap"
     71 
     72 	sudo chroot "$strapdir" /debootstrap/debootstrap --second-stage || { zerr; return 1; }
     73 
     74 	# TODO: sys config as function
     75 	conf_print_fstab       | sudo tee "$strapdir/etc/fstab" >/dev/null
     76 	conf_print_hostname    | sudo tee "$strapdir/etc/hostname" >/dev/null
     77 	conf_print_hosts       | sudo tee "$strapdir/etc/hosts" >/dev/null
     78 	conf_print_netifaces   | sudo tee "$strapdir/etc/network/interfaces" >/dev/null
     79 	conf_print_resolvconf  | sudo tee "$strapdir/etc/resolv.conf" >/dev/null
     80 	conf_print_sourceslist | sudo tee "$strapdir/etc/apt/sources.list" >/dev/null
     81 
     82 	blend_bootstrap_setup || { zerr; return 1; }
     83 
     84 	bootstrap_stage3 || { zerr; return 1; }
     85 	bootstrap_cpio_pack "$bootstrap_cpio_stage3" || { zerr; return 1; }
     86 
     87 	bootstrap_stage4 || { zerr; return 1; }
     88 	if [[ -n "$CPIO_STAGE4" ]]; then
     89 		bootstrap_cpio_pack "$bootstrap_cpio_stage4" || { zerr; return 1; }
     90 	fi
     91 
     92 	return
     93 }
     94 
     95 bootstrap_stage3()
     96 {
     97 	fn bootstrap_stage3
     98 	req=(core_packages base_packages rootcredentials)
     99 	ckreq || return 1
    100 
    101 	cat <<EOF | sudo tee "$strapdir/thirdstage" >/dev/null
    102 #!/bin/sh
    103 apt-get update
    104 apt-get --yes --force-yes install ${core_packages_option} ${core_packages} || exit 1
    105 apt-get --yes --force-yes install ${base_packages_option} ${base_packages} || exit 1
    106 apt-get --yes --force-yes purge ${purge_packages_option} ${purge_packages} || exit 1
    107 apt-get --yes --force-yes --purge autoremove || exit 1
    108 apt-get clean
    109 
    110 echo "${rootcredentials}" | chpasswd
    111 
    112 rm -f /etc/ssh/ssh_host_*
    113 rm -f /root/.bash_history
    114 EOF
    115 
    116 	chroot-script -d thirdstage || { zerr; return 1; }
    117 }
    118 
    119 bootstrap_stage4()
    120 {
    121 	fn bootstrap_stage4
    122 	req=(strapdir extra_packages)
    123 	ckreq || return 1
    124 
    125 	sudo mkdir -p "$strapdir"/{boot,dev,proc,sys}
    126 
    127 	cat <<EOF | sudo tee "$strapdir/fourthstage" >/dev/null
    128 #!/bin/sh
    129 apt-get update
    130 
    131 # check if all our extra_packages exist
    132 allpkgs="\$(apt-cache search '.' | cut -d' ' -f1)"
    133 for i in ${extra_packages}; do
    134 	printf "%s" "\$allpkgs" | grep -q "^\$i$" || {
    135 		case "\$i" in
    136 		--*) continue;;
    137 		*)   missing="\$missing \$i" ;;
    138 		esac
    139 	}
    140 done
    141 
    142 if [ -n "\$missing" ]; then
    143 	printf "\033[1;31m[!!] Some extra packages don't exist:\033[0m\n"
    144 	printf "%s\n" "\$missing"
    145 	exit 1
    146 fi
    147 
    148 apt-get --yes --force-yes upgrade || exit 1
    149 apt-get --yes --force-yes install ${extra_packages_option} ${extra_packages} || exit 1
    150 apt-get --yes --force-yes --purge autoremove || exit 1
    151 apt-get clean
    152 EOF
    153 
    154 	chroot-script -d fourthstage || { zerr; return 1; }
    155 
    156 	for i in $inittab; do
    157 		grep -q "$^i" "$strapdir/etc/inittab" && continue
    158 		echo "$i" | sudo tee -a "$strapdir/etc/inittab" >/dev/null
    159 	done || true
    160 
    161 	for i in $custmodules; do
    162 		grep -q "^$i" "$strapdir/etc/modules" && continue
    163 		echo "$i" | sudo tee -a "$strapdir/etc/modules" >/dev/null
    164 	done || true
    165 }
    166 
    167 qemu_install_user()
    168 {
    169 	fn qemu_install_user "$*"
    170 	req=(arch _target)
    171 	local _target="$1"
    172 	ckreq || return 1
    173 
    174 	case "$(uname -m)" in
    175 	arm*|aarch*)
    176 		return
    177 		;;
    178 	esac
    179 
    180 	notice "Installing qemu-user-static"
    181 
    182 	if [[ -f "/etc/gentoo-release" ]] && [[ "$arch" = armhf ]]; then
    183 		cat <<EOF | gcc -O3 -static -o /tmp/qemu-wrapper -x c -
    184 #include <string.h>
    185 #include <unistd.h>
    186 int main(int argc, char **argv, char **envp) {
    187 	char *newargv[argc+3];
    188 	newargv[0] = argv[0];
    189 	newargv[1] = "-cpu";
    190 	newargv[2] = "cortex-a8";
    191 	memcpy(&newargv[3], &argv[1], sizeof(*argv) * (argc-1));
    192 	newargv[argc+2] = NULL;
    193 	return execve("${armhf_qemu_bin}", newargv, envp);
    194 }
    195 EOF
    196 		sudo mv /tmp/qemu-wrapper "$_target" || { zerr; return 1 ; }
    197 	fi
    198 
    199 	case "$arch" in
    200 	armel)
    201 		sudo cp -a "$armel_qemu_bin" "$_target/usr/bin/" || { zerr; return 1; }
    202 		;;
    203 	armhf)
    204 		sudo cp -a "$armhf_qemu_bin" "$_target/usr/bin/" || { zerr; return 1; }
    205 		;;
    206 	arm64)
    207 		sudo cp -a "$arm64_qemu_bin" "$_target/usr/bin/" || { zerr; return 1; }
    208 		;;
    209 	esac
    210 }
    211 
    212 bootstrap_cpio_pack()
    213 {
    214 	fn bootstrap_cpio_pack "$*"
    215 	req=(_bootstrap_cpio strapdir)
    216 	local _bootstrap_cpio="$1"
    217 	ckreq || return 1
    218 
    219 	local _dest="$(dirname "$_bootstrap_cpio")"
    220 	if [[ -f "$_bootstrap_cpio" ]]; then
    221 		notice "cpio archive already found in $_dest"
    222 		return
    223 	fi
    224 
    225 	notice "Creating bootstrap cpio archive: $_bootstrap_cpio"
    226 	silly
    227 
    228 	pushd "$strapdir"
    229 	mkdir -p "$_dest"
    230 	sudo find . \
    231 		-not -path "./dev/*" \
    232 		-a -not -path "./proc/*" \
    233 		-a -not -path "./sys/*" \
    234 		| sudo cpio -oa --reproducible  --format=newc \
    235 		| gzip - > "$_bootstrap_cpio" || { zerr; return 1; }
    236 	popd
    237 }
    238 
    239 bootstrap_cpio_unpack()
    240 {
    241 	fn bootstrap_cpio_unpack "$*"
    242 	req=(_bootstrap_cpio strapdir)
    243 	local _bootstrap_cpio="$1"
    244 	ckreq || return 1
    245 
    246 	notice "Unpacking bootstrap cpio archive: $_bootstrap_cpio"
    247 	silly
    248 
    249 	# Danger Will Robinson
    250 	# Check for (bind) mounts as sudo rm -rf will trash the host
    251 	for m in sys proc dev; do
    252 		if [[ $(mountpoint -q "${strapdir}/$m") ]]; then
    253 			zerr
    254 			return 1
    255 		fi
    256 	done
    257 	# remove everything, including .dotdirfiles
    258 	sudo rm -rf "$strapdir"
    259 	mkdir -p "$strapdir"
    260 
    261 	pushd "$strapdir" || { zerr; return 1; }
    262 	zcat "$_bootstrap_cpio" | sudo cpio -idmn --format=newc 2>>/dev/null || { zerr; return 1; }
    263 	popd
    264 
    265 	sudo mkdir -p "$strapdir"/{boot,dev,proc,sys}
    266 }
    267 
    268 blend_bootstrap_setup()
    269 {
    270 	fn blend_bootstrap_setup "(noop)"
    271 	return
    272 }