diff options
Diffstat (limited to 'libstore/copy.c')
-rw-r--r-- | libstore/copy.c | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/libstore/copy.c b/libstore/copy.c new file mode 100644 index 00000000..e5e83121 --- /dev/null +++ b/libstore/copy.c @@ -0,0 +1,237 @@ +/* Copy store backend + + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.ai.mit.edu> + + This task 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 <stdio.h> +#include <string.h> +#include <malloc.h> + +#include "store.h" + +static error_t +copy_read (struct store *store, + off_t addr, size_t index, size_t amount, void **buf, size_t *len) +{ + if (*len < amount) + /* Have to allocate memory for the return value. */ + { + error_t err = + vm_allocate (mach_task_self (), (vm_address_t *)buf, amount, 1); + if (err) + return err; + } + + bcopy (store->hook + (addr * store->block_size), *buf, amount); + *len = amount; + return 0; +} + +static error_t +copy_write (struct store *store, + off_t addr, size_t index, void *buf, size_t len, size_t *amount) +{ + bcopy (buf, store->hook + (addr * store->block_size), len); + *amount = len; + return 0; +} + +error_t +copy_allocate_encoding (const struct store *store, struct store_enc *enc) +{ + /* ... */ + return EOPNOTSUPP; +} + +error_t +copy_encode (const struct store *store, struct store_enc *enc) +{ + /* ... */ + return EOPNOTSUPP; +} + +static error_t +copy_decode (struct store_enc *enc, const struct store_class *const *classes, + struct store **store) +{ + /* ... */ + return EOPNOTSUPP; +} + +static error_t +copy_open (const char *name, int flags, + const struct store_class *const *classes, + struct store **store) +{ + return store_copy_open (name, flags, classes, store); +} + +static error_t +copy_set_flags (struct store *store, int flags) +{ + if ((flags & ~(STORE_INACTIVE | STORE_ENFORCED)) != 0) + /* Trying to set flags we don't support. */ + return EINVAL; + + /* ... */ + + store->flags |= flags; /* When inactive, anything goes. */ + + return 0; +} + +static error_t +copy_clear_flags (struct store *store, int flags) +{ + error_t err = 0; + if ((flags & ~(STORE_INACTIVE | STORE_ENFORCED)) != 0) + err = EINVAL; + /* ... */ + if (! err) + store->flags &= ~flags; + return err; +} + +/* Called just before deallocating STORE. */ +void +copy_cleanup (struct store *store) +{ + if (store->size > 0) + vm_deallocate (mach_task_self (), (vm_address_t)store->hook, store->size); +} + +/* 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-indendependent fields have been cloned. */ +error_t +copy_clone (const struct store *from, struct store *to) +{ + error_t err = + vm_allocate (mach_task_self (), (vm_address_t *)&to->hook, to->size, 1); + if (! err) + bcopy (from->hook, to->hook, from->size); + return err; +} + +struct store_class +store_copy_class = +{ + STORAGE_COPY, "copy", copy_read, copy_write, + copy_allocate_encoding, copy_encode, copy_decode, + copy_set_flags, copy_clear_flags, copy_cleanup, copy_clone, 0, copy_open +}; + +/* Return a new store in STORE which contains a snapshot of the contents of + the store FROM; FROM is consumed. */ +error_t +store_copy_create (struct store *from, int flags, struct store **store) +{ + error_t err; + struct store_run run; + + run.start = 0; + run.length = from->size; + + flags |= STORE_ENFORCED; /* Only uses local resources. */ + + err = + _store_create (&store_copy_class, + MACH_PORT_NULL, flags, from->block_size, &run, 1, 0, + store); + if (! err) + { + size_t buf_len = 0; + + /* Copy the input store. */ + err = store_read (from, 0, from->size, &(*store)->hook, &buf_len); + + if (! err) + /* Set the store name. */ + { + if (from->name) + { + size_t len = + strlen (from->class->name) + 1 + strlen (from->name) + 1; + (*store)->name = malloc (len); + if ((*store)->name) + snprintf ((*store)->name, len, + "%s:%s", from->class->name, from->name); + } + else + (*store)->name = strdup (from->class->name); + + if (! (*store)->name) + err = ENOMEM; + } + + if (err) + store_free (*store); + } + + return err; +} + +/* Return a new store in STORE which contains the memory buffer BUF, of + length BUF_LEN, and uses the block size BLOCK_SIZE. BUF must be + vm_allocated, and will be consumed, and BUF_LEN must be a multiple of + BLOCK_SIZE. */ +error_t +store_buffer_create (void *buf, size_t buf_len, int flags, + struct store **store) +{ + error_t err; + struct store_run run; + + run.start = 0; + run.length = buf_len; + + flags |= STORE_ENFORCED; /* Only uses local resources. */ + + err = + _store_create (&store_copy_class, + MACH_PORT_NULL, flags, 1, &run, 1, 0, store); + if (! err) + (*store)->hook = buf; + + return err; +} + +/* Open the copy store NAME -- which consists of another store-class name, a + ':', and a name for that store class to open -- and return the + corresponding store in STORE. CLASSES is used to select classes specified + by the type name; if it is 0, STORE_STD_CLASSES is used. */ +error_t +store_copy_open (const char *name, int flags, + const struct store_class *const *classes, + struct store **store) +{ + struct store *from; + error_t err = + store_typed_open (name, flags | STORE_HARD_READONLY, classes, &from); + + if (! err) + { + err = store_copy_create (from, flags, store); + if (err) + store_free (from); + } + + return err; +} |