base-files: sysupgrade: exit with no error for --help
[openwrt/openwrt.git] / package / base-files / files / sbin / sysupgrade
index 42f0f6bd22e85a62b28a90597ce9bce38b7e8e49..592b1f378165a078d1a0ac13d4fd39780ac3aaca 100755 (executable)
@@ -4,26 +4,35 @@
 . /lib/functions/system.sh
 . /usr/share/libubox/jshn.sh
 
-# initialize defaults
+# File-local constants
+CONF_TAR=/tmp/sysupgrade.tgz
+ETCBACKUP_DIR=/etc/backup
+INSTALLED_PACKAGES=${ETCBACKUP_DIR}/installed_packages.txt
+COMMAND=/lib/upgrade/do_stage2
+
+# File-local globals
+SAVE_OVERLAY=0
+SAVE_OVERLAY_PATH=
+SAVE_PARTITIONS=1
+SAVE_INSTALLED_PKGS=0
+SKIP_UNCHANGED=0
+CONF_IMAGE=
+CONF_BACKUP_LIST=0
+CONF_BACKUP=
+CONF_RESTORE=
+NEED_IMAGE=
+HELP=0
+TEST=0
+
+# Globals accessed in other files
 export MTD_ARGS=""
 export MTD_CONFIG_ARGS=""
 export INTERACTIVE=0
 export VERBOSE=1
 export SAVE_CONFIG=1
-export SAVE_OVERLAY=0
-export SAVE_OVERLAY_PATH=
-export SAVE_PARTITIONS=1
-export SAVE_INSTALLED_PKGS=0
-export SKIP_UNCHANGED=0
-export CONF_IMAGE=
-export CONF_BACKUP_LIST=0
-export CONF_BACKUP=
-export CONF_RESTORE=
-export NEED_IMAGE=
-export HELP=0
+export IGNORE_MINOR_COMPAT=0
 export FORCE=0
-export TEST=0
-export UMOUNT_ETCBACKUP_DIR=0
+export CONFFILES=/tmp/sysupgrade.conffiles
 
 # parse options
 while [ -n "$1" ]; do
@@ -32,18 +41,19 @@ while [ -n "$1" ]; do
                -v) export VERBOSE="$(($VERBOSE + 1))";;
                -q) export VERBOSE="$(($VERBOSE - 1))";;
                -n) export SAVE_CONFIG=0;;
-               -c) export SAVE_OVERLAY=1 SAVE_OVERLAY_PATH=/etc;;
-               -o) export SAVE_OVERLAY=1 SAVE_OVERLAY_PATH=/;;
-               -p) export SAVE_PARTITIONS=0;;
-               -k) export SAVE_INSTALLED_PKGS=1;;
-               -u) export SKIP_UNCHANGED=1;;
-               -b|--create-backup) export CONF_BACKUP="$2" NEED_IMAGE=1; shift;;
-               -r|--restore-backup) export CONF_RESTORE="$2" NEED_IMAGE=1; shift;;
-               -l|--list-backup) export CONF_BACKUP_LIST=1;;
-               -f) export CONF_IMAGE="$2"; shift;;
+               -c) SAVE_OVERLAY=1 SAVE_OVERLAY_PATH=/etc;;
+               -o) SAVE_OVERLAY=1 SAVE_OVERLAY_PATH=/;;
+               -p) SAVE_PARTITIONS=0;;
+               -k) SAVE_INSTALLED_PKGS=1;;
+               -u) SKIP_UNCHANGED=1;;
+               -b|--create-backup) CONF_BACKUP="$2" NEED_IMAGE=1; shift;;
+               -r|--restore-backup) CONF_RESTORE="$2" NEED_IMAGE=1; shift;;
+               -l|--list-backup) CONF_BACKUP_LIST=1;;
+               -f) CONF_IMAGE="$2"; shift;;
                -F|--force) export FORCE=1;;
-               -T|--test) export TEST=1;;
-               -h|--help) export HELP=1; break;;
+               -T|--test) TEST=1;;
+               -h|--help) HELP=1; break;;
+               --ignore-minor-compat-version) export IGNORE_MINOR_COMPAT=1;;
                -*)
                        echo "Invalid option: $1" >&2
                        exit 1
@@ -53,14 +63,7 @@ while [ -n "$1" ]; do
        shift;
 done
 
-export CONFFILES=/tmp/sysupgrade.conffiles
-export CONF_TAR=/tmp/sysupgrade.tgz
-export ETCBACKUP_DIR=/etc/backup
-export INSTALLED_PACKAGES=${ETCBACKUP_DIR}/installed_packages.txt
-
-IMAGE="$1"
-
-[ -z "$IMAGE" -a -z "$NEED_IMAGE" -a $CONF_BACKUP_LIST -eq 0 -o $HELP -gt 0 ] && {
+print_help() {
        cat <<EOF
 Usage: $0 [<upgrade-option>...] <image file or URL>
        $0 [-q] [-i] [-c] [-u] [-o] [-k] <backup-command> <file>
@@ -80,6 +83,8 @@ upgrade-option:
                     Verify image and config .tar.gz but do not actually flash.
        -F | --force
                     Flash image even if image checks fail, this is dangerous!
+       --ignore-minor-compat-version
+                    Flash image even if the minor compat version is incompatible.
        -q           less verbose
        -v           more verbose
        -h | --help  display this help
@@ -98,9 +103,20 @@ backup-command:
                     sysupgrade -b. Does not create a backup file.
 
 EOF
-       exit 1
 }
 
+IMAGE="$1"
+
+if [ $HELP -gt 0 ]; then
+       print_help
+       exit 0
+fi
+
+if [ -z "$IMAGE" -a -z "$NEED_IMAGE" -a $CONF_BACKUP_LIST -eq 0 ]; then
+       print_help
+       exit 1
+fi
+
 [ -n "$IMAGE" -a -n "$NEED_IMAGE" ] && {
        cat <<-EOF
                -b|--create-backup and -r|--restore-backup do not perform a firmware upgrade.
@@ -127,16 +143,23 @@ list_changed_conffiles() {
        list_conffiles | while read file csum; do
                [ -r "$file" ] || continue
 
-               echo "${csum}  ${file}" | sha256sum -sc - || echo "$file"
+               echo "${csum}  ${file}" | busybox sha256sum -sc - || echo "$file"
        done
 }
 
+list_static_conffiles() {
+       local filter=$1
+
+       find $(sed -ne '/^[[:space:]]*$/d; /^#/d; p' \
+               /etc/sysupgrade.conf /lib/upgrade/keep.d/* 2>/dev/null) \
+               \( -type f -o -type l \) $filter 2>/dev/null
+}
+
 add_conffiles() {
        local file="$1"
-       ( find $(sed -ne '/^[[:space:]]*$/d; /^#/d; p' \
-               /etc/sysupgrade.conf /lib/upgrade/keep.d/* 2>/dev/null) \
-               \( -type f -o -type l \) $find_filter 2>/dev/null;
-         list_changed_conffiles ) | sort -u > "$file"
+
+       ( list_static_conffiles "$find_filter"; list_changed_conffiles ) |
+               sort -u > "$file"
        return 0
 }
 
@@ -154,9 +177,7 @@ add_overlayfiles() {
 
                # backup files from /etc/sysupgrade.conf and /lib/upgrade/keep.d, but
                # ignore those aready controlled by opkg conffiles
-               find $(sed -ne '/^[[:space:]]*$/d; /^#/d; p' \
-                       /etc/sysupgrade.conf /lib/upgrade/keep.d/* 2>/dev/null) \
-                       \( -type f -o -type l \) 2>/dev/null | sort -u |
+               list_static_conffiles | sort -u |
                        grep -h -v -x -F -f $conffiles > "$keepfiles"
 
                # backup conffiles, but only those changed if '-u'
@@ -194,7 +215,7 @@ add_overlayfiles() {
 
 if [ $SAVE_OVERLAY = 1 ]; then
        [ ! -d /overlay/upper/etc ] && {
-               echo "Cannot find '/overlay/upper/etc', required for '-c'" >&2
+               echo "Cannot find '/overlay/upper/etc', required for '-c' or '-o'" >&2
                exit 1
        }
        sysupgrade_init_conffiles="add_overlayfiles"
@@ -216,7 +237,9 @@ include /lib/upgrade
 do_save_conffiles() {
        local conf_tar="$1"
 
-       [ -z "$(rootfs_type)" ] && {
+       local umount_etcbackup_dir=0
+
+       [ "$(rootfs_type)" = "tmpfs" ] && {
                echo "Cannot save config while running from ramdisk." >&2
                ask_bool 0 "Abort" && exit
                rm -f "$conf_tar"
@@ -232,12 +255,12 @@ do_save_conffiles() {
                RAMFS="$(mktemp -d -t sysupgrade.XXXXXX)"
                mkdir -p "$RAMFS/upper" "$RAMFS/work"
                mount -t overlay overlay -o lowerdir=$ETCBACKUP_DIR,upperdir=$RAMFS/upper,workdir=$RAMFS/work $ETCBACKUP_DIR &&
-                       UMOUNT_ETCBACKUP_DIR=1 || {
+                       umount_etcbackup_dir=1 || {
                                echo "Cannot mount '$ETCBACKUP_DIR' as tmpfs to avoid touching disk while saving the list of installed packages." >&2
                                ask_bool 0 "Abort" && exit
                        }
 
-               # Format: pkg-name<TAB>{rom,overlay,unkown}
+               # Format: pkg-name<TAB>{rom,overlay,unknown}
                # rom is used for pkgs in /rom, even if updated later
                find /usr/lib/opkg/info -name "*.control" \( \
                        \( -exec test -f /rom/{} \; -exec echo {} rom \; \) -o \
@@ -248,18 +271,21 @@ do_save_conffiles() {
 
        v "Saving config files..."
        [ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V=""
-       tar c${TAR_V}zf "$conf_tar" -T "$CONFFILES" 2>/dev/null
-       if [ "$?" -ne 0 ]; then
+       sed -i -e 's,^/,,' "$CONFFILES"
+       tar c${TAR_V}zf "$conf_tar" -C / -T "$CONFFILES"
+       local err=$?
+       if [ "$err" -ne 0 ]; then
                echo "Failed to create the configuration backup."
                rm -f "$conf_tar"
-               exit 1
        fi
 
-       [ "$UMOUNT_ETCBACKUP_DIR" -eq 1 ] && {
+       [ "$umount_etcbackup_dir" -eq 1 ] && {
                umount "$ETCBACKUP_DIR"
                rm -rf "$RAMFS"
        }
        rm -f "$CONFFILES"
+
+       return "$err"
 }
 
 if [ $CONF_BACKUP_LIST -eq 1 ]; then
@@ -272,7 +298,7 @@ fi
 
 if [ -n "$CONF_BACKUP" ]; then
        do_save_conffiles "$CONF_BACKUP"
-       exit $?
+       exit
 fi
 
 if [ -n "$CONF_RESTORE" ]; then
@@ -282,6 +308,7 @@ if [ -n "$CONF_RESTORE" ]; then
        fi
 
        [ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V=""
+       v "Restoring config files..."
        tar -C / -x${TAR_V}zf "$CONF_RESTORE"
        exit $?
 fi
@@ -294,7 +321,7 @@ type platform_check_image >/dev/null 2>/dev/null || {
 case "$IMAGE" in
        http://*|\
        https://*)
-               wget -O/tmp/sysupgrade.img "$IMAGE"
+               wget -O/tmp/sysupgrade.img "$IMAGE" || exit 1
                IMAGE=/tmp/sysupgrade.img
                ;;
 esac
@@ -340,7 +367,7 @@ if [ -n "$CONF_IMAGE" ]; then
        get_image "$CONF_IMAGE" "cat" > "$CONF_TAR"
        export SAVE_CONFIG=1
 elif ask_bool $SAVE_CONFIG "Keep config files over reflash"; then
-       [ $TEST -eq 1 ] || do_save_conffiles "$CONF_TAR"
+       [ $TEST -eq 1 ] || do_save_conffiles "$CONF_TAR" || exit
        export SAVE_CONFIG=1
 else
        [ $TEST -eq 1 ] || rm -f "$CONF_TAR"
@@ -354,19 +381,19 @@ fi
 install_bin /sbin/upgraded
 v "Commencing upgrade. Closing all shell sessions."
 
-COMMAND='/lib/upgrade/do_stage2'
-
 if [ -n "$FAILSAFE" ]; then
        printf '%s\x00%s\x00%s' "$RAM_ROOT" "$IMAGE" "$COMMAND" >/tmp/sysupgrade
        lock -u /tmp/.failsafe
 else
-       ubus call system sysupgrade "{
-               \"prefix\": $(json_string "$RAM_ROOT"),
-               \"path\": $(json_string "$IMAGE"),
-               \"command\": $(json_string "$COMMAND"),
-               \"options\": {
-                       \"save_config\": $SAVE_CONFIG,
-                       \"save_partitions\": $SAVE_PARTITIONS
-               }
-       }"
+       json_init
+       json_add_string prefix "$RAM_ROOT"
+       json_add_string path "$IMAGE"
+       [ $FORCE -eq 1 ] && json_add_boolean force 1
+       [ $SAVE_CONFIG -eq 1 ] && json_add_string backup "$CONF_TAR"
+       json_add_string command "$COMMAND"
+       json_add_object options
+       json_add_int save_partitions "$SAVE_PARTITIONS"
+       json_close_object
+
+       ubus call system sysupgrade "$(json_dump)"
 fi