summaryrefslogtreecommitdiff
path: root/libdiskfs/dir-lookup.c
diff options
context:
space:
mode:
authorMiles Bader <miles@gnu.org>1995-10-31 18:25:16 +0000
committerMiles Bader <miles@gnu.org>1995-10-31 18:25:16 +0000
commita6e1cfaa1d3e3d43b1ebd9958dd057ab51d6f358 (patch)
tree367b712261dda34ade28c0e212079287505422e9 /libdiskfs/dir-lookup.c
parentd6682a9bab19ad96d17fdabacb4953f919e1b426 (diff)
(diskfs_S_dir_lookup): Deal correctly with short-circuited translators that
diskfs doesn't implement itself. (major, minor): New macros -- temporarily here until libc exports them.
Diffstat (limited to 'libdiskfs/dir-lookup.c')
-rw-r--r--libdiskfs/dir-lookup.c77
1 files changed, 72 insertions, 5 deletions
diff --git a/libdiskfs/dir-lookup.c b/libdiskfs/dir-lookup.c
index bac87859..7e48df60 100644
--- a/libdiskfs/dir-lookup.c
+++ b/libdiskfs/dir-lookup.c
@@ -21,6 +21,10 @@
#include <string.h>
#include <hurd/fsys.h>
+/* XXX - Temporary hack; this belongs in a header file, probably types.h. */
+#define major(x) ((int)(((unsigned) (x) >> 8) & 0xff))
+#define minor(x) ((int)((x) & 0xff))
+
/* Implement dir_lookup as described in <hurd/fs.defs>. */
kern_return_t
diskfs_S_dir_lookup (struct protid *dircred,
@@ -171,15 +175,76 @@ diskfs_S_dir_lookup (struct protid *dircred,
/* If this is translated, start the translator (if necessary)
and return. */
if ((((flags & O_NOTRANS) == 0) || !lastcomp)
- && (np->istranslated || fshelp_translated (&np->transbox)))
+ && (node->istranslated
+ || S_ISFIFO (np->dn_stat.st_mode)
+ || S_ISCHR (np->dn_stat.st_mode)
+ || S_ISBLK (np->dn_stat.st_mode)
+ || fshelp_translated (&np->transbox)))
{
mach_port_t dirport;
+
+ /* A call backup function for short-circuited translators.
+ Symlink & ifsock are handled elsewhere. */
+ error_t short_circuited_callback (void *cookie1, void *cookie2,
+ mach_port_t *underlying,
+ uid_t *uid, gid_t *gid,
+ char **argz, int *argz_len)
+ {
+ struct node *node = cookie1;
+ mach_port_t *dotdot = cookie2;
+ error_t err = 0;
+ struct protid *newpi;
+
+ switch (node->dn_stat.st_mode & S_IFMT)
+ {
+ case S_IFCHR:
+ case S_IFBLK:
+ asprintf (argz, "%s%c%d%c%d",
+ (S_ISCHR (node->dn_stat.st_mode)
+ ? _HURD_CHRDEV : _HURD_BLKDEV),
+ 0, major (node->dn_stat.st_rdev),
+ 0, minor (node->dn_stat.st_rdev),);
+ argz_len = strlen (argz) + 1;
+ argz_len += strlen (argz + argz_len) + 1;
+ argz_len += strlen (argz + argz_len) + 1;
+ break;
+ case S_IFIFO:
+ asprintf (argz, "%s", _HURD_FIFO);
+ argz_len = strlen (argz) + 1;
+ break;
+ default:
+ return ENOENT;
+ }
+
+ *uid = node->dn_stat.st_uid;
+ *gid = node->dn_stat.st_gid;
+
+ newpi =
+ diskfs_make_protid (diskfs_make_peropen (node,
+ (O_READ|O_EXEC
+/* For now, don't give translators write access to their underlying node.
+ The fsys_startup interface will soon make this irrelevant anyway. */
+#ifdef XXX
+ | (!diskfs_readonly
+ ? O_WRITE : 0)
+#endif
+ ),
+ *dotdot),
+ uid, 1, gid, 1);
+
+ *underlying = ports_get_right (newpi);
+ mach_port_insert_right (mach_task_self (), *underlying,
+ *underlying, MACH_MSG_TYPE_MAKE_SEND);
+ ports_port_deref (newpi);
+ return 0;
+ }
/* Create an unauthenticated port for DNP, and then
unlock it. */
- newpi = diskfs_make_protid (diskfs_make_peropen (dnp, 0,
- dircred->po->dotdotport),
- 0, 0, 0, 0);
+ newpi =
+ diskfs_make_protid (diskfs_make_peropen (dnp, 0,
+ dircred->po->dotdotport),
+ 0, 0, 0, 0);
dirport = ports_get_right (newpi);
mach_port_insert_right (mach_task_self (), dirport, dirport,
MACH_MSG_TYPE_MAKE_SEND);
@@ -191,7 +256,9 @@ diskfs_S_dir_lookup (struct protid *dircred,
dirport, dircred->uids, dircred->nuids,
dircred->gids, dircred->ngids,
lastcomp ? flags : 0,
- _diskfs_translator_callback,
+ (node->istranslated
+ ? _diskfs_translator_callback
+ : short_circuited_callback),
retry, retryname, returned_port);
if (error != ENOENT)