PageRenderTime 52ms CodeModel.GetById 10ms app.highlight 35ms RepoModel.GetById 2ms app.codeStats 0ms

/contrib/cvs/src/zlib.c

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