#!/bin/sh

set -u

source /lib/functions/upd_codename.sh
source /lib/functions/upd.sh

prepare_update_factorydata() {
    # Copies the updater to internal storage and creates updater.conf file.

    local updatefile="${1:-}"

    mount -o remount,rw /media/factorydata
    mkdir -p /media/factorydata/.upds
    rm -f /media/factorydata/.upds/*
    local autoupdfile="$(basename $updatefile)"
    autoupdfile="${autoupdfile%.[aA][uU][tT][oO].[uU][pP][dD]}"
    autoupdfile="${autoupdfile%.[uU][pP][dD]}.auto.upd"
    cp "$updatefile" "/media/factorydata/.upds/$autoupdfile"
    echo "EXTRADEVS=mmcblk0p2" > /home/updater.conf
    sync
}

get_mountinfo() {
    local file file_devnr

    if  ! file=$(readlink -f "$1" 2>/dev/null) ||
        ! file_devnr=$(stat -c'%d' "$file");
    then
        return 1  # Missing/invalid filename
    fi

    local file_devmm="$((file_devnr/256)):$((file_devnr%256))" # "major:minor" in decimal
    local file_mtpt=$file prev

    while ! mountpoint -q "$file_mtpt"; do
        prev=$file_mtpt
        file_mtpt=$(dirname "$prev") && [ "$file_mtpt" != "$prev" ] || return 2
    done

    MNT_FILE=${file#${file_mtpt}}
    [ "$MNT_FILE" != "$file" ] || return 3

    # Lookup mount information from /proc/self/mountinfo (refer "man procfs" for format)
    local mid pid devmm root mtpt mtopts extra
    while IFS=' ' read mid pid devmm root mtpt mtopts extra; do
        if [ "$root" = "/" -a "$mtpt" = "$file_mtpt" -a "$devmm" = "$file_devmm" ]; then
            extra=${extra#*- } # strip optional fields and the separator "-"
            MNT_TYPE=$(printf '%s' "$extra" | cut -d' ' -sf1)
            MNT_SRC=$( printf '%s' "$extra" | cut -d' ' -sf2)
            return 0  # Success
        fi
    done </proc/self/mountinfo

    return 4 # Lookup failed
}

get_upd_tags() {
    tar -xOf "$1" update.sh |
    head -n50 |
    cut -f1 |
    cut -f1 -d'#' |
    grep -o '^\(CODENAMELIST\|DATESTAMP\|UPD_PRIORITY\|UPD_FLAGS\)=[^ ]\+'
}

prepare_update_bootstrap() {
    local updfile=$1
    local result=0

    get_mountinfo "$updfile" || result=$?

    if [ $result -eq 0 -a "${MNT_TYPE:-}" = "fuse.shimfs" ]; then
        updfile=/nfs/${updfile#/mnt/}
        get_mountinfo "$updfile" || result=$?
    fi

    local bootstrap_src='/usr/share/update/network-bootstrap.upd'
    local bootstrap_dst='/home/.upds/network-bootstrap.upd'
    local bs_tags upd_size upd_tags tempdir

    if [ $result -ne 0 -o "${MNT_TYPE:-}" != "nfs" ]; then
        [ $result -ne 0 ] || result=10

    elif ! init_codename_re ||
         ! bs_tags=$(get_upd_tags "$bootstrap_src") ||
         ! printf '%s' "$bs_tags" | grep -q "$CODENAME_RE";
    then
        # Bootstrap-updater missing/corrupt or CODENAME not supported.
        result=11

    elif ! upd_size=$(stat -c '%s' "$updfile") ||
         ! upd_tags=$(get_upd_tags "$updfile") ||
         ! printf '%s' "$upd_tags" | grep -q "$CODENAME_RE";
    then
        # Updater missing/corrupt or CODENAME not supported.
        result=12

    elif ! tempdir=$(mktemp -d -p /tmp prepare-update.XXXXXX); then
        result=13

    else
        local mac_list=""
        local cn_list=$(  printf '%s' "$upd_tags" | grep 'CODENAMELIST=' | cut -f2- -d'=')
        local datestamp=$(printf '%s' "$upd_tags" | grep 'DATESTAMP='    | cut -f2- -d'=')
        local priority=$( printf '%s' "$upd_tags" | grep 'UPD_PRIORITY=' | cut -f2- -d'=')
        local flags=$(    printf '%s' "$upd_tags" | grep 'UPD_FLAGS='    | cut -f2- -d'=')

        if ! tar -xf "$bootstrap_src" -C "$tempdir" ||
           ! mkdir -p "$(dirname "$bootstrap_dst")";
        then
            result=14
        elif
            {
                printf '%s\t' \
                    "upd" "nfs" "$MNT_SRC" "$MNT_FILE" "$cn_list" \
                    "$mac_list" "$upd_size" "$datestamp" "$priority" "$flags"
                printf '.\n'
            } > "${tempdir}/resources.txt" &&
            (
                cd "$tempdir" && tar -cf "$bootstrap_dst" *;
            ) &&
            echo 'EXTRADEVS=ubi0:home' > '/home/updater.conf' &&
            append_dummy_updhistory "bootstrap" "$updfile";
        then
            result=0
        else
            result=15
        fi

        rm -r "$tempdir"
    fi

    [ $result -eq 0 ] || printf 'ERROR: prepare_update_bootstrap(%s) = %d\n' "$*" $result >&2
    return $result
}

main() {
    local updatefile="${1:-}"
    local method

    case "${CODENAME}-${SUBFAMILYID}" in
    komodo-*)
        method="${UPDATE_METHOD:-auto}"
        ;;
    *)
        method="${UPDATE_METHOD:-}"
        ;;
    esac

    case "$method" in
    "auto")
        prepare_update_bootstrap   "$updatefile" ||
        prepare_update_factorydata "$updatefile"
        ;;
    *)
        if [[ $updatefile != "*.auto.upd" ]]; then
            mv "$updatefile" "${updatefile%.[uU][pP][dD]}.auto.upd"
        fi
        ;;
    esac
}

main "$@"
