aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/unfs-server/unfs-server-2.2beta47/006-reiserfs.patch
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:14:24 +0100
committerRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:29:45 +0100
commit29d6678fd546377459ef75cf54abeef5b969b5cf (patch)
tree8edd65790e37a00d01c3f203f773fe4b5012db18 /meta/recipes-devtools/unfs-server/unfs-server-2.2beta47/006-reiserfs.patch
parentda49de6885ee1bc424e70bc02f21f6ab920efb55 (diff)
downloadopenembedded-core-contrib-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.gz
Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things and is generally overwhelming. This commit splits it into several logical sections roughly based on function, recipes.txt gives more information about the classifications used. The opportunity is also used to switch from "packages" to "recipes" as used in OpenEmbedded as the term "packages" can be confusing to people and has many different meanings. Not all recipes have been classified yet, this is just a first pass at separating things out. Some packages are moved to meta-extras as they're no longer actively used or maintained. Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'meta/recipes-devtools/unfs-server/unfs-server-2.2beta47/006-reiserfs.patch')
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.2beta47/006-reiserfs.patch1272
1 files changed, 1272 insertions, 0 deletions
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.2beta47/006-reiserfs.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.2beta47/006-reiserfs.patch
new file mode 100644
index 0000000000..abdc67476e
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.2beta47/006-reiserfs.patch
@@ -0,0 +1,1272 @@
+# Patch origin: nfs-server source RPM from openSUSE 10.3
+
+--- nfs-server/Makefile.in
++++ nfs-server/Makefile.in 2002/11/08 13:59:16
+@@ -100,7 +100,7 @@
+ 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 daemon.c signals.c
++ haccess.c daemon.c signals.c teahash3.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
+@@ -112,7 +112,7 @@
+ MANPAGES8 = showmount
+ MANPAGES = $(MANPAGES5) $(MANPAGES8p) $(MANPAGES8)
+ LIBOBJS = version.o fsusage.o mountlist.o xmalloc.o xstrdup.o \
+- nfsmounted.o faccess.o haccess.o daemon.o \
++ nfsmounted.o faccess.o haccess.o daemon.o teahash3.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 \
+--- nfs-server/auth.c
++++ nfs-server/auth.c 2002/11/08 13:59:16
+@@ -83,6 +83,7 @@
+ 0, /* read-only */
+ 0, /* relative links */
+ 0, /* noaccess */
++ 0, /* hashed inodes */
+ 1, /* cross_mounts */
+ 1, /* allow setuid */
+ 65534, /* default uid */
+@@ -100,6 +101,7 @@
+ 0, /* relative links */
+ 0, /* noaccess */
+ 1, /* cross_mounts */
++ 0, /* hashed inodes */
+ 0, /* allow setuid */
+ 65534, /* default uid */
+ 65534, /* default gid */
+@@ -991,6 +993,7 @@
+ if (mp == 0) {
+ mp = (nfs_mount*) xmalloc(sizeof(nfs_mount));
+ memset(mp, 0, sizeof(*mp));
++ mp->mount_dev = 0;
+ mp->origin = cp;
+ mp->client = cp;
+ mp->path = xstrdup(path);
+@@ -1169,6 +1172,8 @@
+ default_options.nobody_gid = anon_gid;
+ anonymous_options.nobody_uid = anon_uid;
+ anonymous_options.nobody_gid = anon_gid;
++ default_options.cross_mounts = cross_mounts;
++ default_options.hashed_inodes = hashed_inodes;
+
+ memset(cached_clients, 0, sizeof(cached_clients));
+ cached_next = 0;
+--- nfs-server/auth.h
++++ nfs-server/auth.h 2002/11/08 13:59:16
+@@ -43,15 +43,16 @@
+
+ typedef struct nfs_options {
+ ugid_mapping_t uidmap; /* uid/gid mapping behavior */
+- int root_squash;
+- int all_squash;
+- int some_squash; /* speed up luid() etc. */
+- int secure_port;
+- int read_only;
+- int link_relative;
+- int noaccess;
+- int cross_mounts;
+- int allow_setuid;
++ unsigned root_squash : 1;
++ unsigned all_squash : 1;
++ unsigned some_squash : 1; /* speed up luid() etc. */
++ unsigned secure_port : 1;
++ unsigned read_only : 1;
++ unsigned link_relative : 1;
++ unsigned noaccess : 1;
++ unsigned cross_mounts : 1;
++ unsigned hashed_inodes : 1;
++ unsigned allow_setuid : 1;
+ uid_t nobody_uid;
+ gid_t nobody_gid;
+ char * clnt_nisdomain;
+@@ -64,6 +65,7 @@
+ int length;
+ char * path;
+ nfs_options o;
++ dev_t mount_dev;
+ /* Original NFS client */
+ struct nfs_client * origin;
+ } nfs_mount;
+@@ -121,6 +123,8 @@
+ extern void auth_check_all_netmasks(void);
+ extern void auth_sort_all_mountlists(void);
+ extern void auth_log_all(void);
++extern int auth_checkdev(nfs_mount *, dev_t dev);
++extern int auth_checkpathdev(char *, dev_t dev);
+
+ /* This function lets us set our euid/fsuid temporarily */
+ extern void auth_override_uid(uid_t);
+--- nfs-server/auth_clnt.c
++++ nfs-server/auth_clnt.c 2002/11/08 13:59:16
+@@ -89,6 +89,13 @@
+ return NULL;
+ }
+
++ if (!mp->o.cross_mounts && !mp->mount_dev) {
++ struct stat st;
++ if (!lstat(mp->path, &st) < 0)
++ return NULL;
++ mp->mount_dev = st.st_dev;
++ }
++
+ /* Check request originated on a privileged port. */
+ if (!allow_non_root && mp->o.secure_port
+ && !SECURE_PORT(svc_getcaller(rqstp->rq_xprt)->sin_port)) {
+@@ -350,3 +357,28 @@
+ return 1;
+ }
+ #endif
++
++int auth_checkpathdev(char *path, dev_t dev)
++{
++ nfs_mount *mp = auth_match_mount(nfsclient, path);
++ if (!mp)
++ return 0;
++ return auth_checkdev(mp, dev);
++}
++
++int auth_checkdev(nfs_mount *mp, dev_t dev)
++{
++ if (!mp->mount_dev)
++ return 1;
++ if (mp->mount_dev != dev) {
++ struct stat st;
++ /* Restat in case the cd switched */
++ if (efs_lstat(mp->path, &st) < 0) {
++ Dprintf(L_ERROR, "Unable to stat mount point %s\n", mp->path);
++ return 0;
++ }
++ mp->mount_dev = st.st_dev;
++ }
++ return mp->mount_dev == dev;
++}
++
+--- nfs-server/auth_init.c
++++ nfs-server/auth_init.c 2002/11/08 13:59:16
+@@ -320,6 +320,14 @@
+ /* knfsd compatibility, ignore */;
+ else ifkwd(4, "sync")
+ /* knfsd compatibility, ignore */;
++ else ifkwd(13, "hashed_inodes")
++ mp->o.hashed_inodes = 1;
++ else ifkwd(16, "no_hashed_inodes")
++ mp->o.hashed_inodes = 0;
++ else ifkwd(12, "cross_mounts")
++ mp->o.cross_mounts = 1;
++ else ifkwd(15, "no_cross_mounts")
++ mp->o.cross_mounts = 0;
+ else {
+ Dprintf(L_ERROR,
+ "Unknown keyword \"%.*s\" in export file\n",
+--- nfs-server/exports.man
++++ nfs-server/exports.man 2002/11/08 13:59:16
+@@ -208,6 +208,17 @@
+ .IR no_all_squash ,
+ which is the default setting.
+ .TP
++.IR hashed_inodes
++Use a special scheme to generate inode numbers that may work better with
++reiserfs filesystems.
++.IR no_hashed_inodes
++which uses a direct mapping is the default.
++.TP
++.IR cross_mounts
++Do not cross mount points in exports. Turning this off with
++.IR no_cross_mounts
++avoids inode number space conflicts when there are too many files.
++.TP
+ .IR map_daemon
+ This option turns on dynamic uid/gid mapping. Each uid in an NFS request
+ will be translated to the equivalent server uid, and each uid in an
+--- nfs-server/fh.c
++++ nfs-server/fh.c 2002/11/08 14:11:31
+@@ -4,8 +4,9 @@
+ *
+ * Interfaces:
+ * pseudo_inode
+- * mostly used internally, but also called from unfsd.c
+- * when reporting directory contents.
++ * mostly used internally, for hash tables
++ * visible_inode
++ * generate visible inode shown to the client in the fattr.
+ * fh_init
+ * Initializes the queues and 'flush' timer
+ * fh_pr
+@@ -47,6 +48,8 @@
+ * Note: the original code mistakenly assumes that the overall path
+ * length remains within the value given by PATH_MAX... that leads
+ * to interesting buffer overflows all over the place.
++ *
++ * Depends that dev_t only uses 16bits.
+ */
+
+ #include <assert.h>
+@@ -137,9 +140,9 @@
+ };
+
+ /* Forward declared local functions */
+-static psi_t path_psi(char *, nfsstat *, struct stat *, int);
++static psi_t path_psi(char *, nfsstat *, struct stat *, int, int *);
+ static psi_t path_psi_m(char *, nfsstat *, struct stat *,
+- struct stat *, int);
++ struct stat *, int, int *);
+ static int fh_flush_fds(void);
+ static char * fh_dump(svc_fh *);
+ static void fh_insert_fdcache(fhcache *fhc);
+@@ -173,19 +176,22 @@
+ fh_list_size++;
+
+ /* Insert into hash tab. */
+- hash_slot = &(fh_hashed[fhc->h.psi % HASH_TAB_SIZE]);
++ hash_slot = &(fh_hashed[pseudo_inode(fhc->h.ino,fhc->h.dev) % HASH_TAB_SIZE]);
+ fhc->hash_next = *hash_slot;
+ *hash_slot = fhc;
+ }
+
+ static fhcache *
+-fh_lookup(psi_t psi)
++fh_lookup(ino_t ino, dev_t dev)
+ {
+ register fhcache *fhc;
+
+- fhc = fh_hashed[psi % HASH_TAB_SIZE];
+- while (fhc != NULL && fhc->h.psi != psi)
++ fhc = fh_hashed[pseudo_inode(ino,dev) % HASH_TAB_SIZE];
++ while (fhc != NULL) {
++ if (fhc->h.ino == ino && fhc->h.dev == dev)
++ break;
+ fhc = fhc->hash_next;
++ }
+ return (fhc);
+ }
+
+@@ -193,7 +199,8 @@
+ fh_insert_fdcache(fhcache *fhc)
+ {
+ #ifdef FHTRACE
+- Dprintf(D_FHTRACE, "insert fh %x into fdcache @%d\n", fhc->h.psi, fhc->fd);
++ Dprintf(D_FHTRACE, "insert fh %x,%x into fdcache @%d\n",
++ fhc->h.ino, fhc->h.dev, fhc->fd);
+ if (fhc->fd < 0) {
+ fh_complain("fd cache bug: bad fd", fhc);
+ return;
+@@ -289,8 +296,9 @@
+ #endif
+
+ Dprintf(D_FHTRACE|D_FHCACHE,
+- "fh_delete: deleting handle %x ('%s', fd=%d)\n",
+- fhc, fhc->path ? fhc->path : "<unnamed>", fhc->fd);
++ "fh_delete: deleting handle %x [%x,%x] ('%s', fd=%d)\n",
++ fhc, fhc->h.dev, fhc->h.ino, fhc->path ? fhc->path : "<unnamed>",
++ fhc->fd);
+
+ /* Remove from current posn */
+ fhc->prev->next = fhc->next;
+@@ -298,7 +306,7 @@
+ fh_list_size--;
+
+ /* Remove from hash tab */
+- hash_slot = &(fh_hashed[fhc->h.psi % HASH_TAB_SIZE]);
++ hash_slot = &(fh_hashed[pseudo_inode(fhc->h.ino,fhc->h.dev) % HASH_TAB_SIZE]);
+ while (*hash_slot != NULL && *hash_slot != fhc)
+ hash_slot = &((*hash_slot)->hash_next);
+ if (*hash_slot == NULL)
+@@ -528,6 +536,7 @@
+ index -= 8;
+ }
+
++#if 0
+ /* If we have an XXL inode number, spew out warning (but at most
+ * once a second) */
+ if (inode & ~mask) {
+@@ -541,14 +550,34 @@
+ }
+ inode &= mask;
+ }
+-
++#endif
+ return (psi_t) (prefix | inode);
+ #endif
+ }
+
++/* Inode as handed out by attr calls. */
++psi_t
++visible_inode(ino_t ino, dev_t dev, nfs_mount *mount)
++{
++ if (!mount->o.cross_mounts)
++ return ino;
++
++ if (mount->o.hashed_inodes) {
++ extern __u32 teahash3(/*u32 k[2], *//*u8*/const char *msg, int len);
++
++ struct {
++ ino_t ino;
++ dev_t dev;
++ } tup = { ino,dev };
++ return teahash3((char *) &tup, sizeof tup);
++ }
++
++ return pseudo_inode(ino, dev);
++}
++
+ #if 1
+ static char *
+-fh_buildpath(svc_fh *h)
++fh_buildpath(svc_fh *h, dev_t basedev)
+ {
+ char pathbuf[PATH_MAX + NAME_MAX + 1], *path;
+ long cookie_stack[HP_LEN + 1];
+@@ -565,13 +594,17 @@
+
+ if (efs_stat("/", &sbuf) < 0)
+ return (NULL);
+- psi = pseudo_inode(sbuf.st_ino, sbuf.st_dev);
+ if (h->hash_path[0] == 0) {
+- if (psi != h->psi)
+- return (NULL);
+- return xstrdup("/");
++ if (sbuf.st_ino == h->ino && sbuf.st_dev == h->dev)
++ ;
++ else
++ return NULL;
++ strcpy(pathbuf,"/");
++ path = xstrdup(pathbuf);
++ return (path);
+ }
+
++ psi = pseudo_inode(sbuf.st_ino, sbuf.st_dev);
+ if (hash_psi(psi) != h->hash_path[1])
+ return (NULL);
+
+@@ -599,11 +632,18 @@
+
+ psi = pseudo_inode(dp->d_ino, sbuf.st_dev);
+ if (i == h->hash_path[0] + 1) {
+- if (psi != h->psi)
++ if (sbuf.st_dev != h->dev || dp->d_ino != h->ino)
+ continue;
+ /* GOT IT */
+ strcpy(pathbuf + pathlen, dp->d_name);
+- path = xstrdup(pathbuf);
++ if (!basedev || sbuf.st_dev == basedev ||
++ auth_checkpathdev(pathbuf, sbuf.st_dev)) {
++ path = xstrdup(pathbuf);
++ } else {
++ dprintf(L_ERROR, "fh_buildpath: basedev %x != dev %x for %s\n",
++ (unsigned)basedev,(unsigned)sbuf.st_dev,pathbuf);
++ path = NULL;
++ }
+ efs_closedir(dir);
+ auth_override_uid(auth_uid);
+ return (path);
+@@ -754,16 +794,16 @@
+ #endif
+
+ static psi_t
+-path_psi(char *path, nfsstat *status, struct stat *sbp, int svalid)
++path_psi(char *path, nfsstat *status, struct stat *sbp, int svalid, int *mp)
+ {
+ struct stat smounted;
+
+- return path_psi_m(path, status, sbp, &smounted, svalid);
++ return path_psi_m(path, status, sbp, &smounted, svalid, mp);
+ }
+
+ static psi_t
+ path_psi_m(char *path, nfsstat *status,
+- struct stat *sbp, struct stat *mbp, int svalid)
++ struct stat *sbp, struct stat *mbp, int svalid, int *mp)
+ {
+ struct stat sbuf, ddbuf;
+
+@@ -815,6 +855,8 @@
+ DIR *dirp;
+ struct dirent *dp;
+
++ if (mp) *mp = 1;
++
+ errno = 0;
+ dirp = efs_opendir(dname);
+ fname[-1] = '/'; /* Restore path */
+@@ -860,9 +902,70 @@
+ }
+
+ fhcache *
+-fh_find(svc_fh *h, int mode)
++fh_newfh(svc_fh *h, int mode, dev_t basedev)
++{
++ fhcache *fhc, *flush;
++
++ ex_state = active;
++ for (flush = fh_tail.prev; fh_list_size > FH_CACHE_LIMIT; flush = fhc) {
++ /* Don't flush current head. */
++ if (flush == &fh_head)
++ break;
++ fhc = flush->prev;
++ fh_delete(flush);
++ }
++ fhc = (fhcache *) xmalloc(sizeof *fhc);
++ if (mode == FHFIND_FCREATE) {
++ /* File will be created */
++ fhc->path = NULL;
++ } else {
++ /* File must exist. Attempt to construct from hash_path */
++ char *path;
++
++ if ((path = fh_buildpath(h, basedev)) == NULL) {
++#ifdef FHTRACE
++ Dprintf(D_FHTRACE, "fh_find: stale fh (hash path)\n");
++ Dprintf(D_FHTRACE, "\tdata: %s\n", fh_dump(h));
++#endif
++ free(fhc);
++ ex_state = inactive;
++ return NULL;
++ }
++ fhc->path = path;
++ }
++ fhc->flags = 0;
++ if (fhc->path && efs_lstat(fhc->path, &fhc->attrs) >= 0) {
++ if (re_export && nfsmounted(fhc->path, &fhc->attrs))
++ fhc->flags |= FHC_NFSMOUNTED;
++ fhc->flags |= FHC_ATTRVALID;
++ }
++ fhc->fd = -1;
++ fhc->last_used = curtime;
++ fhc->h = *h;
++ fhc->last_clnt = NULL;
++ fhc->last_mount = NULL;
++ fhc->last_uid = (uid_t)-1;
++ fhc->fd_next = fhc->fd_prev = NULL;
++ fh_inserthead(fhc);
++ Dprintf(D_FHCACHE,
++ "fh_find: created new handle %x (path `%s' ino:%x dev:%x)\n",
++ fhc, fhc->path ? fhc->path : "<unnamed>", fhc->h.ino, fhc->h.dev);
++ ex_state = inactive;
++ if (fh_list_size > FH_CACHE_LIMIT)
++ flush_cache(0);
++#ifdef FHTRACE
++ if (fhc->h.hash_path[0] == 0xFF) {
++ Dprintf(L_ERROR, "newly created fh instantly flushed?!");
++ return NULL;
++ }
++#endif
++ return (fhc);
++}
++
++fhcache *
++fh_find(svc_fh *h, int mode, dev_t basedev)
+ {
+- register fhcache *fhc, *flush;
++ register fhcache *fhc;
+ int check;
+
+ check = (mode & FHFIND_CHECK);
+@@ -877,12 +980,12 @@
+
+ ex_state = active;
+ time(&curtime);
+- while ((fhc = fh_lookup(h->psi)) != NULL) {
++ while ((fhc = fh_lookup(h->ino,h->dev)) != NULL) {
+ struct stat sbuf, *s = NULL;
+ nfsstat dummy;
+
+- Dprintf(D_FHCACHE, "fh_find: psi=%lx... found '%s', fd=%d\n",
+- (unsigned long) h->psi,
++ Dprintf(D_FHCACHE, "fh_find: (%u,%u)... found '%s', fd=%d\n",
++ h->ino, h->dev,
+ fhc->path ? fhc->path : "<unnamed>",
+ fhc->fd);
+
+@@ -905,6 +1008,7 @@
+ Dprintf(D_FHTRACE,
+ "fh_find: stale fh: lstat: %m\n");
+ } else {
++ int mp = 0;
+ /* If device/ino don't match, fhc->path may
+ * be a mount point (hence lstat() returns
+ * a different inode number than the readdir()
+@@ -915,19 +1019,26 @@
+
+ /* Get the dev/ino of the underlying
+ * mount point. */
+- path_psi(fhc->path, &dummy, s, 1);
+- if (fh_attrmatch(fhc, s))
+- goto fh_return;
++ if (path_psi(fhc->path, &dummy, s, 1, &mp) &&
++ fh_attrmatch(fhc, s)) {
++ if (!mp)
++ Dprintf(D_FHTRACE,"fh_find: should be mount point %x,%x\n",
++ h->dev,h->ino);
++
++ }
+
+- Dprintf(D_FHTRACE, "fh_find: stale fh: %lx",
+- (unsigned long) h->psi);
++ Dprintf(D_FHTRACE, "fh_find: stale fh: "
++ "dev/ino %x/%lx ino:%x dev:%x",
++ s->st_dev, s->st_ino,
++ (unsigned)h->ino, (unsigned)h->dev);
+ }
+
+ fh_discard:
+ #ifdef FHTRACE
+ Dprintf(D_FHTRACE, "\tdata: %s\n", fh_dump(h));
+ #endif
+- Dprintf(D_FHCACHE, "fh_find: delete cached handle\n");
++ Dprintf(D_FHCACHE, "fh_find: delete cached handle %x,%x <%x>\n",
++ fhc->h.dev,fhc->h.ino,fhc->path ? fhc->path : "no path");
+ fh_delete(fhc);
+ break;
+ }
+@@ -947,88 +1058,13 @@
+ return (fhc);
+ }
+
+- Dprintf(D_FHCACHE, "fh_find: psi=%lx... not found\n",
+- (unsigned long) h->psi);
+-
+- if (mode == FHFIND_FCACHED) {
+- ex_state = inactive;
+- return NULL;
+- }
+-
+- for (flush = fh_tail.prev; fh_list_size > FH_CACHE_LIMIT; flush = fhc) {
+- /* Don't flush current head. */
+- if (flush == &fh_head)
+- break;
+- fhc = flush->prev;
+- fh_delete(flush);
+- }
+-
+- fhc = (fhcache *) xmalloc(sizeof *fhc);
+- if (mode == FHFIND_FCREATE) {
+- /* File will be created */
+- fhc->path = NULL;
+- } else {
+- /* File must exist. Attempt to construct from hash_path */
+- char *path;
+-
+- if ((path = fh_buildpath(h)) == NULL) {
+-#ifdef FHTRACE
+- Dprintf(D_FHTRACE, "fh_find: stale fh (hash path)\n");
+- Dprintf(D_FHTRACE, "\tdata: %s\n", fh_dump(h));
+-#endif
+- free(fhc);
+- ex_state = inactive;
+- return NULL;
+- }
+- fhc->path = path;
+- }
+-
+- fhc->flags = 0;
+- if (fhc->path && efs_lstat(fhc->path, &fhc->attrs) >= 0) {
+- 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;
+- fhc->h = *h;
+- fhc->last_clnt = NULL;
+- fhc->last_mount = NULL;
+- fhc->last_uid = (uid_t)-1;
+- fhc->fd_next = fhc->fd_prev = NULL;
+- fh_inserthead(fhc);
+- Dprintf(D_FHCACHE,
+- "fh_find: created new handle %x (path `%s' psi %08x)\n",
+- fhc, fhc->path ? fhc->path : "<unnamed>", fhc->h.psi);
+ ex_state = inactive;
+- if (fh_list_size > FH_CACHE_LIMIT)
+- flush_cache(0);
+-#ifdef FHTRACE
+- if (fhc->h.hash_path[0] == 0xFF) {
+- Dprintf(L_ERROR, "newly created fh instantly flushed?!");
++
++ Dprintf(D_FHCACHE, "fh_find: (%u,%u) ... not found\n",
++ h->ino, h->dev);
++ if (mode == FHFIND_FCACHED)
+ return NULL;
+- }
+-#endif
+- return (fhc);
++ return fh_newfh(h, mode, basedev);
+ }
+
+ /*
+@@ -1040,7 +1076,7 @@
+ {
+ fhcache *h;
+
+- if ((h = fh_find((svc_fh *) fh, FHFIND_FCACHED)) == NULL)
++ if ((h = fh_find((svc_fh *) fh, FHFIND_FCACHED, 0)) == NULL)
+ return fh_dump((svc_fh *) fh);
+ return (h->path);
+ }
+@@ -1050,10 +1086,10 @@
+ {
+ static char buf[65];
+ char *sp;
+- int i, n = fh->hash_path[0];
++ int i, n = fh->hash_path[0], l;
+
+- sprintf(buf, "%08x %02x ", fh->psi, fh->hash_path[0]);
+- for (i = 1, sp = buf + 12; i <= n && i < HP_LEN; i++, sp += 2)
++ l = sprintf(buf, "%08x %04x %02x ", fh->ino, fh->dev, fh->hash_path[0]);
++ for (i = 1, sp = buf + l; i <= n && i < HP_LEN; i++, sp += 2)
+ sprintf(sp, "%02x", fh->hash_path[i]);
+ return buf;
+ }
+@@ -1082,7 +1118,7 @@
+
+ memset(&key, 0, sizeof(key));
+ status = NFS_OK;
+- if ((psi = path_psi("/", &status, &stb, 0)) == 0)
++ if ((psi = path_psi("/", &status, &stb, 0, NULL)) == 0)
+ return ((int) status);
+
+ s = path;
+@@ -1091,7 +1127,7 @@
+ return ((int) NFSERR_NAMETOOLONG);
+ key.hash_path[key.hash_path[0]] = hash_psi(psi);
+ *s = '\0';
+- if ((psi = path_psi(path, &status, &stb, 0)) == 0)
++ if ((psi = path_psi(path, &status, &stb, 0, NULL)) == 0)
+ return ((int) status);
+ *s = '/';
+ }
+@@ -1099,11 +1135,12 @@
+ 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, &stb, 0)) == 0)
++ if ((psi = path_psi(path, &status, &stb, 0, NULL)) == 0)
+ return ((int) status);
+ }
+- key.psi = psi;
+- h = fh_find(&key, FHFIND_FCREATE);
++ key.dev = stb.st_dev;
++ key.ino = stb.st_ino;
++ h = fh_find(&key, FHFIND_FCREATE, 0);
+
+ #ifdef FHTRACE
+ if (!h)
+@@ -1123,6 +1160,7 @@
+ return ((int) status);
+ }
+
++#if 0
+ char *
+ fh_path(nfs_fh *fh, nfsstat *status)
+ {
+@@ -1135,6 +1173,7 @@
+ *status = NFS_OK;
+ return (h->path);
+ }
++#endif
+
+ nfs_fh *
+ fh_handle(fhcache *h)
+@@ -1349,7 +1388,7 @@
+ if (sbp == NULL)
+ sbp = &sbuf;
+
+- if ((dirh = fh_find((svc_fh *) &dopa->dir, FHFIND_FEXISTS)) == NULL)
++ if ((dirh = fh_find((svc_fh *) &dopa->dir, FHFIND_FEXISTS, 0)) == NULL)
+ return NFSERR_STALE;
+
+ /*
+@@ -1419,8 +1458,22 @@
+
+ *new_fh = dopa->dir;
+ key = (svc_fh *) new_fh;
+- if ((key->psi = path_psi_m(pathbuf, &ret, sbp, &smount, 0)) == 0)
++
++ if (path_psi_m(pathbuf, &ret, sbp, &smount, 0, NULL) == 0)
+ return (ret);
++ key->ino = sbp->st_ino;
++ key->dev = sbp->st_dev;
++
++ if (sbp->st_dev != dirh->h.dev) {
++ nfs_mount *mp = dirh->last_mount;
++ if (!mp)
++ Dprintf(L_ERROR, "no last mount in fh_compose for %s\n", pathbuf);
++ else if (auth_checkdev(mp, sbp->st_dev) == 0) {
++ Dprintf(L_ERROR, "access to no cross path below mountpoint (<%s>, %x<->%x)\n",
++ pathbuf, mp->mount_dev, sbp->st_dev);
++ return NFSERR_STALE;
++ }
++ }
+
+ if (is_dd) {
+ /* Don't cd .. from root, or mysterious ailments will
+@@ -1430,11 +1483,12 @@
+ } else {
+ if (++(key->hash_path[0]) >= HP_LEN)
+ return NFSERR_NAMETOOLONG;
+- key->hash_path[key->hash_path[0]] = hash_psi(dirh->h.psi);
++ key->hash_path[key->hash_path[0]] = hash_psi(pseudo_inode(dirh->h.ino,
++ dirh->h.dev));
+ }
+ /* FIXME: when crossing a mount point, we'll find the real
+ * dev/ino in sbp and can store it in h... */
+- h = fh_find(key, FHFIND_FCREATE);
++ h = fh_find(key, FHFIND_FCREATE, 0);
+
+ #ifdef FHTRACE
+ if (h == NULL)
+@@ -1456,7 +1510,7 @@
+ /* We must have cached an old file under the same inode # */
+ Dprintf(D_FHTRACE, "Disposing of fh with bad path.\n");
+ fh_delete(h);
+- h = fh_find(key, FHFIND_FCREATE);
++ h = fh_find(key, FHFIND_FCREATE, dirh->last_mount ? dirh->last_mount->mount_dev : 0);
+ #ifdef FHTRACE
+ if (!h) return NFSERR_STALE;
+ #endif
+@@ -1511,12 +1565,14 @@
+ return (NFS_OK);
+ }
+
++#if 0
+ psi_t
+ fh_psi(nfs_fh *fh)
+ {
+ svc_fh *h = (svc_fh *) fh;
+ return (h->psi);
+ }
++#endif
+
+ void
+ fh_remove(char *path)
+@@ -1524,12 +1580,13 @@
+ psi_t psi;
+ nfsstat status;
+ fhcache *fhc;
++ struct stat st;
+
+- psi = path_psi(path, &status, NULL, 0);
++ psi = path_psi(path, &status, &st, 0, NULL);
+ if (psi == 0)
+ return;
+ ex_state = active;
+- fhc = fh_lookup(psi);
++ fhc = fh_lookup(st.st_ino,st.st_dev);
+ if (fhc != NULL)
+ fh_delete(fhc);
+
+@@ -1634,6 +1691,11 @@
+ fh_init(void)
+ {
+ static int initialized = 0;
++
++ if (sizeof(svc_fh) > 32) {
++ fprintf(stderr, "filehandle wrong size %d\n", sizeof(svc_fh));
++ exit(10);
++ }
+
+ if (initialized)
+ return;
+--- nfs-server/fh.h
++++ nfs-server/fh.h 2002/11/08 13:59:16
+@@ -20,6 +20,7 @@
+ #define FHC_XONLY_PATH 001 /* NOT USED ANYMORE */
+ #define FHC_ATTRVALID 002
+ #define FHC_NFSMOUNTED 004
++#define FHC_CROSS 010
+
+ /* Modes for fh_find */
+ #define FHFIND_FEXISTS 0 /* file must exist */
+@@ -65,11 +66,12 @@
+ *
+ * hash_path[hash_path[0]+1] ... hash_path[HP_LEN-1] == 0
+ */
+-#define HP_LEN (NFS_FHSIZE - sizeof(psi_t))
++#define HP_LEN (NFS_FHSIZE-sizeof(u_int32_t)-sizeof(u_int16_t))
+ typedef struct {
+- psi_t psi;
++ u_int32_t ino;
++ u_int16_t dev;
+ __u8 hash_path[HP_LEN];
+-} svc_fh;
++} svc_fh __attribute__((packed));
+
+ typedef enum { inactive, active } mutex;
+
+@@ -100,6 +102,7 @@
+
+ /* These are fixed during the lifetime of this object */
+ svc_fh h;
++ psi_t psi;
+ dev_t dev;
+ ino_t ino;
+ mode_t type; /* st_mode & S_IFMT */
+@@ -122,10 +125,11 @@
+ /* Global function prototypes. */
+ extern nfsstat nfs_errno(void);
+ extern psi_t pseudo_inode(ino_t inode, dev_t dev);
++extern psi_t visible_inode(ino_t inode, dev_t dev, nfs_mount *);
+ extern void fh_init(void);
+ extern char *fh_pr(nfs_fh *fh);
+ extern int fh_create(nfs_fh *fh, char *path);
+-extern fhcache *fh_find(svc_fh *h, int create);
++extern fhcache *fh_find(svc_fh *h, int create, dev_t basedev);
+ extern char *fh_path(nfs_fh *fh, nfsstat *status);
+ extern int path_open(char *path, int omode, int perm);
+ extern int fh_fd(fhcache *fhc, nfsstat *status, int omode);
+@@ -139,6 +143,7 @@
+ extern void fh_flush(int force);
+ extern RETSIGTYPE flush_cache(int sig);
+ extern int nfsmounted(const char *path, struct stat *sbp);
++extern fhcache *fh_newfh(svc_fh *fh, int mode, dev_t basedev);
+
+ #ifdef ENABLE_DEVTAB
+ extern unsigned int devtab_index(dev_t);
+--- nfs-server/getattr.c
++++ nfs-server/getattr.c 2002/11/08 13:59:16
+@@ -43,7 +43,7 @@
+ {
+ fhcache *fhc;
+
+- if ((fhc = fh_find((svc_fh*)fh, FHFIND_FEXISTS)) == NULL) {
++ if ((fhc = fh_find((svc_fh*)fh, FHFIND_FEXISTS, 0)) == NULL) {
+ Dprintf(D_CALL, "getattr: failed! No such file.\n");
+ return (NFSERR_STALE);
+ }
+@@ -103,18 +103,8 @@
+ #else
+ attr->blocks = st_blocks(s);
+ #endif
+-#if 0
+- if (nfsmount->o.cross_mounts) {
+- attr->fsid = 1;
+- attr->fileid = fh_psi((nfs_fh *)&(fhc->h));
+- } else {
+- attr->fsid = s->st_dev;
+- attr->fileid = covered_ino(fhc->path);
+- }
+-#else
+- attr->fsid = 1;
+- attr->fileid = fh_psi((nfs_fh *)&(fhc->h));
+-#endif
++ attr->fsid = 1; // XXX
++ attr->fileid = visible_inode(fhc->h.ino, fhc->h.dev, nfsmount);
+
+ /* This may be needed by some Suns... testing */
+ #define MINTIME (24 * 2600)
+--- nfs-server/mountd.c
++++ nfs-server/mountd.c 2002/11/08 13:59:16
+@@ -36,6 +36,8 @@
+ #include "signals.h"
+ #include <rpc/pmap_clnt.h>
+
++int cross_mounts = 1;
++int hashed_inodes; /* dummy */
+
+ static void usage(FILE *, int);
+ static void terminate(void);
+@@ -58,9 +60,9 @@
+ { "no-spoof-trace", 0, 0, 't' },
+ { "version", 0, 0, 'v' },
+ { "fail-safe", optional_argument, 0, 'z' },
++ { "no-cross-mounts", 0, 0, 'x' },
+ { "no-tcp", 0, 0, OPT_NOTCP },
+ { "loopback-only", 0, 0, OPT_LOOPBACK },
+-
+ { NULL, 0, 0, 0 }
+ };
+ static const char * shortopts = "Fd:f:hnpP:rtvz::";
+@@ -80,6 +82,7 @@
+ int need_reinit = 0;
+ int need_flush = 0;
+ extern char version[];
++nfs_client *nfsclient; /* dummy */
+
+ /*
+ * NULL
+@@ -319,6 +322,9 @@
+ opterr = 0;
+ while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != EOF)
+ switch (c) {
++ case 'x':
++ cross_mounts = 0;
++ break;
+ case 'F':
+ foreground = 1;
+ break;
+@@ -444,7 +450,7 @@
+ program_name);
+ fprintf(fp, " [--debug kind] [--help] [--allow-non-root]\n");
+ fprintf(fp, " [--promiscuous] [--version] [--port portnum]\n");
+- fprintf(fp, " [--exports-file=file]\n");
++ fprintf(fp, " [--exports-file=file] [--no-cross-mounts]\n");
+ exit(n);
+ }
+
+--- nfs-server/nfsd.c
++++ nfs-server/nfsd.c 2002/11/08 14:20:57
+@@ -72,7 +72,7 @@
+ { "no-tcp", 0, 0, OPT_NOTCP },
+ { "udp-only", 0, 0, OPT_NOTCP },
+ { "loopback-only", 0, 0, OPT_LOOPBACK },
+-
++ { "hashed-inodes", 0, 0, 'I' },
+ { NULL, 0, 0, 0 }
+ };
+ static const char * shortopts = "a:d:Ff:hlnP:prR:tvz::";
+@@ -91,6 +91,7 @@
+ int need_flush = 0; /* flush fh cache */
+ int read_only = 0; /* Global ro forced */
+ int cross_mounts = 1; /* Transparently cross mnts */
++int hashed_inodes = 0;
+ int log_transfers = 0; /* Log transfers */
+ static svc_fh public_fh; /* Public NFSv2 FH */
+
+@@ -122,12 +123,17 @@
+ {
+ static int total = 0, cached = 0;
+ fhcache *fhc;
++ int newfh = 0;
+
+- /* Try to map FH. If not cached, reconstruct path with root priv */
+- fhc = fh_find((svc_fh *)fh, FHFIND_FEXISTS|FHFIND_CHECK);
+- if (fhc == NULL) {
+- *statp = NFSERR_STALE;
+- return NULL;
++ /* Try to map FH. */
++ fhc = fh_find((svc_fh *)fh, FHFIND_FCACHED|FHFIND_CHECK, 0);
++ if (!fhc) {
++ fhc = fh_newfh((svc_fh*)fh, FHFIND_FEXISTS|FHFIND_CHECK, 0);
++ if (!fhc) {
++ *statp = NFSERR_STALE;
++ return NULL;
++ }
++ newfh = 1;
+ }
+
+ /* Try to retrieve last client who accessed this fh */
+@@ -163,6 +169,16 @@
+ 100 * (double) cached / total);
+ */
+
++ /* Trust the crossmount check of the parent directory for creates */
++ if (newfh &&
++ (fhc->flags & FHC_ATTRVALID) &&
++ auth_checkdev(nfsmount, fhc->attrs.st_dev) == 0) {
++ Dprintf(L_ERROR, "auth_fh: fh crossed mount %s: %x<->%x\n",
++ fhc->path ? fhc->path : "???", nfsmount->mount_dev, fhc->attrs.st_dev);
++ *statp = NFSERR_STALE; /* or ACCES? */
++ return NULL;
++ }
++
+ if (nfsmount->o.noaccess &&
+ ((flags & CHK_NOACCESS) || strcmp(nfsmount->path, fhc->path))) {
+ struct in_addr addr = svc_getcaller(rqstp->rq_xprt)->sin_addr;
+@@ -195,6 +211,7 @@
+ fhcache *fhc;
+ nfsstat status;
+ char *path = buf, *sp;
++ struct stat st;
+
+ /* Authenticate directory file handle */
+ if ((fhc = auth_fh(rqstp, &dopa->dir, &status, flags)) == NULL)
+@@ -219,6 +236,9 @@
+ if ((nfsmount = auth_path(nfsclient, rqstp, path)) == NULL)
+ return NFSERR_ACCES;
+
++ if (efs_lstat(path, &st) >= 0 && !auth_checkdev(nfsmount, st.st_dev))
++ return NFSERR_ACCES;
++
+ /* XXX: really need to call it again here?
+ * Already invoked in auth_fh */
+ if (!auth_user(nfsmount, rqstp))
+@@ -318,7 +338,8 @@
+ int ispublic = 0;
+
+ /* First check whether this is the public FH */
+- if (((svc_fh *) fh)->psi == 0 && !memcmp(fh, &public_fh, FHSIZE)) {
++ if (((svc_fh *) fh)->dev == 0 && ((svc_fh*)fh)->ino == 0 &&
++ !memcmp(fh, &public_fh, FHSIZE)) {
+ if (public_root_path == NULL)
+ return NFSERR_ACCES;
+ memcpy(&argp->dir, &public_root, NFS_FHSIZE);
+@@ -333,6 +354,7 @@
+ if (!(fhc = auth_fh(rqstp, fh, &status, CHK_READ)))
+ return status;
+
++ /* FIXME: does too many stats */
+ status = fh_compose(argp, &dp->file, &sbuf, -1, -1, ispublic);
+ if (status != NFS_OK)
+ return status;
+@@ -896,6 +918,9 @@
+ errno = 0;
+ if (efs_lstat(h->path, &sbuf) < 0 || !(S_ISDIR(sbuf.st_mode)))
+ return (NFSERR_NOTDIR);
++ if (!auth_checkdev(h->last_mount, sbuf.st_dev))
++ dotsonly = 1;
++
+ if ((dirp = efs_opendir(h->path)) == NULL)
+ return ((errno ? nfs_errno() : NFSERR_NAMETOOLONG));
+
+@@ -923,7 +948,7 @@
+ }
+
+ e = *ep = (entry *) xmalloc(sizeof(entry));
+- e->fileid = pseudo_inode(dp->d_ino, sbuf.st_dev);
++ e->fileid = visible_inode(dp->d_ino, sbuf.st_dev, h->last_mount);
+ e->name = xmalloc(NLENGTH(dp) + 1);
+ strcpy(e->name, dp->d_name);
+ dloc = htonl(efs_telldir(dirp));
+@@ -1033,6 +1058,9 @@
+ case 'x':
+ cross_mounts = 0;
+ break;
++ case 'I':
++ hashed_inodes = 1;
++ break;
+ case 'z':
+ if (optarg)
+ failsafe_level = atoi(optarg);
+@@ -1189,7 +1217,7 @@
+ " [--debug kind] [--exports-file=file] [--port port]\n"
+ " [--allow-non-root] [--promiscuous] [--version] [--foreground]\n"
+ " [--re-export] [--log-transfers] [--public-root path]\n"
+-" [--no-spoof-trace] [--help]\n"
++" [--no-spoof-trace] [--no-cross-mounts] [--hashed-inodes] [--help]\n"
+ , program_name);
+ exit(n);
+ }
+--- nfs-server/nfsd.h
++++ nfs-server/nfsd.h 2002/11/08 13:59:16
+@@ -51,6 +51,7 @@
+ extern int need_reinit;
+ extern int need_flush;
+ extern time_t nfs_dispatch_time;
++extern int cross_mounts, hashed_inodes;
+
+ /* Include the other module definitions. */
+ #include "auth.h"
+--- nfs-server/setattr.c
++++ nfs-server/setattr.c 2002/11/08 13:59:16
+@@ -17,6 +17,7 @@
+
+ #define IGNORE_TIME ((unsigned int) -1)
+
++#if 0
+ /*
+ * Set file attributes based on file handle
+ */
+@@ -33,6 +34,7 @@
+ }
+ return setattr(path, attr, s, rqstp, flags);
+ }
++#endif
+
+ /*
+ * Set file attributes given the path. The flags argument
+--- nfs-server/teahash3.c
++++ nfs-server/teahash3.c 2002/11/08 13:59:16
+@@ -0,0 +1,168 @@
++/* Taken from the reiserfs source code and hacked slightly by AK.
++ * This is GPLed. */
++/*
++ * Keyed 32-bit hash function using TEA in a Davis-Meyer function
++ * H0 = Key
++ * Hi = E Mi(Hi-1) + Hi-1
++ *
++ * (see Applied Cryptography, 2nd edition, p448).
++ *
++ * Jeremy Fitzhardinge <jeremy@zip.com.au> 1998
++ *
++ * Jeremy has agreed to the contents of reiserfs/README. -Hans
++ */
++
++#include <assert.h>
++
++#if 0
++/* OK for Intel */
++typedef unsigned long u32;
++typedef const unsigned char u8;
++#else
++#include <inttypes.h>
++typedef uint32_t u32;
++typedef uint8_t u8;
++#endif
++
++
++#define DELTA 0x9E3779B9
++#define FULLROUNDS 10 /* 32 is overkill, 16 is strong crypto */
++#define PARTROUNDS 6 /* 6 gets complete mixing */
++
++/* a, b, c, d - data; h0, h1 - accumulated hash */
++#define TEACORE(rounds) \
++ do { \
++ u32 sum = 0; \
++ int n = rounds; \
++ u32 b0, b1; \
++ \
++ b0 = h0; \
++ b1 = h1; \
++ \
++ do \
++ { \
++ sum += DELTA; \
++ b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); \
++ b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); \
++ } while(--n); \
++ \
++ h0 += b0; \
++ h1 += b1; \
++ } while(0)
++
++u32 teahash3(/*u32 k[2], *//*u8*/const char *msg, int len)
++{
++ u32 k[] = { 0x9464a485, 0x542e1a94, 0x3e846bff, 0xb75bcfc3};
++
++ u32 h0 = k[0], h1 = k[1];
++ u32 a, b, c, d;
++ u32 pad;
++ int i;
++
++ assert(len >= 0 && len < 256);
++
++ pad = (u32)len | ((u32)len << 8);
++ pad |= pad << 16;
++
++ while(len >= 16)
++ {
++ a = (u32)msg[ 0] |
++ (u32)msg[ 1] << 8 |
++ (u32)msg[ 2] << 16|
++ (u32)msg[ 3] << 24;
++ b = (u32)msg[ 4] |
++ (u32)msg[ 5] << 8 |
++ (u32)msg[ 6] << 16|
++ (u32)msg[ 7] << 24;
++ c = (u32)msg[ 8] |
++ (u32)msg[ 9] << 8 |
++ (u32)msg[10] << 16|
++ (u32)msg[11] << 24;
++ d = (u32)msg[12] |
++ (u32)msg[13] << 8 |
++ (u32)msg[14] << 16|
++ (u32)msg[15] << 24;
++
++ TEACORE(PARTROUNDS);
++
++ len -= 16;
++ msg += 16;
++ }
++
++ if (len >= 12)
++ {
++ assert(len < 16);
++
++ a = (u32)msg[ 0] |
++ (u32)msg[ 1] << 8 |
++ (u32)msg[ 2] << 16|
++ (u32)msg[ 3] << 24;
++ b = (u32)msg[ 4] |
++ (u32)msg[ 5] << 8 |
++ (u32)msg[ 6] << 16|
++ (u32)msg[ 7] << 24;
++ c = (u32)msg[ 8] |
++ (u32)msg[ 9] << 8 |
++ (u32)msg[10] << 16|
++ (u32)msg[11] << 24;
++
++ d = pad;
++ for(i = 12; i < len; i++)
++ {
++ d <<= 8;
++ d |= msg[i];
++ }
++ }
++ else if (len >= 8)
++ {
++ assert(len < 12);
++
++ a = (u32)msg[ 0] |
++ (u32)msg[ 1] << 8 |
++ (u32)msg[ 2] << 16|
++ (u32)msg[ 3] << 24;
++ b = (u32)msg[ 4] |
++ (u32)msg[ 5] << 8 |
++ (u32)msg[ 6] << 16|
++ (u32)msg[ 7] << 24;
++
++ c = d = pad;
++ for(i = 8; i < len; i++)
++ {
++ c <<= 8;
++ c |= msg[i];
++ }
++ }
++ else if (len >= 4)
++ {
++ assert(len < 8);
++
++ a = (u32)msg[ 0] |
++ (u32)msg[ 1] << 8 |
++ (u32)msg[ 2] << 16|
++ (u32)msg[ 3] << 24;
++
++ b = c = d = pad;
++ for(i = 4; i < len; i++)
++ {
++ b <<= 8;
++ b |= msg[i];
++ }
++ }
++ else
++ {
++ assert(len < 4);
++
++ a = b = c = d = pad;
++ for(i = 0; i < len; i++)
++ {
++ a <<= 8;
++ a |= msg[i];
++ }
++ }
++
++ TEACORE(FULLROUNDS);
++
++/* return 0;*/
++ return h0^h1;
++}
+--- nfs-server/ugid_map.c
++++ nfs-server/ugid_map.c 2002/11/08 13:59:16
+@@ -276,8 +276,10 @@
+ if ((gid == 0 && mountp->o.root_squash) || mountp->o.all_squash)
+ retgid = mountp->o.nobody_gid;
+
++#if 0
+ Dprintf(D_UGID, "lgid(%s, %d) = %d\n",
+ inet_ntoa(mountp->client->clnt_addr), gid, retgid);
++#endif
+ return retgid;
+ }
+