#!/bin/sh
# Checks the root file system like systemd-fsck and Debian's checkroot.sh:
# only while it is mounted read-only and /etc/fstab gives it a pass number.
# Kernel command line: fsck.mode=auto|force|skip, fsck.repair=preen|yes|no,
# forcefsck, fastboot; files /forcefsck, /fastboot.
# Exit status of fsck: 0 or 1 is success, 2 or 3 reboots, 4 and higher fails.
mode=auto
repair=preen
read -r cmdline </proc/cmdline
for a in $cmdline; do
	case $a in
	fsck.mode=*) mode=${a#*=} ;;
	fsck.repair=*) repair=${a#*=} ;;
	forcefsck) mode=force ;;
	fastboot) mode=skip ;;
	esac
done
[ -e /forcefsck ] && mode=force
[ -e /fastboot ] && mode=skip

say() { echo "fsck-root: $*"; }

[ "$mode" = skip ] && { say "skipped, fsck.mode=skip"; exit 0; }
[ -e /run/initramfs/fsck-root ] && { say "checked by the initramfs"; exit 0; }
case ",$(findmnt -n -o OPTIONS /)," in
*,rw,*) say "/ is mounted read-write, not checked"; exit 0 ;;
esac

pass=0
if [ -r /etc/fstab ]; then
	while read -r spec mp _ _ _ p; do
		case $spec in '' | \#*) continue ;; esac
		[ "$mp" = / ] && pass=${p:-0}
	done </etc/fstab
fi
[ "$pass" = 0 ] && { say "no fsck pass for / in /etc/fstab"; exit 0; }

dev=$(findmnt -n -o SOURCE /)
type=$(findmnt -n -o FSTYPE /)
command -v "fsck.$type" >/dev/null 2>&1 || { say "no fsck.$type, $dev not checked"; exit 0; }

case $repair in
yes) opt=-y ;;
no) opt=-n ;;
*) opt=-a ;;
esac
[ "$mode" = force ] && opt="$opt -f"

say "checking $dev ($type)"
# shellcheck disable=SC2086
fsck -T -t "$type" $opt "$dev" </dev/null
rc=$?
if [ "$rc" -ge 4 ]; then
	say "fsck exit $rc, errors left on $dev"
	exit 1
fi
if [ "$rc" -ge 2 ]; then
	say "fsck exit $rc, rebooting"
	reboot
	exit 0
fi
say "fsck exit $rc"
exit 0
