I did commit a few other fw_update fixes, so if you see any problems
with it, let me know soon, although I probably won't have time to look
until this weekend.

Theo rightly complained that the output from fw_update when the network
isn't available isn't very good.

$ doas fw_update 
fw_update:fw_update: firmware.openbsd.org: no address associated with name
 add none; update none
Cannot fetch http://firmware.openbsd.org/firmware/snapshots/SHA256.sig


We can improve that somewhat in the common case when the network is down
with the patch at the end of this email:

$ doas ksh ./fw_update.sh  
fw_update.sh: firmware.openbsd.org: no address associated with name
Cannot fetch http://firmware.openbsd.org/firmware/snapshots/SHA256.sig

It's not quite as nice when DNS works, and the connection times out:
(I could special case this further though)

$ doas ksh ./fw_update.sh  
fw_update.sh|
Cannot fetch http://firmware.openbsd.org/firmware/snapshots/SHA256.sig (timed 
out)


And when specifying firmware files that doesn't exist it's still really
terrible.

$ doas ksh ./fw_update.sh atus-firmware-1.0p1.tgz intel-firmware-20210608v0.tgz 
fw_update.sh: add atus: Error retrieving 
http://firmware.openbsd.org/firmware/snapshots/atus-firmware-1.0p1.tgz: 404 Not 
Found
 failed (atus-firmware-1.0p1.tgz); update intel: Error retrieving 
http://firmware.openbsd.org/firmware/snapshots/intel-firmware-20210608v0.tgz: 
404 Not Found
 failed (intel-firmware-20210608v0.tgz)
Cannot fetch 
http://firmware.openbsd.org/firmware/snapshots/atus-firmware-1.0p1.tgz
Cannot fetch 
http://firmware.openbsd.org/firmware/snapshots/intel-firmware-20210608v0.tgz

I can tidy that up a bit if I exit early on errors downloading firmware,
but that would mean it never attempted installing a firmware that did
exist.  (that's not part of this patch)

$ doas ksh ./fw_update.sh atus-firmware-1.0p1.tgz intel-firmware-20210608v0.tgz 
fw_update.sh: add atus: Error retrieving 
http://firmware.openbsd.org/firmware/snapshots/atus-firmware-1.0p1.tgz: 404 Not 
Found
Cannot fetch 
http://firmware.openbsd.org/firmware/snapshots/atus-firmware-1.0p1.tgz

I'm not sure how much better it's possible to make this without trapping
all output from external commands and filtering them ourselves.  That
though could mean output that just disappers if something goes wrong
which seems like a bad failure mode.

(I think there are some whitespace fixes I need)

Comments, OK?

Testing with different setups and different levels of verbosity are
welcome.  I have been testing some, but it's easy to miss things.

(what other failure modes am I not considering?)


diff --git a/fw_update.sh b/fw_update.sh
index a379d74..151b16c 100644
--- a/fw_update.sh
+++ b/fw_update.sh
@@ -59,7 +59,7 @@ cleanup() {
        set +o errexit # ignore errors from killing ftp
 
        if [ -d "$FD_DIR" ]; then
-               echo "" >&"$STATUS_FD"
+               [ -e "$FD_DIR/status" ] && echo ""  >&"$STATUS_FD"
                exec 4>&-
 
                [ -s "$FD_DIR/status" ] && cat "$FD_DIR/status"
@@ -112,16 +112,18 @@ fetch() {
        set -o monitor # make sure ftp gets its own process group
        (
        _flags=-vm
+       _name=${0##/}
        case "$VERBOSE" in
-               0|1) _flags=-VM ;;
-                 2) _flags=-Vm ;;
+               0) _flags=-VM; _name="" ;;
+               1) _flags=-VM ;;
+               2) _flags=-Vm ;;
        esac
        if [ -x /usr/bin/su ]; then
                exec /usr/bin/su -s /bin/ksh "$_user" -c \
-                   "/usr/bin/ftp -N '${0##/}' -D 'Get/Verify' $_flags -o- 
'$_src'" > "$_dst"
+                   "/usr/bin/ftp -N '$_name' -D 'Get/Verify' $_flags -o- 
'$_src'" > "$_dst"
        else
                exec /usr/bin/doas -u "$_user" \
-                   /usr/bin/ftp -N "${0##/}" -D 'Get/Verify' $_flags -o- 
"$_src" > "$_dst"
+                   /usr/bin/ftp -N "$_name" -D 'Get/Verify' $_flags -o- 
"$_src" > "$_dst"
        fi
        ) & FTPPID=$!
        set +o monitor
@@ -165,12 +167,12 @@ fetch() {
 # a blank file indicating failure.
 check_cfile() {
        if [ -e "$CFILE" ]; then
-               [ -s "$CFILE" ] || return 1
+               [ -s "$CFILE" ] || return 2
                return 0
        fi
        if ! fetch_cfile; then
                echo -n > "$CFILE"
-               return 1
+               return 2
        fi
        return 0
 }
@@ -192,7 +194,7 @@ fetch_cfile() {
 }
 
 verify() {
-       check_cfile || return 1
+       check_cfile || return $?
        # The installer sha256 lacks -C, do it by hand
        if ! grep -Fqx "SHA256 (${1##*/}) = $( /bin/sha256 -qb "$1" )" "$CFILE"
        then
@@ -207,7 +209,7 @@ verify() {
 # if VERBOSE is 0, don't show the checksum failure of an existing file.
 verify_existing() {
        local _v=$VERBOSE
-       check_cfile || return 1
+       check_cfile || return $?
 
        ((_v == 0)) && "$DOWNLOAD" && _v=1
        ( VERBOSE=$_v verify "$@" )
@@ -242,7 +244,7 @@ firmware_in_dmesg() {
 }
 
 firmware_filename() {
-       check_cfile || return 1
+       check_cfile || return $?
        sed -n "s/.*(\($1-firmware-.*\.tgz\)).*/\1/p" "$CFILE" | sed '$!d'
 }
 
@@ -514,11 +516,14 @@ if ((VERBOSE)); then
        exec 4>"${FD_DIR}/status"
        STATUS_FD=4
 else
+       # We use the existence of the status file to indicate
+       # whether we should print the final newline.
+       touch "${FD_DIR}/status"
        exec 4>"${FD_DIR}/warn"
        WARN_FD=4
 fi
 
-status "${0##*/}:"
+status "${0##*/}"
 
 if "$DELETE"; then
        [ "$OPT_F" ] && warn "Cannot use -F and -d" && usage
@@ -599,7 +604,20 @@ if [ "${devices[*]:-}" ]; then
 
                verify_existing=true
                if [ "$f" = "$d" ]; then
-                       f=$( firmware_filename "$d" ) || continue
+                       f=$( firmware_filename "$d" ) || {
+                           # Fetching the CFILE here is often the
+                           # first attempt to talk to FWURL
+                           # Fetching the CFILE here is often the
+                           # If it does, no point in continuing.
+                           if (($? > 1)); then
+                               # Clear status, we printed an error instead
+                               rm -f "$FD_DIR/status"
+                               exit 1
+                           fi
+
+                           # If it does, no point in continuing.
+                           continue
+                         }
                        if [ ! "$f" ]; then
                                if "$INSTALL" && unregister_firmware "$d"; then
                                        unregister="$unregister,$d"
@@ -674,10 +692,10 @@ if [ "${devices[*]:-}" ]; then
 fi
 
 if "$INSTALL"; then
-       status " add "
+       status ": add "
        action=Install
 else
-       status " download "
+       status ": download "
        action=Download
 fi
 

Reply via email to