summaryrefslogtreecommitdiff
path: root/libstore/gunzip.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2002-03-14 21:09:36 +0000
committerRoland McGrath <roland@gnu.org>2002-03-14 21:09:36 +0000
commit09b8c00be38115b1dfe151d1133d97518ea7f40a (patch)
tree7749d9dc12286a1330ae688efc4509317276cdd3 /libstore/gunzip.c
parent1da2660337a3f8cf79dd2c2d6cb8c30fa78ffa73 (diff)
2002-03-11 Roland McGrath <roland@frob.com>
* unzipstore.c: New file, broken out of bunzip2.c. * bunzip2.c: Most code moved to unzipstore.c, which we #include. (DO_UNZIP, UNZIP): New function, macro. * gunzip.c: Most code deleted, now in unzipstore.c, which we #include. (DO_UNZIP, UNZIP): New function, macro. * Makefile (DIST_FILES): New variable, list unzipstore.c here. 2002-02-08 Roland McGrath <roland@frob.com> * Makefile (store-types): New variable. (all): Depend on $(store-types:%=libstore_%.a). (libstore_%.so.$(hurd-version)): New pattern rule. ($(store-types:%=libstore_%.a): libstore_%.a): New static pattern rule to create `-lstore_TYPE' pseudo-objects (linker scripts) for each type. (libstore.so-LDLIBS): New variable, adds -ldl. (GUNZIP_OBJS, BUNZIP2_OBJS): New variables. (UNZIP_OBJS): Variable removed, replaced by those two. (OBJS): Update use. (libstore_gunzip.so.$(hurd-version)): Depend on PIC $(GUNZIP_OBJS). (libstore_bunzip2.so.$(hurd-version)): Depend on PIC $(BUNZIP2_OBJS). * unknown.c: Add STORE_STD_CLASS decl. * bunzip2.c: Likewise. * copy.c: Likewise. * device.c: Likewise. * file.c: Likewise. * gunzip.c: Likewise. * memobj.c: Likewise. * module.c: Likewise. * mvol.c: Likewise. * nbd.c: Likewise. * open.c: Likewise. * part.c: Likewise. * remap.c: Likewise. * stripe.c: Likewise. * stripe.c: Likewise. * task.c: Likewise. * typed.c: Likewise. * typed.c: Likewise. * unknown.c: Likewise. * url.c: Likewise. * zero.c: Likewise.
Diffstat (limited to 'libstore/gunzip.c')
-rw-r--r--libstore/gunzip.c244
1 files changed, 12 insertions, 232 deletions
diff --git a/libstore/gunzip.c b/libstore/gunzip.c
index 5ebfbb7a..3bff6ead 100644
--- a/libstore/gunzip.c
+++ b/libstore/gunzip.c
@@ -1,6 +1,6 @@
/* Decompressing store backend
- Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1999, 2002 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
This file is part of the GNU Hurd.
@@ -33,243 +33,23 @@
#undef file_t
#undef head
-#define IN_BUFFERING (256*1024)
-#define OUT_BUFFERING (512*1024)
-
-static struct mutex unzip_lock = MUTEX_INITIALIZER;
-
-/* Uncompress the contents of FROM, which should contain a valid gzip file,
- into memory, returning the result buffer in BUF & BUF_LEN. */
static error_t
-gunzip (struct store *from, void **buf, size_t *buf_len)
+DO_UNZIP (void)
{
/* Entry points to unzip engine. */
int get_method (int);
extern long int bytes_out;
- /* Callbacks from unzip for I/O and error interface. */
- extern int (*unzip_read) (char *buf, size_t maxread);
- extern void (*unzip_write) (const char *buf, size_t nwrite);
- extern void (*unzip_read_error) (void);
- extern void (*unzip_error) (const char *msg);
-
- /* How we return errors from our hook functions. */
- jmp_buf zerr_jmp_buf;
- error_t zerr;
-
- /* vm_alloced buffer for the input store. */
- void *in_buf = 0;
- size_t in_buf_len = 0;
- size_t in_buf_offs = 0; /* Offset of read point in IN_BUF. */
- off_t in_buf_addr = 0; /* Address in FROM of *next* IN_BUF. */
-
- /* Buffer input in units that are least IN_BUFFERING bytes, but are also a
- multiple of FROM's block size. */
- size_t in_addr_mask = ((1 << from->log2_block_size) - 1);
- size_t in_buffering = ((IN_BUFFERING + in_addr_mask) & ~in_addr_mask);
-
- /* Read at most MAXREAD (or 0 if eof) bytes into BUF from our current
- position in FROM. */
- int zread (char *buf, size_t maxread)
- {
- size_t did_read = 0;
-
- while (maxread > 0)
- {
- size_t left = in_buf_len - in_buf_offs;
-
- if (left > 0)
- /* Fill BUF with what we can from IN_BUF. */
- {
- if (left > maxread)
- left = maxread;
- bcopy (in_buf + in_buf_offs, buf, left);
- in_buf_offs += left;
- buf += left;
- maxread -= left;
- did_read += left;
- }
-
- /* Limit MAXREAD to the number of bytes left in the input. */
- if (maxread > (from->size - (in_buf_addr << from->log2_block_size)))
- maxread = from->size - (in_buf_addr << from->log2_block_size);
-
- if (maxread > 0)
- /* Have to fill IN_BUF again. */
- {
- void *new_in_buf = in_buf;
- size_t new_in_buf_len = in_buf_len;
-
- zerr = store_read (from, in_buf_addr, in_buffering,
- &new_in_buf, &new_in_buf_len);
- if (zerr)
- longjmp (zerr_jmp_buf, 1);
-
- in_buf_addr += (new_in_buf_len >> from->log2_block_size);
-
- if (new_in_buf != in_buf)
- {
- if (in_buf_len > 0)
- munmap (in_buf, in_buf_len);
- in_buf = new_in_buf;
- in_buf_len = new_in_buf_len;
- }
-
- in_buf_offs = 0;
- }
- }
- return did_read;
- }
-
- size_t out_buf_offs = 0; /* Position in the output buffer. */
-
- /* Write compress data to our output buffer. */
- void zwrite (const char *wbuf, size_t nwrite)
- {
- size_t old_buf_len = *buf_len;
-
- if (out_buf_offs + nwrite > old_buf_len)
- /* Have to grow the output buffer. */
- {
- void *old_buf = *buf;
- void *new_buf = old_buf + old_buf_len; /* First try. */
- size_t new_buf_len = round_page (old_buf_len + old_buf_len + nwrite);
-
- /* Try to grow the buffer. */
- zerr =
- vm_allocate (mach_task_self (),
- (vm_address_t *)&new_buf, new_buf_len - old_buf_len,
- 0);
- if (zerr)
- /* Can't do that, try to make a bigger buffer elsewhere. */
- {
- new_buf = mmap (0, new_buf_len, PROT_READ|PROT_WRITE,
- MAP_ANON, 0, 0);
- zerr = (new_buf == (void *) -1) ? errno : 0;
- if (zerr)
- longjmp (zerr_jmp_buf, 1);
-
- if (out_buf_offs > 0)
- /* Copy the old buffer into the start of the new & free it. */
- bcopy (old_buf, new_buf, out_buf_offs);
-
- munmap (old_buf, old_buf_len);
-
- *buf = new_buf;
- }
-
- *buf_len = new_buf_len;
- }
-
- bcopy (wbuf, *buf + out_buf_offs, nwrite);
- out_buf_offs += nwrite;
- }
-
- void zreaderr (void)
- {
- zerr = EIO;
- longjmp (zerr_jmp_buf, 1);
- }
- void zerror (const char *msg)
- {
- zerr = EINVAL;
- longjmp (zerr_jmp_buf, 2);
- }
-
- /* Try to guess a reasonable output buffer size. */
- *buf_len = round_page (from->size * 2);
- *buf = mmap (0, *buf_len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
- zerr = (*buf == (void *) -1) ? errno : 0;
- if (zerr)
- return zerr;
-
- mutex_lock (&unzip_lock);
-
- unzip_read = zread;
- unzip_write = zwrite;
- unzip_read_error = zreaderr;
- unzip_error = zerror;
-
- if (! setjmp (zerr_jmp_buf))
- {
- if (get_method (0) != 0)
- /* Not a happy gzip file. */
- zerr = EINVAL;
- else
- /* Matched gzip magic number. Ready to unzip.
- Set up the output stream and let 'er rip. */
- {
- /* Call the gunzip engine. */
- bytes_out = 0;
- unzip (17, 23); /* Arguments ignored. */
- zerr = 0;
- }
- }
-
- mutex_unlock (&unzip_lock);
-
- if (in_buf_len > 0)
- munmap (in_buf, in_buf_len);
-
- if (zerr)
- {
- if (*buf_len > 0)
- munmap (*buf, *buf_len);
- }
- else if (out_buf_offs < *buf_len)
- /* Trim the output buffer to be the right length. */
- {
- size_t end = round_page (out_buf_offs);
- if (end < *buf_len)
- munmap (*buf + end, *buf_len - end);
- *buf_len = out_buf_offs;
- }
-
- return zerr;
-}
-
-/* Return a new store in STORE which contains a snapshot of the uncompressed
- contents of the store FROM; FROM is consumed. */
-error_t
-store_gunzip_create (struct store *from, int flags, struct store **store)
-{
- void *buf;
- size_t buf_len;
- error_t err = gunzip (from, &buf, &buf_len);
-
- if (! err)
- {
- err = store_buffer_create (buf, buf_len, flags, store);
- if (err)
- munmap (buf, buf_len);
- else
- store_free (from);
- }
-
- return err;
-}
-
-/* Open the gunzip 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_gunzip_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_gunzip_create (from, flags, store);
- if (err)
- store_free (from);
- }
+ if (get_method (0) != 0)
+ /* Not a happy gzip file. */
+ return EINVAL;
- return err;
+ /* Matched gzip magic number. Ready to unzip.
+ Set up the output stream and let 'er rip. */
+ bytes_out = 0;
+ unzip (17, 23); /* Arguments ignored. */
+ return 0;
}
-const struct store_class
-store_gunzip_class = { -1, "gunzip", open: store_gunzip_open };
+#define UNZIP gunzip
+#include "unzipstore.c"