diff options
-rw-r--r-- | libstore/std.c | 7 | ||||
-rw-r--r-- | libstore/store.h | 8 | ||||
-rw-r--r-- | libstore/url.c | 115 |
3 files changed, 129 insertions, 1 deletions
diff --git a/libstore/std.c b/libstore/std.c index 4f82c380..90ddecd1 100644 --- a/libstore/std.c +++ b/libstore/std.c @@ -30,10 +30,15 @@ store_std_classes[] = &store_file_class, &store_zero_class, &store_task_class, - &store_nbd_class, &store_ileave_class, &store_concat_class, &store_remap_class, &store_query_class, &store_copy_class, &store_gunzip_class, &store_bunzip2_class, + + /* This pseudo-class must appear before any real STORAGE_NETWORK class, + to parse STORAGE_NETWORK file_get_storage_info results properly. */ + &store_url_open_class, + &store_nbd_class, + &store_typed_open_class, 0 }; diff --git a/libstore/store.h b/libstore/store.h index a8ff49fe..0f13f96f 100644 --- a/libstore/store.h +++ b/libstore/store.h @@ -421,6 +421,13 @@ error_t store_typed_open (const char *name, int flags, const struct store_class *const *classes, struct store **store); +/* Similar to store_typed_open, but NAME must be in URL format, + i.e. a class name followed by a ':' and any type-specific name. + A leading ':' or no ':' at all is invalid syntax. */ +error_t store_url_open (const char *name, int flags, + const struct store_class *const *classes, + struct store **store); + /* Return a new store in STORE that interleaves all the stores in STRIPES (NUM_STRIPES of them) every INTERLEAVE bytes; INTERLEAVE must be an integer multiple of each stripe's block size. The stores in STRIPES are @@ -526,6 +533,7 @@ extern const struct store_class store_copy_class; extern const struct store_class store_gunzip_class; extern const struct store_class store_bunzip2_class; extern const struct store_class store_typed_open_class; +extern const struct store_class store_url_open_class; /* The following are not included in STORE_STD_CLASSES. */ extern const struct store_class store_mvol_class; diff --git a/libstore/url.c b/libstore/url.c new file mode 100644 index 00000000..967f1342 --- /dev/null +++ b/libstore/url.c @@ -0,0 +1,115 @@ +/* Support for opening stores named in URL syntax. + + Copyright (C) 2001 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "store.h" +#include <string.h> +#include <stdlib.h> + +static const struct store_class * +find_url_class (const char *name, const struct store_class *const *classes) +{ + const struct store_class *const *cl; + const char *clname_end = strchr (name, ':'); + + if (clname_end == name || clname_end == 0) + return 0; + + for (cl = classes ?: store_std_classes; *cl; cl++) + if (strlen ((*cl)->name) == (clname_end - name) + && strncmp (name, (*cl)->name, (clname_end - name)) == 0) + return *cl; + +# pragma weak store_module_open_class + if (classes == 0 && store_module_open_class) + { + const struct store_class *cl; + if (store_module_open_class (name, &cl) == 0) + return cl; + } + + return 0; +} + +/* Similar to store_typed_open, but NAME must be in URL format, + i.e. a class name followed by a ':' and any type-specific name. + Store classes opened this way must strip off the "class:" prefix. + A leading ':' or no ':' at all is invalid syntax. */ + +error_t +store_url_open (const char *name, int flags, + const struct store_class *const *classes, + struct store **store) +{ + const struct store_class *cl = find_url_class (name, classes); + + if (cl == 0) + return EINVAL; + + if (! cl->open) + /* CL cannot be opened. */ + return EOPNOTSUPP; + + return (*cl->open) (name, flags, classes, store); +} + +static error_t +url_decode (struct store_enc *enc, const struct store_class *const *classes, + struct store **store) +{ + const struct store_class *cl; + + /* This is pretty bogus. We use decode.c's code just to validate + the generic format and extract the name from the data. */ + struct store dummy, *dummyptr; + error_t dummy_create (mach_port_t port, int flags, size_t block_size, + const struct store_run *runs, size_t num_runs, + struct store **store) + { + *store = &dummy; + return 0; + } + error_t err = store_std_leaf_decode (enc, &dummy_create, &dummyptr); + if (err) + return err; + + /* Find the class matching this name. */ + cl = find_url_class (dummy.name, classes); + free (dummy.name); + free (dummy.misc); + + if (cl == 0) + return EINVAL; + + /* Now that we have the class, we just punt to its own decode hook. */ + + return (!cl->decode ? EOPNOTSUPP : (*cl->decode) (enc, classes, store)); +} + +/* This class is only trivially different from the "typed" class when used + by name. Its real purpose is to decode file_get_storage_info results + that use the STORAGE_NETWORK type, for which the convention is that the + name be in URL format (i.e. "type:something"). */ + +const struct store_class store_url_open_class = +{ + STORAGE_NETWORK, "url", + open: store_url_open, + decode: url_decode +}; |