Module Name:    othersrc
Committed By:   stacktic
Date:           Wed Jul  8 15:36:46 UTC 2009

Modified Files:
        othersrc/lib/libfsu_mount: Makefile fsu_mount.c
Added Files:
        othersrc/lib/libfsu_mount: getnfsargs.c getnfsargs_small.c iodesc.h
            mount_nfs.c mount_nfs.h udp_xfer.c

Log Message:
Added NFS support to fs-utils


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 othersrc/lib/libfsu_mount/Makefile
cvs rdiff -u -r1.7 -r1.8 othersrc/lib/libfsu_mount/fsu_mount.c
cvs rdiff -u -r0 -r1.1 othersrc/lib/libfsu_mount/getnfsargs.c \
    othersrc/lib/libfsu_mount/getnfsargs_small.c \
    othersrc/lib/libfsu_mount/iodesc.h othersrc/lib/libfsu_mount/mount_nfs.c \
    othersrc/lib/libfsu_mount/mount_nfs.h \
    othersrc/lib/libfsu_mount/udp_xfer.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: othersrc/lib/libfsu_mount/Makefile
diff -u othersrc/lib/libfsu_mount/Makefile:1.5 othersrc/lib/libfsu_mount/Makefile:1.6
--- othersrc/lib/libfsu_mount/Makefile:1.5	Tue Apr 14 23:20:48 2009
+++ othersrc/lib/libfsu_mount/Makefile	Wed Jul  8 15:36:46 2009
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.5 2009/04/14 23:20:48 pooka Exp $
+#	$NetBSD: Makefile,v 1.6 2009/07/08 15:36:46 stacktic Exp $
 #
 
 # XXX: LIBDIR needs to be set before including bsd.own.mk
@@ -30,6 +30,23 @@
 CPPFLAGS+= 	-DMOUNT_NOMAIN -DUSE_UKFS -I${INCSDIR}
 LDFLAGS+= 	-lrump
 
+.ifdef FSU_WITH_NFS
+SRCS+=		mount_nfs.c
+CCPFLAGS+=	-DNFS
+
+.ifndef SMALLPROG
+SRCS+=		getnfsargs.c
+.else
+SRCS+=		udp_xfer.c
+SRCS+=		rpc.c net.c
+SRCS+=		getnfsargs_small.c
+
+.PATH: 		${NETBSDSRCDIR}/sys/lib/libsa
+CPPFLAGS+= 	-I${.CURDIR}  -I${NETBSDSRCDIR}/sys/lib/libsa
+CPPFLAGS+= 	-DNO_PMAP_CACHE
+.endif
+.endif
+
 SHLIB_MAJOR=    0
 SHLIB_MINOR=    0
 

Index: othersrc/lib/libfsu_mount/fsu_mount.c
diff -u othersrc/lib/libfsu_mount/fsu_mount.c:1.7 othersrc/lib/libfsu_mount/fsu_mount.c:1.8
--- othersrc/lib/libfsu_mount/fsu_mount.c:1.7	Thu Apr  9 10:57:31 2009
+++ othersrc/lib/libfsu_mount/fsu_mount.c	Wed Jul  8 15:36:46 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: fsu_mount.c,v 1.7 2009/04/09 10:57:31 stacktic Exp $ */
+/* $NetBSD: fsu_mount.c,v 1.8 2009/07/08 15:36:46 stacktic Exp $ */
 
 /*
  * Copyright (c) 2008 Arnaud Ysmal.  All Rights Reserved.
@@ -41,6 +41,7 @@
 #include <fs/sysvbfs/sysvbfs_args.h>
 #include <fs/tmpfs/tmpfs_args.h>
 #include <fs/udf/udf_mount.h>
+#include <nfs/nfsmount.h>
 
 #include <rump/ukfs.h>
 
@@ -53,6 +54,7 @@
 #include "mount_hfs.h"
 #include "mount_lfs.h"
 #include "mount_msdos.h"
+#include "mount_nfs.h"
 #include "mount_ntfs.h"
 #include "mount_sysvbfs.h"
 #include "mount_tmpfs.h"
@@ -84,6 +86,7 @@
 	struct sysvbfs_args args_sysvbfs;
 	struct tmpfs_args args_tmpfs;
 	struct udf_args args_udf;
+	struct nfs_args args_nfs;
 #ifdef WITH_SYSPUFFS
 	struct syspuffs_args args_syspuffs;
 #endif
@@ -123,6 +126,8 @@
 	  (parseargs_fp)mount_sysvbfs_parseargs,	0 },
 	{ MOUNT_TMPFS,	&args.args_tmpfs,	sizeof(struct tmpfs_args),
 	  (parseargs_fp)mount_tmpfs_parseargs,		FS_NO_AUTODETECT },
+	{ MOUNT_NFS,	&args.args_nfs,		sizeof(struct nfs_args),
+	  (parseargs_fp)mount_nfs_parseargs,		FS_NO_AUTODETECT },
 #ifdef WITH_SYSPUFFS
 	{ MOUNT_PUFFS,	&args.args_syspuffs,	sizeof(struct syspuffs_args),
 	  (parseargs_fp)mount_syspuffs_parseargs,	FS_NO_AUTODETECT },

Added files:

Index: othersrc/lib/libfsu_mount/getnfsargs.c
diff -u /dev/null othersrc/lib/libfsu_mount/getnfsargs.c:1.1
--- /dev/null	Wed Jul  8 15:36:47 2009
+++ othersrc/lib/libfsu_mount/getnfsargs.c	Wed Jul  8 15:36:46 2009
@@ -0,0 +1,378 @@
+/*	$NetBSD: getnfsargs.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $	*/
+
+/*
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1992, 1993, 1994\
+ The Regents of the University of California.  All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)mount_nfs.c	8.11 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: getnfsargs.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <syslog.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_prot.h>
+
+#ifdef ISO
+#include <netiso/iso.h>
+#endif
+
+
+#include <nfs/rpcv2.h>
+#include <nfs/nfsproto.h>
+#include <nfs/nfs.h>
+#include <nfs/nfsmount.h>
+
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <util.h>
+
+#include "mount_nfs.h"
+
+struct nfhret {
+	u_long		stat;
+	long		vers;
+	long		auth;
+	long		fhsize;
+	u_char		nfh[NFSX_V3FHMAX];
+};
+
+static int	xdr_dir(XDR *, char *);
+static int	xdr_fh(XDR *, struct nfhret *);
+
+int
+getnfsargs(char *spec, struct nfs_args *nfsargsp)
+{
+	CLIENT *clp;
+	struct addrinfo hints, *ai_nfs, *ai;
+	int ecode;
+	static struct netbuf nfs_nb;
+	static struct sockaddr_storage nfs_ss;
+	struct netconfig *nconf;
+	const char *netid;
+#ifdef ISO
+	static struct sockaddr_iso isoaddr;
+	struct iso_addr *isop;
+	int isoflag = 0;
+#endif
+	struct timeval pertry, try;
+	enum clnt_stat clnt_stat;
+	int i, nfsvers, mntvers;
+	int retryleft;
+	char *hostp, *delimp;
+	static struct nfhret nfhret;
+	static char nam[MNAMELEN + 1];
+
+	strlcpy(nam, spec, sizeof(nam));
+	if ((delimp = strchr(spec, '@')) != NULL) {
+		hostp = delimp + 1;
+	} else if ((delimp = strrchr(spec, ':')) != NULL) {
+		hostp = spec;
+		spec = delimp + 1;
+	} else {
+		warnx("no <host>:<dirpath> or <dirpath>@<host> spec");
+		return (0);
+	}
+	*delimp = '\0';
+	/*
+	 * DUMB!! Until the mount protocol works on iso transport, we must
+	 * supply both an iso and an inet address for the host.
+	 */
+#ifdef ISO
+	if (!strncmp(hostp, "iso=", 4)) {
+		u_short isoport;
+
+		hostp += 4;
+		isoflag++;
+		if ((delimp = strchr(hostp, '+')) == NULL) {
+			warnx("no iso+inet address");
+			return (0);
+		}
+		*delimp = '\0';
+		if ((isop = iso_addr(hostp)) == NULL) {
+			warnx("bad ISO address");
+			return (0);
+		}
+		memset(&isoaddr, 0, sizeof (isoaddr));
+		memcpy(&isoaddr.siso_addr, isop, sizeof (struct iso_addr));
+		isoaddr.siso_len = sizeof (isoaddr);
+		isoaddr.siso_family = AF_ISO;
+		isoaddr.siso_tlen = 2;
+		isoport = htons(NFS_PORT);
+		memcpy(TSEL(&isoaddr), &isoport, isoaddr.siso_tlen);
+		hostp = delimp + 1;
+	}
+#endif /* ISO */
+
+	/*
+	 * Handle an internet host address.
+	 */
+	memset(&hints, 0, sizeof hints);
+	hints.ai_flags = AI_NUMERICHOST;
+	hints.ai_socktype = nfsargsp->sotype;
+	if (getaddrinfo(hostp, "nfs", &hints, &ai_nfs) != 0) {
+		hints.ai_flags = 0;
+		if ((ecode = getaddrinfo(hostp, "nfs", &hints, &ai_nfs)) != 0) {
+			warnx("can't get net id for host \"%s\": %s", hostp,
+			    gai_strerror(ecode));
+			return (0);
+		}
+	}
+
+	if ((nfsargsp->flags & NFSMNT_NFSV3) != 0) {
+		nfsvers = NFS_VER3;
+		mntvers = RPCMNT_VER3;
+	} else {
+		nfsvers = NFS_VER2;
+		mntvers = RPCMNT_VER1;
+	}
+	nfhret.stat = EACCES;	/* Mark not yet successful */
+
+    for (ai = ai_nfs; ai; ai = ai->ai_next) {
+	/*
+	 * XXX. Need a generic (family, type, proto) -> nconf interface.
+	 * __rpc_*2nconf exist, maybe they should be exported.
+	 */
+	if (nfsargsp->sotype == SOCK_STREAM) {
+		if (ai->ai_family == AF_INET6)	
+			netid = "tcp6";
+		else
+			netid = "tcp";
+	} else {
+		if (ai->ai_family == AF_INET6)
+			netid = "udp6";
+		else
+			netid = "udp";
+	}
+
+	nconf = getnetconfigent(netid);
+
+tryagain:
+	retryleft = retrycnt;
+
+	while (retryleft > 0) {
+		nfs_nb.buf = &nfs_ss;
+		nfs_nb.maxlen = sizeof nfs_ss;
+		if (!rpcb_getaddr(RPCPROG_NFS, nfsvers, nconf, &nfs_nb, hostp)){
+			if (rpc_createerr.cf_stat == RPC_SYSTEMERROR) {
+				nfhret.stat = rpc_createerr.cf_error.re_errno;
+				break;
+			}
+			if (rpc_createerr.cf_stat == RPC_UNKNOWNPROTO) {
+				nfhret.stat = EPROTONOSUPPORT;
+				break;
+			}
+			if ((opflags & ISBGRND) == 0)
+				clnt_pcreateerror(
+				    "mount_nfs: rpcbind to nfs on server");
+		} else {
+			pertry.tv_sec = 30;
+			pertry.tv_usec = 0;
+			/*
+			 * XXX relies on clnt_tcp_create to bind to a reserved
+			 * socket.
+			 */
+			clp = clnt_tp_create(hostp, RPCPROG_MNT, mntvers,
+			     mnttcp_ok ? nconf : getnetconfigent("udp"));
+			if (clp == NULL) {
+				if ((opflags & ISBGRND) == 0) {
+					clnt_pcreateerror(
+					    "Cannot MNT RPC (mountd)");
+				}
+			} else {
+				CLNT_CONTROL(clp, CLSET_RETRY_TIMEOUT,
+				    (char *)&pertry);
+				clp->cl_auth = authsys_create_default();
+				try.tv_sec = 30;
+				try.tv_usec = 0;
+				nfhret.auth = RPCAUTH_UNIX;
+				nfhret.vers = mntvers;
+				clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
+				    xdr_dir, spec, xdr_fh, &nfhret, try);
+				switch (clnt_stat) {
+				case RPC_PROGVERSMISMATCH:
+					if (nfsvers == NFS_VER3 && !force3) {
+						nfsvers = NFS_VER2;
+						mntvers = RPCMNT_VER1;
+						nfsargsp->flags &=
+							~NFSMNT_NFSV3;
+						goto tryagain;
+					} else {
+						errx(1, "%s", clnt_sperror(clp,
+							"MNT RPC"));
+					}
+				case RPC_SUCCESS:
+					auth_destroy(clp->cl_auth);
+					clnt_destroy(clp);
+					retryleft = 0;
+					break;
+				default:
+					/* XXX should give up on some errors */
+					if ((opflags & ISBGRND) == 0)
+						warnx("%s", clnt_sperror(clp,
+						    "bad MNT RPC"));
+					break;
+				}
+			}
+		}
+		if (--retryleft > 0) {
+			if (opflags & BGRND) {
+				opflags &= ~BGRND;
+				if ((i = fork()) != 0) {
+					if (i == -1)
+						err(1, "fork");
+					exit(0);
+				}
+				(void) setsid();
+				(void) close(STDIN_FILENO);
+				(void) close(STDOUT_FILENO);
+				(void) close(STDERR_FILENO);
+				(void) chdir("/");
+				opflags |= ISBGRND;
+			}
+			sleep(60);
+		}
+	}
+	if (nfhret.stat == 0)
+		break;
+    }
+	freeaddrinfo(ai_nfs);
+	if (nfhret.stat) {
+		if (opflags & ISBGRND)
+			exit(1);
+		errno = nfhret.stat;
+		warnx("can't access %s: %s", spec, strerror(nfhret.stat));
+		return (0);
+	}
+#ifdef ISO
+	if (isoflag) {
+		nfsargsp->addr = (struct sockaddr *) &isoaddr;
+		nfsargsp->addrlen = sizeof (isoaddr);
+	} else
+#endif /* ISO */
+	{
+		nfsargsp->addr = (struct sockaddr *) nfs_nb.buf;
+		nfsargsp->addrlen = nfs_nb.len;
+		if (port != 0) {
+			struct sockaddr *sa = nfsargsp->addr;
+			switch (sa->sa_family) {
+			case AF_INET:
+				((struct sockaddr_in *)sa)->sin_port = port;
+				break;
+#ifdef INET6
+			case AF_INET6:
+				((struct sockaddr_in6 *)sa)->sin6_port = port;
+				break;
+#endif
+			default:
+				errx(1, "Unsupported socket family %d",
+				    sa->sa_family);
+			}
+		}
+	}
+	nfsargsp->fh = nfhret.nfh;
+	nfsargsp->fhsize = nfhret.fhsize;
+	nfsargsp->hostname = nam;
+	return (1);
+}
+
+/*
+ * xdr routines for mount rpc's
+ */
+static int
+xdr_dir(XDR *xdrsp, char *dirp)
+{
+	return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
+}
+
+static int
+xdr_fh(XDR *xdrsp, struct nfhret *np)
+{
+	int i;
+	long auth, authcnt, authfnd = 0;
+
+	if (!xdr_u_long(xdrsp, &np->stat))
+		return (0);
+	if (np->stat)
+		return (1);
+	switch (np->vers) {
+	case 1:
+		np->fhsize = NFSX_V2FH;
+		return (xdr_opaque(xdrsp, (caddr_t)np->nfh, NFSX_V2FH));
+	case 3:
+		if (!xdr_long(xdrsp, &np->fhsize))
+			return (0);
+		if (np->fhsize <= 0 || np->fhsize > NFSX_V3FHMAX)
+			return (0);
+		if (!xdr_opaque(xdrsp, (caddr_t)np->nfh, np->fhsize))
+			return (0);
+		if (!xdr_long(xdrsp, &authcnt))
+			return (0);
+		for (i = 0; i < authcnt; i++) {
+			if (!xdr_long(xdrsp, &auth))
+				return (0);
+			if (auth == np->auth)
+				authfnd++;
+		}
+		/*
+		 * Some servers, such as DEC's OSF/1 return a nil authenticator
+		 * list to indicate RPCAUTH_UNIX.
+		 */
+		if (!authfnd && (authcnt > 0 || np->auth != RPCAUTH_UNIX))
+			np->stat = EAUTH;
+		return (1);
+	};
+	return (0);
+}
Index: othersrc/lib/libfsu_mount/getnfsargs_small.c
diff -u /dev/null othersrc/lib/libfsu_mount/getnfsargs_small.c:1.1
--- /dev/null	Wed Jul  8 15:36:47 2009
+++ othersrc/lib/libfsu_mount/getnfsargs_small.c	Wed Jul  8 15:36:46 2009
@@ -0,0 +1,260 @@
+/*	$NetBSD: getnfsargs_small.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $	*/
+
+/*-
+ * Copyright (c) 2006 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ *  Copyright (c) 1993 John Brezak
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: getnfsargs_small.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $");
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <syslog.h>
+
+#include <nfs/rpcv2.h>
+#include <nfs/nfsproto.h>
+#include <nfs/nfs.h>
+#include <nfs/nfsmount.h>
+
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <util.h>
+
+#include "mount_nfs.h"
+
+#include "iodesc.h"
+typedef int32_t n_long;
+#include "rpc.h"
+
+#define RPC_HEADER_WORDS 28	/* more than enough */
+#define FNAME_SIZE 512
+
+struct nfhret {
+	long		fhsize;
+	u_char		nfh[NFSX_V3FHMAX];
+};
+
+/* Ripped from src/sys/arch/i386/stand/libsa/nfs.c */
+static int
+nfs_getrootfh(struct iodesc *d, const char *path, int mntvers, struct nfhret *nfhret)
+{
+	size_t len;
+	struct args {
+		uint32_t len;
+		char	path[FNAME_SIZE];
+	} *args;
+	struct repl {
+		uint32_t errval;
+		u_char	fh[NFSX_V3FHMAX];
+	} *repl;
+	struct {
+		uint32_t h[RPC_HEADER_WORDS];
+		struct args d;
+	} sdata;
+	struct {
+		uint32_t h[RPC_HEADER_WORDS];
+		struct repl d;
+	} rdata;
+	ssize_t cc;
+
+	args = &sdata.d;
+	repl = &rdata.d;
+
+	memset(args, 0, sizeof(*args));
+	len = strlen(path);
+	if (len > sizeof(args->path))
+		len = sizeof(args->path);
+	args->len = htonl(len);
+	memcpy(args->path, path, len);
+	len = 4 + roundup(len, 4);
+
+	cc = rpc_call(d, RPCPROG_MNT, mntvers, RPCMNT_MOUNT,
+	    args, len, repl, sizeof(*repl));
+	if (cc == -1) {
+		/* errno was set by rpc_call */
+		return errno;
+	}
+	if (cc < 4)
+		return EBADRPC;
+	if (repl->errval)
+		return ntohl(repl->errval);
+	nfhret->fhsize = cc;
+	memcpy(nfhret->nfh, repl->fh, sizeof(repl->fh));
+	return 0;
+}
+
+int
+getnfsargs(char *spec, struct nfs_args *nfsargsp)
+{
+	struct addrinfo hints, *ai_nfs;
+	int ecode;
+	int nfsvers, mntvers;
+	char *hostp, *delimp;
+	static struct nfhret nfhret;
+	static char nam[MNAMELEN + 1];
+	struct iodesc d;
+	int nfs_port, rv;
+
+	strlcpy(nam, spec, sizeof(nam));
+	if ((delimp = strchr(spec, '@')) != NULL) {
+		hostp = delimp + 1;
+	} else if ((delimp = strrchr(spec, ':')) != NULL) {
+		hostp = spec;
+		spec = delimp + 1;
+	} else {
+		warnx("no <host>:<dirpath> or <dirpath>@<host> spec");
+		return 0;
+	}
+	*delimp = '\0';
+
+	memset(&hints, 0, sizeof hints);
+	hints.ai_socktype = nfsargsp->sotype;
+
+	if ((ecode = getaddrinfo(hostp, "nfs", &hints, &ai_nfs)) != 0) {
+		warnx("can't get net id for host \"%s\": %s", hostp,
+		    gai_strerror(ecode));
+		return 0;
+	}
+
+	if ((nfsargsp->flags & NFSMNT_NFSV3) != 0) {
+		nfsvers = NFS_VER3;
+		mntvers = RPCMNT_VER3;
+	} else {
+		nfsvers = NFS_VER2;
+		mntvers = RPCMNT_VER1;
+	}
+
+	d.socket = -1;
+	for (d.ai = ai_nfs; ; d.ai = d.ai->ai_next) {
+		if (d.ai == NULL) {
+			if (nfsvers == NFS_VER3 && !force3) {
+				nfsvers = NFS_VER2;
+				mntvers = RPCMNT_VER1;
+				d.ai = ai_nfs;
+				continue;
+			}
+			return 0;
+		}
+		nfs_port = rpc_getport(&d, RPCPROG_NFS, nfsvers);
+		if (nfs_port == -1)
+			continue;
+		if ((rv = nfs_getrootfh(&d, spec, mntvers, &nfhret)) == 0)
+			break;
+		else
+			printf("getrootfh error: %i\n", rv);
+	}
+
+	if (port != 0)
+		nfs_port = port;
+	set_port(d.ai->ai_addr, htons(nfs_port));
+
+	nfsargsp->hostname = nam;
+	nfsargsp->addr = d.ai->ai_addr;
+	nfsargsp->addrlen = d.ai->ai_addrlen;
+
+	nfsargsp->fh = nfhret.nfh;
+	if (nfsvers == NFS_VER3) {
+		nfsargsp->fhsize = ntohl(*(uint32_t *)nfhret.nfh);
+		nfsargsp->fh += 4;
+	} else {
+		nfsargsp->fhsize = NFSX_V2FH;
+		nfsargsp->flags &= ~NFSMNT_NFSV3;
+	}
+	return 1;
+}
Index: othersrc/lib/libfsu_mount/iodesc.h
diff -u /dev/null othersrc/lib/libfsu_mount/iodesc.h:1.1
--- /dev/null	Wed Jul  8 15:36:47 2009
+++ othersrc/lib/libfsu_mount/iodesc.h	Wed Jul  8 15:36:46 2009
@@ -0,0 +1,49 @@
+/*	$NetBSD: iodesc.h,v 1.1 2009/07/08 15:36:46 stacktic Exp $	*/
+
+/*-
+ * Copyright (c) 2006 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _IODESC_H
+#define _IODESC_H
+
+/* An alternative to the definition in sys/lib/libsa/iodesc.h */
+
+typedef	time_t	satime_t;
+typedef	time_t	saseconds_t;
+
+struct addrinfo;
+struct iodesc {
+    struct addrinfo *ai;
+    int             socket;
+    int             destport;
+};
+
+void set_port(struct sockaddr *, int);
+
+#endif
Index: othersrc/lib/libfsu_mount/mount_nfs.c
diff -u /dev/null othersrc/lib/libfsu_mount/mount_nfs.c:1.1
--- /dev/null	Wed Jul  8 15:36:47 2009
+++ othersrc/lib/libfsu_mount/mount_nfs.c	Wed Jul  8 15:36:46 2009
@@ -0,0 +1,537 @@
+/*	$NetBSD: mount_nfs.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $	*/
+
+/*
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1992, 1993, 1994\
+ The Regents of the University of California.  All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)mount_nfs.c	8.11 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: mount_nfs.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <syslog.h>
+
+#ifdef ISO
+#include <netiso/iso.h>
+#endif
+
+#include <nfs/rpcv2.h>
+#include <nfs/nfsproto.h>
+#include <nfs/nfs.h>
+#include <nfs/nfsmount.h>
+
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <util.h>
+
+#include <mntopts.h>
+
+#include "mountprog.h"
+#include "mount_nfs.h"
+
+#define	ALTF_BG		0x00000001
+#define ALTF_CONN	0x00000002
+#define ALTF_DUMBTIMR	0x00000004
+#define ALTF_INTR	0x00000008
+#define ALTF_NFSV3	0x00000020
+#define ALTF_RDIRPLUS	0x00000040
+#define	ALTF_MNTUDP	0x00000080
+#define ALTF_NORESPORT	0x00000100
+#define ALTF_SEQPACKET	0x00000200
+#define ALTF_NQNFS	0x00000400
+#define ALTF_SOFT	0x00000800
+#define ALTF_TCP	0x00001000
+#define ALTF_NFSV2	0x00002000
+#define ALTF_PORT	0x00004000
+#define ALTF_RSIZE	0x00008000
+#define ALTF_WSIZE	0x00010000
+#define ALTF_RDIRSIZE	0x00020000
+#define ALTF_MAXGRPS	0x00040000
+#define ALTF_LEASETERM	0x00080000
+#define ALTF_READAHEAD	0x00100000
+#define ALTF_DEADTHRESH	0x00200000
+#define ALTF_TIMEO	0x00400000
+#define ALTF_RETRANS	0x00800000
+
+static const struct mntopt mopts[] = {
+	MOPT_STDOPTS,
+	MOPT_FORCE,
+	MOPT_UPDATE,
+	MOPT_GETARGS,
+	{ "bg", 0, ALTF_BG, 1 },
+	{ "conn", 0, ALTF_CONN, 1 },
+	{ "dumbtimer", 0, ALTF_DUMBTIMR, 1 },
+	{ "intr", 0, ALTF_INTR, 1 },
+	{ "nfsv3", 0, ALTF_NFSV3, 1 },
+	{ "rdirplus", 0, ALTF_RDIRPLUS, 1 },
+	{ "mntudp", 0, ALTF_MNTUDP, 1 },
+	{ "resport", 1, ALTF_NORESPORT, 1 },
+#ifdef ISO
+	{ "seqpacket", 0, ALTF_SEQPACKET, 1 },
+#endif
+	{ "nqnfs", 0, ALTF_NQNFS, 1 },
+	{ "soft", 0, ALTF_SOFT, 1 },
+	{ "tcp", 0, ALTF_TCP, 1 },
+	{ "nfsv2", 0, ALTF_NFSV2, 1 },
+	{ "port", 0, ALTF_PORT, 1 },
+	{ "rsize", 0, ALTF_RSIZE, 1 },
+	{ "wsize", 0, ALTF_WSIZE, 1 },
+	{ "rdirsize", 0, ALTF_RDIRSIZE, 1 },
+	{ "maxgrps", 0, ALTF_MAXGRPS, 1 },
+	{ "leaseterm", 0, ALTF_LEASETERM, 1 },
+	{ "readahead", 0, ALTF_READAHEAD, 1 },
+	{ "deadthresh", 0, ALTF_DEADTHRESH, 1 },
+	{ "timeo", 0, ALTF_TIMEO, 1 },
+	MOPT_NULL,
+
+};
+
+struct nfs_args nfsdefargs = {
+	.version = NFS_ARGSVERSION,
+	.addr = NULL,
+	.addrlen = sizeof(struct sockaddr_in),
+	.sotype = SOCK_DGRAM,
+	.proto = 0,
+	.fh = NULL,
+	.fhsize = 0,
+	.flags = NFSMNT_NFSV3|NFSMNT_NOCONN|NFSMNT_RESVPORT,
+	.wsize = NFS_WSIZE,
+	.rsize = NFS_RSIZE,
+	.readdirsize = NFS_READDIRSIZE,
+	.timeo = 10,
+	.retrans = NFS_RETRANS,
+	.maxgrouplist = NFS_MAXGRPS,
+	.readahead = NFS_DEFRAHEAD,
+	.leaseterm = 0,	/* Ignored; lease term */
+	.deadthresh = NFS_DEFDEADTHRESH,
+	.hostname = NULL,
+};
+
+#define DEF_RETRY 10000
+
+int retrycnt = DEF_RETRY;
+int opflags = 0;
+int force2 = 0;
+int force3 = 0;
+int mnttcp_ok = 1;
+int port = 0;
+
+static void	shownfsargs(const struct nfs_args *);
+#ifdef ISO
+static struct	iso_addr *iso_addr(const char *);
+#endif
+int	mount_nfs(int argc, char **argv);
+/* void	set_rpc_maxgrouplist(int); */
+static void	usage(void);
+
+#ifndef MOUNT_NOMAIN
+int
+main(int argc, char **argv)
+{
+
+	setprogname(argv[0]);
+	return mount_nfs(argc, argv);
+}
+#endif
+
+int
+mount_nfs_dogetargs(struct nfs_args *nfsargsp, int mntflags, const char *spec)
+{
+	static struct sockaddr_storage sa;
+	char *tspec;
+
+	if ((mntflags & MNT_GETARGS) != 0) {
+		memset(&sa, 0, sizeof(sa));
+		nfsargsp->addr = (struct sockaddr *)&sa;
+		nfsargsp->addrlen = sizeof(sa);
+	} else {
+		if ((tspec = strdup(spec)) == NULL) {
+			return ENOMEM;
+		}
+		if (!getnfsargs(tspec, nfsargsp)) {
+			return 1;
+		}
+		free(tspec);
+	}
+	return 0;
+}
+
+int
+mount_nfs_parseargs(int argc, char *argv[],
+	struct nfs_args *nfsargsp, int *mntflags,
+	char *spec, char *name)
+{
+	char *p;
+	int altflags, num;
+	int c;
+	mntoptparse_t mp;
+
+	*mntflags = 0;
+	altflags = 0;
+	memset(nfsargsp, 0, sizeof(*nfsargsp));
+	*nfsargsp = nfsdefargs;
+	while ((c = getopt(argc, argv,
+	    "23a:bcCdD:g:I:iKL:lm:o:PpqR:r:sTt:w:x:UX")) != -1)
+		switch (c) {
+		case '3':
+		case 'q':
+			if (force2)
+				return EINVAL;
+			force3 = 1;
+			break;
+		case '2':
+			if (force3)
+				return EINVAL;
+			force2 = 1;
+			nfsargsp->flags &= ~NFSMNT_NFSV3;
+			break;
+		case 'a':
+			num = strtol(optarg, &p, 10);
+			if (*p || num < 0)
+				return EINVAL;
+			nfsargsp->readahead = num;
+			nfsargsp->flags |= NFSMNT_READAHEAD;
+			break;
+		case 'b':
+			opflags |= BGRND;
+			break;
+		case 'c':
+			nfsargsp->flags |= NFSMNT_NOCONN;
+			break;
+		case 'C':
+			nfsargsp->flags &= ~NFSMNT_NOCONN;
+			break;
+		case 'D':
+			num = strtol(optarg, &p, 10);
+			if (*p || num <= 0)
+				return EINVAL;
+			nfsargsp->deadthresh = num;
+			nfsargsp->flags |= NFSMNT_DEADTHRESH;
+			break;
+		case 'd':
+			nfsargsp->flags |= NFSMNT_DUMBTIMR;
+			break;
+#if 0 /* XXXX */
+		case 'g':
+			num = strtol(optarg, &p, 10);
+			if (*p || num <= 0)
+				return EINVAL;
+			set_rpc_maxgrouplist(num);
+			nfsargsp->maxgrouplist = num;
+			nfsargsp->flags |= NFSMNT_MAXGRPS;
+			break;
+#endif
+		case 'I':
+			num = strtol(optarg, &p, 10);
+			if (*p || num <= 0)
+				return EINVAL;
+			nfsargsp->readdirsize = num;
+			nfsargsp->flags |= NFSMNT_READDIRSIZE;
+			break;
+		case 'i':
+			nfsargsp->flags |= NFSMNT_INT;
+			break;
+		case 'L':
+			/* ignore */
+			break;
+		case 'l':
+			nfsargsp->flags |= NFSMNT_RDIRPLUS;
+			break;
+		case 'o':
+			mp = getmntopts(optarg, mopts, mntflags, &altflags);
+			if (mp == NULL)
+				return errno;
+			if (altflags & ALTF_BG)
+				opflags |= BGRND;
+			if (altflags & ALTF_CONN)
+				nfsargsp->flags &= ~NFSMNT_NOCONN;
+			if (altflags & ALTF_DUMBTIMR)
+				nfsargsp->flags |= NFSMNT_DUMBTIMR;
+			if (altflags & ALTF_INTR)
+				nfsargsp->flags |= NFSMNT_INT;
+			if (altflags & (ALTF_NFSV3|ALTF_NQNFS)) {
+				if (force2)
+					return EINVAL;
+				force3 = 1;
+			}
+			if (altflags & ALTF_NFSV2) {
+				if (force3)
+					return EINVAL;
+				force2 = 1;
+				nfsargsp->flags &= ~NFSMNT_NFSV3;
+			}
+			if (altflags & ALTF_RDIRPLUS)
+				nfsargsp->flags |= NFSMNT_RDIRPLUS;
+			if (altflags & ALTF_MNTUDP)
+				mnttcp_ok = 0;
+			if (altflags & ALTF_NORESPORT)
+				nfsargsp->flags &= ~NFSMNT_RESVPORT;
+#ifdef ISO
+			if (altflags & ALTF_SEQPACKET)
+				nfsargsp->sotype = SOCK_SEQPACKET;
+#endif
+			if (altflags & ALTF_SOFT)
+				nfsargsp->flags |= NFSMNT_SOFT;
+			if (altflags & ALTF_TCP) {
+				nfsargsp->sotype = SOCK_STREAM;
+			}
+			if (altflags & ALTF_PORT) {
+				port = getmntoptnum(mp, "port");
+			}
+			if (altflags & ALTF_RSIZE) {
+				nfsargsp->rsize =
+				    (int)getmntoptnum(mp, "rsize");
+				nfsargsp->flags |= NFSMNT_RSIZE;
+			}
+			if (altflags & ALTF_WSIZE) {
+				nfsargsp->wsize =
+				    (int)getmntoptnum(mp, "wsize");
+				nfsargsp->flags |= NFSMNT_WSIZE;
+			}
+			if (altflags & ALTF_RDIRSIZE) {
+				nfsargsp->rsize =
+				    (int)getmntoptnum(mp, "rdirsize");
+				nfsargsp->flags |= NFSMNT_READDIRSIZE;
+			}
+#if 0
+			if (altflags & ALTF_MAXGRPS) {
+				set_rpc_maxgrouplist(num);
+				nfsargsp->maxgrouplist =
+				    (int)getmntoptnum(mp, "maxgrps");
+				nfsargsp->flags |= NFSMNT_MAXGRPS;
+			}
+#endif
+			if (altflags & ALTF_LEASETERM) {
+				nfsargsp->leaseterm =
+				(int)getmntoptnum(mp, "leaseterm");
+				nfsargsp->flags |= NFSMNT_LEASETERM;
+			}
+			if (altflags & ALTF_READAHEAD) {
+				nfsargsp->readahead =
+				    (int)getmntoptnum(mp, "readahead");
+				nfsargsp->flags |= NFSMNT_READAHEAD;
+			}
+			if (altflags & ALTF_DEADTHRESH) {
+				nfsargsp->deadthresh = 
+				    (int)getmntoptnum(mp, "deadthresh");
+				nfsargsp->flags |= NFSMNT_DEADTHRESH;
+			}
+			if (altflags & ALTF_TIMEO) {
+				nfsargsp->timeo = 
+				    (int)getmntoptnum(mp, "timeo");
+				nfsargsp->flags |= NFSMNT_TIMEO;
+			}
+			if (altflags & ALTF_RETRANS) {
+				nfsargsp->retrans = 
+				    (int)getmntoptnum(mp, "retrans");
+				nfsargsp->flags |= NFSMNT_RETRANS;
+			}
+			altflags = 0;
+			freemntopts(mp);
+			break;
+		case 'P':
+			nfsargsp->flags |= NFSMNT_RESVPORT;
+			break;
+		case 'p':
+			nfsargsp->flags &= ~NFSMNT_RESVPORT;
+			break;
+		case 'R':
+			num = strtol(optarg, &p, 10);
+			if (*p || num <= 0)
+				return EINVAL;
+			retrycnt = num;
+			break;
+		case 'r':
+			num = strtol(optarg, &p, 10);
+			if (*p || num <= 0)
+				return EINVAL;
+			nfsargsp->rsize = num;
+			nfsargsp->flags |= NFSMNT_RSIZE;
+			break;
+#ifdef ISO
+		case 'S':
+			nfsargsp->sotype = SOCK_SEQPACKET;
+			break;
+#endif
+		case 's':
+			nfsargsp->flags |= NFSMNT_SOFT;
+			break;
+		case 'T':
+			nfsargsp->sotype = SOCK_STREAM;
+			break;
+		case 't':
+			num = strtol(optarg, &p, 10);
+			if (*p || num <= 0)
+				return EINVAL;
+			nfsargsp->timeo = num;
+			nfsargsp->flags |= NFSMNT_TIMEO;
+			break;
+		case 'w':
+			num = strtol(optarg, &p, 10);
+			if (*p || num <= 0)
+				return EINVAL;
+			nfsargsp->wsize = num;
+			nfsargsp->flags |= NFSMNT_WSIZE;
+			break;
+		case 'x':
+			num = strtol(optarg, &p, 10);
+			if (*p || num <= 0)
+				return EINVAL;
+			nfsargsp->retrans = num;
+			nfsargsp->flags |= NFSMNT_RETRANS;
+			break;
+		case 'X':
+			nfsargsp->flags |= NFSMNT_XLATECOOKIE;
+			break;
+		case 'U':
+			mnttcp_ok = 0;
+			break;
+		default:
+			return EINVAL;
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc != 2)
+		usage();
+
+	strlcpy(spec, *argv++, MAXPATHLEN);
+	pathadj(*argv, name);
+	return mount_nfs_dogetargs(nfsargsp, *mntflags, spec);
+}
+
+int
+mount_nfs(int argc, char *argv[])
+{
+	char spec[MAXPATHLEN], name[MAXPATHLEN];
+	struct nfs_args args;
+	int mntflags;
+	int retval;
+
+	mount_nfs_parseargs(argc, argv, &args, &mntflags, spec, name);
+
+ retry:
+	if ((retval = mount(MOUNT_NFS, name, mntflags,
+	    &args, sizeof args)) == -1) {
+		/* Did we just default to v3 on a v2-only kernel?
+		 * If so, default to v2 & try again */
+		if (errno == EPROGMISMATCH &&
+		    (args.flags & NFSMNT_NFSV3) != 0 && !force3) {
+			/*
+			 * fall back to v2.  XXX lack of V3 umount.
+			 */
+			args.flags &= ~NFSMNT_NFSV3;
+			mount_nfs_dogetargs(&args, mntflags, spec);
+			goto retry;
+		}
+	}
+	if (retval == -1)
+		err(1, "%s on %s", spec, name);
+	if (mntflags & MNT_GETARGS) {
+		shownfsargs(&args);
+		return (0);
+	}
+		
+	exit(0);
+}
+
+static void
+shownfsargs(const struct nfs_args *nfsargsp)
+{
+	char fbuf[2048];
+	char host[NI_MAXHOST], serv[NI_MAXSERV];
+	int error;
+
+	(void)snprintb(fbuf, sizeof(fbuf), NFSMNT_BITS, nfsargsp->flags);
+	if (nfsargsp->addr != NULL) {
+		error = getnameinfo(nfsargsp->addr, nfsargsp->addrlen, host,
+		    sizeof(host), serv, sizeof(serv),
+		    NI_NUMERICHOST | NI_NUMERICSERV);
+		if (error != 0)
+			warnx("getnameinfo: %s", gai_strerror(error));
+	} else
+		error = -1;
+
+	if (error == 0)
+		printf("addr=%s, port=%s, addrlen=%d, ",
+		    host, serv, nfsargsp->addrlen);
+	printf("sotype=%d, proto=%d, fhsize=%d, "
+	    "flags=%s, wsize=%d, rsize=%d, readdirsize=%d, timeo=%d, "
+	    "retrans=%d, maxgrouplist=%d, readahead=%d, leaseterm=%d, "
+	    "deadthresh=%d\n",
+	    nfsargsp->sotype,
+	    nfsargsp->proto,
+	    nfsargsp->fhsize,
+	    fbuf,
+	    nfsargsp->wsize,
+	    nfsargsp->rsize,
+	    nfsargsp->readdirsize,
+	    nfsargsp->timeo,
+	    nfsargsp->retrans,
+	    nfsargsp->maxgrouplist,
+	    nfsargsp->readahead,
+	    nfsargsp->leaseterm,
+	    nfsargsp->deadthresh);
+}
+
+static void
+usage(void)
+{
+	(void)fprintf(stderr, "usage: mount_nfs %s\n%s\n%s\n%s\n%s\n",
+"[-23bCcdilPpqsTUX] [-a maxreadahead] [-D deadthresh]",
+"\t[-g maxgroups] [-I readdirsize] [-L leaseterm]",
+"\t[-o options] [-R retrycnt] [-r readsize] [-t timeout]",
+"\t[-w writesize] [-x retrans]",
+"\trhost:path node");
+	exit(1);
+}
Index: othersrc/lib/libfsu_mount/mount_nfs.h
diff -u /dev/null othersrc/lib/libfsu_mount/mount_nfs.h:1.1
--- /dev/null	Wed Jul  8 15:36:47 2009
+++ othersrc/lib/libfsu_mount/mount_nfs.h	Wed Jul  8 15:36:46 2009
@@ -0,0 +1,56 @@
+/*	$NetBSD: mount_nfs.h,v 1.1 2009/07/08 15:36:46 stacktic Exp $	*/
+
+/*
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SBIN_MOUNT_NFS_MOUNT_NFS_H_
+#define _SBIN_MOUNT_NFS_MOUNT_NFS_H_
+
+#include <nfs/nfsmount.h>
+
+extern int force2;
+extern int force3;
+extern int retrycnt;
+
+#define	BGRND	1
+#define	ISBGRND	2
+
+extern int opflags;
+extern int mnttcp_ok;
+extern int port;
+
+int	getnfsargs(char *, struct nfs_args *);
+int	mount_nfs_dogetargs(struct nfs_args *, int, const char *);
+int	mount_nfs_parseargs(int, char **, struct nfs_args *, int *,
+			    char *, char *);
+
+#endif /* _SBIN_MOUNT_NFS_MOUNT_NFS_H_ */
Index: othersrc/lib/libfsu_mount/udp_xfer.c
diff -u /dev/null othersrc/lib/libfsu_mount/udp_xfer.c:1.1
--- /dev/null	Wed Jul  8 15:36:47 2009
+++ othersrc/lib/libfsu_mount/udp_xfer.c	Wed Jul  8 15:36:46 2009
@@ -0,0 +1,99 @@
+/*	$NetBSD: udp_xfer.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $	*/
+
+/*-
+ * Copyright (c) 2006 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: udp_xfer.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $");
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/poll.h>
+#include <netdb.h>
+#include <err.h>
+
+typedef uint32_t n_long;
+#include <net.h>
+
+void
+set_port(struct sockaddr *sa, int port)
+{
+
+	switch (sa->sa_family) {
+	case AF_INET:
+		((struct sockaddr_in *)sa)->sin_port = port;
+		break;
+#ifdef INET6
+	case AF_INET6:
+		((struct sockaddr_in6 *)sa)->sin6_port = port;
+		break;
+#endif
+	default:
+		errx(1, "Unsupported socket family %d",
+		    sa->sa_family);
+	}
+}
+
+ssize_t
+sendudp(struct iodesc *d, void *pkt, size_t len)
+{
+	int sock;
+	int range = IP_PORTRANGE_LOW;
+
+	if (d->socket >= 0) {
+		close(d->socket);
+		d->socket = -1;
+	}
+
+	sock = socket(d->ai->ai_family, SOCK_DGRAM, IPPROTO_UDP);
+	if (sock < 0)
+		return -1;
+	d->socket = sock;
+	set_port(d->ai->ai_addr, d->destport);
+
+	setsockopt(sock, IPPROTO_IP, IP_PORTRANGE, &range, sizeof(range));
+
+	if (connect(sock, d->ai->ai_addr, d->ai->ai_addrlen) != 0)
+		return -1;
+
+	return send(sock, pkt, len, 0);
+}
+
+ssize_t
+readudp(struct iodesc *d, void *pkt, size_t len, time_t tleft)
+{
+	struct pollfd pfd = {d->socket, POLLIN, 0};
+
+	if (poll(&pfd, 1, tleft * 1000) != 1)
+		return -1;
+
+	return recv(d->socket, pkt, len, 0);
+}

Reply via email to