diff options
author | Roland McGrath <roland@gnu.org> | 1998-10-24 07:31:10 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1998-10-24 07:31:10 +0000 |
commit | f8e9c21bc6f36840b308da7bb1c2d1be79386830 (patch) | |
tree | b1a483b0eb4cb992d22d3cbe9fa26302d9b5158b /libdiskfs/init-startup.c | |
parent | 00ccf96ef26845b7182bcbcf48ea061190b7184a (diff) | |
download | hurd-f8e9c21bc6f36840b308da7bb1c2d1be79386830.tar.gz hurd-f8e9c21bc6f36840b308da7bb1c2d1be79386830.tar.bz2 hurd-f8e9c21bc6f36840b308da7bb1c2d1be79386830.zip |
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.c | 75 |
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)); } - - |