aboutsummaryrefslogtreecommitdiff
path: root/nfsd/ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'nfsd/ops.c')
-rw-r--r--nfsd/ops.c405
1 files changed, 254 insertions, 151 deletions
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 */