summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdiskfs/fsys-getfile.c121
1 files changed, 93 insertions, 28 deletions
diff --git a/libdiskfs/fsys-getfile.c b/libdiskfs/fsys-getfile.c
index 90352ead..67bd62e7 100644
--- a/libdiskfs/fsys-getfile.c
+++ b/libdiskfs/fsys-getfile.c
@@ -1,40 +1,105 @@
-/*
- Copyright (C) 1994, 1995 Free Software Foundation
+/* Return the file for a given handle (for nfs server support)
-This file is part of the GNU Hurd.
+ Copyright (C) 1997 Free Software Foundation
-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.
+ This file is part of the GNU Hurd.
-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.
+ 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.
-You should have received a copy of the GNU General Public License
-along with the GNU Hurd; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ 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.
-/* Written by Michael I. Bushnell. */
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <fcntl.h>
#include "priv.h"
#include "fsys_S.h"
+#include "fhandle.h"
+/* Return in FILE & FILE_TYPE the file in FSYS corresponding to the NFS file
+ handle HANDLE & HANDLE_LEN. */
error_t
-diskfs_S_fsys_getfile (mach_port_t fsys __attribute__ ((unused)),
- mach_port_t reply,
- mach_msg_type_name_t replytype,
- uid_t *gen_uids __attribute__ ((unused)),
- u_int ngen_uids __attribute__ ((unused)),
- uid_t *gen_gids __attribute__ ((unused)),
- u_int ngen_gids __attribute__ ((unused)),
- char *handle __attribute__ ((unused)),
- u_int handlelen __attribute__ ((unused)),
- mach_port_t *file __attribute__ ((unused)),
- mach_msg_type_name_t *filetype __attribute__ ((unused)))
+diskfs_S_fsys_getfile (mach_port_t fsys,
+ mach_port_t reply, mach_msg_type_name_t reply_type,
+ uid_t *uids, mach_msg_type_number_t nuids,
+ gid_t *gids, mach_msg_type_number_t ngids,
+ char *handle, mach_msg_type_number_t handle_len,
+ mach_port_t *file, mach_msg_type_name_t *file_type)
{
- return EOPNOTSUPP;
-}
+ int flags;
+ error_t err;
+ struct node *node;
+ struct diskfs_fhandle *f;
+ struct protid *new_cred;
+ struct idvec *uvec, *gvec;
+ struct iouser *user;
+ struct port_info *pt =
+ ports_lookup_port (diskfs_port_bucket, fsys, diskfs_control_class);
+
+ if (!pt)
+ return EOPNOTSUPP;
+
+ if (handle_len != sizeof (struct diskfs_fhandle))
+ {
+ ports_port_deref (pt);
+ return EINVAL;
+ }
+
+ f = (struct diskfs_fhandle *) handle;
+
+ err = diskfs_cached_lookup (f->cache_id, &node);
+ if (err)
+ {
+ ports_port_deref (pt);
+ return err;
+ }
+ if (node->dn_stat.st_gen != f->gen)
+ {
+ diskfs_nput (node);
+ ports_port_deref (pt);
+ return ESTALE;
+ }
+
+ uvec = make_idvec ();
+ gvec = make_idvec ();
+
+ idvec_set_ids (uvec, uids, nuids);
+ idvec_set_ids (gvec, gids, ngids);
+ user = iohelp_create_iouser (uvec, gvec);
+
+ flags = 0;
+ if (! fshelp_access (&node->dn_stat, S_IREAD, user))
+ flags |= O_READ;
+ if (! fshelp_access (&node->dn_stat, S_IEXEC, user))
+ flags |= O_EXEC;
+ if (! fshelp_access (&node->dn_stat, S_IWRITE, user)
+ && ! S_ISDIR (node->dn_stat.st_mode)
+ && ! diskfs_check_readonly ())
+ flags |= O_WRITE;
+
+ err = diskfs_create_protid (diskfs_make_peropen (node, flags,
+ MACH_PORT_NULL, 0),
+ user, &new_cred);
+
+ iohelp_free_iouser (user);
+
+ diskfs_nput (node);
+ ports_port_deref (pt);
+
+ if (! err)
+ {
+ *file = ports_get_right (new_cred);
+ *file_type = MACH_MSG_TYPE_MAKE_SEND;
+ }
+
+ return err;
+}