Blob Blame History Raw
#!/bin/sh

set -eu

trap update_failure 1 2 EXIT

# before we begin...
mb_path="$PATH"
mb_script="$0"
mb_success=no
mb_obtain=no
mb_dlopt="${1:-}"

error_msg()
{
	printf '%s\n' "$@" >&2
}

warning_msg()
{
	printf '%s\n' "$@" >&2
}

update_failure()
{
	if [ _$mb_success = _yes ]; then
		return 0
	fi

	printf 'update info: exiting due to an error.\n' >&3

	exit 2
}


update_needed()
{
	trap '' EXIT
	mb_success=yes
	exit 1
}


update_success()
{
	trap '' EXIT
	mb_success=yes
	exit 0
}

obtain_remote_file()
{
	pathname="$1"

	case "$mb_vendor" in
		/* )
			cp -p "${mb_vendor}/${pathname}" \
				"${pathname}"
			;;

		https://* )
			wget "${mb_vendor}/${pathname}"       \
				--output-document="${pathname}"  \
				--no-check-certificate            \
				2>/dev/null
			;;

		* )
			error_msg "Invalid prefix in path argument ${pathname}"
			update_failure
			;;
	esac
}

# logging
exec 3> /updates/update.log

# previous state
if [ -f /updates/update.pending ]; then
	rm /updates/update.pending
	update_needed
fi

# vendor server location
mb_vendor=$(cat /etc/vendor.host)

# obtain list of advertised updates
obtain_remote_file /updates/updates.sha256
mb_tarballs=$(cut -d' ' -f3 /updates/updates.sha256)

# simple argument parsing
if [ "${mb_dlopt}" = '--obtain-tarballs' ]; then
	mb_obtain=yes
fi

# compare against local state
for tarball in ${mb_tarballs:-}; do
	printf 'checking local status of %s...\n' $tarball >&3

	if ! [ -f /updates/$tarball ]; then
		printf '\t/updates/%s does not exist, download needed.\n' $tarball >&3

		if [ $mb_obtain = no ]; then
			update_needed
		else
			mb_needed=yes
		fi
	else
		printf '\t/updates/%s found, checking signatures...\n' $tarball >&3

		if ! [ -f /updates/$tarball.sha256 ]; then
			sha256sum /updates/$tarball > /updates/$tarball.sha256
		fi

		mb_remotesig=$(grep $tarball /updates/updates.sha256 | cut -d' ' -f1)
		mb_localsig=$(cat /updates/$tarball.sha256 | cut -d' ' -f1)

		printf '\tremote signature: %s\n' $mb_remotesig >&3
		printf '\tlocal  signature: %s\n' $mb_localsig >&3

		if [ $mb_localsig != $mb_remotesig ]; then
			printf '\tsignatures do not match, download needed.\n' >&3

			if [ $mb_obtain = no ]; then
				update_needed
			else
				mb_needed=yes
			fi
		else
			printf '\tsignatures match, local tarball is already up-to-date.\n' >&3
			mb_needed=no
		fi
	fi

	if [ $mb_needed = yes ]; then
		printf '\tattempting to download %s...\n' ${mb_vendor}/updates/$tarball >&3

		obtain_remote_file /updates/$tarball
		sha256sum /updates/$tarball > /updates/$tarball.sha256

		mb_remotesig=$(grep $tarball /updates/updates.sha256 | cut -d' ' -f1)
		mb_localsig=$(cat /updates/$tarball.sha256 | cut -d' ' -f1)

		printf '\tremote signature: %s\n' $mb_remotesig >&3
		printf '\tlocal  signature: %s\n' $mb_localsig >&3

		if [ $mb_localsig != $mb_remotesig ]; then
			printf 'signatures do not match, aborting.\n' >&3
			update_failure
		else
			printf '\t/local tarball is now up-to-date.\n' >&3
		fi
	fi

	printf '\n' >&3
done

# status
touch /updates/update.pending

# all done
update_success