#!/bin/sh
#
# Preferred format:
#	root=nfs[4]:[server:]path[:options]
# FIXME: What is the below referring to other than root=dhcp?
#	[root=*] netroot=nfs[4]:[server:]path[:options]
#
# Legacy format:
#	root=/dev/nfs nfsroot=[server:]path[,options]
#
# FIXME: This blurb below refers to only legacy?
# If the 'nfsroot' parameter is not given on the command line or is empty,
# the dhcp root-path is used as [server:]path[:options] or the default
# "/tftpboot/%s" will be used.
#
# If server is unspecified it will be pulled from one of the following
# sources, in order:
#	static ip= option on kernel command line
#	DHCP next-server option
#	DHCP server-id option
#       DHCP root-path option
#
# NFSv4 is only used if explicitly requested; default is NFSv2 or NFSv3
# depending on kernel configuration
#
# root= takes precedence over netroot= if root=nfs[...]
#

# Sadly there's no easy way to split ':' separated lines into variables
netroot_to_var() {
    local v=${1}:
    set --
    while [ -n "$v" ]; do
	set -- "$@" "${v%%:*}"
	v=${v#*:}
    done

    unset nfs server path options

    nfs=$1
    # Ugly: Can't -z test #path after the case, since it might be allowed
    # to be empty for root=nfs
    case $# in
    0|1);;
    2)	path=${2:-error};;
    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:-error};;
    esac
    ;;
    *)	server=$2; path=${3:-error}; 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
}

#Don't continue if root is ok
[ -n "$rootok" ] && return

# This script is sourced, so root should be set. But let's be paranoid
[ -z "$root" ] && root=$(getarg root=)
[ -z "$netroot" ] && netroot=$(getarg netroot=)
[ -z "$nfsroot" ] && nfsroot=$(getarg nfsroot=)

# netroot= cmdline argument must be ignored, but must be used if
# we're inside netroot to parse dhcp root-path
if [ -n "$netroot" ] ; then
    if [ "$netroot" = "$(getarg netroot=)" ] ; then
        warn "Ignoring netroot argument for NFS"
        netroot=$root
    fi
else
    netroot=$root;
fi 

# LEGACY convert nfsroot= is valid only if root=/dev/nfs
if [ -n "$nfsroot" ] ; then
    # @deprecated
    warn "Argument nfsroot is deprecated and might be removed in a future release. See http://apps.sourceforge.net/trac/dracut/wiki/commandline for more information."
    if [ "$(getarg root=)" != "/dev/nfs"  ]; then
	die "Argument nfsroot only accepted for legacy root=/dev/nfs"
    fi
    netroot=nfs:$nfsroot;
fi

case "$netroot" in
    /dev/nfs) netroot=nfs;;
    /dev/*) unset netroot; return;;
# LEGACY: root=<server-ip>:/<path
    [0-9]*:/*|[0-9]*\.[0-9]*\.[0-9]*[!:]|/*)
       netroot=nfs:$netroot;;
esac

# Continue if nfs
case "${netroot%%:*}" in
    nfs|nfs4|/dev/nfs);;
    *) unset netroot; return;;
esac

# Check required arguments
netroot_to_var $netroot
[ "$path" = "error" ] && die "Argument nfsroot must contain a valid path!"

# Set fstype, might help somewhere
fstype=${nfs#/dev/}

# NFS actually supported? Some more uglyness here: nfs3 or nfs4 might not
# be in the module...
if ! incol2 /proc/filesystems $fstype ; then
    modprobe nfs
    incol2 /proc/filesystems $fstype || die "nfsroot type $fstype requested but kernel/initrd does not support nfs"
fi

# Rewrite root so we don't have to parse this uglyness later on again
netroot="$fstype:$server:$path:$options"

# If we don't have a server, we need dhcp
if [ -z "$server" ] ; then
    DHCPORSERVER="1"
fi;

# Done, all good!
rootok=1

# Shut up init error check or make sure that block parser wont get 
# confused by having /dev/nfs[4]
root="$fstype"
