1 |
|
|
/* $OpenBSD: c_zlib.c,v 1.19 2017/01/29 17:49:22 beck Exp $ */ |
2 |
|
|
#include <stdio.h> |
3 |
|
|
#include <stdlib.h> |
4 |
|
|
#include <string.h> |
5 |
|
|
#include <openssl/objects.h> |
6 |
|
|
#include <openssl/comp.h> |
7 |
|
|
#include <openssl/err.h> |
8 |
|
|
|
9 |
|
|
COMP_METHOD *COMP_zlib(void ); |
10 |
|
|
|
11 |
|
|
static COMP_METHOD zlib_method_nozlib = { |
12 |
|
|
.type = NID_undef, |
13 |
|
|
.name = "(undef)" |
14 |
|
|
}; |
15 |
|
|
|
16 |
|
|
#ifdef ZLIB |
17 |
|
|
|
18 |
|
|
#include <zlib.h> |
19 |
|
|
|
20 |
|
|
static int zlib_stateful_init(COMP_CTX *ctx); |
21 |
|
|
static void zlib_stateful_finish(COMP_CTX *ctx); |
22 |
|
|
static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, |
23 |
|
|
unsigned int olen, unsigned char *in, unsigned int ilen); |
24 |
|
|
static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, |
25 |
|
|
unsigned int olen, unsigned char *in, unsigned int ilen); |
26 |
|
|
|
27 |
|
|
|
28 |
|
|
/* memory allocations functions for zlib intialization */ |
29 |
|
|
static void* |
30 |
|
|
zlib_zalloc(void* opaque, unsigned int no, unsigned int size) |
31 |
|
|
{ |
32 |
|
|
return calloc(no, size); |
33 |
|
|
} |
34 |
|
|
|
35 |
|
|
static void |
36 |
|
|
zlib_zfree(void* opaque, void* address) |
37 |
|
|
{ |
38 |
|
|
free(address); |
39 |
|
|
} |
40 |
|
|
|
41 |
|
|
static COMP_METHOD zlib_stateful_method = { |
42 |
|
|
.type = NID_zlib_compression, |
43 |
|
|
.name = LN_zlib_compression, |
44 |
|
|
.init = zlib_stateful_init, |
45 |
|
|
.finish = zlib_stateful_finish, |
46 |
|
|
.compress = zlib_stateful_compress_block, |
47 |
|
|
.expand = zlib_stateful_expand_block |
48 |
|
|
}; |
49 |
|
|
|
50 |
|
|
struct zlib_state { |
51 |
|
|
z_stream istream; |
52 |
|
|
z_stream ostream; |
53 |
|
|
}; |
54 |
|
|
|
55 |
|
|
static int zlib_stateful_ex_idx = -1; |
56 |
|
|
|
57 |
|
|
static int |
58 |
|
|
zlib_stateful_init(COMP_CTX *ctx) |
59 |
|
|
{ |
60 |
|
|
int err; |
61 |
|
|
struct zlib_state *state = malloc(sizeof(struct zlib_state)); |
62 |
|
|
|
63 |
|
|
if (state == NULL) |
64 |
|
|
goto err; |
65 |
|
|
|
66 |
|
|
state->istream.zalloc = zlib_zalloc; |
67 |
|
|
state->istream.zfree = zlib_zfree; |
68 |
|
|
state->istream.opaque = Z_NULL; |
69 |
|
|
state->istream.next_in = Z_NULL; |
70 |
|
|
state->istream.next_out = Z_NULL; |
71 |
|
|
state->istream.avail_in = 0; |
72 |
|
|
state->istream.avail_out = 0; |
73 |
|
|
err = inflateInit_(&state->istream, ZLIB_VERSION, sizeof(z_stream)); |
74 |
|
|
if (err != Z_OK) |
75 |
|
|
goto err; |
76 |
|
|
|
77 |
|
|
state->ostream.zalloc = zlib_zalloc; |
78 |
|
|
state->ostream.zfree = zlib_zfree; |
79 |
|
|
state->ostream.opaque = Z_NULL; |
80 |
|
|
state->ostream.next_in = Z_NULL; |
81 |
|
|
state->ostream.next_out = Z_NULL; |
82 |
|
|
state->ostream.avail_in = 0; |
83 |
|
|
state->ostream.avail_out = 0; |
84 |
|
|
err = deflateInit_(&state->ostream, Z_DEFAULT_COMPRESSION, |
85 |
|
|
ZLIB_VERSION, sizeof(z_stream)); |
86 |
|
|
if (err != Z_OK) |
87 |
|
|
goto err; |
88 |
|
|
|
89 |
|
|
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_COMP, ctx, &ctx->ex_data); |
90 |
|
|
CRYPTO_set_ex_data(&ctx->ex_data, zlib_stateful_ex_idx, state); |
91 |
|
|
return 1; |
92 |
|
|
|
93 |
|
|
err: |
94 |
|
|
free(state); |
95 |
|
|
return 0; |
96 |
|
|
} |
97 |
|
|
|
98 |
|
|
static void |
99 |
|
|
zlib_stateful_finish(COMP_CTX *ctx) |
100 |
|
|
{ |
101 |
|
|
struct zlib_state *state = |
102 |
|
|
(struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, |
103 |
|
|
zlib_stateful_ex_idx); |
104 |
|
|
|
105 |
|
|
inflateEnd(&state->istream); |
106 |
|
|
deflateEnd(&state->ostream); |
107 |
|
|
free(state); |
108 |
|
|
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP, ctx, &ctx->ex_data); |
109 |
|
|
} |
110 |
|
|
|
111 |
|
|
static int |
112 |
|
|
zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, |
113 |
|
|
unsigned int olen, unsigned char *in, unsigned int ilen) |
114 |
|
|
{ |
115 |
|
|
int err = Z_OK; |
116 |
|
|
struct zlib_state *state = |
117 |
|
|
(struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, |
118 |
|
|
zlib_stateful_ex_idx); |
119 |
|
|
|
120 |
|
|
if (state == NULL) |
121 |
|
|
return -1; |
122 |
|
|
|
123 |
|
|
state->ostream.next_in = in; |
124 |
|
|
state->ostream.avail_in = ilen; |
125 |
|
|
state->ostream.next_out = out; |
126 |
|
|
state->ostream.avail_out = olen; |
127 |
|
|
if (ilen > 0) |
128 |
|
|
err = deflate(&state->ostream, Z_SYNC_FLUSH); |
129 |
|
|
if (err != Z_OK) |
130 |
|
|
return -1; |
131 |
|
|
|
132 |
|
|
#ifdef DEBUG_ZLIB |
133 |
|
|
fprintf(stderr, "compress(%4d)->%4d %s\n", |
134 |
|
|
ilen, olen - state->ostream.avail_out, |
135 |
|
|
(ilen != olen - state->ostream.avail_out)?"zlib":"clear"); |
136 |
|
|
#endif |
137 |
|
|
|
138 |
|
|
return olen - state->ostream.avail_out; |
139 |
|
|
} |
140 |
|
|
|
141 |
|
|
static int |
142 |
|
|
zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, |
143 |
|
|
unsigned int olen, unsigned char *in, unsigned int ilen) |
144 |
|
|
{ |
145 |
|
|
int err = Z_OK; |
146 |
|
|
|
147 |
|
|
struct zlib_state *state = |
148 |
|
|
(struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, |
149 |
|
|
zlib_stateful_ex_idx); |
150 |
|
|
|
151 |
|
|
if (state == NULL) |
152 |
|
|
return 0; |
153 |
|
|
|
154 |
|
|
state->istream.next_in = in; |
155 |
|
|
state->istream.avail_in = ilen; |
156 |
|
|
state->istream.next_out = out; |
157 |
|
|
state->istream.avail_out = olen; |
158 |
|
|
if (ilen > 0) |
159 |
|
|
err = inflate(&state->istream, Z_SYNC_FLUSH); |
160 |
|
|
if (err != Z_OK) |
161 |
|
|
return -1; |
162 |
|
|
|
163 |
|
|
#ifdef DEBUG_ZLIB |
164 |
|
|
fprintf(stderr, "expand(%4d)->%4d %s\n", |
165 |
|
|
ilen, olen - state->istream.avail_out, |
166 |
|
|
(ilen != olen - state->istream.avail_out)?"zlib":"clear"); |
167 |
|
|
#endif |
168 |
|
|
|
169 |
|
|
return olen - state->istream.avail_out; |
170 |
|
|
} |
171 |
|
|
|
172 |
|
|
#endif |
173 |
|
|
|
174 |
|
|
COMP_METHOD * |
175 |
|
|
COMP_zlib(void) |
176 |
|
|
{ |
177 |
|
|
COMP_METHOD *meth = &zlib_method_nozlib; |
178 |
|
|
|
179 |
|
|
#ifdef ZLIB |
180 |
|
|
{ |
181 |
|
|
/* init zlib_stateful_ex_idx here so that in a multi-process |
182 |
|
|
* application it's enough to intialize openssl before forking |
183 |
|
|
* (idx will be inherited in all the children) */ |
184 |
|
|
if (zlib_stateful_ex_idx == -1) { |
185 |
|
|
CRYPTO_w_lock(CRYPTO_LOCK_COMP); |
186 |
|
|
if (zlib_stateful_ex_idx == -1) |
187 |
|
|
zlib_stateful_ex_idx = |
188 |
|
|
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_COMP, |
189 |
|
|
0, NULL, NULL, NULL, NULL); |
190 |
|
|
CRYPTO_w_unlock(CRYPTO_LOCK_COMP); |
191 |
|
|
if (zlib_stateful_ex_idx == -1) |
192 |
|
|
goto err; |
193 |
|
|
} |
194 |
|
|
|
195 |
|
|
meth = &zlib_stateful_method; |
196 |
|
|
} |
197 |
|
|
|
198 |
|
|
err: |
199 |
|
|
#endif |
200 |
|
|
|
201 |
|
|
return (meth); |
202 |
|
|
} |
203 |
|
|
|
204 |
|
|
void |
205 |
|
|
COMP_zlib_cleanup(void) |
206 |
|
|
{ |
207 |
|
|
} |
208 |
|
|
|
209 |
|
|
#ifdef ZLIB |
210 |
|
|
|
211 |
|
|
/* Zlib based compression/decompression filter BIO */ |
212 |
|
|
|
213 |
|
|
typedef struct { |
214 |
|
|
unsigned char *ibuf; /* Input buffer */ |
215 |
|
|
int ibufsize; /* Buffer size */ |
216 |
|
|
z_stream zin; /* Input decompress context */ |
217 |
|
|
unsigned char *obuf; /* Output buffer */ |
218 |
|
|
int obufsize; /* Output buffer size */ |
219 |
|
|
unsigned char *optr; /* Position in output buffer */ |
220 |
|
|
int ocount; /* Amount of data in output buffer */ |
221 |
|
|
int odone; /* deflate EOF */ |
222 |
|
|
int comp_level; /* Compression level to use */ |
223 |
|
|
z_stream zout; /* Output compression context */ |
224 |
|
|
} BIO_ZLIB_CTX; |
225 |
|
|
|
226 |
|
|
#define ZLIB_DEFAULT_BUFSIZE 1024 |
227 |
|
|
|
228 |
|
|
static int bio_zlib_new(BIO *bi); |
229 |
|
|
static int bio_zlib_free(BIO *bi); |
230 |
|
|
static int bio_zlib_read(BIO *b, char *out, int outl); |
231 |
|
|
static int bio_zlib_write(BIO *b, const char *in, int inl); |
232 |
|
|
static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr); |
233 |
|
|
static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp); |
234 |
|
|
|
235 |
|
|
static BIO_METHOD bio_meth_zlib = { |
236 |
|
|
.type = BIO_TYPE_COMP, |
237 |
|
|
.name = "zlib", |
238 |
|
|
.bwrite = bio_zlib_write, |
239 |
|
|
.bread = bio_zlib_read, |
240 |
|
|
.ctrl = bio_zlib_ctrl, |
241 |
|
|
.create = bio_zlib_new, |
242 |
|
|
.destroy = bio_zlib_free, |
243 |
|
|
.callback_ctrl = bio_zlib_callback_ctrl |
244 |
|
|
}; |
245 |
|
|
|
246 |
|
|
BIO_METHOD * |
247 |
|
|
BIO_f_zlib(void) |
248 |
|
|
{ |
249 |
|
|
return &bio_meth_zlib; |
250 |
|
|
} |
251 |
|
|
|
252 |
|
|
|
253 |
|
|
static int |
254 |
|
|
bio_zlib_new(BIO *bi) |
255 |
|
|
{ |
256 |
|
|
BIO_ZLIB_CTX *ctx; |
257 |
|
|
|
258 |
|
|
ctx = malloc(sizeof(BIO_ZLIB_CTX)); |
259 |
|
|
if (!ctx) { |
260 |
|
|
COMPerror(ERR_R_MALLOC_FAILURE); |
261 |
|
|
return 0; |
262 |
|
|
} |
263 |
|
|
ctx->ibuf = NULL; |
264 |
|
|
ctx->obuf = NULL; |
265 |
|
|
ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE; |
266 |
|
|
ctx->obufsize = ZLIB_DEFAULT_BUFSIZE; |
267 |
|
|
ctx->zin.zalloc = Z_NULL; |
268 |
|
|
ctx->zin.zfree = Z_NULL; |
269 |
|
|
ctx->zin.next_in = NULL; |
270 |
|
|
ctx->zin.avail_in = 0; |
271 |
|
|
ctx->zin.next_out = NULL; |
272 |
|
|
ctx->zin.avail_out = 0; |
273 |
|
|
ctx->zout.zalloc = Z_NULL; |
274 |
|
|
ctx->zout.zfree = Z_NULL; |
275 |
|
|
ctx->zout.next_in = NULL; |
276 |
|
|
ctx->zout.avail_in = 0; |
277 |
|
|
ctx->zout.next_out = NULL; |
278 |
|
|
ctx->zout.avail_out = 0; |
279 |
|
|
ctx->odone = 0; |
280 |
|
|
ctx->comp_level = Z_DEFAULT_COMPRESSION; |
281 |
|
|
bi->init = 1; |
282 |
|
|
bi->ptr = (char *)ctx; |
283 |
|
|
bi->flags = 0; |
284 |
|
|
return 1; |
285 |
|
|
} |
286 |
|
|
|
287 |
|
|
static int |
288 |
|
|
bio_zlib_free(BIO *bi) |
289 |
|
|
{ |
290 |
|
|
BIO_ZLIB_CTX *ctx; |
291 |
|
|
|
292 |
|
|
if (!bi) |
293 |
|
|
return 0; |
294 |
|
|
ctx = (BIO_ZLIB_CTX *)bi->ptr; |
295 |
|
|
if (ctx->ibuf) { |
296 |
|
|
/* Destroy decompress context */ |
297 |
|
|
inflateEnd(&ctx->zin); |
298 |
|
|
free(ctx->ibuf); |
299 |
|
|
} |
300 |
|
|
if (ctx->obuf) { |
301 |
|
|
/* Destroy compress context */ |
302 |
|
|
deflateEnd(&ctx->zout); |
303 |
|
|
free(ctx->obuf); |
304 |
|
|
} |
305 |
|
|
free(ctx); |
306 |
|
|
bi->ptr = NULL; |
307 |
|
|
bi->init = 0; |
308 |
|
|
bi->flags = 0; |
309 |
|
|
return 1; |
310 |
|
|
} |
311 |
|
|
|
312 |
|
|
static int |
313 |
|
|
bio_zlib_read(BIO *b, char *out, int outl) |
314 |
|
|
{ |
315 |
|
|
BIO_ZLIB_CTX *ctx; |
316 |
|
|
int ret; |
317 |
|
|
z_stream *zin; |
318 |
|
|
|
319 |
|
|
if (!out || !outl) |
320 |
|
|
return 0; |
321 |
|
|
ctx = (BIO_ZLIB_CTX *)b->ptr; |
322 |
|
|
zin = &ctx->zin; |
323 |
|
|
BIO_clear_retry_flags(b); |
324 |
|
|
if (!ctx->ibuf) { |
325 |
|
|
ctx->ibuf = malloc(ctx->ibufsize); |
326 |
|
|
if (!ctx->ibuf) { |
327 |
|
|
COMPerror(ERR_R_MALLOC_FAILURE); |
328 |
|
|
return 0; |
329 |
|
|
} |
330 |
|
|
inflateInit(zin); |
331 |
|
|
zin->next_in = ctx->ibuf; |
332 |
|
|
zin->avail_in = 0; |
333 |
|
|
} |
334 |
|
|
|
335 |
|
|
/* Copy output data directly to supplied buffer */ |
336 |
|
|
zin->next_out = (unsigned char *)out; |
337 |
|
|
zin->avail_out = (unsigned int)outl; |
338 |
|
|
for (;;) { |
339 |
|
|
/* Decompress while data available */ |
340 |
|
|
while (zin->avail_in) { |
341 |
|
|
ret = inflate(zin, 0); |
342 |
|
|
if ((ret != Z_OK) && (ret != Z_STREAM_END)) { |
343 |
|
|
COMPerror(COMP_R_ZLIB_INFLATE_ERROR); |
344 |
|
|
ERR_asprintf_error_data("zlib error:%s", |
345 |
|
|
zError(ret)); |
346 |
|
|
return 0; |
347 |
|
|
} |
348 |
|
|
/* If EOF or we've read everything then return */ |
349 |
|
|
if ((ret == Z_STREAM_END) || !zin->avail_out) |
350 |
|
|
return outl - zin->avail_out; |
351 |
|
|
} |
352 |
|
|
|
353 |
|
|
/* No data in input buffer try to read some in, |
354 |
|
|
* if an error then return the total data read. |
355 |
|
|
*/ |
356 |
|
|
ret = BIO_read(b->next_bio, ctx->ibuf, ctx->ibufsize); |
357 |
|
|
if (ret <= 0) { |
358 |
|
|
/* Total data read */ |
359 |
|
|
int tot = outl - zin->avail_out; |
360 |
|
|
BIO_copy_next_retry(b); |
361 |
|
|
if (ret < 0) |
362 |
|
|
return (tot > 0) ? tot : ret; |
363 |
|
|
return tot; |
364 |
|
|
} |
365 |
|
|
zin->avail_in = ret; |
366 |
|
|
zin->next_in = ctx->ibuf; |
367 |
|
|
} |
368 |
|
|
} |
369 |
|
|
|
370 |
|
|
static int |
371 |
|
|
bio_zlib_write(BIO *b, const char *in, int inl) |
372 |
|
|
{ |
373 |
|
|
BIO_ZLIB_CTX *ctx; |
374 |
|
|
int ret; |
375 |
|
|
z_stream *zout; |
376 |
|
|
|
377 |
|
|
if (!in || !inl) |
378 |
|
|
return 0; |
379 |
|
|
ctx = (BIO_ZLIB_CTX *)b->ptr; |
380 |
|
|
if (ctx->odone) |
381 |
|
|
return 0; |
382 |
|
|
zout = &ctx->zout; |
383 |
|
|
BIO_clear_retry_flags(b); |
384 |
|
|
if (!ctx->obuf) { |
385 |
|
|
ctx->obuf = malloc(ctx->obufsize); |
386 |
|
|
/* Need error here */ |
387 |
|
|
if (!ctx->obuf) { |
388 |
|
|
COMPerror(ERR_R_MALLOC_FAILURE); |
389 |
|
|
return 0; |
390 |
|
|
} |
391 |
|
|
ctx->optr = ctx->obuf; |
392 |
|
|
ctx->ocount = 0; |
393 |
|
|
deflateInit(zout, ctx->comp_level); |
394 |
|
|
zout->next_out = ctx->obuf; |
395 |
|
|
zout->avail_out = ctx->obufsize; |
396 |
|
|
} |
397 |
|
|
/* Obtain input data directly from supplied buffer */ |
398 |
|
|
zout->next_in = (void *)in; |
399 |
|
|
zout->avail_in = inl; |
400 |
|
|
for (;;) { |
401 |
|
|
/* If data in output buffer write it first */ |
402 |
|
|
while (ctx->ocount) { |
403 |
|
|
ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount); |
404 |
|
|
if (ret <= 0) { |
405 |
|
|
/* Total data written */ |
406 |
|
|
int tot = inl - zout->avail_in; |
407 |
|
|
BIO_copy_next_retry(b); |
408 |
|
|
if (ret < 0) |
409 |
|
|
return (tot > 0) ? tot : ret; |
410 |
|
|
return tot; |
411 |
|
|
} |
412 |
|
|
ctx->optr += ret; |
413 |
|
|
ctx->ocount -= ret; |
414 |
|
|
} |
415 |
|
|
|
416 |
|
|
/* Have we consumed all supplied data? */ |
417 |
|
|
if (!zout->avail_in) |
418 |
|
|
return inl; |
419 |
|
|
|
420 |
|
|
/* Compress some more */ |
421 |
|
|
|
422 |
|
|
/* Reset buffer */ |
423 |
|
|
ctx->optr = ctx->obuf; |
424 |
|
|
zout->next_out = ctx->obuf; |
425 |
|
|
zout->avail_out = ctx->obufsize; |
426 |
|
|
/* Compress some more */ |
427 |
|
|
ret = deflate(zout, 0); |
428 |
|
|
if (ret != Z_OK) { |
429 |
|
|
COMPerror(COMP_R_ZLIB_DEFLATE_ERROR); |
430 |
|
|
ERR_asprintf_error_data("zlib error:%s", zError(ret)); |
431 |
|
|
return 0; |
432 |
|
|
} |
433 |
|
|
ctx->ocount = ctx->obufsize - zout->avail_out; |
434 |
|
|
} |
435 |
|
|
} |
436 |
|
|
|
437 |
|
|
static int |
438 |
|
|
bio_zlib_flush(BIO *b) |
439 |
|
|
{ |
440 |
|
|
BIO_ZLIB_CTX *ctx; |
441 |
|
|
int ret; |
442 |
|
|
z_stream *zout; |
443 |
|
|
|
444 |
|
|
ctx = (BIO_ZLIB_CTX *)b->ptr; |
445 |
|
|
/* If no data written or already flush show success */ |
446 |
|
|
if (!ctx->obuf || (ctx->odone && !ctx->ocount)) |
447 |
|
|
return 1; |
448 |
|
|
zout = &ctx->zout; |
449 |
|
|
BIO_clear_retry_flags(b); |
450 |
|
|
/* No more input data */ |
451 |
|
|
zout->next_in = NULL; |
452 |
|
|
zout->avail_in = 0; |
453 |
|
|
for (;;) { |
454 |
|
|
/* If data in output buffer write it first */ |
455 |
|
|
while (ctx->ocount) { |
456 |
|
|
ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount); |
457 |
|
|
if (ret <= 0) { |
458 |
|
|
BIO_copy_next_retry(b); |
459 |
|
|
return ret; |
460 |
|
|
} |
461 |
|
|
ctx->optr += ret; |
462 |
|
|
ctx->ocount -= ret; |
463 |
|
|
} |
464 |
|
|
if (ctx->odone) |
465 |
|
|
return 1; |
466 |
|
|
|
467 |
|
|
/* Compress some more */ |
468 |
|
|
|
469 |
|
|
/* Reset buffer */ |
470 |
|
|
ctx->optr = ctx->obuf; |
471 |
|
|
zout->next_out = ctx->obuf; |
472 |
|
|
zout->avail_out = ctx->obufsize; |
473 |
|
|
/* Compress some more */ |
474 |
|
|
ret = deflate(zout, Z_FINISH); |
475 |
|
|
if (ret == Z_STREAM_END) |
476 |
|
|
ctx->odone = 1; |
477 |
|
|
else if (ret != Z_OK) { |
478 |
|
|
COMPerror(COMP_R_ZLIB_DEFLATE_ERROR); |
479 |
|
|
ERR_asprintf_error_data("zlib error:%s", zError(ret)); |
480 |
|
|
return 0; |
481 |
|
|
} |
482 |
|
|
ctx->ocount = ctx->obufsize - zout->avail_out; |
483 |
|
|
} |
484 |
|
|
} |
485 |
|
|
|
486 |
|
|
static long |
487 |
|
|
bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) |
488 |
|
|
{ |
489 |
|
|
BIO_ZLIB_CTX *ctx; |
490 |
|
|
int ret, *ip; |
491 |
|
|
int ibs, obs; |
492 |
|
|
if (!b->next_bio) |
493 |
|
|
return 0; |
494 |
|
|
ctx = (BIO_ZLIB_CTX *)b->ptr; |
495 |
|
|
switch (cmd) { |
496 |
|
|
|
497 |
|
|
case BIO_CTRL_RESET: |
498 |
|
|
ctx->ocount = 0; |
499 |
|
|
ctx->odone = 0; |
500 |
|
|
ret = 1; |
501 |
|
|
break; |
502 |
|
|
|
503 |
|
|
case BIO_CTRL_FLUSH: |
504 |
|
|
ret = bio_zlib_flush(b); |
505 |
|
|
if (ret > 0) |
506 |
|
|
ret = BIO_flush(b->next_bio); |
507 |
|
|
break; |
508 |
|
|
|
509 |
|
|
case BIO_C_SET_BUFF_SIZE: |
510 |
|
|
ibs = -1; |
511 |
|
|
obs = -1; |
512 |
|
|
if (ptr != NULL) { |
513 |
|
|
ip = ptr; |
514 |
|
|
if (*ip == 0) |
515 |
|
|
ibs = (int) num; |
516 |
|
|
else |
517 |
|
|
obs = (int) num; |
518 |
|
|
} else { |
519 |
|
|
ibs = (int)num; |
520 |
|
|
obs = ibs; |
521 |
|
|
} |
522 |
|
|
|
523 |
|
|
if (ibs != -1) { |
524 |
|
|
free(ctx->ibuf); |
525 |
|
|
ctx->ibuf = NULL; |
526 |
|
|
ctx->ibufsize = ibs; |
527 |
|
|
} |
528 |
|
|
|
529 |
|
|
if (obs != -1) { |
530 |
|
|
free(ctx->obuf); |
531 |
|
|
ctx->obuf = NULL; |
532 |
|
|
ctx->obufsize = obs; |
533 |
|
|
} |
534 |
|
|
ret = 1; |
535 |
|
|
break; |
536 |
|
|
|
537 |
|
|
case BIO_C_DO_STATE_MACHINE: |
538 |
|
|
BIO_clear_retry_flags(b); |
539 |
|
|
ret = BIO_ctrl(b->next_bio, cmd, num, ptr); |
540 |
|
|
BIO_copy_next_retry(b); |
541 |
|
|
break; |
542 |
|
|
|
543 |
|
|
default: |
544 |
|
|
ret = BIO_ctrl(b->next_bio, cmd, num, ptr); |
545 |
|
|
break; |
546 |
|
|
|
547 |
|
|
} |
548 |
|
|
|
549 |
|
|
return ret; |
550 |
|
|
} |
551 |
|
|
|
552 |
|
|
|
553 |
|
|
static long |
554 |
|
|
bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) |
555 |
|
|
{ |
556 |
|
|
if (!b->next_bio) |
557 |
|
|
return 0; |
558 |
|
|
return BIO_callback_ctrl(b->next_bio, cmd, fp); |
559 |
|
|
} |
560 |
|
|
|
561 |
|
|
#endif |