#!/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_state=true 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 ;; * ) 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 if [ -f /tarballs/$tarball ]; then if ! [ -f /tarballs/$tarball.sha256 ]; then sha256sum /tarballs/$tarball > /tarballs/$tarball.sha256 fi mb_remotesig=$(grep $tarball /updates/updates.sha256 | cut -d' ' -f1) mb_localsig=$(cat /tarballs/$tarball.sha256 | cut -d' ' -f1) printf '\tremote signature: %s\n' $mb_remotesig >&3 printf '\tcached signature: %s\n' $mb_localsig >&3 if [ $mb_localsig != $mb_remotesig ]; then mb_state=false 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, installed tarball is already up-to-date.\n' >&3 mb_needed=no fi else printf '\t/updates/%s does not exist, download needed.\n' $tarball >&3 if [ $mb_obtain = no ]; then update_needed else mb_needed=yes fi fi else mb_state=false 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 # already up-to-date? if [ "${mb_dlopt}" = '--check-state' ]; then if [ $mb_state = true ]; then update_success else update_needed fi fi # status touch /updates/update.pending # all done update_success