#!/bin/bash
### BEGIN INIT INFO
# Provides:            mountfs mountvirtfs $local_fs
# Required-Start:      fstab
# Should-Start:
# Required-Stop:
# Should-Stop:
# Default-Start:       3 4 5
# Default-Stop:
# Short-Description:   Mounts file systems.
# Description:         Mounts file systems.
# X-LFS-Provided-By:   LFS
### END INIT INFO

. /.initrd/initenv
. /etc/init.d/template

MountDev()
{
	if ! mount -t devtmpfs -o mode=755,size=5m udevfs /dev 2>/dev/null; then
		mount -t tmpfs -o mode=755,size=5m udevfs /dev ||
			return 1
	fi

	makenod() { [ -e /dev/$1 ] || mknod /dev/$1 $2 $3 $4; }
	makenod ram     b 1 1
	makenod null    c 1 3
	makenod zero    c 1 5
	makenod full    c 1 7
	makenod random  c 1 8
	makenod kmsg    c 1 11
	makenod systty  c 4 0
	makenod tty0    c 4 0
	makenod tty1    c 4 1
	makenod tty     c 5 0
	makenod console c 5 1
	makenod ptmx    c 5 2
}

MountVirtualFs()
{
	local msg="Mounting filesystem"

	action_shell "$msg [/dev]:" MountDev
	action "$msg [/sys]:"  mount /sys
	action "$msg [/run]:"  mount /run
	modprobe -n efivarfs 2>/dev/null && action "$msg [/sys/firmware/efi/efivars]:"  mount /sys/firmware/efi/efivars

	while read -r l t; do
		[ -e "$l" ] || ln -s "$t" "$l"
	done <<-EOF
	/dev/core   /proc/kcore
	/dev/fd     /proc/self/fd
	/dev/stdin  /proc/self/fd/0
	/dev/stdout /proc/self/fd/1
	/dev/stderr /proc/self/fd/2
	EOF

	mkdir -p /run/lock/subsys /run/user /run/udev /run/systemd

	:> /run/utmp
	chmod 0664 /run/utmp

	touch "$LOCKFILE"
}

MoveFilesystems()
{
	local n
	for n in dev run ${EXPORT_FS-}; do
		[ ! -d "$rootmnt/$n" ] || ! mountpoint -q "/$n" ||
			action "Moving filesystem [/$n]:" mount --move "/$n" "$rootmnt/$n"
	done
}

# Unmount file systems, killing processes if we have to.
UnmountFilesystems()
{
	local sig='' retry delay findmnt msg='' points

	retry="$1"; shift
	delay="$1"; shift
	findmnt="$1"; shift
	umount_types="$1"; shift

	points="$($findmnt)"

	while [ -n "$points" ] && [ "$retry" -gt 0 ]; do
		dsort points $points

		[ "$retry" -eq 3 ] || msg=' (retry)'

		for point in $points; do
			action "Unmounting filesystem$msg [$point]:" umount -fl ${umount_types:+-t $umount_types} "$point"
		done

		points="$($findmnt)"
		[ -n "$points" ] || break

		[ "${BOOTUP-}" != verbose ] || fuser -mv $points
		fuser -km $sig $points >/dev/null

		sleep $delay

		sig=-9
		retry=$(($retry-1))
	done
}

start()
{
	MountVirtualFs
	touch "$LOCKFILE"
}

stop()
{
	# Move some filesystems to real root.
	[ -n "${UMOUNT_ROOTMNT-}" ] || MoveFilesystems

	# Unmount non-/dev tmpfs.
	non_dev_tmpfs()
	{
		findmnt -mno SOURCE,TARGET -t tmpfs |
		while read -r s t; do
			mountpoint -q "$t" ||
				continue
			case "$t" in
				/dev) ;;
				"$rootmnt"|"$rootmnt"/*) [ -z "${UMOUNT_ROOTMNT-}" ] || printf '%s ' "$t" ;;
				*) printf '%s ' "$t" ;;
			esac
		done
	}
	UnmountFilesystems 3 5 non_dev_tmpfs noproc

	# Unmount all the rest.
	non_proc_all()
	{
		findmnt -mno SOURCE,TARGET |
		while read -r s t; do
			mountpoint -q "$t" ||
				continue
			case "$t" in
				/|/proc) ;;
				"$rootmnt"|"$rootmnt"/*) [ -z "${UMOUNT_ROOTMNT-}" ] || printf '%s ' "$t" ;;
				*) printf '%s ' "$t" ;;
			esac
		done
	}
	UnmountFilesystems 3 5 non_proc_all noproc

	rm -f "$LOCKFILE"
}

switch "${1-}"
