#!/bin/sh

# Copy from parse-nfsroot.sh
root_to_var() {
    local v=${1}:
    set --
    while [ -n "$v" ]; do
	set -- "$@" "${v%%:*}"
	v=${v#*:}
    done

    unset nfs server path options

    # Ugly: Can't -z test $path after the case, since it might be allowed
    # to be empty for root=nfs
    nfs=$1
    case $# in
    0|1);;
    2)	path=$2;;
    3)
    # This is ultra ugly. But we can't decide in which position path
    # sits without checking if the string starts with '/'
    case $2 in
	/*) path=$2; options=$3;;
	*) server=$2; path=$3;;
    esac
    ;;
    *)	server=$2; path=$3; options=$4;
    esac
    
    # Does it really start with '/'?
    [ -n "${path%%/*}" ] && path="error";
    
    #Fix kernel legacy style separating path and options with ','
    if [ "$path" != "${path#*,}" ] ; then
	options=${path#*,}
	path=${path%%,*}
    fi
}

. /lib/dracut-lib.sh

PATH=$PATH:/sbin:/usr/sbin

# Huh? Empty $1?
[ -z "$1" ] && exit 1

# Huh? Empty $2?
[ -z "$2" ] && exit 1

# Huh? Empty $3?
[ -z "$3" ] && exit 1

# root is in the form root=nfs[4]:[server:]path[:options], either from
# cmdline or dhcp root-path
netif="$1"
root="$2"
NEWROOT="$3"

# Continue if nfs prefix
case "${root%%:*}" in
    nfs|nfs4);;
    *) return;;
esac

root_to_var $root

#Load other data that might provide info
[ -f /tmp/net.$netif.override ] && . /tmp/net.$netif.override
[ -f /tmp/dhclient.$netif.dhcpopts ] && . /tmp/dhclient.$netif.dhcpopts

#Empty path means try dhcp root-path, this is ok here since parse-nfsroot.sh
#already takes care of nfs:... formatted root-path
[ -z "$path" ] && root_to_var $nfs:$new_root_path

#Empty path defaults to "/tftpboot/%s" only in nfsroot.txt legacy mode
[ -z "$path" ] && [ "$(getarg root=)" = "/dev/nfs" ] && path="/tftpboot/%s"

if [ -z "$server" ] ; then
    # XXX new_dhcp_next_server is unconfirmed this is an assumption
    for var in $srv $new_dhcp_server_identifier $new_dhcp_next_server $new_root_path '' ; do
	[ -n "$var" ] && server=$var && break;
    done

    # XXX This blindly assumes that if new_root_path has to used that 
    # XXX it really can be used as server
    server=${server%%:*}
fi

[ -z "$server" ] && die "Required parameter 'server' is missing"

# Kernel replaces first %s with host name, and falls back to the ip address
# if it isn't set. Only the first %s is substituted.
if [ "${path#*%s}" != "$path" ]; then
    ip=$(ip -o -f inet addr show $netif)
    ip=${ip%%/*}
    ip=${ip##* }
    read node < /proc/sys/kernel/hostname
    [ "$node" = "(none)" ] && node=$ip
    path=${path%%%s*}$node${path#*%s}
fi

# Look through the options and remove rw/locking options
OLDIFS=$IFS
IFS=,
for f in $options ; do
    [ "$f" = "ro" -o "$f" = "rw" ] && nfsrw=$f && continue
    [ "$f" = "lock" -o "$f" = "nolock" ] && nfslock=$f && continue
    flags=${flags:+$flags,}$f
done
IFS=$OLDIFS
options=$flags

# Override rw/ro if set on cmdline
getarg ro && nfsrw=ro
getarg rw && nfsrw=rw

# Default to ro if unset
[ -z "$nfsrw" ] && nfsrw=ro

options=${options:+$options,}$nfsrw

# Start rpcbind or rpcbind
# FIXME occasionally saw 'rpcbind: fork failed: No such device' -- why?
[ -x /sbin/portmap ] && [ -z "$(pidof portmap)" ] && portmap
[ -x /sbin/rpcbind ] && [ -z "$(pidof rpcbind)" ] && rpcbind

if [ "$nfs" = "nfs4" ]; then
    # Start rpc.statd as mount won't let us use locks on a NFSv4
    # filesystem without talking to it. NFSv4 does locks internally,
    # rpc.lockd isn't needed
    [ -z "$(pidof rpc.statd)" ] && rpc.statd

    # XXX really needed? Do we need non-root users before we start it in
    # XXX the real root image?
    if nfsdomain=$(getarg rd_NFS_DOMAIN); then
        [ -z "$(pidof rpc.idmapd)" ] && rpc.idmapd -d $nfsdomain
    else
        [ -z "$(pidof rpc.idmapd)" ] && rpc.idmapd
    fi

    # XXX Should we loop here?
    mount -t nfs4 -o$options${nfslock+,$nfslock} \
	$server:$path $NEWROOT \
	&& { [ -e /dev/root ] || >/dev/root ; }
else
    # NFSv{2,3} doesn't support using locks as it requires a helper to transfer
    # the rpcbind state to the new root
    [ "$nfslock" = "lock" ] && \
        warn "Locks unsupported on NFSv{2,3}, using nolock" 1>&2

    # XXX Should we loop here?
    { mount -t nfs -o$options${options:+,}nolock,nfsvers=3 $server:$path $NEWROOT || \
    mount -t nfs -o$options${options:+,}nolock,nfsvers=2 $server:$path $NEWROOT ; } \
	&& { [ -e /dev/root ] || >/dev/root ; } 
fi

# inject new exit_if_exists
echo 'settle_exit_if_exists="--exit-if-exists=/dev/root"; rm "$job"' > /initqueue/nfs.sh
# force udevsettle to break
> /initqueue/work


