#!/bin/bash

cmdline=""
rc_cmdline()
{
    local arg cmd key val
    test -e /proc/cmdline || mount -nt proc proc /proc
    test -n "$cmdline"    || read -t 2 cmdline < /proc/cmdline
    for arg; do
        for cmd in $cmdline ; do
            key="${cmd%%=*}"
            key="${key//-/_}"
            case "${key}" in
            $arg)
                case "$cmd" in
                *=*) val="${cmd#*=}" ;;
                *)   val=yes
                esac
                echo $key=$val
                return 0
            esac
        done
    done
    return 1
}

rc_readonlyroot()
{
    if test -z "${READONLYROOT+x}" ; then
		if rc_cmdline readonlyroot && ! rc_cmdline noreadonlyroot ; then
			READONLYROOT=yes
		fi > /dev/null
		export READONLYROOT
    fi
    test -n "$READONLYROOT"
}


if rc_readonlyroot ; then
	. /etc/sysconfig/readonlyroot
	STATE_DEV=$(rc_cmdline state)
	STATE_DEV=${STATE_DEV#state=}
	SCRATCH_DEV=$(rc_cmdline scratch)
	SCRATCH_DEV=${SCRATCH_DEV#scratch=}

    init_state() {
        if test -n "$STATE_MOUNT" -a -e "$1" -a ! -e "$STATE_MOUNT/$1" ; then
	        echo "Initializing $STATE_MOUNT/$1 from $1"
	        cp -a --parents "$1" "$STATE_MOUNT/"
	    fi
    }

    mount_state() {
	    if test -n "$STATE_MOUNT" -a -e "$STATE_MOUNT/$1" -a -e "$1" ; then
	        mount -v --bind "$STATE_MOUNT/$1" "$1" &&
	        STATE_MOUNT_USED=1
	    fi
    }

    mount_empty() {
	    if test -n "$SCRATCH_MOUNT" -a -e "$1" ; then
	        echo "$1" \
	        | cpio --pass-through --make-directories --quiet "$SCRATCH_MOUNT" &&
	        mount -v --bind "$SCRATCH_MOUNT$1" "$1" &&
	        SCRATCH_MOUNT_USED=1
	    fi
    }

    mount_dirs() {
	    if test -n "$SCRATCH_MOUNT" -a -d "$1" ; then
	        /usr/bin/find "$1" -type d -print0 \
	        | cpio --pass-through --make-directories --null --quiet "$SCRATCH_MOUNT" &&
	        mount -v --bind "$SCRATCH_MOUNT$1" "$1" &&
	        SCRATCH_MOUNT_USED=1
	    fi
    }

    mount_files() {
	    if test -n "$SCRATCH_MOUNT" -a -e "$1" ; then
	        cp -a --parents "$1" "$SCRATCH_MOUNT" &&
	        mount -v --bind "$SCRATCH_MOUNT$1" "$1" &&
	        SCRATCH_MOUNT_USED=1
	    fi
    }

	if test -d "$STATE_DEV" ; then
		# Assume the state filesystem is already mounted (i.e., listed in /etc/fstab).
		STATE_MOUNT=$STATE_DEV
	elif test -n "$STATE_MOUNT" -a -n "$STATE_DEV" ; then
		# Mount state filesystem if a state= kernel command line option is
		# specified.
		echo "Mounting state filesystem ..."
		if ! err=$(mount -v -n $STATE_MOUNT_OPTS $STATE_DEV $STATE_MOUNT 2>&1) &&
		   ! echo "$err" | grep -q "is already mounted on" ; then
		    /bin/false
		    STATE_MOUNT=
		fi
		test -n "$err" && echo "$err" >&2
	else
		STATE_MOUNT=
	fi

	# Allow to override rwtab from the state file system, too.
	for file in /etc/rwtab /etc/rwtab.d ; do
		mount_state "$file"
	done

    if test -n "$SCRATCH_MOUNT" ; then
	    # Mount scratch areas.
	    if test -z "$SCRATCH_DEV" ; then
	        # The default if no scratch= kernel command line option is
	        # specified is a tmpfs scratch file system.
	        SCRATCH_DEV="-t tmpfs scratch"
	    fi

	    echo "Mounting scratch filesystem ..."
	    if err=$(mount -v -n $SCRATCH_MOUNT_OPTS $SCRATCH_DEV $SCRATCH_MOUNT 2>&1) ||
               echo "$err" | grep -q "is already mounted on" ; then
	        rm -rf "$SCRATCH_MOUNT" &>/dev/null
	    else
	        /bin/false
	        SCRATCH_MOUNT=
	    fi
	    test -n "$err" && echo "$err" >&2
    fi

    echo "Bind mounting ${STATE_MOUNT:+state and }scratch data ..."
    for file in /etc/rwtab /etc/rwtab.d/* ; do
	    [ -f $file ] || continue
	    while read type path ; do
	        case "$type" in
	        state)
	            test "$INIT_STATE_AUTOMATICALLY" = yes && init_state "$path"
		        mount_state "$path"
		    ;;
	        empty)
	            mount_empty "$path"
		    ;;
	        files)
	            mount_files "$path"
		    ;;
	        dirs)
	            mount_dirs "$path"
		    ;;
	        '#'* | '')
	    	;;
	        *)
		    echo "$file: Keyword \"$type\" not recognized." >&2
		    ;;
	        esac
	    done < $file
	    if test -n "$STATE_MOUNT" -a -z "$STATE_MOUNT_USED" ; then
	        umount -n "$STATE_MOUNT"
	    fi
	    if test -n "$SCRATCH_MOUNT" -a -z "$SCRATCH_MOUNT_USED" ; then
	        umount -n "$SCRATCH_MOUNT"
	    fi
    done
fi
