tcompress.c - mixmaster - mixmaster 3.0 patched for libressl
HTML git clone git://parazyd.org/mixmaster.git
DIR Log
DIR Files
DIR Refs
DIR README
---
tcompress.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 }