#!/usr/local/bin/cbsd
#v12.0.4
CIXARG=""
CIXOPTARG="ver arch target_arch destdir"
MYDESC="Update/upgrade/patch jail basejail/world via official tools"
ADDHELP="

${H3_COLOR}Description${N0_COLOR}:

Classic containers use the basejail as a copy of the base  file system.
The directory containing these files is located in ~cbsd/etc/basejails/.

Like the underlying OS, these files periodically require updates (patch levels: -p1 -p2..)

This script will allow you to correctly update these files through the 
official update utility ( freebsd-update, hbsd-update and so on ).

You can update a specific basejail (just one) by specifying the version. 
If the version is not specified, script scan all directories and attempt to update them all.

! Please note: ! 
This script does not update the baserw=1 containers and/or jails directory.
If you need to update the baserw=1 container, use the 'cbsd jupgrade' script or
set destdir= path.

${H3_COLOR}Options${N0_COLOR}:

 ${N2_COLOR}arch=${N0_COLOR}        - <name>, build non-native architectures.
 ${N2_COLOR}destdir=${N0_COLOR}     - <path>, alternative path to basejail dir.
 ${N2_COLOR}target_arch=${N0_COLOR} - <name>, build non-native target arch.
 ${N2_COLOR}ver=${N0_COLOR}         - set version: '14.4', '15.1';

${H3_COLOR}Examples${N0_COLOR}:

 # cbsd baseupdate
 # cbsd baseupdate ver=15.1

${H3_COLOR}See also${N0_COLOR}:

 cbsd bases --help
 cbsd srcup --help
 cbsd buildworld --help
 cbsd installworld --help
 cbsd world --help
 cbsd install-pkg-world --help
 cbsd removebase --help
 cbsd jupgrade --help

"

. ${subrdir}/nc.subr
. ${system}

ver=
arch=
target_arch=
destdir=

keyprint=
servername=
components=
. ${tools}
cixinit

readconf ${platform}-baseupdate.conf

generate_freebsd_config()
{
	local _res=

	# validate mandatory variables
	for i in keyprint servername components; do
		_res=
		eval _res="\$$i"
		[ -z "${_res}" ] && err 1 "${N1_COLOR}baseupdate generate_freebsd_config error: empty variable ${N2_COLOR}${i}${N1_COLOR}. please use ${platform}-baseupdate.conf to setup${N0_COLOR}"
	done

	${CAT_CMD} << EOF > "${1}"
KeyPrint ${keyprint}
ServerName ${servername}
Components ${components}
IgnorePaths
IDSIgnorePaths /usr/share/man/cat
IDSIgnorePaths /usr/share/man/whatis
IDSIgnorePaths /var/db/locate.database
IDSIgnorePaths /var/log
UpdateIfUnmodified /etc/ /var/ /root/ /.cshrc /.profile
MergeChanges /etc/ /boot/device.hints
EOF
}

update_base()
{
	local _i= _res= _cmd=

	sqlfile="local"
	local _mod_count=0

	_sql="SELECT platform,name,arch,targetarch,ver FROM bsdbase"

	# when user specified several parameters,
	# add this as modifiers to narrow down the conditions for an exact result.
	# for example when ver= specidied, we got: "WHERE ver=X"

	for i in ver arch target_arch; do
		_res=
		eval _res="\$$i"
		[ -z "${_res}" ] && continue
		case ${_mod_count} in
			0)
				# first modificator
				_sql="${_sql} WHERE ${i}=\"${_res}\""
				;;
			*)
				# append modificator, concat with AND
				_sql="${_sql} AND ${i}=\"${_res}\""
				;;
		esac
		_mod_count=$(( _mod_count + 1 ))
	done

	#echo "[debug]: ${_sql}"
	local sqldelimer=" "

	cbsdsqlro ${sqlfile} ${_sql} | while read _platform _name _arch _targetarch _ver; do
		base="${_name}_${_arch}_${_targetarch}_${_ver}"
		basepath=${workdir}/basejail/${base}
		if [ ! -r ${basepath}/bin/sh ]; then
			${ECHO} "${N1_COLOR}No such /bin/sh in: ${N2_COLOR}${basepath}${N1_COLOR}. Bad dir/hier? Skipped${N0_COLOR}"
			continue
		fi
		printf "${N1_COLOR}Updating ${basepath}: ${N0_COLOR}"

		# set fake env
		set_bsdenv_by_path -p ${basepath} -v ${_ver}
		${UNAME_CMD} -v
		case "${platform}" in
			HardenedBSD)
				capture _cmd which hbsd-update
				[ ! -x "${_cmd}" ] && err 1 "${W1_COLOR}${CIX_APP} error: ${N1_COLOR}no such executables in PATH: ${N2_COLOR}hbsd-update${N0_COLOR}"
				${ECHO} "${N1_COLOR}${_cmd} -n -r \"${N2_COLOR}${basepath}${N1_COLOR}\"${N0_COLOR}"
				${_cmd} -n -r "${basepath}"
				;;
			FreeBSD)
				capture _cmd which freebsd-update
				[ ! -x "${_cmd}" ] && err 1 "${W1_COLOR}${CIX_APP} error: ${N1_COLOR}no such executables in PATH: ${N2_COLOR}freebsd-update${N0_COLOR}"
				capture tmpconf ${MKTEMP_CMD}
				trap "${RM_CMD} -f ${update_conf}" HUP INT ABRT BUS TERM EXIT
				generate_freebsd_config "${tmpconf}"
				FBSD_UPDATE="${_cmd} -f ${tmpconf} -b ${basepath} --not-running-from-cron"
				${ECHO} "${N1_COLOR}${FBSD_UPDATE}${N0_COLOR}"
				${ENV_CMD} PAGER=${CAT_CMD} ${FBSD_UPDATE} fetch install
				;;
		esac

		unset_bsdenv
	done
}

. ${subrdir}/time.subr
gettime st_time

update_base

gettime end_time
diff_time=$(( end_time - st_time ))
diff_time=$( displaytime ${diff_time} )
${ECHO} "${N1_COLOR}${CIX_APP} done ${N2_COLOR}in ${diff_time}${N0_COLOR}"

exit 0
