#!/bin/bash # This script load zfs kernel module for any archiso. # github.com/eoli3n # Thanks to CalimeroTeknik on #archlinux-fr, FFY00 on #archlinux-projects, JohnDoe2 on #regex exec &> >(tee "debug.log") ### Vars verbose=0 ### Functions usage () { cat << EOF Usage: ${0##*/} [-v] -v increase verbosity -h show this usage EOF } print () { echo -e "\n\033[1m> $1\033[0m" } get_running_kernel_version () { # Returns running kernel version # Get running kernel version kernel_version=$(uname -r) print "Current kernel version is $kernel_version" } init_archzfs () { if pacman -Sl archzfs >&3; then print "archzfs repo was already added" return 0 fi print "Add archzfs repo" # Disable Sig check pacman -Syy archlinux-keyring --noconfirm >&3 || return 1 pacman-key --populate archlinux >&3 || return 1 pacman-key --recv-keys F75D9D76 >&3 || return 1 pacman-key --lsign-key F75D9D76 >&3 || return 1 cat >> /etc/pacman.conf <<"EOF" [archzfs] Server = http://archzfs.com/archzfs/x86_64 Server = http://mirror.sum7.eu/archlinux/archzfs/archzfs/x86_64 Server = https://mirror.biocrafting.net/archlinux/archzfs/archzfs/x86_64 EOF pacman -Sy >&3 || return 1 return 0 } init_archlinux_archive () { # $1 is date formated as 'YYYY/MM/DD' # Returns 1 if repo does not exists # Archlinux Archive workaround for 2022/02/01 if [[ "$1" == "2022/02/01" ]] then version="2022/02/02" else version="$1" fi # Set repo repo="https://archive.archlinux.org/repos/$version/" # If repo exists, set it if curl -s "$repo" >&3 then echo "Server=$repo\$repo/os/\$arch" > /etc/pacman.d/mirrorlist else print "Repository $repo is not reachable or doesn't exist." return 1 fi return 0 } search_package () { # $1 is package name to search # $2 is version to match # Set regex to match package local regex='href="\K(?![^"]*\.sig)'"$1"'-(?=\d)[^"]*'"$2"'[^"]*x86_64[^"]*' # href=" # match href=" # \K # don't return anything matched prior to this point # (?![^"]*\.sig) # remove .sig matches # '"$1"'-(?=\d) # find me '$package-' escaped by shell and ensure that after "-" is a digit # [^"]* # match anything between '"' # '"$2"' # match version escaped by shell # [^"]* # match anything between '"' # x86_64 # now match architecture # [^"]* # match anything between '"' # Set archzfs URLs list local urls="http://archzfs.com/archzfs/x86_64/ http://archzfs.com/archive_archzfs/" # Loop search for url in $urls do print "Searching $1 on $url..." # Query url and try to match package local package package=$(curl -s "$url" | grep -Po "$regex" | tail -n 1) # If a package is found if [[ -n $package ]] then print "Package \"$package\" found" # Build package url package_url="$url$package" return 0 fi done # If no package found return 1 } download_package () { # $1 is package url to download in tmp print "Download to $package_file ..." local filename="${1##*/}" # Download package in tmp cd /tmp || return 1 curl -sO "$1" || return 1 cd - || return 1 # Set out file package_file="/tmp/$filename" return 0 } zfslinux_install () { # Search kernel package # https://github.com/archzfs/archzfs/issues/337#issuecomment-624312576 get_running_kernel_version kernel_version_fixed="${kernel_version//-/\.}" # Search zfs-linux package matching running kernel version if search_package "zfs-linux" "$kernel_version_fixed" then zfs_linux_url="$package_url" # Download package download_package "$zfs_linux_url" || exit 1 zfs_linux_package="$package_file" print "Extracting zfs-utils version from zfs-linux PKGINFO" # Extract zfs-utils version from zfs-linux PKGINFO zfs_utils_version=$(bsdtar -qxO -f "$zfs_linux_package" .PKGINFO | grep -Po 'depend = zfs-utils=\K.*') # Search zfs-utils package matching zfs-linux package dependency if search_package "zfs-utils" "$zfs_utils_version" then zfs_utils_url="$package_url" print "Installing zfs-utils and zfs-linux" # Install packages if pacman -U "$zfs_utils_url" --noconfirm >&3 && pacman -U "$zfs_linux_package" --noconfirm >&3 then zfs=1 else return 1 fi fi fi return 0 } dkms_install () { # Init everything to be able to install zfs-dkms print "No zfs-linux package was found for current running kernel, fallback on DKMS method" print "Init Archlinux Archive repository" archiso_version=$(sed 's-\.-/-g' /version) init_archlinux_archive "$archiso_version" || return 1 print "Download Archlinux Archives package lists and upgrade" pacman -Syyuu --noconfirm >&3 || return 1 print "Install base-devel" pacman -S --noconfirm base-devel linux-headers git >&3 || return 1 print "Install zfs-dkms" # Install package if pacman -S zfs-dkms --noconfirm >&3 then zfs=1 else return 1 fi return 0 } ### Getopts while getopts "vh" option; do case "${option}" in v) verbose=$((verbose + 1)) ;; h) usage exit 0 ;; *) usage exit 0 ;; esac done shift $((OPTIND-1)) ### Verbose mode if [[ "$verbose" -gt 0 ]] then exec 3>&1 else exec 3>/dev/null fi ### Main # Test if archiso is running if ! grep 'arch.*iso' /proc/cmdline >&3 then print "You are not running archiso, exiting." exit 1 fi print "Increase cowspace to half of RAM" mount -o remount,size=50% /run/archiso/cowspace >&3 # Init archzfs repository init_archzfs || exit 1 # Install zfs-linux if found else fallback on dkms_install zfslinux_install || dkms_install || exit 1 # Load kernel module if [[ "$zfs" == "1" ]] then modprobe zfs && echo -e "\n\e[32mZFS is ready\n" else print "No ZFS module found" fi