Skip to content
Snippets Groups Projects
autoupdater 4.22 KiB
Newer Older
  • Learn to ignore specific revisions
  • BRANCH=$(uci get autoupdater.settings.branch)
    
    PROBABILITY=$(uci get autoupdater.${BRANCH}.probability)
    
    
    if test "a$1" != "a-f"; then
    
      if test $(uci get autoupdater.settings.enabled) != 1; then
        echo "autoupdater is disabled"
        exit 0
      fi
    
      # get one random byte from /dev/urandom, convert it to decimal and check
      # against update_probability*255
      hexdump -n1 -e '/1 "%d"' /dev/urandom | awk "{exit \$1 > $PROBABILITY * 255}"
    
      if test $? -ne 0; then
        echo "No autoupdate this time. Use -f to override"
        exit 0
      fi
    fi
    
    
    MIRRORS=$(for mirror in $(uci get autoupdater.${BRANCH}.mirror); do \
                hexdump -n1 -e '/1 "%d '"$mirror"'\n"' /dev/urandom; \
              done | sort -n | cut -d' ' -f2)
    
    PUBKEYS=$(uci get autoupdater.${BRANCH}.pubkey)
    GOOD_SIGNATURES=$(uci get autoupdater.${BRANCH}.good_signatures)
    
    VERSION_FILE=/lib/gluon/release
    
    # returns 0 when $1 is a higher version number than $2
    
    	# negate the return value as opkg returns 1 when the proposition is true
    	! opkg compare-versions "$1" '>>' "$2"
    
    fetch_manifest() {
      local MIRROR=$1
    
      local manifest=$2
    
    
      wget -O$manifest "$MIRROR"/manifest
    
      if test $? -ne 0; then
        echo "Couldn't fetch manifest from $MIRROR" >&2
        return 1
      fi
    
    verify_manifest() {
      local manifest=$1
      local manifest_upper=$2
      local manifest_lower=$(mktemp)
    
      awk "BEGIN    { sep=0 }
    
         /^---\$/ { sep=1; next }
                  { if(sep==0) print > \"$manifest_upper\";
                    else       print > \"$manifest_lower\"}" \
        $manifest
    
      local signatures=""
      while read sig; do
        echo "$sig" | grep -q "^[0-9a-f]\{128\}$"
        if test $? -ne 0; then
          continue
        fi
        signatures="$signatures -s $sig"
      done < $manifest_lower
    
      local pubkeys=""
      for key in $PUBKEYS; do
        pubkeys="$pubkeys -p $key"
      done
    
    
      rm -f $manifest_lower
    
    
      ecdsaverify -n $GOOD_SIGNATURES $pubkeys $signatures $manifest_upper
    
    
        echo "Not enough valid signatures!" >&2
        return 1
    
      return 0
    }
    
    analyse_manifest() {
      local manifest_upper=$1
    
    
      if test $? -ne 0; then
    
      local my_firmware
      my_firmware=$(grep "^${my_model} " $manifest_upper)
    
      if test $? -ne 0; then
        echo "No matching firmware found (model ${my_model})" >&2
        return 1
      fi
    
      fw_version=$(echo "${my_firmware}"|cut -d' ' -f2)
    
      fw_checksum=$(echo "${my_firmware}"|cut -d' ' -f3)
    
      fw_file=$(echo "${my_firmware}"|cut -d' ' -f4)
    
    fetch_firmware() {
      local MIRROR=$1
    
      local fw_image=$2
    
      wget -O$fw_image "${MIRROR}/${fw_file}"
    
        echo "Error downloading image from $MIRROR" >&2
        return 1
    
    }
    
    autoupdate() {
      local MIRROR=$1
    
      local manifest=$(mktemp)
      fetch_manifest $MIRROR $manifest || { rm -f $manifest; return 1; }
    
      local manifest_upper=$(mktemp)
      verify_manifest $manifest $manifest_upper || { rm -f $manifest $manifest_upper; return 1; }
      rm -f $manifest
    
      analyse_manifest $manifest_upper || { rm -f $manifest_upper; return 1; }
      rm -f $manifest_upper
    
    
      if newer_than "$fw_version" "$my_version"; then
        echo "New version available"
    
    
        # drop caches to make room for firmware image
        sync
        sysctl -w vm.drop_caches=3
    
    
        local fw_image=$(mktemp)
        fetch_firmware $MIRROR $fw_image || { rm -f $fw_image; return 1; }
    
        image_sha512=$(sha512sum "$fw_image" | awk '{print $1}')
        image_md5=$(md5sum "$fw_image" | awk '{print $1}')
        if [ "$image_sha512" != "$fw_checksum" -a "$image_md5" != "$fw_checksum" ]; then
    
          echo "Invalid image checksum" >&2
    
          rm -f $fw_image
    
          return 1
        fi
        echo "Upgrading firmware."
    
        sysupgrade "${fw_image}"
      else
        echo "No new firmware available"
    
    trap 'echo Signal ignored.' INT TERM PIPE
    
    . /lib/gluon/functions/model.sh
    my_model="$(get_model | tr '[A-Z]' '[a-z]' | sed -r 's/[^a-z0-9]+/-/g;s/-$//')"
    
    if [ ! -f "$VERSION_FILE" ]; then
      echo "Couldn't determine firmware version!" >&2
      exit 1
    fi
    
    my_version="$(cat "$VERSION_FILE")"
    
    for mirror in $MIRRORS; do
    
      autoupdate $mirror && exit 0
    
      unset fw_version
    
      unset fw_checksum