All of lore.kernel.org
 help / color / mirror / Atom feed
From: Amit Gud <agud@redhat.com>
To: Neil Brown <neilb@suse.de>
Cc: nfs@lists.sourceforge.net, Steve Dickson <SteveD@redhat.com>
Subject: [PATCH 2 / 2] Move NFS mount code from util-linux to nfs-utils
Date: Thu, 08 Jun 2006 15:11:47 -0400	[thread overview]
Message-ID: <44887673.1030003@redhat.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 66 bytes --]



AG
-- 
May the source be with you.
http://www.cis.ksu.edu/~gud


[-- Attachment #2: nfsmount-migration-to-nfsutils-support-v2.patch --]
[-- Type: text/plain, Size: 39760 bytes --]

Adds the support functions needed for mount and umount. This functionality will someday be available in the form of shared mount library.


Signed-off-by: Amit Gud <agud@redhat.com>
Signed-off-by: Steve Dickson <steved@redhat.com>

---
diff -uprN nfs-utils-1.0.8/support/include/conn.h nfs-utils-1.0.8-ag/support/include/conn.h
--- nfs-utils-1.0.8/support/include/conn.h	1969-12-31 19:00:00.000000000 -0500
+++ nfs-utils-1.0.8-ag/support/include/conn.h	2006-06-08 11:22:25.876915000 -0400
@@ -0,0 +1,41 @@
+/* 
+ * conn.h -- Connection routines for NFS mount / umount code.
+ *
+ * 2006-06-06 Amit Gud <agud@redhat.com>
+ * - Moved code snippets here from util-linux/mount
+ */
+
+#ifndef _CONN_H
+#define _CONN_H
+
+#ifdef HAVE_RPCSVC_NFS_PROT_H
+#include <rpcsvc/nfs_prot.h>
+#else
+#include <linux/nfs.h>
+#define nfsstat nfs_stat
+#endif
+
+#include <rpc/pmap_prot.h>
+
+#define MNT_SENDBUFSIZE ((u_int)2048)
+#define MNT_RECVBUFSIZE ((u_int)1024)
+
+typedef struct {
+	char **hostname;
+	struct sockaddr_in saddr;
+	struct pmap pmap;
+} clnt_addr_t;
+
+/* RPC call timeout values */
+static const struct timeval TIMEOUT = { 20, 0 };
+static const struct timeval RETRY_TIMEOUT = { 3, 0 };
+
+int clnt_ping(struct sockaddr_in *, const u_long, const u_long, const u_int);
+u_long nfsvers_to_mnt(const u_long);
+u_long mntvers_to_nfs(const u_long);
+int get_socket(struct sockaddr_in *, u_int, int);
+CLIENT * mnt_openclnt(clnt_addr_t *, int *);
+void mnt_closeclnt(CLIENT *, int);
+
+#endif /* _CONN_H */
+
diff -uprN nfs-utils-1.0.8/support/include/fstab.h nfs-utils-1.0.8-ag/support/include/fstab.h
--- nfs-utils-1.0.8/support/include/fstab.h	1969-12-31 19:00:00.000000000 -0500
+++ nfs-utils-1.0.8-ag/support/include/fstab.h	2006-06-08 11:22:25.881916000 -0400
@@ -0,0 +1,24 @@
+#ifndef _NFS_FSTAB_H
+#define _NFS_FSTAB_H
+
+#include "nfs_mntent.h"
+
+int mtab_is_writable(void);
+int mtab_does_not_exist(void);
+
+struct mntentchn {
+	struct mntentchn *nxt, *prev;
+	nfs_mntent_t m;
+};
+
+struct mntentchn *mtab_head (void);
+struct mntentchn *getmntoptfile (const char *file);
+struct mntentchn *getmntdirbackward (const char *dir, struct mntentchn *mc);
+struct mntentchn *getmntdevbackward (const char *dev, struct mntentchn *mc);
+
+void lock_mtab (void);
+void unlock_mtab (void);
+void update_mtab (const char *special, nfs_mntent_t *with);
+
+#endif /* _NFS_FSTAB_H */
+
diff -uprN nfs-utils-1.0.8/support/include/Makefile.am nfs-utils-1.0.8-ag/support/include/Makefile.am
--- nfs-utils-1.0.8/support/include/Makefile.am	2005-12-19 23:12:43.000000000 -0500
+++ nfs-utils-1.0.8-ag/support/include/Makefile.am	2006-06-08 11:22:25.885917000 -0400
@@ -3,9 +3,13 @@
 SUBDIRS = nfs rpcsvc sys
 
 noinst_HEADERS = \
+	conn.h \
 	exportfs.h \
+	fstab.h \
 	ha-callout.h \
 	misc.h \
+	nfs_mntent.h \
+	nfs_paths.h \
 	nfslib.h \
 	rpcdispatch.h \
 	rpcmisc.h \
@@ -15,6 +19,7 @@ noinst_HEADERS = \
 	xio.h \
 	xlog.h \
 	xmalloc.h \
+	xcommon.h \
 	ypupdate.h
 
 MAINTAINERCLEANFILES = Makefile.in
diff -uprN nfs-utils-1.0.8/support/include/nfs_mntent.h nfs-utils-1.0.8-ag/support/include/nfs_mntent.h
--- nfs-utils-1.0.8/support/include/nfs_mntent.h	1969-12-31 19:00:00.000000000 -0500
+++ nfs-utils-1.0.8-ag/support/include/nfs_mntent.h	2006-06-08 11:22:25.891916000 -0400
@@ -0,0 +1,34 @@
+/*
+ * 2006-06-08 Amit Gud <agud@redhat.com>
+ * - Moved code snippets here from util-linux/mount/my_mntent.h
+ */
+
+#ifndef _NFS_MNTENT_H
+#define _NFS_MNTENT_H
+
+typedef struct nfs_mntent_s {
+	const char *mnt_fsname;
+	const char *mnt_dir;
+	const char *mnt_type;
+	const char *mnt_opts;
+	int mnt_freq;
+	int mnt_passno;
+} nfs_mntent_t;
+
+#define ERR_MAX 5
+
+typedef struct mntFILEstruct {
+	FILE *mntent_fp;
+	char *mntent_file;
+	int mntent_lineno;
+	int mntent_errs;
+	int mntent_softerrs;
+} mntFILE;
+
+mntFILE *nfs_setmntent (const char *file, char *mode);
+void nfs_endmntent (mntFILE *mfp);
+int nfs_addmntent (mntFILE *mfp, nfs_mntent_t *mnt);
+struct nfs_mntent *my_getmntent (mntFILE *mfp);
+nfs_mntent_t *nfs_getmntent (mntFILE *mfp);
+
+#endif /* _NFS_MNTENT_H */
diff -uprN nfs-utils-1.0.8/support/include/nfs_paths.h nfs-utils-1.0.8-ag/support/include/nfs_paths.h
--- nfs-utils-1.0.8/support/include/nfs_paths.h	1969-12-31 19:00:00.000000000 -0500
+++ nfs-utils-1.0.8-ag/support/include/nfs_paths.h	2006-06-08 11:22:25.896916000 -0400
@@ -0,0 +1,16 @@
+#ifndef _NFS_PATHS_H
+#define _NFS_PATHS_H
+
+#include <paths.h>
+#define _PATH_FSTAB	"/etc/fstab"
+#ifdef _PATH_MOUNTED
+#define MOUNTED_LOCK	_PATH_MOUNTED "~"
+#define MOUNTED_TEMP	_PATH_MOUNTED ".tmp"
+#else
+#define MOUNTED_LOCK	"/etc/mtab~"
+#define MOUNTED_TEMP	"/etc/mtab.tmp"
+#endif
+#define LOCK_TIMEOUT	10
+
+#endif /* _NFS_PATHS_H */
+
diff -uprN nfs-utils-1.0.8/support/include/nls.h nfs-utils-1.0.8-ag/support/include/nls.h
--- nfs-utils-1.0.8/support/include/nls.h	1969-12-31 19:00:00.000000000 -0500
+++ nfs-utils-1.0.8-ag/support/include/nls.h	2006-06-08 11:22:25.902916000 -0400
@@ -0,0 +1,27 @@
+/* 
+ * 2006-06-08 Amit Gud <agud@redhat.com>
+ * - Copied to nfs-utils/support/include from util-linux/mount
+ */
+
+#ifndef LOCALEDIR
+#define LOCALEDIR "/usr/share/locale"
+#endif
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(Text) gettext (Text)
+# ifdef gettext_noop
+#  define N_(String) gettext_noop (String)
+# else
+#  define N_(String) (String)
+# endif
+#else
+# undef bindtextdomain
+# define bindtextdomain(Domain, Directory) /* empty */
+# undef textdomain
+# define textdomain(Domain) /* empty */
+# define _(Text) (Text)
+# define N_(Text) (Text)
+#endif
+
+
diff -uprN nfs-utils-1.0.8/support/include/xcommon.h nfs-utils-1.0.8-ag/support/include/xcommon.h
--- nfs-utils-1.0.8/support/include/xcommon.h	1969-12-31 19:00:00.000000000 -0500
+++ nfs-utils-1.0.8-ag/support/include/xcommon.h	2006-06-08 11:22:25.907915000 -0400
@@ -0,0 +1,48 @@
+/*
+ * xcommon.h -- Support function prototypes. Functions are in xcommon.c.
+ *
+ * 2006-06-06 Amit Gud <agud@redhat.com>
+ * - Moved code snippets  from mount/sundries.h of util-linux
+ *   and merged code from support/nfs/xmalloc.c by Olaf Kirch <okir@monad.swb.de> here.
+ */
+
+#ifndef _XMALLOC_H
+#define _MALLOC_H
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define streq(s, t)	(strcmp ((s), (t)) == 0)
+
+/* Functions in sundries.c that are used in mount.c and umount.c  */ 
+char *canonicalize (const char *path);
+void nfs_error (const char *fmt, ...);
+void *xmalloc (size_t size);
+void *xrealloc(void *p, size_t size);
+void xfree(void *);
+char *xstrdup (const char *s);
+char *xstrndup (const char *s, int n);
+char *xstrconcat2 (const char *, const char *);
+char *xstrconcat3 (const char *, const char *, const char *);
+char *xstrconcat4 (const char *, const char *, const char *, const char *);
+void die (int errcode, const char *fmt, ...);
+
+extern void die(int err, const char *fmt, ...);
+extern void (*at_die)(void);
+
+/* exit status - bits below are ORed */
+#define EX_USAGE	1	/* incorrect invocation or permission */
+#define EX_SYSERR	2	/* out of memory, cannot fork, ... */
+#define EX_SOFTWARE	4	/* internal mount bug or wrong version */
+#define EX_USER		8	/* user interrupt */
+#define EX_FILEIO      16	/* problems writing, locking, ... mtab/fstab */
+#define EX_FAIL	       32	/* mount failure */
+#define EX_SOMEOK      64	/* some mount succeeded */
+#define EX_BG         256       /* retry in background (internal only) */
+
+#endif /* XMALLOC_H */
diff -uprN nfs-utils-1.0.8/support/include/xmalloc.h nfs-utils-1.0.8-ag/support/include/xmalloc.h
--- nfs-utils-1.0.8/support/include/xmalloc.h	1999-10-18 19:21:12.000000000 -0400
+++ nfs-utils-1.0.8-ag/support/include/xmalloc.h	2006-06-08 11:22:25.911916000 -0400
@@ -1,16 +1 @@
-/*
- * xmalloc	Module for memory allocation. Drop in your
- *		debugging malloc module if you feel like it.
- *
- * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
- */
-
-#ifndef XMALLOC_H
-#define XMALLOC_H
-
-void	*xmalloc(size_t size);
-void	*xrealloc(void *ptr, size_t size);
-char	*xstrdup(const char *s);
-void	xfree(void *ptr);
-
-#endif /* XMALLOC_H */
+#include "xcommon.h"
diff -uprN nfs-utils-1.0.8/support/nfs/conn.c nfs-utils-1.0.8-ag/support/nfs/conn.c
--- nfs-utils-1.0.8/support/nfs/conn.c	1969-12-31 19:00:00.000000000 -0500
+++ nfs-utils-1.0.8-ag/support/nfs/conn.c	2006-06-08 11:22:25.917915000 -0400
@@ -0,0 +1,212 @@
+/*
+ * conn.c -- NFS client mount / umount connection code support functions
+ *
+ * 2006-06-06 Amit Gud <agud@redhat.com>
+ * - Moved code snippets to nfs-utils/support/nfs from util-linux/mount/nfsmount.c
+ *
+ */
+
+#include <errno.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+//#include <sys/mount.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "conn.h"
+
+extern int verbose;
+
+/* Map an NFS version into the corresponding Mountd version */
+u_long nfsvers_to_mnt(const u_long vers)
+{
+	static const u_long nfs_to_mnt[] = { 0, 0, 1, 3 };
+	if (vers <= 3)
+		return nfs_to_mnt[vers];
+	return 0;
+}
+
+/* Map a Mountd version into the corresponding NFS version */
+u_long mntvers_to_nfs(const u_long vers)
+{
+	static const u_long mnt_to_nfs[] = { 0, 2, 2, 3 };
+	if (vers <= 3)
+		return mnt_to_nfs[vers];
+	return 0;
+}
+
+/*
+ * Create a socket that is locally bound to a 
+ * reserve or non-reserve port. For any failures,
+ * RPC_ANYSOCK is returned which will cause 
+ * the RPC code to create the socket instead. 
+ */
+int get_socket(struct sockaddr_in *saddr, u_int p_prot, int resvp)
+{
+	int so, cc, type;
+	struct sockaddr_in laddr;
+	socklen_t namelen = sizeof(laddr);
+
+	type = (p_prot == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM);
+	if ((so = socket (AF_INET, type, p_prot)) < 0) {
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		if (verbose) {
+			fprintf(stderr, 
+				"mount: Unable to create %s socket: errno %d (%s)\n",
+				p_prot == IPPROTO_UDP ? "UDP" : "TCP", 
+				errno, strerror(errno));
+		}
+		return RPC_ANYSOCK;
+	}
+	laddr.sin_family = AF_INET;
+	laddr.sin_port = 0;
+	laddr.sin_addr.s_addr = htonl(INADDR_ANY);
+	if (resvp) {
+		if (bindresvport(so, &laddr) < 0) {
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+			rpc_createerr.cf_error.re_errno = errno;
+			if (verbose) {
+				fprintf(stderr, 
+					"mount: Unable to bindresvport %s socket: errno %d (%s)\n",
+					p_prot == IPPROTO_UDP ? "UDP" : "TCP", 
+					errno, strerror(errno));
+			}
+			close(so);
+			return RPC_ANYSOCK;
+		}
+	} else {
+		cc = bind(so, (struct sockaddr *)&laddr, namelen);
+		if (cc < 0) {
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+			rpc_createerr.cf_error.re_errno = errno;
+			if (verbose) {
+				fprintf(stderr, 
+					"mount: Unable to bind to %s socket: errno %d (%s)\n",
+					p_prot == IPPROTO_UDP ? "UDP" : "TCP", 
+					errno, strerror(errno));
+			}
+			close(so);
+			return RPC_ANYSOCK;
+		}
+	}
+	if (type == SOCK_STREAM) {
+		cc = connect(so, (struct sockaddr *)saddr, namelen);
+		if (cc < 0) {
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+			rpc_createerr.cf_error.re_errno = errno;
+			if (verbose) {
+				fprintf(stderr, 
+					"mount: Unable to connect to %s:%d, errno %d (%s)\n",
+					inet_ntoa(saddr->sin_addr), ntohs(saddr->sin_port),
+					errno, strerror(errno));
+			}
+			close(so);
+			return RPC_ANYSOCK;
+		}
+	}
+	return so;
+}
+
+/*
+ * Sigh... getport() doesn't actually check the version number.
+ * In order to make sure that the server actually supports the service
+ * we're requesting, we open and RPC client, and fire off a NULL
+ * RPC call.
+ */
+int
+clnt_ping(struct sockaddr_in *saddr, const u_long prog, const u_long vers,
+	  const u_int prot)
+{
+	CLIENT *clnt=NULL;
+	int sock, stat;
+	static char clnt_res;
+
+	rpc_createerr.cf_stat = stat = errno = 0;
+	sock = get_socket(saddr, prot, FALSE);
+	if (sock == RPC_ANYSOCK && errno == ETIMEDOUT) {
+		/*
+		 * TCP timeout. Bubble up the error to see 
+		 * how it should be handled.
+		 */
+		rpc_createerr.cf_stat = RPC_TIMEDOUT;
+		goto out_bad;
+	}
+
+	switch(prot) {
+	case IPPROTO_UDP:
+		clnt = clntudp_bufcreate(saddr, prog, vers,
+					 RETRY_TIMEOUT, &sock,
+					 RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+		break;
+	case IPPROTO_TCP:
+		clnt = clnttcp_create(saddr, prog, vers, &sock,
+				      RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+		break;
+	default:
+		goto out_bad;
+	}
+	if (!clnt)
+		goto out_bad;
+	memset(&clnt_res, 0, sizeof(clnt_res));
+	stat = clnt_call(clnt, NULLPROC,
+			 (xdrproc_t)xdr_void, (caddr_t)NULL,
+			 (xdrproc_t)xdr_void, (caddr_t)&clnt_res,
+			 TIMEOUT);
+	if (stat) {
+		clnt_geterr(clnt, &rpc_createerr.cf_error);
+		rpc_createerr.cf_stat = stat;
+	}
+	clnt_destroy(clnt);
+	if (sock != -1)
+		close(sock);
+
+	if (stat == RPC_SUCCESS)
+		return 1;
+
+ out_bad:
+	return 0;
+}
+
+CLIENT *mnt_openclnt(clnt_addr_t *mnt_server, int *msock)
+{
+	struct sockaddr_in *mnt_saddr = &mnt_server->saddr;
+	struct pmap *mnt_pmap = &mnt_server->pmap;
+	CLIENT *clnt = NULL;
+
+	/* contact the mount daemon via TCP */
+	mnt_saddr->sin_port = htons((u_short)mnt_pmap->pm_port);
+	*msock = get_socket(mnt_saddr, mnt_pmap->pm_prot, TRUE);
+
+	switch (mnt_pmap->pm_prot) {
+	case IPPROTO_UDP:
+		clnt = clntudp_bufcreate(mnt_saddr,
+					 mnt_pmap->pm_prog, mnt_pmap->pm_vers,
+					 RETRY_TIMEOUT, msock,
+					 MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
+		break;
+	case IPPROTO_TCP:
+		clnt = clnttcp_create(mnt_saddr,
+				      mnt_pmap->pm_prog, mnt_pmap->pm_vers,
+				      msock,
+				      MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
+		break;
+	}
+	if (clnt) {
+		/* try to mount hostname:dirname */
+		clnt->cl_auth = authunix_create_default();
+		return clnt;
+	}
+	return NULL;
+}
+
+void mnt_closeclnt(CLIENT *clnt, int msock)
+{
+	auth_destroy(clnt->cl_auth);
+	clnt_destroy(clnt);
+	close(msock);
+}
+
diff -uprN nfs-utils-1.0.8/support/nfs/fstab.c nfs-utils-1.0.8-ag/support/nfs/fstab.c
--- nfs-utils-1.0.8/support/nfs/fstab.c	1969-12-31 19:00:00.000000000 -0500
+++ nfs-utils-1.0.8-ag/support/nfs/fstab.c	2006-06-08 11:26:14.690640000 -0400
@@ -0,0 +1,486 @@
+/* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * - added Native Language Support
+ * Sun Mar 21 1999 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ * - fixed strerr(errno) in gettext calls
+ *
+ * 2006-06-08 Amit Gud <agud@redhat.com>
+ * - Moved code to nfs-utils/support/nfs from util-linux/mount.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <mntent.h>
+
+#include "fstab.h"
+#include "xcommon.h"
+#include "nfs_mntent.h"
+#include "nfs_paths.h"
+#include "nls.h"
+
+#define streq(s, t)	(strcmp ((s), (t)) == 0)
+#define PROC_MOUNTS		"/proc/mounts"
+
+extern int verbose;
+
+/* Information about mtab. ------------------------------------*/
+static int have_mtab_info = 0;
+static int var_mtab_does_not_exist = 0;
+static int var_mtab_is_a_symlink = 0;
+
+static void
+get_mtab_info(void) {
+	struct stat mtab_stat;
+
+	if (!have_mtab_info) {
+		if (lstat(MOUNTED, &mtab_stat))
+			var_mtab_does_not_exist = 1;
+		else if (S_ISLNK(mtab_stat.st_mode))
+			var_mtab_is_a_symlink = 1;
+		have_mtab_info = 1;
+	}
+}
+
+int
+mtab_does_not_exist(void) {
+	get_mtab_info();
+	return var_mtab_does_not_exist;
+}
+
+static int
+mtab_is_a_symlink(void) {
+        get_mtab_info();
+        return var_mtab_is_a_symlink;
+}
+
+int
+mtab_is_writable() {
+	int fd;
+
+	/* Should we write to /etc/mtab upon an update?
+	   Probably not if it is a symlink to /proc/mounts, since that
+	   would create a file /proc/mounts in case the proc filesystem
+	   is not mounted. */
+	if (mtab_is_a_symlink())
+		return 0;
+
+	fd = open(MOUNTED, O_RDWR | O_CREAT, 0644);
+	if (fd >= 0) {
+		close(fd);
+		return 1;
+	} else
+		return 0;
+}
+
+/* Contents of mtab and fstab ---------------------------------*/
+
+struct mntentchn mounttable;
+static int got_mtab = 0;
+
+static void read_mounttable(void);
+
+struct mntentchn *
+mtab_head() {
+	if (!got_mtab)
+		read_mounttable();
+	return &mounttable;
+}
+
+static void
+my_free(const void *s) {
+	if (s)
+		free((void *) s);
+}
+
+static void
+discard_mntentchn(struct mntentchn *mc0) {
+	struct mntentchn *mc, *mc1;
+
+	for (mc = mc0->nxt; mc && mc != mc0; mc = mc1) {
+		mc1 = mc->nxt;
+		my_free(mc->m.mnt_fsname);
+		my_free(mc->m.mnt_dir);
+		my_free(mc->m.mnt_type);
+		my_free(mc->m.mnt_opts);
+		free(mc);
+	}
+}
+
+static void
+read_mntentchn(mntFILE *mfp, const char *fnam, struct mntentchn *mc0) {
+	struct mntentchn *mc = mc0;
+	nfs_mntent_t *mnt;
+
+	while ((mnt = nfs_getmntent(mfp)) != NULL) {
+		if (!streq(mnt->mnt_type, MNTTYPE_IGNORE)) {
+			mc->nxt = (struct mntentchn *) xmalloc(sizeof(*mc));
+			mc->nxt->prev = mc;
+			mc = mc->nxt;
+			mc->m = *mnt;
+			mc->nxt = mc0;
+		}
+	}
+	mc0->prev = mc;
+	if (ferror(mfp->mntent_fp)) {
+		int errsv = errno;
+		nfs_error(_("warning: error reading %s: %s"),
+		      fnam, strerror (errsv));
+		mc0->nxt = mc0->prev = NULL;
+	}
+	nfs_endmntent(mfp);
+}
+
+/*
+ * Read /etc/mtab.  If that fails, try /proc/mounts.
+ * This produces a linked list. The list head mounttable is a dummy.
+ * Return 0 on success.
+ */
+static void
+read_mounttable() {
+        mntFILE *mfp;
+        const char *fnam;
+        struct mntentchn *mc = &mounttable;
+
+        got_mtab = 1;
+        mc->nxt = mc->prev = NULL;
+
+        fnam = MOUNTED;
+        mfp = nfs_setmntent (fnam, "r");
+        if (mfp == NULL || mfp->mntent_fp == NULL) {
+                int errsv = errno;
+                fnam = PROC_MOUNTS;
+                mfp = nfs_setmntent (fnam, "r");
+                if (mfp == NULL || mfp->mntent_fp == NULL) {
+                        nfs_error(_("warning: can't open %s: %s"),
+                              MOUNTED, strerror (errsv));
+                        return;
+                }
+                if (verbose)
+                        printf (_("mount: could not open %s - "
+                                  "using %s instead\n"),
+                                MOUNTED, PROC_MOUNTS);
+        }
+        read_mntentchn(mfp, fnam, mc);
+}
+
+/*
+ * Given the directory name NAME, and the place MCPREV we found it last time,
+ * try to find more occurrences.
+ */ 
+struct mntentchn *
+getmntdirbackward (const char *name, struct mntentchn *mcprev) {
+	struct mntentchn *mc, *mc0;
+
+	mc0 = mtab_head();
+	if (!mcprev)
+		mcprev = mc0;
+	for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev)
+		if (streq(mc->m.mnt_dir, name))
+			return mc;
+	return NULL;
+}
+
+/*
+ * Given the device name NAME, and the place MCPREV we found it last time,
+ * try to find more occurrences.
+ */ 
+struct mntentchn *
+getmntdevbackward (const char *name, struct mntentchn *mcprev) {
+	struct mntentchn *mc, *mc0;
+
+	mc0 = mtab_head();
+	if (!mcprev)
+		mcprev = mc0;
+	for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev)
+		if (streq(mc->m.mnt_fsname, name))
+			return mc;
+	return NULL;
+}
+
+/* Updating mtab ----------------------------------------------*/
+
+/* Flag for already existing lock file. */
+static int we_created_lockfile = 0;
+static int lockfile_fd = -1;
+
+/* Flag to indicate that signals have been set up. */
+static int signals_have_been_setup = 0;
+
+/* Ensure that the lock is released if we are interrupted.  */
+extern char *strsignal(int sig);	/* not always in <string.h> */
+
+static void
+handler (int sig) {
+     die(EX_USER, "%s", strsignal(sig));
+}
+
+static void
+setlkw_timeout (int sig) {
+     /* nothing, fcntl will fail anyway */
+}
+
+/* Remove lock file.  */
+void
+unlock_mtab (void) {
+	if (we_created_lockfile) {
+		close(lockfile_fd);
+		lockfile_fd = -1;
+		unlink (MOUNTED_LOCK);
+		we_created_lockfile = 0;
+	}
+}
+
+/* Create the lock file.
+   The lock file will be removed if we catch a signal or when we exit. */
+/* The old code here used flock on a lock file /etc/mtab~ and deleted
+   this lock file afterwards. However, as rgooch remarks, that has a
+   race: a second mount may be waiting on the lock and proceed as
+   soon as the lock file is deleted by the first mount, and immediately
+   afterwards a third mount comes, creates a new /etc/mtab~, applies
+   flock to that, and also proceeds, so that the second and third mount
+   now both are scribbling in /etc/mtab.
+   The new code uses a link() instead of a creat(), where we proceed
+   only if it was us that created the lock, and hence we always have
+   to delete the lock afterwards. Now the use of flock() is in principle
+   superfluous, but avoids an arbitrary sleep(). */
+
+/* Where does the link point to? Obvious choices are mtab and mtab~~.
+   HJLu points out that the latter leads to races. Right now we use
+   mtab~.<pid> instead. Use 20 as upper bound for the length of %d. */
+#define MOUNTLOCK_LINKTARGET		MOUNTED_LOCK "%d"
+#define MOUNTLOCK_LINKTARGET_LTH	(sizeof(MOUNTED_LOCK)+20)
+
+void
+lock_mtab (void) {
+	int tries = 100000, i;
+	char linktargetfile[MOUNTLOCK_LINKTARGET_LTH];
+
+	at_die = unlock_mtab;
+
+	if (!signals_have_been_setup) {
+		int sig = 0;
+		struct sigaction sa;
+
+		sa.sa_handler = handler;
+		sa.sa_flags = 0;
+		sigfillset (&sa.sa_mask);
+  
+		while (sigismember (&sa.sa_mask, ++sig) != -1
+		       && sig != SIGCHLD) {
+			if (sig == SIGALRM)
+				sa.sa_handler = setlkw_timeout;
+			else
+				sa.sa_handler = handler;
+			sigaction (sig, &sa, (struct sigaction *) 0);
+		}
+		signals_have_been_setup = 1;
+	}
+
+	sprintf(linktargetfile, MOUNTLOCK_LINKTARGET, getpid ());
+
+	i = open (linktargetfile, O_WRONLY|O_CREAT, 0);
+	if (i < 0) {
+		int errsv = errno;
+		/* linktargetfile does not exist (as a file)
+		   and we cannot create it. Read-only filesystem?
+		   Too many files open in the system?
+		   Filesystem full? */
+		die (EX_FILEIO, _("can't create lock file %s: %s "
+						  "(use -n flag to override)"),
+			 linktargetfile, strerror (errsv));
+	}
+	close(i);
+	
+	/* Repeat until it was us who made the link */
+	while (!we_created_lockfile) {
+		struct flock flock;
+		int errsv, j;
+
+		j = link(linktargetfile, MOUNTED_LOCK);
+		errsv = errno;
+
+		if (j == 0)
+			we_created_lockfile = 1;
+
+		if (j < 0 && errsv != EEXIST) {
+			(void) unlink(linktargetfile);
+			die (EX_FILEIO, _("can't link lock file %s: %s "
+			     "(use -n flag to override)"),
+			     MOUNTED_LOCK, strerror (errsv));
+		}
+
+		lockfile_fd = open (MOUNTED_LOCK, O_WRONLY);
+
+		if (lockfile_fd < 0) {
+			int errsv = errno;
+			/* Strange... Maybe the file was just deleted? */
+			if (errno == ENOENT && tries-- > 0) {
+				if (tries % 200 == 0)
+					usleep(30);
+				continue;
+			}
+			(void) unlink(linktargetfile);
+			die (EX_FILEIO, _("can't open lock file %s: %s "
+			     "(use -n flag to override)"),
+			     MOUNTED_LOCK, strerror (errsv));
+		}
+
+		flock.l_type = F_WRLCK;
+		flock.l_whence = SEEK_SET;
+		flock.l_start = 0;
+		flock.l_len = 0;
+
+		if (j == 0) {
+			/* We made the link. Now claim the lock. */
+			if (fcntl (lockfile_fd, F_SETLK, &flock) == -1) {
+				if (verbose) {
+				    int errsv = errno;
+				    printf(_("Can't lock lock file %s: %s\n"),
+					   MOUNTED_LOCK, strerror (errsv));
+				}
+				/* proceed anyway */
+			}
+			(void) unlink(linktargetfile);
+		} else {
+			static int tries = 0;
+
+			/* Someone else made the link. Wait. */
+			alarm(LOCK_TIMEOUT);
+			if (fcntl (lockfile_fd, F_SETLKW, &flock) == -1) {
+				int errsv = errno;
+				(void) unlink(linktargetfile);
+				die (EX_FILEIO, _("can't lock lock file %s: %s"),
+				     MOUNTED_LOCK, (errno == EINTR) ?
+				     _("timed out") : strerror (errsv));
+			}
+			alarm(0);
+			/* Limit the number of iterations - maybe there
+			   still is some old /etc/mtab~ */
+			++tries;
+			if (tries % 200 == 0)
+			   usleep(30);
+			if (tries > 100000) {
+				(void) unlink(linktargetfile);
+				close(lockfile_fd);
+				die (EX_FILEIO, _("Cannot create link %s\n"
+						  "Perhaps there is a stale lock file?\n"),
+					 MOUNTED_LOCK);
+ 			}
+			close(lockfile_fd);
+		}
+	}
+}
+
+/*
+ * Update the mtab.
+ *  Used by umount with null INSTEAD: remove the last DIR entry.
+ *  Used by mount upon a remount: update option part,
+ *   and complain if a wrong device or type was given.
+ *   [Note that often a remount will be a rw remount of /
+ *    where there was no entry before, and we'll have to believe
+ *    the values given in INSTEAD.]
+ */
+
+void
+update_mtab (const char *dir, nfs_mntent_t *instead) {
+	mntFILE *mfp, *mftmp;
+	const char *fnam = MOUNTED;
+	struct mntentchn mtabhead;	/* dummy */
+	struct mntentchn *mc, *mc0, *absent = NULL;
+
+	if (mtab_does_not_exist() || !mtab_is_writable())
+		return;
+
+	lock_mtab();
+
+	/* having locked mtab, read it again */
+	mc0 = mc = &mtabhead;
+	mc->nxt = mc->prev = NULL;
+
+	mfp = nfs_setmntent(fnam, "r");
+	if (mfp == NULL || mfp->mntent_fp == NULL) {
+		int errsv = errno;
+		nfs_error (_("cannot open %s (%s) - mtab not updated"),
+		       fnam, strerror (errsv));
+		goto leave;
+	}
+
+	read_mntentchn(mfp, fnam, mc);
+
+	/* find last occurrence of dir */
+	for (mc = mc0->prev; mc && mc != mc0; mc = mc->prev)
+		if (streq(mc->m.mnt_dir, dir))
+			break;
+	if (mc && mc != mc0) {
+		if (instead == NULL) {
+			/* An umount - remove entry */
+			if (mc && mc != mc0) {
+				mc->prev->nxt = mc->nxt;
+				mc->nxt->prev = mc->prev;
+				free(mc);
+			}
+		} else {
+			/* A remount */
+			mc->m.mnt_opts = instead->mnt_opts;
+		}
+	} else if (instead) {
+		/* not found, add a new entry */
+		absent = xmalloc(sizeof(*absent));
+		absent->m = *instead;
+		absent->nxt = mc0;
+		absent->prev = mc0->prev;
+		mc0->prev = absent;
+		if (mc0->nxt == NULL)
+			mc0->nxt = absent;
+	}
+
+	/* write chain to mtemp */
+	mftmp = nfs_setmntent (MOUNTED_TEMP, "w");
+	if (mftmp == NULL || mftmp->mntent_fp == NULL) {
+		int errsv = errno;
+		nfs_error (_("cannot open %s (%s) - mtab not updated"),
+		       MOUNTED_TEMP, strerror (errsv));
+		goto leave;
+	}
+
+	for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) {
+		if (nfs_addmntent(mftmp, &(mc->m)) == 1) {
+			int errsv = errno;
+			die (EX_FILEIO, _("error writing %s: %s"),
+			     MOUNTED_TEMP, strerror (errsv));
+		}
+	}
+
+	discard_mntentchn(mc0);
+
+	if (fchmod (fileno (mftmp->mntent_fp),
+		    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
+		int errsv = errno;
+		fprintf(stderr, _("error changing mode of %s: %s\n"),
+			MOUNTED_TEMP, strerror (errsv));
+	}
+	nfs_endmntent (mftmp);
+
+	{ /*
+	   * If mount is setuid and some non-root user mounts sth,
+	   * then mtab.tmp might get the group of this user. Copy uid/gid
+	   * from the present mtab before renaming.
+	   */
+	    struct stat sbuf;
+	    if (stat (MOUNTED, &sbuf) == 0)
+		chown (MOUNTED_TEMP, sbuf.st_uid, sbuf.st_gid);
+	}
+
+	/* rename mtemp to mtab */
+	if (rename (MOUNTED_TEMP, MOUNTED) < 0) {
+		int errsv = errno;
+		fprintf(stderr, _("can't rename %s to %s: %s\n"),
+			MOUNTED_TEMP, MOUNTED, strerror(errsv));
+	}
+
+ leave:
+	unlock_mtab();
+}
diff -uprN nfs-utils-1.0.8/support/nfs/Makefile.am nfs-utils-1.0.8-ag/support/nfs/Makefile.am
--- nfs-utils-1.0.8/support/nfs/Makefile.am	2005-12-19 23:12:44.000000000 -0500
+++ nfs-utils-1.0.8-ag/support/nfs/Makefile.am	2006-06-08 11:22:25.928915000 -0400
@@ -2,9 +2,9 @@
 
 noinst_LIBRARIES = libnfs.a
 libnfs_a_SOURCES = exports.c rmtab.c xio.c rpcmisc.c rpcdispatch.c \
-		   xlog.c xmalloc.c wildmat.c nfssvc.c nfsclient.c \
+		   xlog.c xcommon.c wildmat.c nfssvc.c nfsclient.c \
 		   nfsexport.c getfh.c nfsctl.c lockdsvc.c \
-		   svc_socket.c cacheio.c closeall.c
+		   svc_socket.c cacheio.c closeall.c conn.c fstab.c nfs_mntent.c
 
 MAINTAINERCLEANFILES = Makefile.in
 
diff -uprN nfs-utils-1.0.8/support/nfs/nfs_mntent.c nfs-utils-1.0.8-ag/support/nfs/nfs_mntent.c
--- nfs-utils-1.0.8/support/nfs/nfs_mntent.c	1969-12-31 19:00:00.000000000 -0500
+++ nfs-utils-1.0.8-ag/support/nfs/nfs_mntent.c	2006-06-08 11:22:25.934916000 -0400
@@ -0,0 +1,226 @@
+/* Private version of the libc *mntent() routines. */
+/* Note slightly different prototypes. */
+
+/* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * - added Native Language Support
+ *
+ * 2006-06-08 Amit Gud <agud@redhat.com>
+ * - Moved to nfs-utils/support/nfs from util-linux/mount
+ */
+
+#include <stdio.h>
+#include <string.h>		/* for index */
+#include <ctype.h>		/* for isdigit */
+#include <sys/stat.h>		/* for umask */
+
+#include "nfs_mntent.h"
+#include "nls.h"
+#include "xcommon.h"
+
+/* Unfortunately the classical Unix /etc/mtab and /etc/fstab
+   do not handle directory names containing spaces.
+   Here we mangle them, replacing a space by \040.
+   What do other Unices do? */
+
+static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' };
+
+static char *
+mangle(const unsigned char *s) {
+	char *ss, *sp;
+	int n;
+
+	n = strlen(s);
+	ss = sp = xmalloc(4*n+1);
+	while(1) {
+		for (n = 0; n < sizeof(need_escaping); n++) {
+			if (*s == need_escaping[n]) {
+				*sp++ = '\\';
+				*sp++ = '0' + ((*s & 0300) >> 6);
+				*sp++ = '0' + ((*s & 070) >> 3);
+				*sp++ = '0' + (*s & 07);
+				goto next;
+			}
+		}
+		*sp++ = *s;
+		if (*s == 0)
+			break;
+	next:
+		s++;
+	}
+	return ss;
+}
+
+static int
+is_space_or_tab (char c) {
+	return (c == ' ' || c == '\t');
+}
+
+static char *
+skip_spaces(char *s) {
+	while (is_space_or_tab(*s))
+		s++;
+	return s;
+}
+
+static char *
+skip_nonspaces(char *s) {
+	while (*s && !is_space_or_tab(*s))
+		s++;
+	return s;
+}
+
+#define isoctal(a) (((a) & ~7) == '0')
+
+/* returns malloced pointer - no more strdup required */
+static char *
+unmangle(char *s) {
+	char *ret, *ss, *sp;
+
+	ss = skip_nonspaces(s);
+	ret = sp = xmalloc(ss-s+1);
+	while(s != ss) {
+		if (*s == '\\' && isoctal(s[1]) && isoctal(s[2]) && isoctal(s[3])) {
+			*sp++ = 64*(s[1] & 7) + 8*(s[2] & 7) + (s[3] & 7);
+			s += 4;
+		} else
+			*sp++ = *s++;
+	}
+	*sp = 0;
+	return ret;
+}
+
+/*
+ * fstat'ing the file and allocating a buffer holding all of it
+ * may be a bad idea: if the file is /proc/mounts, the stat
+ * returns 0.
+ * (On the other hand, mangling and unmangling is meaningless
+ *  for /proc/mounts.)
+ */
+
+mntFILE *
+nfs_setmntent (const char *file, char *mode) {
+	mntFILE *mfp = xmalloc(sizeof(*mfp));
+	mode_t old_umask = umask(077);
+
+	mfp->mntent_fp = fopen(file, mode);
+	umask(old_umask);
+	mfp->mntent_file = xstrdup(file);
+	mfp->mntent_errs = (mfp->mntent_fp == NULL);
+	mfp->mntent_softerrs = 0;
+	mfp->mntent_lineno = 0;
+	return mfp;
+}
+
+void
+nfs_endmntent (mntFILE *mfp) {
+	if (mfp) {
+		if (mfp->mntent_fp)
+			fclose(mfp->mntent_fp);
+		if (mfp->mntent_file)
+			free(mfp->mntent_file);
+		free(mfp);
+	}
+}
+
+int
+nfs_addmntent (mntFILE *mfp, nfs_mntent_t *mnt) {
+	char *m1, *m2, *m3, *m4;
+	int res;
+
+	if (fseek (mfp->mntent_fp, 0, SEEK_END))
+		return 1;			/* failure */
+
+	m1 = mangle(mnt->mnt_fsname);
+	m2 = mangle(mnt->mnt_dir);
+	m3 = mangle(mnt->mnt_type);
+	m4 = mangle(mnt->mnt_opts);
+
+	res = fprintf (mfp->mntent_fp, "%s %s %s %s %d %d\n",
+		       m1, m2, m3, m4, mnt->mnt_freq, mnt->mnt_passno);
+
+	free(m1);
+	free(m2);
+	free(m3);
+	free(m4);
+	return (res < 0) ? 1 : 0;
+}
+
+/* Read the next entry from the file fp. Stop reading at an incorrect entry. */
+nfs_mntent_t *
+nfs_getmntent (mntFILE *mfp) {
+	static char buf[4096];
+	static nfs_mntent_t me;
+	char *s;
+
+ again:
+	if (mfp->mntent_errs || mfp->mntent_softerrs >= ERR_MAX)
+		return NULL;
+
+	/* read the next non-blank non-comment line */
+	do {
+		if (fgets (buf, sizeof(buf), mfp->mntent_fp) == NULL)
+			return NULL;
+
+		mfp->mntent_lineno++;
+		s = index (buf, '\n');
+		if (s == NULL) {
+			/* Missing final newline?  Otherwise extremely */
+			/* long line - assume file was corrupted */
+			if (feof(mfp->mntent_fp)) {
+				fprintf(stderr, _("[mntent]: warning: no final "
+					"newline at the end of %s\n"),
+					mfp->mntent_file);
+				s = index (buf, 0);
+			} else {
+				mfp->mntent_errs = 1;
+				goto err;
+			}
+		}
+		*s = 0;
+		if (--s >= buf && *s == '\r')
+			*s = 0;
+		s = skip_spaces(buf);
+	} while (*s == '\0' || *s == '#');
+
+	me.mnt_fsname = unmangle(s);
+	s = skip_nonspaces(s);
+	s = skip_spaces(s);
+	me.mnt_dir = unmangle(s);
+	s = skip_nonspaces(s);
+	s = skip_spaces(s);
+	me.mnt_type = unmangle(s);
+	s = skip_nonspaces(s);
+	s = skip_spaces(s);
+	me.mnt_opts = unmangle(s);
+	s = skip_nonspaces(s);
+	s = skip_spaces(s);
+
+	if (isdigit(*s)) {
+		me.mnt_freq = atoi(s);
+		while(isdigit(*s)) s++;
+	} else
+		me.mnt_freq = 0;
+	if(*s && !is_space_or_tab(*s))
+		goto err;
+
+	s = skip_spaces(s);
+	if(isdigit(*s)) {
+		me.mnt_passno = atoi(s);
+		while(isdigit(*s)) s++;
+	} else
+		me.mnt_passno = 0;
+	if(*s && !is_space_or_tab(*s))
+		goto err;
+
+	/* allow more stuff, e.g. comments, on this line */
+
+	return &me;
+
+ err:
+	mfp->mntent_softerrs++;
+	fprintf(stderr, _("[mntent]: line %d in %s is bad%s\n"),
+		mfp->mntent_lineno, mfp->mntent_file,
+		(mfp->mntent_errs || mfp->mntent_softerrs >= ERR_MAX) ?
+		_("; rest of file ignored") : "");
+	goto again;
+}
diff -uprN nfs-utils-1.0.8/support/nfs/xcommon.c nfs-utils-1.0.8-ag/support/nfs/xcommon.c
--- nfs-utils-1.0.8/support/nfs/xcommon.c	1969-12-31 19:00:00.000000000 -0500
+++ nfs-utils-1.0.8-ag/support/nfs/xcommon.c	2006-06-08 11:22:25.940915000 -0400
@@ -0,0 +1,185 @@
+/*
+ * xcommon.c - various functions put together to avoid basic error checking.
+ *
+ * added fcntl locking by Kjetil T. (kjetilho@math.uio.no) - aeb, 950927
+ *
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * - added Native Language Support
+ *
+ * 2006-06-06 Amit Gud <agud@redhat.com>
+ * - Moved code snippets here from mount/sundries.c of util-linux
+ *   and merged code from support/nfs/xmalloc.c by Olaf Kirch <okir@monad.swb.de> here.
+ */
+
+#include <unistd.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xcommon.h"
+#include "nls.h"	/* _() */
+
+void (*at_die)(void ) = NULL;
+
+char *
+xstrndup (const char *s, int n) {
+     char *t;
+
+     if (s == NULL)
+	  die (EX_SOFTWARE, _("bug in xstrndup call"));
+
+     t = xmalloc(n+1);
+     strncpy(t,s,n);
+     t[n] = 0;
+
+     return t;
+}
+
+char *
+xstrconcat2 (const char *s, const char *t) {
+     char *res;
+
+     if (!s) s = "";
+     if (!t) t = "";
+     res = xmalloc(strlen(s) + strlen(t) + 1);
+     strcpy(res, s);
+     strcat(res, t);
+     return res;
+}
+
+/* frees its first arg - typical use: s = xstrconcat3(s,t,u); */
+char *
+xstrconcat3 (const char *s, const char *t, const char *u) {
+     char *res;
+
+     if (!s) s = "";
+     if (!t) t = "";
+     if (!u) u = "";
+     res = xmalloc(strlen(s) + strlen(t) + strlen(u) + 1);
+     strcpy(res, s);
+     strcat(res, t);
+     strcat(res, u);
+     free((void *) s);
+     return res;
+}
+
+/* frees its first arg - typical use: s = xstrconcat4(s,t,u,v); */
+char *
+xstrconcat4 (const char *s, const char *t, const char *u, const char *v) {
+     char *res;
+
+     if (!s) s = "";
+     if (!t) t = "";
+     if (!u) u = "";
+     if (!v) v = "";
+     res = xmalloc(strlen(s) + strlen(t) + strlen(u) + strlen(v) + 1);
+     strcpy(res, s);
+     strcat(res, t);
+     strcat(res, u);
+     strcat(res, v);
+     free((void *) s);
+     return res;
+}
+
+/* Non-fatal error.  Print message and return.  */
+/* (print the message in a single printf, in an attempt
+    to avoid mixing output of several threads) */
+void
+nfs_error (const char *fmt, ...) {
+     va_list args;
+     char *fmt2;
+
+     fmt2 = xstrconcat2 (fmt, "\n");
+     va_start (args, fmt);
+     vfprintf (stderr, fmt2, args);
+     va_end (args);
+     free (fmt2);
+}
+
+/* Make a canonical pathname from PATH.  Returns a freshly malloced string.
+   It is up the *caller* to ensure that the PATH is sensible.  i.e.
+   canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.''
+   is not a legal pathname for ``/dev/fd0''.  Anything we cannot parse
+   we return unmodified.   */
+char *canonicalize (const char *path) {
+	char canonical[PATH_MAX+2];
+
+	if (path == NULL)
+		return NULL;
+
+#if 1
+	if (streq(path, "none") ||
+	    streq(path, "proc") ||
+	    streq(path, "devpts"))
+		return xstrdup(path);
+#endif
+	if (realpath (path, canonical))
+		return xstrdup(canonical);
+
+	return xstrdup(path);
+}
+
+/* Fatal error.  Print message and exit.  */
+void
+die(int err, const char *fmt, ...) {
+	va_list args;
+
+	va_start(args, fmt);
+	vfprintf(stderr, fmt, args);
+	fprintf(stderr, "\n");
+	va_end(args);
+
+	if (at_die)
+		(*at_die)();
+
+	exit(err);
+}
+
+static void
+die_if_null(void *t) {
+	if (t == NULL)
+		die(EX_SYSERR, _("not enough memory"));
+}
+
+void *
+xmalloc (size_t size) {
+	void *t;
+
+	if (size == 0)
+		return NULL;
+
+	t = malloc(size);
+	die_if_null(t);
+
+	return t;
+}
+
+void *
+xrealloc (void *p, size_t size) {
+	void *t;
+
+	t = realloc(p, size);
+	die_if_null(t);
+
+	return t;
+}
+
+void
+xfree(void *ptr)
+{
+	free(ptr);
+}
+
+char *
+xstrdup (const char *s) {
+	char *t;
+
+	if (s == NULL)
+		return NULL;
+
+	t = strdup(s);
+	die_if_null(t);
+
+	return t;
+}
diff -uprN nfs-utils-1.0.8/support/nfs/xmalloc.c nfs-utils-1.0.8-ag/support/nfs/xmalloc.c
--- nfs-utils-1.0.8/support/nfs/xmalloc.c	2005-12-19 23:12:44.000000000 -0500
+++ nfs-utils-1.0.8-ag/support/nfs/xmalloc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/*
- * support/nfs/xmalloc.c
- *
- * malloc with NULL checking.
- *
- * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include "xmalloc.h"
-#include "xlog.h"
-
-void *
-xmalloc(size_t size)
-{
-	void	*ptr;
-
-	if (!(ptr = malloc(size)))
-		xlog(L_FATAL, "malloc: out of memory");
-	return ptr;
-}
-
-void *
-xrealloc(void *ptr, size_t size)
-{
-	if (!(ptr = realloc(ptr, size)))
-		xlog(L_FATAL, "realloc: out of memory");
-	return ptr;
-}
-
-void
-xfree(void *ptr)
-{
-	free(ptr);
-}
-
-char *
-xstrdup(const char *str)
-{
-	char	*ret;
-
-	if (!(ret = strdup(str)))
-		xlog(L_FATAL, "strdup: out of memory");
-	return ret;
-}

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



[-- Attachment #4: Type: text/plain, Size: 140 bytes --]

_______________________________________________
NFS maillist  -  NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs

             reply	other threads:[~2006-06-08 19:08 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-06-08 19:11 Amit Gud [this message]
2006-06-09  6:21 ` [PATCH 2 / 2] Move NFS mount code from util-linux to nfs-utils Neil Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=44887673.1030003@redhat.com \
    --to=agud@redhat.com \
    --cc=SteveD@redhat.com \
    --cc=neilb@suse.de \
    --cc=nfs@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.