summaryrefslogtreecommitdiff
path: root/libdiskfs/init-startup.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1998-10-24 07:31:10 +0000
committerRoland McGrath <roland@gnu.org>1998-10-24 07:31:10 +0000
commitf8e9c21bc6f36840b308da7bb1c2d1be79386830 (patch)
treeb1a483b0eb4cb992d22d3cbe9fa26302d9b5158b /libdiskfs/init-startup.c
parent00ccf96ef26845b7182bcbcf48ea061190b7184a (diff)
1998-04-04 Roland McGrath <roland@baalperazim.frob.com>
Add support for a "virtual root directory" specified at startup. * priv.h (_diskfs_chroot_directory): Declare new variable. * opts-std-startup.c (startup_options, parse_startup_opt): New string-valued option -C/--directory/--virtual-root/--chroot sets _diskfs_chroot_directory. * init-startup.c (_diskfs_chroot_directory): New variable. (diskfs_startup_diskfs): If that's set, look up the name and warp us to that as a virtual root directory. * fsys-getroot.c (diskfs_S_fsys_getroot): Initialize new peropen's shadow_root_parent to null, and shadow_root to either null or, if _diskfs_chroot_directory is set, to diskfs_root_node.
Diffstat (limited to 'libdiskfs/init-startup.c')
-rw-r--r--libdiskfs/init-startup.c75
1 files changed, 60 insertions, 15 deletions
diff --git a/libdiskfs/init-startup.c b/libdiskfs/init-startup.c
index d2802db5..3573f8ff 100644
--- a/libdiskfs/init-startup.c
+++ b/libdiskfs/init-startup.c
@@ -1,5 +1,5 @@
/* diskfs_startup_diskfs -- advertise our fsys control port to our parent FS.
- Copyright (C) 1994, 1995, 1996 Free Software Foundation
+ Copyright (C) 1994, 1995, 1996, 1998 Free Software Foundation
This file is part of the GNU Hurd.
@@ -8,7 +8,7 @@ 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,
+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.
@@ -22,15 +22,62 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "priv.h"
#include <stdio.h>
#include <string.h>
+#include <fcntl.h>
+#include <error.h>
#include <hurd/fsys.h>
#include <hurd/startup.h>
+const char *_diskfs_chroot_directory;
+
mach_port_t
diskfs_startup_diskfs (mach_port_t bootstrap, int flags)
{
mach_port_t realnode;
struct port_info *newpi;
-
+
+ if (_diskfs_chroot_directory != NULL)
+ {
+ /* The boot options requested we change to a subdirectory
+ and treat that as the root of the filesystem. */
+ error_t err;
+ struct node *np, *old;
+ struct protid *rootpi;
+
+ mutex_lock (&diskfs_root_node->lock);
+
+ /* Create a protid we can use in diskfs_lookup. */
+ err = diskfs_create_protid (diskfs_make_peropen (diskfs_root_node,
+ O_READ|O_EXEC, 0),
+ 0, &rootpi);
+ assert_perror (err);
+
+ /* Look up the directory name. */
+ err = diskfs_lookup (diskfs_root_node, _diskfs_chroot_directory,
+ LOOKUP, &np, NULL, rootpi);
+ mutex_unlock (&diskfs_root_node->lock);
+ ports_port_deref (rootpi);
+
+ if (err == EAGAIN)
+ error (1, 0, "`--virtual-root=%s' specifies the real root directory",
+ _diskfs_chroot_directory);
+ else if (err)
+ error (1, err, "`%s' not found", _diskfs_chroot_directory);
+
+ if (!S_ISDIR (np->dn_stat.st_mode))
+ {
+ mutex_unlock (&np->lock);
+ error (1, ENOTDIR, "%s", _diskfs_chroot_directory);
+ }
+
+ /* Install this node as the new root, forgetting about the real root
+ node. The last essential piece that makes the virtual root work
+ is in fsys-getroot.c, which sets the first peropen's shadow_root
+ if _diskfs_chroot_directory is non-null. */
+ old = diskfs_root_node;
+ diskfs_root_node = np;
+ ports_port_deref (old);
+ }
+
if (bootstrap != MACH_PORT_NULL)
{
errno = ports_create_port (diskfs_control_class, diskfs_port_bucket,
@@ -70,22 +117,22 @@ error_t
diskfs_S_startup_dosync (mach_port_t handle)
{
error_t err = 0;
- struct port_info *pi
+ struct port_info *pi
= ports_lookup_port (diskfs_port_bucket, handle,
diskfs_shutdown_notification_class);
if (!pi)
return EOPNOTSUPP;
-
+
if (! diskfs_readonly)
{
/* First start a sync so that if something goes wrong
we at least get this much done. */
diskfs_sync_everything (0);
diskfs_set_hypermetadata (0, 0);
-
+
rwlock_writer_lock (&diskfs_fsys_lock);
-
+
/* Permit all the current RPC's to finish, and then suspend new ones */
err = ports_inhibit_class_rpcs (diskfs_protid_class);
if (! err)
@@ -107,7 +154,7 @@ diskfs_S_startup_dosync (mach_port_t handle)
/* This is called when we have an ordinary environment, complete
with proc and auth ports. */
-void
+void
_diskfs_init_completed ()
{
startup_t init;
@@ -117,12 +164,12 @@ _diskfs_init_completed ()
mach_port_t notify;
char *name;
- /* Contact the startup server and register our shutdown request.
+ /* Contact the startup server and register our shutdown request.
If we get an error, print an informational message. */
proc = getproc ();
assert (proc);
-
+
err = ports_create_port (diskfs_shutdown_notification_class,
diskfs_port_bucket, sizeof (struct port_info),
&pi);
@@ -133,17 +180,17 @@ _diskfs_init_completed ()
mach_port_deallocate (mach_task_self (), proc);
if (err)
goto errout;
-
+
notify = ports_get_right (pi);
ports_port_deref (pi);
asprintf (&name,
"%s %s", program_invocation_short_name, diskfs_disk_name ?: "-");
- err = startup_request_notification (init, notify,
+ err = startup_request_notification (init, notify,
MACH_MSG_TYPE_MAKE_SEND, name);
free (name);
if (err)
goto errout;
-
+
mach_port_deallocate (mach_task_self (), init);
return;
@@ -151,5 +198,3 @@ _diskfs_init_completed ()
fprintf (stderr, "Cannot request shutdown notification: %s\n",
strerror (err));
}
-
-