diff --git a/airootfs/usr/share/sysrescue/bin/build-zfs-srm b/airootfs/usr/share/sysrescue/bin/build-zfs-srm new file mode 100755 index 0000000..6b5a4a2 --- /dev/null +++ b/airootfs/usr/share/sysrescue/bin/build-zfs-srm @@ -0,0 +1,248 @@ +#! /usr/bin/env bash +# +# build-zfs-srm - build ZFS support for SystemRescue +# +# This script builds a SystemRescue Module (SRM) file that adds support +# for the ZFS file system to a running instance of SystemRescue. +# +# Author: Daniel Richard G. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# SystemRescue cannot be distributed with ZFS support due to licensing +# issues, but users are free to build ZFS for SystemRescue themselves. +# As the build process is non-trivial, it has been elaborated in this +# script as a service to the SystemRescue community. +# +# Usage: +# ./build-zfs-srm [--latest] +# +# By default, this script will build the version of ZFS that was current +# (in the AUR repo) at the time of the host system's release. If the +# --latest option is given, then it will instead build the latest version +# available now (when the script is run). +# +# Note that the build is performed reproducibly; i.e. re-running the +# build in the same environment should yield exactly the same output +# file. Thus, builds performed with --latest will produce different +# output as new ZFS versions become available, whereas builds performed +# without should (in theory) remain unchanged in perpetuity. +# +# For more information, refer to +# https://www.system-rescue.org/scripts/build-zfs-srm/ +# + +use_latest_zfs=no + +while [ -n "$1" ] +do + case "$1" in + --latest) use_latest_zfs=yes ;; + -h|--help) echo "$0: see comment header of script for usage info"; exit 0 ;; + -*) echo "$0: error: unrecognized option \"$1\""; exit 1 ;; + *) echo "$0: error: unrecognized argument \"$1\""; exit 1 ;; + esac + shift +done + +# Sanity checks +if [ ! -f /etc/arch-release ] || ! /usr/bin/pacman --version >/dev/null 2>&1 +then + echo "$0: error: this script must be run on SystemRescue / Arch Linux" + exit 1 +fi +if [ $(id -u) -ne 0 ] +then + echo "$0: error: this script must be run as root" + exit 1 +fi +if [ $(awk '$1=="MemAvailable:"{print $2}' /proc/meminfo) -lt 3500000 ] && \ + ! make --version >/dev/null 2>&1 +then + echo "$0: error: not enough RAM available for build, ~4 GB needed" + exit 1 +fi + +set -e -u + +# Use this timestamp for reproducibility +t_epoch=$(stat -c '%Y' /etc/os-release) +t_date=$(date -d @${t_epoch} -R) + +# Are we in an actual live running instance of SystemRescue? +# (The expected alternative is an "archlinux" Docker container) +in_live_system=$(test "_$(findmnt -n -o SOURCE /)" = _airootfs && echo true || echo false) + +srm_file=/tmp/$(. /etc/os-release && echo ${ID}-${VERSION_ID}-zfs.srm) +srm_info=${srm_file%.srm}.txt + +cat <&2 + env "$@" +} + +# Install some prerequisites +run_command pacman -Sy --needed --noconfirm base-devel git + +reinstall_if_missing() +{ + local pkg="$1" + local file="$2" + test -f ${file} || run_command pacman -S --noconfirm ${pkg} +} + +# Many packages in the SystemRescue ISO have had files removed to save on +# space, but we will need to restore some of them to build ZFS. Reinstall +# the following packages as needed: +reinstall_if_missing curl /usr/include/curl/curl.h +reinstall_if_missing glibc /usr/lib/libc_nonshared.a +reinstall_if_missing libtirpc /usr/include/tirpc/rpc/xdr.h +reinstall_if_missing linux-api-headers /usr/include/linux/limits.h +reinstall_if_missing openssl /usr/include/openssl/evp.h +reinstall_if_missing pam /usr/include/security/pam_modules.h +reinstall_if_missing systemd-libs /usr/include/libudev.h +reinstall_if_missing util-linux-libs /usr/include/uuid/uuid.h +reinstall_if_missing zlib /usr/include/zlib.h + +if ${in_live_system} +then + # More disk space is available in a tmpfs + work_dir=/tmp/zfsbuild +else + work_dir=/home/zfsbuild +fi +if [ ! -d ${work_dir} ] +then + run_command useradd --create-home --home-dir ${work_dir} zfsbuild +fi + +run_as_user() +{ + local cmd="$1" + setpriv \ + --reuid=zfsbuild \ + --regid=zfsbuild \ + --init-groups \ + --no-new-privs \ + --reset-env \ + bash -e -x -c "${cmd}" +} + +cd ${work_dir} + +# Build these two essential ZFS packages from the AUR +for aur_pkg in \ + zfs-dkms \ + zfs-utils +do + if [ ! -d ${aur_pkg} ] + then + run_as_user "git clone https://aur.archlinux.org/${aur_pkg}.git" + fi + if [ ! -f ${aur_pkg}.repro.stamp -a ${use_latest_zfs} = no ] + then + run_as_user "cd ${aur_pkg} && rev=\$(git rev-list -n 1 --first-parent --before=@${t_epoch} HEAD) && git checkout \${rev}" + touch ${aur_pkg}.repro.stamp + fi + if [ ! -f ${aur_pkg}.pgp.stamp ] + then + run_as_user ". ${aur_pkg}/PKGBUILD && gpg --recv-keys \${validpgpkeys[*]}" + touch ${aur_pkg}.pgp.stamp + fi + if [ ! -f ${aur_pkg}.build.stamp ] + then + run_as_user "cd ${aur_pkg} && makepkg --clean" + run_as_user "cd ${aur_pkg} && git rev-parse HEAD" > ${aur_pkg}.commit.txt + touch ${aur_pkg}.build.stamp + fi +done + +# Install more prerequisites +run_command pacman -S --needed --noconfirm \ + dkms linux-lts linux-lts-headers squashfs-tools + +# Tweak DKMS configuration +x=/etc/dkms/framework.conf +if ! grep -q '^dkms_tree=' $x && ${in_live_system} +then + # More disk space is available in a tmpfs + mkdir -p /tmp/dkms + (echo; echo 'dkms_tree="/tmp/dkms"') >> $x +fi +if ! grep -q '^sign_file=' $x +then + # Do not sign the kernel modules as this breaks reproducibility + (echo; echo 'sign_file="/nope"') >> $x +fi + +if ! ${in_live_system} +then + # The Docker container does not extract/install man pages from + # packages, but we want the SRM to include those + perl -pi -e '/^NoExtract\s*=/ && m! usr/share/man/! and s/^/#/' \ + /etc/pacman.conf +fi + +# Kernel module builds need the kernel file in the standard location +x=/run/archiso/bootmnt/sysresccd/boot/x86_64/vmlinuz +y=/boot/vmlinuz-linux-lts +if [ -f $x -a ! -f $y ] +then + run_command ln -s $x $y +fi + +# Do not pass the -j option to pahole(1) as it breaks reproducibility +# https://github.com/acmel/dwarves/issues/42 +perl -pi -e 's/^(\s*)(extra_paholeopt=".* -j")/${1}true $2/' \ + /lib/modules/*-lts/build/scripts/pahole-flags.sh + +# Install the newly-built ZFS packages, and let DKMS do its thing +run_command pacman -U --needed --noconfirm \ + zfs-utils/zfs-utils-*.pkg.tar.zst \ + zfs-dkms/zfs-dkms-*.pkg.tar.zst + +# Generate list of files in the zfs-utils package +pacman -Ql zfs-utils \ +| sed 's!^zfs-utils /!!' \ +| grep -v '/$' \ +> zfs-utils.files.txt + +# mksquashfs(1) uses this +export SOURCE_DATE_EPOCH=${t_epoch} + +# Create the SRM file +rm -f ${srm_file} +(cd / && tar cf - --sort=name \ + usr/lib/modules/*-lts/updates/dkms/* \ + usr/lib/modules/*-lts/modules.* \ + -T ${work_dir}/zfs-utils.files.txt) \ +| run_command mksquashfs - ${srm_file} -comp xz -tar -exports + +tee ${srm_info} </dev/null || echo unknown) +zfs-utils version: $(. zfs-utils/PKGBUILD && echo ${pkgver}-${pkgrel}) +* AUR Git commit : $(cat zfs-utils.commit.txt 2>/dev/null || echo unknown) +SRM file location: ${srm_file} +SRM file size : $(stat -c '%s' ${srm_file}) bytes +SRM file SHA-1 : $(sha1sum < ${srm_file} | awk '{print $1}') +SRM file SHA-512 : $(sha512sum < ${srm_file} | awk '{print $1}') + +Please visit https://www.system-rescue.org/Modules/ for instructions on +loading the SRM file into a running instance of SystemRescue. + +END + +# EOF