125839Speter/* zlib.c --- interface to the zlib compression library
225839Speter   Ian Lance Taylor <ian@cygnus.com>
325839Speter
425839Speter   This file is part of GNU CVS.
525839Speter
625839Speter   GNU CVS is free software; you can redistribute it and/or modify it
725839Speter   under the terms of the GNU General Public License as published by the
825839Speter   Free Software Foundation; either version 2, or (at your option) any
925839Speter   later version.
1025839Speter
1125839Speter   This program is distributed in the hope that it will be useful,
1225839Speter   but WITHOUT ANY WARRANTY; without even the implied warranty of
1325839Speter   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1425839Speter   GNU General Public License for more details.  */
1525839Speter
1625839Speter/* The routines in this file are the interface between the CVS
1725839Speter   client/server support and the zlib compression library.  */
1825839Speter
1925839Speter#include <assert.h>
2025839Speter#include "cvs.h"
2125839Speter#include "buffer.h"
2225839Speter
2325839Speter#if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
2425839Speter
2525839Speter#include "zlib.h"
2625839Speter
2725839Speter/* OS/2 doesn't have EIO.  FIXME: this whole notion of turning
2825839Speter   a different error into EIO strikes me as pretty dubious.  */
2925839Speter#if !defined (EIO)
3025839Speter#define EIO EBADPOS
3125839Speter#endif
3225839Speter
3325839Speter/* The compression interface is built upon the buffer data structure.
3425839Speter   We provide a buffer type which compresses or decompresses the data
3525839Speter   which passes through it.  An input buffer decompresses the data
3625839Speter   read from an underlying buffer, and an output buffer compresses the
3725839Speter   data before writing it to an underlying buffer.  */
3825839Speter
3925839Speter/* This structure is the closure field of the buffer.  */
4025839Speter
4125839Speterstruct compress_buffer
4225839Speter{
4325839Speter    /* The underlying buffer.  */
4425839Speter    struct buffer *buf;
4525839Speter    /* The compression information.  */
4625839Speter    z_stream zstr;
4725839Speter};
4825839Speter
4925839Speterstatic void compress_error PROTO((int, int, z_stream *, const char *));
5025839Speterstatic int compress_buffer_input PROTO((void *, char *, int, int, int *));
5125839Speterstatic int compress_buffer_output PROTO((void *, const char *, int, int *));
5225839Speterstatic int compress_buffer_flush PROTO((void *));
5325839Speterstatic int compress_buffer_block PROTO((void *, int));
54102840Speterstatic int compress_buffer_shutdown_input PROTO((struct buffer *));
55102840Speterstatic int compress_buffer_shutdown_output PROTO((struct buffer *));
5625839Speter
5725839Speter/* Report an error from one of the zlib functions.  */
5825839Speter
5925839Speterstatic void
6025839Spetercompress_error (status, zstatus, zstr, msg)
6125839Speter     int status;
6225839Speter     int zstatus;
6325839Speter     z_stream *zstr;
6425839Speter     const char *msg;
6525839Speter{
6625839Speter    int hold_errno;
6725839Speter    const char *zmsg;
6825839Speter    char buf[100];
6925839Speter
7025839Speter    hold_errno = errno;
7125839Speter
7225839Speter    zmsg = zstr->msg;
7325839Speter    if (zmsg == NULL)
7425839Speter    {
7525839Speter        sprintf (buf, "error %d", zstatus);
7625839Speter	zmsg = buf;
7725839Speter    }
7825839Speter
7925839Speter    error (status,
8025839Speter	   zstatus == Z_ERRNO ? hold_errno : 0,
8125839Speter	   "%s: %s", msg, zmsg);
8225839Speter}
8325839Speter
8425839Speter/* Create a compression buffer.  */
8525839Speter
8625839Speterstruct buffer *
8725839Spetercompress_buffer_initialize (buf, input, level, memory)
8825839Speter     struct buffer *buf;
8925839Speter     int input;
9025839Speter     int level;
9125839Speter     void (*memory) PROTO((struct buffer *));
9225839Speter{
9325839Speter    struct compress_buffer *n;
9425839Speter    int zstatus;
9525839Speter
9625839Speter    n = (struct compress_buffer *) xmalloc (sizeof *n);
9725839Speter    memset (n, 0, sizeof *n);
9825839Speter
9925839Speter    n->buf = buf;
10025839Speter
10125839Speter    if (input)
10225839Speter	zstatus = inflateInit (&n->zstr);
10325839Speter    else
10425839Speter	zstatus = deflateInit (&n->zstr, level);
10525839Speter    if (zstatus != Z_OK)
10625839Speter	compress_error (1, zstatus, &n->zstr, "compression initialization");
10725839Speter
10825839Speter    /* There may already be data buffered on BUF.  For an output
10925839Speter       buffer, this is OK, because these routines will just use the
11025839Speter       buffer routines to append data to the (uncompressed) data
11125839Speter       already on BUF.  An input buffer expects to handle a single
11225839Speter       buffer_data of buffered input to be uncompressed, so that is OK
11325839Speter       provided there is only one buffer.  At present that is all
11425839Speter       there ever will be; if this changes, compress_buffer_input must
11525839Speter       be modified to handle multiple input buffers.  */
11625839Speter    assert (! input || buf->data == NULL || buf->data->next == NULL);
11725839Speter
11825839Speter    return buf_initialize (input ? compress_buffer_input : NULL,
11925839Speter			   input ? NULL : compress_buffer_output,
12025839Speter			   input ? NULL : compress_buffer_flush,
12125839Speter			   compress_buffer_block,
12225839Speter			   (input
12325839Speter			    ? compress_buffer_shutdown_input
12425839Speter			    : compress_buffer_shutdown_output),
12525839Speter			   memory,
12625839Speter			   n);
12725839Speter}
12825839Speter
12925839Speter/* Input data from a compression buffer.  */
13025839Speter
13125839Speterstatic int
13225839Spetercompress_buffer_input (closure, data, need, size, got)
13325839Speter     void *closure;
13425839Speter     char *data;
13525839Speter     int need;
13625839Speter     int size;
13725839Speter     int *got;
13825839Speter{
13925839Speter    struct compress_buffer *cb = (struct compress_buffer *) closure;
14025839Speter    struct buffer_data *bd;
14125839Speter
14225839Speter    if (cb->buf->input == NULL)
14325839Speter	abort ();
14425839Speter
14525839Speter    /* We use a single buffer_data structure to buffer up data which
14625839Speter       the z_stream structure won't use yet.  We can safely store this
14725839Speter       on cb->buf->data, because we never call the buffer routines on
14825839Speter       cb->buf; we only call the buffer input routine, since that
14925839Speter       gives us the semantics we want.  As noted in
15025839Speter       compress_buffer_initialize, the buffer_data structure may
15125839Speter       already exist, and hold data which was already read and
15225839Speter       buffered before the decompression began.  */
15325839Speter    bd = cb->buf->data;
15425839Speter    if (bd == NULL)
15525839Speter    {
156109655Speter	bd = ((struct buffer_data *) xmalloc (sizeof (struct buffer_data)));
15725839Speter	if (bd == NULL)
15825839Speter	    return -2;
159109655Speter	bd->text = (char *) xmalloc (BUFFER_DATA_SIZE);
16025839Speter	if (bd->text == NULL)
16125839Speter	{
16225839Speter	    free (bd);
16325839Speter	    return -2;
16425839Speter	}
16525839Speter	bd->bufp = bd->text;
16625839Speter	bd->size = 0;
16725839Speter	cb->buf->data = bd;
16825839Speter    }
16925839Speter
17025839Speter    cb->zstr.avail_out = size;
17125839Speter    cb->zstr.next_out = (Bytef *) data;
17225839Speter
17325839Speter    while (1)
17425839Speter    {
17525839Speter	int zstatus, sofar, status, nread;
17625839Speter
17725839Speter	/* First try to inflate any data we already have buffered up.
17825839Speter	   This is useful even if we don't have any buffered data,
17925839Speter	   because there may be data buffered inside the z_stream
18025839Speter	   structure.  */
18125839Speter
18225839Speter	cb->zstr.avail_in = bd->size;
18325839Speter	cb->zstr.next_in = (Bytef *) bd->bufp;
18425839Speter
18525839Speter	do
18625839Speter	{
18725839Speter	    zstatus = inflate (&cb->zstr, Z_NO_FLUSH);
18825839Speter	    if (zstatus == Z_STREAM_END)
18925839Speter		break;
19025839Speter	    if (zstatus != Z_OK && zstatus != Z_BUF_ERROR)
19125839Speter	    {
19225839Speter		compress_error (0, zstatus, &cb->zstr, "inflate");
19325839Speter		return EIO;
19425839Speter	    }
19525839Speter	} while (cb->zstr.avail_in > 0
19625839Speter		 && cb->zstr.avail_out > 0);
19725839Speter
19825839Speter	bd->size = cb->zstr.avail_in;
19925839Speter	bd->bufp = (char *) cb->zstr.next_in;
20025839Speter
20125839Speter	if (zstatus == Z_STREAM_END)
20225839Speter	    return -1;
20325839Speter
20425839Speter	/* If we have obtained NEED bytes, then return, unless NEED is
20525839Speter           zero and we haven't obtained anything at all.  If NEED is
20625839Speter           zero, we will keep reading from the underlying buffer until
20725839Speter           we either can't read anything, or we have managed to
20825839Speter           inflate at least one byte.  */
20925839Speter	sofar = size - cb->zstr.avail_out;
21025839Speter	if (sofar > 0 && sofar >= need)
21125839Speter	    break;
21225839Speter
21325839Speter	/* All our buffered data should have been processed at this
21425839Speter           point.  */
21525839Speter	assert (bd->size == 0);
21625839Speter
21725839Speter	/* This will work well in the server, because this call will
21825839Speter	   do an unblocked read and fetch all the available data.  In
21925839Speter	   the client, this will read a single byte from the stdio
22025839Speter	   stream, which will cause us to call inflate once per byte.
22125839Speter	   It would be more efficient if we could make a call which
22225839Speter	   would fetch all the available bytes, and at least one byte.  */
22325839Speter
22425839Speter	status = (*cb->buf->input) (cb->buf->closure, bd->text,
22525839Speter				    need > 0 ? 1 : 0,
22625839Speter				    BUFFER_DATA_SIZE, &nread);
22725839Speter	if (status != 0)
22825839Speter	    return status;
22925839Speter
23025839Speter	/* If we didn't read anything, then presumably the buffer is
23125839Speter           in nonblocking mode, and we should just get out now with
23225839Speter           whatever we've inflated.  */
23325839Speter	if (nread == 0)
23425839Speter	{
23525839Speter	    assert (need == 0);
23625839Speter	    break;
23725839Speter	}
23825839Speter
23925839Speter	bd->bufp = bd->text;
24025839Speter	bd->size = nread;
24125839Speter    }
24225839Speter
24325839Speter    *got = size - cb->zstr.avail_out;
24425839Speter
24525839Speter    return 0;
24625839Speter}
24725839Speter
24825839Speter/* Output data to a compression buffer.  */
24925839Speter
25025839Speterstatic int
25125839Spetercompress_buffer_output (closure, data, have, wrote)
25225839Speter     void *closure;
25325839Speter     const char *data;
25425839Speter     int have;
25525839Speter     int *wrote;
25625839Speter{
25725839Speter    struct compress_buffer *cb = (struct compress_buffer *) closure;
25825839Speter
25925839Speter    cb->zstr.avail_in = have;
26025839Speter    cb->zstr.next_in = (unsigned char *) data;
26125839Speter
26225839Speter    while (cb->zstr.avail_in > 0)
26325839Speter    {
26425839Speter	char buffer[BUFFER_DATA_SIZE];
26525839Speter	int zstatus;
26625839Speter
26725839Speter	cb->zstr.avail_out = BUFFER_DATA_SIZE;
26825839Speter	cb->zstr.next_out = (unsigned char *) buffer;
26925839Speter
27025839Speter	zstatus = deflate (&cb->zstr, Z_NO_FLUSH);
27125839Speter	if (zstatus != Z_OK)
27225839Speter	{
27325839Speter	    compress_error (0, zstatus, &cb->zstr, "deflate");
27425839Speter	    return EIO;
27525839Speter	}
27625839Speter
27725839Speter	if (cb->zstr.avail_out != BUFFER_DATA_SIZE)
27825839Speter	    buf_output (cb->buf, buffer,
27925839Speter			BUFFER_DATA_SIZE - cb->zstr.avail_out);
28025839Speter    }
28125839Speter
28225839Speter    *wrote = have;
28325839Speter
28425839Speter    /* We will only be here because buf_send_output was called on the
28525839Speter       compression buffer.  That means that we should now call
28625839Speter       buf_send_output on the underlying buffer.  */
28725839Speter    return buf_send_output (cb->buf);
28825839Speter}
28925839Speter
29025839Speter/* Flush a compression buffer.  */
29125839Speter
29225839Speterstatic int
29325839Spetercompress_buffer_flush (closure)
29425839Speter     void *closure;
29525839Speter{
29625839Speter    struct compress_buffer *cb = (struct compress_buffer *) closure;
29725839Speter
29825839Speter    cb->zstr.avail_in = 0;
29925839Speter    cb->zstr.next_in = NULL;
30025839Speter
30125839Speter    while (1)
30225839Speter    {
30325839Speter	char buffer[BUFFER_DATA_SIZE];
30425839Speter	int zstatus;
30525839Speter
30625839Speter	cb->zstr.avail_out = BUFFER_DATA_SIZE;
30725839Speter	cb->zstr.next_out = (unsigned char *) buffer;
30825839Speter
30925839Speter	zstatus = deflate (&cb->zstr, Z_SYNC_FLUSH);
31025839Speter
31125839Speter	/* The deflate function will return Z_BUF_ERROR if it can't do
31225839Speter           anything, which in this case means that all data has been
31325839Speter           flushed.  */
31425839Speter	if (zstatus == Z_BUF_ERROR)
31525839Speter	    break;
31625839Speter
31725839Speter	if (zstatus != Z_OK)
31825839Speter	{
31925839Speter	    compress_error (0, zstatus, &cb->zstr, "deflate flush");
32025839Speter	    return EIO;
32125839Speter	}
32225839Speter
32325839Speter	if (cb->zstr.avail_out != BUFFER_DATA_SIZE)
32425839Speter	    buf_output (cb->buf, buffer,
32525839Speter			BUFFER_DATA_SIZE - cb->zstr.avail_out);
32625839Speter
32725839Speter	/* If the deflate function did not fill the output buffer,
32825839Speter           then all data has been flushed.  */
32925839Speter	if (cb->zstr.avail_out > 0)
33025839Speter	    break;
33125839Speter    }
33225839Speter
33325839Speter    /* Now flush the underlying buffer.  Note that if the original
33425839Speter       call to buf_flush passed 1 for the BLOCK argument, then the
33525839Speter       buffer will already have been set into blocking mode, so we
33625839Speter       should always pass 0 here.  */
33725839Speter    return buf_flush (cb->buf, 0);
33825839Speter}
33925839Speter
34025839Speter/* The block routine for a compression buffer.  */
34125839Speter
34225839Speterstatic int
34325839Spetercompress_buffer_block (closure, block)
34425839Speter     void *closure;
34525839Speter     int block;
34625839Speter{
34725839Speter    struct compress_buffer *cb = (struct compress_buffer *) closure;
34825839Speter
34925839Speter    if (block)
35025839Speter	return set_block (cb->buf);
35125839Speter    else
35225839Speter	return set_nonblock (cb->buf);
35325839Speter}
35425839Speter
35525839Speter/* Shut down an input buffer.  */
35625839Speter
35725839Speterstatic int
358102840Spetercompress_buffer_shutdown_input (buf)
359102840Speter     struct buffer *buf;
36025839Speter{
361102840Speter    struct compress_buffer *cb = (struct compress_buffer *) buf->closure;
36225839Speter    int zstatus;
36325839Speter
364175261Sobrien    /* Don't make any attempt to pick up trailing data since we are shutting
365175261Sobrien     * down.  If the client doesn't know we are shutting down, we might not
366175261Sobrien     * see the EOF we are expecting.
367175261Sobrien     */
36825839Speter
36925839Speter    zstatus = inflateEnd (&cb->zstr);
37025839Speter    if (zstatus != Z_OK)
37125839Speter    {
37225839Speter	compress_error (0, zstatus, &cb->zstr, "inflateEnd");
37325839Speter	return EIO;
37425839Speter    }
37525839Speter
37625839Speter    return buf_shutdown (cb->buf);
37725839Speter}
37825839Speter
37925839Speter/* Shut down an output buffer.  */
38025839Speter
38125839Speterstatic int
382102840Spetercompress_buffer_shutdown_output (buf)
383102840Speter     struct buffer *buf;
38425839Speter{
385102840Speter    struct compress_buffer *cb = (struct compress_buffer *) buf->closure;
38625839Speter    int zstatus, status;
38725839Speter
38825839Speter    do
38925839Speter    {
39025839Speter	char buffer[BUFFER_DATA_SIZE];
39125839Speter
39225839Speter	cb->zstr.avail_out = BUFFER_DATA_SIZE;
39325839Speter	cb->zstr.next_out = (unsigned char *) buffer;
39425839Speter
39525839Speter	zstatus = deflate (&cb->zstr, Z_FINISH);
39625839Speter	if (zstatus != Z_OK && zstatus != Z_STREAM_END)
39725839Speter	{
39825839Speter	    compress_error (0, zstatus, &cb->zstr, "deflate finish");
39925839Speter	    return EIO;
40025839Speter	}
40125839Speter
40225839Speter	if (cb->zstr.avail_out != BUFFER_DATA_SIZE)
40325839Speter	    buf_output (cb->buf, buffer,
40425839Speter			BUFFER_DATA_SIZE - cb->zstr.avail_out);
40525839Speter    } while (zstatus != Z_STREAM_END);
40625839Speter
40725839Speter    zstatus = deflateEnd (&cb->zstr);
40825839Speter    if (zstatus != Z_OK)
40925839Speter    {
41025839Speter	compress_error (0, zstatus, &cb->zstr, "deflateEnd");
41125839Speter	return EIO;
41225839Speter    }
41325839Speter
41425839Speter    status = buf_flush (cb->buf, 1);
41525839Speter    if (status != 0)
41625839Speter	return status;
41725839Speter
41825839Speter    return buf_shutdown (cb->buf);
41925839Speter}
42025839Speter
42132785Speter
42232785Speter
42332785Speter/* Here is our librarified gzip implementation.  It is very minimal
42432785Speter   but attempts to be RFC1952 compliant.  */
42532785Speter
426128266Speter/* GZIP ID byte values */
427128266Speter#define GZIP_ID1	31
428128266Speter#define GZIP_ID2	139
429128266Speter
430128266Speter/* Compression methods */
431128266Speter#define GZIP_CDEFLATE	8
432128266Speter
433128266Speter/* Flags */
434128266Speter#define GZIP_FTEXT	1
435128266Speter#define GZIP_FHCRC	2
436128266Speter#define GZIP_FEXTRA	4
437128266Speter#define GZIP_FNAME	8
438128266Speter#define GZIP_FCOMMENT	16
439128266Speter
44032785Speter/* BUF should contain SIZE bytes of gzipped data (RFC1952/RFC1951).
44132785Speter   We are to uncompress the data and write the result to the file
44254427Speter   descriptor FD.  If something goes wrong, give a nonfatal error message
44354427Speter   mentioning FULLNAME as the name of the file for FD.  Return 1 if
44454427Speter   it is an error we can't recover from.  */
44532785Speter
44654427Speterint
44732785Spetergunzip_and_write (fd, fullname, buf, size)
44832785Speter    int fd;
44932785Speter    char *fullname;
45032785Speter    unsigned char *buf;
45132785Speter    size_t size;
45232785Speter{
45332785Speter    size_t pos;
45432785Speter    z_stream zstr;
45532785Speter    int zstatus;
45632785Speter    unsigned char outbuf[32768];
45732785Speter    unsigned long crc;
45832785Speter
459128266Speter    if (size < 10)
46054427Speter    {
461128266Speter	error (0, 0, "gzipped data too small - lacks complete header");
462128266Speter	return 1;
463128266Speter    }
464128266Speter    if (buf[0] != GZIP_ID1 || buf[1] != GZIP_ID2)
465128266Speter    {
46654427Speter	error (0, 0, "gzipped data does not start with gzip identification");
46754427Speter	return 1;
46854427Speter    }
469128266Speter    if (buf[2] != GZIP_CDEFLATE)
47054427Speter    {
47154427Speter	error (0, 0, "only the deflate compression method is supported");
47254427Speter	return 1;
47354427Speter    }
47432785Speter
47532785Speter    /* Skip over the fixed header, and then skip any of the variable-length
476128266Speter       fields.  As we skip each field, we keep pos <= size. The checks
477128266Speter       on positions and lengths are really checks for malformed or
478128266Speter       incomplete gzip data.  */
47932785Speter    pos = 10;
480128266Speter    if (buf[3] & GZIP_FEXTRA)
481128266Speter    {
482128266Speter	if (pos + 2 >= size)
483128266Speter	{
484128266Speter	    error (0, 0, "%s lacks proper gzip XLEN field", fullname);
485128266Speter	    return 1;
486128266Speter	}
48732785Speter	pos += buf[pos] + (buf[pos + 1] << 8) + 2;
488128266Speter	if (pos > size)
489128266Speter	{
490128266Speter	    error (0, 0, "%s lacks proper gzip \"extra field\"", fullname);
491128266Speter	    return 1;
492128266Speter	}
493128266Speter
494128266Speter    }
495128266Speter    if (buf[3] & GZIP_FNAME)
496128266Speter    {
497128266Speter	unsigned char *p = memchr(buf + pos, '\0', size - pos);
498128266Speter	if (p == NULL)
499128266Speter	{
500128266Speter	    error (0, 0, "%s has bad gzip filename field", fullname);
501128266Speter	    return 1;
502128266Speter	}
503128266Speter	pos = p - buf + 1;
504128266Speter    }
505128266Speter    if (buf[3] & GZIP_FCOMMENT)
506128266Speter    {
507128266Speter	unsigned char *p = memchr(buf + pos, '\0', size - pos);
508128266Speter	if (p == NULL)
509128266Speter	{
510128266Speter	    error (0, 0, "%s has bad gzip comment field", fullname);
511128266Speter	    return 1;
512128266Speter	}
513128266Speter	pos = p - buf + 1;
514128266Speter    }
515128266Speter    if (buf[3] & GZIP_FHCRC)
516128266Speter    {
51732785Speter	pos += 2;
518128266Speter	if (pos > size)
519128266Speter	{
520128266Speter	    error (0, 0, "%s has bad gzip CRC16 field", fullname);
521128266Speter	    return 1;
522128266Speter	}
523128266Speter    }
52432785Speter
525128266Speter    /* There could be no data to decompress - check and short circuit.  */
526128266Speter    if (pos >= size)
527128266Speter    {
528128266Speter	error (0, 0, "gzip data incomplete for %s (no data)", fullname);
529128266Speter	return 1;
530128266Speter    }
531128266Speter
53232785Speter    memset (&zstr, 0, sizeof zstr);
53332785Speter    /* Passing a negative argument tells zlib not to look for a zlib
53432785Speter       (RFC1950) header.  This is an undocumented feature; I suppose if
53532785Speter       we wanted to be anal we could synthesize a header instead,
53632785Speter       but why bother?  */
53732785Speter    zstatus = inflateInit2 (&zstr, -15);
53832785Speter
53932785Speter    if (zstatus != Z_OK)
54032785Speter	compress_error (1, zstatus, &zstr, fullname);
54132785Speter
54232785Speter    /* I don't see why we should have to include the 8 byte trailer in
54332785Speter       avail_in.  But I see that zlib/gzio.c does, and it seemed to fix
54432785Speter       a fairly rare bug in which we'd get a Z_BUF_ERROR for no obvious
54532785Speter       reason.  */
54632785Speter    zstr.avail_in = size - pos;
54732785Speter    zstr.next_in = buf + pos;
54832785Speter
54932785Speter    crc = crc32 (0, NULL, 0);
55032785Speter
55132785Speter    do
55232785Speter    {
55332785Speter	zstr.avail_out = sizeof (outbuf);
55432785Speter	zstr.next_out = outbuf;
55532785Speter	zstatus = inflate (&zstr, Z_NO_FLUSH);
55632785Speter	if (zstatus != Z_STREAM_END && zstatus != Z_OK)
55754427Speter	{
55854427Speter	    compress_error (0, zstatus, &zstr, fullname);
55954427Speter	    return 1;
56054427Speter	}
56132785Speter	if (write (fd, outbuf, sizeof (outbuf) - zstr.avail_out) < 0)
56254427Speter	{
56354427Speter	    error (0, errno, "writing decompressed file %s", fullname);
56454427Speter	    return 1;
56554427Speter	}
56632785Speter	crc = crc32 (crc, outbuf, sizeof (outbuf) - zstr.avail_out);
56732785Speter    } while (zstatus != Z_STREAM_END);
56832785Speter    zstatus = inflateEnd (&zstr);
56932785Speter    if (zstatus != Z_OK)
57032785Speter	compress_error (0, zstatus, &zstr, fullname);
57132785Speter
572128266Speter    /* Check that there is still 8 trailer bytes remaining (CRC32
573128266Speter       and ISIZE).  Check total decomp. data, plus header len (pos)
574128266Speter       against input buffer total size.  */
575128266Speter    pos += zstr.total_in;
576128266Speter    if (size - pos != 8)
57754427Speter    {
578128266Speter	error (0, 0, "gzip data incomplete for %s (no trailer)", fullname);
579128266Speter	return 1;
580128266Speter    }
581128266Speter
582128266Speter    if (crc != ((unsigned long)buf[pos]
583128266Speter		+ ((unsigned long)buf[pos + 1] << 8)
584128266Speter		+ ((unsigned long)buf[pos + 2] << 16)
585128266Speter		+ ((unsigned long)buf[pos + 3] << 24)))
586128266Speter    {
58754427Speter	error (0, 0, "CRC error uncompressing %s", fullname);
58854427Speter	return 1;
58954427Speter    }
59032785Speter
591128266Speter    if (zstr.total_out != ((unsigned long)buf[pos + 4]
592128266Speter			   + ((unsigned long)buf[pos + 5] << 8)
593128266Speter			   + ((unsigned long)buf[pos + 6] << 16)
594128266Speter			   + ((unsigned long)buf[pos + 7] << 24)))
59554427Speter    {
59654427Speter	error (0, 0, "invalid length uncompressing %s", fullname);
59754427Speter	return 1;
59854427Speter    }
59954427Speter
60054427Speter    return 0;
60132785Speter}
60232785Speter
60332785Speter/* Read all of FD and put the gzipped data (RFC1952/RFC1951) into *BUF,
604109655Speter   replacing previous contents of *BUF.  *BUF is xmalloc'd and *SIZE is
60532785Speter   its allocated size.  Put the actual number of bytes of data in
60654427Speter   *LEN.  If something goes wrong, give a nonfatal error mentioning
60754427Speter   FULLNAME as the name of the file for FD, and return 1 if we can't
60854427Speter   recover from it).  LEVEL is the compression level (1-9).  */
60932785Speter
61054427Speterint
61132785Speterread_and_gzip (fd, fullname, buf, size, len, level)
61232785Speter    int fd;
613128266Speter    const char *fullname;
61432785Speter    unsigned char **buf;
61532785Speter    size_t *size;
61632785Speter    size_t *len;
61732785Speter    int level;
61832785Speter{
61932785Speter    z_stream zstr;
62032785Speter    int zstatus;
62132785Speter    unsigned char inbuf[8192];
62232785Speter    int nread;
62332785Speter    unsigned long crc;
62432785Speter
62532785Speter    if (*size < 1024)
62632785Speter    {
62754427Speter	unsigned char *newbuf;
62854427Speter
62932785Speter	*size = 1024;
630109655Speter	newbuf = xrealloc (*buf, *size);
63154427Speter	if (newbuf == NULL)
63254427Speter	{
63354427Speter	    error (0, 0, "out of memory");
63454427Speter	    return 1;
63554427Speter	}
63654427Speter	*buf = newbuf;
63732785Speter    }
638128266Speter    (*buf)[0] = GZIP_ID1;
639128266Speter    (*buf)[1] = GZIP_ID2;
640128266Speter    (*buf)[2] = GZIP_CDEFLATE;
64132785Speter    (*buf)[3] = 0;
64232785Speter    (*buf)[4] = (*buf)[5] = (*buf)[6] = (*buf)[7] = 0;
64332785Speter    /* Could set this based on level, but why bother?  */
64432785Speter    (*buf)[8] = 0;
64532785Speter    (*buf)[9] = 255;
64632785Speter
64732785Speter    memset (&zstr, 0, sizeof zstr);
64832785Speter    zstatus = deflateInit2 (&zstr, level, Z_DEFLATED, -15, 8,
64932785Speter			    Z_DEFAULT_STRATEGY);
65032785Speter    crc = crc32 (0, NULL, 0);
65132785Speter    if (zstatus != Z_OK)
65254427Speter    {
65354427Speter	compress_error (0, zstatus, &zstr, fullname);
65454427Speter	return 1;
65554427Speter    }
656128266Speter
657128266Speter    /* Adjust for 10-byte output header (filled in above) */
658128266Speter    zstr.total_out = 10;
659128266Speter    zstr.avail_out = *size - 10;
66032785Speter    zstr.next_out = *buf + 10;
66132785Speter
66232785Speter    while (1)
66332785Speter    {
66432785Speter	int finish = 0;
66532785Speter
66632785Speter	nread = read (fd, inbuf, sizeof inbuf);
66732785Speter	if (nread < 0)
66854427Speter	{
66954427Speter	    error (0, errno, "cannot read %s", fullname);
67054427Speter	    return 1;
67154427Speter	}
67232785Speter	else if (nread == 0)
67332785Speter	    /* End of file.  */
67432785Speter	    finish = 1;
67532785Speter	crc = crc32 (crc, inbuf, nread);
67632785Speter	zstr.next_in = inbuf;
67732785Speter	zstr.avail_in = nread;
67832785Speter
67932785Speter	do
68032785Speter	{
68132785Speter	    /* I don't see this documented anywhere, but deflate seems
68232785Speter	       to tend to dump core sometimes if we pass it Z_FINISH and
68332785Speter	       a small (e.g. 2147 byte) avail_out.  So we insist on at
68432785Speter	       least 4096 bytes (that is what zlib/gzio.c uses).  */
68532785Speter
68632785Speter	    if (zstr.avail_out < 4096)
68732785Speter	    {
68854427Speter		unsigned char *newbuf;
68954427Speter
690128266Speter		assert(zstr.avail_out + zstr.total_out == *size);
691128266Speter		assert(zstr.next_out == *buf + zstr.total_out);
69232785Speter		*size *= 2;
693109655Speter		newbuf = xrealloc (*buf, *size);
69454427Speter		if (newbuf == NULL)
69554427Speter		{
69654427Speter		    error (0, 0, "out of memory");
69754427Speter		    return 1;
69854427Speter		}
69954427Speter		*buf = newbuf;
700128266Speter		zstr.next_out = *buf + zstr.total_out;
701128266Speter		zstr.avail_out = *size - zstr.total_out;
702128266Speter		assert(zstr.avail_out + zstr.total_out == *size);
703128266Speter		assert(zstr.next_out == *buf + zstr.total_out);
70432785Speter	    }
70532785Speter
70632785Speter	    zstatus = deflate (&zstr, finish ? Z_FINISH : 0);
70732785Speter	    if (zstatus == Z_STREAM_END)
70832785Speter		goto done;
70932785Speter	    else if (zstatus != Z_OK)
71032785Speter		compress_error (0, zstatus, &zstr, fullname);
71132785Speter	} while (zstr.avail_out == 0);
71232785Speter    }
71332785Speter done:
714128266Speter    /* Need to add the CRC information (8 bytes)
715128266Speter       to the end of the gzip'd output.
716128266Speter       Ensure there is enough space in the output buffer
717128266Speter       to do so.  */
718128266Speter    if (zstr.avail_out < 8)
719128266Speter    {
720128266Speter	unsigned char *newbuf;
72132785Speter
722128266Speter	assert(zstr.avail_out + zstr.total_out == *size);
723128266Speter	assert(zstr.next_out == *buf + zstr.total_out);
724128266Speter	*size += 8 - zstr.avail_out;
725128266Speter	newbuf = realloc (*buf, *size);
726128266Speter	if (newbuf == NULL)
727128266Speter	{
728128266Speter	    error (0, 0, "out of memory");
729128266Speter	    return 1;
730128266Speter	}
731128266Speter	*buf = newbuf;
732128266Speter	zstr.next_out = *buf + zstr.total_out;
733128266Speter	zstr.avail_out = *size - zstr.total_out;
734128266Speter	assert(zstr.avail_out + zstr.total_out == *size);
735128266Speter	assert(zstr.next_out == *buf + zstr.total_out);
736128266Speter    }
737128266Speter    *zstr.next_out++ = (unsigned char)(crc & 0xff);
738128266Speter    *zstr.next_out++ = (unsigned char)((crc >> 8) & 0xff);
739128266Speter    *zstr.next_out++ = (unsigned char)((crc >> 16) & 0xff);
740128266Speter    *zstr.next_out++ = (unsigned char)((crc >> 24) & 0xff);
74132785Speter
742128266Speter    *zstr.next_out++ = (unsigned char)(zstr.total_in & 0xff);
743128266Speter    *zstr.next_out++ = (unsigned char)((zstr.total_in >> 8) & 0xff);
744128266Speter    *zstr.next_out++ = (unsigned char)((zstr.total_in >> 16) & 0xff);
745128266Speter    *zstr.next_out++ = (unsigned char)((zstr.total_in >> 24) & 0xff);
74632785Speter
747128266Speter    zstr.total_out += 8;
748128266Speter    zstr.avail_out -= 8;
749128266Speter    assert(zstr.avail_out + zstr.total_out == *size);
750128266Speter    assert(zstr.next_out == *buf + zstr.total_out);
751128266Speter
752128266Speter    *len = zstr.total_out;
753128266Speter
75432785Speter    zstatus = deflateEnd (&zstr);
75532785Speter    if (zstatus != Z_OK)
75632785Speter	compress_error (0, zstatus, &zstr, fullname);
75754427Speter
75854427Speter    return 0;
75932785Speter}
76025839Speter#endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
761