12232f800Sagc /*-
22232f800Sagc * Copyright (c) 2009 The NetBSD Foundation, Inc.
32232f800Sagc * All rights reserved.
42232f800Sagc *
52232f800Sagc * This code is derived from software contributed to The NetBSD Foundation
62232f800Sagc * by Alistair Crooks (agc@NetBSD.org)
72232f800Sagc *
82232f800Sagc * Redistribution and use in source and binary forms, with or without
92232f800Sagc * modification, are permitted provided that the following conditions
102232f800Sagc * are met:
112232f800Sagc * 1. Redistributions of source code must retain the above copyright
122232f800Sagc * notice, this list of conditions and the following disclaimer.
132232f800Sagc * 2. Redistributions in binary form must reproduce the above copyright
142232f800Sagc * notice, this list of conditions and the following disclaimer in the
152232f800Sagc * documentation and/or other materials provided with the distribution.
162232f800Sagc *
172232f800Sagc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
182232f800Sagc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
192232f800Sagc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
202232f800Sagc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
212232f800Sagc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
222232f800Sagc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
232232f800Sagc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
242232f800Sagc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
252232f800Sagc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
262232f800Sagc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
272232f800Sagc * POSSIBILITY OF SUCH DAMAGE.
282232f800Sagc */
2993bf6008Sagc /*
3093bf6008Sagc * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
3193bf6008Sagc * All rights reserved.
3293bf6008Sagc * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
3393bf6008Sagc * their moral rights under the UK Copyright Design and Patents Act 1988 to
3493bf6008Sagc * be recorded as the authors of this copyright work.
3593bf6008Sagc *
3693bf6008Sagc * Licensed under the Apache License, Version 2.0 (the "License"); you may not
3793bf6008Sagc * use this file except in compliance with the License.
3893bf6008Sagc *
3993bf6008Sagc * You may obtain a copy of the License at
4093bf6008Sagc * http://www.apache.org/licenses/LICENSE-2.0
4193bf6008Sagc *
4293bf6008Sagc * Unless required by applicable law or agreed to in writing, software
4393bf6008Sagc * distributed under the License is distributed on an "AS IS" BASIS,
4493bf6008Sagc * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4593bf6008Sagc *
4693bf6008Sagc * See the License for the specific language governing permissions and
4793bf6008Sagc * limitations under the License.
4893bf6008Sagc */
4993bf6008Sagc
5093bf6008Sagc /** \file
5193bf6008Sagc */
5293bf6008Sagc #include "config.h"
5393bf6008Sagc
5457324b9fSagc #ifdef HAVE_SYS_CDEFS_H
5557324b9fSagc #include <sys/cdefs.h>
5657324b9fSagc #endif
5757324b9fSagc
5857324b9fSagc #if defined(__NetBSD__)
5957324b9fSagc __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
60*94fcde8eSchristos __RCSID("$NetBSD: compress.c,v 1.23 2012/03/05 02:20:18 christos Exp $");
6157324b9fSagc #endif
6257324b9fSagc
6393bf6008Sagc #ifdef HAVE_ZLIB_H
6493bf6008Sagc #include <zlib.h>
6593bf6008Sagc #endif
6693bf6008Sagc
6793bf6008Sagc #ifdef HAVE_BZLIB_H
6893bf6008Sagc #include <bzlib.h>
6993bf6008Sagc #endif
7093bf6008Sagc
7193bf6008Sagc #include <string.h>
7293bf6008Sagc
7393bf6008Sagc #include "packet-parse.h"
7493bf6008Sagc #include "errors.h"
7593bf6008Sagc #include "netpgpdefs.h"
764b3a3e18Sagc #include "crypto.h"
7793bf6008Sagc #include "memory.h"
78efdd9dbaSagc #include "writer.h"
7993bf6008Sagc
8093bf6008Sagc #define DECOMPRESS_BUFFER 1024
8193bf6008Sagc
8293bf6008Sagc typedef struct {
83fc1f8641Sagc pgp_compression_type_t type;
84fc1f8641Sagc pgp_region_t *region;
85b15ec256Sagc uint8_t in[DECOMPRESS_BUFFER];
86b15ec256Sagc uint8_t out[DECOMPRESS_BUFFER];
8793bf6008Sagc z_stream zstream;/* ZIP and ZLIB */
8893bf6008Sagc size_t offset;
8993bf6008Sagc int inflate_ret;
9093bf6008Sagc } z_decompress_t;
9193bf6008Sagc
9222b68feaSagc #ifdef HAVE_BZLIB_H
9393bf6008Sagc typedef struct {
94fc1f8641Sagc pgp_compression_type_t type;
95fc1f8641Sagc pgp_region_t *region;
9693bf6008Sagc char in[DECOMPRESS_BUFFER];
9793bf6008Sagc char out[DECOMPRESS_BUFFER];
9893bf6008Sagc bz_stream bzstream; /* BZIP2 */
9993bf6008Sagc size_t offset;
10093bf6008Sagc int inflate_ret;
10193bf6008Sagc } bz_decompress_t;
10222b68feaSagc #endif
10393bf6008Sagc
10493bf6008Sagc typedef struct {
10593bf6008Sagc z_stream stream;
106b15ec256Sagc uint8_t *src;
107b15ec256Sagc uint8_t *dst;
10893bf6008Sagc } compress_t;
10993bf6008Sagc
11093bf6008Sagc /*
11193bf6008Sagc * \todo remove code duplication between this and
11293bf6008Sagc * bzip2_compressed_data_reader
11393bf6008Sagc */
11493bf6008Sagc static int
zlib_compressed_data_reader(pgp_stream_t * stream,void * dest,size_t length,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)115b0df0a22Sagc zlib_compressed_data_reader(pgp_stream_t *stream, void *dest, size_t length,
116fc1f8641Sagc pgp_error_t **errors,
117fc1f8641Sagc pgp_reader_t *readinfo,
118fc1f8641Sagc pgp_cbdata_t *cbinfo)
11993bf6008Sagc {
120fc1f8641Sagc z_decompress_t *z = pgp_reader_get_arg(readinfo);
12193bf6008Sagc size_t len;
12285073018Sagc size_t cc;
12393bf6008Sagc char *cdest = dest;
12493bf6008Sagc
125fc1f8641Sagc if (z->type != PGP_C_ZIP && z->type != PGP_C_ZLIB) {
126bcfd8565Sagc (void) fprintf(stderr,
127bcfd8565Sagc "zlib_compressed_data_reader: weird type %d\n",
128bcfd8565Sagc z->type);
129bcfd8565Sagc return 0;
130bcfd8565Sagc }
13193bf6008Sagc
13293bf6008Sagc if (z->inflate_ret == Z_STREAM_END &&
13393bf6008Sagc z->zstream.next_out == &z->out[z->offset]) {
13493bf6008Sagc return 0;
13593bf6008Sagc }
136fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
1374b3a3e18Sagc (void) fprintf(stderr,
1384b3a3e18Sagc "zlib_compressed_data_reader: length %" PRIsize "d\n",
1394b3a3e18Sagc length);
14093bf6008Sagc }
14193bf6008Sagc for (cc = 0 ; cc < length ; cc += len) {
14293bf6008Sagc if (&z->out[z->offset] == z->zstream.next_out) {
14393bf6008Sagc int ret;
14493bf6008Sagc
14593bf6008Sagc z->zstream.next_out = z->out;
14693bf6008Sagc z->zstream.avail_out = sizeof(z->out);
14793bf6008Sagc z->offset = 0;
14893bf6008Sagc if (z->zstream.avail_in == 0) {
14993bf6008Sagc unsigned n = z->region->length;
15093bf6008Sagc
15193bf6008Sagc if (!z->region->indeterminate) {
15257324b9fSagc n -= z->region->readc;
15393bf6008Sagc if (n > sizeof(z->in)) {
15493bf6008Sagc n = sizeof(z->in);
15593bf6008Sagc }
15693bf6008Sagc } else {
15793bf6008Sagc n = sizeof(z->in);
15893bf6008Sagc }
159b0df0a22Sagc if (!pgp_stacked_limited_read(stream, z->in, n,
1604b3a3e18Sagc z->region,
1612232f800Sagc errors, readinfo, cbinfo)) {
16293bf6008Sagc return -1;
16393bf6008Sagc }
16493bf6008Sagc
16593bf6008Sagc z->zstream.next_in = z->in;
16693bf6008Sagc z->zstream.avail_in = (z->region->indeterminate) ?
16793bf6008Sagc z->region->last_read : n;
16893bf6008Sagc }
16993bf6008Sagc ret = inflate(&z->zstream, Z_SYNC_FLUSH);
17093bf6008Sagc if (ret == Z_STREAM_END) {
17193bf6008Sagc if (!z->region->indeterminate &&
17257324b9fSagc z->region->readc != z->region->length) {
173*94fcde8eSchristos PGP_ERROR_1(cbinfo->errors,
174fc1f8641Sagc PGP_E_P_DECOMPRESSION_ERROR,
175*94fcde8eSchristos "%s",
17693bf6008Sagc "Compressed stream ended before packet end.");
17793bf6008Sagc }
17893bf6008Sagc } else if (ret != Z_OK) {
17993bf6008Sagc (void) fprintf(stderr, "ret=%d\n", ret);
180*94fcde8eSchristos PGP_ERROR_1(cbinfo->errors,
181ddccfadcSagc PGP_E_P_DECOMPRESSION_ERROR, "%s",
182ddccfadcSagc z->zstream.msg);
18393bf6008Sagc }
18493bf6008Sagc z->inflate_ret = ret;
18593bf6008Sagc }
186bcfd8565Sagc if (z->zstream.next_out <= &z->out[z->offset]) {
187bcfd8565Sagc (void) fprintf(stderr, "Out of memory in buffer\n");
188bcfd8565Sagc return 0;
189bcfd8565Sagc }
1903574ef6dSagc len = (size_t)(z->zstream.next_out - &z->out[z->offset]);
19193bf6008Sagc if (len > length) {
19293bf6008Sagc len = length;
19393bf6008Sagc }
19493bf6008Sagc (void) memcpy(&cdest[cc], &z->out[z->offset], len);
19593bf6008Sagc z->offset += len;
19693bf6008Sagc }
19793bf6008Sagc
19869d4f30fSagc return (int)length;
19993bf6008Sagc }
20093bf6008Sagc
20122b68feaSagc #ifdef HAVE_BZLIB_H
20293bf6008Sagc /* \todo remove code duplication between this and zlib_compressed_data_reader */
20393bf6008Sagc static int
bzip2_compressed_data_reader(pgp_stream_t * stream,void * dest,size_t length,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)204b0df0a22Sagc bzip2_compressed_data_reader(pgp_stream_t *stream, void *dest, size_t length,
205fc1f8641Sagc pgp_error_t **errors,
206fc1f8641Sagc pgp_reader_t *readinfo,
207fc1f8641Sagc pgp_cbdata_t *cbinfo)
20893bf6008Sagc {
209fc1f8641Sagc bz_decompress_t *bz = pgp_reader_get_arg(readinfo);
21093bf6008Sagc size_t len;
21185073018Sagc size_t cc;
21293bf6008Sagc char *cdest = dest;
21393bf6008Sagc
214fc1f8641Sagc if (bz->type != PGP_C_BZIP2) {
215bcfd8565Sagc (void) fprintf(stderr, "Weird type %d\n", bz->type);
216bcfd8565Sagc return 0;
217bcfd8565Sagc }
21893bf6008Sagc if (bz->inflate_ret == BZ_STREAM_END &&
21993bf6008Sagc bz->bzstream.next_out == &bz->out[bz->offset]) {
22093bf6008Sagc return 0;
22193bf6008Sagc }
22293bf6008Sagc for (cc = 0 ; cc < length ; cc += len) {
22393bf6008Sagc if (&bz->out[bz->offset] == bz->bzstream.next_out) {
22493bf6008Sagc int ret;
22593bf6008Sagc
22693bf6008Sagc bz->bzstream.next_out = (char *) bz->out;
22793bf6008Sagc bz->bzstream.avail_out = sizeof(bz->out);
22893bf6008Sagc bz->offset = 0;
22993bf6008Sagc if (bz->bzstream.avail_in == 0) {
23093bf6008Sagc unsigned n = bz->region->length;
23193bf6008Sagc
23293bf6008Sagc if (!bz->region->indeterminate) {
23357324b9fSagc n -= bz->region->readc;
23493bf6008Sagc if (n > sizeof(bz->in))
23593bf6008Sagc n = sizeof(bz->in);
23693bf6008Sagc } else
23793bf6008Sagc n = sizeof(bz->in);
23893bf6008Sagc
239b0df0a22Sagc if (!pgp_stacked_limited_read(stream,
240b15ec256Sagc (uint8_t *) bz->in,
2414b3a3e18Sagc n, bz->region,
2422232f800Sagc errors, readinfo, cbinfo))
24393bf6008Sagc return -1;
24493bf6008Sagc
24593bf6008Sagc bz->bzstream.next_in = bz->in;
2464b3a3e18Sagc bz->bzstream.avail_in =
2474b3a3e18Sagc (bz->region->indeterminate) ?
2484b3a3e18Sagc bz->region->last_read : n;
24993bf6008Sagc }
25093bf6008Sagc ret = BZ2_bzDecompress(&bz->bzstream);
25193bf6008Sagc if (ret == BZ_STREAM_END) {
25293bf6008Sagc if (!bz->region->indeterminate &&
25357324b9fSagc bz->region->readc != bz->region->length)
254*94fcde8eSchristos PGP_ERROR_1(cbinfo->errors,
255fc1f8641Sagc PGP_E_P_DECOMPRESSION_ERROR,
256*94fcde8eSchristos "%s",
25793bf6008Sagc "Compressed stream ended before packet end.");
25893bf6008Sagc } else if (ret != BZ_OK) {
259fc1f8641Sagc PGP_ERROR_1(cbinfo->errors,
260fc1f8641Sagc PGP_E_P_DECOMPRESSION_ERROR,
26193bf6008Sagc "Invalid return %d from BZ2_bzDecompress", ret);
26293bf6008Sagc }
26393bf6008Sagc bz->inflate_ret = ret;
26493bf6008Sagc }
265bcfd8565Sagc if (bz->bzstream.next_out <= &bz->out[bz->offset]) {
266bcfd8565Sagc (void) fprintf(stderr, "Out of bz memroy\n");
267bcfd8565Sagc return 0;
268bcfd8565Sagc }
2693574ef6dSagc len = (size_t)(bz->bzstream.next_out - &bz->out[bz->offset]);
270bcfd8565Sagc if (len > length) {
27193bf6008Sagc len = length;
272bcfd8565Sagc }
27393bf6008Sagc (void) memcpy(&cdest[cc], &bz->out[bz->offset], len);
27493bf6008Sagc bz->offset += len;
27593bf6008Sagc }
27693bf6008Sagc
27769d4f30fSagc return (int)length;
27893bf6008Sagc }
27922b68feaSagc #endif
28093bf6008Sagc
28193bf6008Sagc /**
28293bf6008Sagc * \ingroup Core_Compress
28393bf6008Sagc *
28493bf6008Sagc * \param *region Pointer to a region
28541335e2dSagc * \param *stream How to parse
28693bf6008Sagc * \param type Which compression type to expect
28793bf6008Sagc */
28893bf6008Sagc
28993bf6008Sagc int
pgp_decompress(pgp_region_t * region,pgp_stream_t * stream,pgp_compression_type_t type)290fc1f8641Sagc pgp_decompress(pgp_region_t *region, pgp_stream_t *stream,
291fc1f8641Sagc pgp_compression_type_t type)
29293bf6008Sagc {
29393bf6008Sagc z_decompress_t z;
29422b68feaSagc #ifdef HAVE_BZLIB_H
29593bf6008Sagc bz_decompress_t bz;
29622b68feaSagc #endif
297393ecd92Sagc const int printerrors = 1;
29893bf6008Sagc int ret;
29993bf6008Sagc
30093bf6008Sagc switch (type) {
301fc1f8641Sagc case PGP_C_ZIP:
302fc1f8641Sagc case PGP_C_ZLIB:
30393bf6008Sagc (void) memset(&z, 0x0, sizeof(z));
30493bf6008Sagc
30593bf6008Sagc z.region = region;
30693bf6008Sagc z.offset = 0;
30793bf6008Sagc z.type = type;
30893bf6008Sagc
30993bf6008Sagc z.zstream.next_in = Z_NULL;
31093bf6008Sagc z.zstream.avail_in = 0;
31193bf6008Sagc z.zstream.next_out = z.out;
31293bf6008Sagc z.zstream.zalloc = Z_NULL;
31393bf6008Sagc z.zstream.zfree = Z_NULL;
31493bf6008Sagc z.zstream.opaque = Z_NULL;
31593bf6008Sagc
31693bf6008Sagc break;
31793bf6008Sagc
31822b68feaSagc #ifdef HAVE_BZLIB_H
319fc1f8641Sagc case PGP_C_BZIP2:
32093bf6008Sagc (void) memset(&bz, 0x0, sizeof(bz));
32193bf6008Sagc
32293bf6008Sagc bz.region = region;
32393bf6008Sagc bz.offset = 0;
32493bf6008Sagc bz.type = type;
32593bf6008Sagc
32693bf6008Sagc bz.bzstream.next_in = NULL;
32793bf6008Sagc bz.bzstream.avail_in = 0;
32893bf6008Sagc bz.bzstream.next_out = bz.out;
32993bf6008Sagc bz.bzstream.bzalloc = NULL;
33093bf6008Sagc bz.bzstream.bzfree = NULL;
33193bf6008Sagc bz.bzstream.opaque = NULL;
33222b68feaSagc #endif
33393bf6008Sagc
33493bf6008Sagc break;
33593bf6008Sagc
33693bf6008Sagc default:
337fc1f8641Sagc PGP_ERROR_1(&stream->errors,
338fc1f8641Sagc PGP_E_ALG_UNSUPPORTED_COMPRESS_ALG,
33993bf6008Sagc "Compression algorithm %d is not yet supported", type);
34093bf6008Sagc return 0;
34193bf6008Sagc }
34293bf6008Sagc
34393bf6008Sagc switch (type) {
344fc1f8641Sagc case PGP_C_ZIP:
3453f685a78Sagc /* LINTED */ /* this is a lint problem in zlib.h header */
34669d4f30fSagc ret = (int)inflateInit2(&z.zstream, -15);
34793bf6008Sagc break;
34893bf6008Sagc
349fc1f8641Sagc case PGP_C_ZLIB:
3503f685a78Sagc /* LINTED */ /* this is a lint problem in zlib.h header */
35169d4f30fSagc ret = (int)inflateInit(&z.zstream);
35293bf6008Sagc break;
35393bf6008Sagc
35422b68feaSagc #ifdef HAVE_BZLIB_H
355fc1f8641Sagc case PGP_C_BZIP2:
35693bf6008Sagc ret = BZ2_bzDecompressInit(&bz.bzstream, 1, 0);
35793bf6008Sagc break;
35822b68feaSagc #endif
35993bf6008Sagc
36093bf6008Sagc default:
361fc1f8641Sagc PGP_ERROR_1(&stream->errors,
362fc1f8641Sagc PGP_E_ALG_UNSUPPORTED_COMPRESS_ALG,
36393bf6008Sagc "Compression algorithm %d is not yet supported", type);
36493bf6008Sagc return 0;
36593bf6008Sagc }
36693bf6008Sagc
36793bf6008Sagc switch (type) {
368fc1f8641Sagc case PGP_C_ZIP:
369fc1f8641Sagc case PGP_C_ZLIB:
37093bf6008Sagc if (ret != Z_OK) {
371fc1f8641Sagc PGP_ERROR_1(&stream->errors,
372fc1f8641Sagc PGP_E_P_DECOMPRESSION_ERROR,
37393bf6008Sagc "Cannot initialise ZIP or ZLIB stream for decompression: error=%d", ret);
37493bf6008Sagc return 0;
37593bf6008Sagc }
376fc1f8641Sagc pgp_reader_push(stream, zlib_compressed_data_reader,
3774b3a3e18Sagc NULL, &z);
37893bf6008Sagc break;
37993bf6008Sagc
38022b68feaSagc #ifdef HAVE_BZLIB_H
381fc1f8641Sagc case PGP_C_BZIP2:
38293bf6008Sagc if (ret != BZ_OK) {
383fc1f8641Sagc PGP_ERROR_1(&stream->errors,
384fc1f8641Sagc PGP_E_P_DECOMPRESSION_ERROR,
38593bf6008Sagc "Cannot initialise BZIP2 stream for decompression: error=%d", ret);
38693bf6008Sagc return 0;
38793bf6008Sagc }
388fc1f8641Sagc pgp_reader_push(stream, bzip2_compressed_data_reader,
3894b3a3e18Sagc NULL, &bz);
39093bf6008Sagc break;
39122b68feaSagc #endif
39293bf6008Sagc
39393bf6008Sagc default:
394fc1f8641Sagc PGP_ERROR_1(&stream->errors,
395fc1f8641Sagc PGP_E_ALG_UNSUPPORTED_COMPRESS_ALG,
39693bf6008Sagc "Compression algorithm %d is not yet supported", type);
39793bf6008Sagc return 0;
39893bf6008Sagc }
39993bf6008Sagc
400fc1f8641Sagc ret = pgp_parse(stream, !printerrors);
40193bf6008Sagc
402fc1f8641Sagc pgp_reader_pop(stream);
40393bf6008Sagc
40493bf6008Sagc return ret;
40593bf6008Sagc }
40693bf6008Sagc
40793bf6008Sagc /**
40893bf6008Sagc \ingroup Core_WritePackets
40993bf6008Sagc \brief Writes Compressed packet
41093bf6008Sagc \param data Data to write out
41193bf6008Sagc \param len Length of data
41257324b9fSagc \param output Write settings
4134b3a3e18Sagc \return 1 if OK; else 0
41493bf6008Sagc */
41593bf6008Sagc
4164b3a3e18Sagc unsigned
pgp_writez(pgp_output_t * out,const uint8_t * data,const unsigned len)417fc1f8641Sagc pgp_writez(pgp_output_t *out, const uint8_t *data, const unsigned len)
41893bf6008Sagc {
419e82f21ebSagc compress_t *zip;
4203574ef6dSagc size_t sz_in;
4213574ef6dSagc size_t sz_out;
422e82f21ebSagc int ret;
42393bf6008Sagc int r = 0;
42493bf6008Sagc
42593bf6008Sagc /* compress the data */
42693bf6008Sagc const int level = Z_DEFAULT_COMPRESSION; /* \todo allow varying
42793bf6008Sagc * levels */
428e82f21ebSagc
429e82f21ebSagc if ((zip = calloc(1, sizeof(*zip))) == NULL) {
430fc1f8641Sagc (void) fprintf(stderr, "pgp_writez: bad alloc\n");
431e82f21ebSagc return 0;
432e82f21ebSagc }
433efdd9dbaSagc zip->stream.zalloc = Z_NULL;
434efdd9dbaSagc zip->stream.zfree = Z_NULL;
435efdd9dbaSagc zip->stream.opaque = NULL;
43693bf6008Sagc
43793bf6008Sagc /* all other fields set to zero by use of calloc */
43893bf6008Sagc
4393f685a78Sagc /* LINTED */ /* this is a lint problem in zlib.h header */
44069d4f30fSagc if ((int)deflateInit(&zip->stream, level) != Z_OK) {
441fc1f8641Sagc (void) fprintf(stderr, "pgp_writez: can't initialise\n");
4424b3a3e18Sagc return 0;
44393bf6008Sagc }
44493bf6008Sagc /* do necessary transformation */
44593bf6008Sagc /* copy input to maintain const'ness of src */
446bcfd8565Sagc if (zip->src != NULL || zip->dst != NULL) {
447fc1f8641Sagc (void) fprintf(stderr, "pgp_writez: non-null streams\n");
4484b3a3e18Sagc return 0;
449bcfd8565Sagc }
45093bf6008Sagc
451b15ec256Sagc sz_in = len * sizeof(uint8_t);
4523574ef6dSagc sz_out = ((101 * sz_in) / 100) + 12; /* from zlib webpage */
453e82f21ebSagc if ((zip->src = calloc(1, sz_in)) == NULL) {
454e82f21ebSagc free(zip);
455fc1f8641Sagc (void) fprintf(stderr, "pgp_writez: bad alloc2\n");
456e82f21ebSagc return 0;
457e82f21ebSagc }
458e82f21ebSagc if ((zip->dst = calloc(1, sz_out)) == NULL) {
459e82f21ebSagc free(zip->src);
460e82f21ebSagc free(zip);
461fc1f8641Sagc (void) fprintf(stderr, "pgp_writez: bad alloc3\n");
462e82f21ebSagc return 0;
463e82f21ebSagc }
464efdd9dbaSagc (void) memcpy(zip->src, data, len);
46593bf6008Sagc
46693bf6008Sagc /* setup stream */
467efdd9dbaSagc zip->stream.next_in = zip->src;
46869d4f30fSagc zip->stream.avail_in = (unsigned)sz_in;
469efdd9dbaSagc zip->stream.total_in = 0;
47093bf6008Sagc
471efdd9dbaSagc zip->stream.next_out = zip->dst;
47269d4f30fSagc zip->stream.avail_out = (unsigned)sz_out;
473efdd9dbaSagc zip->stream.total_out = 0;
47493bf6008Sagc
475bcfd8565Sagc do {
476efdd9dbaSagc r = deflate(&zip->stream, Z_FINISH);
477bcfd8565Sagc } while (r != Z_STREAM_END);
47893bf6008Sagc
47993bf6008Sagc /* write it out */
480fc1f8641Sagc ret = pgp_write_ptag(out, PGP_PTAG_CT_COMPRESSED) &&
481fc1f8641Sagc pgp_write_length(out, (unsigned)(zip->stream.total_out + 1))&&
482fc1f8641Sagc pgp_write_scalar(out, PGP_C_ZLIB, 1) &&
483fc1f8641Sagc pgp_write(out, zip->dst, (unsigned)zip->stream.total_out);
484e82f21ebSagc
485e82f21ebSagc free(zip->src);
486e82f21ebSagc free(zip->dst);
487e82f21ebSagc free(zip);
488e82f21ebSagc return ret;
48993bf6008Sagc }
490