From: Luca Dariz <luca.da...@gmail.com> Basically it is an automation of this: http://walfield.org/pub/people/neal/papers/hurd-misc/manual-bootstrap.txt
To launch a storeio translator on FILE: $ storeio -d FILE -T TYPE ARG --- libtrivfs/startup.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++ libtrivfs/trivfs.h | 11 +++++++++ storeio/storeio.c | 46 ++++++++++++++++++++++++++++------- 3 files changed, 117 insertions(+), 9 deletions(-) diff --git a/libtrivfs/startup.c b/libtrivfs/startup.c index 4d76d47cb..43a858c4c 100644 --- a/libtrivfs/startup.c +++ b/libtrivfs/startup.c @@ -86,3 +86,72 @@ trivfs_startup(mach_port_t bootstrap, int flags, return err; } + +/* Start in debug mode, no need to be called by settrans. Common options are + the same as in trivfs_startup. FILE_NAME is the path of the node where the + translator is set*/ +error_t +trivfs_startup_debug(const char *file_name, + struct port_class *control_class, + struct port_bucket *control_bucket, + struct port_class *protid_class, + struct port_bucket *protid_bucket, + struct trivfs_control **control) +{ + mach_port_t underlying, right, goaway; + struct trivfs_control *fsys; + error_t err = + trivfs_create_control (MACH_PORT_NULL, + control_class, control_bucket, + protid_class, protid_bucket, + &fsys); + + if (err) + return err; + + right = ports_get_send_right (fsys); + goaway = ports_get_send_right (fsys); + + /* Start ourselves as transpator instead of replying to settrans */ + underlying = file_name_lookup(file_name, 0, 0); + if (underlying == MACH_PORT_NULL) + err = errno; + else + err = file_set_translator(underlying, 0, FS_TRANS_SET, 0, "", 0, + right, MACH_MSG_TYPE_COPY_SEND); + mach_port_deallocate (mach_task_self (), right); + + if (! err) + fsys->underlying = underlying; + + ports_port_deref (fsys); + + /* Pass back what we got, unless the caller doesn't want it. */ + if (!err && control) + *control = fsys; + + /* don't mark us as important and install a SIGTERM handler, so we can be + * easily killed by Ctrl-C */ + void handler_sigterm(int signum) + { + error_t ee; + ee = fsys_goaway(goaway, 0); + if (ee == ESUCCESS) + { + mach_port_deallocate (mach_task_self (), goaway); + } + else if (ee != EBUSY) + { + /* Not nice */ + error(99, err, "fsys_goaway"); + } + /* else the translator is busy, please retry */ + } + + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = handler_sigterm; + if (sigaction(SIGTERM, &sa, NULL) < 0) + err = errno; + return err; +} diff --git a/libtrivfs/trivfs.h b/libtrivfs/trivfs.h index 49cc765f9..bcebe7eb3 100644 --- a/libtrivfs/trivfs.h +++ b/libtrivfs/trivfs.h @@ -151,6 +151,17 @@ error_t trivfs_startup (mach_port_t bootstrap, int flags, struct port_bucket *protid_bucket, struct trivfs_control **control); +/* Start in debug mode, no need to be called by settrans. Common options are + the same as in trivfs_startup. FILE_NAME is the path of the node where the + translator is set*/ +error_t +trivfs_startup_debug(const char *file_name, + struct port_class *control_class, + struct port_bucket *control_bucket, + struct port_class *protid_class, + struct port_bucket *protid_bucket, + struct trivfs_control **control); + /* Create a new trivfs control port, with underlying node UNDERLYING, and return it in CONTROL. CONTROL_CLASS & CONTROL_BUCKET are passed to the ports library to create the control port, and PROTID_CLASS & diff --git a/storeio/storeio.c b/storeio/storeio.c index fcf2f30f3..cc4274edd 100644 --- a/storeio/storeio.c +++ b/storeio/storeio.c @@ -23,6 +23,7 @@ #include <fcntl.h> #include <argp.h> #include <argz.h> +#include <stdbool.h> #include <hurd.h> #include <hurd/ports.h> @@ -41,6 +42,8 @@ static struct argp_option options[] = {"no-file-io", 'F', 0, 0,"Never perform io via plain file io RPCs"}, {"no-fileio", 0, 0, OPTION_ALIAS | OPTION_HIDDEN}, {"enforced", 'e', 0, 0,"Never reveal underlying devices, even to root"}, + {"debug", 'd', "PATH", 0, + "Launch a standalone translator, for debug purposes"}, {"rdev", 'n', "ID", 0, "The stat rdev number for this node; may be either a" " single integer, or of the form MAJOR,MINOR"}, @@ -49,7 +52,10 @@ static struct argp_option options[] = static const char doc[] = "Translator for devices and other stores"; const char *argp_program_version = STANDARD_HURD_VERSION (storeio); - + +static bool debug=false; +static char *debug_fname=NULL; + /* Desired store parameters specified by the user. */ struct storeio_argp_params { @@ -96,6 +102,16 @@ parse_opt (int key, char *arg, struct argp_state *state) } break; + case 'd': + { + debug=true; + char *new = strdup (arg); + if (new == NULL) + return ENOMEM; + debug_fname = new; + } + break; + case ARGP_KEY_INIT: /* Now store_argp's parser will get to initialize its state. The default_type member is our input parameter to it. */ @@ -134,14 +150,26 @@ main (int argc, char *argv[]) params.dev = &device; argp_parse (&argp, argc, argv, 0, 0, ¶ms); - task_get_bootstrap_port (mach_task_self (), &bootstrap); - if (bootstrap == MACH_PORT_NULL) - error (2, 0, "Must be started as a translator"); - - /* Reply to our parent */ - err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &storeio_fsys); - if (err) - error (3, err, "trivfs_startup"); + if (debug) + { + if (debug_fname) + err = trivfs_startup_debug (debug_fname, 0, 0, 0, 0, &storeio_fsys); + else + error (3, err, "missing translated node"); + if (err) + error (3, err, "trivfs_startup_debug failed"); + } + else + { + task_get_bootstrap_port (mach_task_self (), &bootstrap); + if (bootstrap == MACH_PORT_NULL) + error (2, 0, "Must be started as a translator"); + + /* Reply to our parent */ + err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &storeio_fsys); + if (err) + error (3, err, "trivfs_startup"); + } storeio_fsys->hook = &device; -- 2.11.0