summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libstore/std.c7
-rw-r--r--libstore/store.h8
-rw-r--r--libstore/url.c115
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
+};