#!/bin/sh
#Copyright: 2026 Aitor <aitor@genuen.org>
#License: CC0-1.0
#Comment: oneshot; invoke with: sv once checkroot.sh

exec 2>&1

ebegin() { [ "${VERBOSE:-}" = no ] || echo "$@"; }
eend() { r=${1:-0}; shift || true; [ "$r" -eq 0 ] || [ "${VERBOSE:-}" = no ] || echo "$*" >&2; return "$r"; }
einfo() { [ "${VERBOSE:-}" = no ] || echo "$@"; }
ewarn() { echo "$@" >&2; }
eerror() { echo "$@" >&2; }

/usr/lib/runit-services/stage1/sv once hostname.sh || exit 1
/usr/lib/runit-services/stage1/sv once mountdevsubfs.sh || exit 1

/usr/lib/runit-services/stage1/sv once keyboard-setup.sh || true


FSCK_LOGFILE=/var/log/fsck/checkroot
[ "$FSCKFIX" ] || FSCKFIX=no
[ "$SULOGIN" ] || SULOGIN=no
. /lib/init/vars.sh
. /lib/init/mount-functions.sh

if command -v setterm >/dev/null 2>&1; then
	setterm=setterm
else
	setterm='true -- '
fi

_want_force_fsck() {
	case "$(findmnt -n -o FSTYPE /)" in
	(ext*) [ -f /forcefsck ] || grep -q -s -w -i "forcefsck" /proc/cmdline ;;
	(*) return 1 ;;
	esac
}

trap "" INT
[ "$SULOGIN" = yes ] && sulogin -t 30 $CONSOLE

KERNEL="$(uname -s)"
MACHINE="$(uname -m)"
read_fstab

ENABLE_SWAP=no
case "$KERNEL" in
  Linux)
	if [ "$NOSWAP" = yes ]; then
		[ "$VERBOSE" = no ] || ewarn "Not activating swap as requested via bootoption noswap."
		ENABLE_SWAP=no
	else
		if [ "$swap_on_lv" = yes ]; then
			[ "$VERBOSE" = no ] || ewarn "Not activating swap on logical volume."
		elif [ "$swap_on_file" = yes ]; then
			[ "$VERBOSE" = no ] || ewarn "Not activating swap on swapfile."
		else
			ENABLE_SWAP=yes
		fi
	fi
	;;
  *)
	ENABLE_SWAP=yes
	;;
esac
if [ "$ENABLE_SWAP" = yes ]; then
	ebegin "Activating swap"
	if [ "$VERBOSE" = no ]; then
		swapon -a -e >/dev/null 2>&1
	else
		swapon -a -v
	fi
	eend $?
fi

KERNEL="$(uname)"
if [ "$rootcheck" = yes ] && [ "$KERNEL" = Linux ]; then
	ddev="$(mountpoint -qx $rootdev)"
	rdev="$(mountpoint -d /)"
	if [ "$ddev" != "$rdev" ] && [ "$ddev" != "4:0" ]; then
		if [ "$(mountpoint -qx /dev/root)" = "4:0" ]; then
			rootdev=/dev/root
		else
			if rm -f /dev/rootdev \
				&& mknod -m 600 /dev/rootdev b ${rdev%:*} ${rdev#*:} \
				&& [ -b /dev/rootdev ]
			then
				rootdev=/dev/rootdev
			else
				rootfatal=yes
			fi
		fi
	fi
fi

if [ "$rootfatal" = yes ]; then
	eerror "The device node $rootdev for the root filesystem is missing or incorrect."
	ewarn "A maintenance shell will now be started. CONTROL-D restarts the system."
	if ! sulogin --force $CONSOLE; then
		eerror "Attempt to start maintenance shell failed. Will restart in 5 seconds."
		sleep 5
	fi
	reboot -f
fi

FSCKCODE=0

if [ -e /run/initramfs/fsck-root ]; then
	rootcheck=no
	if [ -x /sbin/logsave ] && [ -e "${FSCK_LOGFILE}" ]; then
		logsave -s "${FSCK_LOGFILE}" >/dev/null cat /run/initramfs/fsck.log
	else
		eerror "Cannot persist initramfs fsck.log"
	fi
fi

if is_fastboot_active; then
	[ "$rootcheck" = yes ] && ewarn "Fast boot enabled, so skipping root file system check."
	rootcheck=no
fi

if command -v findmnt >/dev/null 2>&1; then
	if [ "$(findmnt -f -n -o FSTYPE /)" = "btrfs" ]; then
		[ "$rootcheck" = yes ] && ewarn "btrfs root detected, so skipping root file system check."
		rootcheck=no
	fi
fi

if [ "$rootcheck" = yes ]; then
	if ! mount -n -o remount,ro $rootdev / \
		&& ! mount -n -o remount,ro -t dummytype $rootdev / 2>/dev/null \
		&& ! mount -n -o remount,ro / 2>/dev/null
	then
		eerror "Cannot check root file system because it is not mounted read-only."
		rootcheck=no
	fi
fi

if [ "$rootcheck" = yes ]; then
	force=""
	_want_force_fsck && force="-f"
	if [ "$FSCKFIX" = yes ]; then fix="-y"; else fix="-a"; fi
	spinner="-C"
	case "$TERM" in
	  dumb|network|unknown|"") spinner="" ;;
	esac
	if [ "${KERNEL}:${MACHINE}" = Linux:s390x ]; then spinner=""; fi

	ebegin "Checking root file system"
	$setterm --msg off
	if [ "$VERBOSE" = no ]; then
		logsave_best_effort fsck $spinner $force $fix -T -t $roottype $rootdev
	else
		logsave_best_effort fsck $spinner $force $fix -T -V -t $roottype $rootdev
	fi
	FSCKCODE=$?
	$setterm --msg on
	eend $FSCKCODE
fi

if [ "$FSCKCODE" -eq 32 ]; then
	ewarn "File system check was interrupted by user"
elif [ "$FSCKCODE" -gt 3 ]; then
	eerror "An automatic fsck of the root filesystem failed."
	ewarn "A maintenance shell will now be started. CONTROL-D restarts the system."
	if ! sulogin --force $CONSOLE; then
		eerror "Attempt to start maintenance shell failed. Will restart in 5 seconds."
		sleep 5
	fi
	reboot -f
elif [ "$FSCKCODE" -gt 1 ]; then
	eerror "fsck corrected errors on root but requested that the system be restarted."
	sleep 5
	reboot -f
fi

if ! mount -n -o remount,$rootopts,$rootmode $fstabroot / 2>/dev/null; then
	mount -n -o remount,$rootopts,$rootmode /
fi

if [ "$rootmode" != "ro" ]; then
	mtab_migrate
fi

if selinux_enabled && [ -x /sbin/restorecon ] && [ -r /etc/mtab ]; then
	restorecon /etc/mtab
fi

rm -f /dev/rootdev

# Remount early virtual filesystems after root is rw
/usr/lib/runit-services/stage1/sv once mountkernfs.sh || true
/usr/lib/runit-services/stage1/sv once mountdevsubfs.sh || true

exit 0
