summaryrefslogtreecommitdiff
path: root/libstore/copy.c
diff options
context:
space:
mode:
Diffstat (limited to 'libstore/copy.c')
-rw-r--r--libstore/copy.c237
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;
+}