diff options
Diffstat (limited to 'libstore')
-rw-r--r-- | libstore/Makefile | 2 | ||||
-rw-r--r-- | libstore/create.c | 7 | ||||
-rw-r--r-- | libstore/store.h | 9 | ||||
-rw-r--r-- | libstore/unknown.c | 187 |
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, +}; |