summaryrefslogtreecommitdiff
path: root/meta/recipes-devtools/unfs-server/unfs-server-2.2beta47/001-2.2b47-2.2b51.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/unfs-server/unfs-server-2.2beta47/001-2.2b47-2.2b51.patch')
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.2beta47/001-2.2b47-2.2b51.patch2344
1 files changed, 0 insertions, 2344 deletions
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.2beta47/001-2.2b47-2.2b51.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.2beta47/001-2.2b47-2.2b51.patch
deleted file mode 100644
index 886ce92b3..000000000
--- a/meta/recipes-devtools/unfs-server/unfs-server-2.2beta47/001-2.2b47-2.2b51.patch
+++ /dev/null
@@ -1,2344 +0,0 @@
-# Patch origin: nfs-server source RPM from openSUSE 10.3
-
-diff -urN nfs-server-2.2beta47/.version nfs-server-2.2beta51/.version
---- nfs-server-2.2beta47/.version Tue Sep 7 09:47:27 1999
-+++ nfs-server-2.2beta51/.version Fri Nov 8 14:45:36 2002
-@@ -1 +1 @@
--2.2beta46
-+2.2beta51
-diff -urN nfs-server-2.2beta47/ChangeLog nfs-server-2.2beta51/ChangeLog
---- nfs-server-2.2beta47/ChangeLog Wed Nov 10 10:17:51 1999
-+++ nfs-server-2.2beta51/ChangeLog Fri Nov 8 14:45:36 2002
-@@ -1,8 +1,59 @@
-+Thu Nov 9 17:03:05 2000
-+
-+ * No longer use OPEN_MAX
-+
-+ * Reworked configure.in, BUILD script no longer needed
-+ (nor functioning)
-+
-+ * Be more anal about matching cached fh's and real files.
-+ In addition to the psi, we also store dev/ino/type now
-+ and match that in fh_find.
-+
-+ * Write pidfiles
-+
-+ * Support nosetuid
-+
-+Wed Feb 9 14:52:34 2000
-+
-+ * auth_init.c didn't properly parse options--rot_squash
-+ which is obviously a typo was parsed as ro.
-+ Thanks to Jan Steffan for complaining about this :-)
-+
-+Mon Jan 31 11:48:34 2000
-+
-+ * Fixed Y2K bug in logging.c.
-+ Thanks to Jonathan Hankins <jhankins@homewood.k12.al.us>.
-+
-+Thu Dec 9 11:14:21 1999
-+
-+ * Fix handling of NFS-mounted and /proc directories.
-+ They weren't properly hidden.
-+ Thanks to Dick Streefland <dick_streefland@tasking.com>
-+ for the report and a first patch.
-+
- Wed Nov 10 10:17:16 1999
-
- * Security fix for buffer overflow in fh_buildpath
- No thanks to Mariusz who reported it to bugtraq
- rather than me.
-+
-+Wed Nov 09 17:10:00 1999
-+
-+ * Workaround for broken Solaris clients that can't handle
-+ atime/mtime/ctime of 0.
-+ Thanks to Frank Wuebbelin for his problem report and
-+ testing the fix.
-+
-+ * Fixed typo in exports.man
-+
-+Tue Nov 2 10:31:14 1999
-+
-+ * Patch for mode 0100 and 0100 executables by
-+ Michael Deutschmann <michael@talamasca.wkpowerlink.com>
-+
-+ * Common startup stuff for all daemons.
-+ Inspired by code sent to me by someone (sorry, I forgot
-+ your name, and the mail's gone!)
-
- Wed Sep 8 09:07:38 1999
-
-diff -urN nfs-server-2.2beta47/Makefile.in nfs-server-2.2beta51/Makefile.in
---- nfs-server-2.2beta47/Makefile.in Tue Jun 22 14:53:10 1999
-+++ nfs-server-2.2beta51/Makefile.in Fri Nov 8 14:45:36 2002
-@@ -17,23 +17,30 @@
-
- #### Start of system configuration section. ####
-
--srcdir = @srcdir@
--VPATH = @srcdir@
-+srcdir = @srcdir@
-+VPATH = @srcdir@
-
--CC = @CC@
--AR = ar
--RANLIB = @RANLIB@
--
--INSTALL = @INSTALL@
--INSTALL_PROGRAM = @INSTALL_PROGRAM@ -m 755
--INSTALL_DATA = @INSTALL_DATA@
--MAKEINFO = makeinfo
--TEXI2DVI = texi2dvi
--RPCGEN = @RPCGEN@ @RPCGEN_C@
-+CC = @CC@
-+AR = ar
-+RANLIB = @RANLIB@
-+
-+INSTALL = @INSTALL@
-+INSTALL_PROGRAM = @INSTALL_PROGRAM@ -m 755
-+INSTALL_DATA = @INSTALL_DATA@
-+MAKEINFO = makeinfo
-+TEXI2DVI = texi2dvi
-+RPCGEN = @RPCGEN@ @RPCGEN_C@
-
- # General compile options and libs:
--DEFS = @DEFS@ $(NFSD_DEFS)
--LIBS = libnfs.a @LIBS@
-+DEFS = @DEFS@ $(NFSD_DEFS)
-+LIBS = libnfs.a @LIBS@
-+
-+# Ugidd support
-+UGIDD_PROG = @UGIDD_PROG@
-+UGIDD_MAN = @UGIDD_MAN@
-+
-+# New inode mapping scheme
-+DEVTAB_FILE = $(install_prefix)@PATH_DEVTAB@
-
- # Compile options for nfsd:
- # CALL_PROFILING
-@@ -80,9 +87,6 @@
-
- #### End of system configuration section. ####
-
--# include site-specific defintions generated by BUILD.
--include site.mk
--
- SHELL = /bin/sh
-
- SRCS = version.c logging.c fh.c devtab.c \
-@@ -96,19 +100,19 @@
- utimes.c mkdir.c rename.c getopt.c getopt_long.c \
- alloca.c mountlist.c xmalloc.c \
- xstrdup.c strdup.c strstr.c nfsmounted.c faccess.c \
-- haccess.c failsafe.c signals.c
-+ haccess.c daemon.c signals.c
- XDRFILES = mount.x nfs_prot.x
- GENFILES = mount.h mount_xdr.c mount_svc.c nfs_prot.h nfs_prot_xdr.c \
- ugid.h ugid_xdr.c ugid_clnt.c
- HDRS = system.h nfsd.h auth.h fh.h logging.h fakefsuid.h \
- rpcmisc.h faccess.h rquotad.h rquota.h haccess.h
--LIBHDRS = fsusage.h getopt.h mountlist.h failsafe.h signals.h
-+LIBHDRS = fsusage.h getopt.h mountlist.h daemon.h signals.h
- MANPAGES5 = exports
- MANPAGES8p = mountd nfsd $(UGIDD_MAN)
- MANPAGES8 = showmount
- MANPAGES = $(MANPAGES5) $(MANPAGES8p) $(MANPAGES8)
- LIBOBJS = version.o fsusage.o mountlist.o xmalloc.o xstrdup.o \
-- nfsmounted.o faccess.o haccess.o failsafe.o \
-+ nfsmounted.o faccess.o haccess.o daemon.o \
- signals.o @LIBOBJS@ @ALLOCA@
- OBJS = logging.o fh.o devtab.o auth_init.o auth_clnt.o auth.o
- NFSD_OBJS = nfsd.o rpcmisc.o nfs_dispatch.o getattr.o setattr.o \
-@@ -174,15 +178,13 @@
- ${srcdir}/mkinstalldirs $(bindir) $(man5dir) $(man8dir)
-
- $(rpcprefix)mountd: $(MOUNTD_OBJS) libnfs.a
-- $(CC) $(LDFLAGS) -o $@ $(MOUNTD_OBJS) $(LIBS) \
-- $(LIBWRAP_DIR) $(LIBWRAP_LIB)
-+ $(CC) $(LDFLAGS) -o $@ $(MOUNTD_OBJS) $(LIBS)
-
- $(rpcprefix)nfsd: $(NFSD_OBJS) libnfs.a
- $(CC) $(LDFLAGS) -o $@ $(NFSD_OBJS) $(LIBS)
-
- $(rpcprefix)ugidd: $(UGIDD_OBJS) libnfs.a
-- $(CC) $(LDFLAGS) -o $@ $(UGIDD_OBJS) $(LIBS) \
-- $(LIBWRAP_DIR) $(LIBWRAP_LIB)
-+ $(CC) $(LDFLAGS) -o $@ $(UGIDD_OBJS) $(LIBS)
-
- showmount: $(SHOWMOUNT_OBJS) libnfs.a
- $(CC) $(LDFLAGS) -o $@ $(SHOWMOUNT_OBJS) $(LIBS)
-diff -urN nfs-server-2.2beta47/aclocal.m4 nfs-server-2.2beta51/aclocal.m4
---- nfs-server-2.2beta47/aclocal.m4 Fri Jun 11 12:04:22 1999
-+++ nfs-server-2.2beta51/aclocal.m4 Fri Nov 8 14:45:36 2002
-@@ -221,20 +221,14 @@
- ])dnl
- dnl *********** libwrap bug **************
- define(AC_LIBWRAP_BUG,
-- [if test -f site.mk; then
-- . ./site.mk
-- fi
-- if test ! -z "$LIBWRAP_DIR"; then
-+ [if test "$ac_cv_lib_wrap_main" = yes; then
- AC_MSG_CHECKING(for link problem with libwrap.a)
- AC_CACHE_VAL(nfsd_cv_lib_wrap_bug,
-- [ac_save_LIBS=$LIBS
-- LIBS="$LIBS $LIBWRAP_DIR $LIBWRAP_LIB"
-- AC_TRY_LINK([
-+ [AC_TRY_LINK([
- extern int deny_severity;
- ],[
- deny_severity=1;
- ], nfsd_cv_lib_wrap_bug=no, nfsd_cv_lib_wrap_bug=yes)
-- LIBS=$ac_save_LIBS
- ]) dnl
- AC_MSG_RESULT($nfsd_cv_lib_wrap_bug)
- test $nfsd_cv_lib_wrap_bug = yes && AC_DEFINE(HAVE_LIBWRAP_BUG)
-diff -urN nfs-server-2.2beta47/auth.c nfs-server-2.2beta51/auth.c
---- nfs-server-2.2beta47/auth.c Mon Sep 13 16:56:03 1999
-+++ nfs-server-2.2beta51/auth.c Fri Nov 8 14:45:36 2002
-@@ -84,8 +84,9 @@
- 0, /* relative links */
- 0, /* noaccess */
- 1, /* cross_mounts */
-- (uid_t)-2, /* default uid */
-- (gid_t)-2, /* default gid */
-+ 1, /* allow setuid */
-+ 65534, /* default uid */
-+ 65534, /* default gid */
- 0, /* no NIS domain */
- };
-
-@@ -99,8 +100,9 @@
- 0, /* relative links */
- 0, /* noaccess */
- 1, /* cross_mounts */
-- (uid_t)-2, /* default uid */
-- (gid_t)-2, /* default gid */
-+ 0, /* allow setuid */
-+ 65534, /* default uid */
-+ 65534, /* default gid */
- 0, /* no NIS domain */
- };
-
-@@ -673,6 +675,7 @@
- cpp = &unknown_clients;
- } else {
- cpp = &known_clients;
-+ cp->clnt_addr = *(struct in_addr *) hp->h_addr;
- auth_hash_host(cp, hp);
- }
- cp->next = *cpp;
-diff -urN nfs-server-2.2beta47/auth.h nfs-server-2.2beta51/auth.h
---- nfs-server-2.2beta47/auth.h Thu Apr 8 14:47:56 1999
-+++ nfs-server-2.2beta51/auth.h Fri Nov 8 14:45:36 2002
-@@ -23,14 +23,6 @@
- extern char * public_root_path;
- extern struct nfs_fh public_root;
-
--#if defined(linux) && defined(i386) && !defined(HAVE_SETFSUID)
--# define MAYBE_HAVE_SETFSUID
--#endif
--
--#ifdef MAYBE_HAVE_SETFSUID
--extern int have_setfsuid;
--#endif
--
- /*
- * These externs are set in the dispatcher (dispatch.c) and auth_fh
- * (nfsd.c) so that we can determine access rights, export options,
-@@ -59,6 +51,7 @@
- int link_relative;
- int noaccess;
- int cross_mounts;
-+ int allow_setuid;
- uid_t nobody_uid;
- gid_t nobody_gid;
- char * clnt_nisdomain;
-@@ -112,7 +105,7 @@
- extern void auth_free_lists(void);
- extern nfs_client *auth_clnt(struct svc_req *rqstp);
- extern nfs_mount *auth_path(nfs_client *, struct svc_req *, char *);
--extern void auth_user(nfs_mount *, struct svc_req *);
-+extern int auth_user(nfs_mount *, struct svc_req *);
-
- extern nfs_client *auth_get_client(char *);
- extern nfs_mount *auth_match_mount(nfs_client *, char *);
-diff -urN nfs-server-2.2beta47/auth_clnt.c nfs-server-2.2beta51/auth_clnt.c
---- nfs-server-2.2beta47/auth_clnt.c Wed Nov 10 10:18:06 1999
-+++ nfs-server-2.2beta51/auth_clnt.c Fri Nov 8 14:45:36 2002
-@@ -12,20 +12,17 @@
- */
-
-
-+#include <sys/fsuid.h>
- #include "system.h"
- #include "nfsd.h"
--#include "fakefsuid.h"
--
--#ifndef svc_getcaller
--#define svc_getcaller(x) ((struct sockaddr_in *) &(x)->xp_rtaddr.buf)
--#endif
-+#include "rpcmisc.h"
-
-
--#if defined(HAVE_SETFSUID) || defined(MAYBE_HAVE_SETFSUID)
--static void setfsids(uid_t, gid_t, gid_t *, int);
-+#if defined(HAVE_SETFSUID)
-+static int setfsids(uid_t, gid_t, gid_t *, int);
- #endif
- #ifndef HAVE_SETFSUID
--static void seteids(uid_t, gid_t, gid_t *, int);
-+static int seteids(uid_t, gid_t, gid_t *, int);
- #endif
-
- uid_t auth_uid = 0; /* Current effective user ids */
-@@ -43,6 +40,17 @@
- short *gid, short *nrgids, int *groups);
- #endif
-
-+/*
-+ * The following crap is required for glibc 2.1 which has 32bit uids
-+ * in user land mapped to 16bit uids in the Linux kernel
-+ */
-+#if defined(HAVE_BROKEN_SETFSUID)
-+# define native_uid(u) ((unsigned short)(u))
-+# define native_gid(g) ((unsigned short)(g))
-+#else
-+# define native_uid(u) (u)
-+# define native_gid(g) (g)
-+#endif
-
- /*
- * For an RPC request, look up the NFS client info along with the
-@@ -92,8 +100,9 @@
- }
-
- if (logging_enabled(D_AUTH)) {
-- Dprintf(D_AUTH, "auth_path(%s): mount point %s, (%s%s%s%s%s)\n",
-- path, mp->path,
-+ Dprintf(D_AUTH, "auth_path(%s, %s): "
-+ "mount point %s, (%s%s%s%s%s)\n",
-+ inet_ntoa(cp->clnt_addr), path, mp->path,
- mp->o.all_squash? "all_squash " : (
- mp->o.root_squash? "root_squash " : ""),
- (mp->o.uidmap == map_daemon)? "uidmap " : "",
-@@ -105,7 +114,8 @@
- return mp;
- }
-
--void auth_user(nfs_mount *mp, struct svc_req *rqstp)
-+int
-+auth_user(nfs_mount *mp, struct svc_req *rqstp)
- {
- uid_t cuid;
- gid_t cgid;
-@@ -160,23 +170,18 @@
- else if (cred_len > NGRPS)
- cred_len = NGRPS;
-
-- cuid = luid(cred_uid, mp, rqstp);
-- cgid = lgid(cred_gid, mp, rqstp);
-+ cuid = luid(native_uid(cred_uid), mp, rqstp);
-+ cgid = lgid(native_gid(cred_gid), mp, rqstp);
- clen = cred_len;
- for (i = 0; i < cred_len; i++)
-- cgids[i] = lgid(cred_gids[i], mp, rqstp);
-+ cgids[i] = lgid(native_gid(cred_gids[i]), mp, rqstp);
- } else {
- /* On systems that have 32bit uid_t in user space but
- * 16bit in the kernel, we need to truncate the
- * nobody ID (default -2).
- */
--#if !defined(HAVE_BROKEN_SETFSUID)
-- cuid = mp->o.nobody_uid;
-- cgid = mp->o.nobody_gid;
--#else
-- cuid = (unsigned short) mp->o.nobody_uid;
-- cgid = (unsigned short) mp->o.nobody_gid;
--#endif
-+ cuid = native_uid(mp->o.nobody_uid);
-+ cgid = native_gid(mp->o.nobody_gid);
- /* Construct a list of one gid. */
- cgids[0] = cgid;
- clen = 1;
-@@ -193,14 +198,9 @@
- * upper 16 bits set (including our default nobody uid -2).
- */
- #if defined(HAVE_SETFSUID)
-- setfsids(cuid, cgid, cgids, clen);
-+ return setfsids(cuid, cgid, cgids, clen);
- #else
--#if defined(MAYBE_HAVE_SETFSUID)
-- if (have_setfsuid)
-- setfsids(cuid, cgid, cgids, clen);
-- else
--#endif
-- seteids(cuid, cgid, cgids, clen);
-+ return seteids(cuid, cgid, cgids, clen);
- #endif
- }
-
-@@ -210,6 +210,8 @@
- void
- auth_override_uid(uid_t uid)
- {
-+ int res;
-+
- /* extension hooks: */
- efs_setfsuid(uid);
-
-@@ -217,19 +219,18 @@
- uid = (unsigned short) uid;
- #endif
- #if defined(HAVE_SETFSUID)
-- setfsuid(uid);
-+ res = setfsuid(uid);
- #else
--#if defined(MAYBE_HAVE_SETFSUID)
-- if (have_setfsuid)
-- setfsuid(uid);
-- else
--#endif
-- seteuid(uid);
-+ res = seteuid(uid);
- #endif
-+ /* should never happen */
-+ if (res < 0)
-+ Dprintf(L_FATAL, "auth_override_uid(%d) failed: %s",
-+ uid, strerror(errno));
- }
-
--#if defined(HAVE_SETFSUID) || defined(MAYBE_HAVE_SETFSUID)
--static void
-+#if defined(HAVE_SETFSUID)
-+static int
- setfsids(uid_t cred_uid, gid_t cred_gid, gid_t *cred_gids, int cred_len)
- {
- /* extension hooks: */
-@@ -238,43 +239,47 @@
-
- /* First, set the user ID. */
- if (auth_uid != cred_uid) {
-- if (setfsuid(cred_uid) < 0)
-+ if (setfsuid(cred_uid) < 0) {
- Dprintf(L_ERROR, "Unable to setfsuid %d: %s\n",
- cred_uid, strerror(errno));
-- else
-- auth_uid = cred_uid;
-+ return 0;
-+ }
-+ auth_uid = cred_uid;
- }
-
- /* Next, the group ID. */
- if (auth_gid != cred_gid) {
-- if (setfsgid(cred_gid) < 0)
-+ if (setfsgid(cred_gid) < 0) {
- Dprintf(L_ERROR, "Unable to setfsgid %d: %s\n",
- cred_gid, strerror(errno));
-- else
-- auth_gid = cred_gid;
-+ return 0;
-+ }
-+ auth_gid = cred_gid;
- }
-
- #ifdef HAVE_SETGROUPS
- /* Finally, set the supplementary group IDs if possible. */
-- if (cred_len < 0 || cred_len > NGRPS)
-+ if (cred_len < 0 || cred_len > NGRPS) {
- Dprintf(L_ERROR, "Negative or huge cred_len: %d\n", cred_len);
-- else if (cred_len != auth_gidlen
-- || memcmp(cred_gids, auth_gids, auth_gidlen*sizeof(gid_t))) {
-- if (setgroups(cred_len, cred_gids) < 0)
-+ return 0;
-+ }
-+ if (cred_len != auth_gidlen
-+ || memcmp(cred_gids, auth_gids, auth_gidlen*sizeof(gid_t))) {
-+ if (setgroups(cred_len, cred_gids) < 0) {
- Dprintf(L_ERROR, "Unable to setgroups: %s\n",
- strerror(errno));
-- else {
-- memcpy(auth_gids, cred_gids, cred_len*sizeof(gid_t));
-- auth_gidlen = cred_len;
-+ return 0;
- }
-+ memcpy(auth_gids, cred_gids, cred_len*sizeof(gid_t));
-+ auth_gidlen = cred_len;
- }
- #endif /* HAVE_SETGROUPS */
--
-+ return 1;
- }
- #endif
-
- #if !defined(HAVE_SETFSUID)
--static void
-+static int
- seteids(uid_t cred_uid, gid_t cred_gid, gid_t *cred_gids, int cred_len)
- {
- /* extension hooks: */
-@@ -286,52 +291,62 @@
- /* First set the group ID. */
- if (auth_gid != cred_gid) {
- if (auth_uid != ROOT_UID) {
-- if (seteuid(ROOT_UID) < 0)
-+ if (seteuid(ROOT_UID) < 0) {
- Dprintf(L_ERROR, "Unable to seteuid(%d): %s\n",
- ROOT_UID, strerror(errno));
-- else
-- auth_uid = ROOT_UID;
-+ return 0;
-+ }
-+ auth_uid = ROOT_UID;
- }
-- if (setegid(cred_gid) < 0)
-+ if (setegid(cred_gid) < 0) {
- Dprintf(L_ERROR, "Unable to setegid(%d): %s\n",
- cred_gid, strerror(errno));
-- else
-- auth_gid = cred_gid;
-+ return 0;
-+ }
-+ auth_gid = cred_gid;
- }
-
- #ifdef HAVE_SETGROUPS
- /* Next set the supplementary group IDs if possible. */
-- if (cred_len < 0 || cred_len > NGRPS)
-+ if (cred_len < 0 || cred_len > NGRPS) {
- Dprintf(L_ERROR, "Negative or huge cred_len: %d\n", cred_len);
-- else if (cred_len != auth_gidlen
-- || memcmp(cred_gids, auth_gids, auth_gidlen*sizeof(gid_t))) {
-+ return 0;
-+ }
-+ if (cred_len != auth_gidlen
-+ || memcmp(cred_gids, auth_gids, auth_gidlen*sizeof(gid_t))) {
- if (auth_uid != ROOT_UID) {
-- if (seteuid(ROOT_UID) < 0)
-+ if (seteuid(ROOT_UID) < 0) {
- Dprintf(L_ERROR, "Unable to seteuid(%d): %s\n",
- ROOT_UID, strerror(errno));
-- else
-- auth_uid = ROOT_UID;
-+ return 0;
-+ }
-+ auth_uid = ROOT_UID;
- }
-- if (setgroups(cred_len, cred_gids) < 0)
-+ if (setgroups(cred_len, cred_gids) < 0) {
- Dprintf(L_ERROR, "Unable to setgroups: %s\n",
- strerror(errno));
-- else {
-- memcpy(auth_gids, cred_gids, cred_len*sizeof(gid_t));
-- auth_gidlen = cred_len;
-+ return 0;
- }
-+ memcpy(auth_gids, cred_gids, cred_len*sizeof(gid_t));
-+ auth_gidlen = cred_len;
- }
- #endif /* HAVE_SETGROUPS */
-
- /* Finally, set the user ID. */
- if (auth_uid != cred_uid) {
-- if (auth_uid != ROOT_UID && seteuid(ROOT_UID) < 0)
-+ if (auth_uid != ROOT_UID && seteuid(ROOT_UID) < 0) {
- Dprintf(L_ERROR, "Unable to seteuid(%d): %s\n",
- ROOT_UID, strerror(errno));
-- if (seteuid(cred_uid) < 0)
-+ return 0;
-+ }
-+ if (seteuid(cred_uid) < 0) {
- Dprintf(L_ERROR, "Unable to seteuid(%d): %s\n",
- cred_uid, strerror(errno));
-- else
-- auth_uid = cred_uid;
-+ return 0;
-+ }
-+ auth_uid = cred_uid;
- }
-+
-+ return 1;
- }
- #endif
-diff -urN nfs-server-2.2beta47/auth_init.c nfs-server-2.2beta51/auth_init.c
---- nfs-server-2.2beta47/auth_init.c Mon Apr 19 14:01:21 1999
-+++ nfs-server-2.2beta51/auth_init.c Fri Nov 8 14:45:36 2002
-@@ -13,7 +13,6 @@
- */
-
- #include "nfsd.h"
--#include "fakefsuid.h"
- #include <pwd.h>
-
- #define LINE_SIZE 1024
-@@ -263,55 +262,63 @@
- cp++;
- while (*cp != terminator) {
- kwd = cp;
-- while (isalpha(*cp) || *cp == '_' || *cp == '=') {
-- /* break out of loop after = sign */
-- if (*cp++ == '=')
-- break;
-- }
-+ /* Gobble up keyword and "=" if there is one */
-+ while (isalpha(*cp) || *cp == '_')
-+ ++cp;
-+ if (*cp == '=')
-+ ++cp;
-+
- klen = cp - kwd;
-
- /* process keyword */
-- if (strncmp(kwd, "secure", 6) == 0)
-+#define ifkwd(n, string) \
-+ if (klen == (n) && !strncmp(kwd, string, (n)))
-+
-+ ifkwd(2, "ro")
-+ mp->o.read_only = 1;
-+ else ifkwd(2, "rw")
-+ mp->o.read_only = 0;
-+ else ifkwd(6, "secure")
- mp->o.secure_port = 1;
-- else if (strncmp(kwd, "insecure", 8) == 0)
-+ else ifkwd(8, "insecure")
- mp->o.secure_port = 0;
-- else if (strncmp(kwd, "root_squash", 11) == 0)
-+ else ifkwd(11, "root_squash")
- mp->o.root_squash = 1;
-- else if (strncmp(kwd, "no_root_squash", 14) == 0)
-+ else ifkwd(14, "no_root_squash")
- mp->o.root_squash = 0;
-- else if (strncmp(kwd, "ro", 2) == 0)
-- mp->o.read_only = 1;
-- else if (strncmp(kwd, "rw", 2) == 0)
-- mp->o.read_only = 0;
-- else if (strncmp(kwd, "link_relative", 13) == 0)
-+ else ifkwd(13, "link_relative")
- mp->o.link_relative = 1;
-- else if (strncmp(kwd, "link_absolute", 13) == 0)
-+ else ifkwd(13, "link_absolute")
- mp->o.link_relative = 0;
-- else if (strncmp(kwd, "map_daemon", 10) == 0)
-+ else ifkwd(10, "map_daemon")
- mp->o.uidmap = map_daemon;
-- else if (strncmp(kwd, "map_nis=", 8) == 0)
-+ else ifkwd(8, "map_nis=")
- parse_nis_uidmap(mp, &cp);
-- else if (strncmp(kwd, "map_static=", 11) == 0)
-+ else ifkwd(11, "map_static=")
- parse_static_uidmap(mp, &cp);
-- else if (strncmp(kwd, "map_identity", 12) == 0)
-+ else ifkwd(12, "map_identity")
- mp->o.uidmap = identity;
-- else if (strncmp(kwd, "all_squash", 10) == 0)
-+ else ifkwd(10, "all_squash")
- mp->o.all_squash = 1;
-- else if (strncmp(kwd, "no_all_squash", 13) == 0)
-+ else ifkwd(13, "no_all_squash")
- mp->o.all_squash = 0;
-- else if (strncmp(kwd, "noaccess", 8) == 0)
-+ else ifkwd(8, "noaccess")
- mp->o.noaccess = 1;
-- else if (strncmp(kwd, "squash_uids=", 12) == 0)
-+ else ifkwd(12, "squash_uids=")
- parse_squash(mp, 1, &cp);
-- else if (strncmp(kwd, "squash_gids=", 12) == 0)
-+ else ifkwd(12, "squash_gids=")
- parse_squash(mp, 0, &cp);
-- else if (strncmp(kwd, "anonuid=", 8) == 0)
-+ else ifkwd(8, "anonuid=")
- mp->o.nobody_uid = parse_num(&cp);
-- else if (strncmp(kwd, "anongid=", 8) == 0)
-+ else ifkwd(8, "anongid=")
- mp->o.nobody_gid = parse_num(&cp);
-- else if (strncmp(kwd, "async", 5) == 0)
-+ else ifkwd(6, "setuid")
-+ mp->o.allow_setuid = 1;
-+ else ifkwd(8, "nosetuid")
-+ mp->o.allow_setuid = 0;
-+ else ifkwd(5, "async")
- /* knfsd compatibility, ignore */;
-- else if (strncmp(kwd, "sync", 4) == 0)
-+ else ifkwd(4, "sync")
- /* knfsd compatibility, ignore */;
- else {
- Dprintf(L_ERROR,
-@@ -566,11 +573,6 @@
- auth_check_all_wildcards();
- auth_sort_all_mountlists();
- auth_log_all();
--
--#if defined(MAYBE_HAVE_SETFSUID) && !defined(HAVE_SETFSUID)
-- /* check if the a.out setfsuid syscall works on this machine */
-- have_setfsuid = (setfsuid(0) >= 0);
--#endif
-
- auth_initialized = 1;
- }
-diff -urN nfs-server-2.2beta47/config.h.in nfs-server-2.2beta51/config.h.in
---- nfs-server-2.2beta47/config.h.in Fri Jun 11 12:01:22 1999
-+++ nfs-server-2.2beta51/config.h.in Fri Nov 8 14:45:36 2002
-@@ -3,7 +3,7 @@
- /* Define if on AIX 3.
- System headers sometimes define this.
- We just want to avoid a redefinition error message. */
--#ifndef _ALL_SOURCE
-+#ifdef _ALL_SOURCE
- #undef _ALL_SOURCE
- #endif
-
-diff -urN nfs-server-2.2beta47/configure.in nfs-server-2.2beta51/configure.in
---- nfs-server-2.2beta47/configure.in Fri Jun 11 11:58:10 1999
-+++ nfs-server-2.2beta51/configure.in Fri Nov 8 14:45:36 2002
-@@ -2,7 +2,36 @@
- dnl Updated for autoconf 2.
- dnl
- AC_INIT(nfsd.c)
--AC_CONFIG_HEADER(config.h)
-+AC_CONFIG_HEADER(config.h site.h)
-+
-+dnl **************************************************************
-+dnl * handle --enable options
-+dnl **************************************************************
-+AC_ARG_ENABLE(new-inodes,
-+ [ --enable-new-inodes Enable new-style inode inodes])
-+AC_ARG_WITH(devtab,
-+ [ --with-devtab=file Specify location for devtab [/var/lib/nfs/devtab]],
-+ PATH_DEVTAB=$withval,
-+ PATH_DEVTAB=/var/lib/nfs/devtab)
-+AC_ARG_ENABLE(ugid-dynamic,
-+ [ --enable-ugid-dynamic Enable uid mapping using rpc.ugidd (not recommended)])
-+AC_ARG_ENABLE(ugid-nis,
-+ [ --enable-ugid-nis Enable NIS-based uid mapping])
-+AC_ARG_ENABLE(host-access,
-+ [ --enable-host-access Enable host access checking])
-+AC_ARG_ENABLE(mount-logging,
-+ [ --disable-mount-logging Do not log mount operations to syslog],,
-+ enable_mount_logging=yes)
-+AC_ARG_WITH(exports-uid,
-+ [ --with-exports-uid=N Make sure that /etc/exports is owned by uid N],,
-+ with_exports_uid=0)
-+AC_ARG_WITH(exports-gid,
-+ [ --with-exports-gid=N Make sure that /etc/exports is owned by gid N],,
-+ with_exports_gid=0)
-+
-+dnl **************************************************************
-+dnl * Check for all kinds of stuff
-+dnl **************************************************************
- AC_PROG_CC
- # If we're using gcc, we want warning flags
- test -n "$GCC" &&
-@@ -19,7 +48,7 @@
- AC_MINIX
- AC_ISC_POSIX
- AC_PROG_INSTALL
--AC_CROSS_CHECK
-+dnl AC_CROSS_CHECK
- AC_STDC_HEADERS
- AC_GNULIBC
- AC_CONST
-@@ -52,14 +81,45 @@
- AC_CHECK_LIB(rpc, main)
- AC_CHECK_LIB(crypt, main)
- AC_CHECK_LIB(nys, main)
--AC_REPLACE_FUNCS(strerror realpath mkdir rename utimes strdup strstr getopt getopt_long)
- AC_HAVE_FUNCS(getcwd seteuid setreuid getdtablesize setgroups lchown setsid setfsuid setfsgid innetgr quotactl authdes_getucred)
- AC_AUTHDES_GETUCRED
- AC_BROKEN_SETFSUID
- AC_MOUNTLIST
- AC_FSUSAGE
-+AC_CHECK_LIB(wrap, main)
- AC_LIBWRAP_BUG
- AC_BSD_SIGNALS
-+
-+dnl **************************************************************
-+dnl * Munge user specified options
-+dnl **************************************************************
-+if test "$enable_new_inodes" = yes; then
-+ AC_DEFINE(ENABLE_DEVTAB)
-+fi
-+if test "$enable_ugid_dynamic" = yes; then
-+ AC_DEFINE(ENABLE_UGID_DAEMON)
-+ UGIDD_PROG=\${rpcprefix}.ugidd
-+ UGIDD_MAN=ugidd
-+fi
-+if test "$enable_ugid_nis" = yes; then
-+ AC_DEFINE(ENABLE_UGID_NIS)
-+fi
-+if test "$enable_host_access" = yes; then
-+ AC_DEFINE(HOSTS_ACCESS)
-+fi
-+if test "$enable_mount_logging" = yes; then
-+ AC_DEFINE(WANT_LOG_MOUNTS)
-+fi
-+AC_DEFINE_UNQUOTED(EXPORTSOWNERUID, $with_exports_uid)
-+AC_DEFINE_UNQUOTED(EXPORTSOWNERGID, $with_exports_gid)
-+AC_SUBST(PATH_DEVTAB)
-+AC_SUBST(UGIDD_PROG)
-+AC_SUBST(UGIDD_MAN)
-+
-+dnl **************************************************************
-+dnl * Output CFLAGS and LDFLAGS
-+dnl **************************************************************
- AC_SUBST(LDFLAGS)
- AC_SUBST(CFLAGS)
-+
- AC_OUTPUT(Makefile)
-diff -urN nfs-server-2.2beta47/daemon.c nfs-server-2.2beta51/daemon.c
---- nfs-server-2.2beta47/daemon.c Thu Jan 1 01:00:00 1970
-+++ nfs-server-2.2beta51/daemon.c Fri Nov 8 14:45:52 2002
-@@ -0,0 +1,270 @@
-+/*
-+ * daemon.c
-+ *
-+ * Copyright (C) 1998, <okir@monad.swb.de>
-+ *
-+ * Implements common daemon stuff and
-+ * fail-safe mode for nfsd/mountd.
-+ */
-+
-+#include "system.h"
-+#include "logging.h"
-+#include "signals.h"
-+#include <sys/wait.h>
-+
-+static const char * pidfilename = 0;
-+static const char * get_signame(int signo);
-+
-+/*
-+ * Do the Crawley Thing
-+ */
-+void
-+daemonize(void)
-+{
-+ int c;
-+
-+ /* Ignore SIGHUP so the parent can exit while we're still
-+ * in limbo */
-+ ignore_signal(SIGHUP);
-+
-+ /* Now fork */
-+ c = fork();
-+ if (c < 0)
-+ Dprintf(L_FATAL, "unable to fork: %s", strerror(errno));
-+
-+ /* Parent process: exit */
-+ if (c > 0)
-+ exit(0);
-+
-+ /* Do the session stuff */
-+ close(0);
-+ close(1);
-+ close(2);
-+#ifdef HAVE_SETSID
-+ setsid();
-+#else
-+ if ((c = open("/dev/tty", O_RDWR)) >= 0) {
-+ ioctl(c, TIOCNOTTY, (char *) NULL);
-+ close(c);
-+ }
-+#endif
-+
-+ /* Stop stderr logging */
-+ background_logging();
-+}
-+
-+void
-+setpidpath(const char *filename)
-+{
-+ pidfilename = filename;
-+}
-+
-+void
-+writepid(pid_t pid, int clear)
-+{
-+ FILE *fp;
-+
-+ fp = fopen(pidfilename, clear? "w" : "a");
-+ if (fp == NULL)
-+ Dprintf(L_FATAL, "Unable to open %s: %m", pidfilename);
-+ fprintf(fp, "%d\n", pid);
-+ fclose(fp);
-+ return;
-+}
-+
-+void
-+failsafe(int level, int ncopies)
-+{
-+ int *servers, running, child, i;
-+ int pid, signo, status;
-+ time_t last_restart = 0, now;
-+ int restarts = 0, backoff = 60;
-+
-+ servers = (int *) xmalloc(ncopies * sizeof(int));
-+ memset(servers, 0, ncopies * sizeof(int));
-+
-+ /* Loop forever, until we get SIGTERM */
-+ running = 0;
-+ while (1) {
-+ /* Rewrite the pidfile */
-+ writepid(getpid(), 1);
-+ for (i = 0; i < ncopies; i++) {
-+ if (servers[i] != 0)
-+ writepid(servers[i], 0);
-+ }
-+
-+ while (running < ncopies) {
-+ if ((now = time(NULL)) == last_restart) {
-+ if (++restarts > 2 * ncopies) {
-+ Dprintf(L_ERROR,
-+ "Servers restarting too "
-+ "quickly, backing off.");
-+ if (backoff < 60 * 60)
-+ backoff <<= 1;
-+ sleep(backoff);
-+ }
-+ } else {
-+ last_restart = now;
-+ restarts = 0;
-+ backoff = 60;
-+ }
-+
-+ /* Locate a free pid slot */
-+ for (i = 0, child = -1; i < ncopies; i++) {
-+ if (servers[i] == 0) {
-+ child = i;
-+ break;
-+ }
-+ }
-+
-+ if (child < 0)
-+ Dprintf(L_FATAL, "failsafe: no pid slot?!");
-+
-+ Dprintf(D_GENERAL,
-+ "starting server thread %d...\n", child + 1);
-+
-+ pid = fork();
-+ if (pid < 0)
-+ Dprintf(L_FATAL,
-+ "Unable to fork for failsafe: %s",
-+ strerror(errno));
-+
-+ if (pid == 0) {
-+ /* Child process: continue with execution. */
-+ return;
-+ }
-+
-+ writepid(pid, 0);
-+ servers[child] = pid;
-+ running++;
-+ }
-+
-+ /* Ignore some signals */
-+ ignore_signal(SIGTERM);
-+ ignore_signal(SIGHUP);
-+ ignore_signal(SIGINT);
-+ ignore_signal(SIGCHLD);
-+
-+ if ((pid = wait(&status)) < 0) {
-+ Dprintf((errno == ECHILD)? L_FATAL : L_WARNING,
-+ "failsafe: wait(): %s", strerror(errno));
-+ continue;
-+ }
-+
-+ /* Locate the child */
-+ for (i = 0, child = -1; i < ncopies; i++) {
-+ if (servers[i] == pid) {
-+ child = i;
-+ break;
-+ }
-+ }
-+
-+ if (child < 0) {
-+ Dprintf(L_WARNING,
-+ "failsafe: unknown child (pid %d) terminated",
-+ pid);
-+ continue;
-+ }
-+
-+ /* Book-keeping */
-+ servers[child] = 0;
-+ running--;
-+
-+ if (WIFSIGNALED(status)) {
-+ signo = WTERMSIG(status);
-+ if (signo == SIGTERM) {
-+ Dprintf(L_NOTICE, "failsafe: "
-+ "child %d terminated by SIGTERM. %s.",
-+ pid, running? "Continue" : "Exit");
-+ } else {
-+ Dprintf(L_WARNING, "failsafe: "
-+ "child %d terminated by %s. "
-+ "Restarting.",
-+ pid, get_signame(signo));
-+ child = -1; /* Restart */
-+ }
-+ } else if (WIFEXITED(status)) {
-+ Dprintf(L_NOTICE, "failsafe: "
-+ "child %d exited, status %d.",
-+ pid, WEXITSTATUS(status));
-+ } else {
-+ Dprintf(L_ERROR, "failsafe: "
-+ "abnormal child termination, "
-+ "pid=%d status=%d. Restarting.",
-+ pid, status);
-+ child = -1; /* Restart */
-+ }
-+
-+ /* If child >= 0, we should not restart */
-+ if (child >= 0) {
-+ if (!running) {
-+ Dprintf(D_GENERAL,
-+ "No more children, exiting.");
-+ exit(0);
-+ }
-+ for (i = child; i < ncopies-1; i++)
-+ servers[i] = servers[i+1];
-+ ncopies--; /* Make sure we start no new servers */
-+ }
-+ }
-+}
-+
-+/*
-+ * Failsafe session, catch core file.
-+ *
-+ * Not yet implemented.
-+ * General outline: we need to fork first, because nfsd changes
-+ * uids frequently, and the kernel won't write out a core file after
-+ * that. The forked proc starts out with a clean dumpable flag though.
-+ *
-+ * After the fork, we might want to make sure we end up in some common
-+ * directory that the failsafe loop knows about.
-+ */
-+void
-+failsafe_loop(int level, void (*function)(void))
-+{
-+ /* NOP */
-+}
-+
-+static const char *
-+get_signame(int signo)
-+{
-+ static char namebuf[30];
-+
-+ switch (signo) {
-+ case SIGHUP: return "SIGHUP";
-+ case SIGINT: return "SIGINT";
-+ case SIGQUIT: return "SIGQUIT";
-+ case SIGILL: return "SIGILL";
-+ case SIGTRAP: return "SIGTRAP";
-+ case SIGIOT: return "SIGIOT";
-+ case SIGBUS: return "SIGBUS";
-+ case SIGFPE: return "SIGFPE";
-+ case SIGKILL: return "SIGKILL";
-+ case SIGUSR1: return "SIGUSR1";
-+ case SIGSEGV: return "SIGSEGV";
-+ case SIGUSR2: return "SIGUSR2";
-+ case SIGPIPE: return "SIGPIPE";
-+ case SIGALRM: return "SIGALRM";
-+ case SIGTERM: return "SIGTERM";
-+ case SIGCHLD: return "SIGCHLD";
-+ case SIGCONT: return "SIGCONT";
-+ case SIGSTOP: return "SIGSTOP";
-+ case SIGTSTP: return "SIGTSTP";
-+ case SIGTTIN: return "SIGTTIN";
-+ case SIGTTOU: return "SIGTTOU";
-+ case SIGURG: return "SIGURG";
-+ case SIGXCPU: return "SIGXCPU";
-+ case SIGXFSZ: return "SIGXFSZ";
-+ case SIGVTALRM: return "SIGVTALRM";
-+ case SIGPROF: return "SIGPROF";
-+ case SIGWINCH: return "SIGWINCH";
-+ case SIGIO: return "SIGIO";
-+#ifdef SIGPWR
-+ case SIGPWR: return "SIGPWR";
-+#endif
-+ }
-+
-+ sprintf(namebuf, "signal #%d", signo);
-+ return namebuf;
-+}
-diff -urN nfs-server-2.2beta47/daemon.h nfs-server-2.2beta51/daemon.h
---- nfs-server-2.2beta47/daemon.h Thu Jan 1 01:00:00 1970
-+++ nfs-server-2.2beta51/daemon.h Fri Nov 8 14:45:52 2002
-@@ -0,0 +1,18 @@
-+/*
-+ * daemon.h
-+ *
-+ * Daemon support
-+ */
-+
-+#ifndef CRAWLEY_H
-+#define CRAWLEY_H
-+
-+#define _PATH_NFSD_PIDFILE "/var/run/nfsd.pid"
-+#define _PATH_MOUNTD_PIDFILE "/var/run/mountd.pid"
-+
-+extern void daemonize(void);
-+extern void setpidpath(const char *);
-+extern void writepid(pid_t, int);
-+extern void failsafe(int level, int ncopies);
-+
-+#endif /* CRAWLEY_H */
-diff -urN nfs-server-2.2beta47/exports.man nfs-server-2.2beta51/exports.man
---- nfs-server-2.2beta47/exports.man Wed Nov 10 10:18:49 1999
-+++ nfs-server-2.2beta51/exports.man Fri Nov 8 14:45:36 2002
-@@ -45,6 +45,12 @@
- simultaneously. This is done by specifying an IP address and netmask pair
- as
- .IR address/netmask .
-+.IP "world
-+You can export a directory to the world (i.e. to all computers that
-+are able to reach your NFS server network-wise) by using the empty
-+hostname. When exporting to the world, the
-+.BR root_squash ", " all_squash ", " ro " and " nosetuid
-+options are turned on by default.
- .TP
- .B =public
- This is a special ``hostname'' that identifies the given directory name
-@@ -81,6 +87,12 @@
- by using the
- .IR ro " option.
- .TP
-+.I setuid
-+This allows clients to assert the setuid and setgid bits on regular
-+files. For non-anonymous exports, this option is on by default.
-+For anonymous exports, the default is
-+.IR nosetuid .
-+.TP
- .I noaccess
- This makes everything below the directory inaccessible for the named
- client. This is useful when you want to export a directory hierarchy to
-@@ -296,6 +308,22 @@
- .I /usr/X11R6
- entry apply. This is also true when the latter is a wildcard or netgroup
- entry.
-+.PP
-+You should also be careful about where you place spaces in the
-+exports file. For instance, the following may appear as if you've
-+exported
-+.BR /pub " readonly to host " foozle ,
-+but what this does in fact is export the directory to
-+.B foozle
-+with the default options,
-+.I and
-+export it to the world with the readonly option:
-+.PP
-+.nf
-+.ta +3i
-+# bad: export to the world
-+/pub foozle (ro)
-+.fi
- .SH FILES
- /etc/exports
- .SH DIAGNOSTICS
-diff -urN nfs-server-2.2beta47/fh.c nfs-server-2.2beta51/fh.c
---- nfs-server-2.2beta47/fh.c Wed Nov 10 10:41:14 1999
-+++ nfs-server-2.2beta51/fh.c Fri Nov 8 14:45:36 2002
-@@ -95,17 +95,14 @@
- static int fh_list_size;
- static time_t curtime;
-
--#ifndef FOPEN_MAX
--#define FOPEN_MAX 256
--#endif
--
- #ifndef FHTRACE
- #undef D_FHTRACE
- #define D_FHTRACE D_FHCACHE
- #endif
-
--static fhcache * fd_cache[FOPEN_MAX] = { NULL };
-+static fhcache ** fd_cache = NULL;
- static int fd_cache_size = 0;
-+static int fd_cache_max = 0;
-
- #ifndef NFSERR_INVAL /* that Sun forgot */
- #define NFSERR_INVAL 22
-@@ -141,10 +138,13 @@
-
- /* Forward declared local functions */
- static psi_t path_psi(char *, nfsstat *, struct stat *, int);
-+static psi_t path_psi_m(char *, nfsstat *, struct stat *,
-+ struct stat *, int);
- static int fh_flush_fds(void);
- static char * fh_dump(svc_fh *);
- static void fh_insert_fdcache(fhcache *fhc);
- static void fh_unlink_fdcache(fhcache *fhc);
-+static void fh_complain(const char *msg, fhcache *fhc);
-
- static void
- fh_move_to_front(fhcache *fhc)
-@@ -192,6 +192,13 @@
- static void
- fh_insert_fdcache(fhcache *fhc)
- {
-+#ifdef FHTRACE
-+ Dprintf(D_FHTRACE, "insert fh %x into fdcache @%d\n", fhc->h.psi, fhc->fd);
-+ if (fhc->fd < 0) {
-+ fh_complain("fd cache bug: bad fd", fhc);
-+ return;
-+ }
-+#endif
- if (fhc == fd_lru_head)
- return;
- if (fhc->fd_next || fhc->fd_prev)
-@@ -203,9 +210,20 @@
- fhc->fd_next = fd_lru_head;
- fd_lru_head = fhc;
-
-+ if (fhc->fd >= fd_cache_max) {
-+ int oldmax = fd_cache_max, newmax;
-+
-+ newmax = (fhc->fd + 8) & ~7;
-+ fd_cache = (fhcache **) xrealloc(fd_cache, newmax * sizeof(fhcache *));
-+ memset(fd_cache + oldmax, 0, (newmax - oldmax) * sizeof(fhcache *));
-+ fd_cache_max = newmax;
-+ }
-+
- #ifdef FHTRACE
- if (fd_cache[fhc->fd] != NULL) {
-- Dprintf(L_ERROR, "fd cache inconsistency!\n");
-+ Dprintf(L_ERROR, "fd cache inconsistency (two fh's for same fd)");
-+ fh_complain("new fh", fhc);
-+ fh_complain("old fh", fd_cache[fhc->fd]);
- return;
- }
- #endif
-@@ -225,7 +243,7 @@
- } else if (fd_lru_tail == fhc) {
- fd_lru_tail = prev;
- } else {
-- Dprintf(L_ERROR, "fd cache inconsistency\n");
-+ fh_complain("fd cache inconsistency (no next and not at tail)", fhc);
- return;
- }
- if (prev) {
-@@ -233,13 +251,13 @@
- } else if (fd_lru_head == fhc) {
- fd_lru_head = next;
- } else {
-- Dprintf(L_ERROR, "fd cache inconsistency\n");
-+ fh_complain("fd cache inconsistency (no prev and not at head)", fhc);
- return;
- }
-
- #ifdef FHTRACE
- if (fd_cache[fhc->fd] != fhc) {
-- Dprintf(L_ERROR, "fd cache inconsistency!\n");
-+ fh_complain("fd cache inconsistency (fd cache ptr mismatch)", fhc);
- return;
- }
- #endif
-@@ -285,7 +303,7 @@
- hash_slot = &((*hash_slot)->hash_next);
- if (*hash_slot == NULL)
- Dprintf(L_ERROR,
-- "internal inconsistency -- fhc(%x) not in hash table\n",
-+ "internal inconsistency -- fhc(%x) not in hash table!\n",
- fhc);
- else
- *hash_slot = fhc->hash_next;
-@@ -572,7 +590,7 @@
- efs_seekdir(dir, cookie_stack[i]);
- while ((dp = efs_readdir(dir))) {
- char *name = dp->d_name;
-- int n = strlen(name);
-+ int n = strlen(name); /* or: dp->d_reclen */
-
- if (pathlen + n + 1 >= NFS_MAXPATHLEN
- || (name[0] == '.'
-@@ -738,7 +756,16 @@
- static psi_t
- path_psi(char *path, nfsstat *status, struct stat *sbp, int svalid)
- {
-- struct stat sbuf;
-+ struct stat smounted;
-+
-+ return path_psi_m(path, status, sbp, &smounted, svalid);
-+}
-+
-+static psi_t
-+path_psi_m(char *path, nfsstat *status,
-+ struct stat *sbp, struct stat *mbp, int svalid)
-+{
-+ struct stat sbuf, ddbuf;
-
- if (sbp == NULL)
- sbp = &sbuf;
-@@ -746,10 +773,10 @@
- *status = nfs_errno();
- return (0);
- }
-+ *mbp = *sbp;
- if (S_ISDIR(sbp->st_mode) && strcmp(path, "/") != 0) {
- /* Special case for directories--test for mount point. */
-- struct stat ddbuf;
-- char *fname;
-+ char *fname;
-
- /* Find start of last component of path. */
- #if 1
-@@ -819,6 +846,19 @@
- return (pseudo_inode(sbp->st_ino, sbp->st_dev));
- }
-
-+/*
-+ * Match attributes to make sure we're still referring to the original file
-+ */
-+static inline int
-+fh_attrmatch(struct fhcache *fhc, struct stat *attr)
-+{
-+ if (fhc->dev == attr->st_dev
-+ && fhc->ino == attr->st_ino
-+ && fhc->type == (attr->st_mode & S_IFMT))
-+ return 1;
-+ return 0;
-+}
-+
- fhcache *
- fh_find(svc_fh *h, int mode)
- {
-@@ -838,6 +878,9 @@
- ex_state = active;
- time(&curtime);
- while ((fhc = fh_lookup(h->psi)) != NULL) {
-+ struct stat sbuf, *s = NULL;
-+ nfsstat dummy;
-+
- Dprintf(D_FHCACHE, "fh_find: psi=%lx... found '%s', fd=%d\n",
- (unsigned long) h->psi,
- fhc->path ? fhc->path : "<unnamed>",
-@@ -857,33 +900,27 @@
- * If it doesn't try to rebuild the path.
- */
- if (check) {
-- struct stat *s = &fhc->attrs;
-- psi_t psi;
-- nfsstat dummy;
--
-+ s = &sbuf;
- if (efs_lstat(fhc->path, s) < 0) {
- Dprintf(D_FHTRACE,
- "fh_find: stale fh: lstat: %m\n");
- } else {
-- fhc->flags |= FHC_ATTRVALID;
-- /* If pseudo-inos don't match, we fhc->path
-- * may be a mount point (hence lstat() returns
-+ /* If device/ino don't match, fhc->path may
-+ * be a mount point (hence lstat() returns
- * a different inode number than the readdir()
- * stuff used in path_psi)
- */
-- psi = pseudo_inode(s->st_ino, s->st_dev);
-- if (h->psi == psi)
-+ if (fh_attrmatch(fhc, s))
- goto fh_return;
-
-- /* Try again by computing the path psi */
-- psi = path_psi(fhc->path, &dummy, s, 1);
-- if (h->psi == psi)
-+ /* Get the dev/ino of the underlying
-+ * mount point. */
-+ path_psi(fhc->path, &dummy, s, 1);
-+ if (fh_attrmatch(fhc, s))
- goto fh_return;
-
-- Dprintf(D_FHTRACE, "fh_find: stale fh: "
-- "dev/ino %x/%lx psi %lx",
-- s->st_dev, s->st_ino,
-- (unsigned long) psi);
-+ Dprintf(D_FHTRACE, "fh_find: stale fh: %lx",
-+ (unsigned long) h->psi);
- }
-
- fh_discard:
-@@ -896,6 +933,12 @@
- }
-
- fh_return:
-+ /* Valid attributes; cache them */
-+ if (s != NULL) {
-+ memcpy(&fhc->attrs, s, sizeof(*s));
-+ fhc->flags |= FHC_ATTRVALID;
-+ }
-+
- /* The cached fh seems valid */
- if (fhc != fh_head.next)
- fh_move_to_front(fhc);
-@@ -905,7 +948,8 @@
- }
-
- Dprintf(D_FHCACHE, "fh_find: psi=%lx... not found\n",
-- (unsigned long) h->psi);
-+ (unsigned long) h->psi);
-+
- if (mode == FHFIND_FCACHED) {
- ex_state = inactive;
- return NULL;
-@@ -918,6 +962,7 @@
- fhc = flush->prev;
- fh_delete(flush);
- }
-+
- fhc = (fhcache *) xmalloc(sizeof *fhc);
- if (mode == FHFIND_FCREATE) {
- /* File will be created */
-@@ -937,11 +982,31 @@
- }
- fhc->path = path;
- }
-+
- fhc->flags = 0;
- if (fhc->path && efs_lstat(fhc->path, &fhc->attrs) >= 0) {
-- if (re_export && nfsmounted(fhc->path, &fhc->attrs))
-+ if (nfsmounted(fhc->path, &fhc->attrs)) {
- fhc->flags |= FHC_NFSMOUNTED;
-+#if 0
-+ /* We must allow the client to send us the
-+ * file handle for the NFS mount point itself,
-+ * but not for entries within an NFS mount.
-+ * XXX: needs fixing.
-+ */
-+ if (!re_export) {
-+ Dprintf(D_FHTRACE,
-+ "Attempt to use %s (non-exportable)\n",
-+ fhc->path);
-+ free(fhc);
-+ ex_state = inactive;
-+ return NULL;
-+ }
-+#endif
-+ }
- fhc->flags |= FHC_ATTRVALID;
-+ fhc->dev = fhc->attrs.st_dev;
-+ fhc->ino = fhc->attrs.st_ino;
-+ fhc->type = fhc->attrs.st_mode & S_IFMT;
- }
- fhc->fd = -1;
- fhc->last_used = curtime;
-@@ -993,6 +1058,14 @@
- return buf;
- }
-
-+static void
-+fh_complain(const char *msg, fhcache *fhc)
-+{
-+ Dprintf(L_ERROR, "%s: ptr=%p fd=%d path=%s\n", msg,
-+ fhc, fhc->fd,
-+ fhc->path? fhc->path : "<unnamed>");
-+}
-+
- /*
- * This routine is only used by the mount daemon.
- * It creates the initial file handle.
-@@ -1000,23 +1073,25 @@
- int
- fh_create(nfs_fh *fh, char *path)
- {
-- svc_fh key;
-- fhcache *h;
-- psi_t psi;
-- nfsstat status;
-- char *s;
-+ struct stat stb;
-+ svc_fh key;
-+ fhcache *h;
-+ psi_t psi;
-+ nfsstat status;
-+ char *s;
-
- memset(&key, 0, sizeof(key));
- status = NFS_OK;
-- if ((psi = path_psi("/", &status, NULL, 0)) == 0)
-+ if ((psi = path_psi("/", &status, &stb, 0)) == 0)
- return ((int) status);
-+
- s = path;
- while ((s = strchr(s + 1, '/')) != NULL) {
- if (++(key.hash_path[0]) >= HP_LEN)
- return ((int) NFSERR_NAMETOOLONG);
- key.hash_path[key.hash_path[0]] = hash_psi(psi);
- *s = '\0';
-- if ((psi = path_psi(path, &status, NULL, 0)) == 0)
-+ if ((psi = path_psi(path, &status, &stb, 0)) == 0)
- return ((int) status);
- *s = '/';
- }
-@@ -1024,7 +1099,7 @@
- if (++(key.hash_path[0]) >= HP_LEN)
- return ((int) NFSERR_NAMETOOLONG);
- key.hash_path[key.hash_path[0]] = hash_psi(psi);
-- if ((psi = path_psi(path, &status, NULL, 0)) == 0)
-+ if ((psi = path_psi(path, &status, &stb, 0)) == 0)
- return ((int) status);
- }
- key.psi = psi;
-@@ -1037,9 +1112,12 @@
-
- /* assert(h != NULL); */
- if (h->path == NULL) {
-- h->fd = -1;
-- h->path = xstrdup(path);
-+ h->fd = -1;
-+ h->path = xstrdup(path);
- h->flags = 0;
-+ h->dev = stb.st_dev;
-+ h->ino = stb.st_ino;
-+ h->type = stb.st_mode & S_IFMT;
- }
- memcpy(fh, &key, sizeof(key));
- return ((int) status);
-@@ -1064,6 +1142,44 @@
- return ((nfs_fh*)&(h->h));
- }
-
-+
-+static inline int
-+access_override(int omode, int perm, struct stat *buf)
-+{
-+ /* Be suspicous of flags, particularly O_CREAT/O_TRUNC. A previous
-+ * comment said:
-+ *
-+ * "[Not checking this] would truncate read-only files on creat()
-+ * calls. Of course, ftruncate(fd, 0) should still be legal for
-+ * the user when the file was chmoded *after* opening it, but we
-+ * have no way to tell, and a semi-succeding `cp foo readonly-file'
-+ * is much more unintuitive and destructive than a failing
-+ * ftruncate()."
-+ */
-+ if (omode & ~O_ACCMODE)
-+ return 0;
-+
-+ /* Users can do anything to their own files. Harmless (since they
-+ * could chown anyway), and helps to mask NFSes statelessness.
-+ *
-+ * (in passing, this also handles mode 0100 execution)
-+ */
-+ if (buf->st_uid == auth_uid)
-+ return 1;
-+
-+ /* Henceforth, we are considering granting read access to facilitate
-+ * exec access. This is read only */
-+ if (omode != O_RDONLY)
-+ return 0;
-+
-+ /* Mode 0110 execution */
-+ if (buf->st_gid == auth_gid)
-+ return (buf->st_mode & S_IXGRP) != 0;
-+
-+ /* Mode 0111 execution */
-+ return (buf->st_mode & S_IXOTH) != 0;
-+}
-+
- int
- path_open(char *path, int omode, int perm)
- {
-@@ -1113,30 +1229,15 @@
- * lishes two things: first, it gives the file owner r/w access to
- * the file whatever the permissions are, so that files are still
- * accessible after an fchown(fd, 0). The second part of the
-- * condition allows read access to mode 0111 executables.
-- *
-- * The old conditon read like this:
-- * if (fd < 0 && oerrno == EACCES) {
-- * if (oerrno == EACCES && (buf.st_uid == auth_uid
-- * || (omode == O_RDONLY && (buf.st_mode & S_IXOTH)))) {
-- * override uid; etc...
-- * }
-- * }
-- * This would truncate read-only files on creat() calls. Now
-- * ftruncate(fd, 0) should still be legal for the user when the
-- * file was chmoded *after* opening it, but we have no way to tell,
-- * and a semi-succeding `cp foo readonly-file' is much more
-- * unintuitive and destructive than a failing ftruncate().
-+ * condition allows read access to `execute-only' files.
- */
-- if (fd < 0 && oerrno == EACCES && !(omode & (O_CREAT|O_TRUNC))) {
-- if ((buf.st_uid == auth_uid && (omode & O_ACCMODE) == omode)
-- || ((buf.st_mode & S_IXOTH) && omode == O_RDONLY)) {
-- auth_override_uid(ROOT_UID);
-- fd = efs_open(path, omode, perm);
-- oerrno = errno;
-- auth_override_uid(auth_uid);
-- }
-+ if (fd < 0 && oerrno == EACCES && access_override(omode, perm, &buf)) {
-+ auth_override_uid(ROOT_UID);
-+ fd = efs_open(path, omode, perm);
-+ oerrno = errno;
-+ auth_override_uid(auth_uid);
- }
-+
-
- if (fd < 0) {
- Dprintf(D_FHCACHE,
-@@ -1241,7 +1342,7 @@
- char *sindx;
- int is_dd;
- nfsstat ret;
-- struct stat sbuf;
-+ struct stat sbuf, smount;
- char pathbuf[PATH_MAX + NAME_MAX + 1], *fname;
-
- /* should not happen */
-@@ -1318,7 +1419,7 @@
-
- *new_fh = dopa->dir;
- key = (svc_fh *) new_fh;
-- if ((key->psi = path_psi(pathbuf, &ret, sbp, 0)) == 0)
-+ if ((key->psi = path_psi_m(pathbuf, &ret, sbp, &smount, 0)) == 0)
- return (ret);
-
- if (is_dd) {
-@@ -1344,6 +1445,10 @@
- h->h.hash_path[0]);
- return NFSERR_STALE;
- }
-+ if (sbp->st_dev != smount.st_dev) {
-+ Dprintf(D_FHTRACE, "fh_compose: %s hit%s mount point\n",
-+ pathbuf, nfsmounted(pathbuf, &smount)? " NFS" : "");
-+ }
- #endif
-
- /* New code added by Don Becker */
-@@ -1356,7 +1461,8 @@
- if (!h) return NFSERR_STALE;
- #endif
- if (h->path)
-- Dprintf(L_ERROR, "Internal inconsistency: double entry (path '%s', now '%s').\n",
-+ Dprintf(L_ERROR,
-+ "internal inconsistency: double entry (path '%s', now '%s').\n",
- h->path, pathbuf);
- }
- Dprintf(D_FHCACHE, "fh_compose: using handle %x ('%s', fd=%d)\n",
-@@ -1365,9 +1471,18 @@
-
- /* assert(h != NULL); */
- if (h->path == 0) {
-- h->path = xstrdup(pathbuf);
-+ h->path = xstrdup(pathbuf);
- h->flags = 0;
-- if (!re_export && nfsmounted(pathbuf, sbp))
-+ h->dev = sbp->st_dev;
-+ h->ino = sbp->st_ino;
-+ h->type = sbp->st_mode & S_IFMT;
-+
-+ /* Note: in the case of a mount point,
-+ * sbp contains the stats of the mount point, while
-+ * ddbuf has the dev/ino of the underlying directory
-+ */
-+ if (sbp->st_dev != smount.st_dev
-+ && nfsmounted(pathbuf, &smount))
- h->flags |= FHC_NFSMOUNTED;
- #ifdef FHTRACE
- Dprintf(D_FHTRACE, "fh_compose: created handle %s\n", h->path);
-diff -urN nfs-server-2.2beta47/fh.h nfs-server-2.2beta51/fh.h
---- nfs-server-2.2beta47/fh.h Mon Nov 23 12:15:43 1998
-+++ nfs-server-2.2beta51/fh.h Fri Nov 8 14:45:36 2002
-@@ -97,7 +97,13 @@
- struct fhcache * hash_next;
- struct fhcache * fd_next;
- struct fhcache * fd_prev;
-+
-+ /* These are fixed during the lifetime of this object */
- svc_fh h;
-+ dev_t dev;
-+ ino_t ino;
-+ mode_t type; /* st_mode & S_IFMT */
-+
- int fd;
- int omode;
- char * path;
-diff -urN nfs-server-2.2beta47/getattr.c nfs-server-2.2beta51/getattr.c
---- nfs-server-2.2beta47/getattr.c Fri Oct 30 18:10:11 1998
-+++ nfs-server-2.2beta51/getattr.c Fri Nov 8 14:45:36 2002
-@@ -115,6 +115,16 @@
- attr->fsid = 1;
- attr->fileid = fh_psi((nfs_fh *)&(fhc->h));
- #endif
-+
-+ /* This may be needed by some Suns... testing */
-+#define MINTIME (24 * 2600)
-+ if (s->st_atime < MINTIME)
-+ s->st_atime = MINTIME;
-+ if (s->st_mtime < MINTIME)
-+ s->st_mtime = MINTIME;
-+ if (s->st_ctime < MINTIME)
-+ s->st_ctime = MINTIME;
-+
- attr->atime.seconds = s->st_atime;
- attr->atime.useconds = 0;
- attr->mtime.seconds = s->st_mtime;
-diff -urN nfs-server-2.2beta47/logging.c nfs-server-2.2beta51/logging.c
---- nfs-server-2.2beta47/logging.c Fri Oct 30 17:11:22 1998
-+++ nfs-server-2.2beta51/logging.c Fri Nov 8 14:45:36 2002
-@@ -147,8 +147,9 @@
- (void) time(&now);
- tm = localtime(&now);
- fprintf(log_fp, "%s %02d/%02d/%02d %02d:%02d %s",
-- log_name, tm->tm_mon + 1, tm->tm_mday, tm->tm_year,
-- tm->tm_hour, tm->tm_min, buff);
-+ log_name, tm->tm_mon + 1, tm->tm_mday,
-+ tm->tm_year % 100,
-+ tm->tm_hour, tm->tm_min, buff);
- if (strchr(buff, '\n') == NULL)
- fputc('\n', log_fp);
- }
-@@ -182,7 +183,8 @@
- tm = localtime(&unix_cred->aup_time);
- snprintf(buffer + len, total - len,
- "%d/%d/%d %02d:%02d:%02d %s %d.%d",
-- tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
-+ tm->tm_year %100,
-+ tm->tm_mon + 1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec,
- unix_cred->aup_machname,
- unix_cred->aup_uid,
-diff -urN nfs-server-2.2beta47/mountd.c nfs-server-2.2beta51/mountd.c
---- nfs-server-2.2beta47/mountd.c Wed Jun 2 14:10:33 1999
-+++ nfs-server-2.2beta51/mountd.c Fri Nov 8 14:45:36 2002
-@@ -32,7 +32,7 @@
- #include "rpcmisc.h"
- #include "rmtab.h"
- #include "haccess.h"
--#include "failsafe.h"
-+#include "daemon.h"
- #include "signals.h"
- #include <rpc/pmap_clnt.h>
-
-@@ -44,6 +44,8 @@
- /*
- * Option table for mountd
- */
-+#define OPT_NOTCP 300
-+#define OPT_LOOPBACK 301
- static struct option longopts[] =
- {
- { "debug", required_argument, 0, 'd' },
-@@ -56,6 +58,8 @@
- { "no-spoof-trace", 0, 0, 't' },
- { "version", 0, 0, 'v' },
- { "fail-safe", optional_argument, 0, 'z' },
-+ { "no-tcp", 0, 0, OPT_NOTCP },
-+ { "loopback-only", 0, 0, OPT_LOOPBACK },
-
- { NULL, 0, 0, 0 }
- };
-@@ -358,6 +362,12 @@
- break;
- case 0:
- break;
-+ case OPT_NOTCP:
-+ udp_only = 1;
-+ break;
-+ case OPT_LOOPBACK:
-+ loopback_only = 1;
-+ break;
- case '?':
- default:
- usage(stderr, 1);
-@@ -384,38 +394,27 @@
- /* Create services and register with portmapper */
- rpc_init("mountd", MOUNTPROG, mountd_versions, mount_dispatch, port, 0);
-
-- if (!foreground && !_rpcpmstart) {
--#ifndef RPC_SVC_FG
-- /* We first fork off a child. */
-- if ((c = fork()) > 0)
-- exit(0);
-- if (c < 0) {
-- Dprintf(L_FATAL, "mountd: cannot fork: %s\n",
-- strerror(errno));
-- }
-- /* No more logging to stderr */
-- background_logging();
-+ if (_rpcpmstart) {
-+ /* Always foreground mode */
-+ foreground = 1;
-
-- /* Now we remove ourselves from the foreground. */
-- (void) close(0);
-- (void) close(1);
-- (void) close(2);
--#ifdef TIOCNOTTY
-- if ((c = open("/dev/tty", O_RDWR)) >= 0) {
-- (void) ioctl(c, TIOCNOTTY, (char *) NULL);
-- (void) close(c);
-- }
--#else
-- setsid();
--#endif
--#endif /* not RPC_SVC_FG */
-+ /* ... but no logging */
-+ background_logging();
- }
-
-+ /* Become a daemon */
-+ if (!foreground)
-+ daemonize();
-+
- /* Initialize the FH module. */
- fh_init();
-
- /* Initialize the AUTH module. */
- auth_init(auth_file);
-+
-+ /* Write pidfile */
-+ setpidpath(_PATH_MOUNTD_PIDFILE);
-+ writepid(getpid(), 1);
-
- /* Failsafe mode */
- if (failsafe_level)
-diff -urN nfs-server-2.2beta47/mountd.man nfs-server-2.2beta51/mountd.man
---- nfs-server-2.2beta47/mountd.man Wed Jun 2 14:12:21 1999
-+++ nfs-server-2.2beta51/mountd.man Fri Nov 8 14:45:36 2002
-@@ -14,6 +14,8 @@
- .B "[\ \-\-allow\-non\-root\ ]"
- .B "[\ \-\-re\-export\ ]"
- .B "[\ \-\-no\-spoof\-trace\ ]"
-+.B "[\ \-\-no\-tcp ]"
-+.B "[\ \-\-loopback\-only ]"
- .B "[\ \-\-version\ ]"
- .ad b
- .SH DESCRIPTION
-@@ -123,6 +125,18 @@
- .TP
- .BR \-v " or " \-\-version
- Report the current version number of the program.
-+.TP
-+.BR \-\-no\-tcp
-+Force
-+.I mountd
-+to register only the UDP transport, but no TCP.
-+This is an experimental option.
-+.TP
-+.BR \-\-loopback\-only
-+Force
-+.I mountd
-+to bind to the loopback interface.
-+This is an experimental option.
- .SS Access Control
- For enhanced security, access to
- .I mountd
-diff -urN nfs-server-2.2beta47/nfsd.c nfs-server-2.2beta51/nfsd.c
---- nfs-server-2.2beta47/nfsd.c Wed Nov 10 10:33:28 1999
-+++ nfs-server-2.2beta51/nfsd.c Fri Nov 8 14:45:36 2002
-@@ -21,7 +21,7 @@
- #include "getopt.h"
- #include "fsusage.h"
- #include "rpcmisc.h"
--#include "failsafe.h"
-+#include "daemon.h"
- #include "signals.h"
- #ifdef __linux__ /* XXX - MvS: for UNIX sockets. */
- # include <sys/un.h>
-@@ -30,7 +30,6 @@
- # include <syslog.h>
- #endif
-
--#define MULTIPLE_SERVERS
-
- /* Flags for auth_fh */
- #define CHK_READ 0
-@@ -51,6 +50,8 @@
- /*
- * Option table
- */
-+#define OPT_NOTCP 300
-+#define OPT_LOOPBACK 301
- static struct option longopts[] = {
- { "auth-deamon", required_argument, 0, 'a' },
- { "debug", required_argument, 0, 'd' },
-@@ -68,6 +69,9 @@
- { "version", 0, 0, 'v' },
- { "no-cross-mounts", 0, 0, 'x' },
- { "fail-safe", optional_argument, 0, 'z' },
-+ { "no-tcp", 0, 0, OPT_NOTCP },
-+ { "udp-only", 0, 0, OPT_NOTCP },
-+ { "loopback-only", 0, 0, OPT_LOOPBACK },
-
- { NULL, 0, 0, 0 }
- };
-@@ -173,7 +177,10 @@
- return NULL;
- }
-
-- auth_user(nfsmount, rqstp);
-+ if (!auth_user(nfsmount, rqstp)) {
-+ *statp = NFSERR_ACCES;
-+ return NULL;
-+ }
-
- *statp = NFS_OK;
- return fhc;
-@@ -211,7 +218,11 @@
-
- if ((nfsmount = auth_path(nfsclient, rqstp, path)) == NULL)
- return NFSERR_ACCES;
-- auth_user(nfsmount, rqstp);
-+
-+ /* XXX: really need to call it again here?
-+ * Already invoked in auth_fh */
-+ if (!auth_user(nfsmount, rqstp))
-+ return NFSERR_ACCES;
-
- return (NFS_OK);
- }
-@@ -575,7 +586,8 @@
- #endif
-
- /* MvS: Some clients use chardev 0xFFFF for a FIFO. */
-- if (S_ISCHR(argp->attributes.mode) && dev == 0xFFFF) {
-+ if (S_ISCHR(argp->attributes.mode)
-+ && (dev == 0xFFFF || dev == (dev_t) -1)) {
- is_borc = 0;
- dev = 0;
- argp->attributes.mode &= ~S_IFMT;
-@@ -623,7 +635,7 @@
- flags = (argp->attributes.size == 0 ?
- CREATE_OMODE | O_TRUNC : CREATE_OMODE);
- if (!exists)
-- flags |= O_CREAT;
-+ flags |= O_CREAT|O_EXCL;
- tmpfd = path_open(pathbuf, flags,
- argp->attributes.mode & ~S_IFMT);
- if (tmpfd < 0)
-@@ -965,9 +977,7 @@
- int nfsport = 0;
- int failsafe_level = 0;
- int c;
--#ifdef MULTIPLE_SERVERS
- int i, ncopies = 1;
--#endif
-
- program_name = argv[0];
- chdir("/");
-@@ -1031,12 +1041,17 @@
- break;
- case 0:
- break;
-+ case OPT_NOTCP:
-+ udp_only = 1;
-+ break;
-+ case OPT_LOOPBACK:
-+ loopback_only = 1;
-+ break;
- case '?':
- default:
- usage(stderr, 1);
- }
-
--#ifdef MULTIPLE_SERVERS
- if (optind == argc-1 && isdigit(argv[optind][0])) {
- ncopies = atoi(argv[optind++]);
- if (ncopies <= 0) {
-@@ -1051,7 +1066,6 @@
- ncopies = 1;
- }
- }
--#endif
-
- /* No more arguments allowed. */
- if (optind != argc)
-@@ -1075,72 +1089,54 @@
- rpc_init("nfsd", NFS_PROGRAM, nfsd_versions, nfs_dispatch,
- nfsport, NFS_MAXDATA);
-
-- /* No more than 1 copy when run from inetd */
-- if (_rpcpmstart && ncopies > 1) {
-- Dprintf(L_WARNING,
-- "nfsd: warning: can run only "
-- "one server in inetd mode\n");
-- ncopies = 1;
-+ if (_rpcpmstart) {
-+ /* Always do foreground mode */
-+ foreground = 1;
-+
-+ /* ... but don't log to stderr */
-+ background_logging();
-+
-+ /* No more than 1 copy when run from inetd */
-+ if (ncopies > 1) {
-+ Dprintf(L_WARNING,
-+ "nfsd: warning: can run only "
-+ "one server in inetd mode\n");
-+ ncopies = 1;
-+ }
- }
-
--#ifndef MULTIPLE_SERVERS_READWRITE
- if (ncopies > 1)
- read_only = 1;
--#endif
-
-- /* We first fork off a child. */
-- if (!foreground) {
-- if ((c = fork()) > 0)
-- exit(0);
-- if (c < 0) {
-- Dprintf(L_FATAL, "nfsd: cannot fork: %s\n",
-- strerror(errno));
-- }
-- }
-+ /*
-+ * We first fork off a child and detach from tty
-+ */
-+ if (!foreground)
-+ daemonize();
-
- /* Initialize the AUTH module. */
- auth_init(auth_file);
-
-+ setpidpath(_PATH_NFSD_PIDFILE);
- if (failsafe_level == 0) {
- /* Start multiple copies of the server */
-+ writepid(getpid(), 1);
- for (i = 1; i < ncopies; i++) {
-+ pid_t pid;
-+
- Dprintf(D_GENERAL, "Forking server thread...\n");
-- if ((c = fork()) < 0) {
-+ if ((pid = fork()) < 0) {
- Dprintf(L_ERROR, "Unable to fork: %s",
- strerror(errno));
-- } else if (c == 0) {
-- /* Child process */
-- break;
-+ } else if (pid != 0) {
-+ writepid(pid, 0);
-+ } else {
-+ break; /* Child process */
- }
- }
- } else {
- /* Init for failsafe mode */
- failsafe(failsafe_level, ncopies);
-- }
--
-- /* Now that we've done all the required forks, we make do all the
-- * session magic.
-- */
-- if (!foreground) {
-- /* No more logging to stderr */
-- background_logging();
--
-- /* Now we remove ourselves from the foreground. */
-- close(0);
-- close(1);
-- close(2);
--#ifdef HAVE_SETSID
-- setsid();
--#else
-- {
-- int fd;
--
-- if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
-- ioctl(fd, TIOCNOTTY, (char *) NULL);
-- close(fd);
-- }
-- }
--#endif
- }
-
- /*
-diff -urN nfs-server-2.2beta47/nfsd.man nfs-server-2.2beta51/nfsd.man
---- nfs-server-2.2beta47/nfsd.man Wed Jun 2 14:13:37 1999
-+++ nfs-server-2.2beta51/nfsd.man Fri Nov 8 14:45:36 2002
-@@ -8,7 +8,7 @@
- .B "[\ \-d\ facility\ ]"
- .B "[\ \-P\ port\ ]"
- .B "[\ \-R\ dirname\ ]"
--.B "[\ \-Fhlnprstv\ ]"
-+.B "[\ \-Fhlnprstuv\ ]"
- .B "[\ \-\-debug\ facility\ ]"
- .B "[\ \-\-exports\-file=file\ ]"
- .B "[\ \-\-foreground\ ]"
-@@ -18,6 +18,8 @@
- .B "[\ \-\-public\-root\ dirname\ ]"
- .\".B "[\ \-\-synchronous\-writes\ ]"
- .B "[\ \-\-no\-spoof\-trace\ ]"
-+.B "[\ \-\-no\-tcp ]"
-+.B "[\ \-\-loopback-only ]"
- .B "[\ \-\-port\ port\ ]"
- .B "[\ \-\-log-transfers\ ]"
- .B "[\ \-\-version\ ]"
-@@ -56,7 +58,7 @@
- .PP
- When run from
- .IR inetd ,
--.i nfsd
-+.I nfsd
- will terminate after a certain period of inactivity.
- .SH OPTIONS
- .TP
-@@ -167,6 +169,14 @@
- .BR \-v " or " \-\-version
- Report the current version number of the program.
- .TP
-+.BR \-\-no\-tcp
-+Force nfsd to only register a UDP transport, but not TCP.
-+This is an experimental option.
-+.TP
-+.BR \-\-loopback\-only
-+Force nfsd to bind to the loopback interface.
-+This is an experimental option.
-+.TP
- .BR numcopies
- This is an experimental feature that lets you run several instances of
- .I nfsd
-@@ -174,15 +184,8 @@
- .B numcopies
- greater than one,
- .I nfsd
--will fork as many times as specified by this value.
--However, the servers do not share a common file handle
--cache, which makes certain file operations impossible.
--.IP
--For this reason,
--.I nfsd
--will disallow all write operations when invoked with this option. Although
--this is very limiting, this feature may still prove useful for exporting
--public FTP areas or Usenet News spools.
-+will fork as many times as specified by this value so it is able to
-+handle that many NFS requests in parallel.
- .SS WebNFS Support
- WebNFS is an extension to the normal NFS protocol developed by Sun
- that is particularly well-suited for file retrieval over the
-@@ -268,6 +271,19 @@
- .I nfsd
- writes out a transfer record whenever it encounters a READ or WRITE
- request at offset zero.
-+.SS Generating a debug trace
-+When suspecting a bug in nfsd, it is helpful to look at a debug trace
-+of what's going on. You can create such a trace by first killing nfsd,
-+and then restarting it as
-+.PP
-+.nf
-+.ta +3i
-+/usr/sbin/rpc.nfsd -F -d all
-+.fi
-+.PP
-+Instead of
-+.BR all ,
-+you can use less verbose debug facilities as described above.
- .SH "SEE ALSO"
- exports(5), mountd(8), ugidd(8C)
- .SH AUTHORS
-diff -urN nfs-server-2.2beta47/rmtab.c nfs-server-2.2beta51/rmtab.c
---- nfs-server-2.2beta47/rmtab.c Fri Feb 6 09:43:25 1998
-+++ nfs-server-2.2beta51/rmtab.c Fri Nov 8 14:45:36 2002
-@@ -8,6 +8,7 @@
-
- #include "nfsd.h"
- #include "rmtab.h"
-+#include "rpcmisc.h"
-
- static char * rmtab_gethost(struct svc_req *);
- static int rmtab_insert(char *, char *);
-diff -urN nfs-server-2.2beta47/rpcmisc.c nfs-server-2.2beta51/rpcmisc.c
---- nfs-server-2.2beta47/rpcmisc.c Tue Sep 7 10:42:58 1999
-+++ nfs-server-2.2beta51/rpcmisc.c Fri Nov 8 14:45:36 2002
-@@ -39,6 +39,8 @@
- int _rpcfdtype = 0;
- int _rpcsvcdirty = 0;
- const char * auth_daemon = 0;
-+int udp_only = 0;
-+int loopback_only = 0;
-
- #ifdef AUTH_DAEMON
- static bool_t (*tcp_rendevouser)(SVCXPRT *, struct rpc_msg *);
-@@ -96,7 +98,7 @@
- }
- }
-
-- if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) {
-+ if ((_rpcfdtype == 0 && !udp_only) || (_rpcfdtype == SOCK_STREAM)) {
- if (_rpcfdtype == 0 && defport != 0)
- sock = makesock(defport, IPPROTO_TCP, bufsiz);
- transp = svctcp_create(sock, 0, 0);
-@@ -199,6 +201,9 @@
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
- sin.sin_port = htons(port);
-+
-+ if (loopback_only)
-+ sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
- #ifdef DEBUG
- {
-diff -urN nfs-server-2.2beta47/rpcmisc.h nfs-server-2.2beta51/rpcmisc.h
---- nfs-server-2.2beta47/rpcmisc.h Tue Sep 7 10:37:38 1999
-+++ nfs-server-2.2beta51/rpcmisc.h Fri Nov 8 14:45:36 2002
-@@ -9,6 +9,8 @@
- extern int _rpcpmstart;
- extern int _rpcfdtype;
- extern int _rpcsvcdirty;
-+extern int udp_only;
-+extern int loopback_only;
- extern const char * auth_daemon;
-
- extern void rpc_init(const char *name, int prog, int *verstbl,
-@@ -16,5 +18,13 @@
- int defport, int bufsize);
- extern void rpc_exit(int prog, int *verstbl);
- extern void rpc_closedown(void);
-+
-+/*
-+ * Some older systems don't have svc_getcaller.
-+ * Some, like glibc 2.2, have it but it returns some type that's
-+ * not a sockaddr_in anymore.
-+ */
-+#undef svc_getcaller
-+#define svc_getcaller(xprt) ((struct sockaddr_in *) (&(xprt)->xp_raddr))
-
- #endif /* RPCMISC_H */
-diff -urN nfs-server-2.2beta47/setattr.c nfs-server-2.2beta51/setattr.c
---- nfs-server-2.2beta47/setattr.c Fri Oct 30 18:29:42 1998
-+++ nfs-server-2.2beta51/setattr.c Fri Nov 8 14:45:36 2002
-@@ -103,6 +103,10 @@
- if (flags & SATTR_CHMOD) {
- unsigned int mode = attr->mode;
-
-+ /* If setuid is not allowed, silently squash them */
-+ if (!nfsmount->o.allow_setuid && S_ISREG(s->st_mode))
-+ mode &= ~(S_ISUID|S_ISGID) | s->st_mode;
-+
- if (mode != -1 && mode != 0xFFFF /* ultrix bug */
- && (mode & 07777) != (s->st_mode & 07777)) {
- if (efs_chmod(path, mode) < 0)
-diff -urN nfs-server-2.2beta47/showmount.c nfs-server-2.2beta51/showmount.c
---- nfs-server-2.2beta47/showmount.c Wed Jun 12 22:31:04 1996
-+++ nfs-server-2.2beta51/showmount.c Fri Nov 8 14:45:36 2002
-@@ -162,17 +162,13 @@
- break;
- }
-
-- if (hostname[0] >= '0' && hostname[0] <= '9') {
-- server_addr.sin_family = AF_INET;
-- server_addr.sin_addr.s_addr = inet_addr(hostname);
-- }
-- else {
-+ server_addr.sin_family = AF_INET;
-+ if (!inet_aton(hostname, &server_addr.sin_addr)) {
- if ((hp = gethostbyname(hostname)) == NULL) {
- fprintf(stderr, "%s: can't get address for %s\n",
- program_name, hostname);
- exit(1);
- }
-- server_addr.sin_family = AF_INET;
- memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
- }
-
-diff -urN nfs-server-2.2beta47/site.h.in nfs-server-2.2beta51/site.h.in
---- nfs-server-2.2beta47/site.h.in Thu Jan 1 01:00:00 1970
-+++ nfs-server-2.2beta51/site.h.in Fri Nov 8 14:45:57 2002
-@@ -0,0 +1,50 @@
-+/*
-+ * Site-specific configuration options generated by BUILD.
-+ * Please do not edit.
-+ */
-+
-+/*
-+ * If ENABLE_DEVTAB is defined, nfsd will use the new inode
-+ * number generation scheme for avoiding inode number clashes
-+ * on big hard disks.
-+ */
-+#undef ENABLE_DEVTAB
-+
-+/*
-+ * If MULTIPLE_SERVER_READWRITE is defined, you will be able
-+ * to run several nfsd process in parallel servicing all NFS
-+ * requests.
-+ */
-+#define MULTIPLE_SERVERS_READWRITE
-+
-+/*
-+ * If ENABLE_UGID_DAEMON is defined, the real rpc.ugidd is built,
-+ * nfsd is built to support ugidd queries.
-+ * Otherwise, a dummy program is created
-+ */
-+#undef ENABLE_UGID_DAEMON
-+
-+/*
-+ * If ENABLE_UGID_NIS is defined, nfsd will support user mapping
-+ * vie the client's NIS server.
-+ */
-+#undef ENABLE_UGID_NIS
-+
-+/*
-+ * if HOSTS_ACCESS is defined, ugidd uses host access control
-+ * provided by libwrap.a from tcp_wrappers
-+ */
-+#define HOSTS_ACCESS
-+
-+/*
-+ * Define correct ownership of export control file
-+ */
-+#define EXPORTSOWNERUID 0
-+#define EXPORTSOWNERGID 0
-+
-+/*
-+ * If WANT_LOG_MOUNTS is defined, every mount request will be logged
-+ * to syslogd with the name of source site and a path that was
-+ * it requested
-+ */
-+#define WANT_LOG_MOUNTS
-diff -urN nfs-server-2.2beta47/ugidd.c nfs-server-2.2beta51/ugidd.c
---- nfs-server-2.2beta47/ugidd.c Wed Dec 10 12:34:16 1997
-+++ nfs-server-2.2beta51/ugidd.c Fri Nov 8 14:45:36 2002
-@@ -43,9 +43,7 @@
- };
-
- int
--main(argc, argv)
--int argc;
--char **argv;
-+main(int argc, char **argv)
- {
- SVCXPRT *transp;
- int c, longind;
-@@ -92,32 +90,11 @@
- exit(1);
- }
-
-- if (!foreground) {
-- if ((c = fork()) > 0)
-- exit(0);
-- if (c < 0) {
-- fprintf(stderr, "ugidd: cannot fork: %s\n",
-- strerror(errno));
-- exit(-1);
-- }
-- close(0);
-- close(1);
-- close(2);
--#ifdef HAVE_SETSID
-- setsid();
--#else
-- {
-- int fd;
--
-- if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
-- ioctl(fd, TIOCNOTTY, (char *) NULL);
-- close(fd);
-- }
-- }
--#endif
-- }
--
- log_open("ugidd", foreground);
-+
-+ /* Become a daemon */
-+ if (!foreground)
-+ daemonize();
-
- svc_run();
- Dprintf(L_ERROR, "svc_run returned\n");
-diff -urN nfs-server-2.2beta47/version.c nfs-server-2.2beta51/version.c
---- nfs-server-2.2beta47/version.c Wed Nov 10 10:33:33 1999
-+++ nfs-server-2.2beta51/version.c Fri Nov 8 14:45:36 2002
-@@ -1 +1 @@
--char version[] = "Universal NFS Server 2.2beta47";
-+char version[] = "Universal NFS Server 2.2beta51";