#!/bin/sh
#v9.2.0
globalconf="${workdir}/cbsd.conf";
MYARG="target"
MYOPTARG="ver basename name destdir stable"
MYDESC="Upgrade for FreeBSD node or cbsd"
ADDHELP="target= kernel, world, node(world+kernel)\n"

[ -f ${globalconf} ] || err 1 "no such conf file";
. ${globalconf}
. ${subr}
. ${inventory}
init $*

. ${buildconf}
. ${mailconf}
. ${color}

# $1 - source dir
# if $destdir set - install to $destdir (default is /boot/kernel)
upgrade_kernel() {
    local _basedir _dest _err
    [ -z "$1" ] && err 1 "Give me source dir"

    _basedir="${1}"

    if [ -n "${destdir}" ]; then
	_dest="${destdir}"
    else
	_dest="/boot/kernel"
    fi

    [ -d "${_dest}.old" ] && rm -rf "${_dest}.old"
    if [ -d "${_dest}" ]; then
	mv "${_dest}" "${_dest}.old"
	echo "Old kernel rotated to ${_dest}.old"
    fi
    echo -e "\033[40;35m Upgrading kernel in ${_dest}. don't interrup the process.\033[0m"
    _err=0
    cp -rP ${KERNELSOURCE}/boot/kernel ${_dest} || _err=$(( _err + 1 ))
    kldxref ${_dest} || _err=$(( _err + 1 ))

    [ ! -f "${_dest}/kernel" ] && _err=$(( _err + 1 ))

    if [ $_err -ne 0 ]; then
	echo "Error while upgrading kernel. Restoring old version"
	rm -rf ${_dest}
	mv "${_dest}.old ${_dest}"
    fi

    sync
}

# $1 -source
# if $destdir set - install to $destdir (default is /)
upgrade_world() {
    set -e
    local _basedir _dest _excludedata
    [ -z "$1" ] && err 1 "Give me source dir"

    _basedir="${1}"

    if [ -n "${destdir}" ]; then
	_dest="${destdir}"
    else
        _dest="/"
    fi

_excludedata="${_basedir}/.cshrc.*|\
${_basedir}/etc.*|\
${_basedir}/root.*|\
${_basedir}/dev.*|"

    set +o errexit
    cd ${_basedir} && find -E . ! -name . \( -type f -or -type d -or -type l \) -and -not -regex \"${_excludedata}\" -print |sed 's/^\.\///g'| while read _f; do
	[ "`stat -f %Sf ${_dest}${_f} ||true`" = "schg" ] && chflags noschg ${_dest}${_f}
    # here is place for IDS/checksum map for rollback operation
    done
    set -o errexit
    echo -e "\033[40;35mUpgrading world in ${_dest}. don't interrupt the process.\033[0m"
#    cd ${_basedir} && find -E . ! -name . \( -type f -or -type d -or -type l \) -and -not -regex \"${_excludedata}\" -exec pax -p eme -X -rwl {} ${_dest} \;
#    cd ${_basedir} && find -E . ! -name . \( -type f -or -type d -or -type l \) -and -not -regex \"${_excludedata}\" -print| cpio -pdmu ${_dest}
#    cd ${_basedir} && pax -c \"${_excludedata}\" -p eme -X -rw {} ${_dest}
    cd ${_basedir} && find -E ${_basedir} \( -type f -or -type d -or -type l \) -and -not -regex \"${_excludedata}\" -print |sed s:${_basedir}:./:g |cpio -pdmu ${_dest}
    sync
}


check_world() {

    if [ -z "${basename}" ]; then
	BASESOURCE="${basejaildir}/${basejailpref}_${arch}_${ver}"
    else
	BASESOURCE="${basejaildir}/${basejailpref}_${basename}_${arch}_${ver}"
    fi

    [ ! -d "${BASESOURCE}" ] && err 1 "You have no ${BASESOURCE}. Use cbsd installworld or repo action=get sources=base before upgrade"
}

check_kernel() {

    [ -z "${name}" ] && name="GENERIC"

    if [ -n "${destdir}" ]; then
	KERNELSOURCE="${destdir}"
    else
	if [ -z "${basename}" ]; then
    	    KERNELSOURCE="${basejaildir}/kernel_${name}_${arch}_${ver}"
	else
    	    KERNELSOURCE="${basejaildir}/kernel_${basename}_${name}_${arch}_${ver}"
	fi
    fi

    [ ! -d "${KERNELSOURCE}" ] && err 1 "You have no ${KERNELSOURCE}. Use cbsd installkernel or repo action=get sources=kernel before upgrade"
}

# MAIN

case "${target}" in
"world")
    check_world
    upgrade_world "${BASESOURCE}"
    ;;
"kernel")
    check_kernel
    upgrade_kernel "${KERNELSOURCE}"
    ;;
"node")
    check_world
    check_kernel
    upgrade_world "${BASESOURCE}"
    upgrade_kernel "${KERNELSOURCE}"
    ;;
*)
    echo "Unsupported target"
    ;;
esac
