#!/bin/sh
# DF-2462 make_fixed.sh -- build the FIXED kernel for the A/B run:
#   1. boot the guest if it is down (post-S5-panic state is fine; the
#      disk is intact with the baseline harness in /usr/src)
#   2. verify fix.diff applies to the guest's pristine iscsi sources
#      (sha256-gated against the audit tree first)
#   3. apply fix.diff, push the harness, regenerate the TU (the
#      verbatim text is now the PATCHED driver), rebuild, reboot
set -e
cd "$(dirname "$0")"
ROOT=/home/maxx/dfbsd/dfbsd
CFG=$ROOT/dfbsd-qemu/config
SSH="ssh -F $CFG -o ConnectTimeout=8 -o BatchMode=yes dfbsd"
SCP="scp -F $CFG -o ConnectTimeout=8 -o BatchMode=yes"

$ROOT/dfbsd-qemu/vm.sh status >/dev/null 2>&1 || $ROOT/dfbsd-qemu/vm.sh up

# pristine gate (the .orig copies are the audit-tree bytes)
WANT_SM=ec8cb8b085556c897b69c3fe1aa150742d971c8dbf034b5ee77f2c9cab161bf0
WANT_CAM=9f6705907fbc67a7fdc66e3123472f2780e95feb1b750617a8a5e991352dcbf8
D=/usr/src/sys/dev/disk/iscsi/initiator
G1=$(printf 'sha256 %s 2>/dev/null\n' "$D/isc_sm.c.orig" | $SSH /bin/sh 2>/dev/null | awk '{print $4}')
G2=$(printf 'sha256 %s 2>/dev/null\n' "$D/isc_cam.c.orig" | $SSH /bin/sh 2>/dev/null | awk '{print $4}')
if [ "$G1" != "$WANT_SM" ] || [ "$G2" != "$WANT_CAM" ]; then
	echo "pristine gate FAILED: isc_sm.c $G1 isc_cam.c $G2" >&2
	exit 1
fi
echo "pristine gate OK (.orig copies match the audit tree)"

rsh() { printf '%s\n' "$1" | $SSH /bin/sh; }

# clean slate: push PRISTINE .orig copies from the audit tree (the
# guest's .orig set may have been created from modified files by an
# earlier run), then restore + apply fix.diff + verify (guest script)
rsh "mkdir -p $D"
for f in isc_sm.c isc_cam.c iscsi_subr.c isc_subr.c iscsi.c iscsi.h iscsivar.h; do
	$SCP "$ROOT/sys/dev/disk/iscsi/initiator/$f" "dfbsd:$D/$f.orig" >/dev/null
done
$SCP fix.diff dfbsd:/tmp/df2462_fix.diff >/dev/null
$SCP /tmp/df2462_applyfix.sh dfbsd:/tmp/df2462_applyfix.sh >/dev/null
rsh 'sh /tmp/df2462_applyfix.sh' | tee fixed_gate.log

$SCP df_pre.c df_post.c gen.sh dfbsd:$D/ >/dev/null
rsh "sh $D/gen.sh" > gen_fixed.log 2>&1
cat gen_fixed.log

echo '=== nativekernel (fixed, detached) ==='
rsh 'rm -f /root/build.ok /root/build.fail /root/build.log'
rsh 'cd /usr/src && nohup make -j6 nativekernel KERNCONF=X86_64_GENERIC > /root/build.log 2>&1 < /dev/null && touch /root/build.ok || touch /root/build.fail' \
    > /dev/null 2>&1 &
i=0
while [ $i -lt 3600 ]; do
	sleep 10
	if rsh 'test -f /root/build.ok || test -f /root/build.fail' 2>/dev/null; then
		break
	fi
	i=$((i + 10))
	if [ $((i % 120)) -eq 0 ]; then echo "... building (${i}s)"; fi
done
$SCP dfbsd:/root/build.log fix_build.log >/dev/null
if ! rsh 'test -f /root/build.ok' 2>/dev/null; then
	echo 'FIXED BUILD FAILED -- last 100 lines:'
	tail -100 fix_build.log
	exit 1
fi
echo "fixed kernel build ok ($(wc -l < fix_build.log) lines)"

rsh 'cd /usr/src && make installkernel KERNCONF=X86_64_GENERIC' \
	> fix_installkernel.log 2>&1
tail -2 fix_installkernel.log

echo '=== rebooting into the FIXED kernel ==='
rsh 'reboot' > /dev/null 2>&1 || true
sleep 20
i=0
while [ $i -lt 240 ]; do
	sleep 5
	if $ROOT/dfbsd-qemu/vm.sh status >/dev/null 2>&1; then break; fi
	i=$((i + 5))
done
sleep 5
rsh 'uname -a'
echo 'FIXED BUILD OK'
