summaryrefslogtreecommitdiff
path: root/libstore
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2001-12-29 00:31:52 +0000
committerRoland McGrath <roland@gnu.org>2001-12-29 00:31:52 +0000
commite251acc12f50473729daa7c1b1890f1c050063c0 (patch)
tree88028e6999f09108f42a3a378459d07b50e0ed21 /libstore
parent1d751a7a5810c6b1bdf4557dfb8bdfdb27405fea (diff)
2001-12-26 Roland McGrath <roland@frob.com>
* unknown.c: New file. * Makefile (SRCS): Add it. * store.h (store_unknown_class, store_unknown_decode): Declare them. * create.c (store_create): If store_decode fails with EINVAL, and we were called with the STORE_NO_FILEIO flag bit set, then use store_unknown_decode.
Diffstat (limited to 'libstore')
-rw-r--r--libstore/Makefile2
-rw-r--r--libstore/create.c7
-rw-r--r--libstore/store.h9
-rw-r--r--libstore/unknown.c187
4 files changed, 202 insertions, 3 deletions
diff --git a/libstore/Makefile b/libstore/Makefile
index bfbb4937..7050f13d 100644
--- a/libstore/Makefile
+++ b/libstore/Makefile
@@ -26,7 +26,7 @@ libname = libstore
SRCS = create.c derive.c make.c rdwr.c set.c device.c file.c stripe.c \
enc.c encode.c decode.c clone.c argp.c std.c kids.c zero.c flags.c \
open.c remap.c xinl.c task.c typed.c copy.c gunzip.c map.c mvol.c \
- bunzip2.c part.c nbd.c memobj.c url.c
+ bunzip2.c part.c nbd.c memobj.c url.c unknown.c
LCLHDRS=store.h
installhdrs=store.h
diff --git a/libstore/create.c b/libstore/create.c
index 71a4c62e..010a053e 100644
--- a/libstore/create.c
+++ b/libstore/create.c
@@ -1,7 +1,7 @@
/* Store creation
- Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
- Written by Miles Bader <miles@gnu.ai.mit.edu>
+ Copyright (C) 1995,96,97,2001 Free Software Foundation, Inc.
+ Written by Miles Bader <miles@gnu.org>
This file is part of the GNU Hurd.
The GNU Hurd is free software; you can redistribute it and/or
@@ -65,6 +65,9 @@ store_create (file_t source, int flags,
if (err)
store_free (*store);
}
+ else if (err == EINVAL && (flags &~ STORE_INACTIVE) == STORE_NO_FILEIO)
+ /* Open a generic "unknown" store that can regurgitate this encoding. */
+ err = store_unknown_decode (&enc, classes, store);
store_enc_dealloc (&enc);
diff --git a/libstore/store.h b/libstore/store.h
index 0f13f96f..6fc77950 100644
--- a/libstore/store.h
+++ b/libstore/store.h
@@ -428,6 +428,14 @@ error_t store_url_open (const char *name, int flags,
const struct store_class *const *classes,
struct store **store);
+/* Return a new store of type "unknown" that holds a copy of the
+ given encoding. The name of the store is taken from ENC->data.
+ Future calls to store_encode/store_return will produce exactly
+ the encoding supplied here. All i/o operations fail with EFTYPE. */
+error_t store_unknown_decode (struct store_enc *enc,
+ 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
@@ -534,6 +542,7 @@ 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;
+extern const struct store_class store_unknown_class;
/* The following are not included in STORE_STD_CLASSES. */
extern const struct store_class store_mvol_class;
diff --git a/libstore/unknown.c b/libstore/unknown.c
new file mode 100644
index 00000000..fce6b558
--- /dev/null
+++ b/libstore/unknown.c
@@ -0,0 +1,187 @@
+/* Store backend for unknown encodings
+
+ 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+
+/* You can't do anything with an unknown store but encode it. */
+
+static error_t
+noread (struct store *store, store_offset_t addr, size_t index,
+ size_t amount, void **buf, size_t *len)
+{
+ return EFTYPE;
+}
+
+static error_t
+nowrite (struct store *store,
+ store_offset_t addr, size_t index,
+ const void *buf, size_t len, size_t *amount)
+{
+ return EFTYPE;
+}
+
+static error_t
+noflags (struct store *store, int flags)
+{
+ return EINVAL;
+}
+
+/* This is the only way that stores of the "unknown" class get created.
+ We save the store encoding verbatim and regurgitate it as our own. */
+
+static struct store_enc *
+duplicate_encoding (struct store_enc *enc)
+{
+ struct store_enc *us;
+ size_t i;
+
+ us = calloc (1, sizeof *us);
+ if (us == NULL)
+ return NULL;
+
+ us->ports = mmap (0, enc->num_ports * sizeof *enc->ports,
+ PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ if (us->ports == MAP_FAILED)
+ {
+ no_memory:
+ store_enc_dealloc (us);
+ free (us);
+ return NULL;
+ }
+ us->ints = mmap (0, enc->num_ints * sizeof *enc->ints,
+ PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ if (us->ints == MAP_FAILED)
+ goto no_memory;
+ us->offsets = mmap (0, enc->num_offsets * sizeof *enc->offsets,
+ PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ if (us->offsets == MAP_FAILED)
+ goto no_memory;
+ us->data = mmap (0, enc->data_len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ if (us->data == MAP_FAILED)
+ goto no_memory;
+
+ memcpy (us->ports, enc->ports, enc->num_ports * sizeof *enc->ports);
+ memcpy (us->ints, enc->ints, enc->num_ints * sizeof *enc->ints);
+ memcpy (us->offsets, enc->offsets, enc->num_offsets * sizeof *enc->offsets);
+ memcpy (us->data, enc->data, enc->data_len);
+
+ us->num_ports = enc->num_ports;
+ us->num_ints = enc->num_ints;
+ us->num_offsets = enc->num_offsets;
+ us->data_len = enc->data_len;
+
+ for (i = 0; i < us->num_ports; ++i)
+ mach_port_mod_refs (mach_task_self (), us->ports[i],
+ MACH_PORT_RIGHT_SEND, +1);
+
+ return us;
+}
+
+error_t
+store_unknown_decode (struct store_enc *enc,
+ const struct store_class *const *classes,
+ struct store **store)
+{
+ struct store_enc *us;
+ error_t err = _store_create (&store_unknown_class,
+ MACH_PORT_NULL, STORE_ENFORCED, 0, NULL, 0, 0,
+ store);
+ if (err)
+ return err;
+
+ us = duplicate_encoding (enc);
+ if (us == NULL)
+ {
+ store_free (*store);
+ return ENOMEM;
+ }
+ (*store)->hook = us;
+
+ /* Derive a name for this unknown store from its encoded type field
+ (or lack thereof) and the leading string of its encoded data bytes. */
+ if (enc->cur_int == enc->num_ints)
+ asprintf (&(*store)->name, "notype:%.*s",
+ us->data_len - us->cur_data, us->data + us->cur_data);
+ else
+ asprintf (&(*store)->name, "type-%d:%.*s", enc->ints[enc->cur_int],
+ us->data_len - us->cur_data, us->data + us->cur_data);
+
+ return 0;
+}
+
+/* Re-encode just the way we got it. */
+error_t
+unknown_allocate_encoding (const struct store *store, struct store_enc *enc)
+{
+ const struct store_enc *us = store->hook;
+ enc->num_ports += us->num_ports;
+ enc->num_ints += us->num_ints;
+ enc->num_offsets += us->num_offsets;
+ enc->data_len += us->data_len;
+ return 0;
+}
+
+error_t
+unknown_encode (const struct store *store, struct store_enc *enc)
+{
+ const struct store_enc *us = store->hook;
+
+ memcpy (enc->ports, us->ports, us->num_ports * sizeof enc->ports[0]);
+ enc->ports += us->num_ports;
+ memcpy (enc->ints, us->ints, us->num_ints * sizeof enc->ints[0]);
+ enc->ints += us->num_ints;
+ memcpy (enc->offsets, us->offsets, us->num_offsets * sizeof enc->offsets[0]);
+ enc->offsets += us->num_offsets;
+ memcpy (enc->data + enc->cur_data, us->data, us->data_len);
+ enc->cur_data += us->data_len;
+
+ return 0;
+}
+
+
+/* Called just before deallocating STORE. */
+static void
+unknown_cleanup (struct store *store)
+{
+ store_enc_dealloc (store->hook);
+ free (store->hook);
+}
+
+/* Copy any format-dependent fields in FROM to TO; if there's some reason
+ why the copy can't be made, an error should be returned. This call is
+ made after all format-independent fields have been cloned. */
+static error_t
+unknown_clone (const struct store *from, struct store *to)
+{
+ to->hook = duplicate_encoding (from->hook);
+ return to->hook ? 0 : ENOMEM;
+}
+
+
+const struct store_class store_unknown_class =
+{
+ -1, "unknown", noread, nowrite,
+ unknown_allocate_encoding, unknown_encode, store_unknown_decode,
+ noflags, noflags, unknown_cleanup, unknown_clone,
+};