aboutsummaryrefslogtreecommitdiff
path: root/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'nfsd')
-rw-r--r--nfsd/Makefile4
-rw-r--r--nfsd/cache.c381
-rw-r--r--nfsd/fsys.c91
-rw-r--r--nfsd/loop.c326
-rw-r--r--nfsd/main.c34
-rw-r--r--nfsd/nfsd.h33
-rw-r--r--nfsd/ops.c405
-rw-r--r--nfsd/proctables.c57
-rw-r--r--nfsd/xdr.c116
9 files changed, 802 insertions, 645 deletions
diff --git a/nfsd/Makefile b/nfsd/Makefile
index 4460b4ba..2c05b7ed 100644
--- a/nfsd/Makefile
+++ b/nfsd/Makefile
@@ -26,9 +26,9 @@ OBJS = $(subst .c,.o,$(SRCS))
LCLHDRS = nfsd.h
target = nfsd
installationdir = $(sbindir)
+HURDLIBS=threads shouldbeinlibc
include ../Makeconf
-CPPFLAGS += -DLOCALSTATEDIR=$(localstatedir)
+CPPFLAGS += -DLOCALSTATEDIR=\"$(localstatedir)\"
-nfsd: ../libthreads/libthreads.a ../libshouldbeinlibc/libshouldbeinlibc.a \ No newline at end of file
diff --git a/nfsd/cache.c b/nfsd/cache.c
index 745a7c8e..7b96dbc2 100644
--- a/nfsd/cache.c
+++ b/nfsd/cache.c
@@ -1,5 +1,5 @@
-/*
- Copyright (C) 1996 Free Software Foundation, Inc.
+/* cache.c - Cache operations for the nfs daemon.
+ Copyright (C) 1996,98,99,2000,02 Free Software Foundation, Inc.
Written by Michael I. Bushnell, p/BSG.
This file is part of the GNU Hurd.
@@ -20,9 +20,12 @@
#include <string.h>
+#include <sys/mman.h>
#include <hurd/fsys.h>
#include <assert.h>
#include <string.h>
+#include <hurd/io.h>
+#include <hurd/auth.h>
#include "nfsd.h"
@@ -31,7 +34,6 @@
#define malloc spoogie_woogie /* ugh^2. */
#include <rpc/types.h>
#include <rpc/auth.h>
-#include <rpc/auth_unix.h>
#undef malloc
#define IDHASH_TABLE_SIZE 1024
@@ -44,9 +46,9 @@ spin_lock_t idhashlock = SPIN_LOCK_INITIALIZER;
static int nfreeids;
static int leastidlastuse;
-/* Compare I against the specified set of users/groups. */
+/* Compare I against the specified set of users/groups. */
/* Use of int in decl of UIDS and GIDS is correct here; that's
- the NFS type because they come in in known 32 bit slots. */
+ the NFS type because they come in in known 32 bit slots. */
static int
idspec_compare (struct idspec *i, int nuids, int ngids,
int *uids, int *gids)
@@ -56,20 +58,20 @@ idspec_compare (struct idspec *i, int nuids, int ngids,
return 0;
assert (sizeof (int) == sizeof (uid_t));
-
+
if (bcmp (i->uids, uids, nuids * sizeof (uid_t))
|| bcmp (i->gids, gids, ngids * sizeof (gid_t)))
return 0;
-
+
return 1;
}
-/* Compute a hash value for a given user spec */
+/* Compute a hash value for a given user spec. */
static int
idspec_hash (int nuids, int ngids, int *uids, int *gids)
{
int hash, n;
-
+
hash = nuids + ngids;
for (n = 0; n < ngids; n++)
hash += gids[n];
@@ -79,7 +81,7 @@ idspec_hash (int nuids, int ngids, int *uids, int *gids)
return hash;
}
-/* Lookup a user spec in the hash table and allocate a reference */
+/* Lookup a user spec in the hash table and allocate a reference. */
static struct idspec *
idspec_lookup (int nuids, int ngids, int *uids, int *gids)
{
@@ -98,15 +100,15 @@ idspec_lookup (int nuids, int ngids, int *uids, int *gids)
spin_unlock (&idhashlock);
return i;
}
-
+
assert (sizeof (uid_t) == sizeof (int));
i = malloc (sizeof (struct idspec));
i->nuids = nuids;
i->ngids = ngids;
i->uids = malloc (nuids * sizeof (uid_t));
i->gids = malloc (ngids * sizeof (gid_t));
- bcopy (uids, i->uids, nuids * sizeof (uid_t));
- bcopy (gids, i->gids, ngids * sizeof (gid_t));
+ memcpy (i->uids, uids, nuids * sizeof (uid_t));
+ memcpy (i->gids, gids, ngids * sizeof (gid_t));
i->references = 1;
i->next = idhashtable[hash];
@@ -129,42 +131,53 @@ process_cred (int *p, struct idspec **credp)
int ngids;
int firstgid;
int i;
-
- type = ntohl (*p++);
+
+ type = ntohl (*p);
+ p++;
if (type != AUTH_UNIX)
{
- int size = ntohl (*p++);
+ int size = ntohl (*p);
+ p++;
*credp = idspec_lookup (0, 0, 0, 0);
- return p + INTSIZE (size);
+ p += INTSIZE (size);
+ }
+ else
+ {
+ p++; /* Skip size. */
+ p++; /* Skip seconds. */
+ len = ntohl (*p);
+ p++;
+ p += INTSIZE (len); /* Skip hostname. */
+
+ uid = p++; /* Remember location of uid. */
+ *uid = ntohl (*uid);
+
+ firstgid = *(p++); /* Remember first gid. */
+ gids = p; /* Here is where the array will start. */
+ ngids = ntohl (*p);
+ p++;
+
+ /* Now swap the first gid to be the first element of the
+ array. */
+ *gids = firstgid;
+ ngids++; /* And count it. */
+
+ /* And byteswap the gids. */
+ for (i = 0; i < ngids; i++)
+ gids[i] = ntohl (gids[i]);
+
+ p += ngids - 1;
+
+ *credp = idspec_lookup (1, ngids, uid, gids);
}
-
- p++; /* skip size */
- p++; /* skip seconds */
- len = ntohl (*p++);
- p += INTSIZE (len); /* skip hostname */
-
- uid = p++; /* remember loc of uid */
- *uid = ntohl (*uid);
-
- firstgid = *p++; /* remember first gid */
- gids = p; /* here's where the array will start */
- ngids = ntohl (*p++);
-
- /* Now swap the first gid to be the first element of the array */
- *gids = firstgid;
- ngids++; /* and count it */
-
- /* And byteswap the gids */
- for (i = 1; i < ngids; i++)
- gids[i] = ntohl (gids[i]);
-
- /* Next is the verf field; skip it entirely */
- p++; /* skip id */
- len = htonl (*p++);
+
+ /* Next is the verf field; skip it entirely. */
+ p++; /* Skip ID. */
+ len = htonl (*p);
+ p++;
p += INTSIZE (len);
-
- *credp = idspec_lookup (1, ngids, uid, gids);
+
return p;
}
@@ -195,32 +208,43 @@ cred_ref (struct idspec *i)
void
scan_creds ()
{
- struct idspec *i;
int n;
int newleast = mapped_time->seconds;
spin_lock (&idhashlock);
+
if (mapped_time->seconds - leastidlastuse > ID_KEEP_TIMEOUT)
- for (n = 0; n < IDHASH_TABLE_SIZE && nfreeids; n++)
- for (i = idhashtable[n]; i && nfreeids; i = i->next)
- if (!i->references
- && mapped_time->seconds - i->lastuse > ID_KEEP_TIMEOUT)
- {
- nfreeids--;
- *i->prevp = i->next;
- if (i->next)
- i->next->prevp = i->prevp;
- free (i->uids);
- free (i->gids);
- free (i);
- }
- else
- if (!i->references && newleast > i->lastuse)
- newleast = i->lastuse;
-
- /* If we didn't bail early, then this is valid */
- if (nfreeids)
- leastidlastuse = newleast;
+ {
+ for (n = 0; n < IDHASH_TABLE_SIZE && nfreeids; n++)
+ {
+ struct idspec *i = idhashtable[n];
+
+ while (i && nfreeids)
+ {
+ struct idspec *next_i = i->next;
+
+ if (!i->references
+ && mapped_time->seconds - i->lastuse > ID_KEEP_TIMEOUT)
+ {
+ nfreeids--;
+ *i->prevp = i->next;
+ if (i->next)
+ i->next->prevp = i->prevp;
+ free (i->uids);
+ free (i->gids);
+ free (i);
+ }
+ else if (!i->references && newleast > i->lastuse)
+ newleast = i->lastuse;
+
+ i = next_i;
+ }
+ }
+
+ /* If we didn't bail early, then this is valid. */
+ if (nfreeids)
+ leastidlastuse = newleast;
+ }
spin_unlock (&idhashlock);
}
@@ -235,11 +259,11 @@ static int
fh_hash (char *fhandle, struct idspec *i)
{
int hash = 0, n;
-
- for (n = 0; n < NFS_FHSIZE; n++)
+
+ for (n = 0; n < NFS2_FHSIZE; n++)
hash += fhandle[n];
- hash += (int) i >> 6;
- return hash;
+ hash += (intptr_t) i >> 6;
+ return hash % FHHASH_TABLE_SIZE;
}
int *
@@ -249,35 +273,35 @@ lookup_cache_handle (int *p, struct cache_handle **cp, struct idspec *i)
struct cache_handle *c;
fsys_t fsys;
file_t port;
-
+
hash = fh_hash ((char *)p, i);
mutex_lock (&fhhashlock);
for (c = fhhashtable[hash]; c; c = c->next)
- if (c->ids == i && ! bcmp (c->handle, p, NFS_FHSIZE))
+ if (c->ids == i && ! bcmp (c->handle, p, NFS2_FHSIZE))
{
if (c->references == 0)
nfreefh--;
c->references++;
mutex_unlock (&fhhashlock);
*cp = c;
- return p + NFS_FHSIZE / sizeof (int);
+ return p + NFS2_FHSIZE / sizeof (int);
}
-
- /* Not found */
-
- /* First four bytes are our internal table of filesystems */
+
+ /* Not found. */
+
+ /* First four bytes are our internal table of filesystems. */
fsys = lookup_filesystem (*p);
if (fsys == MACH_PORT_NULL
|| fsys_getfile (fsys, i->uids, i->nuids, i->gids, i->ngids,
- (char *)(p + 1), NFS_FHSIZE - sizeof (int), &port))
+ (char *)(p + 1), NFS2_FHSIZE - sizeof (int), &port))
{
mutex_unlock (&fhhashlock);
*cp = 0;
- return p + NFS_FHSIZE / sizeof (int);
+ return p + NFS2_FHSIZE / sizeof (int);
}
-
+
c = malloc (sizeof (struct cache_handle));
- bcopy (p, c->handle, NFS_FHSIZE);
+ memcpy (c->handle, p, NFS2_FHSIZE);
cred_ref (i);
c->ids = i;
c->port = port;
@@ -288,10 +312,10 @@ lookup_cache_handle (int *p, struct cache_handle **cp, struct idspec *i)
c->next->prevp = &c->next;
c->prevp = &fhhashtable[hash];
fhhashtable[hash] = c;
-
+
mutex_unlock (&fhhashlock);
*cp = c;
- return p + NFS_FHSIZE / sizeof (int);
+ return p + NFS2_FHSIZE / sizeof (int);
}
void
@@ -309,91 +333,131 @@ cache_handle_rele (struct cache_handle *c)
mutex_unlock (&fhhashlock);
}
-void
+void
scan_fhs ()
{
- struct cache_handle *c;
int n;
int newleast = mapped_time->seconds;
-
+
mutex_lock (&fhhashlock);
+
if (mapped_time->seconds - leastfhlastuse > FH_KEEP_TIMEOUT)
- for (n = 0; n < FHHASH_TABLE_SIZE && nfreefh; n++)
- for (c = fhhashtable[n]; c && nfreefh; c = c->next)
- if (!c->references
- && mapped_time->seconds - c->lastuse > FH_KEEP_TIMEOUT)
- {
- nfreefh--;
- *c->prevp = c->next;
- if (c->next)
- c->next->prevp = c->prevp;
- cred_rele (c->ids);
- mach_port_deallocate (mach_task_self (), c->port);
- free (c);
- }
- else
- if (!c->references && newleast > c->lastuse)
- newleast = c->lastuse;
-
- /* If we didn't bail early, then this is valid. */
- if (nfreefh)
- leastfhlastuse = newleast;
+ {
+ for (n = 0; n < FHHASH_TABLE_SIZE && nfreefh; n++)
+ {
+ struct cache_handle *c = fhhashtable[n];
+
+ while (c && nfreefh)
+ {
+ struct cache_handle *next_c = c->next;
+
+ if (!c->references
+ && mapped_time->seconds - c->lastuse > FH_KEEP_TIMEOUT)
+ {
+ nfreefh--;
+ *c->prevp = c->next;
+ if (c->next)
+ c->next->prevp = c->prevp;
+ cred_rele (c->ids);
+ mach_port_deallocate (mach_task_self (), c->port);
+ free (c);
+ }
+ else if (!c->references && newleast > c->lastuse)
+ newleast = c->lastuse;
+
+ c = next_c;
+ }
+ }
+
+ /* If we didn't bail early, then this is valid. */
+ if (nfreefh)
+ leastfhlastuse = newleast;
+ }
mutex_unlock (&fhhashlock);
}
struct cache_handle *
-create_cached_handle (int fs, struct cache_handle *credc, file_t newport)
+create_cached_handle (int fs, struct cache_handle *credc, file_t userport)
{
- char fhandle[NFS_FHSIZE];
+ char fhandle[NFS2_FHSIZE];
error_t err;
struct cache_handle *c;
int hash;
char *bp = fhandle + sizeof (int);
- size_t handlelen = NFS_FHSIZE - sizeof (int);
+ size_t handlelen = NFS2_FHSIZE - sizeof (int);
+ mach_port_t newport, ref;
+
+ /* Authenticate USERPORT so that we can call file_getfh on it. */
+ ref = mach_reply_port ();
+ /* MAKE_SEND is safe becaue we destroy REF ourselves. */
+ if (io_reauthenticate (userport, ref, MACH_MSG_TYPE_MAKE_SEND)
+ || auth_user_authenticate (authserver, ref, MACH_MSG_TYPE_MAKE_SEND,
+ &newport))
+ {
+ /* Reauthentication has failed, but maybe the filesystem will let
+ us call file_getfh anyway. */
+ newport = userport;
+ }
+ else
+ mach_port_deallocate (mach_task_self (), userport);
+ mach_port_destroy (mach_task_self (), ref);
+ /* Fetch the file handle. */
*(int *)fhandle = fs;
err = file_getfh (newport, &bp, &handlelen);
- if (err || handlelen != NFS_FHSIZE - sizeof (int))
- {
- mach_port_deallocate (mach_task_self (), newport);
- return 0;
- }
+ mach_port_deallocate (mach_task_self (), newport);
+ if (err || handlelen != NFS2_FHSIZE - sizeof (int))
+ return 0;
if (bp != fhandle + sizeof (int))
{
- bcopy (bp, fhandle + sizeof (int), NFS_FHSIZE - sizeof (int));
- vm_deallocate (mach_task_self (), (vm_address_t) bp, handlelen);
+ memcpy (fhandle + sizeof (int), bp, NFS2_FHSIZE - sizeof (int));
+ munmap (bp, handlelen);
}
-
+
+ /* Cache it. */
hash = fh_hash (fhandle, credc->ids);
mutex_lock (&fhhashlock);
for (c = fhhashtable[hash]; c; c = c->next)
- if (c->ids == credc->ids && ! bcmp (fhandle, c->handle, NFS_FHSIZE))
+ if (c->ids == credc->ids && ! bcmp (fhandle, c->handle, NFS2_FHSIZE))
{
- /* Return this one */
+ /* Return this one. */
if (c->references == 0)
nfreefh--;
c->references++;
mutex_unlock (&fhhashlock);
- mach_port_deallocate (mach_task_self (), newport);
return c;
}
-
- /* Create it anew */
+
+ /* Always call fsys_getfile so that we don't depend on the
+ particular open modes of the port passed in. */
+
+ err = fsys_getfile (lookup_filesystem (fs),
+ credc->ids->uids, credc->ids->nuids,
+ credc->ids->gids, credc->ids->ngids,
+ fhandle + sizeof (int), NFS2_FHSIZE - sizeof (int),
+ &newport);
+ if (err)
+ {
+ mutex_unlock (&fhhashlock);
+ return 0;
+ }
+
+ /* Create it anew. */
c = malloc (sizeof (struct cache_handle));
- bcopy (fhandle, c->handle, NFS_FHSIZE);
+ memcpy (c->handle, fhandle, NFS2_FHSIZE);
cred_ref (credc->ids);
c->ids = credc->ids;
c->port = newport;
c->references = 1;
-
- /* And add it to the hash table */
+
+ /* And add it to the hash table. */
c->next = fhhashtable[hash];
if (c->next)
c->next->prevp = &c->next;
c->prevp = &fhhashtable[hash];
fhhashtable[hash] = c;
mutex_unlock (&fhhashlock);
-
+
return c;
}
@@ -406,19 +470,19 @@ static int leastreplylastuse;
/* Check the list of cached replies to see if this is a replay of a
previous transaction; if so, return the cache record. Otherwise,
- create a new cache record. */
+ create a new cache record. */
struct cached_reply *
-check_cached_replies (int xid,
+check_cached_replies (int xid,
struct sockaddr_in *sender)
{
struct cached_reply *cr;
int hash;
- hash = xid % REPLYHASH_TABLE_SIZE;
-
+ hash = abs(xid % REPLYHASH_TABLE_SIZE);
+
spin_lock (&replycachelock);
for (cr = replyhashtable[hash]; cr; cr = cr->next)
- if (cr->xid == xid
+ if (cr->xid == xid
&& !bcmp (sender, &cr->source, sizeof (struct sockaddr_in)))
{
cr->references++;
@@ -432,9 +496,10 @@ check_cached_replies (int xid,
cr = malloc (sizeof (struct cached_reply));
mutex_init (&cr->lock);
mutex_lock (&cr->lock);
- bcopy (sender, &cr->source, sizeof (struct sockaddr_in));
+ memcpy (&cr->source, sender, sizeof (struct sockaddr_in));
cr->xid = xid;
cr->data = 0;
+ cr->references = 1;
cr->next = replyhashtable[hash];
if (replyhashtable[hash])
@@ -447,7 +512,7 @@ check_cached_replies (int xid,
}
/* A cached reply returned by check_cached_replies is now no longer
- needed by its caller. */
+ needed by its caller. */
void
release_cached_reply (struct cached_reply *cr)
{
@@ -467,30 +532,42 @@ release_cached_reply (struct cached_reply *cr)
void
scan_replies ()
{
- struct cached_reply *cr;
int n;
int newleast = mapped_time->seconds;
-
+
spin_lock (&replycachelock);
+
if (mapped_time->seconds - leastreplylastuse > REPLY_KEEP_TIMEOUT)
- for (n = 0; n < REPLYHASH_TABLE_SIZE && nfreereplies; n++)
- for (cr = replyhashtable[n]; cr && nfreereplies; cr = cr->next)
- if (!cr->references
- && mapped_time->seconds - cr->lastuse > REPLY_KEEP_TIMEOUT)
- {
- nfreereplies--;
- *cr->prevp = cr->next;
- if (cr->next)
- cr->next->prevp = cr->prevp;
- if (cr->data)
- free (cr->data);
- }
- else
- if (!cr->references && newleast > cr->lastuse)
- newleast = cr->lastuse;
-
- /* If we didn't bail early, then this is valid */
- if (nfreereplies)
- leastreplylastuse = newleast;
+ {
+ for (n = 0; n < REPLYHASH_TABLE_SIZE && nfreereplies; n++)
+ {
+ struct cached_reply *cr = replyhashtable[n];
+
+ while (cr && nfreereplies)
+ {
+ struct cached_reply *next_cr = cr->next;
+
+ if (!cr->references
+ && mapped_time->seconds - cr->lastuse > REPLY_KEEP_TIMEOUT)
+ {
+ nfreereplies--;
+ *cr->prevp = cr->next;
+ if (cr->next)
+ cr->next->prevp = cr->prevp;
+ if (cr->data)
+ free (cr->data);
+ free (cr);
+ }
+ else if (!cr->references && newleast > cr->lastuse)
+ newleast = cr->lastuse;
+
+ cr = next_cr;
+ }
+ }
+
+ /* If we didn't bail early, then this is valid. */
+ if (nfreereplies)
+ leastreplylastuse = newleast;
+ }
spin_unlock (&replycachelock);
}
diff --git a/nfsd/fsys.c b/nfsd/fsys.c
index d3c50220..7b15d150 100644
--- a/nfsd/fsys.c
+++ b/nfsd/fsys.c
@@ -1,5 +1,5 @@
/* Filesystem management for NFS server
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 2002 Free Software Foundation, Inc.
Written by Michael I. Bushnell, p/BSG.
This file is part of the GNU Hurd.
@@ -20,13 +20,14 @@
#include <stdio.h>
#include <errno.h>
+#include <error.h>
#include <hurd.h>
#include <fcntl.h>
#include <string.h>
#include "nfsd.h"
-struct fsys_spec
+struct fsys_spec
{
fsys_t fsys;
char *name;
@@ -49,18 +50,23 @@ init_filesystems (void)
int line;
file_t root;
static FILE *index_file;
+ int i;
fsystable = (struct fsys_spec *) malloc ((fsystablesize = 10)
* sizeof (struct fsys_spec));
+ for (i = 0; i < fsystablesize; i++)
+ {
+ fsystable[i].fsys = MACH_PORT_NULL;
+ fsystable[i].name = 0;
+ }
if (!index_file_name)
return;
-
+
index_file = fopen (index_file_name, "r");
if (!index_file)
{
- fprintf (stderr, "%s: Cannot open `%s': %s\n",
- program_invocation_name, index_file_name, strerror (errno));
+ error (0, errno, "Cannot open `%s'", index_file_name);
return;
}
@@ -72,33 +78,39 @@ init_filesystems (void)
fclose (index_file);
return;
}
-
+
if (nitems != 2)
{
- fprintf (stderr, "%s:%s:%d Bad syntax\n",
- program_invocation_name, index_file_name, line);
+ error (0, 0, "%s:%d Bad syntax", index_file_name, line);
continue;
}
root = file_name_lookup (name, 0, 0);
- if (!root)
+ if (root == MACH_PORT_NULL)
{
- fprintf (stderr, "%s:%s:%d Filesystem `%s': %s\n",
- program_invocation_name, index_file_name, line,
- name, strerror (errno));
+ error (0, errno, "%s:%d Filesystem `%s'",
+ index_file_name, line, name);
free (name);
continue;
}
if (index >= fsystablesize)
- fsystable = (struct fsys_spec *) realloc (fsystable,
- (fsystablesize = index * 2)
- * sizeof (struct fsys_spec));
- if (index > nfsys)
- nfsys = index;
-
+ {
+ fsystable = (struct fsys_spec *)
+ realloc (fsystable, index * 2 * sizeof (struct fsys_spec));
+ for (i = fsystablesize; i < index * 2; i++)
+ {
+ fsystable[i].fsys = MACH_PORT_NULL;
+ fsystable[i].name = 0;
+ }
+ fsystablesize = index * 2;
+ }
+
+ if (index + 1 > nfsys)
+ nfsys = index + 1;
+
fsystable[index].name = name;
- file_getcontrol (root, &fsystable[nfsys].fsys);
+ file_getcontrol (root, &fsystable[index].fsys);
mach_port_deallocate (mach_task_self (), root);
}
}
@@ -109,46 +121,44 @@ write_filesystems (void)
{
file_t newindex;
FILE *f;
+ error_t err;
int i;
if (!index_file_name)
return;
-
+
if (index_file_dir == MACH_PORT_NULL)
{
index_file_dir = file_name_split (index_file_name, &index_file_compname);
if (index_file_dir == MACH_PORT_NULL)
{
- fprintf (stderr, "%s: `%s': %s\n",
- program_invocation_name, index_file_name, strerror (errno));
+ error (0, errno, "`%s'", index_file_name);
index_file_name = 0;
return;
}
}
/* Create an anonymous file in the same directory */
- errno = dir_mkfile (index_file_dir, O_WRONLY, 0666, &newindex);
- if (errno)
+ err = dir_mkfile (index_file_dir, O_WRONLY, 0666, &newindex);
+ if (err)
{
- fprintf (stderr, "%s: `%s': %s\n",
- program_invocation_name, index_file_name, strerror (errno));
+ error (0, err, "`%s'", index_file_name);
index_file_name = 0;
mach_port_deallocate (mach_task_self (), index_file_dir);
index_file_dir = MACH_PORT_NULL;
return;
}
-
+
f = fopenport (newindex, "w");
-
+
for (i = 0; i < nfsys; i++)
if (fsystable[i].name)
fprintf (f, "%d %s\n", i, fsystable[i].name);
/* Link it in */
- errno = dir_link (index_file_dir, newindex, index_file_compname, 0);
- if (errno)
- fprintf (stderr, "%s: `%s': %s\n",
- program_invocation_name, index_file_name, strerror (errno));
+ err = dir_link (index_file_dir, newindex, index_file_compname, 0);
+ if (err)
+ error (0, err, "`%s'", index_file_name);
fflush (f);
file_sync (newindex, 1, 0);
fclose (f);
@@ -174,11 +184,19 @@ enter_filesystem (char *name, file_t root)
for (i = 0; i < nfsys; i++)
if (fsystable[i].name && !strcmp (fsystable[i].name, name))
return i;
-
+
if (nfsys == fsystablesize)
- fsystable = (struct fsys_spec *) realloc (fsystable,
- (fsystablesize *= 2)
- * sizeof (struct fsys_spec));
+ {
+ fsystable = (struct fsys_spec *) realloc (fsystable,
+ (fsystablesize * 2)
+ * sizeof (struct fsys_spec));
+ for (i = fsystablesize; i < fsystablesize * 2; i++)
+ {
+ fsystable[i].fsys = MACH_PORT_NULL;
+ fsystable[i].name = 0;
+ }
+ fsystablesize *= 2;
+ }
fsystable[nfsys].name = malloc (strlen (name) + 1);
strcpy (fsystable[nfsys].name, name);
@@ -189,4 +207,3 @@ enter_filesystem (char *name, file_t root)
return nfsys - 1;
}
-
diff --git a/nfsd/loop.c b/nfsd/loop.c
index 3520e1da..bfec5e5a 100644
--- a/nfsd/loop.c
+++ b/nfsd/loop.c
@@ -1,5 +1,5 @@
-/*
- Copyright (C) 1996 Free Software Foundation, Inc.
+/* loop.c - Main server loop for nfs server.
+ Copyright (C) 1996,98,2002,2006 Free Software Foundation, Inc.
Written by Michael I. Bushnell, p/BSG.
This file is part of the GNU Hurd.
@@ -24,7 +24,7 @@
#include "nfsd.h"
#include <rpc/pmap_prot.h>
-#include "../nfs/rpcsvc/mount.h"
+#include "../nfs/mount.h"
#undef TRUE
#undef FALSE
@@ -36,7 +36,7 @@
#undef malloc
void
-server_loop ()
+server_loop (int fd)
{
char buf[MAXIOSIZE];
int xid;
@@ -52,182 +52,172 @@ server_loop ()
struct idspec *cred;
struct cache_handle *c, fakec;
error_t err;
- size_t addrlen;
- fd_set readfds;
- int maxfd;
- int i;
- int *errloc;
-
- bzero (&fakec, sizeof (struct cache_handle));
-
- if (main_udp_socket > pmap_udp_socket)
- maxfd = main_udp_socket;
- else
- maxfd = pmap_udp_socket;
-
+ socklen_t addrlen;
+ int cc;
+
+ memset (&fakec, 0, sizeof (struct cache_handle));
+
for (;;)
{
- FD_ZERO (&readfds);
- FD_SET (main_udp_socket, &readfds);
- FD_SET (pmap_udp_socket, &readfds);
- select (maxfd, &readfds, 0, 0, 0);
-
- for (i = main_udp_socket;
- i != -1;
- i = (i == main_udp_socket ? pmap_udp_socket : -1))
+ p = (int *) buf;
+ proc = 0;
+ addrlen = sizeof (struct sockaddr_in);
+ cc = recvfrom (fd, buf, MAXIOSIZE, 0, &sender, &addrlen);
+ if (cc == -1)
+ continue; /* Ignore errors. */
+ xid = *(p++);
+
+ /* Ignore things that aren't proper RPCs. */
+ if (ntohl (*p) != CALL)
+ continue;
+ p++;
+
+ cr = check_cached_replies (xid, &sender);
+ if (cr->data)
+ /* This transacation has already completed. */
+ goto repost_reply;
+
+ r = (int *) (rbuf = malloc (MAXIOSIZE));
+
+ if (ntohl (*p) != RPC_MSG_VERSION)
{
- if (!FD_ISSET (i, &readfds))
- continue;
-
- p = (int *) buf;
- proc = 0;
- addrlen = sizeof (struct sockaddr_in);
- recvfrom (i, buf, MAXIOSIZE, 0, &sender, &addrlen);
- xid = *p++;
-
- /* Ignore things that aren't proper RPCs. */
- if (ntohl (*p++) != CALL)
- continue;
-
- cr = check_cached_replies (xid, &sender);
- if (cr->data)
- /* This transacation has already completed */
- goto repost_reply;
-
- r = (int *) rbuf = malloc (MAXIOSIZE);
-
- if (ntohl (*p++) != RPC_MSG_VERSION)
- {
- /* Reject RPC */
- *r++ = xid;
- *r++ = htonl (REPLY);
- *r++ = htonl (MSG_DENIED);
- *r++ = htonl (RPC_MISMATCH);
- *r++ = htonl (RPC_MSG_VERSION);
- *r++ = htonl (RPC_MSG_VERSION);
- goto send_reply;
- }
-
- program = ntohl (*p++);
- switch (program)
- {
- case MOUNTPROG:
- version = MOUNTVERS;
- table = &mounttable;
- break;
-
- case NFS_PROGRAM:
- version = NFS_VERSION;
- table = &nfstable;
- break;
-
- case PMAPPROG:
- version = PMAPVERS;
- table = &pmaptable;
- break;
-
- default:
- /* Program unavailable */
- *r++ = xid;
- *r++ = htonl (REPLY);
- *r++ = htonl (MSG_ACCEPTED);
- *r++ = htonl (AUTH_NULL);
- *r++ = htonl (0);
- *r++ = htonl (PROG_UNAVAIL);
- goto send_reply;
- }
-
- if (ntohl (*p++) != version)
- {
- /* Program mismatch */
- *r++ = xid;
- *r++ = htonl (REPLY);
- *r++ = htonl (MSG_ACCEPTED);
- *r++ = htonl (AUTH_NULL);
- *r++ = htonl (0);
- *r++ = htonl (PROG_MISMATCH);
- *r++ = htonl (version);
- *r++ = htonl (version);
- goto send_reply;
- }
-
- procedure = htonl (*p++);
- if (procedure < table->min
- || procedure > table->max
- || table->procs[procedure - table->min].func == 0)
- {
- /* Procedure unavailable */
- *r++ = xid;
- *r++ = htonl (REPLY);
- *r++ = htonl (MSG_ACCEPTED);
- *r++ = htonl (AUTH_NULL);
- *r++ = htonl (0);
- *r++ = htonl (PROC_UNAVAIL);
- *r++ = htonl (table->min);
- *r++ = htonl (table->max);
- goto send_reply;
- }
- proc = &table->procs[procedure - table->min];
-
- p = process_cred (p, &cred); /* auth */
- p = skip_cred (p); /* verf */
-
- if (proc->need_handle)
- p = lookup_cache_handle (p, &c, cred);
- else
- {
- fakec.ids = cred;
- c = &fakec;
- }
-
- if (proc->alloc_reply)
- {
- size_t amt;
- amt = (*proc->alloc_reply) (p) + 256;
- if (amt > MAXIOSIZE)
- {
- free (rbuf);
- r = (int *) rbuf = malloc (amt);
- }
- }
+ /* Reject RPC. */
+ *(r++) = xid;
+ *(r++) = htonl (REPLY);
+ *(r++) = htonl (MSG_DENIED);
+ *(r++) = htonl (RPC_MISMATCH);
+ *(r++) = htonl (RPC_MSG_VERSION);
+ *(r++) = htonl (RPC_MSG_VERSION);
+ goto send_reply;
+ }
+ p++;
+
+ program = ntohl (*p);
+ p++;
+ switch (program)
+ {
+ case MOUNTPROG:
+ version = MOUNTVERS;
+ table = &mounttable;
+ break;
+
+ case NFS_PROGRAM:
+ version = NFS_VERSION;
+ table = &nfs2table;
+ break;
+
+ case PMAPPROG:
+ version = PMAPVERS;
+ table = &pmaptable;
+ break;
+
+ default:
+ /* Program unavailable. */
+ *(r++) = xid;
+ *(r++) = htonl (REPLY);
+ *(r++) = htonl (MSG_ACCEPTED);
+ *(r++) = htonl (AUTH_NULL);
+ *(r++) = htonl (0);
+ *(r++) = htonl (PROG_UNAVAIL);
+ goto send_reply;
+ }
- /* Fill in beginning of reply */
- *r++ = xid;
- *r++ = htonl (REPLY);
- *r++ = htonl (MSG_ACCEPTED);
- *r++ = htonl (AUTH_NULL);
- *r++ = htonl (0);
- *r++ = htonl (SUCCESS);
- if (proc->process_error)
+ if (ntohl (*p) != version)
+ {
+ /* Program mismatch. */
+ *(r++) = xid;
+ *(r++) = htonl (REPLY);
+ *(r++) = htonl (MSG_ACCEPTED);
+ *(r++) = htonl (AUTH_NULL);
+ *(r++) = htonl (0);
+ *(r++) = htonl (PROG_MISMATCH);
+ *(r++) = htonl (version);
+ *(r++) = htonl (version);
+ goto send_reply;
+ }
+ p++;
+
+ procedure = htonl (*p);
+ p++;
+ if (procedure < table->min
+ || procedure > table->max
+ || table->procs[procedure - table->min].func == 0)
+ {
+ /* Procedure unavailable. */
+ *(r++) = xid;
+ *(r++) = htonl (REPLY);
+ *(r++) = htonl (MSG_ACCEPTED);
+ *(r++) = htonl (AUTH_NULL);
+ *(r++) = htonl (0);
+ *(r++) = htonl (PROC_UNAVAIL);
+ *(r++) = htonl (table->min);
+ *(r++) = htonl (table->max);
+ goto send_reply;
+ }
+ proc = &table->procs[procedure - table->min];
+
+ p = process_cred (p, &cred);
+
+ if (proc->need_handle)
+ p = lookup_cache_handle (p, &c, cred);
+ else
+ {
+ fakec.ids = cred;
+ c = &fakec;
+ }
+
+ if (proc->alloc_reply)
+ {
+ size_t amt;
+ amt = (*proc->alloc_reply) (p, version) + 256;
+ if (amt > MAXIOSIZE)
{
- /* Assume success for now and patch it later if necessary */
- errloc = r;
- *r++ = htonl (0);
+ free (rbuf);
+ r = (int *) (rbuf = malloc (amt));
}
+ }
+ /* Fill in beginning of reply. */
+ *(r++) = xid;
+ *(r++) = htonl (REPLY);
+ *(r++) = htonl (MSG_ACCEPTED);
+ *(r++) = htonl (AUTH_NULL);
+ *(r++) = htonl (0);
+ *(r++) = htonl (SUCCESS);
+ if (!proc->process_error)
+ /* The function does its own error processing, and we ignore
+ its return value. */
+ (void) (*proc->func) (c, p, &r, version);
+ else
+ {
if (c)
- err = (*proc->func) (c, p, &r);
- else
- err = ESTALE;
-
- if (proc->process_error && err)
{
- r = errloc;
- *r++ = htonl (nfs_error_trans (err));
+ /* Assume success for now and patch it later if necessary. */
+ int *errloc = r;
+ *(r++) = htonl (0);
+ /* Call processing function, its output after error code. */
+ err = (*proc->func) (c, p, &r, version);
+ if (err)
+ {
+ r = errloc; /* Back up, patch error code, discard rest. */
+ *(r++) = htonl (nfs_error_trans (err, version));
+ }
}
+ else
+ *(r++) = htonl (nfs_error_trans (ESTALE, version));
+ }
- cred_rele (cred);
- if (c != &fakec)
- cache_handle_rele (c);
+ cred_rele (cred);
+ if (c && c != &fakec)
+ cache_handle_rele (c);
- send_reply:
- cr->data = rbuf;
- cr->len = (char *)r - rbuf;
+ send_reply:
+ cr->data = rbuf;
+ cr->len = (char *)r - rbuf;
- repost_reply:
- sendto (i, cr->data, cr->len, 0,
- (struct sockaddr *)&sender, addrlen);
- release_cached_reply (cr);
- }
+ repost_reply:
+ sendto (fd, cr->data, cr->len, 0,
+ (struct sockaddr *) &sender, addrlen);
+ release_cached_reply (cr);
}
}
diff --git a/nfsd/main.c b/nfsd/main.c
index 69099361..ee071090 100644
--- a/nfsd/main.c
+++ b/nfsd/main.c
@@ -1,5 +1,5 @@
/* Main NFS server program
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 2002 Free Software Foundation, Inc.
Written by Michael I. Bushnell, p/BSG.
This file is part of the GNU Hurd.
@@ -23,16 +23,20 @@
#include <unistd.h>
#include <rpc/pmap_prot.h>
#include <maptime.h>
+#include <hurd.h>
+#include <error.h>
int main_udp_socket, pmap_udp_socket;
struct sockaddr_in main_address, pmap_address;
-char *index_file_name;
+static char index_file[] = LOCALSTATEDIR "/state/misc/nfsd.index";
+char *index_file_name = index_file;
int
main (int argc, char **argv)
{
int nthreads;
-
+ int fail;
+
if (argc > 2)
{
fprintf (stderr, "%s [num-threads]\n", argv[0]);
@@ -44,9 +48,8 @@ main (int argc, char **argv)
nthreads = atoi (argv[1]);
if (!nthreads)
nthreads = 4;
-
- index_file_name = asprintf ("%s/state/misc/nfsd.index", LOCALSTATEDIR);
+ authserver = getauth ();
maptime_map (0, 0, &mapped_time);
main_address.sin_family = AF_INET;
@@ -58,16 +61,25 @@ main (int argc, char **argv)
main_udp_socket = socket (PF_INET, SOCK_DGRAM, 0);
pmap_udp_socket = socket (PF_INET, SOCK_DGRAM, 0);
- bind (main_udp_socket, (struct sockaddr *)&main_address,
- sizeof (struct sockaddr_in));
- bind (pmap_udp_socket, (struct sockaddr *)&pmap_address,
- sizeof (struct sockaddr_in));
+ fail = bind (main_udp_socket, (struct sockaddr *)&main_address,
+ sizeof (struct sockaddr_in));
+ if (fail)
+ error (1, errno, "Binding NFS socket");
+
+ fail = bind (pmap_udp_socket, (struct sockaddr *)&pmap_address,
+ sizeof (struct sockaddr_in));
+ if (fail)
+ error (1, errno, "Binding PMAP socket");
init_filesystems ();
+ cthread_detach (cthread_fork ((cthread_fn_t) server_loop,
+ (any_t)(intptr_t) pmap_udp_socket));
+
while (nthreads--)
- cthread_detach (cthread_fork ((cthread_fn_t) server_loop, 0));
-
+ cthread_detach (cthread_fork ((cthread_fn_t) server_loop,
+ (any_t)(intptr_t) main_udp_socket));
+
for (;;)
{
sleep (1);
diff --git a/nfsd/nfsd.h b/nfsd/nfsd.h
index 7b6f530d..e89a411b 100644
--- a/nfsd/nfsd.h
+++ b/nfsd/nfsd.h
@@ -1,5 +1,5 @@
-/*
- Copyright (C) 1996 Free Software Foundation, Inc.
+/*
+ Copyright (C) 1996,98,2002 Free Software Foundation, Inc.
Written by Michael I. Bushnell, p/BSG.
This file is part of the GNU Hurd.
@@ -18,14 +18,13 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
-typedef int bool_t;
-
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>
#include <cthreads.h>
-#include "../nfs/rpcsvc/nfs_prot.h" /* XXX */
+#include <rpc/types.h>
+#include "../nfs/nfs-spec.h" /* XXX */
#include <hurd/fs.h>
/* These should be configuration options */
@@ -34,7 +33,7 @@ typedef int bool_t;
#define REPLY_KEEP_TIMEOUT 120 /* two minutes */
#define MAXIOSIZE 10240
-struct idspec
+struct idspec
{
struct idspec *next, **prevp;
int nuids, ngids;
@@ -46,7 +45,7 @@ struct idspec
struct cache_handle
{
struct cache_handle *next, **prevp;
- char handle[NFS_FHSIZE];
+ char handle[NFS2_FHSIZE];
struct idspec *ids;
file_t port;
time_t lastuse;
@@ -67,17 +66,17 @@ struct cached_reply
struct procedure
{
- error_t (*func) (struct cache_handle *, int *, int **);
- size_t (*alloc_reply) (int *);
+ error_t (*func) (struct cache_handle *, int *, int **, int);
+ size_t (*alloc_reply) (int *, int);
int need_handle;
int process_error;
};
-struct proctable
+struct proctable
{
int min;
int max;
- struct procedure procs[0];
+ struct procedure procs[];
};
volatile struct mapped_time_value *mapped_time;
@@ -92,6 +91,9 @@ extern struct sockaddr_in main_address, pmap_address;
/* Name of the file on disk containing the filesystem index table */
extern char *index_file_name;
+/* Our auth server */
+auth_t authserver;
+
/* cache.c */
int *process_cred (int *, struct idspec **);
@@ -107,15 +109,14 @@ void release_cached_reply (struct cached_reply *cr);
void scan_replies (void);
/* loop.c */
-void server_loop (void);
+void server_loop (int);
/* ops.c */
-extern struct proctable nfstable, mounttable, pmaptable;
+extern struct proctable nfs2table, mounttable, pmaptable;
/* xdr.c */
-int *skip_cred (int *);
-int nfs_error_trans (error_t);
-int *encode_fattr (int *, struct stat *);
+int nfs_error_trans (error_t, int);
+int *encode_fattr (int *, struct stat *, int version);
int *decode_name (int *, char **);
int *encode_fhandle (int *, char *);
int *encode_string (int *, char *);
diff --git a/nfsd/ops.c b/nfsd/ops.c
index 93c8373c..d503290e 100644
--- a/nfsd/ops.c
+++ b/nfsd/ops.c
@@ -1,5 +1,7 @@
-/* NFS daemon protocol operations
- Copyright (C) 1996 Free Software Foundation, Inc.
+/* ops.c NFS daemon protocol operations.
+
+ Copyright (C) 1996, 2001, 2002, 2007 Free Software Foundation, Inc.
+
Written by Michael I. Bushnell, p/BSG.
This file is part of the GNU Hurd.
@@ -24,15 +26,18 @@
#include <hurd/paths.h>
#include <hurd.h>
#include <dirent.h>
+#include <string.h>
+#include <sys/mman.h>
#include "nfsd.h"
-#include "../nfs/rpcsvc/mount.h" /* XXX */
+#include "../nfs/mount.h" /* XXX */
#include <rpc/pmap_prot.h>
static error_t
op_null (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
return 0;
}
@@ -40,14 +45,15 @@ op_null (struct cache_handle *c,
static error_t
op_getattr (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
struct stat st;
error_t err;
-
+
err = io_stat (c->port, &st);
if (!err)
- *reply = encode_fattr (*reply, &st);
+ *reply = encode_fattr (*reply, &st, version);
return err;
}
@@ -65,74 +71,89 @@ complete_setattr (mach_port_t port,
if (err)
return err;
- uid = ntohl (*p++);
- gid = ntohl (*p++);
- if ((uid != -1 && uid != st.st_uid)
- || (gid != -1 && gid != st.st_gid))
- {
- if (uid == -1)
- uid = st.st_uid;
- if (gid == -1)
- gid = st.st_gid;
- err = file_chown (port, uid, gid);
- if (err)
- return err;
- }
-
- size = ntohl (*p++);
+ uid = ntohl (*p);
+ p++;
+ gid = ntohl (*p);
+ p++;
+ if (uid == -1)
+ uid = st.st_uid;
+ if (gid == -1)
+ gid = st.st_gid;
+ if (uid != st.st_uid || gid != st.st_gid)
+ err = file_chown (port, uid, gid);
+ if (err)
+ return err;
+
+ size = ntohl (*p);
+ p++;
if (size != -1 && size != st.st_size)
err = file_set_size (port, size);
if (err)
return err;
-
- atime.seconds = ntohl (*p++);
- atime.microseconds = ntohl (*p++);
- mtime.seconds = ntohl (*p++);
- mtime.microseconds = ntohl (*p++);
+
+ atime.seconds = ntohl (*p);
+ p++;
+ atime.microseconds = ntohl (*p);
+ p++;
+ mtime.seconds = ntohl (*p);
+ p++;
+ mtime.microseconds = ntohl (*p);
+ p++;
+
if (atime.seconds != -1 && atime.microseconds == -1)
atime.microseconds = 0;
if (mtime.seconds != -1 && mtime.microseconds == -1)
mtime.microseconds = 0;
- if (atime.seconds != -1 || mtime.seconds != -1
- || atime.microseconds != -1 || mtime.microseconds != -1)
- {
- if (atime.seconds == -1)
- atime.seconds = st.st_atime;
- if (atime.microseconds == -1)
- atime.microseconds = st.st_atime_usec;
- if (mtime.seconds == -1)
- mtime.seconds = st.st_mtime;
- if (mtime.microseconds == -1)
- mtime.microseconds = st.st_mtime_usec;
- err = file_utimes (port, atime, mtime);
- if (err)
- return err;
- }
-
- return 0;
+
+ if (atime.seconds == -1)
+ atime.seconds = st.st_atim.tv_sec;
+ if (atime.microseconds == -1)
+ atime.microseconds = st.st_atim.tv_nsec / 1000;
+ if (mtime.seconds == -1)
+ mtime.seconds = st.st_mtim.tv_sec;
+ if (mtime.microseconds == -1)
+ mtime.microseconds = st.st_mtim.tv_nsec / 1000;
+
+ if (atime.seconds != st.st_atim.tv_sec
+ || atime.microseconds != st.st_atim.tv_nsec / 1000
+ || mtime.seconds != st.st_mtim.tv_sec
+ || mtime.microseconds != st.st_mtim.tv_nsec / 1000)
+ err = file_utimes (port, atime, mtime);
+
+ return err;
}
static error_t
op_setattr (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
error_t err = 0;
mode_t mode;
+ struct stat st;
- mode = ntohl (*p++);
+ mode = ntohl (*p);
+ p++;
if (mode != -1)
err = file_chmod (c->port, mode);
+
+ if (!err)
+ err = complete_setattr (c->port, p);
+ if (!err)
+ err = io_stat (c->port, &st);
if (err)
return err;
-
- return complete_setattr (c->port, p);
+
+ *reply = encode_fattr (*reply, &st, version);
+ return 0;
}
static error_t
op_lookup (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
error_t err;
char *name;
@@ -143,65 +164,76 @@ op_lookup (struct cache_handle *c,
struct stat st;
decode_name (p, &name);
-
+
err = dir_lookup (c->port, name, O_NOTRANS, 0, &do_retry, retry_name,
&newport);
free (name);
- /* Block attempts to bounce out of this filesystem by any technique */
+ /* Block attempts to bounce out of this filesystem by any technique. */
if (!err
&& (do_retry != FS_RETRY_NORMAL
|| retry_name[0] != '\0'))
err = EACCES;
-
+
if (!err)
err = io_stat (newport, &st);
-
+
if (err)
return err;
-
+
newc = create_cached_handle (*(int *)c->handle, c, newport);
if (!newc)
return ESTALE;
*reply = encode_fhandle (*reply, newc->handle);
- *reply = encode_fattr (*reply, &st);
+ *reply = encode_fattr (*reply, &st, version);
return 0;
}
static error_t
op_readlink (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
char buf[2048], *transp = buf;
mach_msg_type_number_t len = sizeof (buf);
error_t err;
-
- /* Shamelessly copied from the libc readlink */
+
+ /* Shamelessly copied from the libc readlink. */
err = file_get_translator (c->port, &transp, &len);
if (err)
- return err;
-
+ {
+ if (transp != buf)
+ munmap (transp, len);
+ return err;
+ }
+
if (len < sizeof (_HURD_SYMLINK)
|| memcmp (transp, _HURD_SYMLINK, sizeof (_HURD_SYMLINK)))
return EINVAL;
-
+
transp += sizeof (_HURD_SYMLINK);
-
+
*reply = encode_string (*reply, transp);
+
+ if (transp != buf)
+ munmap (transp, len);
+
return 0;
}
static size_t
-count_read_buffersize (int *p)
+count_read_buffersize (int *p, int version)
{
- return ntohl (*++p); /* skip OFFSET, return COUNT */
+ p++; /* Skip OFFSET. */
+ return ntohl (*p); /* Return COUNT. */
}
static error_t
op_read (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
off_t offset;
size_t count;
@@ -210,26 +242,37 @@ op_read (struct cache_handle *c,
struct stat st;
error_t err;
- offset = ntohl (*p++);
- count = ntohl (*p++);
-
+ offset = ntohl (*p);
+ p++;
+ count = ntohl (*p);
+ p++;
+
err = io_read (c->port, &bp, &buflen, offset, count);
if (err)
- return err;
-
+ {
+ if (bp != buf)
+ munmap (bp, buflen);
+ return err;
+ }
+
err = io_stat (c->port, &st);
if (err)
return err;
-
- *reply = encode_fattr (*reply, &st);
+
+ *reply = encode_fattr (*reply, &st, version);
*reply = encode_data (*reply, bp, buflen);
+
+ if (bp != buf)
+ munmap (bp, buflen);
+
return 0;
}
static error_t
op_write (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
off_t offset;
size_t count;
@@ -239,11 +282,13 @@ op_write (struct cache_handle *c,
struct stat st;
p++;
- offset = ntohl (*p++);
+ offset = ntohl (*p);
+ p++;
+ p++;
+ count = ntohl (*p);
p++;
- count = ntohl (*p++);
bp = (char *) *reply;
-
+
while (count)
{
err = io_write (c->port, bp, count, offset, &amt);
@@ -255,20 +300,21 @@ op_write (struct cache_handle *c,
bp += amt;
offset += amt;
}
-
+
file_sync (c->port, 1, 0);
err = io_stat (c->port, &st);
if (err)
return err;
- *reply = encode_fattr (*reply, &st);
+ *reply = encode_fattr (*reply, &st, version);
return 0;
}
static error_t
op_create (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
error_t err;
char *name;
@@ -278,26 +324,51 @@ op_create (struct cache_handle *c,
struct cache_handle *newc;
struct stat st;
mode_t mode;
+ int statchanged = 0;
+ off_t size;
p = decode_name (p, &name);
- mode = ntohl (*p++);
-
- err = dir_lookup (c->port, name, O_NOTRANS | O_CREAT | O_EXCL, mode,
+ mode = ntohl (*p);
+ p++;
+
+ err = dir_lookup (c->port, name, O_NOTRANS | O_CREAT | O_TRUNC, mode,
&do_retry, retry_name, &newport);
if (!err
&& (do_retry != FS_RETRY_NORMAL
|| retry_name[0] != '\0'))
err = EACCES;
-
+
if (err)
return err;
- err = complete_setattr (newport, p);
if (!err)
err = io_stat (newport, &st);
+ if (err)
+ goto errout;
+
+ /* NetBSD ignores most of the setattr fields given; that's good enough
+ for me too. */
+
+ p++, p++; /* Skip uid and gid. */
+
+ size = ntohl (*p);
+ p++;
+ if (size != -1 && size != st.st_size)
+ {
+ err = file_set_size (newport, size);
+ statchanged = 1;
+ }
+ if (err)
+ goto errout;
+
+ /* Ignore times. */
+
+ if (statchanged)
+ err = io_stat (newport, &st);
if (err)
{
+ errout:
dir_unlink (c->port, name);
free (name);
return err;
@@ -307,41 +378,43 @@ op_create (struct cache_handle *c,
newc = create_cached_handle (*(int *)c->handle, c, newport);
if (!newc)
return ESTALE;
-
+
*reply = encode_fhandle (*reply, newc->handle);
- *reply = encode_fattr (*reply, &st);
+ *reply = encode_fattr (*reply, &st, version);
return 0;
}
static error_t
op_remove (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
error_t err;
char *name;
-
+
decode_name (p, &name);
-
+
err = dir_unlink (c->port, name);
free (name);
-
+
return 0;
}
static error_t
op_rename (struct cache_handle *fromc,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
struct cache_handle *toc;
char *fromname, *toname;
error_t err = 0;
-
+
p = decode_name (p, &fromname);
p = lookup_cache_handle (p, &toc, fromc->ids);
decode_name (p, &toname);
-
+
if (!toc)
err = ESTALE;
if (!err)
@@ -354,20 +427,21 @@ op_rename (struct cache_handle *fromc,
static error_t
op_link (struct cache_handle *filec,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
struct cache_handle *dirc;
char *name;
error_t err = 0;
-
+
p = lookup_cache_handle (p, &dirc, filec->ids);
decode_name (p, &name);
-
+
if (!dirc)
err = ESTALE;
if (!err)
err = dir_link (dirc->port, filec->port, name, 1);
-
+
free (name);
return err;
}
@@ -375,7 +449,8 @@ op_link (struct cache_handle *filec,
static error_t
op_symlink (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
char *name, *target;
error_t err;
@@ -386,7 +461,8 @@ op_symlink (struct cache_handle *c,
p = decode_name (p, &name);
p = decode_name (p, &target);
- mode = ntohl (*p++);
+ mode = ntohl (*p);
+ p++;
if (mode == -1)
mode = 0777;
@@ -416,7 +492,8 @@ op_symlink (struct cache_handle *c,
static error_t
op_mkdir (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
char *name;
mode_t mode;
@@ -428,8 +505,9 @@ op_mkdir (struct cache_handle *c,
error_t err;
p = decode_name (p, &name);
- mode = ntohl (*p++);
-
+ mode = ntohl (*p);
+ p++;
+
err = dir_mkdir (c->port, name, mode);
if (err)
@@ -437,7 +515,7 @@ op_mkdir (struct cache_handle *c,
free (name);
return err;
}
-
+
err = dir_lookup (c->port, name, O_NOTRANS, 0, &do_retry,
retry_name, &newport);
free (name);
@@ -447,29 +525,31 @@ op_mkdir (struct cache_handle *c,
err = EACCES;
if (err)
return err;
-
- err = complete_setattr (newport, p);
+
+ /* Ignore the rest of the sattr structure. */
+
if (!err)
err = io_stat (newport, &st);
if (err)
return err;
-
+
newc = create_cached_handle (*(int *)c->handle, c, newport);
if (!newc)
return ESTALE;
*reply = encode_fhandle (*reply, newc->handle);
- *reply = encode_fattr (*reply, &st);
+ *reply = encode_fattr (*reply, &st, version);
return 0;
}
static error_t
op_rmdir (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
char *name;
error_t err;
-
+
decode_name (p, &name);
err = dir_rmdir (c->port, name);
@@ -480,7 +560,8 @@ op_rmdir (struct cache_handle *c,
static error_t
op_readdir (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
int cookie;
unsigned count;
@@ -491,20 +572,29 @@ op_readdir (struct cache_handle *c,
int nentries;
int i;
int *replystart;
+ int *r;
- cookie = ntohl (*p++);
- count = ntohl (*p++);
+ cookie = ntohl (*p);
+ p++;
+ count = ntohl (*p);
+ p++;
- buf = alloca (count);
- bufsize = count;
+ buf = (char *) 0;
+ bufsize = 0;
err = dir_readdir (c->port, &buf, &bufsize, cookie, -1, count, &nentries);
if (err)
- return err;
+ {
+ if (buf)
+ munmap (buf, bufsize);
+ return err;
+ }
+
+ r = *reply;
if (nentries == 0)
{
- *(*reply)++ = htonl (0); /* no entry */
- *(*reply)++ = htonl (1); /* EOF */
+ *(r++) = htonl (0); /* No entry. */
+ *(r++) = htonl (1); /* EOF. */
}
else
{
@@ -514,31 +604,39 @@ op_readdir (struct cache_handle *c,
&& (char *)reply < (char *)replystart + count);
i++, dp = (struct dirent *) ((char *)dp + dp->d_reclen))
{
- *(*reply)++ = htonl (1); /* entry present */
- *(*reply)++ = htonl (dp->d_ino);
- *reply = encode_string (*reply, dp->d_name);
- *(*reply)++ = htonl (i + cookie + 1); /* next entry */
+ *(r++) = htonl (1); /* Entry present. */
+ *(r++) = htonl (dp->d_ino);
+ r = encode_string (r, dp->d_name);
+ *(r++) = htonl (i + cookie + 1); /* Next entry. */
}
- *(*reply)++ = htonl (0); /* not EOF */
+ *(r++) = htonl (0); /* No more entries. */
+ *(r++) = htonl (0); /* Not EOF. */
}
-
+
+ *reply = r;
+
+ if (buf)
+ munmap (buf, bufsize);
+
return 0;
}
-static size_t
-count_readdir_buffersize (int *p)
+static size_t
+count_readdir_buffersize (int *p, int version)
{
- return ntohl (*++p); /* skip COOKIE; return COUNT */
+ p++; /* Skip COOKIE. */
+ return ntohl (*p); /* Return COUNT. */
}
static error_t
op_statfs (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
struct statfs st;
error_t err;
-
+
err = file_statfs (c->port, &st);
if (!err)
*reply = encode_statfs (*reply, &st);
@@ -548,14 +646,15 @@ op_statfs (struct cache_handle *c,
static error_t
op_mnt (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
file_t root;
struct cache_handle *newc;
char *name;
-
+
decode_name (p, &name);
-
+
root = file_name_lookup (name, 0, 0);
if (!root)
{
@@ -574,14 +673,18 @@ op_mnt (struct cache_handle *c,
static error_t
op_getport (struct cache_handle *c,
int *p,
- int **reply)
+ int **reply,
+ int version)
{
int prog, vers, prot;
-
- prog = ntohl (*p++);
- vers = ntohl (*p++);
- prot = ntohl (*p++);
-
+
+ prog = ntohl (*p);
+ p++;
+ vers = ntohl (*p);
+ p++;
+ prot = ntohl (*p);
+ p++;
+
if (prot != IPPROTO_UDP)
*(*reply)++ = htonl (0);
else if ((prog == MOUNTPROG && vers == MOUNTVERS)
@@ -591,24 +694,24 @@ op_getport (struct cache_handle *c,
*(*reply)++ = htonl (PMAPPORT);
else
*(*reply)++ = 0;
-
+
return 0;
}
-struct proctable nfstable =
+struct proctable nfs2table =
{
- NFSPROC_NULL, /* first proc */
- NFSPROC_STATFS, /* last proc */
+ NFS2PROC_NULL, /* First proc. */
+ NFS2PROC_STATFS, /* Last proc. */
{
{ op_null, 0, 0, 0},
{ op_getattr, 0, 1, 1},
{ op_setattr, 0, 1, 1},
- { 0, 0, 0, 0 }, /* deprecated NFSPROC_ROOT */
+ { 0, 0, 0, 0 }, /* Deprecated NFSPROC_ROOT. */
{ op_lookup, 0, 1, 1},
{ op_readlink, 0, 1, 1},
{ op_read, count_read_buffersize, 1, 1},
- { 0, 0, 0, 0 }, /* nonexistent NFSPROC_WRITECACHE */
+ { 0, 0, 0, 0 }, /* Nonexistent NFSPROC_WRITECACHE. */
{ op_write, 0, 1, 1},
{ op_create, 0, 1, 1},
{ op_remove, 0, 1, 1},
@@ -622,25 +725,25 @@ struct proctable nfstable =
}
};
-
+
struct proctable mounttable =
{
- MOUNTPROC_NULL, /* first proc */
- MOUNTPROC_EXPORT, /* last proc */
+ MOUNTPROC_NULL, /* First proc. */
+ MOUNTPROC_EXPORT, /* Last proc. */
{
{ op_null, 0, 0, 0},
{ op_mnt, 0, 0, 1},
{ 0, 0, 0, 0}, /* MOUNTPROC_DUMP */
- { 0, 0, 0, 0}, /* MOUNTPROC_UMNT */
- { 0, 0, 0, 0}, /* MOUNTPROC_UMNTALL */
+ { op_null, 0, 0, 0}, /* MOUNTPROC_UMNT */
+ { op_null, 0, 0, 0}, /* MOUNTPROC_UMNTALL */
{ 0, 0, 0, 0}, /* MOUNTPROC_EXPORT */
}
};
-struct proctable pmaptable =
+struct proctable pmaptable =
{
- PMAPPROC_NULL, /* first proc */
- PMAPPROC_CALLIT, /* last proc */
+ PMAPPROC_NULL, /* First proc. */
+ PMAPPROC_CALLIT, /* Last proc. */
{
{ op_null, 0, 0, 0},
{ 0, 0, 0, 0}, /* PMAPPROC_SET */
diff --git a/nfsd/proctables.c b/nfsd/proctables.c
deleted file mode 100644
index 1bc76a38..00000000
--- a/nfsd/proctables.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- Copyright (C) 1996 Free Software Foundation, Inc.
- Written by Michael I. Bushnell, p/BSG.
-
- This file is part of the GNU Hurd.
-
- The GNU Hurd is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- The GNU Hurd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
-
-
-struct proctable nfstable =
-{
- NFSPROC_NULL, /* first proc */
- NFSPROC_STATFS, /* last proc */
- { op_null, 0, 0},
- { op_getattr, 0, 1},
- { op_setattr, 0, 1},
- { 0, 0, 0 }, /* deprecated NFSPROC_ROOT */
- { op_lookup, 0, 1},
- { op_readlink, 0, 1},
- { op_read, count_read_buffersize, 1},
- { 0, 0, 0 }, /* nonexistent NFSPROC_WRITECACHE */
- { op_write, 0, 1},
- { op_create, 0, 1},
- { op_remove, 0, 1},
- { op_rename, 0, 1},
- { op_link, 0, 1},
- { op_symlink, 0, 1},
- { op_mkdir, 0, 1},
- { op_rmdir, 0, 1},
- { op_readdir, count_readdir_buffersize, 1},
- { op_statfs, 0, 1},
-};
-
-
-struct proctable mounttable =
-{
- MOUNTPROC_NULL, /* first proc */
- MOUNTPROC_EXPORT, /* last proc */
- { op_null, 0, 0},
- { op_mnt, 0, 0},
- { 0, 0, 0}, /* MOUNTPROC_DUMP */
- { 0, 0, 0}, /* MOUNTPROC_UMNT */
- { 0, 0, 0}, /* MOUNTPROC_UMNTALL */
- { 0, 0, 0}, /* MOUNTPROC_EXPORT */
-};
diff --git a/nfsd/xdr.c b/nfsd/xdr.c
index d5bea0bd..1ff77851 100644
--- a/nfsd/xdr.c
+++ b/nfsd/xdr.c
@@ -1,5 +1,7 @@
-/* XDR packing and unpacking in nfsd
- Copyright (C) 1996 Free Software Foundation, Inc.
+/* xdr.c - XDR packing and unpacking in nfsd.
+
+ Copyright (C) 1996, 2002, 2007 Free Software Foundation, Inc.
+
Written by Michael I. Bushnell, p/BSG.
This file is part of the GNU Hurd.
@@ -23,26 +25,15 @@
#include <string.h>
#include "nfsd.h"
-/* Return the address of the next thing after the credential at P. */
-int *
-skip_cred (int *p)
-{
- int size;
-
- p++; /* TYPE */
- size = ntohl (*p++);
- return p + INTSIZE (size);
-}
-
-/* Any better ideas? */
+/* Any better ideas? */
static int
hurd_mode_to_nfs_mode (mode_t m)
{
- return m & 0x177777;
+ return m & 0177777;
}
static int
-hurd_mode_to_nfs_type (mode_t m)
+hurd_mode_to_nfs_type (mode_t m, int version)
{
switch (m & S_IFMT)
{
@@ -65,84 +56,93 @@ hurd_mode_to_nfs_type (mode_t m)
return NFSOCK;
case S_IFIFO:
- return NFFIFO;
+ return (version == 2 ? NF2FIFO : NF3FIFO);
default:
- return NFNON;
+ return (version == 2 ? NF2NON : NFREG);
}
}
-/* Encode ST into P and return the next thing to come after it. */
+/* Encode ST into P and return the next thing to come after it. */
int *
-encode_fattr (int *p, struct stat *st)
+encode_fattr (int *p, struct stat *st, int version)
{
- *p++ = htonl (hurd_mode_to_nfs_type (st->st_mode));
- *p++ = htonl (hurd_mode_to_nfs_mode (st->st_mode));
- *p++ = htonl (st->st_nlink);
- *p++ = htonl (st->st_uid);
- *p++ = htonl (st->st_gid);
- *p++ = htonl (st->st_size);
- *p++ = htonl (st->st_blksize);
- *p++ = htonl (st->st_rdev);
- *p++ = htonl (st->st_blocks);
+ *(p++) = htonl (hurd_mode_to_nfs_type (st->st_mode, version));
+ *(p++) = htonl (hurd_mode_to_nfs_mode (st->st_mode));
+ *(p++) = htonl (st->st_nlink);
+ *(p++) = htonl (st->st_uid);
+ *(p++) = htonl (st->st_gid);
+ *(p++) = htonl (st->st_size);
+ *(p++) = htonl (st->st_blksize);
+ *(p++) = htonl (st->st_rdev);
+ *(p++) = htonl (st->st_blocks);
+ *(p++) = htonl (st->st_fsid);
+ *(p++) = htonl (st->st_ino);
+ *(p++) = htonl (st->st_atim.tv_sec);
+ *(p++) = htonl (st->st_atim.tv_nsec / 1000);
+ *(p++) = htonl (st->st_mtim.tv_sec);
+ *(p++) = htonl (st->st_mtim.tv_nsec / 1000);
+ *(p++) = htonl (st->st_ctim.tv_sec);
+ *(p++) = htonl (st->st_ctim.tv_nsec / 1000);
return p;
}
-/* Decode P into NAME and return the next thing to come after it. */
+/* Decode P into NAME and return the next thing to come after it. */
int *
decode_name (int *p, char **name)
{
int len;
- len = ntohl (*p++);
+ len = ntohl (*p);
+ p++;
*name = malloc (len + 1);
- bcopy (p, *name, len);
+ memcpy (*name, p, len);
(*name)[len] = '\0';
return p + INTSIZE (len);
}
-/* Encode HANDLE into P and return the next thing to come after it. */
+/* Encode HANDLE into P and return the next thing to come after it. */
int *
encode_fhandle (int *p, char *handle)
{
- bcopy (handle, p, NFS_FHSIZE);
- return p + INTSIZE (NFS_FHSIZE);
+ memcpy (p, handle, NFS2_FHSIZE);
+ return p + INTSIZE (NFS2_FHSIZE);
}
-/* Encode STRING into P and return the next thing to come after it. */
+/* Encode STRING into P and return the next thing to come after it. */
int *
encode_string (int *p, char *string)
{
return encode_data (p, string, strlen (string));
}
-/* Encode DATA into P and return the next thing to come after it. */
+/* Encode DATA into P and return the next thing to come after it. */
int *
encode_data (int *p, char *data, size_t len)
{
int nints = INTSIZE (len);
p[nints] = 0;
- *p++ = htonl (len);
- bcopy (data, p, len);
+ *(p++) = htonl (len);
+ memcpy (p, data, len);
return p + nints;
}
-/* Encode ST into P and return the next thing to come after it. */
+/* Encode ST into P and return the next thing to come after it. */
int *
encode_statfs (int *p, struct statfs *st)
{
- *p++ = st->f_bsize;
- *p++ = st->f_bsize;
- *p++ = st->f_blocks;
- *p++ = st->f_bfree;
- *p++ = st->f_bavail;
+ *(p++) = st->f_bsize;
+ *(p++) = st->f_bsize;
+ *(p++) = st->f_blocks;
+ *(p++) = st->f_bfree;
+ *(p++) = st->f_bavail;
return p;
}
-/* Return an NFS error corresponding to Hurd error ERR. */
+/* Return an NFS error corresponding to Hurd error ERR. */
int
-nfs_error_trans (error_t err)
+nfs_error_trans (error_t err, int version)
{
switch (err)
{
@@ -156,7 +156,6 @@ nfs_error_trans (error_t err)
return NFSERR_NOENT;
case EIO:
- default:
return NFSERR_IO;
case ENXIO:
@@ -197,8 +196,23 @@ nfs_error_trans (error_t err)
case ESTALE:
return NFSERR_STALE;
+
+ default:
+ if (version == 2)
+ return NFSERR_IO;
+ else switch (err)
+ {
+ case EXDEV:
+ return NFSERR_XDEV;
+
+ case EINVAL:
+ return NFSERR_INVAL;
+
+ case EOPNOTSUPP:
+ return NFSERR_NOTSUPP; /* Are we sure here? */
+
+ default:
+ return NFSERR_IO;
+ }
}
}
-
-
-