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