[BACK]Return to compress.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cvs

Annotation of src/usr.bin/cvs/compress.c, Revision 1.6

1.6     ! otto        1: /*     $OpenBSD: compress.c,v 1.5 2006/05/29 17:10:57 pat Exp $        */
1.1       xsa         2: /*
1.5       pat         3:  * Copyright (c) 2006 Patrick Latifi <pat@openbsd.org>
1.1       xsa         4:  * Copyright (c) 2005 Jean-Francois Brousseau <jfb@openbsd.org>
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  *
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. The name of the author may not be used to endorse or promote products
                     14:  *    derived from this software without specific prior written permission.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                     17:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
                     18:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
                     19:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     20:  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     21:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     22:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     23:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     24:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                     25:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  */
                     27:
1.6     ! otto       28: #include <zlib.h>
1.1       xsa        29:
                     30: #include "cvs.h"
                     31: #include "compress.h"
                     32:
                     33: #define CVS_ZLIB_BUFSIZE       1024
                     34:
                     35: struct cvs_zlib_ctx {
                     36:        int             z_level;
                     37:        z_stream        z_instrm;
                     38:        z_stream        z_destrm;
                     39: };
                     40:
1.5       pat        41: struct zlib_ioctx {
                     42:        z_stream *stream;
                     43:        int     (*reset)(z_stream *);
                     44:        int     (*io)(z_stream *, int);
                     45:        int     ioflags;
                     46: };
                     47:
                     48: static int cvs_zlib_io(struct zlib_ioctx *, BUF *, u_char *, size_t);
1.1       xsa        49:
                     50: /*
                     51:  * cvs_zlib_newctx()
                     52:  *
                     53:  * Allocate a new ZLIB context structure used for both inflation and deflation
                     54:  * of data with compression level <level>, which must be between 0 and 9.  A
                     55:  * value of 0 means no compression, and 9 is the highest level of compression.
                     56:  */
                     57: CVSZCTX *
                     58: cvs_zlib_newctx(int level)
                     59: {
                     60:        CVSZCTX *ctx;
                     61:
1.4       deraadt    62:        if (level < 0 || level > 9)
1.1       xsa        63:                fatal("invalid compression level %d (must be between 0 and 9)",
                     64:                    level);
                     65:
1.2       ray        66:        ctx = xcalloc(1, sizeof(*ctx));
1.1       xsa        67:
                     68:        ctx->z_level = level;
                     69:
                     70:        ctx->z_instrm.zalloc = Z_NULL;
                     71:        ctx->z_instrm.zfree = Z_NULL;
                     72:        ctx->z_instrm.opaque = Z_NULL;
                     73:        ctx->z_destrm.zalloc = Z_NULL;
                     74:        ctx->z_destrm.zfree = Z_NULL;
                     75:        ctx->z_destrm.opaque = Z_NULL;
                     76:
1.4       deraadt    77:        if (inflateInit(&(ctx->z_instrm)) != Z_OK ||
                     78:            deflateInit(&(ctx->z_destrm), level) != Z_OK)
1.1       xsa        79:                fatal("failed to initialize zlib streams");
                     80:
                     81:        return (ctx);
                     82: }
                     83:
                     84:
                     85: /*
                     86:  * cvs_zlib_free()
                     87:  *
                     88:  * Free a ZLIB context previously allocated with cvs_zlib_newctx().
                     89:  */
                     90: void
                     91: cvs_zlib_free(CVSZCTX *ctx)
                     92: {
                     93:        if (ctx != NULL) {
                     94:                (void)inflateEnd(&(ctx->z_instrm));
                     95:                (void)deflateEnd(&(ctx->z_destrm));
                     96:                xfree(ctx);
                     97:        }
                     98: }
                     99:
                    100: /*
                    101:  * cvs_zlib_inflate()
                    102:  *
                    103:  * Decompress the first <slen> bytes of <src> using the zlib context <ctx> and
                    104:  * store the resulting data in <dst>.
                    105:  * Returns the number of bytes inflated on success, or -1 on failure.
                    106:  */
                    107: int
                    108: cvs_zlib_inflate(CVSZCTX *ctx, BUF *dst, u_char *src, size_t slen)
                    109: {
1.5       pat       110:        struct zlib_ioctx zio;
1.1       xsa       111:
1.5       pat       112:        zio.stream = &ctx->z_instrm;
                    113:        zio.reset = inflateReset;
                    114:        zio.io = inflate;
                    115:        zio.ioflags = Z_FINISH;
1.1       xsa       116:
1.5       pat       117:        return cvs_zlib_io(&zio, dst, src, slen);
1.1       xsa       118: }
                    119:
                    120: /*
                    121:  * cvs_zlib_deflate()
                    122:  *
                    123:  * Compress the first <slen> bytes of <src> using the zlib context <ctx> and
                    124:  * store the resulting data in <dst>.
                    125:  * Returns the number of bytes deflated on success, or -1 on failure.
                    126:  */
                    127: int
                    128: cvs_zlib_deflate(CVSZCTX *ctx, BUF *dst, u_char *src, size_t slen)
                    129: {
1.5       pat       130:        struct zlib_ioctx zio;
                    131:
                    132:        zio.stream = &ctx->z_destrm;
                    133:        zio.reset = deflateReset;
                    134:        zio.io = deflate;
                    135:        zio.ioflags = Z_FINISH;
                    136:
                    137:        return cvs_zlib_io(&zio, dst, src, slen);
                    138: }
                    139:
                    140: static int
                    141: cvs_zlib_io(struct zlib_ioctx *zio, BUF *dst, u_char *src, size_t slen)
                    142: {
1.1       xsa       143:        int bytes, ret;
                    144:        u_char buf[CVS_ZLIB_BUFSIZE];
1.5       pat       145:        z_stream *zstream = zio->stream;
1.1       xsa       146:
                    147:        bytes = 0;
                    148:        cvs_buf_empty(dst);
1.5       pat       149:        if ((*zio->reset)(zstream) == Z_STREAM_ERROR)
                    150:                fatal("%s error: %s", (zio->reset == inflateReset) ?
                    151:                    "inflate" : "deflate", zstream->msg);
1.1       xsa       152:
1.5       pat       153:        zstream->next_in = src;
                    154:        zstream->avail_in = slen;
1.1       xsa       155:
                    156:        do {
1.5       pat       157:                zstream->next_out = buf;
                    158:                zstream->avail_out = sizeof(buf);
                    159:                ret = (*zio->io)(zstream, zio->ioflags);
                    160:                if (ret == Z_MEM_ERROR || ret == Z_STREAM_ERROR ||
                    161:                    ret == Z_BUF_ERROR || ret == Z_DATA_ERROR)
                    162:                        fatal("%s error: %s", (zio->reset == inflateReset) ?
                    163:                            "inflate" : "deflate", zstream->msg);
1.1       xsa       164:
                    165:                if (cvs_buf_append(dst, buf,
1.5       pat       166:                    sizeof(buf) - zstream->avail_out) < 0)
1.1       xsa       167:                        return (-1);
1.5       pat       168:                bytes += sizeof(buf) - zstream->avail_out;
1.1       xsa       169:        } while (ret != Z_STREAM_END);
                    170:
                    171:        return (bytes);
                    172: }