bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/3] Add the code for starting up the mountee


From: Sergiu Ivanov
Subject: [PATCH 2/3] Add the code for starting up the mountee
Date: Thu, 11 Jun 2009 21:19:21 +0300
User-agent: Mutt/1.5.18 (2008-05-17)

>From feb8c6ff2c42f0d0f556aa1eb1b033cb875d5f2f Mon Sep 17 00:00:00 2001
From: Sergiu Ivanov <address@hidden>
Date: Thu, 11 Jun 2009 17:09:38 +0300
Subject: [PATCH] Add the code for starting up the mountee.

* netfs.c: Update copyright years.
(netfs_S_dir_lookup): Add the code for starting up the mountee
at the first invocation.
(netfs_get_dirents): Likewise.

* unionmount.h: (unionmount_proxy): Declare this variable.
(mountee_port): Likewise.
(mountee_started): Likewise.
(unionmount_start_mountee): Declare this function.
(unionmount_setup): Likewise.

* unionmount.c: (unionmount_proxy): Define this variable.
(mountee_port): Likewise.
(mountee_started): Likewise.
(unionmount_start_mountee): Borrow the code of this function
from node_set_translator in nsmux and adapt its variable names.
(unionmount_setup): Define this function.
---
 netfs.c      |   38 +++++++++++++-
 unionmount.c |  168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 unionmount.h |   26 +++++++++
 3 files changed, 231 insertions(+), 1 deletions(-)

diff --git a/netfs.c b/netfs.c
index 89d1bf6..fce3366 100644
--- a/netfs.c
+++ b/netfs.c
@@ -1,7 +1,11 @@
 /* Hurd unionfs
-   Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software
+   Foundation, Inc.
+
    Written by Moritz Schulte <address@hidden>.
 
+   Adapted to unionmount by Sergiu Ivanov <address@hidden>
+
    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 of the
@@ -36,6 +40,7 @@
 #include "lib.h"
 #include "ncache.h"
 #include "options.h"
+#include "unionmount.h"
 
 /* Return an argz string describing the current options.  Fill *ARGZ
    with a pointer to newly malloced storage holding the list and *LEN
@@ -810,6 +815,21 @@ netfs_S_dir_lookup (struct protid *diruser,
       goto gotit;
     }
 
+  /*Start the mountee if it's not running yet. */
+  if (!mountee_started)
+    {
+      error = unionmount_setup (diruser);
+      if (error)
+       {
+       /*This is actually the end of initialization, so if something
+         goes bad here we are rightful to die. And, of course,
+         unionmount makes no sense if the mountee is not running. */
+         errno = error;
+         perror ("failed to setup the mountee");
+         exit (EXIT_FAILURE);
+       }
+    }
+
   dnp = diruser->po->np;
 
   mutex_lock (&dnp->lock);
@@ -1112,6 +1132,22 @@ netfs_get_dirents (struct iouser *cred, struct node *dir,
        return 0;
     }
 
+  /*Start the mountee if it's not running yet. */
+  if (!mountee_started)
+    {
+      err = unionmount_setup
+       (netfs_make_protid (netfs_make_peropen (dir, O_READ, NULL), cred));
+      if (err)
+       {
+       /*This is actually the end of initialization, so if something
+         goes bad here we are rightful to die. And, of course,
+         unionmount makes no sense if the mountee is not running. */
+         errno = err;
+         perror ("failed to setup the mountee");
+         exit (EXIT_FAILURE);
+       }
+    }
+
   err = node_entries_get (dir, &dirent_list);
 
   if (! err)
diff --git a/unionmount.c b/unionmount.c
index e4aa043..0e3317d 100644
--- a/unionmount.c
+++ b/unionmount.c
@@ -21,8 +21,176 @@
 
 #define _GNU_SOURCE 1
 
+#include <hurd/fsys.h>
+#include <fcntl.h>
+
+#include "lib.h"
+#include "ulfs.h"
 #include "unionmount.h"
 
 /*The command line for starting the mountee. */
 char * mountee_argz;
 size_t mountee_argz_len;
+
+/*The node the mountee is sitting on. */
+node_t * unionmount_proxy;
+
+/*The port to the mountee. */
+mach_port_t mountee_port;
+
+/*Shows whether the mountee has been started already. */
+int mountee_started = 0;
+
+/*Starts the mountee (given by `argz` and `argz_len`), sets it on node
+  `np` and opens a port `port` to with `flags`. */
+error_t
+unionmount_start_mountee (struct protid * diruser, node_t * np, char * argz,
+                         size_t argz_len, int flags, mach_port_t * port)
+{
+  error_t err;
+  mach_port_t p;
+
+  /*An unauthenticated port to the directory containing `np` */
+  mach_port_t unauth_dir;
+
+  /*The control port for the active translator */
+  mach_port_t active_control;
+
+  /*A copy of the user information, supplied in `user` */
+  struct iouser * user;
+
+  /*A protid for the supplied node */
+  struct protid * newpi;
+
+  /*Identity information about the current process (for fsys_getroot) */
+  uid_t * uids;
+  size_t nuids;
+
+  gid_t * gids;
+  size_t ngids;
+
+  /*The retry information returned by fsys_getroot */
+  string_t retry_name;
+  mach_port_t retry_port;
+
+  /*Try to get the number of effective UIDs */
+  nuids = geteuids (0, 0);
+  if (nuids < 0)
+    return EPERM;
+
+  /*Allocate some memory for the UIDs on the stack */
+  uids = alloca (nuids * sizeof (uid_t));
+
+  /*Fetch the UIDs themselves */
+  nuids = geteuids (nuids, uids);
+  if (nuids < 0)
+    return EPERM;
+
+  /*Try to get the number of effective GIDs */
+  ngids = getgroups (0, 0);
+  if (ngids < 0)
+    return EPERM;
+
+  /*Allocate some memory for the GIDs on the stack */
+  gids = alloca (ngids * sizeof (gid_t));
+
+  /*Fetch the GIDs themselves */
+  ngids = getgroups (ngids, gids);
+  if (ngids < 0)
+    return EPERM;
+
+  /*Opens the port on which to set the new translator */
+  error_t
+    open_port
+    (int flags, mach_port_t * underlying,
+     mach_msg_type_name_t * underlying_type, task_t task, void *cookie)
+  {
+    err = 0;
+
+    /*Duplicate the supplied user */
+    err = iohelp_dup_iouser (&user, diruser->user);
+    if (err)
+      return err;
+
+    /*Create a protid for this node */
+    newpi = netfs_make_protid
+      (netfs_make_peropen (np, flags, diruser->po), user);
+    if (!newpi)
+      {
+       iohelp_free_iouser (user);
+       return errno;
+      }
+
+    /*Obtain the resulting port right and set its type appropriately */
+    *underlying = p = ports_get_send_right (newpi);
+    *underlying_type = MACH_MSG_TYPE_COPY_SEND;
+
+    /*Drop our reference to the port */
+    ports_port_deref (newpi);
+
+    /*Return the result of operations (everything should be okay here) */
+    return err;
+  }                            /*open_port */
+
+  /*Obtain the unauthenticated port to the directory */
+  err = io_restrict_auth
+    (diruser->po->np->nn->ulfs[0].port, &unauth_dir, 0, 0, 0, 0);
+  if (err)
+    return err;
+
+  /*Start the translator */
+  /*The value 60000 for the timeout is the one found in settrans */
+  err = fshelp_start_translator
+    (open_port, NULL, argz, argz, argz_len, 60000, &active_control);
+  if (err)
+    return err;
+
+  /*Attempt to set a translator on the port opened by the previous call */
+  err = file_set_translator
+    (p, 0, FS_TRANS_SET, 0, argz, argz_len,
+     active_control, MACH_MSG_TYPE_COPY_SEND);
+  port_dealloc (p);
+  if (err)
+    return err;
+
+  /*Obtain the port to the top of the newly-set translator */
+  err = fsys_getroot
+    (active_control, unauth_dir, MACH_MSG_TYPE_COPY_SEND,
+     uids, nuids, gids, ngids, flags, &retry_port, retry_name, &p);
+  if (err)
+    return err;
+
+  /*Return the port */
+  *port = p;
+
+  /*Everything is OK here */
+  return 0;
+}                              /* unionmount_start_trans */
+
+/*Sets up a proxy node, sets the translator on it, and registers the
+  filesystem published by the translator in the list of merged
+  filesystems. */
+/*Diruser is required for some additional information. */
+error_t
+unionmount_setup (struct protid * diruser)
+{
+  error_t err = 0;
+
+  /*Create a clone of the root node of the translator. */
+  unionmount_proxy = netfs_make_node (netfs_root_node->nn);
+  if (!unionmount_proxy)
+    return ENOMEM;
+
+  /*Set the mountee on the proxy node. */
+  /*Note that the flags parameter does not actually limit access to
+    the translator's filesystem, because unionmount gives off ports to
+    libnetfs nodes only when it looks up directories. The end client
+    communicates to the translator when operating on regular files. */
+  unionmount_start_mountee (diruser, unionmount_proxy, mountee_argz,
+                           mountee_argz_len, O_READ, &mountee_port);
+
+  mountee_started = 1;
+
+  return err;
+}                              /* unionmount_setup */
+
diff --git a/unionmount.h b/unionmount.h
index a3f7588..fabb2f5 100644
--- a/unionmount.h
+++ b/unionmount.h
@@ -22,10 +22,36 @@
 #ifndef INCLUDED_UNIONMOUNT_H
 #define INCLUDED_UNIONMOUNT_H
 
+#include <error.h>
 #include <unistd.h>
+#include <hurd/hurd_types.h>
+
+#include "node.h"
 
 /*The command line for starting the mountee. */
 extern char * mountee_argz;
 extern size_t mountee_argz_len;
 
+/*The node the mountee is sitting on. */
+extern node_t * unionmount_proxy;
+
+/*The port to the mountee. */
+extern mach_port_t mountee_port;
+
+/*Shows whether the mountee has been started already. */
+extern int mountee_started;
+
+/*Starts the mountee (given by `argz` and `argz_len`), sets it on node
+  `np` and opens a port `port` to with `flags`. */
+error_t
+unionmount_start_mountee (struct protid * diruser, node_t * np, char * argz,
+                         size_t argz_len, int flags, mach_port_t * port);
+
+/*Sets up a proxy node, sets the translator on it, and registers the
+  filesystem published by the translator in the list of merged
+  filesystems. */
+/*Diruser is required for additional information. */
+error_t
+unionmount_setup (struct protid * diruser);
+
 #endif /*INCLUDED_UNIONMOUNT_H*/
-- 
1.5.2.4





reply via email to

[Prev in Thread] Current Thread [Next in Thread]