summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src/zlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cvs/src/zlib.c')
-rw-r--r--contrib/cvs/src/zlib.c760
1 files changed, 0 insertions, 760 deletions
diff --git a/contrib/cvs/src/zlib.c b/contrib/cvs/src/zlib.c
deleted file mode 100644
index 46ed0e6..0000000
--- a/contrib/cvs/src/zlib.c
+++ /dev/null
@@ -1,760 +0,0 @@
-/* zlib.c --- interface to the zlib compression library
- Ian Lance Taylor <ian@cygnus.com>
-
- This file is part of GNU CVS.
-
- GNU CVS 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.
-
- This program 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. */
-
-/* The routines in this file are the interface between the CVS
- client/server support and the zlib compression library. */
-
-#include <assert.h>
-#include "cvs.h"
-#include "buffer.h"
-
-#if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
-
-#include "zlib.h"
-
-/* OS/2 doesn't have EIO. FIXME: this whole notion of turning
- a different error into EIO strikes me as pretty dubious. */
-#if !defined (EIO)
-#define EIO EBADPOS
-#endif
-
-/* The compression interface is built upon the buffer data structure.
- We provide a buffer type which compresses or decompresses the data
- which passes through it. An input buffer decompresses the data
- read from an underlying buffer, and an output buffer compresses the
- data before writing it to an underlying buffer. */
-
-/* This structure is the closure field of the buffer. */
-
-struct compress_buffer
-{
- /* The underlying buffer. */
- struct buffer *buf;
- /* The compression information. */
- z_stream zstr;
-};
-
-static void compress_error PROTO((int, int, z_stream *, const char *));
-static int compress_buffer_input PROTO((void *, char *, int, int, int *));
-static int compress_buffer_output PROTO((void *, const char *, int, int *));
-static int compress_buffer_flush PROTO((void *));
-static int compress_buffer_block PROTO((void *, int));
-static int compress_buffer_shutdown_input PROTO((struct buffer *));
-static int compress_buffer_shutdown_output PROTO((struct buffer *));
-
-/* Report an error from one of the zlib functions. */
-
-static void
-compress_error (status, zstatus, zstr, msg)
- int status;
- int zstatus;
- z_stream *zstr;
- const char *msg;
-{
- int hold_errno;
- const char *zmsg;
- char buf[100];
-
- hold_errno = errno;
-
- zmsg = zstr->msg;
- if (zmsg == NULL)
- {
- sprintf (buf, "error %d", zstatus);
- zmsg = buf;
- }
-
- error (status,
- zstatus == Z_ERRNO ? hold_errno : 0,
- "%s: %s", msg, zmsg);
-}
-
-/* Create a compression buffer. */
-
-struct buffer *
-compress_buffer_initialize (buf, input, level, memory)
- struct buffer *buf;
- int input;
- int level;
- void (*memory) PROTO((struct buffer *));
-{
- struct compress_buffer *n;
- int zstatus;
-
- n = (struct compress_buffer *) xmalloc (sizeof *n);
- memset (n, 0, sizeof *n);
-
- n->buf = buf;
-
- if (input)
- zstatus = inflateInit (&n->zstr);
- else
- zstatus = deflateInit (&n->zstr, level);
- if (zstatus != Z_OK)
- compress_error (1, zstatus, &n->zstr, "compression initialization");
-
- /* There may already be data buffered on BUF. For an output
- buffer, this is OK, because these routines will just use the
- buffer routines to append data to the (uncompressed) data
- already on BUF. An input buffer expects to handle a single
- buffer_data of buffered input to be uncompressed, so that is OK
- provided there is only one buffer. At present that is all
- there ever will be; if this changes, compress_buffer_input must
- be modified to handle multiple input buffers. */
- assert (! input || buf->data == NULL || buf->data->next == NULL);
-
- return buf_initialize (input ? compress_buffer_input : NULL,
- input ? NULL : compress_buffer_output,
- input ? NULL : compress_buffer_flush,
- compress_buffer_block,
- (input
- ? compress_buffer_shutdown_input
- : compress_buffer_shutdown_output),
- memory,
- n);
-}
-
-/* Input data from a compression buffer. */
-
-static int
-compress_buffer_input (closure, data, need, size, got)
- void *closure;
- char *data;
- int need;
- int size;
- int *got;
-{
- struct compress_buffer *cb = (struct compress_buffer *) closure;
- struct buffer_data *bd;
-
- if (cb->buf->input == NULL)
- abort ();
-
- /* We use a single buffer_data structure to buffer up data which
- the z_stream structure won't use yet. We can safely store this
- on cb->buf->data, because we never call the buffer routines on
- cb->buf; we only call the buffer input routine, since that
- gives us the semantics we want. As noted in
- compress_buffer_initialize, the buffer_data structure may
- already exist, and hold data which was already read and
- buffered before the decompression began. */
- bd = cb->buf->data;
- if (bd == NULL)
- {
- bd = ((struct buffer_data *) xmalloc (sizeof (struct buffer_data)));
- if (bd == NULL)
- return -2;
- bd->text = (char *) xmalloc (BUFFER_DATA_SIZE);
- if (bd->text == NULL)
- {
- free (bd);
- return -2;
- }
- bd->bufp = bd->text;
- bd->size = 0;
- cb->buf->data = bd;
- }
-
- cb->zstr.avail_out = size;
- cb->zstr.next_out = (Bytef *) data;
-
- while (1)
- {
- int zstatus, sofar, status, nread;
-
- /* First try to inflate any data we already have buffered up.
- This is useful even if we don't have any buffered data,
- because there may be data buffered inside the z_stream
- structure. */
-
- cb->zstr.avail_in = bd->size;
- cb->zstr.next_in = (Bytef *) bd->bufp;
-
- do
- {
- zstatus = inflate (&cb->zstr, Z_NO_FLUSH);
- if (zstatus == Z_STREAM_END)
- break;
- if (zstatus != Z_OK && zstatus != Z_BUF_ERROR)
- {
- compress_error (0, zstatus, &cb->zstr, "inflate");
- return EIO;
- }
- } while (cb->zstr.avail_in > 0
- && cb->zstr.avail_out > 0);
-
- bd->size = cb->zstr.avail_in;
- bd->bufp = (char *) cb->zstr.next_in;
-
- if (zstatus == Z_STREAM_END)
- return -1;
-
- /* If we have obtained NEED bytes, then return, unless NEED is
- zero and we haven't obtained anything at all. If NEED is
- zero, we will keep reading from the underlying buffer until
- we either can't read anything, or we have managed to
- inflate at least one byte. */
- sofar = size - cb->zstr.avail_out;
- if (sofar > 0 && sofar >= need)
- break;
-
- /* All our buffered data should have been processed at this
- point. */
- assert (bd->size == 0);
-
- /* This will work well in the server, because this call will
- do an unblocked read and fetch all the available data. In
- the client, this will read a single byte from the stdio
- stream, which will cause us to call inflate once per byte.
- It would be more efficient if we could make a call which
- would fetch all the available bytes, and at least one byte. */
-
- status = (*cb->buf->input) (cb->buf->closure, bd->text,
- need > 0 ? 1 : 0,
- BUFFER_DATA_SIZE, &nread);
- if (status != 0)
- return status;
-
- /* If we didn't read anything, then presumably the buffer is
- in nonblocking mode, and we should just get out now with
- whatever we've inflated. */
- if (nread == 0)
- {
- assert (need == 0);
- break;
- }
-
- bd->bufp = bd->text;
- bd->size = nread;
- }
-
- *got = size - cb->zstr.avail_out;
-
- return 0;
-}
-
-/* Output data to a compression buffer. */
-
-static int
-compress_buffer_output (closure, data, have, wrote)
- void *closure;
- const char *data;
- int have;
- int *wrote;
-{
- struct compress_buffer *cb = (struct compress_buffer *) closure;
-
- cb->zstr.avail_in = have;
- cb->zstr.next_in = (unsigned char *) data;
-
- while (cb->zstr.avail_in > 0)
- {
- char buffer[BUFFER_DATA_SIZE];
- int zstatus;
-
- cb->zstr.avail_out = BUFFER_DATA_SIZE;
- cb->zstr.next_out = (unsigned char *) buffer;
-
- zstatus = deflate (&cb->zstr, Z_NO_FLUSH);
- if (zstatus != Z_OK)
- {
- compress_error (0, zstatus, &cb->zstr, "deflate");
- return EIO;
- }
-
- if (cb->zstr.avail_out != BUFFER_DATA_SIZE)
- buf_output (cb->buf, buffer,
- BUFFER_DATA_SIZE - cb->zstr.avail_out);
- }
-
- *wrote = have;
-
- /* We will only be here because buf_send_output was called on the
- compression buffer. That means that we should now call
- buf_send_output on the underlying buffer. */
- return buf_send_output (cb->buf);
-}
-
-/* Flush a compression buffer. */
-
-static int
-compress_buffer_flush (closure)
- void *closure;
-{
- struct compress_buffer *cb = (struct compress_buffer *) closure;
-
- cb->zstr.avail_in = 0;
- cb->zstr.next_in = NULL;
-
- while (1)
- {
- char buffer[BUFFER_DATA_SIZE];
- int zstatus;
-
- cb->zstr.avail_out = BUFFER_DATA_SIZE;
- cb->zstr.next_out = (unsigned char *) buffer;
-
- zstatus = deflate (&cb->zstr, Z_SYNC_FLUSH);
-
- /* The deflate function will return Z_BUF_ERROR if it can't do
- anything, which in this case means that all data has been
- flushed. */
- if (zstatus == Z_BUF_ERROR)
- break;
-
- if (zstatus != Z_OK)
- {
- compress_error (0, zstatus, &cb->zstr, "deflate flush");
- return EIO;
- }
-
- if (cb->zstr.avail_out != BUFFER_DATA_SIZE)
- buf_output (cb->buf, buffer,
- BUFFER_DATA_SIZE - cb->zstr.avail_out);
-
- /* If the deflate function did not fill the output buffer,
- then all data has been flushed. */
- if (cb->zstr.avail_out > 0)
- break;
- }
-
- /* Now flush the underlying buffer. Note that if the original
- call to buf_flush passed 1 for the BLOCK argument, then the
- buffer will already have been set into blocking mode, so we
- should always pass 0 here. */
- return buf_flush (cb->buf, 0);
-}
-
-/* The block routine for a compression buffer. */
-
-static int
-compress_buffer_block (closure, block)
- void *closure;
- int block;
-{
- struct compress_buffer *cb = (struct compress_buffer *) closure;
-
- if (block)
- return set_block (cb->buf);
- else
- return set_nonblock (cb->buf);
-}
-
-/* Shut down an input buffer. */
-
-static int
-compress_buffer_shutdown_input (buf)
- struct buffer *buf;
-{
- struct compress_buffer *cb = (struct compress_buffer *) buf->closure;
- int zstatus;
-
- /* Don't make any attempt to pick up trailing data since we are shutting
- * down. If the client doesn't know we are shutting down, we might not
- * see the EOF we are expecting.
- */
-
- zstatus = inflateEnd (&cb->zstr);
- if (zstatus != Z_OK)
- {
- compress_error (0, zstatus, &cb->zstr, "inflateEnd");
- return EIO;
- }
-
- return buf_shutdown (cb->buf);
-}
-
-/* Shut down an output buffer. */
-
-static int
-compress_buffer_shutdown_output (buf)
- struct buffer *buf;
-{
- struct compress_buffer *cb = (struct compress_buffer *) buf->closure;
- int zstatus, status;
-
- do
- {
- char buffer[BUFFER_DATA_SIZE];
-
- cb->zstr.avail_out = BUFFER_DATA_SIZE;
- cb->zstr.next_out = (unsigned char *) buffer;
-
- zstatus = deflate (&cb->zstr, Z_FINISH);
- if (zstatus != Z_OK && zstatus != Z_STREAM_END)
- {
- compress_error (0, zstatus, &cb->zstr, "deflate finish");
- return EIO;
- }
-
- if (cb->zstr.avail_out != BUFFER_DATA_SIZE)
- buf_output (cb->buf, buffer,
- BUFFER_DATA_SIZE - cb->zstr.avail_out);
- } while (zstatus != Z_STREAM_END);
-
- zstatus = deflateEnd (&cb->zstr);
- if (zstatus != Z_OK)
- {
- compress_error (0, zstatus, &cb->zstr, "deflateEnd");
- return EIO;
- }
-
- status = buf_flush (cb->buf, 1);
- if (status != 0)
- return status;
-
- return buf_shutdown (cb->buf);
-}
-
-
-
-/* Here is our librarified gzip implementation. It is very minimal
- but attempts to be RFC1952 compliant. */
-
-/* GZIP ID byte values */
-#define GZIP_ID1 31
-#define GZIP_ID2 139
-
-/* Compression methods */
-#define GZIP_CDEFLATE 8
-
-/* Flags */
-#define GZIP_FTEXT 1
-#define GZIP_FHCRC 2
-#define GZIP_FEXTRA 4
-#define GZIP_FNAME 8
-#define GZIP_FCOMMENT 16
-
-/* BUF should contain SIZE bytes of gzipped data (RFC1952/RFC1951).
- We are to uncompress the data and write the result to the file
- descriptor FD. If something goes wrong, give a nonfatal error message
- mentioning FULLNAME as the name of the file for FD. Return 1 if
- it is an error we can't recover from. */
-
-int
-gunzip_and_write (fd, fullname, buf, size)
- int fd;
- char *fullname;
- unsigned char *buf;
- size_t size;
-{
- size_t pos;
- z_stream zstr;
- int zstatus;
- unsigned char outbuf[32768];
- unsigned long crc;
-
- if (size < 10)
- {
- error (0, 0, "gzipped data too small - lacks complete header");
- return 1;
- }
- if (buf[0] != GZIP_ID1 || buf[1] != GZIP_ID2)
- {
- error (0, 0, "gzipped data does not start with gzip identification");
- return 1;
- }
- if (buf[2] != GZIP_CDEFLATE)
- {
- error (0, 0, "only the deflate compression method is supported");
- return 1;
- }
-
- /* Skip over the fixed header, and then skip any of the variable-length
- fields. As we skip each field, we keep pos <= size. The checks
- on positions and lengths are really checks for malformed or
- incomplete gzip data. */
- pos = 10;
- if (buf[3] & GZIP_FEXTRA)
- {
- if (pos + 2 >= size)
- {
- error (0, 0, "%s lacks proper gzip XLEN field", fullname);
- return 1;
- }
- pos += buf[pos] + (buf[pos + 1] << 8) + 2;
- if (pos > size)
- {
- error (0, 0, "%s lacks proper gzip \"extra field\"", fullname);
- return 1;
- }
-
- }
- if (buf[3] & GZIP_FNAME)
- {
- unsigned char *p = memchr(buf + pos, '\0', size - pos);
- if (p == NULL)
- {
- error (0, 0, "%s has bad gzip filename field", fullname);
- return 1;
- }
- pos = p - buf + 1;
- }
- if (buf[3] & GZIP_FCOMMENT)
- {
- unsigned char *p = memchr(buf + pos, '\0', size - pos);
- if (p == NULL)
- {
- error (0, 0, "%s has bad gzip comment field", fullname);
- return 1;
- }
- pos = p - buf + 1;
- }
- if (buf[3] & GZIP_FHCRC)
- {
- pos += 2;
- if (pos > size)
- {
- error (0, 0, "%s has bad gzip CRC16 field", fullname);
- return 1;
- }
- }
-
- /* There could be no data to decompress - check and short circuit. */
- if (pos >= size)
- {
- error (0, 0, "gzip data incomplete for %s (no data)", fullname);
- return 1;
- }
-
- memset (&zstr, 0, sizeof zstr);
- /* Passing a negative argument tells zlib not to look for a zlib
- (RFC1950) header. This is an undocumented feature; I suppose if
- we wanted to be anal we could synthesize a header instead,
- but why bother? */
- zstatus = inflateInit2 (&zstr, -15);
-
- if (zstatus != Z_OK)
- compress_error (1, zstatus, &zstr, fullname);
-
- /* I don't see why we should have to include the 8 byte trailer in
- avail_in. But I see that zlib/gzio.c does, and it seemed to fix
- a fairly rare bug in which we'd get a Z_BUF_ERROR for no obvious
- reason. */
- zstr.avail_in = size - pos;
- zstr.next_in = buf + pos;
-
- crc = crc32 (0, NULL, 0);
-
- do
- {
- zstr.avail_out = sizeof (outbuf);
- zstr.next_out = outbuf;
- zstatus = inflate (&zstr, Z_NO_FLUSH);
- if (zstatus != Z_STREAM_END && zstatus != Z_OK)
- {
- compress_error (0, zstatus, &zstr, fullname);
- return 1;
- }
- if (write (fd, outbuf, sizeof (outbuf) - zstr.avail_out) < 0)
- {
- error (0, errno, "writing decompressed file %s", fullname);
- return 1;
- }
- crc = crc32 (crc, outbuf, sizeof (outbuf) - zstr.avail_out);
- } while (zstatus != Z_STREAM_END);
- zstatus = inflateEnd (&zstr);
- if (zstatus != Z_OK)
- compress_error (0, zstatus, &zstr, fullname);
-
- /* Check that there is still 8 trailer bytes remaining (CRC32
- and ISIZE). Check total decomp. data, plus header len (pos)
- against input buffer total size. */
- pos += zstr.total_in;
- if (size - pos != 8)
- {
- error (0, 0, "gzip data incomplete for %s (no trailer)", fullname);
- return 1;
- }
-
- if (crc != ((unsigned long)buf[pos]
- + ((unsigned long)buf[pos + 1] << 8)
- + ((unsigned long)buf[pos + 2] << 16)
- + ((unsigned long)buf[pos + 3] << 24)))
- {
- error (0, 0, "CRC error uncompressing %s", fullname);
- return 1;
- }
-
- if (zstr.total_out != ((unsigned long)buf[pos + 4]
- + ((unsigned long)buf[pos + 5] << 8)
- + ((unsigned long)buf[pos + 6] << 16)
- + ((unsigned long)buf[pos + 7] << 24)))
- {
- error (0, 0, "invalid length uncompressing %s", fullname);
- return 1;
- }
-
- return 0;
-}
-
-/* Read all of FD and put the gzipped data (RFC1952/RFC1951) into *BUF,
- replacing previous contents of *BUF. *BUF is xmalloc'd and *SIZE is
- its allocated size. Put the actual number of bytes of data in
- *LEN. If something goes wrong, give a nonfatal error mentioning
- FULLNAME as the name of the file for FD, and return 1 if we can't
- recover from it). LEVEL is the compression level (1-9). */
-
-int
-read_and_gzip (fd, fullname, buf, size, len, level)
- int fd;
- const char *fullname;
- unsigned char **buf;
- size_t *size;
- size_t *len;
- int level;
-{
- z_stream zstr;
- int zstatus;
- unsigned char inbuf[8192];
- int nread;
- unsigned long crc;
-
- if (*size < 1024)
- {
- unsigned char *newbuf;
-
- *size = 1024;
- newbuf = xrealloc (*buf, *size);
- if (newbuf == NULL)
- {
- error (0, 0, "out of memory");
- return 1;
- }
- *buf = newbuf;
- }
- (*buf)[0] = GZIP_ID1;
- (*buf)[1] = GZIP_ID2;
- (*buf)[2] = GZIP_CDEFLATE;
- (*buf)[3] = 0;
- (*buf)[4] = (*buf)[5] = (*buf)[6] = (*buf)[7] = 0;
- /* Could set this based on level, but why bother? */
- (*buf)[8] = 0;
- (*buf)[9] = 255;
-
- memset (&zstr, 0, sizeof zstr);
- zstatus = deflateInit2 (&zstr, level, Z_DEFLATED, -15, 8,
- Z_DEFAULT_STRATEGY);
- crc = crc32 (0, NULL, 0);
- if (zstatus != Z_OK)
- {
- compress_error (0, zstatus, &zstr, fullname);
- return 1;
- }
-
- /* Adjust for 10-byte output header (filled in above) */
- zstr.total_out = 10;
- zstr.avail_out = *size - 10;
- zstr.next_out = *buf + 10;
-
- while (1)
- {
- int finish = 0;
-
- nread = read (fd, inbuf, sizeof inbuf);
- if (nread < 0)
- {
- error (0, errno, "cannot read %s", fullname);
- return 1;
- }
- else if (nread == 0)
- /* End of file. */
- finish = 1;
- crc = crc32 (crc, inbuf, nread);
- zstr.next_in = inbuf;
- zstr.avail_in = nread;
-
- do
- {
- /* I don't see this documented anywhere, but deflate seems
- to tend to dump core sometimes if we pass it Z_FINISH and
- a small (e.g. 2147 byte) avail_out. So we insist on at
- least 4096 bytes (that is what zlib/gzio.c uses). */
-
- if (zstr.avail_out < 4096)
- {
- unsigned char *newbuf;
-
- assert(zstr.avail_out + zstr.total_out == *size);
- assert(zstr.next_out == *buf + zstr.total_out);
- *size *= 2;
- newbuf = xrealloc (*buf, *size);
- if (newbuf == NULL)
- {
- error (0, 0, "out of memory");
- return 1;
- }
- *buf = newbuf;
- zstr.next_out = *buf + zstr.total_out;
- zstr.avail_out = *size - zstr.total_out;
- assert(zstr.avail_out + zstr.total_out == *size);
- assert(zstr.next_out == *buf + zstr.total_out);
- }
-
- zstatus = deflate (&zstr, finish ? Z_FINISH : 0);
- if (zstatus == Z_STREAM_END)
- goto done;
- else if (zstatus != Z_OK)
- compress_error (0, zstatus, &zstr, fullname);
- } while (zstr.avail_out == 0);
- }
- done:
- /* Need to add the CRC information (8 bytes)
- to the end of the gzip'd output.
- Ensure there is enough space in the output buffer
- to do so. */
- if (zstr.avail_out < 8)
- {
- unsigned char *newbuf;
-
- assert(zstr.avail_out + zstr.total_out == *size);
- assert(zstr.next_out == *buf + zstr.total_out);
- *size += 8 - zstr.avail_out;
- newbuf = realloc (*buf, *size);
- if (newbuf == NULL)
- {
- error (0, 0, "out of memory");
- return 1;
- }
- *buf = newbuf;
- zstr.next_out = *buf + zstr.total_out;
- zstr.avail_out = *size - zstr.total_out;
- assert(zstr.avail_out + zstr.total_out == *size);
- assert(zstr.next_out == *buf + zstr.total_out);
- }
- *zstr.next_out++ = (unsigned char)(crc & 0xff);
- *zstr.next_out++ = (unsigned char)((crc >> 8) & 0xff);
- *zstr.next_out++ = (unsigned char)((crc >> 16) & 0xff);
- *zstr.next_out++ = (unsigned char)((crc >> 24) & 0xff);
-
- *zstr.next_out++ = (unsigned char)(zstr.total_in & 0xff);
- *zstr.next_out++ = (unsigned char)((zstr.total_in >> 8) & 0xff);
- *zstr.next_out++ = (unsigned char)((zstr.total_in >> 16) & 0xff);
- *zstr.next_out++ = (unsigned char)((zstr.total_in >> 24) & 0xff);
-
- zstr.total_out += 8;
- zstr.avail_out -= 8;
- assert(zstr.avail_out + zstr.total_out == *size);
- assert(zstr.next_out == *buf + zstr.total_out);
-
- *len = zstr.total_out;
-
- zstatus = deflateEnd (&zstr);
- if (zstatus != Z_OK)
- compress_error (0, zstatus, &zstr, fullname);
-
- return 0;
-}
-#endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
OpenPOWER on IntegriCloud