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 }