Blame once/get_updates.sh

ec0f88
#!/bin/sh
ec0f88
ec0f88
set -eu
ec0f88
ec0f88
trap update_failure 1 2 EXIT
ec0f88
ec0f88
# before we begin...
ec0f88
mb_path="$PATH"
ec0f88
mb_script="$0"
ec0f88
mb_success=no
ec0f88
mb_obtain=no
ec0f88
mb_dlopt="${1:-}"
ec0f88
ec0f88
error_msg()
ec0f88
{
ec0f88
	printf '%s\n' "$@" >&2
ec0f88
}
ec0f88
ec0f88
warning_msg()
ec0f88
{
ec0f88
	printf '%s\n' "$@" >&2
ec0f88
}
ec0f88
ec0f88
update_failure()
ec0f88
{
ec0f88
	if [ _$mb_success = _yes ]; then
ec0f88
		return 0
ec0f88
	fi
ec0f88
ec0f88
	printf 'update info: exiting due to an error.\n' >&3
ec0f88
ec0f88
	exit 2
ec0f88
}
ec0f88
ec0f88
ec0f88
update_needed()
ec0f88
{
ec0f88
	trap '' EXIT
ec0f88
	mb_success=yes
ec0f88
	exit 1
ec0f88
}
ec0f88
ec0f88
ec0f88
update_success()
ec0f88
{
ec0f88
	trap '' EXIT
ec0f88
	mb_success=yes
ec0f88
	exit 0
ec0f88
}
ec0f88
ec0f88
obtain_remote_file()
ec0f88
{
ec0f88
	pathname="$1"
ec0f88
ec0f88
	case "$mb_vendor" in
ec0f88
		/* )
ec0f88
			cp -p "${mb_vendor}/${pathname}" \
ec0f88
				"${pathname}"
ec0f88
			;;
ec0f88
ec0f88
		https://* )
ec0f88
			wget "${mb_vendor}/${pathname}"       \
ec0f88
				--output-document="${pathname}"  \
ec0f88
				--no-check-certificate            \
ec0f88
				2>/dev/null
ec0f88
			;;
ec0f88
ec0f88
		* )
ec0f88
			error_msg "Invalid prefix in path argument ${pathname}"
ec0f88
			update_failure
ec0f88
			;;
ec0f88
	esac
ec0f88
}
ec0f88
ec0f88
# logging
ec0f88
exec 3> /updates/update.log
ec0f88
ec0f88
# previous state
ec0f88
if [ -f /updates/update.pending ]; then
ec0f88
	rm /updates/update.pending
ec0f88
	update_needed
ec0f88
fi
ec0f88
ec0f88
# vendor server location
ec0f88
mb_vendor=$(cat /etc/vendor.host)
ec0f88
ec0f88
# obtain list of advertised updates
ec0f88
obtain_remote_file /updates/updates.sha256
ec0f88
mb_tarballs=$(cut -d' ' -f3 /updates/updates.sha256)
ec0f88
ec0f88
# simple argument parsing
ec0f88
if [ "${mb_dlopt}" = '--obtain-tarballs' ]; then
ec0f88
	mb_obtain=yes
ec0f88
fi
ec0f88
ec0f88
# compare against local state
ec0f88
for tarball in ${mb_tarballs:-}; do
ec0f88
	printf 'checking local status of %s...\n' $tarball >&3
ec0f88
ec0f88
	if ! [ -f /updates/$tarball ]; then
ec0f88
		printf '\t/updates/%s does not exist, download needed.\n' $tarball >&3
ec0f88
ec0f88
		if [ $mb_obtain = no ]; then
ec0f88
			update_needed
ec0f88
		else
ec0f88
			mb_needed=yes
ec0f88
		fi
ec0f88
	else
ec0f88
		printf '\t/updates/%s found, checking signatures...\n' $tarball >&3
ec0f88
ec0f88
		if ! [ -f /updates/$tarball.sha256 ]; then
ec0f88
			sha256sum /updates/$tarball > /updates/$tarball.sha256
ec0f88
		fi
ec0f88
ec0f88
		mb_remotesig=$(grep $tarball /updates/updates.sha256 | cut -d' ' -f1)
ec0f88
		mb_localsig=$(cat /updates/$tarball.sha256 | cut -d' ' -f1)
ec0f88
ec0f88
		printf '\tremote signature: %s\n' $mb_remotesig >&3
ec0f88
		printf '\tlocal  signature: %s\n' $mb_localsig >&3
ec0f88
ec0f88
		if [ $mb_localsig != $mb_remotesig ]; then
ec0f88
			printf '\tsignatures do not match, download needed.\n' >&3
ec0f88
ec0f88
			if [ $mb_obtain = no ]; then
ec0f88
				update_needed
ec0f88
			else
ec0f88
				mb_needed=yes
ec0f88
			fi
ec0f88
		else
ec0f88
			printf '\tsignatures match, local tarball is already up-to-date.\n' >&3
ec0f88
			mb_needed=no
ec0f88
		fi
ec0f88
	fi
ec0f88
ec0f88
	if [ $mb_needed = yes ]; then
ec0f88
		printf '\tattempting to download %s...\n' ${mb_vendor}/updates/$tarball >&3
ec0f88
ec0f88
		obtain_remote_file /updates/$tarball
ec0f88
		sha256sum /updates/$tarball > /updates/$tarball.sha256
ec0f88
ec0f88
		mb_remotesig=$(grep $tarball /updates/updates.sha256 | cut -d' ' -f1)
ec0f88
		mb_localsig=$(cat /updates/$tarball.sha256 | cut -d' ' -f1)
ec0f88
ec0f88
		printf '\tremote signature: %s\n' $mb_remotesig >&3
ec0f88
		printf '\tlocal  signature: %s\n' $mb_localsig >&3
ec0f88
ec0f88
		if [ $mb_localsig != $mb_remotesig ]; then
ec0f88
			printf 'signatures do not match, aborting.\n' >&3
ec0f88
			update_failure
ec0f88
		else
ec0f88
			printf '\t/local tarball is now up-to-date.\n' >&3
ec0f88
		fi
ec0f88
	fi
ec0f88
ec0f88
	printf '\n' >&3
ec0f88
done
ec0f88
ec0f88
# status
ec0f88
touch /updates/update.pending
ec0f88
ec0f88
# all done
ec0f88
update_success