mixmaster

mixmaster 3.0 patched for libressl
git clone git://parazyd.org/mixmaster.git
Log | Files | Refs | README

compress.c (4790B)


      1 /* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
      2 
      3    Mixmaster may be redistributed and modified under certain conditions.
      4    This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
      5    ANY KIND, either express or implied. See the file COPYRIGHT for
      6    details.
      7 
      8    Buffer compression (interface to zlib)
      9    $Id: compress.c 934 2006-06-24 13:40:39Z rabbi $ */
     10 
     11 
     12 #include "mix3.h"
     13 #include <stdio.h>
     14 #include <assert.h>
     15 
     16 static byte gz_magic[2] =
     17 {0x1f, 0x8b};			/* gzip magic header */
     18 
     19 /* gzip flag byte */
     20 #define ASCII_FLAG   0x01
     21 #define HEAD_CRC     0x02
     22 #define EXTRA_FIELD  0x04
     23 #define ORIG_NAME    0x08
     24 #define COMMENT      0x10
     25 #define RESERVED     0xE0
     26 #define Z_DEFLATED   8
     27 
     28 #ifdef USE_ZLIB
     29 #include "zlib.h"
     30 
     31 int buf_unzip(BUFFER *in, int type)
     32 {
     33   BUFFER *out;
     34   z_stream s;
     35   long outstart;
     36   int err;
     37   int ret = 0;
     38 
     39   out = buf_new();
     40 
     41   s.zalloc = (alloc_func) 0;
     42   s.zfree = (free_func) 0;
     43   s.opaque = (voidpf) 0;
     44 
     45   s.next_in = in->data + in->ptr;
     46   s.avail_in = in->length + 1 - in->ptr;	/* terminating 0 byte as "dummy" */
     47   s.next_out = NULL;
     48 
     49   if (type == 1)
     50     err = inflateInit(&s);    /* zlib */
     51   else
     52     err = inflateInit2(&s, -MAX_WBITS);
     53   if (err != Z_OK) {
     54     ret = -1;
     55     goto end;
     56   }
     57   outstart = 0;
     58   buf_append(out, NULL, in->length * 15 / 10);
     59 
     60   for (;;) {
     61     s.next_out = out->data + s.total_out + outstart;
     62     s.avail_out = out->length - outstart - s.total_out;
     63     err = inflate(&s, Z_PARTIAL_FLUSH);
     64     out->length -= s.avail_out;
     65     if (err != Z_OK)
     66       break;
     67     buf_append(out, NULL, BUFSIZE);
     68   }
     69   if (err != Z_STREAM_END)
     70     errlog(WARNING, "Decompression error %d\n", err);
     71 
     72   err = inflateEnd(&s);
     73   if (err != Z_OK)
     74     ret = -1;
     75 end:
     76   if (ret != 0)
     77     switch (err) {
     78     case Z_STREAM_ERROR:
     79       errlog(ERRORMSG, "Decompression error Z_STREAM_ERROR.\n", err);
     80       break;
     81     case Z_MEM_ERROR:
     82       errlog(ERRORMSG, "Decompression error Z_MEM_ERROR.\n", err);
     83       break;
     84     case Z_BUF_ERROR:
     85       errlog(ERRORMSG, "Decompression error Z_BUF_ERROR.\n", err);
     86       break;
     87     case Z_VERSION_ERROR:
     88       errlog(ERRORMSG, "Decompression error Z_VERSION_ERROR.\n", err);
     89       break;
     90     default:
     91       errlog(ERRORMSG, "Decompression error %d.\n", err);
     92     }
     93   buf_move(in, out);
     94   buf_free(out);
     95   return (ret);
     96 }
     97 
     98 int buf_zip(BUFFER *out, BUFFER *in, int bits)
     99 {
    100   z_stream s;
    101   long outstart;
    102   int err = -1;
    103 
    104   assert(in != out);
    105 
    106   s.zalloc = (alloc_func) 0;
    107   s.zfree = (free_func) 0;
    108   s.opaque = (voidpf) 0;
    109   s.next_in = NULL;
    110 
    111   if (bits == 0)
    112     bits = MAX_WBITS;
    113 
    114   if (deflateInit2(&s, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -bits, 8, 0) != Z_OK)
    115     goto end;
    116 
    117   outstart = out->length;
    118   /* 12 is overhead, 1.01 is maximum expansion, and 1 is there to force a round-up */
    119   buf_append(out, NULL, (int)13+in->length*1.01); /* fit it in one chunk */
    120 
    121   s.next_in = in->data;
    122   s.avail_in = in->length;
    123 
    124   for (;;) {
    125     s.next_out = out->data + s.total_out + outstart;
    126     s.avail_out = out->length - outstart - s.total_out;
    127     err = deflate(&s, Z_FINISH);
    128     out->length -= s.avail_out;
    129     if (err != Z_OK)
    130       break;
    131     errlog(ERRORMSG, "Compressed data did not fit in one chunk.\n");
    132     buf_append(out, NULL, BUFSIZE);
    133   }
    134   if (deflateEnd(&s) != Z_OK || err != Z_STREAM_END)
    135     err = -1;
    136   else
    137     err = 0;
    138 end:
    139   if (err != 0)
    140     errlog(ERRORMSG, "Compression error.\n");
    141   return (err);
    142 }
    143 
    144 #else /* end of USE_ZLIB */
    145 int buf_zip(BUFFER *out, BUFFER *in, int bits)
    146 {
    147   return (-1);
    148 }
    149 
    150 int buf_unzip(BUFFER *b, int type)
    151 {
    152   errlog(ERRORMSG, "Can't uncompress: no zlib\n");
    153   return (-1);
    154 }
    155 #endif /* else not USE_ZLIB */
    156 
    157 int compressed(BUFFER *b)
    158 {
    159   return (b->length >= 10 && b->data[0] == gz_magic[0] &&
    160 	  b->data[1] == gz_magic[1]);
    161 }
    162 
    163 int buf_uncompress(BUFFER *in)
    164 {
    165   int type;
    166   int err = -1;
    167   unsigned int len;
    168 
    169   if (!compressed(in))
    170     return (0);
    171   type = in->data[3];
    172   if (in->data[2] != Z_DEFLATED || (type & RESERVED) == 0) {
    173     in->ptr = 10;
    174     if ((type & EXTRA_FIELD) != 0) {
    175       len = buf_geti(in);
    176       in->ptr += len;
    177     }
    178     if ((type & ORIG_NAME) != 0)
    179       while (buf_getc(in) > 0) ;
    180     if ((type & COMMENT) != 0)
    181       while (buf_getc(in) > 0) ;
    182     if ((type & HEAD_CRC) != 0)
    183       buf_geti(in);
    184     err = buf_unzip(in, 0);
    185   }
    186   return (err);
    187 }
    188 
    189 int buf_compress(BUFFER *in)
    190 {
    191   BUFFER *out;
    192   int err;
    193 
    194   if (compressed(in))
    195     return (0);
    196 
    197   out = buf_new();
    198   buf_appendc(out, gz_magic[0]);
    199   buf_appendc(out, gz_magic[1]);
    200   buf_appendc(out, Z_DEFLATED);
    201   buf_appendc(out, 0);		/* flags */
    202   buf_appendl(out, 0);		/* time */
    203   buf_appendc(out, 0);		/* xflags */
    204   buf_appendc(out, 3);		/* Unix */
    205   err = buf_zip(out, in, 0);
    206   if (err == 0)
    207     buf_move(in, out);
    208   buf_free(out);
    209   return (err);
    210 }