# -*- mode: sh -*-

# Find kernel flavour and release
KVER=
for flavour in $SUPPORTED_FLAVOURS; do
	KVER="$(dpkg-query -Wf '${Depends}' "linux-image-${flavour}" 2>/dev/null | tr ',' '\n' | sed -n 's/^ *linux-image-\([-a-z0-9+.]*\).*/\1/p')"
	if [ "$KVER" ]; then
		break
	fi
done
if [ -z "$KVER" ]; then
	echo >&2 "E: Test must set SUPPORTED_FLAVOURS and depend on those flavours"
	exit 2
fi

case "$(dpkg --print-architecture)" in
arm64)
	# The Ubuntu arm64 autopkgtest runs rarely into the 1200 seconds timeout.
	QEMU_TIMEOUT=1800
	;;
armhf)
	# qemu-busybox on Ubuntu armhf runs into the 300 seconds timeout.
	QEMU_TIMEOUT=600
	;;
ppc64el)
	# Slowest execution seen in Ubuntu ppc64el autopkgtest: 230 seconds
	QEMU_TIMEOUT=600
	;;
s390x)
	# Slowest execution seen in Ubuntu s390x autopkgtest: 58 seconds
	QEMU_TIMEOUT=120
	;;
*)
	QEMU_TIMEOUT=60
esac

if [ -n "${AUTOPKGTEST_TMP-}" ]; then
	export TMPDIR="${AUTOPKGTEST_TMP}"
fi

BASEDIR="$(mktemp -d -t initramfs-test.XXXXXXXXXX)"

# Skeleton configuration directory
CONFDIR="${BASEDIR}/config"
mkdir -p "${CONFDIR}"
cp conf/initramfs.conf "${CONFDIR}/initramfs.conf"
echo "RESUME=none" >>"${CONFDIR}/initramfs.conf"
mkdir "${CONFDIR}/hooks"
touch "${CONFDIR}/modules"
mkdir "${CONFDIR}/scripts"

# initramfs image file
INITRAMFS="${BASEDIR}/initrd.img"

# root disk image file
ROOTDISK="${BASEDIR}/rootdisk.raw"

# root disk interface type (for qemu) and device name (for Linux)
test -n "${ROOTDISK_QEMU_IF}" || ROOTDISK_QEMU_IF=virtio
test -n "${ROOTDISK_LINUX_NAME}" || ROOTDISK_LINUX_NAME=vda

# Create a root fs with a trivial userspace
ROOTDIR="${BASEDIR}/rootdir"
INIT_MESSAGE='root fs init system started successfully'
for subdir in dev proc run sys usr usr/bin usr/lib/modules usr/lib64 usr/sbin; do
	mkdir -p "${ROOTDIR}/${subdir}"
done
for subdir in bin lib lib64 sbin; do
	ln -s "usr/${subdir}" "${ROOTDIR}/${subdir}"
done
cat >"${ROOTDIR}/sbin/init" <<EOF
#!/bin/sh -e
test -b /dev/${ROOTDISK_LINUX_NAME}
test -d /proc/1
test -d /run/initramfs
test -d /sys/class
test -d /usr/bin
echo '${INIT_MESSAGE}'
poweroff
EOF
chmod a+x "${ROOTDIR}/sbin/init"
cp /usr/lib/klibc/bin/sh "${ROOTDIR}/bin/sh"
cp /usr/lib/klibc/bin/poweroff "${ROOTDIR}/bin/poweroff"
cp "$(dpkg -L libklibc | grep '^/lib/klibc.*\.so$')" "${ROOTDIR}/lib/"

# VM output file
OUTPUT="${BASEDIR}/output.log"

prepare_network_dumping_rootfs() {
	local root_dir="${1-$ROOTDIR}"
	cat >"${root_dir}/sbin/init" <<EOF
#!/bin/sh
echo "I: Executing /sbin/init from root fs"
# Stop the kernel from spamming the output
current_printk=\$(sysctl kernel.printk)
sysctl -w kernel.printk="4 4 1 7"
# Run twice, once for the human, once for the test harness
echo "I: ip addr"
ip addr
echo "I: ip route"
ip route
echo "I: ip -6 route"
ip -6 route
for file in /run/net*.conf; do
	[ -f \$file ] || continue;
	echo "########## \$file ##########"
	cat \$file
	echo "########################################"
done
echo "########## hostname ##########"
hostname
echo "########################################"
echo "########## ip -json addr ##########"
ip -json addr
echo "########################################"
echo "########## ip -json route ##########"
ip -json route
echo "########################################"
echo "########## ip -json -6 route ##########"
ip -json -6 route
echo "########################################"
echo "########## ps -ww aux ##########"
ps -ww aux
echo "########################################"
sysctl -w "\${current_printk}"
echo '${INIT_MESSAGE}'
poweroff
EOF

	. /usr/share/initramfs-tools/hook-functions
	verbose=y
	DESTDIR="$root_dir"
	for binary in /bin/cat /bin/hostname /bin/ps /sbin/ip /sbin/sysctl; do
		copy_exec "$binary"
	done
}

build_initramfs() {
	echo "build_initramfs: /usr/sbin/mkinitramfs -d ${CONFDIR} -o ${INITRAMFS} ${KVER}"
	/usr/sbin/mkinitramfs -d "${CONFDIR}" -o "${INITRAMFS}" "${KVER}"
}

build_fs_ext2() {
	local dir="${1}"
	local disk="${2}"

	# Get directory size
	local blocks="$(du --summarize "${dir}" | cut -f 1)"
	local inodes="$(du --summarize --inodes "${dir}" | cut -f 1)"

	# Add fudge factor
	blocks="$((blocks + 28 + blocks / 4))"
	inodes="$((inodes + 10))"

	# genext2fs writes status messages to stderr; hide that from
	# autopkgtest
	genext2fs 2>&1 -b "${blocks}" -N "${inodes}" -U -d "${dir}" "${disk}"
}

build_rootfs_ext2() {
	build_fs_ext2 "${ROOTDIR}" "${ROOTDISK}"
}

_run_qemu() {
	local extra_append="$1"
	shift

	echo "I: Running qemu (with a timeout of $QEMU_TIMEOUT seconds)..."
	timeout --foreground "$QEMU_TIMEOUT" \
		debian/tests/run-qemu /boot/vmlinu*-"${KVER}" "${INITRAMFS}" \
		"root=/dev/${ROOTDISK_LINUX_NAME} ${extra_append}" -nographic \
		-drive "file=${ROOTDISK},if=${ROOTDISK_QEMU_IF},media=disk,format=raw" \
		${USRDISK:+-drive "file=${USRDISK},if=${USRDISK_QEMU_IF},media=disk,format=raw"} \
		-chardev stdio,id=char0 -serial chardev:char0 "$@" | tee "${OUTPUT}"
}

run_qemu_nocheck() {
	# hide error messages from autopkgtest
	_run_qemu "${1-}" 2>&1
}

run_qemu() {
	_run_qemu "panic=-1 $*" \
		-device "virtio-net-pci,netdev=lan0,mac=52:54:00:65:43:21" \
		-netdev "user,id=lan0,net=10.0.3.0/24,ipv6-net=fec7::/48,hostname=pizza,dnssearch=test,domainname=example.com,bootfile=/path/to/bootfile2" \
		-device "virtio-net-pci,netdev=lan1,mac=52:54:00:12:34:56" \
		-netdev "user,id=lan1,hostname=goulash,dnssearch=example,dnssearch=example.net,domainname=test,bootfile=/path/to/bootfile"
	grep -qF "${INIT_MESSAGE}" "${OUTPUT}"
}

check_output() {
	local msg="$1"
	if ! grep -qF "${msg}" "${OUTPUT}"; then
		echo >&2 "E: Message '${msg}' not found in log output '${OUTPUT}."
		exit 1
	fi
}
