summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdiskfs/fsys-getroot.c39
-rw-r--r--libdiskfs/init-startup.c75
-rw-r--r--libdiskfs/opts-std-startup.c7
-rw-r--r--libdiskfs/priv.h5
4 files changed, 92 insertions, 34 deletions
diff --git a/libdiskfs/fsys-getroot.c b/libdiskfs/fsys-getroot.c
index 2a18810c..4e44395d 100644
--- a/libdiskfs/fsys-getroot.c
+++ b/libdiskfs/fsys-getroot.c
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation
+ Copyright (C) 1993, 1994, 1995, 1996, 1997, 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.
@@ -40,13 +40,18 @@ diskfs_S_fsys_getroot (fsys_t controlport,
file_t *returned_port,
mach_msg_type_name_t *returned_port_poly)
{
- struct port_info *pt = ports_lookup_port (diskfs_port_bucket, controlport,
+ struct port_info *pt = ports_lookup_port (diskfs_port_bucket, controlport,
diskfs_control_class);
error_t error = 0;
mode_t type;
struct protid *newpi;
struct iouser user;
- struct peropen peropen_context = { root_parent: dotdot };
+ struct peropen peropen_context =
+ {
+ root_parent: dotdot,
+ shadow_root_parent: MACH_PORT_NULL,
+ shadow_root: _diskfs_chroot_directory ? diskfs_root_node : NULL /* XXX */
+ };
if (!pt)
return EOPNOTSUPP;
@@ -61,7 +66,7 @@ diskfs_S_fsys_getroot (fsys_t controlport,
rwlock_reader_lock (&diskfs_fsys_lock);
mutex_lock (&diskfs_root_node->lock);
-
+
/* This code is similar (but not the same as) the code in
dir-pathtrans.c that does the same thing. Perhaps a way should
be found to share the logic. */
@@ -73,7 +78,7 @@ diskfs_S_fsys_getroot (fsys_t controlport,
&& !(flags & O_NOTRANS))
{
error = fshelp_fetch_root (&diskfs_root_node->transbox,
- &peropen_context, dotdot, &user, flags,
+ &peropen_context, dotdot, &user, flags,
_diskfs_translator_callback1,
_diskfs_translator_callback2,
retry, retryname, returned_port);
@@ -86,17 +91,17 @@ diskfs_S_fsys_getroot (fsys_t controlport,
*returned_port_poly = MACH_MSG_TYPE_MOVE_SEND;
return error;
}
-
+
/* ENOENT means the translator was removed in the interim. */
error = 0;
}
-
+
if (type == S_IFLNK && !(flags & (O_NOLINK | O_NOTRANS)))
{
/* Handle symlink interpretation */
char pathbuf[diskfs_root_node->dn_stat.st_size + 1];
int amt;
-
+
if (diskfs_read_symlink_hook)
error = (*diskfs_read_symlink_hook) (diskfs_root_node, pathbuf);
if (!diskfs_read_symlink_hook || error == EINVAL)
@@ -112,7 +117,7 @@ diskfs_S_fsys_getroot (fsys_t controlport,
drop_idvec ();
return error;
}
-
+
if (pathbuf[0] == '/')
{
*retry = FS_RETRY_MAGICAL;
@@ -134,24 +139,24 @@ diskfs_S_fsys_getroot (fsys_t controlport,
}
}
- if ((type == S_IFSOCK || type == S_IFBLK
+ if ((type == S_IFSOCK || type == S_IFBLK
|| type == S_IFCHR || type == S_IFIFO)
&& (flags & (O_READ|O_WRITE|O_EXEC)))
error = EOPNOTSUPP;
-
+
if (!error && (flags & O_READ))
error = fshelp_access (&diskfs_root_node->dn_stat, S_IREAD, &user);
-
+
if (!error && (flags & O_EXEC))
error = fshelp_access (&diskfs_root_node->dn_stat, S_IEXEC, &user);
-
+
if (!error && (flags & (O_WRITE)))
{
if (type == S_IFDIR)
error = EISDIR;
else if (diskfs_check_readonly ())
error = EROFS;
- else
+ else
error = fshelp_access (&diskfs_root_node->dn_stat,
S_IWRITE, &user);
}
@@ -163,7 +168,7 @@ diskfs_S_fsys_getroot (fsys_t controlport,
drop_idvec ();
return error;
}
-
+
if ((flags & O_NOATIME)
&& (fshelp_isowner (&diskfs_root_node->dn_stat, &user)
== EPERM))
@@ -186,7 +191,7 @@ diskfs_S_fsys_getroot (fsys_t controlport,
*returned_port_poly = MACH_MSG_TYPE_MAKE_SEND;
ports_port_deref (newpi);
}
-
+
mutex_unlock (&diskfs_root_node->lock);
rwlock_reader_unlock (&diskfs_fsys_lock);
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));
}
-
-
diff --git a/libdiskfs/opts-std-startup.c b/libdiskfs/opts-std-startup.c
index 13cf8e65..14760ed7 100644
--- a/libdiskfs/opts-std-startup.c
+++ b/libdiskfs/opts-std-startup.c
@@ -1,6 +1,6 @@
/* Standard startup-time command line parser
- Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
@@ -46,6 +46,9 @@ startup_options[] =
{"device-master-port", OPT_DEVICE_MASTER_PORT, "PORT"},
{"exec-server-task", OPT_EXEC_SERVER_TASK, "PORT"},
{"bootflags", OPT_BOOTFLAGS, "FLAGS"},
+ {"directory", 'C', "DIRECTORY"},
+ {"virtual-root", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"chroot", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
{0}
};
@@ -84,6 +87,8 @@ parse_startup_opt (int opt, char *arg, struct argp_state *state)
diskfs_exec_server_task = atoi (arg); break;
case OPT_BOOTFLAGS:
diskfs_boot_flags = arg; break;
+ case 'C':
+ _diskfs_chroot_directory = arg; break;
case ARGP_KEY_END:
diskfs_argv = state->argv; break;
diff --git a/libdiskfs/priv.h b/libdiskfs/priv.h
index c03d93dc..5a90c2b8 100644
--- a/libdiskfs/priv.h
+++ b/libdiskfs/priv.h
@@ -1,5 +1,5 @@
/* Private declarations for fileserver library
- Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation
+ Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -30,6 +30,9 @@
/* These inhibit setuid or exec. */
extern int _diskfs_nosuid, _diskfs_noexec;
+/* This is the -C argument value. */
+extern const char *_diskfs_chroot_directory;
+
volatile struct mapped_time_value *_diskfs_mtime;
extern struct argp_option diskfs_common_options[];