aboutsummaryrefslogtreecommitdiff
path: root/trans/symlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'trans/symlink.c')
-rw-r--r--trans/symlink.c236
1 files changed, 236 insertions, 0 deletions
diff --git a/trans/symlink.c b/trans/symlink.c
new file mode 100644
index 00000000..845a1121
--- /dev/null
+++ b/trans/symlink.c
@@ -0,0 +1,236 @@
+/* Translator for S_IFLNK nodes
+ Copyright (C) 1994, 2000, 2001, 2002 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
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <hurd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <argp.h>
+#include <hurd/fsys.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <error.h>
+#include <version.h>
+#include "fsys_S.h"
+
+mach_port_t realnode;
+
+/* We return this for O_NOLINK lookups */
+mach_port_t realnodenoauth;
+
+/* We return this for non O_NOLINK lookups */
+char *linktarget;
+
+extern int fsys_server (mach_msg_header_t *, mach_msg_header_t *);
+
+const char *argp_program_version = STANDARD_HURD_VERSION (symlink);
+
+static const struct argp_option options[] =
+ {
+ { 0 }
+ };
+
+static const char args_doc[] = "TARGET";
+static const char doc[] = "A translator for symlinks."
+"\vA symlink is an alias for another node in the filesystem."
+"\n"
+"\nA symbolic link refers to its target `by name', and contains no actual"
+" reference to the target. The target referenced by the symlink is"
+" looked up in the namespace of the client.";
+
+/* Parse a single option/argument. */
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+ if (key == ARGP_KEY_ARG && state->arg_num == 0)
+ linktarget = arg;
+ else if (key == ARGP_KEY_ARG || key == ARGP_KEY_NO_ARGS)
+ argp_usage (state);
+ else
+ return ARGP_ERR_UNKNOWN;
+ return 0;
+}
+
+static struct argp argp = { options, parse_opt, args_doc, doc };
+
+
+int
+main (int argc, char **argv)
+{
+ mach_port_t bootstrap;
+ mach_port_t control;
+ error_t err;
+
+ /* Parse our options... */
+ argp_parse (&argp, argc, argv, 0, 0, 0);
+
+ task_get_bootstrap_port (mach_task_self (), &bootstrap);
+ if (bootstrap == MACH_PORT_NULL)
+ error (1, 0, "Must be started as a translator");
+
+ linktarget = argv[1];
+
+ /* Reply to our parent */
+ mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &control);
+ mach_port_insert_right (mach_task_self (), control, control,
+ MACH_MSG_TYPE_MAKE_SEND);
+ err =
+ fsys_startup (bootstrap, 0, control, MACH_MSG_TYPE_COPY_SEND, &realnode);
+ mach_port_deallocate (mach_task_self (), control);
+ mach_port_deallocate (mach_task_self (), bootstrap);
+ if (err)
+ error (1, err, "Starting up translator");
+
+ io_restrict_auth (realnode, &realnodenoauth, 0, 0, 0, 0);
+ mach_port_deallocate (mach_task_self (), realnode);
+
+ /* Mark us as important. */
+ mach_port_t proc = getproc ();
+ if (proc == MACH_PORT_NULL)
+ error (2, err, "cannot get a handle to our process");
+
+ err = proc_mark_important (proc);
+ /* This might fail due to permissions or because the old proc server
+ is still running, ignore any such errors. */
+ if (err && err != EPERM && err != EMIG_BAD_ID)
+ error (2, err, "Cannot mark us as important");
+
+ mach_port_deallocate (mach_task_self (), proc);
+
+ /* Launch */
+ while (1)
+ {
+ /* The timeout here is 10 minutes */
+ err = mach_msg_server_timeout (fsys_server, 0, control,
+ MACH_RCV_TIMEOUT, 1000 * 60 * 10);
+ if (err == MACH_RCV_TIMED_OUT)
+ exit (0);
+ }
+}
+
+error_t
+S_fsys_getroot (mach_port_t fsys_t,
+ mach_port_t dotdotnode,
+ uid_t *uids, size_t nuids,
+ uid_t *gids, size_t ngids,
+ int flags,
+ retry_type *do_retry,
+ char *retry_name,
+ mach_port_t *ret,
+ mach_msg_type_name_t *rettype)
+{
+ if (flags & O_NOLINK)
+ {
+ /* Return our underlying node. */
+ *ret = realnodenoauth;
+ *rettype = MACH_MSG_TYPE_COPY_SEND;
+ *do_retry = FS_RETRY_REAUTH;
+ retry_name[0] = '\0';
+ return 0;
+ }
+ else
+ {
+ /* Return telling the user to follow the link */
+ strcpy (retry_name, linktarget);
+ if (linktarget[0] == '/')
+ {
+ *do_retry = FS_RETRY_MAGICAL;
+ *ret = MACH_PORT_NULL;
+ *rettype = MACH_MSG_TYPE_COPY_SEND;
+ }
+ else
+ {
+ *do_retry = FS_RETRY_REAUTH;
+ *ret = dotdotnode;
+ *rettype = MACH_MSG_TYPE_MOVE_SEND;
+ }
+ }
+ return 0;
+}
+
+error_t
+S_fsys_startup (mach_port_t bootstrap, int flags, mach_port_t control,
+ mach_port_t *real, mach_msg_type_name_t *realtype)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_goaway (mach_port_t control, int flags)
+{
+ exit (0);
+}
+
+error_t
+S_fsys_syncfs (mach_port_t control,
+ int wait,
+ int recurse)
+{
+ return 0;
+}
+
+error_t
+S_fsys_set_options (mach_port_t control,
+ char *data, mach_msg_type_number_t len,
+ int do_children)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_get_options (mach_port_t control,
+ char **data, mach_msg_type_number_t *len)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_getfile (mach_port_t control,
+ uid_t *uids, size_t nuids,
+ uid_t *gids, size_t ngids,
+ char *handle, size_t handllen,
+ mach_port_t *pt,
+ mach_msg_type_name_t *pttype)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_getpriv (mach_port_t control,
+ mach_port_t *host_priv, mach_msg_type_name_t *host_priv_type,
+ mach_port_t *dev_master, mach_msg_type_name_t *dev_master_type,
+ task_t *fs_task, mach_msg_type_name_t *fs_task_type)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_init (mach_port_t control,
+ mach_port_t reply,
+ mach_msg_type_name_t replytype,
+ mach_port_t proc,
+ auth_t auth)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_forward (mach_port_t server, mach_port_t requestor,
+ char *argz, size_t argz_len)
+{
+ return EOPNOTSUPP;
+}