[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
01/04: gnu: hurd: Add `libhurdutil' patch.
From: |
guix-commits |
Subject: |
01/04: gnu: hurd: Add `libhurdutil' patch. |
Date: |
Tue, 7 Apr 2020 10:17:38 -0400 (EDT) |
janneke pushed a commit to branch wip-hurd-vm
in repository guix.
commit f63bf4ba490de06183ce08de5f9b570db07f3647
Author: Jan (janneke) Nieuwenhuizen <address@hidden>
AuthorDate: Tue Apr 7 08:23:53 2020 +0200
gnu: hurd: Add `libhurdutil' patch.
* gnu/packages/patches/hurd-libhurdutil.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add it.
* gnu/packages/hurd.scm (hurd)[source]: Use it.
---
gnu/local.mk | 1 +
gnu/packages/hurd.scm | 3 +-
gnu/packages/patches/hurd-libhurdutil.patch | 1111 +++++++++++++++++++++++++++
3 files changed, 1114 insertions(+), 1 deletion(-)
diff --git a/gnu/local.mk b/gnu/local.mk
index 526b8a0..6ffe515 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1041,6 +1041,7 @@ dist_patch_DATA =
\
%D%/packages/patches/higan-remove-march-native-flag.patch \
%D%/packages/patches/hubbub-sort-entities.patch \
%D%/packages/patches/hurd-cross.patch \
+ %D%/packages/patches/hurd-libhurdutil.patch \
%D%/packages/patches/hplip-remove-imageprocessor.patch \
%D%/packages/patches/hydra-disable-darcs-test.patch \
%D%/packages/patches/icecat-makeicecat.patch \
diff --git a/gnu/packages/hurd.scm b/gnu/packages/hurd.scm
index e5ad8e4..8b5199a 100644
--- a/gnu/packages/hurd.scm
+++ b/gnu/packages/hurd.scm
@@ -339,7 +339,8 @@ boot, since this cannot be done from GNU/Linux."
(name "hurd")
(version (package-version hurd-headers))
(source (origin (inherit (package-source hurd-headers))
- (patches (search-patches "hurd-cross.patch"))))
+ (patches (search-patches "hurd-cross.patch"
+ "hurd-libhurdutil.patch"))))
(arguments
`(#:phases
(modify-phases %standard-phases
diff --git a/gnu/packages/patches/hurd-libhurdutil.patch
b/gnu/packages/patches/hurd-libhurdutil.patch
new file mode 100644
index 0000000..f4788c8
--- /dev/null
+++ b/gnu/packages/patches/hurd-libhurdutil.patch
@@ -0,0 +1,1111 @@
+This patch is from Manolis' GSoC work, not upstreamed yet.
+
+Forward ported from:
+
+
https://github.com/Phant0mas/Hurd/commit/3501ee22ad4150b3b2cf9a386d2350b9a68aecd8.patch
+
+See also:
+ https://lists.gnu.org/archive/html/guix-devel/2020-03/msg00174.html
+
+From 1a6ba95e260c044bf4f84c8c8887fbdcd6c4fce5 Mon Sep 17 00:00:00 2001
+From: Manolis Ragkousis <address@hidden>
+Date: Wed, 25 May 2016 17:45:28 +0300
+Subject: [PATCH] libhurdutil: New library containing utils to be used by Guix.
+
+* libhurdutil/hurdutil.h: New file.
+* libhurdutil/settrans.c: New file.
+* libhurdutil/Makefile: New file.
+* utils/Makefile (HURDLIBS, settrans): Use the new library.
+* utils/settrans.c: Update to use the new library.
+* Makefile: (lib-subdirs): Add library.
+---
+ Makefile | 2 +-
+ libhurdutil/Makefile | 28 +++
+ libhurdutil/hurdutil.h | 84 +++++++
+ libhurdutil/settrans.c | 377 ++++++++++++++++++++++++++++++++
+ utils/Makefile | 4 +-
+ utils/settrans.c | 482 ++++++++++-------------------------------
+ 6 files changed, 604 insertions(+), 373 deletions(-)
+ create mode 100644 libhurdutil/Makefile
+ create mode 100644 libhurdutil/hurdutil.h
+ create mode 100644 libhurdutil/settrans.c
+
+diff --git a/Makefile b/Makefile
+index 6b1e8066..f7a8224d 100644
+--- a/Makefile
++++ b/Makefile
+@@ -29,7 +29,7 @@ include ./Makeconf
+ lib-subdirs = libshouldbeinlibc libihash libiohelp libports libthreads \
+ libpager libfshelp libdiskfs libtrivfs libps \
+ libnetfs libpipe libstore libhurdbugaddr libftpconn libcons \
+- libhurd-slab \
++ libhurd-slab libhurdutil \
+ libbpf \
+ libmachdev \
+
+diff --git a/libhurdutil/Makefile b/libhurdutil/Makefile
+new file mode 100644
+index 00000000..6d2dc7f8
+--- /dev/null
++++ b/libhurdutil/Makefile
+@@ -0,0 +1,28 @@
++# Copyright (C) 2016 Free Software Foundation, Inc.
++#
++# This file is part of the GNU Hurd.
++#
++# The GNU Hurd 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.
++#
++# 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.
++#
++# You should have received a copy of the GNU General Public License
++# along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>.
++
++dir := libhurdutil
++makemode := library
++
++libname := libhurdutil
++SRCS = settrans.c
++installhdrs = hurdutil.h
++
++HURDLIBS= fshelp
++OBJS = $(SRCS:.c=.o)
++
++include ../Makeconf
+diff --git a/libhurdutil/hurdutil.h b/libhurdutil/hurdutil.h
+new file mode 100644
+index 00000000..2ff1e985
+--- /dev/null
++++ b/libhurdutil/hurdutil.h
+@@ -0,0 +1,84 @@
++/* hurdutil.h - Hurd utils interface.
++ Copyright (C) 2016 Free Software Foundation, Inc.
++ Written by Manolis Fragkiskos Ragkousis <address@hidden>.
++
++ This file is part of the GNU Hurd.
++
++ The GNU Hurd 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.
++
++ 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.
++
++ You should have received a copy of the GNU General Public License
++ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>.*/
++
++#ifndef _HURD_UTIL_H
++#define _HURD_UTIL_H
++
++#include <errno.h>
++#include <sys/types.h>
++#include <limits.h>
++#include <stdint.h>
++#include <stddef.h>
++
++#include <hurd/fsys.h>
++
++struct settrans_context
++{
++ /* The name of the node we're putting the translator on. */
++ char *node_name;
++
++ /* Flags to pass to file_set_translator. */
++ int lookup_flags;
++ int goaway_flags;
++
++ /* Various option flags. */
++ int passive : 1;
++ int active : 1;
++ int keep_active : 1;
++ int pause : 1;
++ int kill_active : 1;
++ int orphan : 1;
++ int start : 1;
++ int stack : 1;
++ int excl : 1;
++ int timeout;
++ char *pid_file;
++ char *underlying_node_name;
++ int underlying_lookup_flags;
++ char **chroot_command;
++ char *chroot_chdir;
++
++ /* The translator's arg vector, in '\0' separated format. */
++ char *argz;
++ size_t argz_len;
++};
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* Initialize the flags to be used. */
++void settrans_context_init (struct settrans_context *context);
++
++/* Release the memory allocated. */
++void settrans_context_cleanup (struct settrans_context *context);
++
++/* Create the struct containing the flags and initialize them.
++ If a memory allocation error occurs, ENOMEM is returned,
++ otherwise 0.*/
++error_t settrans_context_create (struct settrans_context **context);
++
++/* Set a translator according to the flags passed. On success return 0. */
++error_t settrans(struct settrans_context *context);
++
++#ifdef __cplusplus
++} /* extern "C" */
++#endif
++
++#endif /* _HURD_UTIL_H */
+diff --git a/libhurdutil/settrans.c b/libhurdutil/settrans.c
+new file mode 100644
+index 00000000..245fae76
+--- /dev/null
++++ b/libhurdutil/settrans.c
+@@ -0,0 +1,377 @@
++/* settrans.c - Set a file's translator.
++
++ Copyright (C) 1995,96,97,98,2001,02,13,14,16
++ Free Software Foundation, Inc.
++ Written by Miles Bader <address@hidden>
++ Written by Manolis Fragkiskos Ragkousis <address@hidden>.
++
++ This file is part of the GNU Hurd.
++
++ The GNU Hurd 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.
++
++ 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.
++
++ You should have received a copy of the GNU General Public License
++ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>.*/
++
++#include <errno.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <assert-backtrace.h>
++#include <fcntl.h>
++#include <argp.h>
++#include <unistd.h>
++#include <sys/wait.h>
++
++#include <hurd.h>
++#include <error.h>
++#include <argz.h>
++#include <hurd/fshelp.h>
++#include <hurd/lookup.h>
++
++
++#include "hurdutil.h"
++
++#define DEFAULT_TIMEOUT 60
++
++/* Authentication of the current process. */
++uid_t *uids;
++gid_t *gids;
++size_t uids_len, gids_len;
++
++/* Initialize and populate the uids and gids vectors. */
++error_t
++get_credentials (void)
++{
++ /* Fetch uids... */
++ uids_len = geteuids (0, 0);
++ if (uids_len < 0)
++ return errno;
++
++ uids = malloc (uids_len * sizeof (uid_t));
++ if (! uids)
++ return ENOMEM;
++
++ uids_len = geteuids (uids_len, uids);
++ if (uids_len < 0)
++ return errno;
++
++ /* ... and gids. */
++ gids_len = getgroups (0, 0);
++ if (gids_len < 0)
++ return errno;
++
++ gids = malloc (gids_len * sizeof (gid_t));
++ if (! uids)
++ return ENOMEM;
++
++ gids_len = getgroups (gids_len, gids);
++ if (gids_len < 0)
++ return errno;
++
++ return 0;
++}
++
++/* ---------------------------------------------------------------- */
++
++void
++settrans_context_init (struct settrans_context *context)
++{
++ context->node_name = 0;
++
++ context->lookup_flags = O_NOTRANS;
++ context->goaway_flags = 0;
++
++ context->passive = 0;
++ context->active = 0;
++ context->keep_active = 0;
++ context->pause = 0;
++ context->kill_active = 0;
++ context->orphan = 0;
++ context->start = 0;
++ context->stack = 0;
++ context->excl = 0;
++ context->timeout = DEFAULT_TIMEOUT * 1000; /* ms */
++ context->pid_file = 0;
++ context->underlying_node_name = NULL;
++ context->chroot_command = 0;
++ context->chroot_chdir = "/";
++
++ context->argz;
++ context->argz_len;
++}
++
++void
++settrans_context_cleanup (struct settrans_context *context)
++{
++ free(context);
++}
++
++error_t
++settrans_context_create (struct settrans_context **context)
++{
++ *context = malloc (sizeof (struct settrans_context));
++ if (*context == NULL)
++ return ENOMEM;
++
++ settrans_context_init(*context);
++
++ return 0;
++}
++
++error_t
++settrans(struct settrans_context *context)
++{
++ error_t err;
++
++ /* The filesystem node we're putting a translator on. */
++ char *node_name = context->node_name;
++ file_t node;
++
++ /* The translator's arg vector, in '\0' separated format. */
++ char *argz = context->argz;
++ size_t argz_len = context->argz_len;
++
++ /* The control port for any active translator we start up. */
++ fsys_t active_control = MACH_PORT_NULL;
++
++ /* Flags to pass to file_set_translator. */
++ int active_flags = 0;
++ int passive_flags = 0;
++ int lookup_flags = context->lookup_flags;
++ int goaway_flags = context->goaway_flags;
++
++ /* Various option flags. */
++ int passive = context->passive;
++ int active = context->active;
++ int keep_active = context->keep_active;
++ int pause = context->pause;
++ int kill_active = context->kill_active;
++ int orphan = context->orphan;
++ int start = context->start;
++ int stack = context->stack;
++ char *pid_file = context->pid_file;
++ unsigned int excl = context->excl;
++ int timeout = context->timeout; /* ms */
++ char *underlying_node_name = context->underlying_node_name;
++ int underlying_lookup_flags = context->underlying_lookup_flags;
++ char **chroot_command = context->chroot_command;
++ char *chroot_chdir = context->chroot_chdir;
++
++ if (stack)
++ {
++ underlying_node_name = node_name;
++ underlying_lookup_flags = lookup_flags && ~O_NOTRANS;
++ }
++ else
++ underlying_lookup_flags = lookup_flags;
++
++
++ if (!active && !passive && !chroot_command)
++ passive = 1; /* By default, set the passive translator. */
++
++ if (passive)
++ passive_flags = FS_TRANS_SET | (excl ? FS_TRANS_EXCL : 0);
++ if (active)
++ active_flags = FS_TRANS_SET | (excl ? FS_TRANS_EXCL : 0)
++ | (orphan ? FS_TRANS_ORPHAN : 0);
++
++ if (passive && !active)
++ {
++ /* When setting just the passive, decide what to do with any active. */
++ if (kill_active)
++ /* Make it go away. */
++ active_flags = FS_TRANS_SET;
++ else if (! keep_active)
++ /* Ensure that there isn't one. */
++ active_flags = FS_TRANS_SET | FS_TRANS_EXCL;
++ }
++
++ if (start)
++ {
++ /* Retrieve the passive translator record in argz. */
++ mach_port_t node = file_name_lookup (node_name, lookup_flags, 0);
++ if (node == MACH_PORT_NULL)
++ error (4, errno, "%s", node_name);
++
++ char buf[1024];
++ argz = buf;
++ argz_len = sizeof (buf);
++
++ err = file_get_translator (node, &argz, &argz_len);
++ if (err == EINVAL)
++ error (4, 0, "%s: no passive translator record found", node_name);
++ if (err)
++ error (4, err, "%s", node_name);
++
++ mach_port_deallocate (mach_task_self (), node);
++ }
++
++ if ((active || chroot_command) && argz_len > 0)
++ {
++ /* Error during file lookup; we use this to avoid duplicating error
++ messages. */
++ error_t open_err = 0;
++
++ /* The callback to start_translator opens NODE as a side effect. */
++ error_t open_node (int flags,
++ mach_port_t *underlying,
++ mach_msg_type_name_t *underlying_type,
++ task_t task, void *cookie)
++ {
++ if (pause)
++ {
++ fprintf (stderr, "Translator pid: %d\nPausing...",
++ task2pid (task));
++ getchar ();
++ }
++
++ if (pid_file != NULL)
++ {
++ FILE *h;
++ h = fopen (pid_file, "w");
++ if (h == NULL)
++ error (4, errno, "Failed to open pid file");
++
++ fprintf (h, "%i\n", task2pid (task));
++ fclose (h);
++ }
++
++ node = file_name_lookup (node_name, flags | lookup_flags, 0666);
++ if (node == MACH_PORT_NULL)
++ {
++ open_err = errno;
++ return open_err;
++ }
++
++ if (underlying_node_name)
++ {
++ *underlying = file_name_lookup (underlying_node_name,
++ flags | underlying_lookup_flags,
++ 0666);
++ if (! MACH_PORT_VALID (*underlying))
++ {
++ /* For the error message. */
++ node_name = underlying_node_name;
++ open_err = errno;
++ return open_err;
++ }
++ }
++ else
++ *underlying = node;
++ *underlying_type = MACH_MSG_TYPE_COPY_SEND;
++
++ return 0;
++ }
++ err = fshelp_start_translator (open_node, NULL, argz, argz, argz_len,
++ timeout, &active_control);
++ if (err)
++ /* If ERR is due to a problem opening the translated node, we print
++ that name, otherwise, the name of the translator. */
++ error(4, err, "%s", (err == open_err) ? node_name : argz);
++ }
++ else
++ {
++ node = file_name_lookup(node_name, lookup_flags, 0666);
++ if (node == MACH_PORT_NULL)
++ error(1, errno, "%s", node_name);
++ }
++
++ if (active || passive)
++ {
++ err = file_set_translator (node,
++ passive_flags, active_flags, goaway_flags,
++ argz, argz_len,
++ active_control, MACH_MSG_TYPE_COPY_SEND);
++ if (err)
++ {
++ error (5, err, "%s", node_name);
++ }
++
++ }
++
++ if (chroot_command)
++ {
++ pid_t child;
++ int status;
++ switch ((child = fork ()))
++ {
++ case -1:
++ error (6, errno, "fork");
++
++ case 0:; /* Child. */
++ /* We will act as the parent filesystem would for a lookup
++ of the active translator's root node, then use this port
++ as our root directory while we exec the command. */
++
++ char retry_name[1024]; /* XXX */
++ retry_type do_retry;
++ mach_port_t root;
++ file_t executable;
++ char *prefixed_name;
++
++ err = get_credentials ();
++ if (err)
++ error (6, err, "getting credentials");
++
++ err = fsys_getroot (active_control,
++ MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND,
++ uids, uids_len, gids, gids_len, 0,
++ &do_retry, retry_name, &root);
++ mach_port_deallocate (mach_task_self (), active_control);
++ if (err)
++ error (6, err, "fsys_getroot");
++ err = hurd_file_name_lookup_retry (&_hurd_ports_use, &getdport, 0,
++ do_retry, retry_name, 0, 0,
++ &root);
++ if (err)
++ error (6, err, "cannot resolve root port");
++
++ if (setcrdir (root))
++ error (7, errno, "cannot install root port");
++ mach_port_deallocate (mach_task_self (), root);
++ if (chdir (chroot_chdir))
++ error (8, errno, "%s", chroot_chdir);
++
++ /* Lookup executable in PATH. */
++ executable = file_name_path_lookup (chroot_command[0],
++ getenv ("PATH"),
++ O_EXEC, 0,
++ &prefixed_name);
++ if (MACH_PORT_VALID (executable))
++ {
++ err = mach_port_deallocate (mach_task_self (), executable);
++ assert_perror_backtrace (err);
++ if (prefixed_name)
++ chroot_command[0] = prefixed_name;
++ }
++
++ execvp (chroot_command[0], chroot_command);
++ error (8, errno, "cannot execute %s", chroot_command[0]);
++ break;
++
++ default: /* Parent. */
++ if (waitpid (child, &status, 0) != child)
++ error (8, errno, "waitpid on %d", child);
++
++ err = fsys_goaway (active_control, goaway_flags);
++ if (err && err != EBUSY)
++ error (9, err, "fsys_goaway");
++
++ if (WIFSIGNALED (status))
++ error (WTERMSIG (status) + 128, 0,
++ "%s for child %d", strsignal (WTERMSIG (status)), child);
++ if (WEXITSTATUS (status) != 0)
++ error (WEXITSTATUS (status), 0,
++ "Error %d for child %d", WEXITSTATUS (status), child);
++ }
++ }
++ return 0;
++}
+diff --git a/utils/Makefile b/utils/Makefile
+index 0cefd27b..f81472f1 100644
+--- a/utils/Makefile
++++ b/utils/Makefile
+@@ -34,7 +34,7 @@ SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c
rmauth.c \
+ nullauth.c match-options.c msgids.c rpcscan.c
+
+ OBJS = $(filter-out %.sh,$(SRCS:.c=.o))
+-HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc
++HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc hurdutil
+ LDLIBS += -lpthread
+ login-LDLIBS = -lutil $(and $(HAVE_LIBCRYPT),-lcrypt)
+ addauth-LDLIBS = $(and $(HAVE_LIBCRYPT),-lcrypt)
+@@ -60,7 +60,7 @@ storeinfo storecat storeread: ../libstore/libstore.a
+ ftpcp ftpdir: ../libftpconn/libftpconn.a
+ mount umount: ../libihash/libihash.a
+ settrans: ../libfshelp/libfshelp.a ../libihash/libihash.a \
+- ../libports/libports.a
++ ../libports/libports.a ../libhurdutil/libhurdutil.a
+ ps w ids settrans syncfs showtrans fsysopts storeinfo login vmstat portinfo \
+ devprobe vminfo addauth rmauth setauth unsu ftpcp ftpdir storeread \
+ storecat msgport mount umount nullauth rpctrace: \
+diff --git a/utils/settrans.c b/utils/settrans.c
+index 9c9f087e..0b580392 100644
+--- a/utils/settrans.c
++++ b/utils/settrans.c
+@@ -3,6 +3,7 @@
+ Copyright (C) 1995,96,97,98,2001,02,13,14
+ Free Software Foundation, Inc.
+ Written by Miles Bader <address@hidden>
++ Revised by Manolis Fragkiskos Ragkousis <address@hidden>.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+@@ -15,8 +16,8 @@
+ 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. */
++ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>.*/
++
+
+ #include <assert-backtrace.h>
+ #include <hurd.h>
+@@ -38,11 +39,10 @@
+ #include <hurd/lookup.h>
+ #include <hurd/fsys.h>
+
++#include <hurd/hurdutil.h>
+
+ const char *argp_program_version = STANDARD_HURD_VERSION (settrans);
+
+-#define DEFAULT_TIMEOUT 60
+-
+ #define _STRINGIFY(arg) #arg
+ #define STRINGIFY(arg) _STRINGIFY (arg)
+
+@@ -92,389 +92,131 @@ static struct argp_option options[] =
+ static char *args_doc = "NODE [TRANSLATOR ARG...]";
+ static char *doc = "Set the passive/active translator on NODE."
+ "\vBy default the passive translator is set.";
+-
+-/* Authentication of the current process. */
+-uid_t *uids;
+-gid_t *gids;
+-size_t uids_len, gids_len;
+-
+-/* Initialize and populate the uids and gids vectors. */
+-error_t
+-get_credentials (void)
+-{
+- /* Fetch uids... */
+- uids_len = geteuids (0, 0);
+- if (uids_len < 0)
+- return errno;
+-
+- uids = malloc (uids_len * sizeof (uid_t));
+- if (! uids)
+- return ENOMEM;
+
+- uids_len = geteuids (uids_len, uids);
+- if (uids_len < 0)
+- return errno;
+-
+- /* ... and gids. */
+- gids_len = getgroups (0, 0);
+- if (gids_len < 0)
+- return errno;
+-
+- gids = malloc (gids_len * sizeof (gid_t));
+- if (! uids)
+- return ENOMEM;
+-
+- gids_len = getgroups (gids_len, gids);
+- if (gids_len < 0)
+- return errno;
++/* The context to be used to create the translator. */
++struct settrans_context *context;
++
++/* ---------------------------------------------------------------- */
+
++/* Parse our options... */
++error_t parse_opt (int key, char *arg, struct argp_state *state)
++{
++ switch (key)
++ {
++ case ARGP_KEY_ARG:
++ if (state->arg_num == 0)
++ context->node_name = arg;
++ else /* command */
++ {
++ if (context->start)
++ argp_error (state, "both --start and TRANSLATOR given");
++
++ error_t err =
++ argz_create (state->argv + state->next - 1, &context->argz,
&context->argz_len);
++ if (err)
++ error(3, err, "Can't create options vector");
++ state->next = state->argc; /* stop parsing */
++ }
++ break;
++
++ case ARGP_KEY_NO_ARGS:
++ argp_usage (state);
++ return EINVAL;
++
++ case 'a': context->active = 1; break;
++ case 's':
++ context->start = 1;
++ context->active = 1; /* start implies active */
++ break;
++ case OPT_STACK:
++ context->stack = 1;
++ context->active = 1; /* stack implies active */
++ context->orphan = 1; /* stack implies orphan */
++ break;
++ case 'p': context->passive = 1; break;
++ case 'k': context->keep_active = 1; break;
++ case 'g': context->kill_active = 1; break;
++ case 'x': context->excl = 1; break;
++ case 'P': context->pause = 1; break;
++ case 'F':
++ context->pid_file = strdup (arg);
++ if (context->pid_file == NULL)
++ error(3, ENOMEM, "Failed to duplicate argument");
++ break;
++
++ case 'o': context->orphan = 1; break;
++ case 'U':
++ context->underlying_node_name = strdup (arg);
++ if (context->underlying_node_name == NULL)
++ error(3, ENOMEM, "Failed to duplicate argument");
++ break;
++
++ case 'C':
++ if (context->chroot_command)
++ {
++ argp_error (state, "--chroot given twice");
++ return EINVAL;
++ }
++ context->chroot_command = &state->argv[state->next];
++ while (state->next < state->argc)
++ {
++ if (!strcmp (state->argv[state->next], "--"))
++ {
++ state->argv[state->next++] = 0;
++ if (context->chroot_command[0] == 0)
++ {
++ argp_error (state,
++ "--chroot must be followed by a command");
++ return EINVAL;
++ }
++ return 0;
++ }
++ ++state->next;
++ }
++ argp_error (state, "--chroot command must be terminated with `--'");
++ return EINVAL;
++
++ case OPT_CHROOT_CHDIR:
++ if (arg[0] != '/')
++ argp_error (state, "--chroot-chdir must be absolute");
++ context->chroot_chdir = arg;
++ break;
++
++ case 'c': context->lookup_flags |= O_CREAT; break;
++ case 'L': context->lookup_flags &= ~O_NOTRANS; break;
++
++ case 'R': context->goaway_flags |= FSYS_GOAWAY_RECURSE; break;
++ case 'S': context->goaway_flags |= FSYS_GOAWAY_NOSYNC; break;
++ case 'f': context->goaway_flags |= FSYS_GOAWAY_FORCE; break;
++
++ /* Use atof so the user can specifiy fractional timeouts. */
++ case 't': context->timeout = atof (arg) * 1000.0; break;
++
++ default:
++ return ARGP_ERR_UNKNOWN;
++ }
+ return 0;
+ }
+-
+-/* ---------------------------------------------------------------- */
+
+ int
+ main(int argc, char *argv[])
+ {
+ error_t err;
+
+- /* The filesystem node we're putting a translator on. */
+- char *node_name = 0;
+- file_t node;
+-
+- /* The translator's arg vector, in '\0' separated format. */
+- char *argz = 0;
+- size_t argz_len = 0;
+-
+- /* The control port for any active translator we start up. */
+- fsys_t active_control = MACH_PORT_NULL;
+-
+- /* Flags to pass to file_set_translator. */
+- int active_flags = 0;
+- int passive_flags = 0;
+- int lookup_flags = O_NOTRANS;
+- int goaway_flags = 0;
+-
+- /* Various option flags. */
+- int passive = 0, active = 0, keep_active = 0, pause = 0, kill_active = 0,
+- orphan = 0;
+- int start = 0;
+- int stack = 0;
+- char *pid_file = NULL;
+- int excl = 0;
+- int timeout = DEFAULT_TIMEOUT * 1000; /* ms */
+- char *underlying_node_name = NULL;
+- int underlying_lookup_flags;
+- char **chroot_command = 0;
+- char *chroot_chdir = "/";
+-
+- /* Parse our options... */
+- error_t parse_opt (int key, char *arg, struct argp_state *state)
+- {
+- switch (key)
+- {
+- case ARGP_KEY_ARG:
+- if (state->arg_num == 0)
+- node_name = arg;
+- else /* command */
+- {
+- if (start)
+- argp_error (state, "both --start and TRANSLATOR given");
+-
+- error_t err =
+- argz_create (state->argv + state->next - 1, &argz, &argz_len);
+- if (err)
+- error(3, err, "Can't create options vector");
+- state->next = state->argc; /* stop parsing */
+- }
+- break;
+-
+- case ARGP_KEY_NO_ARGS:
+- argp_usage (state);
+- return EINVAL;
+-
+- case 'a': active = 1; break;
+- case 's':
+- start = 1;
+- active = 1; /* start implies active */
+- break;
+- case OPT_STACK:
+- stack = 1;
+- active = 1; /* stack implies active */
+- orphan = 1; /* stack implies orphan */
+- break;
+- case 'p': passive = 1; break;
+- case 'k': keep_active = 1; break;
+- case 'g': kill_active = 1; break;
+- case 'x': excl = 1; break;
+- case 'P': pause = 1; break;
+- case 'F':
+- pid_file = strdup (arg);
+- if (pid_file == NULL)
+- error(3, ENOMEM, "Failed to duplicate argument");
+- break;
+-
+- case 'o': orphan = 1; break;
+- case 'U':
+- underlying_node_name = strdup (arg);
+- if (underlying_node_name == NULL)
+- error(3, ENOMEM, "Failed to duplicate argument");
+- break;
+-
+- case 'C':
+- if (chroot_command)
+- {
+- argp_error (state, "--chroot given twice");
+- return EINVAL;
+- }
+- chroot_command = &state->argv[state->next];
+- while (state->next < state->argc)
+- {
+- if (!strcmp (state->argv[state->next], "--"))
+- {
+- state->argv[state->next++] = 0;
+- if (chroot_command[0] == 0)
+- {
+- argp_error (state,
+- "--chroot must be followed by a command");
+- return EINVAL;
+- }
+- return 0;
+- }
+- ++state->next;
+- }
+- argp_error (state, "--chroot command must be terminated with `--'");
+- return EINVAL;
+-
+- case OPT_CHROOT_CHDIR:
+- if (arg[0] != '/')
+- argp_error (state, "--chroot-chdir must be absolute");
+- chroot_chdir = arg;
+- break;
+-
+- case 'c': lookup_flags |= O_CREAT; break;
+- case 'L': lookup_flags &= ~O_NOTRANS; break;
+-
+- case 'R': goaway_flags |= FSYS_GOAWAY_RECURSE; break;
+- case 'S': goaway_flags |= FSYS_GOAWAY_NOSYNC; break;
+- case 'f': goaway_flags |= FSYS_GOAWAY_FORCE; break;
+-
+- /* Use atof so the user can specifiy fractional timeouts. */
+- case 't': timeout = atof (arg) * 1000.0; break;
+-
+- default:
+- return ARGP_ERR_UNKNOWN;
+- }
+- return 0;
+- }
++ settrans_context_create(&context);
++
+ struct argp argp = {options, parse_opt, args_doc, doc};
+
+ argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0);
+
+- if (stack)
++ err = settrans(context);
++ if (err)
+ {
+- underlying_node_name = node_name;
+- underlying_lookup_flags = lookup_flags && ~O_NOTRANS;
++ settrans_context_cleanup(context);
++ error(1, err, "Could not set translator");
+ }
+- else
+- underlying_lookup_flags = lookup_flags;
+
+- if (!active && !passive && !chroot_command)
+- passive = 1; /* By default, set the passive translator. */
+-
+- if (passive)
+- passive_flags = FS_TRANS_SET | (excl ? FS_TRANS_EXCL : 0);
+- if (active)
+- active_flags = FS_TRANS_SET | (excl ? FS_TRANS_EXCL : 0)
+- | (orphan ? FS_TRANS_ORPHAN : 0);
+-
+- if (passive && !active)
+- {
+- /* When setting just the passive, decide what to do with any active. */
+- if (kill_active)
+- /* Make it go away. */
+- active_flags = FS_TRANS_SET;
+- else if (! keep_active)
+- /* Ensure that there isn't one. */
+- active_flags = FS_TRANS_SET | FS_TRANS_EXCL;
+- }
+-
+- if (start)
+- {
+- /* Retrieve the passive translator record in argz. */
+- mach_port_t node = file_name_lookup (node_name, lookup_flags, 0);
+- if (node == MACH_PORT_NULL)
+- error (4, errno, "%s", node_name);
+-
+- char buf[1024];
+- argz = buf;
+- argz_len = sizeof (buf);
+-
+- err = file_get_translator (node, &argz, &argz_len);
+- if (err == EINVAL)
+- error (4, 0, "%s: no passive translator record found", node_name);
+- if (err)
+- error (4, err, "%s", node_name);
+-
+- mach_port_deallocate (mach_task_self (), node);
+- }
+-
+- if ((active || chroot_command) && argz_len > 0)
+- {
+- /* Error during file lookup; we use this to avoid duplicating error
+- messages. */
+- error_t open_err = 0;
+-
+- /* The callback to start_translator opens NODE as a side effect. */
+- error_t open_node (int flags,
+- mach_port_t *underlying,
+- mach_msg_type_name_t *underlying_type,
+- task_t task, void *cookie)
+- {
+- if (pause)
+- {
+- fprintf (stderr, "Translator pid: %d\nPausing...",
+- task2pid (task));
+- getchar ();
+- }
+-
+- if (pid_file != NULL)
+- {
+- FILE *h;
+- h = fopen (pid_file, "w");
+- if (h == NULL)
+- error (4, errno, "Failed to open pid file");
+-
+- fprintf (h, "%i\n", task2pid (task));
+- fclose (h);
+- }
+-
+- node = file_name_lookup (node_name, flags | lookup_flags, 0666);
+- if (node == MACH_PORT_NULL)
+- {
+- open_err = errno;
+- return open_err;
+- }
+-
+- if (underlying_node_name)
+- {
+- *underlying = file_name_lookup (underlying_node_name,
+- flags | underlying_lookup_flags,
+- 0666);
+- if (! MACH_PORT_VALID (*underlying))
+- {
+- /* For the error message. */
+- node_name = underlying_node_name;
+- open_err = errno;
+- return open_err;
+- }
+- }
+- else
+- *underlying = node;
+- *underlying_type = MACH_MSG_TYPE_COPY_SEND;
+-
+- return 0;
+- }
+- err = fshelp_start_translator (open_node, NULL, argz, argz, argz_len,
+- timeout, &active_control);
+- if (err)
+- /* If ERR is due to a problem opening the translated node, we print
+- that name, otherwise, the name of the translator. */
+- error(4, err, "%s", (err == open_err) ? node_name : argz);
+- }
+- else
+- {
+- node = file_name_lookup(node_name, lookup_flags, 0666);
+- if (node == MACH_PORT_NULL)
+- error(1, errno, "%s", node_name);
+- }
+-
+- if (active || passive)
+- {
+- err = file_set_translator (node,
+- passive_flags, active_flags, goaway_flags,
+- argz, argz_len,
+- active_control, MACH_MSG_TYPE_COPY_SEND);
+- if (err)
+- error (5, err, "%s", node_name);
+- }
+-
+- if (chroot_command)
+- {
+- pid_t child;
+- int status;
+- switch ((child = fork ()))
+- {
+- case -1:
+- error (6, errno, "fork");
+-
+- case 0:; /* Child. */
+- /* We will act as the parent filesystem would for a lookup
+- of the active translator's root node, then use this port
+- as our root directory while we exec the command. */
+-
+- char retry_name[1024]; /* XXX */
+- retry_type do_retry;
+- mach_port_t root;
+- file_t executable;
+- char *prefixed_name;
+-
+- err = get_credentials ();
+- if (err)
+- error (6, err, "getting credentials");
+-
+- err = fsys_getroot (active_control,
+- MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND,
+- uids, uids_len, gids, gids_len, 0,
+- &do_retry, retry_name, &root);
+- mach_port_deallocate (mach_task_self (), active_control);
+- if (err)
+- error (6, err, "fsys_getroot");
+- err = hurd_file_name_lookup_retry (&_hurd_ports_use, &getdport, 0,
+- do_retry, retry_name, 0, 0,
+- &root);
+- if (err)
+- error (6, err, "cannot resolve root port");
+-
+- if (setcrdir (root))
+- error (7, errno, "cannot install root port");
+- mach_port_deallocate (mach_task_self (), root);
+- if (chdir (chroot_chdir))
+- error (8, errno, "%s", chroot_chdir);
+-
+- /* Lookup executable in PATH. */
+- executable = file_name_path_lookup (chroot_command[0],
+- getenv ("PATH"),
+- O_EXEC, 0,
+- &prefixed_name);
+- if (MACH_PORT_VALID (executable))
+- {
+- err = mach_port_deallocate (mach_task_self (), executable);
+- assert_perror_backtrace (err);
+- if (prefixed_name)
+- chroot_command[0] = prefixed_name;
+- }
+-
+- execvp (chroot_command[0], chroot_command);
+- error (8, errno, "cannot execute %s", chroot_command[0]);
+- break;
+-
+- default: /* Parent. */
+- if (waitpid (child, &status, 0) != child)
+- error (8, errno, "waitpid on %d", child);
+-
+- err = fsys_goaway (active_control, goaway_flags);
+- if (err && err != EBUSY)
+- error (9, err, "fsys_goaway");
+-
+- if (WIFSIGNALED (status))
+- error (WTERMSIG (status) + 128, 0,
+- "%s for child %d", strsignal (WTERMSIG (status)), child);
+- if (WEXITSTATUS (status) != 0)
+- error (WEXITSTATUS (status), 0,
+- "Error %d for child %d", WEXITSTATUS (status), child);
+- }
+- }
++ settrans_context_cleanup(context);
+
+ return 0;
+ }
+--
+2.26.0
+