#!/bin/bash -efu

if [ -z "${__bootchain_sh_functions-}" ]; then
__bootchain_sh_functions=1

BC_DEBUG=
BC_LOG_VT=3
BC_DEVICE_TIMEOUT=60

[ ! -s /etc/sysconfig/bootchain ] ||
	. /etc/sysconfig/bootchain

. initrd-sh-functions
. /.initrd/initenv
. shell-signal

message_time=1

if [ "${ROOT-}" = pipeline ]; then
	BC_LOGFILE="${BC_LOGFILE:-/var/log/pipelined.log}"
	mntdir="${mntdir:-/dev/pipeline}"
	pipeline_mode=1
else
	BC_LOGFILE="${BC_LOGFILE:-/var/log/chaind.log}"
	mntdir="${mntdir:-/dev/bootchain}"
	pipeline_mode=
fi

[ -n "$BC_DEBUG" ] && BC_FGVT_ACTIVATE=1 ||
	BC_FGVT_ACTIVATE="${BC_FGVT_ACTIVATE:-7}"
BC_NEXTCHAIN=/.initrd/bootchain/bootchain.next
BC_PASSED=/.initrd/bootchain/passed
BC_TMPFS_SIZE="${BC_TMPFS_SIZE-50%}"
handlerdir=/lib/bootchain
BC_ROOT=/bc-root


check_parameter()
{
	local _v

	eval "_v=\"\${$1-}\""
	[ -n "${_v}" ] ||
		fatal "Parameter '$1' required"
}

get_parameter()
{
	eval "printf '%s' \"\${${1}$callnum-}\""
}

resolve_target()
{
	local target="$1"
	local where="${target%%/*}"
	local n="${#where}"

	target="${target:$n}"

	case "$where" in
	'')
		;;
	pipe[0-9]|pipe[0-9][0-9]|pipe[0-9][0-9][0-9])
		[ -d "$mntdir/dst/step${where:4}" ] ||
			return 0
		target="$(readlink-e "$mntdir/dst/step${where:4}")${target}"
		;;
	step-[1-9]|step-[1-9][0-9]|step-[1-9][0-9][0-9])
		case "$destdir" in
		"$mntdir"/dst/step[0-9]*)
			n="${destdir##*/}"
			n="$(( ${n:4} - ${where:5} ))"
			;;
		*)
			return 0
			;;
		esac
		[ "$n" -ge 0 ] && [ -d "$mntdir/dst/step$n" ] ||
			return 0
		target="$(readlink-e "$mntdir/dst/step$n")${target}"
		;;
	*)
		if [ -z "${prevdir-}" ]; then
			message "no previous step results to use with $name"
			return 0
		fi
		if [ -z "$target" ] &&
		   [ "$where" = DEVNAME ] &&
		   [ -s "$prevdir"/DEVNAME ]
		then
			read -r target <"$prevdir"/DEVNAME ||:
		else
			target="$prevdir/${where#/}${target}"
		fi
		;;
	esac

	printf '%s' "$target"
}

resolve_devname()
{
	local dir="${1-}"
	local devname=

	[ -n "$dir" ] ||
		dir="${prevdir-}"
	[ -d "$dir" ] ||
		return 0

	if [ -s "$dir"/DEVNAME ]; then
		read -r devname <"$dir"/DEVNAME ||:
	elif [ -b "$dir"/dev ] || [ -c "$dir"/dev ]; then
		devname="$(get_majmin "$dir"/dev ||:)"
		devname="/sys/dev/block/$devname/uevent"
		[ -b "$dir"/dev ] ||
			devname="/sys/dev/char/$devname/uevent"
		devname="/dev/$(sed -E -n 's/^DEVNAME=(.*)/\1/p' "$devname" ||:)"
	fi

	[ ! -b "$devname" ] && [ ! -c "$devname" ] ||
		printf '%s' "$devname"
}

debug()
{
	[ -z "$BC_DEBUG" ] ||
		message "[$callnum] $*"
}

enter()
{
	debug "ENTER: $*"
}

leave()
{
	debug "LEAVE: $*"
}

run()
{
	debug "RUN: $*"
	"$@" || return $?
}

fdump()
{
	[ -n "$BC_DEBUG" ] && [ -f "$1" ] ||
		return 0
	{ printf '============================================================\n'
	  cat -- "$1" ||:
	  printf '============================================================\n\n'
	} 1>&2
}

assign()
{
	local _v="" _k="$1" _e="${2-}"

	eval "_v=\"${_e}\""
	eval "${_k}=\"${_e}\""
	debug "LET: ${_k}=\"${_v}\""
}

next_bootchain()
{
	local _v="${1-}"

	printf 'chainsteps="%s"\n' "${_v}" >>"$BC_NEXTCHAIN"
	debug "BOOTCHAIN REPLACED: '${_v}'"
}

is_step_passed()
{
	[ -f "$BC_PASSED/$PROG" ] ||
		return 1
}

launch_step_once()
{
	[ ! -f "$BC_PASSED/$PROG" ] ||
		fatal "this step has been already passed"
}

break_bc_loop()
{
	enter "break_bc_loop"

	:> "$BC_PASSED/chaind"

	leave "break_bc_loop"
}

bc_reboot()
{
	run reboot -f -d
}

bypass_results()
{
	enter "bypass_results"

	local realdir="${1-}"
	local srcdir="${realdir:-$prevdir}"

	if [ -n "$srcdir" ] && [ "$srcdir" != "$destdir" ]; then
		if [ -d "$realdir" ] || [ -L "$prevdir" ] ||
			[ "$srcdir" = "${srcdir#"$mntdir"/}" ]
		then
			run rmdir -- "$destdir" ||:
			run ln -snf -- "$(readlink-e "$srcdir")" "$destdir"
		elif mountpoint -q -- "$prevdir"; then
			run mkdir -p -- "$destdir"
			run mount --move -- "$prevdir" "$destdir"
		else
			run rmdir -- "$destdir" ||:
			run mv -f -- "$prevdir" "$destdir"
		fi
	fi

	leave "bypass_results"
}

initrd_version()
{
	[ ! -s /etc/initrd-release ] ||
		. /etc/initrd-release
	local __version="${VERSION_ID-}"
	printf '%s' "INITRAMFS${__version:+ $__version}"
}

fi # __bootchain_sh_functions
