---
 hurd/fsys.defs                       |    8 ++
 libdiskfs/Makefile                   |    3 +-
 libdiskfs/dir-lookup.c               |    5 +
 libdiskfs/diskfs.h                   |    3 +
 libdiskfs/file-set-trans.c           |    4 +
 libdiskfs/fsys-get-translator-info.c |   61 +++++++++++
 libdiskfs/fsys-getroot.c             |    3 +-
 libdiskfs/peropen-make.c             |    8 ++
 libdiskfs/peropen-rele.c             |    1 +
 libfshelp/Makefile                   |    3 +-
 libfshelp/fshelp.h                   |   12 +++
 libfshelp/translator-list.c          |   87 ++++++++++++++++
 utils/Makefile                       |    8 +-
 utils/mtab.c                         |  187 ++++++++++++++++++++++++++++++++++
 14 files changed, 388 insertions(+), 5 deletions(-)
 create mode 100644 libdiskfs/fsys-get-translator-info.c
 create mode 100644 libfshelp/translator-list.c
 create mode 100644 utils/mtab.c

diff --git a/hurd/fsys.defs b/hurd/fsys.defs
index 979a6cf..f816da0 100644
--- a/hurd/fsys.defs
+++ b/hurd/fsys.defs
@@ -127,3 +127,11 @@ routine fsys_get_options (
        server: fsys_t;
        RPT
        out options: data_t, dealloc);
+
+/* Return the options describing the operation of the receiving
+   filesystem (sutiable for fsys_set_options).  */
+routine fsys_get_translator_info (
+       server: fsys_t;
+       RPT
+        out source: string_t;
+        out children: data_t);
diff --git a/libdiskfs/Makefile b/libdiskfs/Makefile
index c6b5c3f..2bfb1bf 100644
--- a/libdiskfs/Makefile
+++ b/libdiskfs/Makefile
@@ -34,7 +34,8 @@ IOSRCS= io-async-icky.c io-async.c io-duplicate.c 
io-get-conch.c io-revoke.c \
        io-reauthenticate.c io-rel-conch.c io-restrict-auth.c io-seek.c \
        io-select.c io-stat.c io-stubs.c io-write.c io-version.c io-sigio.c
 FSYSSRCS=fsys-getroot.c fsys-goaway.c fsys-startup.c fsys-getfile.c \
-       fsys-options.c fsys-syncfs.c fsys-forward.c
+       fsys-options.c fsys-syncfs.c fsys-forward.c \
+       fsys-get-translator-info.c
 IFSOCKSRCS=ifsock.c
 OTHERSRCS = conch-fetch.c conch-set.c dir-clear.c dir-init.c dir-renamed.c \
        extern-inline.c \
diff --git a/libdiskfs/dir-lookup.c b/libdiskfs/dir-lookup.c
index 923be03..31142ef 100644
--- a/libdiskfs/dir-lookup.c
+++ b/libdiskfs/dir-lookup.c
@@ -82,6 +82,11 @@ diskfs_S_dir_lookup (struct protid *dircred,
       goto gotit;
     }
 
+  free (dircred->po->path);
+  dircred->po->path = strdup(path); /* XXX is this the right place? */
+  if (! dircred->po->path)
+    return ENOMEM;
+
   dnp = dircred->po->np;
 
   pthread_mutex_lock (&dnp->lock);
diff --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h
index 0f9c1d3..2489517 100644
--- a/libdiskfs/diskfs.h
+++ b/libdiskfs/diskfs.h
@@ -69,6 +69,9 @@ struct peropen
   mach_port_t shadow_root_parent;
   /* If in a shadow tree, its root node in this translator.  */
   struct node *shadow_root;
+
+  /* Path relative to the root of the translator. */
+  char *path;
 };
 
 /* A unique one of these exists for each node currently in use (and
diff --git a/libdiskfs/file-set-trans.c b/libdiskfs/file-set-trans.c
index 3798001..acd47bb 100644
--- a/libdiskfs/file-set-trans.c
+++ b/libdiskfs/file-set-trans.c
@@ -206,5 +206,9 @@ diskfs_S_file_set_translator (struct protid *cred,
     }
 
   pthread_mutex_unlock (&np->lock);
+
+  if (! error && cred->po->path)
+    error = fshelp_add_translator (cred->po->path);
+
   return error;
 }
diff --git a/libdiskfs/fsys-get-translator-info.c 
b/libdiskfs/fsys-get-translator-info.c
new file mode 100644
index 0000000..d882397
--- /dev/null
+++ b/libdiskfs/fsys-get-translator-info.c
@@ -0,0 +1,61 @@
+/* fsys_get_translator_info
+
+   Copyright (C) 2013 Free Software Foundation, Inc.
+
+   Written by Justus Winter <4win...@informatik.uni-hamburg.de>
+
+   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 the GNU Hurd; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "priv.h"
+#include "fsys_S.h"
+
+/* Ask SERVER to provide fsys translation service for us.  REQUESTOR is
+   the bootstrap port supplied to the original translator, and ARGV are
+   the command line arguments.  If the recipient accepts the request, he
+   (or some delegate) should send fsys_startup to REQUESTOR to start the
+   filesystem up.  */
+error_t
+diskfs_S_fsys_get_translator_info (mach_port_t server,
+                                   mach_port_t reply,
+                                   mach_msg_type_name_t replyPoly,
+                                   string_t source,
+                                   char **children,
+                                   mach_msg_type_number_t *children_len)
+{
+  error_t err;
+
+  source[0] = 0;
+  /* Let the translator provide a more accurate device. */
+  /* sth along the lines of:
+  if (diskfs_get_device)
+    source = diskfs_get_device();
+  */
+
+  char *c = NULL;
+  size_t c_len = 0;
+
+  err = fshelp_get_translators (&c, &c_len);
+  if (err)
+    goto errout;
+
+  err = iohelp_return_malloced_buffer (c, c_len, children, children_len);
+  c = NULL; /* c was freed by iohelp_return_malloced_buffer. */
+
+ errout:
+  free (c);
+  return err;
+}
diff --git a/libdiskfs/fsys-getroot.c b/libdiskfs/fsys-getroot.c
index 2e11da4..39973a8 100644
--- a/libdiskfs/fsys-getroot.c
+++ b/libdiskfs/fsys-getroot.c
@@ -51,7 +51,8 @@ diskfs_S_fsys_getroot (fsys_t controlport,
   {
     root_parent: dotdot,
     shadow_root_parent: MACH_PORT_NULL,
-    shadow_root: _diskfs_chroot_directory ? diskfs_root_node : NULL /* XXX */
+    shadow_root: _diskfs_chroot_directory ? diskfs_root_node : NULL, /* XXX */
+    path: NULL,
   };
 
   if (!pt)
diff --git a/libdiskfs/peropen-make.c b/libdiskfs/peropen-make.c
index d37516c..d0ac698 100644
--- a/libdiskfs/peropen-make.c
+++ b/libdiskfs/peropen-make.c
@@ -34,6 +34,7 @@ diskfs_make_peropen (struct node *np, int flags, struct 
peropen *context,
   po->refcnt = 0;
   po->openstat = flags;
   po->np = np;
+  po->path = NULL;
 
   if (context)
     {
@@ -50,6 +51,13 @@ diskfs_make_peropen (struct node *np, int flags, struct 
peropen *context,
       if (po->shadow_root_parent != MACH_PORT_NULL)
        mach_port_mod_refs (mach_task_self (), po->shadow_root_parent, 
                            MACH_PORT_RIGHT_SEND, 1);
+
+      if (context->path)
+        {
+          po->path = strdup (context->path);
+          if (! po->path)
+            return ENOMEM;
+        }
     }
   else
     {
diff --git a/libdiskfs/peropen-rele.c b/libdiskfs/peropen-rele.c
index 08276ec..d3f7492 100644
--- a/libdiskfs/peropen-rele.c
+++ b/libdiskfs/peropen-rele.c
@@ -45,5 +45,6 @@ diskfs_release_peropen (struct peropen *po)
 
   diskfs_nput (po->np);
 
+  free (po->path);
   free (po);
 }
diff --git a/libfshelp/Makefile b/libfshelp/Makefile
index 4de3837..6ba6a14 100644
--- a/libfshelp/Makefile
+++ b/libfshelp/Makefile
@@ -20,6 +20,7 @@ makemode := library
 
 libname = libfshelp
 SRCS = lock-acquire.c lock-init.c \
+       translator-list.c \
        start-translator-long.c start-translator.c \
        fetch-root.c transbox-init.c set-active.c fetch-control.c \
        drop-transbox.c translated.c \
@@ -32,7 +33,7 @@ SRCS =        lock-acquire.c lock-init.c \
        touch.c
 installhdrs = fshelp.h
 
-HURDLIBS = shouldbeinlibc iohelp ports
+HURDLIBS = shouldbeinlibc iohelp ports ihash
 LDLIBS += -lpthread
 OBJS = $(subst .c,.o,$(SRCS))
 
diff --git a/libfshelp/fshelp.h b/libfshelp/fshelp.h
index cf39fbc..ce9b0ae 100644
--- a/libfshelp/fshelp.h
+++ b/libfshelp/fshelp.h
@@ -32,6 +32,18 @@
 #include <maptime.h>
 
 
+/* XXX */
+/* XXX */
+
+/* XXX  */
+error_t
+fshelp_add_translator (const char *name);
+
+/* XXX */
+error_t
+fshelp_get_translators (char **translators, size_t *translators_len);
+
+
 /* Passive translator linkage */
 /* These routines are self-contained and start passive translators,
    returning the control port.  They do not require multi threading
diff --git a/libfshelp/translator-list.c b/libfshelp/translator-list.c
new file mode 100644
index 0000000..4a4524c
--- /dev/null
+++ b/libfshelp/translator-list.c
@@ -0,0 +1,87 @@
+/*
+   Copyright (C) 2013 Free Software Foundation
+   Written by Justus Winter <4win...@informatik.uni-hamburg.de>
+
+   This file is part of the GNU Hurd.
+
+   This program 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <argz.h>
+#include <pthread.h>
+#include <hurd/ihash.h>
+
+/* XXX */
+//typedef char * translator_ihash_entry;
+
+/* XXX */
+static struct hurd_ihash translator_ihash
+  = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP);
+
+static pthread_mutex_t translator_ihash_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* XXX */
+static void
+translator_ihash_cleanup (void *element, void *arg)
+{
+  free (element);
+}
+
+error_t
+fshelp_add_translator (const char *name)
+{
+  error_t err = 0;
+  pthread_mutex_lock (&translator_ihash_lock);
+
+  if (! translator_ihash.cleanup)
+    hurd_ihash_set_cleanup (&translator_ihash, translator_ihash_cleanup, NULL);
+
+  HURD_IHASH_ITERATE (&translator_ihash, value)
+    if (strcmp (name, (char *) value) == 0)
+      goto out; /* Entry exists, do nothing. */
+
+  name = strdup (name);
+  if (! name)
+    {
+      err = errno;
+      goto out;
+    }
+
+  err = hurd_ihash_add (&translator_ihash, (hurd_ihash_key_t) name, name);
+  if (err)
+    free (name);
+
+ out:
+  pthread_mutex_unlock (&translator_ihash_lock);
+  return err;
+}
+
+error_t
+fshelp_get_translators (char **translators, size_t *translators_len)
+{
+  error_t err = 0;
+  pthread_mutex_lock (&translator_ihash_lock);
+
+  HURD_IHASH_ITERATE (&translator_ihash, value)
+    {
+      err = argz_add (translators, translators_len, (char *) value);
+      if (err)
+        break;
+    }
+
+  pthread_mutex_unlock (&translator_ihash_lock);
+  return err;
+}
diff --git a/utils/Makefile b/utils/Makefile
index e3bed0b..8a998f3 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -21,14 +21,16 @@ makemode := utilities
 targets = shd ps settrans showtrans syncfs fsysopts \
        storeinfo login w uptime ids loginpr sush vmstat portinfo \
        devprobe vminfo addauth rmauth unsu setauth ftpcp ftpdir storecat \
-       storeread msgport rpctrace mount gcore fakeauth fakeroot remap
+       storeread msgport rpctrace mount gcore fakeauth fakeroot remap \
+       mtab
 special-targets = loginpr sush uptime fakeroot remap
 SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \
        fsysopts.c storeinfo.c login.c loginpr.sh sush.sh w.c \
        uptime.sh psout.c ids.c vmstat.c portinfo.c devprobe.c vminfo.c \
        parse.c frobauth.c frobauth-mod.c setauth.c pids.c nonsugid.c \
        unsu.c ftpcp.c ftpdir.c storeread.c storecat.c msgport.c \
-       rpctrace.c mount.c gcore.c fakeauth.c fakeroot.sh remap.sh
+       rpctrace.c mount.c gcore.c fakeauth.c fakeroot.sh remap.sh \
+       mtab.c
 
 OBJS = $(filter-out %.sh,$(SRCS:.c=.o))
 HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc
@@ -77,3 +79,5 @@ mount: ../sutils/fstab.o ../sutils/clookup.o \
 ../sutils/fstab.o ../sutils/clookup.o: FORCE
        $(MAKE) -C $(@D) $(@F)
 FORCE:
+
+mtab: fsysUser.o
diff --git a/utils/mtab.c b/utils/mtab.c
new file mode 100644
index 0000000..0c91168
--- /dev/null
+++ b/utils/mtab.c
@@ -0,0 +1,187 @@
+/* XXX
+
+   Copyright (C) 2013 Free Software Foundation, Inc.
+
+   Written by Justus Winter <4win...@informatik.uni-hamburg.de>
+
+   This program 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <hurd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <argp.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <error.h>
+#include <argz.h>
+#include <version.h>
+
+#include <hurd/fsys.h>
+
+#include "fsys_U.h"
+
+const char *argp_program_version = STANDARD_HURD_VERSION (fsysopts);
+
+static struct argp_option options[] =
+{
+  {"insecure", 'I', 0, 0, "Follow translators not started by root"},
+  {}
+};
+static char *args_doc = "PATH";
+static char *doc = "XXX";
+
+
+error_t
+print_translator_info (const char *path, int insecure);
+
+error_t
+map_device_to_path (const char *device, char **path);
+
+int
+main (int argc, char *argv[])
+{
+  error_t err;
+  char *path = NULL;
+  int insecure = 0;
+
+  /* Parse a command line option.  */
+  error_t parse_opt (int key, char *arg, struct argp_state *state)
+    {
+      switch (key)
+       {
+        case 'I':
+          insecure = 1;
+          break;
+
+       case ARGP_KEY_ARG:
+         path = arg;
+         break;
+
+       case ARGP_KEY_NO_ARGS:
+         argp_usage (state);
+         return EINVAL;
+
+       default:
+         return ARGP_ERR_UNKNOWN;
+       }
+      return 0;
+    }
+
+  struct argp argp = {options, parse_opt, args_doc, doc};
+
+  argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0);
+
+  err = print_translator_info (path, insecure);
+  if (err)
+    error (5, err, "%s", path);
+
+  return 0;
+}
+
+/* XXX */
+error_t
+print_translator_info (const char *path, int insecure)
+{
+  if (! insecure)
+    {
+      /* XXX check who owns the translator */
+    }
+
+  file_t node = file_name_lookup (path, 0, 0666);
+  if (node == MACH_PORT_NULL)
+    error (1, errno, "%s", path);
+
+  error_t err;
+  char *argz = 0;
+  size_t argz_len = 0;
+  err = file_get_fs_options (node, &argz, &argz_len);
+  if (err)
+    error (5, err, "%s", path);
+
+  size_t count = argz_count (argz, argz_len);
+  char **argv = malloc ((count + 1) * sizeof (char *));
+  if (! argv)
+    return ENOMEM;
+
+  argz_extract (argz, argz_len, argv);
+
+  char *type = strdup (argv[0]);
+  if (! type)
+    return ENOMEM;
+
+  char *options = NULL;
+  size_t options_len = 0;
+
+  for (int i = 1; i < count - 1; i++)
+    {
+      char *v = argv[i];
+
+      if (*v == '-')
+        v++;
+      if (*v == '-')
+        v++;
+
+      err = argz_add (&options, &options_len, v);
+      if (err)
+        return err;
+    }
+
+  argz_stringify (options, options_len, ',');
+
+  string_t source;
+  char *children = NULL;
+  size_t childrenCnt = 0;
+  err = fsys_get_translator_info (node, source, &children, &childrenCnt);
+  if (err)
+    error (5, err, "get_translator_info");
+
+  char *src = NULL;
+  if (*source != '\0')
+    src = source;
+  else
+    map_device_to_path (argv[count - 1], &src);
+
+  printf ("%s %s %s %s 0 0\n", src, path, type, options);
+
+  if (childrenCnt)
+    for (char *c = children; c; c = argz_next (children, childrenCnt, c))
+      {
+        char *p;
+        asprintf (&p, "%s/%s", path, c);
+        if (! p)
+          return ENOMEM;
+
+        print_translator_info (p, insecure);
+      }
+
+  return 0;
+}
+
+/* XXX */
+error_t
+map_device_to_path (const char *device, char **path)
+{
+  if (strcmp (device, "device:") == 0)
+    asprintf (path, "/dev/%s", &device[7]);
+  else
+    *path = strdup ("none");
+
+  if (! *path)
+    return ENOMEM;
+
+  return 0;
+}
-- 
1.7.10.4


Reply via email to