base-files: use jshn lib for ubus sysupgrade argument generation
[openwrt/staging/dedeckeh.git] / package / base-files / files / sbin / sysupgrade
index 55c323d0017221aa2c079d1cf97908e28baee716..abd34bdcfb6388280e844ce370c60f23d25dc806 100755 (executable)
@@ -2,8 +2,10 @@
 
 . /lib/functions.sh
 . /lib/functions/system.sh
+. /usr/share/libubox/jshn.sh
 
 # initialize defaults
+export MTD_ARGS=""
 export MTD_CONFIG_ARGS=""
 export INTERACTIVE=0
 export VERBOSE=1
@@ -11,6 +13,7 @@ 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
@@ -20,6 +23,7 @@ export NEED_IMAGE=
 export HELP=0
 export FORCE=0
 export TEST=0
+export UMOUNT_ETCBACKUP_DIR=0
 
 # parse options
 while [ -n "$1" ]; do
@@ -31,6 +35,7 @@ while [ -n "$1" ]; do
                -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;;
@@ -50,13 +55,15 @@ 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 ] && {
        cat <<EOF
 Usage: $0 [<upgrade-option>...] <image file or URL>
-       $0 [-q] [-i] [-c] [-u] [-o] <backup-command> <file>
+       $0 [-q] [-i] [-c] [-u] [-o] [-k] <backup-command> <file>
 
 upgrade-option:
        -f <config>  restore configuration from .tar.gz (file or url)
@@ -67,6 +74,8 @@ upgrade-option:
        -u           skip from backup files that are equal to those in /rom
        -n           do not save configuration over reflash
        -p           do not attempt to restore the partition table after flash.
+       -k           include in backup a list of current installed packages at
+                    $INSTALLED_PACKAGES
        -T | --test
                     Verify image and config .tar.gz but do not actually flash.
        -F | --force
@@ -174,6 +183,7 @@ add_overlayfiles() {
                -e '\,^/etc/board.json$,d' \
                -e '\,/[^/]*-opkg$,d' \
                -e '\,^/etc/urandom.seed$,d' \
+               -e "\,^$INSTALLED_PACKAGES$,d" \
                -e '\,^/usr/lib/opkg/.*,d' \
        ) | grep -v -x -F -f $packagesfiles > "$file"
 
@@ -182,9 +192,6 @@ add_overlayfiles() {
        return 0
 }
 
-# hooks
-sysupgrade_image_check="fwtool_check_signature fwtool_check_image platform_check_image"
-
 if [ $SAVE_OVERLAY = 1 ]; then
        [ ! -d /overlay/upper/etc ] && {
                echo "Cannot find '/overlay/upper/etc', required for '-c'" >&2
@@ -218,6 +225,27 @@ do_save_conffiles() {
        run_hooks "$CONFFILES" $sysupgrade_init_conffiles
        ask_bool 0 "Edit config file list" && vi "$CONFFILES"
 
+       if [ "$SAVE_INSTALLED_PKGS" -eq 1 ]; then
+               echo "${INSTALLED_PACKAGES}" >> "$CONFFILES"
+               mkdir -p "$ETCBACKUP_DIR"
+               # Avoid touching filesystem on each backup
+               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 || {
+                               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}
+               # 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 \
+                       \( -exec test -f /overlay/upper/{} \; -exec echo {} overlay \; \) -o \
+                       \( -exec echo {} unknown \; \) \
+                       \) | sed -e 's,.*/,,;s/\.control /\t/' > ${INSTALLED_PACKAGES}
+       fi
+
        v "Saving config files..."
        [ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V=""
        tar c${TAR_V}zf "$conf_tar" -T "$CONFFILES" 2>/dev/null
@@ -227,11 +255,16 @@ do_save_conffiles() {
                exit 1
        fi
 
+       [ "$UMOUNT_ETCBACKUP_DIR" -eq 1 ] && {
+               umount "$ETCBACKUP_DIR"
+               rm -rf "$RAMFS"
+       }
        rm -f "$CONFFILES"
 }
 
 if [ $CONF_BACKUP_LIST -eq 1 ]; then
        run_hooks "$CONFFILES" $sysupgrade_init_conffiles
+       [ "$SAVE_INSTALLED_PKGS" -eq 1 ] && echo ${INSTALLED_PACKAGES} >> "$CONFFILES"
        cat "$CONFFILES"
        rm -f "$CONFFILES"
        exit 0
@@ -261,7 +294,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
@@ -281,20 +314,19 @@ case "$IMAGE" in
                ;;
 esac
 
-export ARGV="$IMAGE"
-export ARGC=1
-
-for check in $sysupgrade_image_check; do
-       ( $check "$IMAGE" ) || {
-               if [ $FORCE -eq 1 ]; then
-                       echo "Image check '$check' failed but --force given - will update anyway!" >&2
-                       break
-               else
-                       echo "Image check '$check' failed." >&2
-                       exit 1
-               fi
-       }
-done
+json_load "$(/usr/libexec/validate_firmware_image "$IMAGE")" || {
+       echo "Failed to check image"
+       exit 1
+}
+json_get_var valid "valid"
+[ "$valid" -eq 0 ] && {
+       if [ $FORCE -eq 1 ]; then
+               echo "Image check failed but --force given - will update anyway!" >&2
+       else
+               echo "Image check failed." >&2
+               exit 1
+       fi
+}
 
 if [ -n "$CONF_IMAGE" ]; then
        case "$(get_magic_word $CONF_IMAGE cat)" in
@@ -319,24 +351,24 @@ if [ $TEST -eq 1 ]; then
        exit 0
 fi
 
-if [ $SAVE_PARTITIONS -eq 0 ]; then
-       touch /tmp/sysupgrade.always.overwrite.bootdisk.partmap
-else
-       rm -f /tmp/sysupgrade.always.overwrite.bootdisk.partmap
-fi
-
 install_bin /sbin/upgraded
 v "Commencing upgrade. Closing all shell sessions."
 
-COMMAND='. /lib/functions.sh; include /lib/upgrade; do_upgrade_stage2'
+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")
-       }"
+       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