diff options
-rwxr-xr-x | once/get_updates.sh | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/once/get_updates.sh b/once/get_updates.sh new file mode 100755 index 0000000..2f6485b --- /dev/null +++ b/once/get_updates.sh @@ -0,0 +1,162 @@ +#!/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 |