Skip to content

Instantly share code, notes, and snippets.

@xginn8
Created September 17, 2020 18:20
Show Gist options
  • Save xginn8/26f7cddf0da1c79365c3522bb133c3ec to your computer and use it in GitHub Desktop.
Save xginn8/26f7cddf0da1c79365c3522bb133c3ec to your computer and use it in GitHub Desktop.
#!/bin/sh
#
# Script to deploy the boot files from rootfs to the boot partition
#
# This hook is meant to run in the `next` resinOS container
#
set -o errexit
# Variables
boot_fingerprint="@RESIN_BOOT_FINGERPRINT@"
bootfiles_blacklist="\
/config.json \
/config.txt \
/extlinux/extlinux.conf \
/splash/balena-logo.png \
"
boot_mountpoint="/mnt/boot"
DURING_UDPATE=${DURING_UPDATE:-0}
# Checks if a file is present in the blacklist
# Arguments:
# $1: file to be checked
# Return value:
# 0: file is blacklisted
# 1: file is not blacklisted
isBlacklisted() {
local _file="$1"
for b in $bootfiles_blacklist; do
if [ "$b" = "$_file" ]; then
return 0
fi
done
return 1
}
# Checks if a file was modified by verifying its fingerprint
# Arguments:
# $1: file to be checked
# Return value:
# 0: file is modified
# 1: file is not modified
isModified() {
local _file="$1"
local _current_md5
_current_md5="$(md5sum "$boot_mountpoint/$_file" | awk '{print $1}')"
local _initial_md5
_initial_md5="$(grep "$_file" < "$boot_mountpoint/$boot_fingerprint" | awk '{print $1}')"
if [ "$_current_md5" != "$_initial_md5" ]; then
return 0
else
return 1
fi
}
# Copies a file from /resin-boot to boot partition filesystem atomically and durable
# Arguments:
# $1: boot partition file
copyBootFile() {
local _file="$1"
mkdir -p "$boot_mountpoint/$(dirname "$_file")"
if cp "/resin-boot/$_file" "$boot_mountpoint/$_file.new"; then
sync -f $boot_mountpoint
mv "$boot_mountpoint/$_file.new" "$boot_mountpoint/$_file"
sync -f $boot_mountpoint
else
if [ "$DURING_UPDATE" = "1" ]; then
# Cleanup all new files we deployed
find "$boot_mountpoint" -type f -name "*.new" -exec rm -f {} \;
for file in $new_deployed_files; do
rm -f "$boot_mountpoint/$file"
done
exit 1
fi
fi
}
# Deploys files to boot partition
# Arguments:
# $1: file path relative to boot partition's root
deploy() {
local _file="$1"
printf "[INFO] Deploying %s%s..." "${boot_mountpoint}" "${_file}"
if isBlacklisted "$_file"; then
if [ "$_file" = "/splash/balena-logo.png" ]; then
if [ -f "$boot_mountpoint/splash/resin-logo.png" ]; then
if isModified "/splash/resin-logo.png"; then
# Keep custom logo
printf "renaming resin-logo to balena-logo..."
sync -f $boot_mountpoint
mv $boot_mountpoint/splash/resin-logo.png $boot_mountpoint/splash/balena-logo.png
sync -f $boot_mountpoint
else
# This rebrands from old resin logo
printf "replacing resin-logo with balena-logo..."
copyBootFile "$_file"
rm "$boot_mountpoint/splash/resin-logo.png"
fi
printf " done.\n"
return
fi
fi
printf "file blacklisted. Ignoring.\n"
else
if [ -f "$boot_mountpoint/$_file" ]; then
if isModified "$_file"; then
printf " overwriting modified file..."
copyBootFile "$_file"
printf " done.\n"
else
copyBootFile "$_file"
printf " done.\n"
fi
else
new_deployed_files="$new_deployed_files $_file"
printf " new file..."
copyBootFile "$_file"
printf " done.\n"
fi
fi
}
#
# MAIN
#
# Do a dry run for copying the boot files and figure out if we would get in an
# out of space situation
boot_space="$(df -B1 --output=avail $boot_mountpoint | grep -v Avail)"
available="$boot_space"
available_threshold="524288" # All sizes in bytes
printf "[INFO] Checking if boot partition can accommodate the new update... "
for filepath in $(find /resin-boot -type f | sed 's#^/resin-boot##g'); do
if isBlacklisted "$filepath"; then
continue
fi
filesize=$(stat --format %s "/resin-boot${filepath}")
available="$((available - filesize))"
if [ "$available" -lt "$available_threshold" ]; then
echo "fail."
echo "[ERROR] Boot files copy operations will fail with out of space error."
if [ "$DURING_UPDATE" = "1" ]; then
exit 1
fi
fi
if [ -f "${boot_mountpoint}${filepath}" ]; then
available="$((available + $(stat --format %s "${boot_mountpoint}${filepath}")))"
fi
done
echo "success."
# Deploy all files in the bootfiles list except fingerprint
new_deployed_files=""
for filepath in $(find /resin-boot -type f | sed 's#^/resin-boot##g'); do
if [ "$filepath" != "/$boot_fingerprint" ]; then
deploy "$filepath"
fi
done
# Deploy fingerprint last
deploy "/$boot_fingerprint"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment