>From feb8c6ff2c42f0d0f556aa1eb1b033cb875d5f2f Mon Sep 17 00:00:00 2001 From: Sergiu Ivanov <unlimitedscol...@gmail.com> 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 <mor...@duesseldorf.ccc.de>. + Adapted to unionmount by Sergiu Ivanov <unlimitedscol...@gmail.com> + 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