| version 1.6, 2021/10/14 02:39:43 | 
version 1.137, 2021/12/26 18:39:46 | 
 | 
 | 
|  #!/bin/ksh | 
 #!/bin/ksh | 
|  set -e | 
 #       $OpenBSD$ | 
|   | 
 # | 
|   | 
 # Copyright (c) 2021 Andrew Hewus Fresh <afresh1@openbsd.org> | 
|   | 
 # | 
|   | 
 # Permission to use, copy, modify, and distribute this software for any | 
|   | 
 # purpose with or without fee is hereby granted, provided that the above | 
|   | 
 # copyright notice and this permission notice appear in all copies. | 
|   | 
 # | 
|   | 
 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 
|   | 
 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 
|   | 
 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 
|   | 
 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 
|   | 
 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 
|   | 
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 
|   | 
 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 
|   | 
  | 
|  scan_dmesg() { | 
 set -o errexit -o pipefail -o nounset -o noclobber -o noglob | 
|          # no bsort for now | 
 set +o monitor | 
|          sed -n "$1" /var/run/dmesg.boot | 
 export PATH=/usr/bin:/bin:/usr/sbin:/sbin | 
|   | 
  | 
|   | 
 CFILE=SHA256.sig | 
|   | 
 DESTDIR=${DESTDIR:-} | 
|   | 
 FWPATTERNS="${DESTDIR}/usr/share/misc/firmware_patterns" | 
|   | 
  | 
|   | 
 VNAME=${VNAME:-$(sysctl -n kern.osrelease)} | 
|   | 
 VERSION=${VERSION:-"${VNAME%.*}${VNAME#*.}"} | 
|   | 
  | 
|   | 
 HTTP_FWDIR="$VNAME" | 
|   | 
 VTYPE=$( sed -n "/^OpenBSD $VNAME\([^ ]*\).*$/s//\1/p" \ | 
|   | 
     /var/run/dmesg.boot | sed '$!d' ) | 
|   | 
 [[ $VTYPE == -!(stable) ]] && HTTP_FWDIR=snapshots | 
|   | 
  | 
|   | 
 FWURL=http://firmware.openbsd.org/firmware/${HTTP_FWDIR} | 
|   | 
 FWPUB_KEY=${DESTDIR}/etc/signify/openbsd-${VERSION}-fw.pub | 
|   | 
  | 
|   | 
 DRYRUN=false | 
|   | 
 VERBOSE=false | 
|   | 
 DELETE=false | 
|   | 
 DOWNLOAD=true | 
|   | 
 INSTALL=true | 
|   | 
 LOCALSRC= | 
|   | 
  | 
|   | 
 unset FTPPID | 
|   | 
 unset FWPKGTMP | 
|   | 
 REMOVE_LOCALSRC=false | 
|   | 
 cleanup() { | 
|   | 
         set +o errexit # ignore errors from killing ftp | 
|   | 
         [ "${FTPPID:-}" ] && kill -TERM -"$FTPPID" 2>/dev/null | 
|   | 
         [ "${FWPKGTMP:-}" ] && rm -rf "$FWPKGTMP" | 
|   | 
         "$REMOVE_LOCALSRC" && rm -rf "$LOCALSRC" | 
|  } | 
 } | 
|   | 
 trap cleanup EXIT | 
|   | 
  | 
|  installed_firmware() { | 
 tmpdir() { | 
|          for fw in ${PKGDIR}/$1-firmware*; do | 
         local _i=1 _dir | 
|                  [ -e "$fw" ] || continue | 
  | 
|                  echo ${fw##*/} | 
         # If we're not in the installer, | 
|          done | 
         # we have mktemp and a more hostile environment. | 
|   | 
         if [ -x /usr/bin/mktemp ]; then | 
|   | 
                 _dir=$( mktemp -d "${1}-XXXXXXXXX" ) | 
|   | 
         else | 
|   | 
                 until _dir="${1}.$_i.$RANDOM" && mkdir -- "$_dir" 2>/dev/null; do | 
|   | 
                     ((++_i < 10000)) || return 1 | 
|   | 
                 done | 
|   | 
         fi | 
|   | 
  | 
|   | 
         echo "$_dir" | 
|  } | 
 } | 
|   | 
  | 
|  # do_as, unpriv, and unpriv2 are from install.sub | 
 fetch() { | 
|   | 
         local _src="${FWURL}/${1##*/}" _dst=$1 _user=_file _exit _error='' | 
|   | 
  | 
|  # Run a command ($2+) as unprivileged user ($1). | 
         # If we're not in the installer, | 
|  # Take extra care that after "cmd" no "user" processes exist. | 
         # we have su(1) and doas(1) is unlikely to be configured. | 
|  # | 
         set -o monitor # make sure ftp gets its own process group | 
|  # Optionally: | 
         ( | 
|  #       - create "file" and chown it to "user" | 
         flags=-VM | 
|  #       - after "cmd", chown "file" back to root | 
         "$VERBOSE" && flags=-vm | 
|  # | 
         if [ -x /usr/bin/su ]; then | 
|  # Usage: do_as user [-f file] cmd | 
                 exec /usr/bin/su -s /bin/ksh "$_user" -c \ | 
|  do_as() { | 
                     "/usr/bin/ftp -N '${0##/}' -D 'Get/Verify' $flags -o- '$_src'" > "$_dst" | 
|          (( $# >= 2 )) || return | 
         else | 
|   | 
                 exec /usr/bin/doas -u "$_user" \ | 
|   | 
                     /usr/bin/ftp -N "${0##/}" -D 'Get/Verify' $flags -o- "$_src" > "$_dst" | 
|   | 
         fi | 
|   | 
         ) & FTPPID=$! | 
|   | 
         set +o monitor | 
|   | 
  | 
|          local _file _rc _user=$1 | 
         SECONDS=0 | 
|          shift | 
         _last=0 | 
|   | 
         while kill -0 -"$FTPPID" 2>/dev/null; do | 
|   | 
                 if [[ $SECONDS -gt 12 ]]; then | 
|   | 
                         set -- $( ls -ln "$_dst" 2>/dev/null ) | 
|   | 
                         if [[ $_last -ne $5 ]]; then | 
|   | 
                                 _last=$5 | 
|   | 
                                 SECONDS=0 | 
|   | 
                                 sleep 1 | 
|   | 
                         else | 
|   | 
                                 kill -INT -"$FTPPID" 2>/dev/null | 
|   | 
                                 _error=" (timed out)" | 
|   | 
                         fi | 
|   | 
                 else | 
|   | 
                         sleep 1 | 
|   | 
                 fi | 
|   | 
         done | 
|   | 
  | 
|          if [[ $1 == -f ]]; then | 
         set +o errexit | 
|                  _file=$2 | 
         wait "$FTPPID" | 
|                  shift 2 | 
         _exit=$? | 
|   | 
         set -o errexit | 
|   | 
  | 
|   | 
         unset FTPPID | 
|   | 
  | 
|   | 
         if [ "$_exit" -ne 0 ]; then | 
|   | 
                 rm -f "$_dst" | 
|   | 
                 echo "Cannot fetch $_src$_error" >&2 | 
|   | 
                 return 1 | 
|          fi | 
         fi | 
|   | 
 } | 
|   | 
  | 
|          if [[ -n $_file ]]; then | 
 verify() { | 
|                  >$_file | 
         # On the installer we don't get sha256 -C, so fake it. | 
|                  chown "$_user" "$_file" | 
         if ! fgrep -qx "SHA256 (${1##*/}) = $( /bin/sha256 -qb "$1" )" "$CFILE"; then | 
|   | 
                 echo "Checksum test for ${1##*/} failed." >&2 | 
|   | 
                 return 1 | 
|          fi | 
         fi | 
|   | 
 } | 
|   | 
  | 
|          doas -u "$_user" "$@" | 
 firmware_in_dmesg() { | 
|          _rc=$? | 
         local _d _m _line _dmesgtail _last='' _nl=$( echo ) | 
|   | 
  | 
|          while doas -u "$_user" kill -9 -1 2>/dev/null; do | 
         # When we're not in the installer, the dmesg.boot can | 
|                  echo "Processes still running for user $_user after: $@" | 
         # contain multiple boots, so only look in the last one | 
|                  sleep 1 | 
         _dmesgtail="$( echo ; sed -n 'H;/^OpenBSD/h;${g;p;}' /var/run/dmesg.boot )" | 
|          done | 
  | 
|   | 
  | 
|          [[ -n $_file ]] && chown root "$_file" | 
         grep -v '^[[:space:]]*#' "$FWPATTERNS" | | 
|   | 
             while read -r _d _m; do | 
|   | 
                 [ "$_d" = "$_last" ] && continue | 
|   | 
                 [ "$_m" ]             || _m="${_nl}${_d}[0-9] at " | 
|   | 
                 [ "$_m" = "${_m#^}" ] || _m="${_nl}${_m#^}" | 
|   | 
  | 
|          return $_rc | 
                 if [[ $_dmesgtail = *$_m* ]]; then | 
|   | 
                         echo "$_d" | 
|   | 
                         _last="$_d" | 
|   | 
                 fi | 
|   | 
             done | 
|  } | 
 } | 
|   | 
  | 
|  unpriv() { | 
 firmware_filename() { | 
|          do_as _sndio "$@" | 
         local _f | 
|   | 
         _f="$( sed -n "s/.*(\($1-firmware-.*\.tgz\)).*/\1/p" "$CFILE" | sed '$!d' )" | 
|   | 
         ! [ "$_f" ] && echo "Unable to find firmware for $1" >&2 && return 1 | 
|   | 
         echo "$_f" | 
|  } | 
 } | 
|   | 
  | 
|  unpriv2() { | 
 firmware_devicename() { | 
|          do_as _file "$@" | 
         local _d="${1##*/}" | 
|   | 
         _d="${_d%-firmware-*}" | 
|   | 
         echo "$_d" | 
|  } | 
 } | 
|   | 
  | 
|  set -A _KERNV -- $( scan_dmesg '/^OpenBSD \([1-9][0-9]*\.[0-9]\)\([^ ]*\) .*/ { s//\1 \2/p; q; }' ) | 
 installed_firmware() { | 
|  VNAME=${_KERNV[0]} | 
         local _pre="$1" _match="$2" _post="$3" _firmware | 
|  OSDIR=$VNAME | 
         set -sA _firmware -- $( | 
|  if ((${#_KERNV[*]} > 1)) && [ "$_KERNV[1]" = "-current" -o "$_KERNV[1]" = "-beta" ]; then | 
             set +o noglob | 
|          OSDIR=snapshots | 
             grep -Fxl '@option firmware' \ | 
|  fi | 
                 "${DESTDIR}/var/db/pkg/"$_pre"$_match"$_post"/+CONTENTS" \ | 
|   | 
                 2>/dev/null || true | 
|   | 
             set -o noglob | 
|   | 
         ) | 
|   | 
  | 
|  FWURL=http://firmware.openbsd.org/firmware/${OSDIR} | 
         [ "${_firmware[*]:-}" ] || return 0 | 
|  PKGDIR=${DESTDIR}/var/db/pkg | 
         for fw in "${_firmware[@]}"; do | 
|  PATTERNS="file:${0%/*}/firmware_patterns" | 
                 fw="${fw%/+CONTENTS}" | 
|   | 
                 echo "${fw##*/}" | 
|   | 
         done | 
|   | 
 } | 
|   | 
  | 
|  drivers=$( | 
 detect_firmware() { | 
|          last='' | 
         local _devices _last='' _d | 
|          ftp -D "Detecting" -Vmo- $PATTERNS | | 
  | 
|          while read d m; do | 
         set -sA _devices -- $( | 
|                  grep=grep | 
             firmware_in_dmesg | 
|                  [ "$last" = "$d" ] && continue | 
             for _d in $( installed_firmware '*' '-firmware-' '*' ); do | 
|                  [ "$m" ] || m="^$d[0-9][0-9]* at " | 
                 firmware_devicename "$_d" | 
|                  [ "$m" = "${m#^}" ] && grep=fgrep | 
             done | 
|                  $grep -q "$m" /var/run/dmesg.boot || continue | 
         ) | 
|                  echo $d | 
  | 
|                  last=$d | 
         [ "${_devices[*]:-}" ] || return 0 | 
|   | 
         for _d in "${_devices[@]}"; do | 
|   | 
                 [ "$_last" = "$_d" ] && continue | 
|   | 
                 echo "$_d" | 
|   | 
                 _last="$_d" | 
|          done | 
         done | 
|  ) | 
 } | 
|   | 
  | 
|  if [ -z "$drivers" ]; then | 
 add_firmware () { | 
|          echo "No devices found which need firmware files to be downloaded." >&2 | 
         local _f="${1##*/}" _pkgname | 
|          exit 0 | 
         FWPKGTMP="$( tmpdir "${DESTDIR}/var/db/pkg/.firmware" )" | 
|  fi | 
         local flags=-VM | 
|   | 
         "$VERBOSE" && flags=-vm | 
|   | 
         ftp -N "${0##/}" -D "Install" "$flags" -o- "file:${1}" | | 
|   | 
                 tar -s ",^\+,${FWPKGTMP}/+," \ | 
|   | 
                     -s ",^firmware,${DESTDIR}/etc/firmware," \ | 
|   | 
                     -C / -zxphf - "+*" "firmware/*" | 
|   | 
  | 
|  tmpdir=${DESTDIR}/tmp/fw_update | 
         _pkgname="$( sed -n '/^@name /{s///p;q;}' "${FWPKGTMP}/+CONTENTS" )" | 
|  [ -e "$tmpdir" ] && rm -rf "$tmpdir" | 
         if [ ! "$_pkgname" ]; then | 
|  mkdir -p "$tmpdir" | 
                 echo "Failed to extract name from $1, partial install" 2>&1 | 
|  cd "$tmpdir" | 
                 rm -rf "$FWPKGTMP" | 
|   | 
                 unset FWPKGTMP | 
|   | 
                 return 1 | 
|   | 
         fi | 
|   | 
  | 
|  # TODO: Drop privs during fetch and verify | 
         # TODO: Should we mark these so real fw_update can -Drepair? | 
|  ftp -D Get -Vm "$FWURL/SHA256.sig" | 
         ed -s "${FWPKGTMP}/+CONTENTS" <<EOL | 
|   | 
 /^@comment pkgpath/ -1a | 
|   | 
 @option manual-installation | 
|   | 
 @option firmware | 
|   | 
 @comment install-script | 
|   | 
 . | 
|   | 
 w | 
|   | 
 EOL | 
|   | 
  | 
|  # Probably should bundle the firmware sigfile on the installer, | 
         chmod 755 "$FWPKGTMP" | 
|  # although we can just get it from the recently installed system. | 
         mv "$FWPKGTMP" "${DESTDIR}/var/db/pkg/${_pkgname}" | 
|  if [ "$DESTDIR" ]; then | 
         unset FWPKGTMP | 
|          sigfile=$( sed -n '/^untrusted comment: verify with \(.*\)$/ { s//\1/p; q; }' SHA256.sig ) | 
 } | 
|          if [ ! -e "/etc/signify/$sigfile" ] \ | 
  | 
|            && [ -e "${DESTDIR}/etc/signify/$sigfile" ]; then | 
 delete_firmware() { | 
|                  cp -a "${DESTDIR}/etc/signify/$sigfile" "/etc/signify/$sigfile" | 
         local _cwd _pkg="$1" _pkgdir="${DESTDIR}/var/db/pkg" | 
|   | 
  | 
|   | 
         # TODO: Check hash for files before deleting | 
|   | 
         "$VERBOSE" && echo "Uninstalling $_pkg" | 
|   | 
         _cwd="${_pkgdir}/$_pkg" | 
|   | 
  | 
|   | 
         if [ ! -e "$_cwd/+CONTENTS" ] || | 
|   | 
             ! grep -Fxq '@option firmware' "$_cwd/+CONTENTS"; then | 
|   | 
                 echo "${0##*/}: $_pkg does not appear to be firmware" >&2 | 
|   | 
                 return 2 | 
|          fi | 
         fi | 
|  fi | 
  | 
|   | 
  | 
|  signify -Ve -x SHA256.sig -m - < SHA256.sig > SHA256 | 
         set -A _remove -- "${_cwd}/+CONTENTS" "${_cwd}" | 
|   | 
  | 
|  for d in $drivers; do | 
         while read -r c g; do | 
|          firmware=$( sed -n "s/.*(\($d-firmware-.*\.tgz\)).*/\1/p" SHA256 ) | 
                 case $c in | 
|          installed=$( installed_firmware $d ) | 
                 @cwd) _cwd="${DESTDIR}$g" | 
|   | 
                   ;; | 
|   | 
                 @*) continue | 
|   | 
                   ;; | 
|   | 
                 *) set -A _remove -- "$_cwd/$c" "${_remove[@]}" | 
|   | 
                   ;; | 
|   | 
                 esac | 
|   | 
         done < "${_pkgdir}/${_pkg}/+CONTENTS" | 
|   | 
  | 
|          for i in $installed; do | 
         # We specifically rm -f here because not removing files/dirs | 
|                  if [ "$firmware" = "$i.tgz" ]; then | 
         # is probably not worth failing over. | 
|                          echo "Firmware for $d already installed ($installed)" | 
         for _r in "${_remove[@]}" ; do | 
|                          continue 2 | 
                 if [ -d "$_r" ]; then | 
|   | 
                         # Try hard not to actually remove recursively | 
|   | 
                         # without rmdir on the install media. | 
|   | 
                         set +o noglob | 
|   | 
                         [ "$_r/*" = "$( echo "$_r"/* )" ] && rm -rf "$_r" | 
|   | 
                         set -o noglob | 
|   | 
                 else | 
|   | 
                         rm -f "$_r" | 
|                  fi | 
                 fi | 
|          done | 
         done | 
|   | 
 } | 
|   | 
  | 
|          mkdir $d | 
 usage() { | 
|   | 
         echo "usage:  ${0##*/} [-d | -D] [-av] [-p path] [driver | file ...]" | 
|   | 
         exit 2 | 
|   | 
 } | 
|   | 
  | 
|          # TODO: Drop privs during fetch and verify | 
 ALL=false | 
|          ftp -D "Get/Verify" -Vmo- "$FWURL/$firmware" | sha256 -bph "$d/h" > "$firmware" | 
 OPT_D= | 
|          fgrep -qx "SHA256 ($firmware) = $(<$d/h)" SHA256 | 
 while getopts :adDnp:v name | 
|   | 
 do | 
|   | 
        case "$name" in | 
|   | 
        a) ALL=true ;; | 
|   | 
        d) DELETE=true ;; | 
|   | 
        D) OPT_D=true ;; | 
|   | 
        n) DRYRUN=true ;; | 
|   | 
        p) LOCALSRC="$OPTARG" ;; | 
|   | 
        v) VERBOSE=true ;; | 
|   | 
        :) | 
|   | 
            echo "${0##*/}: option requires an argument -- -$OPTARG" >&2 | 
|   | 
            usage 2 | 
|   | 
            ;; | 
|   | 
        ?) | 
|   | 
            echo "${0##*/}: unknown option -- -$OPTARG" >&2 | 
|   | 
            usage 2 | 
|   | 
            ;; | 
|   | 
        esac | 
|   | 
 done | 
|   | 
 shift $((OPTIND - 1)) | 
|   | 
  | 
|          # TODO: Check hash for files before deleting | 
 if [ "$LOCALSRC" ]; then | 
|          if [ "$installed" ] && [ -e "${PKGDIR}/$installed/+CONTENTS" ]; then | 
         if [[ $LOCALSRC = @(ftp|http?(s))://* ]]; then | 
|                  echo "Uninstalling $installed" | 
                 FWURL="${LOCALSRC}" | 
|                  cwd=${PKGDIR}/$installed | 
                 LOCALSRC= | 
|   | 
         else | 
|   | 
                 LOCALSRC="${LOCALSRC:#file:}" | 
|   | 
                 ! [ -d "$LOCALSRC" ] && | 
|   | 
                     echo "The path must be a URL or an existing directory" >&2 && | 
|   | 
                     exit 2 | 
|   | 
         fi | 
|   | 
 fi | 
|   | 
  | 
|                  remove="${cwd}/+CONTENTS ${cwd}" | 
 # "Download only" means local dir and don't install | 
|   | 
 if [ "$OPT_D" ]; then | 
|   | 
         INSTALL=false | 
|   | 
         LOCALSRC="${LOCALSRC:-.}" | 
|   | 
 elif [ "$LOCALSRC" ]; then | 
|   | 
         DOWNLOAD=false | 
|   | 
 fi | 
|   | 
  | 
|                  while read c g; do | 
 if [ -x /usr/bin/id ] && [ "$(/usr/bin/id -u)" != 0 ]; then | 
|                          case $c in | 
         echo "need root privileges" >&2 | 
|                          @cwd) cwd=$g | 
         exit 1 | 
|                            ;; | 
 fi | 
|                          @*) continue | 
  | 
|                            ;; | 
  | 
|                          *)  remove="$cwd/$c $remove" | 
  | 
|                            ;; | 
  | 
|                          esac | 
  | 
|                  done < "${PKGDIR}/$installed/+CONTENTS" | 
  | 
|   | 
  | 
|                  for r in $remove ; do | 
 set -sA devices -- "$@" | 
|                          if [ -d "$r" ]; then | 
  | 
|                                  # Try hard not to actually remove recursively | 
 if "$DELETE"; then | 
|                                  # without rmdir on the install media. | 
         [ "$OPT_D" ] && usage 22 | 
|                                  [ "$r/*" = $( echo "$r"/* ) ] && rm -rf "$r" | 
  | 
|   | 
         set -A installed | 
|   | 
         if [ "${devices[*]:-}" ]; then | 
|   | 
                 "$ALL" && usage 22 | 
|   | 
  | 
|   | 
                 set -A installed -- $( | 
|   | 
                     for d in "${devices[@]}"; do | 
|   | 
                         f="${d##*/}"  # only care about the name | 
|   | 
                         f="${f%.tgz}" # allow specifying the package name | 
|   | 
                         [ "$( firmware_devicename "$f" )" = "$f" ] && f="$f-firmware" | 
|   | 
  | 
|   | 
                         set -A i -- $( installed_firmware '' "$f-" '*' ) | 
|   | 
  | 
|   | 
                         if [ "${i[*]:-}" ]; then | 
|   | 
                                 echo "${i[@]}" | 
|                          else | 
                         else | 
|                                  rm -f "$r" | 
                                 echo "No firmware found for '$d'" >&2 | 
|                          fi | 
                         fi | 
|   | 
                     done | 
|   | 
                 ) | 
|   | 
         elif "$ALL"; then | 
|   | 
                 set -A installed -- $( installed_firmware '*' '-firmware-' '*' ) | 
|   | 
         fi | 
|   | 
  | 
|   | 
         deleted='' | 
|   | 
         if [ "${installed:-}" ]; then | 
|   | 
                 for fw in "${installed[@]}"; do | 
|   | 
                         if "$DRYRUN"; then | 
|   | 
                                 "$VERBOSE" && echo "Delete $fw" | 
|   | 
                         else | 
|   | 
                                 delete_firmware "$fw" || continue | 
|   | 
                         fi | 
|   | 
                         deleted="$deleted,$( firmware_devicename "$fw" )" | 
|                  done | 
                 done | 
|          fi | 
         fi | 
|   | 
  | 
|          # TODO: Add some details about the install to +CONTENTS like pkg_add | 
         deleted="${deleted:+${deleted#,}}" | 
|          # TODO: Or, maybe we save the firmware someplace and make pkg_add reinstall | 
         echo "${0:##*/}: deleted ${deleted:-none}"; | 
|          echo "Installing $firmware" | 
  | 
|          tar -zxphf "$firmware" -C /etc "firmware/*" | 
         exit | 
|          mkdir -p ${PKGDIR}/${firmware%.tgz}/ | 
 fi | 
|          tar -zxphf "$firmware" -C "${PKGDIR}/${firmware%.tgz}" "+*" | 
  | 
|          ed -s "${PKGDIR}/${firmware%.tgz}/+CONTENTS" <<EOL | 
 if [ ! "$LOCALSRC" ]; then | 
|  /^@comment pkgpath/ -1a | 
     LOCALSRC="$( tmpdir "${DESTDIR}/tmp/${0##*/}" )" | 
|  @option manual-installation | 
     REMOVE_LOCALSRC=true | 
|  @option firmware | 
 fi | 
|  @comment install-script | 
  | 
|  . | 
 CFILE="$LOCALSRC/$CFILE" | 
|  w | 
  | 
|  EOL | 
 if [ "${devices[*]:-}" ]; then | 
|   | 
         "$ALL" && usage 22 | 
|   | 
 else | 
|   | 
         "$VERBOSE" && echo -n "Detecting firmware ..." | 
|   | 
         set -sA devices -- $( detect_firmware ) | 
|   | 
         "$VERBOSE" && | 
|   | 
             { [ "${devices[*]:-}" ] && echo " found." || echo " done." ; } | 
|   | 
 fi | 
|   | 
  | 
|   | 
 [ "${devices[*]:-}" ] || exit | 
|   | 
  | 
|   | 
 if "$DOWNLOAD"; then | 
|   | 
         set +o noclobber # we want to get the latest CFILE | 
|   | 
         fetch "$CFILE" | 
|   | 
         set -o noclobber | 
|   | 
         ! signify -qVep "$FWPUB_KEY" -x "$CFILE" -m "$CFILE" && | 
|   | 
             echo "Signature check of SHA256.sig failed" >&2 && exit 1 | 
|   | 
 elif [ ! -e "$CFILE" ]; then | 
|   | 
         # TODO: We shouldn't need a CFILE if all arguments are files. | 
|   | 
         echo "${0##*/}: $CFILE: No such file or directory" >&2 | 
|   | 
         exit 2 | 
|   | 
 fi | 
|   | 
  | 
|   | 
 added='' | 
|   | 
 updated='' | 
|   | 
 kept='' | 
|   | 
 for f in "${devices[@]}"; do | 
|   | 
         d="$( firmware_devicename "$f" )" | 
|   | 
  | 
|   | 
         if [ "$f" = "$d" ]; then | 
|   | 
                 f=$( firmware_filename "$d" || true ) | 
|   | 
                 [ "$f" ] || continue | 
|   | 
                 f="$LOCALSRC/$f" | 
|   | 
         elif ! "$INSTALL" && ! grep -Fq "($f)" "$CFILE" ; then | 
|   | 
                 echo "Cannot download local file $f" >&2 | 
|   | 
                 exit 2 | 
|   | 
         fi | 
|   | 
  | 
|   | 
         set -A installed -- $( installed_firmware '' "$d-firmware-" '*' ) | 
|   | 
  | 
|   | 
         if "$INSTALL" && [ "${installed[*]:-}" ]; then | 
|   | 
                 for i in "${installed[@]}"; do | 
|   | 
                         if [ "${f##*/}" = "$i.tgz" ]; then | 
|   | 
                                 "$VERBOSE" && echo "Keep $i" | 
|   | 
                                 kept="$kept,$d" | 
|   | 
                                 continue 2 | 
|   | 
                         fi | 
|   | 
                 done | 
|   | 
         fi | 
|   | 
  | 
|   | 
         if [ -e "$f" ]; then | 
|   | 
                 if "$DOWNLOAD"; then | 
|   | 
                         "$VERBOSE" && ! "$INSTALL" && | 
|   | 
                             echo "Keep/Verify ${f##*/}" | 
|   | 
                         "$DRYRUN"  || verify "$f" || continue | 
|   | 
                         "$INSTALL" || kept="$kept,$d" | 
|   | 
                 # else assume it was verified when downloaded | 
|   | 
                 fi | 
|   | 
         elif "$DOWNLOAD"; then | 
|   | 
                 if "$DRYRUN"; then | 
|   | 
                         "$VERBOSE" && echo "Get/Verify ${f##*/}" | 
|   | 
                 else | 
|   | 
                         fetch  "$f" || continue | 
|   | 
                         verify "$f" || continue | 
|   | 
                 fi | 
|   | 
                 "$INSTALL"  || added="$added,$d" | 
|   | 
         elif "$INSTALL"; then | 
|   | 
                 echo "Cannot install ${f##*/}, not found" >&2 | 
|   | 
                 continue | 
|   | 
         fi | 
|   | 
  | 
|   | 
         "$INSTALL" || continue | 
|   | 
  | 
|   | 
         removed=false | 
|   | 
         if [ "${installed[*]:-}" ]; then | 
|   | 
                 for i in "${installed[@]}"; do | 
|   | 
                         "$DRYRUN" || delete_firmware "$i" | 
|   | 
                         removed=true | 
|   | 
                 done | 
|   | 
         fi | 
|   | 
  | 
|   | 
         "$DRYRUN" || add_firmware "$f" | 
|   | 
  | 
|   | 
         f="${f##*/}" | 
|   | 
         f="${f%.tgz}" | 
|   | 
         if "$removed"; then | 
|   | 
                 "$DRYRUN" && "$VERBOSE" && echo "Update $f" | 
|   | 
                 updated="$updated,$d" | 
|   | 
         else | 
|   | 
                 "$DRYRUN" && "$VERBOSE" && echo "Install $f" | 
|   | 
                 added="$added,$d" | 
|   | 
         fi | 
|  done | 
 done | 
|   | 
  | 
|   | 
 added="${added:#,}" | 
|   | 
 updated="${updated:#,}" | 
|   | 
 kept="${kept:#,}" | 
|   | 
 if "$INSTALL"; then | 
|   | 
         echo  "${0##*/}: added ${added:-none}; updated ${updated:-none}; kept ${kept:-none}" | 
|   | 
 else | 
|   | 
         echo  "${0##*/}: downloaded ${added:-none}; kept ${kept:-none}" | 
|   | 
 fi |