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*69d4f30fSagc __RCSID("$NetBSD: compress.c,v 1.16 2010/08/15 07:52:26 agc 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 { 8393bf6008Sagc __ops_compression_type_t type; 8493bf6008Sagc __ops_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 9293bf6008Sagc typedef struct { 9393bf6008Sagc __ops_compression_type_t type; 9493bf6008Sagc __ops_region_t *region; 9593bf6008Sagc char in[DECOMPRESS_BUFFER]; 9693bf6008Sagc char out[DECOMPRESS_BUFFER]; 9793bf6008Sagc bz_stream bzstream; /* BZIP2 */ 9893bf6008Sagc size_t offset; 9993bf6008Sagc int inflate_ret; 10093bf6008Sagc } bz_decompress_t; 10193bf6008Sagc 10293bf6008Sagc typedef struct { 10393bf6008Sagc z_stream stream; 104b15ec256Sagc uint8_t *src; 105b15ec256Sagc uint8_t *dst; 10693bf6008Sagc } compress_t; 10793bf6008Sagc 10893bf6008Sagc /* 10993bf6008Sagc * \todo remove code duplication between this and 11093bf6008Sagc * bzip2_compressed_data_reader 11193bf6008Sagc */ 11293bf6008Sagc static int 11393bf6008Sagc zlib_compressed_data_reader(void *dest, size_t length, 11493bf6008Sagc __ops_error_t **errors, 1152232f800Sagc __ops_reader_t *readinfo, 116d21b929eSagc __ops_cbdata_t *cbinfo) 11793bf6008Sagc { 1182232f800Sagc z_decompress_t *z = __ops_reader_get_arg(readinfo); 11993bf6008Sagc size_t len; 12085073018Sagc size_t cc; 12193bf6008Sagc char *cdest = dest; 12293bf6008Sagc 123bcfd8565Sagc if (z->type != OPS_C_ZIP && z->type != OPS_C_ZLIB) { 124bcfd8565Sagc (void) fprintf(stderr, 125bcfd8565Sagc "zlib_compressed_data_reader: weird type %d\n", 126bcfd8565Sagc z->type); 127bcfd8565Sagc return 0; 128bcfd8565Sagc } 12993bf6008Sagc 13093bf6008Sagc if (z->inflate_ret == Z_STREAM_END && 13193bf6008Sagc z->zstream.next_out == &z->out[z->offset]) { 13293bf6008Sagc return 0; 13393bf6008Sagc } 13493bf6008Sagc 13593bf6008Sagc if (__ops_get_debug_level(__FILE__)) { 1364b3a3e18Sagc (void) fprintf(stderr, 1374b3a3e18Sagc "zlib_compressed_data_reader: length %" PRIsize "d\n", 1384b3a3e18Sagc length); 13993bf6008Sagc } 14093bf6008Sagc 14157324b9fSagc if (z->region->readc == z->region->length) { 14293bf6008Sagc if (z->inflate_ret != Z_STREAM_END) { 14393bf6008Sagc OPS_ERROR(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR, 14493bf6008Sagc "Compressed data didn't end when region ended."); 14593bf6008Sagc } 14693bf6008Sagc } 14793bf6008Sagc for (cc = 0 ; cc < length ; cc += len) { 14893bf6008Sagc if (&z->out[z->offset] == z->zstream.next_out) { 14993bf6008Sagc int ret; 15093bf6008Sagc 15193bf6008Sagc z->zstream.next_out = z->out; 15293bf6008Sagc z->zstream.avail_out = sizeof(z->out); 15393bf6008Sagc z->offset = 0; 15493bf6008Sagc if (z->zstream.avail_in == 0) { 15593bf6008Sagc unsigned n = z->region->length; 15693bf6008Sagc 15793bf6008Sagc if (!z->region->indeterminate) { 15857324b9fSagc n -= z->region->readc; 15993bf6008Sagc if (n > sizeof(z->in)) { 16093bf6008Sagc n = sizeof(z->in); 16193bf6008Sagc } 16293bf6008Sagc } else { 16393bf6008Sagc n = sizeof(z->in); 16493bf6008Sagc } 1654b3a3e18Sagc if (!__ops_stacked_limited_read(z->in, n, 1664b3a3e18Sagc z->region, 1672232f800Sagc errors, readinfo, cbinfo)) { 16893bf6008Sagc return -1; 16993bf6008Sagc } 17093bf6008Sagc 17193bf6008Sagc z->zstream.next_in = z->in; 17293bf6008Sagc z->zstream.avail_in = (z->region->indeterminate) ? 17393bf6008Sagc z->region->last_read : n; 17493bf6008Sagc } 17593bf6008Sagc ret = inflate(&z->zstream, Z_SYNC_FLUSH); 17693bf6008Sagc if (ret == Z_STREAM_END) { 17793bf6008Sagc if (!z->region->indeterminate && 17857324b9fSagc z->region->readc != z->region->length) { 17993bf6008Sagc OPS_ERROR(cbinfo->errors, 18093bf6008Sagc OPS_E_P_DECOMPRESSION_ERROR, 18193bf6008Sagc "Compressed stream ended before packet end."); 18293bf6008Sagc } 18393bf6008Sagc } else if (ret != Z_OK) { 18493bf6008Sagc (void) fprintf(stderr, "ret=%d\n", ret); 1854b3a3e18Sagc OPS_ERROR(cbinfo->errors, 1864b3a3e18Sagc OPS_E_P_DECOMPRESSION_ERROR, z->zstream.msg); 18793bf6008Sagc } 18893bf6008Sagc z->inflate_ret = ret; 18993bf6008Sagc } 190bcfd8565Sagc if (z->zstream.next_out <= &z->out[z->offset]) { 191bcfd8565Sagc (void) fprintf(stderr, "Out of memory in buffer\n"); 192bcfd8565Sagc return 0; 193bcfd8565Sagc } 1943574ef6dSagc len = (size_t)(z->zstream.next_out - &z->out[z->offset]); 19593bf6008Sagc if (len > length) { 19693bf6008Sagc len = length; 19793bf6008Sagc } 19893bf6008Sagc (void) memcpy(&cdest[cc], &z->out[z->offset], len); 19993bf6008Sagc z->offset += len; 20093bf6008Sagc } 20193bf6008Sagc 202*69d4f30fSagc return (int)length; 20393bf6008Sagc } 20493bf6008Sagc 20593bf6008Sagc /* \todo remove code duplication between this and zlib_compressed_data_reader */ 20693bf6008Sagc static int 20793bf6008Sagc bzip2_compressed_data_reader(void *dest, size_t length, 20893bf6008Sagc __ops_error_t **errors, 2092232f800Sagc __ops_reader_t *readinfo, 210d21b929eSagc __ops_cbdata_t *cbinfo) 21193bf6008Sagc { 2122232f800Sagc bz_decompress_t *bz = __ops_reader_get_arg(readinfo); 21393bf6008Sagc size_t len; 21485073018Sagc size_t cc; 21593bf6008Sagc char *cdest = dest; 21693bf6008Sagc 217bcfd8565Sagc if (bz->type != OPS_C_BZIP2) { 218bcfd8565Sagc (void) fprintf(stderr, "Weird type %d\n", bz->type); 219bcfd8565Sagc return 0; 220bcfd8565Sagc } 22193bf6008Sagc 22293bf6008Sagc if (bz->inflate_ret == BZ_STREAM_END && 22393bf6008Sagc bz->bzstream.next_out == &bz->out[bz->offset]) { 22493bf6008Sagc return 0; 22593bf6008Sagc } 22657324b9fSagc if (bz->region->readc == bz->region->length) { 22793bf6008Sagc if (bz->inflate_ret != BZ_STREAM_END) { 22893bf6008Sagc OPS_ERROR(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR, 22993bf6008Sagc "Compressed data didn't end when region ended."); 23093bf6008Sagc } 23193bf6008Sagc } 23293bf6008Sagc for (cc = 0 ; cc < length ; cc += len) { 23393bf6008Sagc if (&bz->out[bz->offset] == bz->bzstream.next_out) { 23493bf6008Sagc int ret; 23593bf6008Sagc 23693bf6008Sagc bz->bzstream.next_out = (char *) bz->out; 23793bf6008Sagc bz->bzstream.avail_out = sizeof(bz->out); 23893bf6008Sagc bz->offset = 0; 23993bf6008Sagc if (bz->bzstream.avail_in == 0) { 24093bf6008Sagc unsigned n = bz->region->length; 24193bf6008Sagc 24293bf6008Sagc if (!bz->region->indeterminate) { 24357324b9fSagc n -= bz->region->readc; 24493bf6008Sagc if (n > sizeof(bz->in)) 24593bf6008Sagc n = sizeof(bz->in); 24693bf6008Sagc } else 24793bf6008Sagc n = sizeof(bz->in); 24893bf6008Sagc 2494b3a3e18Sagc if (!__ops_stacked_limited_read( 250b15ec256Sagc (uint8_t *) bz->in, 2514b3a3e18Sagc n, bz->region, 2522232f800Sagc errors, readinfo, cbinfo)) 25393bf6008Sagc return -1; 25493bf6008Sagc 25593bf6008Sagc bz->bzstream.next_in = bz->in; 2564b3a3e18Sagc bz->bzstream.avail_in = 2574b3a3e18Sagc (bz->region->indeterminate) ? 2584b3a3e18Sagc bz->region->last_read : n; 25993bf6008Sagc } 26093bf6008Sagc ret = BZ2_bzDecompress(&bz->bzstream); 26193bf6008Sagc if (ret == BZ_STREAM_END) { 26293bf6008Sagc if (!bz->region->indeterminate && 26357324b9fSagc bz->region->readc != bz->region->length) 26493bf6008Sagc OPS_ERROR(cbinfo->errors, 26593bf6008Sagc OPS_E_P_DECOMPRESSION_ERROR, 26693bf6008Sagc "Compressed stream ended before packet end."); 26793bf6008Sagc } else if (ret != BZ_OK) { 26893bf6008Sagc OPS_ERROR_1(cbinfo->errors, 26993bf6008Sagc OPS_E_P_DECOMPRESSION_ERROR, 27093bf6008Sagc "Invalid return %d from BZ2_bzDecompress", ret); 27193bf6008Sagc } 27293bf6008Sagc bz->inflate_ret = ret; 27393bf6008Sagc } 274bcfd8565Sagc if (bz->bzstream.next_out <= &bz->out[bz->offset]) { 275bcfd8565Sagc (void) fprintf(stderr, "Out of bz memroy\n"); 276bcfd8565Sagc return 0; 277bcfd8565Sagc } 2783574ef6dSagc len = (size_t)(bz->bzstream.next_out - &bz->out[bz->offset]); 279bcfd8565Sagc if (len > length) { 28093bf6008Sagc len = length; 281bcfd8565Sagc } 28293bf6008Sagc (void) memcpy(&cdest[cc], &bz->out[bz->offset], len); 28393bf6008Sagc bz->offset += len; 28493bf6008Sagc } 28593bf6008Sagc 286*69d4f30fSagc return (int)length; 28793bf6008Sagc } 28893bf6008Sagc 28993bf6008Sagc /** 29093bf6008Sagc * \ingroup Core_Compress 29193bf6008Sagc * 29293bf6008Sagc * \param *region Pointer to a region 29341335e2dSagc * \param *stream How to parse 29493bf6008Sagc * \param type Which compression type to expect 29593bf6008Sagc */ 29693bf6008Sagc 29793bf6008Sagc int 29841335e2dSagc __ops_decompress(__ops_region_t *region, __ops_stream_t *stream, 29993bf6008Sagc __ops_compression_type_t type) 30093bf6008Sagc { 30193bf6008Sagc z_decompress_t z; 30293bf6008Sagc bz_decompress_t bz; 303393ecd92Sagc const int printerrors = 1; 30493bf6008Sagc int ret; 30593bf6008Sagc 30693bf6008Sagc switch (type) { 30793bf6008Sagc case OPS_C_ZIP: 30893bf6008Sagc case OPS_C_ZLIB: 30993bf6008Sagc (void) memset(&z, 0x0, sizeof(z)); 31093bf6008Sagc 31193bf6008Sagc z.region = region; 31293bf6008Sagc z.offset = 0; 31393bf6008Sagc z.type = type; 31493bf6008Sagc 31593bf6008Sagc z.zstream.next_in = Z_NULL; 31693bf6008Sagc z.zstream.avail_in = 0; 31793bf6008Sagc z.zstream.next_out = z.out; 31893bf6008Sagc z.zstream.zalloc = Z_NULL; 31993bf6008Sagc z.zstream.zfree = Z_NULL; 32093bf6008Sagc z.zstream.opaque = Z_NULL; 32193bf6008Sagc 32293bf6008Sagc break; 32393bf6008Sagc 32493bf6008Sagc case OPS_C_BZIP2: 32593bf6008Sagc (void) memset(&bz, 0x0, sizeof(bz)); 32693bf6008Sagc 32793bf6008Sagc bz.region = region; 32893bf6008Sagc bz.offset = 0; 32993bf6008Sagc bz.type = type; 33093bf6008Sagc 33193bf6008Sagc bz.bzstream.next_in = NULL; 33293bf6008Sagc bz.bzstream.avail_in = 0; 33393bf6008Sagc bz.bzstream.next_out = bz.out; 33493bf6008Sagc bz.bzstream.bzalloc = NULL; 33593bf6008Sagc bz.bzstream.bzfree = NULL; 33693bf6008Sagc bz.bzstream.opaque = NULL; 33793bf6008Sagc 33893bf6008Sagc break; 33993bf6008Sagc 34093bf6008Sagc default: 34141335e2dSagc OPS_ERROR_1(&stream->errors, 34293bf6008Sagc OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, 34393bf6008Sagc "Compression algorithm %d is not yet supported", type); 34493bf6008Sagc return 0; 34593bf6008Sagc } 34693bf6008Sagc 34793bf6008Sagc switch (type) { 34893bf6008Sagc case OPS_C_ZIP: 349*69d4f30fSagc ret = (int)inflateInit2(&z.zstream, -15); 35093bf6008Sagc break; 35193bf6008Sagc 35293bf6008Sagc case OPS_C_ZLIB: 353*69d4f30fSagc ret = (int)inflateInit(&z.zstream); 35493bf6008Sagc break; 35593bf6008Sagc 35693bf6008Sagc case OPS_C_BZIP2: 35793bf6008Sagc ret = BZ2_bzDecompressInit(&bz.bzstream, 1, 0); 35893bf6008Sagc break; 35993bf6008Sagc 36093bf6008Sagc default: 36141335e2dSagc OPS_ERROR_1(&stream->errors, 36293bf6008Sagc OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, 36393bf6008Sagc "Compression algorithm %d is not yet supported", type); 36493bf6008Sagc return 0; 36593bf6008Sagc } 36693bf6008Sagc 36793bf6008Sagc switch (type) { 36893bf6008Sagc case OPS_C_ZIP: 36993bf6008Sagc case OPS_C_ZLIB: 37093bf6008Sagc if (ret != Z_OK) { 37141335e2dSagc OPS_ERROR_1(&stream->errors, 37293bf6008Sagc OPS_E_P_DECOMPRESSION_ERROR, 37393bf6008Sagc "Cannot initialise ZIP or ZLIB stream for decompression: error=%d", ret); 37493bf6008Sagc return 0; 37593bf6008Sagc } 37641335e2dSagc __ops_reader_push(stream, zlib_compressed_data_reader, 3774b3a3e18Sagc NULL, &z); 37893bf6008Sagc break; 37993bf6008Sagc 38093bf6008Sagc case OPS_C_BZIP2: 38193bf6008Sagc if (ret != BZ_OK) { 38241335e2dSagc OPS_ERROR_1(&stream->errors, 38393bf6008Sagc OPS_E_P_DECOMPRESSION_ERROR, 38493bf6008Sagc "Cannot initialise BZIP2 stream for decompression: error=%d", ret); 38593bf6008Sagc return 0; 38693bf6008Sagc } 38741335e2dSagc __ops_reader_push(stream, bzip2_compressed_data_reader, 3884b3a3e18Sagc NULL, &bz); 38993bf6008Sagc break; 39093bf6008Sagc 39193bf6008Sagc default: 39241335e2dSagc OPS_ERROR_1(&stream->errors, 39393bf6008Sagc OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, 39493bf6008Sagc "Compression algorithm %d is not yet supported", type); 39593bf6008Sagc return 0; 39693bf6008Sagc } 39793bf6008Sagc 39841335e2dSagc ret = __ops_parse(stream, !printerrors); 39993bf6008Sagc 40041335e2dSagc __ops_reader_pop(stream); 40193bf6008Sagc 40293bf6008Sagc return ret; 40393bf6008Sagc } 40493bf6008Sagc 40593bf6008Sagc /** 40693bf6008Sagc \ingroup Core_WritePackets 40793bf6008Sagc \brief Writes Compressed packet 40893bf6008Sagc \param data Data to write out 40993bf6008Sagc \param len Length of data 41057324b9fSagc \param output Write settings 4114b3a3e18Sagc \return 1 if OK; else 0 41293bf6008Sagc */ 41393bf6008Sagc 4144b3a3e18Sagc unsigned 415b15ec256Sagc __ops_writez(__ops_output_t *out, const uint8_t *data, const unsigned len) 41693bf6008Sagc { 417e82f21ebSagc compress_t *zip; 4183574ef6dSagc size_t sz_in; 4193574ef6dSagc size_t sz_out; 420e82f21ebSagc int ret; 42193bf6008Sagc int r = 0; 42293bf6008Sagc 42393bf6008Sagc /* compress the data */ 42493bf6008Sagc const int level = Z_DEFAULT_COMPRESSION; /* \todo allow varying 42593bf6008Sagc * levels */ 426e82f21ebSagc 427e82f21ebSagc if ((zip = calloc(1, sizeof(*zip))) == NULL) { 428e82f21ebSagc (void) fprintf(stderr, "__ops_writez: bad alloc\n"); 429e82f21ebSagc return 0; 430e82f21ebSagc } 431efdd9dbaSagc zip->stream.zalloc = Z_NULL; 432efdd9dbaSagc zip->stream.zfree = Z_NULL; 433efdd9dbaSagc zip->stream.opaque = NULL; 43493bf6008Sagc 43593bf6008Sagc /* all other fields set to zero by use of calloc */ 43693bf6008Sagc 437*69d4f30fSagc if ((int)deflateInit(&zip->stream, level) != Z_OK) { 43857324b9fSagc (void) fprintf(stderr, "__ops_writez: can't initialise\n"); 4394b3a3e18Sagc return 0; 44093bf6008Sagc } 44193bf6008Sagc /* do necessary transformation */ 44293bf6008Sagc /* copy input to maintain const'ness of src */ 443bcfd8565Sagc if (zip->src != NULL || zip->dst != NULL) { 44457324b9fSagc (void) fprintf(stderr, "__ops_writez: non-null streams\n"); 4454b3a3e18Sagc return 0; 446bcfd8565Sagc } 44793bf6008Sagc 448b15ec256Sagc sz_in = len * sizeof(uint8_t); 4493574ef6dSagc sz_out = ((101 * sz_in) / 100) + 12; /* from zlib webpage */ 450e82f21ebSagc if ((zip->src = calloc(1, sz_in)) == NULL) { 451e82f21ebSagc free(zip); 452e82f21ebSagc (void) fprintf(stderr, "__ops_writez: bad alloc2\n"); 453e82f21ebSagc return 0; 454e82f21ebSagc } 455e82f21ebSagc if ((zip->dst = calloc(1, sz_out)) == NULL) { 456e82f21ebSagc free(zip->src); 457e82f21ebSagc free(zip); 458e82f21ebSagc (void) fprintf(stderr, "__ops_writez: bad alloc3\n"); 459e82f21ebSagc return 0; 460e82f21ebSagc } 461efdd9dbaSagc (void) memcpy(zip->src, data, len); 46293bf6008Sagc 46393bf6008Sagc /* setup stream */ 464efdd9dbaSagc zip->stream.next_in = zip->src; 465*69d4f30fSagc zip->stream.avail_in = (unsigned)sz_in; 466efdd9dbaSagc zip->stream.total_in = 0; 46793bf6008Sagc 468efdd9dbaSagc zip->stream.next_out = zip->dst; 469*69d4f30fSagc zip->stream.avail_out = (unsigned)sz_out; 470efdd9dbaSagc zip->stream.total_out = 0; 47193bf6008Sagc 472bcfd8565Sagc do { 473efdd9dbaSagc r = deflate(&zip->stream, Z_FINISH); 474bcfd8565Sagc } while (r != Z_STREAM_END); 47593bf6008Sagc 47693bf6008Sagc /* write it out */ 477e82f21ebSagc ret = __ops_write_ptag(out, OPS_PTAG_CT_COMPRESSED) && 47857324b9fSagc __ops_write_length(out, (unsigned)(zip->stream.total_out + 1))&& 47957324b9fSagc __ops_write_scalar(out, OPS_C_ZLIB, 1) && 480e82f21ebSagc __ops_write(out, zip->dst, (unsigned)zip->stream.total_out); 481e82f21ebSagc 482e82f21ebSagc free(zip->src); 483e82f21ebSagc free(zip->dst); 484e82f21ebSagc free(zip); 485e82f21ebSagc return ret; 48693bf6008Sagc } 487