diff options
Diffstat (limited to 'nfsd')
-rw-r--r-- | nfsd/Makefile | 4 | ||||
-rw-r--r-- | nfsd/cache.c | 381 | ||||
-rw-r--r-- | nfsd/fsys.c | 91 | ||||
-rw-r--r-- | nfsd/loop.c | 326 | ||||
-rw-r--r-- | nfsd/main.c | 34 | ||||
-rw-r--r-- | nfsd/nfsd.h | 33 | ||||
-rw-r--r-- | nfsd/ops.c | 405 | ||||
-rw-r--r-- | nfsd/proctables.c | 57 | ||||
-rw-r--r-- | nfsd/xdr.c | 116 |
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 *); @@ -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 */ -}; @@ -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; + } } } - - - |