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