#!/bin/bash -ex CURDIR=$(pwd) PROGNAME=${0##*/} usage() { cat << EOF Usage: $PROGNAME [OPTION] -h, --help Display this help --force Update, even if the signature checks fail --dir DIR Update from DIR, instead of downloading --nocheck Do not check the integrity of the update data --nodownload Use the existing *.json file in the current directory EOF } TEMP=$( getopt -o '' \ --long dir: \ --long force \ --long nocheck \ --long nodownload \ --long help \ -- "$@" ) if (( $? != 0 )); then usage >&2 exit 1 fi eval set -- "$TEMP" unset TEMP while true; do case "$1" in '--dir') USE_DIR="$(readlink -e $2)" shift 2; continue ;; '--force') FORCE="y" shift 1; continue ;; '--nocheck') NO_CHECK="y" shift 1; continue ;; '--nodownload') NO_DOWNLOAD="y" shift 1; continue ;; '--help') usage exit 0 ;; '--') shift break ;; *) echo 'Internal error!' >&2 exit 1 ;; esac done BASEURL="$1" . /etc/os-release CURRENT_ROOT_HASH=$(&2 exit 1 } # clean up after ourselves no matter how we die. trap ' ret=$?; [[ $MY_TMPDIR ]] && rm -rf --one-file-system -- "$MY_TMPDIR" exit $ret; ' EXIT # clean up after ourselves no matter how we die. trap 'exit 1;' SIGINT if [[ $USE_DIR ]]; then IMAGE="$USE_DIR" ROOT_HASH=$(jq -r '.roothash' "$IMAGE"/release.json) if ! [[ $FORCE ]] && [[ $CURRENT_ROOT_HASH == $ROOT_HASH ]]; then echo "Already up2date" exit 1 fi else if ! [[ $NO_DOWNLOAD ]]; then cd "$MY_TMPDIR" JSON="${NAME}-latest.json" curl ${BASEURL}/${JSON} --output ${JSON} else JSON="$(realpath $1)" cd ${JSON%/*} fi IMAGE="$(jq -r '.name' ${JSON})-$(jq -r '.version' ${JSON})" ROOT_HASH=$(jq -r '.roothash' ${JSON}) if ! [[ $FORCE ]] && [[ $CURRENT_ROOT_HASH == $ROOT_HASH ]]; then echo "Already up2date" exit 1 fi if ! [[ $NO_DOWNLOAD ]]; then [[ -d ${IMAGE} ]] || curl ${BASEURL}/${IMAGE}.tgz | tar xzf - fi fi [[ -d ${IMAGE} ]] cd ${IMAGE} unset FILES; declare -A FILES while read _ file || [[ $file ]]; do FILES["$file"]="1" done < sha512sum.txt if ! [[ $NO_CHECK ]]; then # check integrity openssl dgst -sha256 -verify "$sysroot"/etc/pki/${NAME}/pubkey \ -signature sha512sum.txt.sig sha512sum.txt sha512sum --strict -c sha512sum.txt for i in $(find . -type f); do [[ $i == ./sha512sum.txt ]] && continue [[ $i == ./sha512sum.txt.sig ]] && continue if ! [[ ${FILES["$i"]} ]]; then echo "File $i not signed" exit 1 fi done fi if [[ ${FILES["update.sh"]} ]] && [[ -e ./update.sh ]]; then . ./update.sh exit $? fi dd bs=4096 conv=fsync status=progress \ if=root.img \ of=${ROOT_DEV}-part${NEW_ROOT_PARTNO} # set the new partition uuids ROOT_UUID=${ROOT_HASH:32:8}-${ROOT_HASH:40:4}-${ROOT_HASH:44:4}-${ROOT_HASH:48:4}-${ROOT_HASH:52:12} sfdisk --part-uuid ${ROOT_DEV} ${NEW_ROOT_PARTNO} ${ROOT_UUID} # install to /efi if [[ -d efi/EFI ]]; then cp -vr efi/EFI/* /efi/EFI/ fi if [[ ! -f /efi/EFI/Boot/bootx64.efi ]] \ || cmp --quiet /efi/EFI/${NAME}/${OLD_ROOT_NUM}.efi /efi/EFI/Boot/bootx64.efi \ || cmp --quiet /efi/EFI/${NAME}/_${OLD_ROOT_NUM}.efi /efi/EFI/Boot/bootx64.efi then cp /efi/EFI/${NAME}/bootx64-$ROOT_HASH.efi /efi/EFI/Boot/bootx64.efi fi cp /efi/EFI/${NAME}/bootx64-$ROOT_HASH.efi /efi/EFI/${NAME}/${NEW_ROOT_NUM}.efi if [[ -f /efi/EFI/${NAME}/${OLD_ROOT_NUM}.efi ]]; then mv /efi/EFI/${NAME}/${OLD_ROOT_NUM}.efi /efi/EFI/${NAME}/_${OLD_ROOT_NUM}.efi fi rm -f /efi/EFI/${NAME}/_${NEW_ROOT_NUM}.efi BOOT_ORDER=$(efibootmgr | grep BootOrder: | { read _ a; echo "$a"; }) BOOT_ORDER=${BOOT_ORDER//FED?,} BOOT_ORDER=${BOOT_ORDER//FED?} BOOT_ORDER=${BOOT_ORDER%,} BOOT_ORDER=${BOOT_ORDER#,} efibootmgr -o "FED${NEW_ROOT_NUM},FED$((${OLD_ROOT_NUM}+2)),$BOOT_ORDER" for i in /efi/EFI/${NAME}/bootx64-*.efi; do [[ $i == /efi/EFI/${NAME}/bootx64-$ROOT_HASH.efi ]] && continue [[ $i == /efi/EFI/${NAME}/bootx64-$CURRENT_ROOT_HASH.efi ]] && continue rm -f "$i" done echo "Update successful. Reboot your machine to use it."