diff options
-rw-r--r-- | libstore/argp.c | 240 |
1 files changed, 107 insertions, 133 deletions
diff --git a/libstore/argp.c b/libstore/argp.c index 70c05759..c375a069 100644 --- a/libstore/argp.c +++ b/libstore/argp.c @@ -20,9 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <stdlib.h> #include <string.h> -#include <fcntl.h> +#include <assert.h> #include <hurd.h> #include <argp.h> #include <argz.h> @@ -30,9 +29,9 @@ #include "store.h" static const struct argp_option options[] = { - {"machdev", 'm', 0, 0, "DEVICE is a mach device, not a file"}, - {"interleave", 'i', "BLOCKS", 0, "Interleave in runs of length BLOCKS"}, - {"layer", 'l', 0, 0, "Layer multiple devices for redundancy"}, + {"device", 'D', 0, 0, "DEVICE is a mach device, not a file"}, + {"interleave",'i', "BLOCKS", 0, "Interleave in runs of length BLOCKS"}, + {"layer", 'l', 0, 0, "Layer multiple devices for redundancy"}, {0} }; @@ -41,68 +40,107 @@ static const char doc[] = "\vIf multiple DEVICEs are specified, they are" " concatenated unless either --interleave or --layer is specified (mutually" " exlusive)."; -/* Used to hold data during argument parsing. */ -struct store_parse_hook +struct store_parsed { - /* A malloced vector of stores specified on the command line, NUM_STORES - long. */ - struct store **stores; - size_t num_stores; - - /* Pointer to params struct passed in by user. */ - struct store_argp_params *params; - + char *names; + size_t names_len; off_t interleave; /* --interleave value */ int machdev : 1; /* --machdev specified */ int layer : 1; /* --layer specified */ }; -/* Free the parse hook H. If ERR_RETURN is true, also free the stores in H's - store vector, and any other return values, otherwise just free the vector - itself. */ -static void -free_hook (struct store_parse_hook *h, int err_return) +void +store_parsed_free (struct store_parsed *parsed) { - int i; - if (err_return) - for (i = 0; i < h->num_stores; i++) - store_free (h->stores[i]); - if (h->stores) - free (h->stores); - if (err_return && h->params->return_args && h->params->args) - free (h->params->args); - free (h); + free (parsed->names); + free (parsed); } - -static error_t -open_file (char *name, struct store_parse_hook *h, struct store **s) + +/* Add the arguments PARSED, and return the corresponding store in STORE. */ +error_t +store_parsed_append_args (const struct store_parsed *parsed, + char **args, size_t *args_len) { - error_t err; - int flags = h->params->flags; - int open_flags = (flags & STORE_HARD_READONLY) ? O_RDONLY : O_RDWR; - file_t node = file_name_lookup (name, open_flags, 0); + error_t err = 0; + size_t num_names = argz_count (parsed->names, parsed->names_len); - if (node == MACH_PORT_NULL) - return errno; + if (parsed->machdev) + err = argz_add (args, args_len, "--machdev"); - err = store_create (node, flags, 0, s); - if (err) + if (!err && num_names > 1 && (parsed->interleave || parsed->layer)) { - if (! h->params->no_file_io) - /* Try making a store that does file io to NODE. */ - err = store_file_create (node, flags, s); - if (err) - mach_port_deallocate (mach_task_self (), node); + char buf[40]; + if (parsed->interleave) + snprintf (buf, sizeof buf, "--interleave=%ld", parsed->interleave); + else + snprintf (buf, sizeof buf, "--layer=%ld", parsed->layer); + err = argz_add (args, args_len, buf); } + if (! err) + err = argz_append (args, args_len, parsed->names, parsed->names_len); + return err; } +/* Open PARSED, and return the corresponding store in STORE. */ +error_t +store_parsed_open (const struct store_parsed *parsed, int flags, + struct store_class *classes, + struct store **store) +{ + size_t num = argz_count (parsed->names, parsed->names_len); + error_t open (char *name, struct store **store) + { + if (parsed->machdev) + return store_device_open (name, flags, store); + else + return store_open (name, flags, classes, store); + } + + if (num == 1) + return open (parsed->names, store); + else + { + int i; + char *name; + error_t err = 0; + struct store **stores = malloc (sizeof (struct store *) * num); + + if (! stores) + return ENOMEM; + + for (i = 0, name = parsed->names; + !err && i < num; + i++, name = argz_next (parsed->names, parsed->names_len, name)) + err = open (name, &stores[i]); + + if (! err) + if (parsed->interleave) + err = + store_ileave_create (stores, num, parsed->interleave, + flags, store); + else if (parsed->layer) + assert (! parsed->layer); + else + err = store_concat_create (stores, num, flags, store); + + if (err) + { + while (i > 0) + store_free (stores[i--]); + free (stores); + } + + return err; + } +} + static error_t parse_opt (int opt, char *arg, struct argp_state *state) { - error_t err = 0; - struct store_parse_hook *h = state->hook; + error_t err; + struct store_parsed *parsed = state->hook; /* Print a parsing error message and (if exiting is turned off) return the error code ERR. */ @@ -111,127 +149,63 @@ parse_opt (int opt, char *arg, struct argp_state *state) switch (opt) { - struct store *s; - case 'm': - h->machdev = 1; break; + parsed->machdev = 1; break; case 'i': - if (h->layer) + if (parsed->layer) PERR (EINVAL, "--layer and --interleave are exclusive"); - if (h->interleave) + if (parsed->interleave) /* Actually no reason why we couldn't support this.... */ PERR (EINVAL, "--interleave specified multiple times"); - h->interleave = atoi (arg); - if (! h->interleave) + parsed->interleave = atoi (arg); + if (! parsed->interleave) PERR (EINVAL, "%s: Bad value for --interleave", arg); break; case 'l': - if (h->interleave) +#if 1 + argp_failure (state, 5, 0, "--layer not implemented"); + return EINVAL; +#else + if (parsed->interleave) PERR (EINVAL, "--layer and --interleave are exclusive"); - h->layer = 1; + parsed->layer = 1; +#endif break; case ARGP_KEY_ARG: /* A store device to use! */ - if (h->machdev) - err = store_device_open (arg, h->params->flags, &s); - else - err = open_file (arg, h, &s); - if (! err) - { - struct store **stores = realloc (h->stores, h->num_stores + 1); - if (stores) - { - stores[h->num_stores++] = s; - h->stores = stores; - if (h->params->return_args) - err = argz_add (&h->params->args, &h->params->args_len, arg); - } - else - err = ENOMEM; /* Just fucking lovely */ - } + err = argz_add (&parsed->names, &parsed->names_len, arg); if (err) - { - argp_failure (state, 1, err, "%s", arg); - return err; - } + argp_failure (state, 1, err, "%s", arg); + return err; break; case ARGP_KEY_INIT: /* Initialize our parsing state. */ if (! state->input) return EINVAL; /* Need at least a way to return a result. */ - h = malloc (sizeof (struct store_parse_hook)); - if (! h) + state->hook = malloc (sizeof (struct store_parsed)); + if (! state->hook) return ENOMEM; - bzero (h, sizeof (struct store_parse_hook)); - h->params = state->input; - if (h->params->return_args) - /* Initialiaze the returned argument vector. */ - { - h->params->args = 0; - h->params->args_len = 0; - } - state->hook = h; + bzero (state->hook, sizeof (struct store_parsed)); break; case ARGP_KEY_ERROR: /* Parsing error occured, free everything. */ - free_hook (h, 1); break; + store_parsed_free (parsed); break; case ARGP_KEY_SUCCESS: /* Successfully finished parsing, return a result. */ - - if (h->num_stores == 0) + if (parsed->names == 0) { - free_hook (h, 1); + store_parsed_free (parsed); PERR (EINVAL, "No store specified"); } - - if (h->params->return_args) - { - if (h->machdev) - err = argz_insert (&h->params->args, &h->params->args_len, - h->params->args, "--machdev"); - if (!err && h->num_stores > 1 && (h->interleave || h->layer)) - { - char buf[40]; - if (h->interleave) - snprintf (buf, sizeof buf, "--interleave=%ld", h->interleave); - else - snprintf (buf, sizeof buf, "--layer=%ld", h->layer); - err = argz_insert (&h->params->args, &h->params->args_len, - h->params->args, buf); - } - } - - if (err) - /* nothing */; - else if (state->input == 0) - /* No way to return a value! */ - err = EINVAL; - else if (h->num_stores == 1) - s = h->stores[0]; /* Just a single store. */ - else if (h->interleave) - err = - store_ileave_create (h->stores, h->num_stores, h->interleave, - h->params->flags, &s); - else if (h->layer) - { - free_hook (h, 1); - PERR (EINVAL, "--layer not implemented"); - } else - err = - store_concat_create (h->stores, h->num_stores, h->params->flags, &s); - - free_hook (h, err); - if (! err) - h->params->result = s; - + *(struct store_parsed **)state->input = parsed; break; default: |