xref: /dragonfly/contrib/cvs-1.12/src/zlib.c (revision 86d7f5d3)
1*86d7f5d3SJohn Marino /* zlib.c --- interface to the zlib compression library
2*86d7f5d3SJohn Marino    Ian Lance Taylor <ian@cygnus.com>
3*86d7f5d3SJohn Marino 
4*86d7f5d3SJohn Marino    This file is part of GNU CVS.
5*86d7f5d3SJohn Marino 
6*86d7f5d3SJohn Marino    GNU CVS is free software; you can redistribute it and/or modify it
7*86d7f5d3SJohn Marino    under the terms of the GNU General Public License as published by the
8*86d7f5d3SJohn Marino    Free Software Foundation; either version 2, or (at your option) any
9*86d7f5d3SJohn Marino    later version.
10*86d7f5d3SJohn Marino 
11*86d7f5d3SJohn Marino    This program is distributed in the hope that it will be useful,
12*86d7f5d3SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*86d7f5d3SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*86d7f5d3SJohn Marino    GNU General Public License for more details.  */
15*86d7f5d3SJohn Marino 
16*86d7f5d3SJohn Marino /* The routines in this file are the interface between the CVS
17*86d7f5d3SJohn Marino    client/server support and the zlib compression library.  */
18*86d7f5d3SJohn Marino 
19*86d7f5d3SJohn Marino #include "cvs.h"
20*86d7f5d3SJohn Marino #include "buffer.h"
21*86d7f5d3SJohn Marino #include "pagealign_alloc.h"
22*86d7f5d3SJohn Marino 
23*86d7f5d3SJohn Marino #if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
24*86d7f5d3SJohn Marino 
25*86d7f5d3SJohn Marino #if HAVE_ZLIB_H
26*86d7f5d3SJohn Marino # include <zlib.h>
27*86d7f5d3SJohn Marino #else
28*86d7f5d3SJohn Marino # include "zlib.h"
29*86d7f5d3SJohn Marino #endif
30*86d7f5d3SJohn Marino 
31*86d7f5d3SJohn Marino /* OS/2 doesn't have EIO.  FIXME: this whole notion of turning
32*86d7f5d3SJohn Marino    a different error into EIO strikes me as pretty dubious.  */
33*86d7f5d3SJohn Marino #if !defined (EIO)
34*86d7f5d3SJohn Marino #define EIO EBADPOS
35*86d7f5d3SJohn Marino #endif
36*86d7f5d3SJohn Marino 
37*86d7f5d3SJohn Marino /* The compression interface is built upon the buffer data structure.
38*86d7f5d3SJohn Marino    We provide a buffer type which compresses or decompresses the data
39*86d7f5d3SJohn Marino    which passes through it.  An input buffer decompresses the data
40*86d7f5d3SJohn Marino    read from an underlying buffer, and an output buffer compresses the
41*86d7f5d3SJohn Marino    data before writing it to an underlying buffer.  */
42*86d7f5d3SJohn Marino 
43*86d7f5d3SJohn Marino /* This structure is the closure field of the buffer.  */
44*86d7f5d3SJohn Marino 
45*86d7f5d3SJohn Marino struct compress_buffer
46*86d7f5d3SJohn Marino {
47*86d7f5d3SJohn Marino     /* The underlying buffer.  */
48*86d7f5d3SJohn Marino     struct buffer *buf;
49*86d7f5d3SJohn Marino 
50*86d7f5d3SJohn Marino     /* The compression information.  */
51*86d7f5d3SJohn Marino     z_stream zstr;
52*86d7f5d3SJohn Marino     int level;
53*86d7f5d3SJohn Marino };
54*86d7f5d3SJohn Marino 
55*86d7f5d3SJohn Marino static void compress_error (int, int, z_stream *, const char *);
56*86d7f5d3SJohn Marino static int compress_buffer_input (void *, char *, size_t, size_t, size_t *);
57*86d7f5d3SJohn Marino static int compress_buffer_output (void *, const char *, size_t, size_t *);
58*86d7f5d3SJohn Marino static int compress_buffer_flush (void *);
59*86d7f5d3SJohn Marino static int compress_buffer_block (void *, bool);
60*86d7f5d3SJohn Marino static int compress_buffer_get_fd (void *);
61*86d7f5d3SJohn Marino static int compress_buffer_shutdown_input (struct buffer *);
62*86d7f5d3SJohn Marino static int compress_buffer_shutdown_output (struct buffer *);
63*86d7f5d3SJohn Marino 
64*86d7f5d3SJohn Marino /* Report an error from one of the zlib functions.  */
65*86d7f5d3SJohn Marino 
66*86d7f5d3SJohn Marino static void
compress_error(int status,int zstatus,z_stream * zstr,const char * msg)67*86d7f5d3SJohn Marino compress_error (int status, int zstatus, z_stream *zstr, const char *msg)
68*86d7f5d3SJohn Marino {
69*86d7f5d3SJohn Marino     int hold_errno;
70*86d7f5d3SJohn Marino     const char *zmsg;
71*86d7f5d3SJohn Marino     char buf[100];
72*86d7f5d3SJohn Marino 
73*86d7f5d3SJohn Marino     hold_errno = errno;
74*86d7f5d3SJohn Marino 
75*86d7f5d3SJohn Marino     zmsg = zstr->msg;
76*86d7f5d3SJohn Marino     if (zmsg == NULL)
77*86d7f5d3SJohn Marino     {
78*86d7f5d3SJohn Marino         sprintf (buf, "error %d", zstatus);
79*86d7f5d3SJohn Marino 	zmsg = buf;
80*86d7f5d3SJohn Marino     }
81*86d7f5d3SJohn Marino 
82*86d7f5d3SJohn Marino     error (status,
83*86d7f5d3SJohn Marino 	   zstatus == Z_ERRNO ? hold_errno : 0,
84*86d7f5d3SJohn Marino 	   "%s: %s", msg, zmsg);
85*86d7f5d3SJohn Marino }
86*86d7f5d3SJohn Marino 
87*86d7f5d3SJohn Marino 
88*86d7f5d3SJohn Marino 
89*86d7f5d3SJohn Marino /* Create a compression buffer.  */
90*86d7f5d3SJohn Marino struct buffer *
compress_buffer_initialize(struct buffer * buf,int input,int level,void (* memory)(struct buffer *))91*86d7f5d3SJohn Marino compress_buffer_initialize (struct buffer *buf, int input, int level,
92*86d7f5d3SJohn Marino                             void (*memory) (struct buffer *))
93*86d7f5d3SJohn Marino {
94*86d7f5d3SJohn Marino     struct compress_buffer *n;
95*86d7f5d3SJohn Marino     int zstatus;
96*86d7f5d3SJohn Marino 
97*86d7f5d3SJohn Marino     n = xmalloc (sizeof *n);
98*86d7f5d3SJohn Marino     memset (n, 0, sizeof *n);
99*86d7f5d3SJohn Marino 
100*86d7f5d3SJohn Marino     n->buf = buf;
101*86d7f5d3SJohn Marino     n->level = level;
102*86d7f5d3SJohn Marino 
103*86d7f5d3SJohn Marino     if (input)
104*86d7f5d3SJohn Marino 	zstatus = inflateInit (&n->zstr);
105*86d7f5d3SJohn Marino     else
106*86d7f5d3SJohn Marino 	zstatus = deflateInit (&n->zstr, level);
107*86d7f5d3SJohn Marino     if (zstatus != Z_OK)
108*86d7f5d3SJohn Marino 	compress_error (1, zstatus, &n->zstr, "compression initialization");
109*86d7f5d3SJohn Marino 
110*86d7f5d3SJohn Marino     /* There may already be data buffered on BUF.  For an output
111*86d7f5d3SJohn Marino        buffer, this is OK, because these routines will just use the
112*86d7f5d3SJohn Marino        buffer routines to append data to the (uncompressed) data
113*86d7f5d3SJohn Marino        already on BUF.  An input buffer expects to handle a single
114*86d7f5d3SJohn Marino        buffer_data of buffered input to be uncompressed, so that is OK
115*86d7f5d3SJohn Marino        provided there is only one buffer.  At present that is all
116*86d7f5d3SJohn Marino        there ever will be; if this changes, compress_buffer_input must
117*86d7f5d3SJohn Marino        be modified to handle multiple input buffers.  */
118*86d7f5d3SJohn Marino     assert (! input || buf->data == NULL || buf->data->next == NULL);
119*86d7f5d3SJohn Marino 
120*86d7f5d3SJohn Marino     return buf_initialize (input ? compress_buffer_input : NULL,
121*86d7f5d3SJohn Marino 			   input ? NULL : compress_buffer_output,
122*86d7f5d3SJohn Marino 			   input ? NULL : compress_buffer_flush,
123*86d7f5d3SJohn Marino 			   compress_buffer_block, compress_buffer_get_fd,
124*86d7f5d3SJohn Marino 			   (input
125*86d7f5d3SJohn Marino 			    ? compress_buffer_shutdown_input
126*86d7f5d3SJohn Marino 			    : compress_buffer_shutdown_output),
127*86d7f5d3SJohn Marino 			   memory,
128*86d7f5d3SJohn Marino 			   n);
129*86d7f5d3SJohn Marino }
130*86d7f5d3SJohn Marino 
131*86d7f5d3SJohn Marino 
132*86d7f5d3SJohn Marino 
133*86d7f5d3SJohn Marino /* Input data from a compression buffer.  */
134*86d7f5d3SJohn Marino static int
compress_buffer_input(void * closure,char * data,size_t need,size_t size,size_t * got)135*86d7f5d3SJohn Marino compress_buffer_input (void *closure, char *data, size_t need, size_t size,
136*86d7f5d3SJohn Marino 		       size_t *got)
137*86d7f5d3SJohn Marino {
138*86d7f5d3SJohn Marino     struct compress_buffer *cb = closure;
139*86d7f5d3SJohn Marino     struct buffer_data *bd;
140*86d7f5d3SJohn Marino 
141*86d7f5d3SJohn Marino     assert (cb->buf->input);
142*86d7f5d3SJohn Marino 
143*86d7f5d3SJohn Marino     /* We use a single buffer_data structure to buffer up data which
144*86d7f5d3SJohn Marino        the z_stream structure won't use yet.  We can safely store this
145*86d7f5d3SJohn Marino        on cb->buf->data, because we never call the buffer routines on
146*86d7f5d3SJohn Marino        cb->buf; we only call the buffer input routine, since that
147*86d7f5d3SJohn Marino        gives us the semantics we want.  As noted in
148*86d7f5d3SJohn Marino        compress_buffer_initialize, the buffer_data structure may
149*86d7f5d3SJohn Marino        already exist, and hold data which was already read and
150*86d7f5d3SJohn Marino        buffered before the decompression began.  */
151*86d7f5d3SJohn Marino     bd = cb->buf->data;
152*86d7f5d3SJohn Marino     if (bd == NULL)
153*86d7f5d3SJohn Marino     {
154*86d7f5d3SJohn Marino 	bd = xmalloc (sizeof (struct buffer_data));
155*86d7f5d3SJohn Marino 	if (bd == NULL)
156*86d7f5d3SJohn Marino 	    return -2;
157*86d7f5d3SJohn Marino 	bd->text = pagealign_xalloc (BUFFER_DATA_SIZE);
158*86d7f5d3SJohn Marino 	if (bd->text == NULL)
159*86d7f5d3SJohn Marino 	{
160*86d7f5d3SJohn Marino 	    free (bd);
161*86d7f5d3SJohn Marino 	    return -2;
162*86d7f5d3SJohn Marino 	}
163*86d7f5d3SJohn Marino 	bd->bufp = bd->text;
164*86d7f5d3SJohn Marino 	bd->size = 0;
165*86d7f5d3SJohn Marino 	cb->buf->data = bd;
166*86d7f5d3SJohn Marino     }
167*86d7f5d3SJohn Marino 
168*86d7f5d3SJohn Marino     cb->zstr.avail_out = size;
169*86d7f5d3SJohn Marino     cb->zstr.next_out = (Bytef *) data;
170*86d7f5d3SJohn Marino 
171*86d7f5d3SJohn Marino     while (1)
172*86d7f5d3SJohn Marino     {
173*86d7f5d3SJohn Marino 	int zstatus, sofar, status;
174*86d7f5d3SJohn Marino 	size_t nread;
175*86d7f5d3SJohn Marino 
176*86d7f5d3SJohn Marino 	/* First try to inflate any data we already have buffered up.
177*86d7f5d3SJohn Marino 	   This is useful even if we don't have any buffered data,
178*86d7f5d3SJohn Marino 	   because there may be data buffered inside the z_stream
179*86d7f5d3SJohn Marino 	   structure.  */
180*86d7f5d3SJohn Marino 
181*86d7f5d3SJohn Marino 	cb->zstr.avail_in = bd->size;
182*86d7f5d3SJohn Marino 	cb->zstr.next_in = (Bytef *) bd->bufp;
183*86d7f5d3SJohn Marino 
184*86d7f5d3SJohn Marino 	do
185*86d7f5d3SJohn Marino 	{
186*86d7f5d3SJohn Marino 	    zstatus = inflate (&cb->zstr, Z_NO_FLUSH);
187*86d7f5d3SJohn Marino 	    if (zstatus == Z_STREAM_END)
188*86d7f5d3SJohn Marino 		break;
189*86d7f5d3SJohn Marino 	    if (zstatus != Z_OK && zstatus != Z_BUF_ERROR)
190*86d7f5d3SJohn Marino 	    {
191*86d7f5d3SJohn Marino 		compress_error (0, zstatus, &cb->zstr, "inflate");
192*86d7f5d3SJohn Marino 		return EIO;
193*86d7f5d3SJohn Marino 	    }
194*86d7f5d3SJohn Marino 	} while (cb->zstr.avail_in > 0
195*86d7f5d3SJohn Marino 		 && cb->zstr.avail_out > 0);
196*86d7f5d3SJohn Marino 
197*86d7f5d3SJohn Marino 	bd->size = cb->zstr.avail_in;
198*86d7f5d3SJohn Marino 	bd->bufp = (char *) cb->zstr.next_in;
199*86d7f5d3SJohn Marino 
200*86d7f5d3SJohn Marino 	sofar = size - cb->zstr.avail_out;
201*86d7f5d3SJohn Marino 
202*86d7f5d3SJohn Marino 	if (zstatus == Z_STREAM_END)
203*86d7f5d3SJohn Marino 	{
204*86d7f5d3SJohn Marino 	    /* If we read any data, then return it, relying on the fact that
205*86d7f5d3SJohn Marino 	     * we will get Z_STREAM_END on the next read too.
206*86d7f5d3SJohn Marino 	     */
207*86d7f5d3SJohn Marino 	    if (sofar > 0) break;
208*86d7f5d3SJohn Marino 
209*86d7f5d3SJohn Marino 	    /* Otherwise, return EOF.  */
210*86d7f5d3SJohn Marino 	    return -1;
211*86d7f5d3SJohn Marino 	}
212*86d7f5d3SJohn Marino 
213*86d7f5d3SJohn Marino 	/* If we have obtained NEED bytes, then return, unless NEED is
214*86d7f5d3SJohn Marino            zero and we haven't obtained anything at all.  If NEED is
215*86d7f5d3SJohn Marino            zero, we will attempt at least one nonblocking read and see if
216*86d7f5d3SJohn Marino 	   we can inflate anything then.  */
217*86d7f5d3SJohn Marino 	if (sofar > 0 && sofar >= need)
218*86d7f5d3SJohn Marino 	    break;
219*86d7f5d3SJohn Marino 
220*86d7f5d3SJohn Marino 	/* All our buffered data should have been processed at this
221*86d7f5d3SJohn Marino            point.  */
222*86d7f5d3SJohn Marino 	assert (bd->size == 0);
223*86d7f5d3SJohn Marino 
224*86d7f5d3SJohn Marino 	/* This will work well in the server, because this call will
225*86d7f5d3SJohn Marino 	   do an unblocked read and fetch all the available data.  In
226*86d7f5d3SJohn Marino 	   the client, this will read a single byte from the stdio
227*86d7f5d3SJohn Marino 	   stream, which will cause us to call inflate once per byte.
228*86d7f5d3SJohn Marino 	   It would be more efficient if we could make a call which
229*86d7f5d3SJohn Marino 	   would fetch all the available bytes, and at least one byte.  */
230*86d7f5d3SJohn Marino 
231*86d7f5d3SJohn Marino 	status = (*cb->buf->input) (cb->buf->closure, bd->text,
232*86d7f5d3SJohn Marino 				    need > 0 ? 1 : 0, BUFFER_DATA_SIZE, &nread);
233*86d7f5d3SJohn Marino 
234*86d7f5d3SJohn Marino 	if (status == -2)
235*86d7f5d3SJohn Marino 	    /* Don't try to recover from memory allcoation errors.  */
236*86d7f5d3SJohn Marino 	    return status;
237*86d7f5d3SJohn Marino 
238*86d7f5d3SJohn Marino 	if (status != 0)
239*86d7f5d3SJohn Marino 	{
240*86d7f5d3SJohn Marino 	    /* If we read any data, then return it, relying on the fact that
241*86d7f5d3SJohn Marino 	     * we will get the same error reading the underlying buffer
242*86d7f5d3SJohn Marino 	     * on the next read too.
243*86d7f5d3SJohn Marino 	     */
244*86d7f5d3SJohn Marino 	    if (sofar > 0) break;
245*86d7f5d3SJohn Marino 
246*86d7f5d3SJohn Marino 	    /* Otherwise, return EOF.  */
247*86d7f5d3SJohn Marino 	    return status;
248*86d7f5d3SJohn Marino 	}
249*86d7f5d3SJohn Marino 
250*86d7f5d3SJohn Marino 	/* If we didn't read anything, then presumably the buffer is
251*86d7f5d3SJohn Marino            in nonblocking mode, and we should just get out now with
252*86d7f5d3SJohn Marino            whatever we've inflated.  */
253*86d7f5d3SJohn Marino 	if (nread == 0)
254*86d7f5d3SJohn Marino 	{
255*86d7f5d3SJohn Marino 	    assert (need == 0);
256*86d7f5d3SJohn Marino 	    break;
257*86d7f5d3SJohn Marino 	}
258*86d7f5d3SJohn Marino 
259*86d7f5d3SJohn Marino 	bd->bufp = bd->text;
260*86d7f5d3SJohn Marino 	bd->size = nread;
261*86d7f5d3SJohn Marino     }
262*86d7f5d3SJohn Marino 
263*86d7f5d3SJohn Marino     *got = size - cb->zstr.avail_out;
264*86d7f5d3SJohn Marino 
265*86d7f5d3SJohn Marino     return 0;
266*86d7f5d3SJohn Marino }
267*86d7f5d3SJohn Marino 
268*86d7f5d3SJohn Marino 
269*86d7f5d3SJohn Marino 
270*86d7f5d3SJohn Marino extern int gzip_level;
271*86d7f5d3SJohn Marino 
272*86d7f5d3SJohn Marino /* Output data to a compression buffer.
273*86d7f5d3SJohn Marino  *
274*86d7f5d3SJohn Marino  * GLOBALS
275*86d7f5d3SJohn Marino  *   gzip_level		If GZIP_LEVEL has changed to a value different from
276*86d7f5d3SJohn Marino  *			CLOSURE->level, then set the compression level on the
277*86d7f5d3SJohn Marino  *			stream to the new value.
278*86d7f5d3SJohn Marino  */
279*86d7f5d3SJohn Marino static int
compress_buffer_output(void * closure,const char * data,size_t have,size_t * wrote)280*86d7f5d3SJohn Marino compress_buffer_output (void *closure, const char *data, size_t have,
281*86d7f5d3SJohn Marino 			size_t *wrote)
282*86d7f5d3SJohn Marino {
283*86d7f5d3SJohn Marino     struct compress_buffer *cb = closure;
284*86d7f5d3SJohn Marino 
285*86d7f5d3SJohn Marino     /* This is only used within the while loop below, but allocated here for
286*86d7f5d3SJohn Marino      * efficiency.
287*86d7f5d3SJohn Marino      */
288*86d7f5d3SJohn Marino     static char *buffer = NULL;
289*86d7f5d3SJohn Marino     if (!buffer)
290*86d7f5d3SJohn Marino 	buffer = pagealign_xalloc (BUFFER_DATA_SIZE);
291*86d7f5d3SJohn Marino 
292*86d7f5d3SJohn Marino     if (cb->level != gzip_level)
293*86d7f5d3SJohn Marino     {
294*86d7f5d3SJohn Marino 	cb->level = gzip_level;
295*86d7f5d3SJohn Marino 	deflateParams (&cb->zstr, gzip_level, Z_DEFAULT_STRATEGY);
296*86d7f5d3SJohn Marino     }
297*86d7f5d3SJohn Marino 
298*86d7f5d3SJohn Marino     cb->zstr.avail_in = have;
299*86d7f5d3SJohn Marino     cb->zstr.next_in = (unsigned char *) data;
300*86d7f5d3SJohn Marino 
301*86d7f5d3SJohn Marino     while (cb->zstr.avail_in > 0)
302*86d7f5d3SJohn Marino     {
303*86d7f5d3SJohn Marino 	int zstatus;
304*86d7f5d3SJohn Marino 
305*86d7f5d3SJohn Marino 	cb->zstr.avail_out = BUFFER_DATA_SIZE;
306*86d7f5d3SJohn Marino 	cb->zstr.next_out = (unsigned char *) buffer;
307*86d7f5d3SJohn Marino 
308*86d7f5d3SJohn Marino 	zstatus = deflate (&cb->zstr, Z_NO_FLUSH);
309*86d7f5d3SJohn Marino 	if (zstatus != Z_OK)
310*86d7f5d3SJohn Marino 	{
311*86d7f5d3SJohn Marino 	    compress_error (0, zstatus, &cb->zstr, "deflate");
312*86d7f5d3SJohn Marino 	    return EIO;
313*86d7f5d3SJohn Marino 	}
314*86d7f5d3SJohn Marino 
315*86d7f5d3SJohn Marino 	if (cb->zstr.avail_out != BUFFER_DATA_SIZE)
316*86d7f5d3SJohn Marino 	    buf_output (cb->buf, buffer,
317*86d7f5d3SJohn Marino 			BUFFER_DATA_SIZE - cb->zstr.avail_out);
318*86d7f5d3SJohn Marino     }
319*86d7f5d3SJohn Marino 
320*86d7f5d3SJohn Marino     *wrote = have;
321*86d7f5d3SJohn Marino 
322*86d7f5d3SJohn Marino     /* We will only be here because buf_send_output was called on the
323*86d7f5d3SJohn Marino        compression buffer.  That means that we should now call
324*86d7f5d3SJohn Marino        buf_send_output on the underlying buffer.  */
325*86d7f5d3SJohn Marino     return buf_send_output (cb->buf);
326*86d7f5d3SJohn Marino }
327*86d7f5d3SJohn Marino 
328*86d7f5d3SJohn Marino 
329*86d7f5d3SJohn Marino 
330*86d7f5d3SJohn Marino /* Flush a compression buffer.  */
331*86d7f5d3SJohn Marino static int
compress_buffer_flush(void * closure)332*86d7f5d3SJohn Marino compress_buffer_flush (void *closure)
333*86d7f5d3SJohn Marino {
334*86d7f5d3SJohn Marino     struct compress_buffer *cb = closure;
335*86d7f5d3SJohn Marino 
336*86d7f5d3SJohn Marino     /* This is only used within the while loop below, but allocated here for
337*86d7f5d3SJohn Marino      * efficiency.
338*86d7f5d3SJohn Marino      */
339*86d7f5d3SJohn Marino     static char *buffer = NULL;
340*86d7f5d3SJohn Marino     if (!buffer)
341*86d7f5d3SJohn Marino 	buffer = pagealign_xalloc (BUFFER_DATA_SIZE);
342*86d7f5d3SJohn Marino 
343*86d7f5d3SJohn Marino     cb->zstr.avail_in = 0;
344*86d7f5d3SJohn Marino     cb->zstr.next_in = NULL;
345*86d7f5d3SJohn Marino 
346*86d7f5d3SJohn Marino     while (1)
347*86d7f5d3SJohn Marino     {
348*86d7f5d3SJohn Marino 	int zstatus;
349*86d7f5d3SJohn Marino 
350*86d7f5d3SJohn Marino 	cb->zstr.avail_out = BUFFER_DATA_SIZE;
351*86d7f5d3SJohn Marino 	cb->zstr.next_out = (unsigned char *) buffer;
352*86d7f5d3SJohn Marino 
353*86d7f5d3SJohn Marino 	zstatus = deflate (&cb->zstr, Z_SYNC_FLUSH);
354*86d7f5d3SJohn Marino 
355*86d7f5d3SJohn Marino 	/* The deflate function will return Z_BUF_ERROR if it can't do
356*86d7f5d3SJohn Marino            anything, which in this case means that all data has been
357*86d7f5d3SJohn Marino            flushed.  */
358*86d7f5d3SJohn Marino 	if (zstatus == Z_BUF_ERROR)
359*86d7f5d3SJohn Marino 	    break;
360*86d7f5d3SJohn Marino 
361*86d7f5d3SJohn Marino 	if (zstatus != Z_OK)
362*86d7f5d3SJohn Marino 	{
363*86d7f5d3SJohn Marino 	    compress_error (0, zstatus, &cb->zstr, "deflate flush");
364*86d7f5d3SJohn Marino 	    return EIO;
365*86d7f5d3SJohn Marino 	}
366*86d7f5d3SJohn Marino 
367*86d7f5d3SJohn Marino 	if (cb->zstr.avail_out != BUFFER_DATA_SIZE)
368*86d7f5d3SJohn Marino 	    buf_output (cb->buf, buffer,
369*86d7f5d3SJohn Marino 			BUFFER_DATA_SIZE - cb->zstr.avail_out);
370*86d7f5d3SJohn Marino 
371*86d7f5d3SJohn Marino 	/* If the deflate function did not fill the output buffer,
372*86d7f5d3SJohn Marino            then all data has been flushed.  */
373*86d7f5d3SJohn Marino 	if (cb->zstr.avail_out > 0)
374*86d7f5d3SJohn Marino 	    break;
375*86d7f5d3SJohn Marino     }
376*86d7f5d3SJohn Marino 
377*86d7f5d3SJohn Marino     /* Now flush the underlying buffer.  Note that if the original
378*86d7f5d3SJohn Marino        call to buf_flush passed 1 for the BLOCK argument, then the
379*86d7f5d3SJohn Marino        buffer will already have been set into blocking mode, so we
380*86d7f5d3SJohn Marino        should always pass 0 here.  */
381*86d7f5d3SJohn Marino     return buf_flush (cb->buf, 0);
382*86d7f5d3SJohn Marino }
383*86d7f5d3SJohn Marino 
384*86d7f5d3SJohn Marino 
385*86d7f5d3SJohn Marino 
386*86d7f5d3SJohn Marino /* The block routine for a compression buffer.  */
387*86d7f5d3SJohn Marino static int
compress_buffer_block(void * closure,bool block)388*86d7f5d3SJohn Marino compress_buffer_block (void *closure, bool block)
389*86d7f5d3SJohn Marino {
390*86d7f5d3SJohn Marino     struct compress_buffer *cb = closure;
391*86d7f5d3SJohn Marino 
392*86d7f5d3SJohn Marino     if (block)
393*86d7f5d3SJohn Marino 	return set_block (cb->buf);
394*86d7f5d3SJohn Marino     else
395*86d7f5d3SJohn Marino 	return set_nonblock (cb->buf);
396*86d7f5d3SJohn Marino }
397*86d7f5d3SJohn Marino 
398*86d7f5d3SJohn Marino 
399*86d7f5d3SJohn Marino 
400*86d7f5d3SJohn Marino /* Return the file descriptor underlying any child buffers.  */
401*86d7f5d3SJohn Marino static int
compress_buffer_get_fd(void * closure)402*86d7f5d3SJohn Marino compress_buffer_get_fd (void *closure)
403*86d7f5d3SJohn Marino {
404*86d7f5d3SJohn Marino     struct compress_buffer *cb = closure;
405*86d7f5d3SJohn Marino     return buf_get_fd (cb->buf);
406*86d7f5d3SJohn Marino }
407*86d7f5d3SJohn Marino 
408*86d7f5d3SJohn Marino 
409*86d7f5d3SJohn Marino 
410*86d7f5d3SJohn Marino /* Shut down an input buffer.  */
411*86d7f5d3SJohn Marino static int
compress_buffer_shutdown_input(struct buffer * buf)412*86d7f5d3SJohn Marino compress_buffer_shutdown_input (struct buffer *buf)
413*86d7f5d3SJohn Marino {
414*86d7f5d3SJohn Marino     struct compress_buffer *cb = buf->closure;
415*86d7f5d3SJohn Marino     int zstatus;
416*86d7f5d3SJohn Marino 
417*86d7f5d3SJohn Marino     /* Don't make any attempt to pick up trailing data since we are shutting
418*86d7f5d3SJohn Marino      * down.  If the client doesn't know we are shutting down, we might not
419*86d7f5d3SJohn Marino      * see the EOF we are expecting.
420*86d7f5d3SJohn Marino      */
421*86d7f5d3SJohn Marino 
422*86d7f5d3SJohn Marino     zstatus = inflateEnd (&cb->zstr);
423*86d7f5d3SJohn Marino     if (zstatus != Z_OK)
424*86d7f5d3SJohn Marino     {
425*86d7f5d3SJohn Marino 	compress_error (0, zstatus, &cb->zstr, "inflateEnd");
426*86d7f5d3SJohn Marino 	return EIO;
427*86d7f5d3SJohn Marino     }
428*86d7f5d3SJohn Marino 
429*86d7f5d3SJohn Marino     return buf_shutdown (cb->buf);
430*86d7f5d3SJohn Marino }
431*86d7f5d3SJohn Marino 
432*86d7f5d3SJohn Marino 
433*86d7f5d3SJohn Marino 
434*86d7f5d3SJohn Marino /* Shut down an output buffer.  */
435*86d7f5d3SJohn Marino static int
compress_buffer_shutdown_output(struct buffer * buf)436*86d7f5d3SJohn Marino compress_buffer_shutdown_output (struct buffer *buf)
437*86d7f5d3SJohn Marino {
438*86d7f5d3SJohn Marino     struct compress_buffer *cb = buf->closure;
439*86d7f5d3SJohn Marino     int zstatus, status;
440*86d7f5d3SJohn Marino 
441*86d7f5d3SJohn Marino     /* This is only used within the while loop below, but allocated here for
442*86d7f5d3SJohn Marino      * efficiency.
443*86d7f5d3SJohn Marino      */
444*86d7f5d3SJohn Marino     static char *buffer = NULL;
445*86d7f5d3SJohn Marino     if (!buffer)
446*86d7f5d3SJohn Marino 	buffer = pagealign_xalloc (BUFFER_DATA_SIZE);
447*86d7f5d3SJohn Marino 
448*86d7f5d3SJohn Marino     do
449*86d7f5d3SJohn Marino     {
450*86d7f5d3SJohn Marino 	cb->zstr.avail_out = BUFFER_DATA_SIZE;
451*86d7f5d3SJohn Marino 	cb->zstr.next_out = (unsigned char *) buffer;
452*86d7f5d3SJohn Marino 
453*86d7f5d3SJohn Marino 	zstatus = deflate (&cb->zstr, Z_FINISH);
454*86d7f5d3SJohn Marino 	if (zstatus != Z_OK && zstatus != Z_STREAM_END)
455*86d7f5d3SJohn Marino 	{
456*86d7f5d3SJohn Marino 	    compress_error (0, zstatus, &cb->zstr, "deflate finish");
457*86d7f5d3SJohn Marino 	    return EIO;
458*86d7f5d3SJohn Marino 	}
459*86d7f5d3SJohn Marino 
460*86d7f5d3SJohn Marino 	if (cb->zstr.avail_out != BUFFER_DATA_SIZE)
461*86d7f5d3SJohn Marino 	    buf_output (cb->buf, buffer,
462*86d7f5d3SJohn Marino 			BUFFER_DATA_SIZE - cb->zstr.avail_out);
463*86d7f5d3SJohn Marino     } while (zstatus != Z_STREAM_END);
464*86d7f5d3SJohn Marino 
465*86d7f5d3SJohn Marino     zstatus = deflateEnd (&cb->zstr);
466*86d7f5d3SJohn Marino     if (zstatus != Z_OK)
467*86d7f5d3SJohn Marino     {
468*86d7f5d3SJohn Marino 	compress_error (0, zstatus, &cb->zstr, "deflateEnd");
469*86d7f5d3SJohn Marino 	return EIO;
470*86d7f5d3SJohn Marino     }
471*86d7f5d3SJohn Marino 
472*86d7f5d3SJohn Marino     status = buf_flush (cb->buf, 1);
473*86d7f5d3SJohn Marino     if (status != 0)
474*86d7f5d3SJohn Marino 	return status;
475*86d7f5d3SJohn Marino 
476*86d7f5d3SJohn Marino     return buf_shutdown (cb->buf);
477*86d7f5d3SJohn Marino }
478*86d7f5d3SJohn Marino 
479*86d7f5d3SJohn Marino 
480*86d7f5d3SJohn Marino 
481*86d7f5d3SJohn Marino /* Here is our librarified gzip implementation.  It is very minimal
482*86d7f5d3SJohn Marino    but attempts to be RFC1952 compliant.  */
483*86d7f5d3SJohn Marino 
484*86d7f5d3SJohn Marino /* GZIP ID byte values */
485*86d7f5d3SJohn Marino #define GZIP_ID1	31
486*86d7f5d3SJohn Marino #define GZIP_ID2	139
487*86d7f5d3SJohn Marino 
488*86d7f5d3SJohn Marino /* Compression methods */
489*86d7f5d3SJohn Marino #define GZIP_CDEFLATE	8
490*86d7f5d3SJohn Marino 
491*86d7f5d3SJohn Marino /* Flags */
492*86d7f5d3SJohn Marino #define GZIP_FTEXT	1
493*86d7f5d3SJohn Marino #define GZIP_FHCRC	2
494*86d7f5d3SJohn Marino #define GZIP_FEXTRA	4
495*86d7f5d3SJohn Marino #define GZIP_FNAME	8
496*86d7f5d3SJohn Marino #define GZIP_FCOMMENT	16
497*86d7f5d3SJohn Marino 
498*86d7f5d3SJohn Marino /* BUF should contain SIZE bytes of gzipped data (RFC1952/RFC1951).
499*86d7f5d3SJohn Marino    We are to uncompress the data and write the result to the file
500*86d7f5d3SJohn Marino    descriptor FD.  If something goes wrong, give a nonfatal error message
501*86d7f5d3SJohn Marino    mentioning FULLNAME as the name of the file for FD.  Return 1 if
502*86d7f5d3SJohn Marino    it is an error we can't recover from.  */
503*86d7f5d3SJohn Marino 
504*86d7f5d3SJohn Marino int
gunzip_and_write(int fd,const char * fullname,unsigned char * buf,size_t size)505*86d7f5d3SJohn Marino gunzip_and_write (int fd, const char *fullname, unsigned char *buf,
506*86d7f5d3SJohn Marino 		  size_t size)
507*86d7f5d3SJohn Marino {
508*86d7f5d3SJohn Marino     size_t pos;
509*86d7f5d3SJohn Marino     z_stream zstr;
510*86d7f5d3SJohn Marino     int zstatus;
511*86d7f5d3SJohn Marino     unsigned char outbuf[32768];
512*86d7f5d3SJohn Marino     unsigned long crc;
513*86d7f5d3SJohn Marino 
514*86d7f5d3SJohn Marino     if (size < 10)
515*86d7f5d3SJohn Marino     {
516*86d7f5d3SJohn Marino 	error (0, 0, "gzipped data too small - lacks complete header");
517*86d7f5d3SJohn Marino 	return 1;
518*86d7f5d3SJohn Marino     }
519*86d7f5d3SJohn Marino     if (buf[0] != GZIP_ID1 || buf[1] != GZIP_ID2)
520*86d7f5d3SJohn Marino     {
521*86d7f5d3SJohn Marino 	error (0, 0, "gzipped data does not start with gzip identification");
522*86d7f5d3SJohn Marino 	return 1;
523*86d7f5d3SJohn Marino     }
524*86d7f5d3SJohn Marino     if (buf[2] != GZIP_CDEFLATE)
525*86d7f5d3SJohn Marino     {
526*86d7f5d3SJohn Marino 	error (0, 0, "only the deflate compression method is supported");
527*86d7f5d3SJohn Marino 	return 1;
528*86d7f5d3SJohn Marino     }
529*86d7f5d3SJohn Marino 
530*86d7f5d3SJohn Marino     /* Skip over the fixed header, and then skip any of the variable-length
531*86d7f5d3SJohn Marino        fields.  As we skip each field, we keep pos <= size. The checks
532*86d7f5d3SJohn Marino        on positions and lengths are really checks for malformed or
533*86d7f5d3SJohn Marino        incomplete gzip data.  */
534*86d7f5d3SJohn Marino     pos = 10;
535*86d7f5d3SJohn Marino     if (buf[3] & GZIP_FEXTRA)
536*86d7f5d3SJohn Marino     {
537*86d7f5d3SJohn Marino 	if (pos + 2 >= size)
538*86d7f5d3SJohn Marino 	{
539*86d7f5d3SJohn Marino 	    error (0, 0, "%s lacks proper gzip XLEN field", fullname);
540*86d7f5d3SJohn Marino 	    return 1;
541*86d7f5d3SJohn Marino 	}
542*86d7f5d3SJohn Marino 	pos += buf[pos] + (buf[pos + 1] << 8) + 2;
543*86d7f5d3SJohn Marino 	if (pos > size)
544*86d7f5d3SJohn Marino 	{
545*86d7f5d3SJohn Marino 	    error (0, 0, "%s lacks proper gzip \"extra field\"", fullname);
546*86d7f5d3SJohn Marino 	    return 1;
547*86d7f5d3SJohn Marino 	}
548*86d7f5d3SJohn Marino 
549*86d7f5d3SJohn Marino     }
550*86d7f5d3SJohn Marino     if (buf[3] & GZIP_FNAME)
551*86d7f5d3SJohn Marino     {
552*86d7f5d3SJohn Marino 	unsigned char *p = memchr(buf + pos, '\0', size - pos);
553*86d7f5d3SJohn Marino 	if (p == NULL)
554*86d7f5d3SJohn Marino 	{
555*86d7f5d3SJohn Marino 	    error (0, 0, "%s has bad gzip filename field", fullname);
556*86d7f5d3SJohn Marino 	    return 1;
557*86d7f5d3SJohn Marino 	}
558*86d7f5d3SJohn Marino 	pos = p - buf + 1;
559*86d7f5d3SJohn Marino     }
560*86d7f5d3SJohn Marino     if (buf[3] & GZIP_FCOMMENT)
561*86d7f5d3SJohn Marino     {
562*86d7f5d3SJohn Marino 	unsigned char *p = memchr(buf + pos, '\0', size - pos);
563*86d7f5d3SJohn Marino 	if (p == NULL)
564*86d7f5d3SJohn Marino 	{
565*86d7f5d3SJohn Marino 	    error (0, 0, "%s has bad gzip comment field", fullname);
566*86d7f5d3SJohn Marino 	    return 1;
567*86d7f5d3SJohn Marino 	}
568*86d7f5d3SJohn Marino 	pos = p - buf + 1;
569*86d7f5d3SJohn Marino     }
570*86d7f5d3SJohn Marino     if (buf[3] & GZIP_FHCRC)
571*86d7f5d3SJohn Marino     {
572*86d7f5d3SJohn Marino 	pos += 2;
573*86d7f5d3SJohn Marino 	if (pos > size)
574*86d7f5d3SJohn Marino 	{
575*86d7f5d3SJohn Marino 	    error (0, 0, "%s has bad gzip CRC16 field", fullname);
576*86d7f5d3SJohn Marino 	    return 1;
577*86d7f5d3SJohn Marino 	}
578*86d7f5d3SJohn Marino     }
579*86d7f5d3SJohn Marino 
580*86d7f5d3SJohn Marino     /* There could be no data to decompress - check and short circuit.  */
581*86d7f5d3SJohn Marino     if (pos >= size)
582*86d7f5d3SJohn Marino     {
583*86d7f5d3SJohn Marino 	error (0, 0, "gzip data incomplete for %s (no data)", fullname);
584*86d7f5d3SJohn Marino 	return 1;
585*86d7f5d3SJohn Marino     }
586*86d7f5d3SJohn Marino 
587*86d7f5d3SJohn Marino     memset (&zstr, 0, sizeof zstr);
588*86d7f5d3SJohn Marino     /* Passing a negative argument tells zlib not to look for a zlib
589*86d7f5d3SJohn Marino        (RFC1950) header.  This is an undocumented feature; I suppose if
590*86d7f5d3SJohn Marino        we wanted to be anal we could synthesize a header instead,
591*86d7f5d3SJohn Marino        but why bother?  */
592*86d7f5d3SJohn Marino     zstatus = inflateInit2 (&zstr, -15);
593*86d7f5d3SJohn Marino 
594*86d7f5d3SJohn Marino     if (zstatus != Z_OK)
595*86d7f5d3SJohn Marino 	compress_error (1, zstatus, &zstr, fullname);
596*86d7f5d3SJohn Marino 
597*86d7f5d3SJohn Marino     /* I don't see why we should have to include the 8 byte trailer in
598*86d7f5d3SJohn Marino        avail_in.  But I see that zlib/gzio.c does, and it seemed to fix
599*86d7f5d3SJohn Marino        a fairly rare bug in which we'd get a Z_BUF_ERROR for no obvious
600*86d7f5d3SJohn Marino        reason.  */
601*86d7f5d3SJohn Marino     zstr.avail_in = size - pos;
602*86d7f5d3SJohn Marino     zstr.next_in = buf + pos;
603*86d7f5d3SJohn Marino 
604*86d7f5d3SJohn Marino     crc = crc32 (0, NULL, 0);
605*86d7f5d3SJohn Marino 
606*86d7f5d3SJohn Marino     do
607*86d7f5d3SJohn Marino     {
608*86d7f5d3SJohn Marino 	zstr.avail_out = sizeof (outbuf);
609*86d7f5d3SJohn Marino 	zstr.next_out = outbuf;
610*86d7f5d3SJohn Marino 	zstatus = inflate (&zstr, Z_NO_FLUSH);
611*86d7f5d3SJohn Marino 	if (zstatus != Z_STREAM_END && zstatus != Z_OK)
612*86d7f5d3SJohn Marino 	{
613*86d7f5d3SJohn Marino 	    compress_error (0, zstatus, &zstr, fullname);
614*86d7f5d3SJohn Marino 	    return 1;
615*86d7f5d3SJohn Marino 	}
616*86d7f5d3SJohn Marino 	if (write (fd, outbuf, sizeof (outbuf) - zstr.avail_out) < 0)
617*86d7f5d3SJohn Marino 	{
618*86d7f5d3SJohn Marino 	    error (0, errno, "writing decompressed file %s", fullname);
619*86d7f5d3SJohn Marino 	    return 1;
620*86d7f5d3SJohn Marino 	}
621*86d7f5d3SJohn Marino 	crc = crc32 (crc, outbuf, sizeof (outbuf) - zstr.avail_out);
622*86d7f5d3SJohn Marino     } while (zstatus != Z_STREAM_END);
623*86d7f5d3SJohn Marino     zstatus = inflateEnd (&zstr);
624*86d7f5d3SJohn Marino     if (zstatus != Z_OK)
625*86d7f5d3SJohn Marino 	compress_error (0, zstatus, &zstr, fullname);
626*86d7f5d3SJohn Marino 
627*86d7f5d3SJohn Marino     /* Check that there is still 8 trailer bytes remaining (CRC32
628*86d7f5d3SJohn Marino        and ISIZE).  Check total decomp. data, plus header len (pos)
629*86d7f5d3SJohn Marino        against input buffer total size.  */
630*86d7f5d3SJohn Marino     pos += zstr.total_in;
631*86d7f5d3SJohn Marino     if (size - pos != 8)
632*86d7f5d3SJohn Marino     {
633*86d7f5d3SJohn Marino 	error (0, 0, "gzip data incomplete for %s (no trailer)", fullname);
634*86d7f5d3SJohn Marino 	return 1;
635*86d7f5d3SJohn Marino     }
636*86d7f5d3SJohn Marino 
637*86d7f5d3SJohn Marino     if (crc != ((unsigned long)buf[pos]
638*86d7f5d3SJohn Marino 		+ ((unsigned long)buf[pos + 1] << 8)
639*86d7f5d3SJohn Marino 		+ ((unsigned long)buf[pos + 2] << 16)
640*86d7f5d3SJohn Marino 		+ ((unsigned long)buf[pos + 3] << 24)))
641*86d7f5d3SJohn Marino     {
642*86d7f5d3SJohn Marino 	error (0, 0, "CRC error uncompressing %s", fullname);
643*86d7f5d3SJohn Marino 	return 1;
644*86d7f5d3SJohn Marino     }
645*86d7f5d3SJohn Marino 
646*86d7f5d3SJohn Marino     if (zstr.total_out != ((unsigned long)buf[pos + 4]
647*86d7f5d3SJohn Marino 			   + ((unsigned long)buf[pos + 5] << 8)
648*86d7f5d3SJohn Marino 			   + ((unsigned long)buf[pos + 6] << 16)
649*86d7f5d3SJohn Marino 			   + ((unsigned long)buf[pos + 7] << 24)))
650*86d7f5d3SJohn Marino     {
651*86d7f5d3SJohn Marino 	error (0, 0, "invalid length uncompressing %s", fullname);
652*86d7f5d3SJohn Marino 	return 1;
653*86d7f5d3SJohn Marino     }
654*86d7f5d3SJohn Marino 
655*86d7f5d3SJohn Marino     return 0;
656*86d7f5d3SJohn Marino }
657*86d7f5d3SJohn Marino 
658*86d7f5d3SJohn Marino /* Read all of FD and put the gzipped data (RFC1952/RFC1951) into *BUF,
659*86d7f5d3SJohn Marino    replacing previous contents of *BUF.  *BUF is xmalloc'd and *SIZE is
660*86d7f5d3SJohn Marino    its allocated size.  Put the actual number of bytes of data in
661*86d7f5d3SJohn Marino    *LEN.  If something goes wrong, give a nonfatal error mentioning
662*86d7f5d3SJohn Marino    FULLNAME as the name of the file for FD, and return 1 if we can't
663*86d7f5d3SJohn Marino    recover from it).  LEVEL is the compression level (1-9).  */
664*86d7f5d3SJohn Marino 
665*86d7f5d3SJohn Marino int
read_and_gzip(int fd,const char * fullname,unsigned char ** buf,size_t * size,size_t * len,int level)666*86d7f5d3SJohn Marino read_and_gzip (int fd, const char *fullname, unsigned char **buf, size_t *size,
667*86d7f5d3SJohn Marino                size_t *len, int level)
668*86d7f5d3SJohn Marino {
669*86d7f5d3SJohn Marino     z_stream zstr;
670*86d7f5d3SJohn Marino     int zstatus;
671*86d7f5d3SJohn Marino     unsigned char inbuf[8192];
672*86d7f5d3SJohn Marino     int nread;
673*86d7f5d3SJohn Marino     unsigned long crc;
674*86d7f5d3SJohn Marino 
675*86d7f5d3SJohn Marino     if (*size < 1024)
676*86d7f5d3SJohn Marino     {
677*86d7f5d3SJohn Marino 	unsigned char *newbuf;
678*86d7f5d3SJohn Marino 
679*86d7f5d3SJohn Marino 	*size = 1024;
680*86d7f5d3SJohn Marino 	newbuf = xrealloc (*buf, *size);
681*86d7f5d3SJohn Marino 	if (newbuf == NULL)
682*86d7f5d3SJohn Marino 	{
683*86d7f5d3SJohn Marino 	    error (0, 0, "out of memory");
684*86d7f5d3SJohn Marino 	    return 1;
685*86d7f5d3SJohn Marino 	}
686*86d7f5d3SJohn Marino 	*buf = newbuf;
687*86d7f5d3SJohn Marino     }
688*86d7f5d3SJohn Marino     (*buf)[0] = GZIP_ID1;
689*86d7f5d3SJohn Marino     (*buf)[1] = GZIP_ID2;
690*86d7f5d3SJohn Marino     (*buf)[2] = GZIP_CDEFLATE;
691*86d7f5d3SJohn Marino     (*buf)[3] = 0;
692*86d7f5d3SJohn Marino     (*buf)[4] = (*buf)[5] = (*buf)[6] = (*buf)[7] = 0;
693*86d7f5d3SJohn Marino     /* Could set this based on level, but why bother?  */
694*86d7f5d3SJohn Marino     (*buf)[8] = 0;
695*86d7f5d3SJohn Marino     (*buf)[9] = 255;
696*86d7f5d3SJohn Marino 
697*86d7f5d3SJohn Marino     memset (&zstr, 0, sizeof zstr);
698*86d7f5d3SJohn Marino     zstatus = deflateInit2 (&zstr, level, Z_DEFLATED, -15, 8,
699*86d7f5d3SJohn Marino 			    Z_DEFAULT_STRATEGY);
700*86d7f5d3SJohn Marino     crc = crc32 (0, NULL, 0);
701*86d7f5d3SJohn Marino     if (zstatus != Z_OK)
702*86d7f5d3SJohn Marino     {
703*86d7f5d3SJohn Marino 	compress_error (0, zstatus, &zstr, fullname);
704*86d7f5d3SJohn Marino 	return 1;
705*86d7f5d3SJohn Marino     }
706*86d7f5d3SJohn Marino 
707*86d7f5d3SJohn Marino     /* Adjust for 10-byte output header (filled in above) */
708*86d7f5d3SJohn Marino     zstr.total_out = 10;
709*86d7f5d3SJohn Marino     zstr.avail_out = *size - 10;
710*86d7f5d3SJohn Marino     zstr.next_out = *buf + 10;
711*86d7f5d3SJohn Marino 
712*86d7f5d3SJohn Marino     while (1)
713*86d7f5d3SJohn Marino     {
714*86d7f5d3SJohn Marino 	int finish = 0;
715*86d7f5d3SJohn Marino 
716*86d7f5d3SJohn Marino 	nread = read (fd, inbuf, sizeof inbuf);
717*86d7f5d3SJohn Marino 	if (nread < 0)
718*86d7f5d3SJohn Marino 	{
719*86d7f5d3SJohn Marino 	    error (0, errno, "cannot read %s", fullname);
720*86d7f5d3SJohn Marino 	    return 1;
721*86d7f5d3SJohn Marino 	}
722*86d7f5d3SJohn Marino 	else if (nread == 0)
723*86d7f5d3SJohn Marino 	    /* End of file.  */
724*86d7f5d3SJohn Marino 	    finish = 1;
725*86d7f5d3SJohn Marino 	crc = crc32 (crc, inbuf, nread);
726*86d7f5d3SJohn Marino 	zstr.next_in = inbuf;
727*86d7f5d3SJohn Marino 	zstr.avail_in = nread;
728*86d7f5d3SJohn Marino 
729*86d7f5d3SJohn Marino 	do
730*86d7f5d3SJohn Marino 	{
731*86d7f5d3SJohn Marino 	    /* I don't see this documented anywhere, but deflate seems
732*86d7f5d3SJohn Marino 	       to tend to dump core sometimes if we pass it Z_FINISH and
733*86d7f5d3SJohn Marino 	       a small (e.g. 2147 byte) avail_out.  So we insist on at
734*86d7f5d3SJohn Marino 	       least 4096 bytes (that is what zlib/gzio.c uses).  */
735*86d7f5d3SJohn Marino 
736*86d7f5d3SJohn Marino 	    if (zstr.avail_out < 4096)
737*86d7f5d3SJohn Marino 	    {
738*86d7f5d3SJohn Marino 		unsigned char *newbuf;
739*86d7f5d3SJohn Marino 
740*86d7f5d3SJohn Marino 		assert(zstr.avail_out + zstr.total_out == *size);
741*86d7f5d3SJohn Marino 		assert(zstr.next_out == *buf + zstr.total_out);
742*86d7f5d3SJohn Marino 		*size *= 2;
743*86d7f5d3SJohn Marino 		newbuf = xrealloc (*buf, *size);
744*86d7f5d3SJohn Marino 		if (newbuf == NULL)
745*86d7f5d3SJohn Marino 		{
746*86d7f5d3SJohn Marino 		    error (0, 0, "out of memory");
747*86d7f5d3SJohn Marino 		    return 1;
748*86d7f5d3SJohn Marino 		}
749*86d7f5d3SJohn Marino 		*buf = newbuf;
750*86d7f5d3SJohn Marino 		zstr.next_out = *buf + zstr.total_out;
751*86d7f5d3SJohn Marino 		zstr.avail_out = *size - zstr.total_out;
752*86d7f5d3SJohn Marino 		assert(zstr.avail_out + zstr.total_out == *size);
753*86d7f5d3SJohn Marino 		assert(zstr.next_out == *buf + zstr.total_out);
754*86d7f5d3SJohn Marino 	    }
755*86d7f5d3SJohn Marino 
756*86d7f5d3SJohn Marino 	    zstatus = deflate (&zstr, finish ? Z_FINISH : 0);
757*86d7f5d3SJohn Marino 	    if (zstatus == Z_STREAM_END)
758*86d7f5d3SJohn Marino 		goto done;
759*86d7f5d3SJohn Marino 	    else if (zstatus != Z_OK)
760*86d7f5d3SJohn Marino 		compress_error (0, zstatus, &zstr, fullname);
761*86d7f5d3SJohn Marino 	} while (zstr.avail_out == 0);
762*86d7f5d3SJohn Marino     }
763*86d7f5d3SJohn Marino  done:
764*86d7f5d3SJohn Marino     /* Need to add the CRC information (8 bytes)
765*86d7f5d3SJohn Marino        to the end of the gzip'd output.
766*86d7f5d3SJohn Marino        Ensure there is enough space in the output buffer
767*86d7f5d3SJohn Marino        to do so.  */
768*86d7f5d3SJohn Marino     if (zstr.avail_out < 8)
769*86d7f5d3SJohn Marino     {
770*86d7f5d3SJohn Marino 	unsigned char *newbuf;
771*86d7f5d3SJohn Marino 
772*86d7f5d3SJohn Marino 	assert(zstr.avail_out + zstr.total_out == *size);
773*86d7f5d3SJohn Marino 	assert(zstr.next_out == *buf + zstr.total_out);
774*86d7f5d3SJohn Marino 	*size += 8 - zstr.avail_out;
775*86d7f5d3SJohn Marino 	newbuf = realloc (*buf, *size);
776*86d7f5d3SJohn Marino 	if (newbuf == NULL)
777*86d7f5d3SJohn Marino 	{
778*86d7f5d3SJohn Marino 	    error (0, 0, "out of memory");
779*86d7f5d3SJohn Marino 	    return 1;
780*86d7f5d3SJohn Marino 	}
781*86d7f5d3SJohn Marino 	*buf = newbuf;
782*86d7f5d3SJohn Marino 	zstr.next_out = *buf + zstr.total_out;
783*86d7f5d3SJohn Marino 	zstr.avail_out = *size - zstr.total_out;
784*86d7f5d3SJohn Marino 	assert(zstr.avail_out + zstr.total_out == *size);
785*86d7f5d3SJohn Marino 	assert(zstr.next_out == *buf + zstr.total_out);
786*86d7f5d3SJohn Marino     }
787*86d7f5d3SJohn Marino     *zstr.next_out++ = (unsigned char)(crc & 0xff);
788*86d7f5d3SJohn Marino     *zstr.next_out++ = (unsigned char)((crc >> 8) & 0xff);
789*86d7f5d3SJohn Marino     *zstr.next_out++ = (unsigned char)((crc >> 16) & 0xff);
790*86d7f5d3SJohn Marino     *zstr.next_out++ = (unsigned char)((crc >> 24) & 0xff);
791*86d7f5d3SJohn Marino 
792*86d7f5d3SJohn Marino     *zstr.next_out++ = (unsigned char)(zstr.total_in & 0xff);
793*86d7f5d3SJohn Marino     *zstr.next_out++ = (unsigned char)((zstr.total_in >> 8) & 0xff);
794*86d7f5d3SJohn Marino     *zstr.next_out++ = (unsigned char)((zstr.total_in >> 16) & 0xff);
795*86d7f5d3SJohn Marino     *zstr.next_out++ = (unsigned char)((zstr.total_in >> 24) & 0xff);
796*86d7f5d3SJohn Marino 
797*86d7f5d3SJohn Marino     zstr.total_out += 8;
798*86d7f5d3SJohn Marino     zstr.avail_out -= 8;
799*86d7f5d3SJohn Marino     assert(zstr.avail_out + zstr.total_out == *size);
800*86d7f5d3SJohn Marino     assert(zstr.next_out == *buf + zstr.total_out);
801*86d7f5d3SJohn Marino 
802*86d7f5d3SJohn Marino     *len = zstr.total_out;
803*86d7f5d3SJohn Marino 
804*86d7f5d3SJohn Marino     zstatus = deflateEnd (&zstr);
805*86d7f5d3SJohn Marino     if (zstatus != Z_OK)
806*86d7f5d3SJohn Marino 	compress_error (0, zstatus, &zstr, fullname);
807*86d7f5d3SJohn Marino 
808*86d7f5d3SJohn Marino     return 0;
809*86d7f5d3SJohn Marino }
810*86d7f5d3SJohn Marino #endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
811