Annotation of src/usr.bin/cvs/compress.c, Revision 1.5
1.5 ! pat 1: /* $OpenBSD: compress.c,v 1.4 2006/04/14 02:45:35 deraadt 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:
28: #include "includes.h"
29:
30: #include "log.h"
31: #include "cvs.h"
32: #include "compress.h"
33:
34: #define CVS_ZLIB_BUFSIZE 1024
35:
36: struct cvs_zlib_ctx {
37: int z_level;
38: z_stream z_instrm;
39: z_stream z_destrm;
40: };
41:
1.5 ! pat 42: struct zlib_ioctx {
! 43: z_stream *stream;
! 44: int (*reset)(z_stream *);
! 45: int (*io)(z_stream *, int);
! 46: int ioflags;
! 47: };
! 48:
! 49: static int cvs_zlib_io(struct zlib_ioctx *, BUF *, u_char *, size_t);
1.1 xsa 50:
51: /*
52: * cvs_zlib_newctx()
53: *
54: * Allocate a new ZLIB context structure used for both inflation and deflation
55: * of data with compression level <level>, which must be between 0 and 9. A
56: * value of 0 means no compression, and 9 is the highest level of compression.
57: */
58: CVSZCTX *
59: cvs_zlib_newctx(int level)
60: {
61: CVSZCTX *ctx;
62:
1.4 deraadt 63: if (level < 0 || level > 9)
1.1 xsa 64: fatal("invalid compression level %d (must be between 0 and 9)",
65: level);
66:
1.2 ray 67: ctx = xcalloc(1, sizeof(*ctx));
1.1 xsa 68:
69: ctx->z_level = level;
70:
71: ctx->z_instrm.zalloc = Z_NULL;
72: ctx->z_instrm.zfree = Z_NULL;
73: ctx->z_instrm.opaque = Z_NULL;
74: ctx->z_destrm.zalloc = Z_NULL;
75: ctx->z_destrm.zfree = Z_NULL;
76: ctx->z_destrm.opaque = Z_NULL;
77:
1.4 deraadt 78: if (inflateInit(&(ctx->z_instrm)) != Z_OK ||
79: deflateInit(&(ctx->z_destrm), level) != Z_OK)
1.1 xsa 80: fatal("failed to initialize zlib streams");
81:
82: return (ctx);
83: }
84:
85:
86: /*
87: * cvs_zlib_free()
88: *
89: * Free a ZLIB context previously allocated with cvs_zlib_newctx().
90: */
91: void
92: cvs_zlib_free(CVSZCTX *ctx)
93: {
94: if (ctx != NULL) {
95: (void)inflateEnd(&(ctx->z_instrm));
96: (void)deflateEnd(&(ctx->z_destrm));
97: xfree(ctx);
98: }
99: }
100:
101: /*
102: * cvs_zlib_inflate()
103: *
104: * Decompress the first <slen> bytes of <src> using the zlib context <ctx> and
105: * store the resulting data in <dst>.
106: * Returns the number of bytes inflated on success, or -1 on failure.
107: */
108: int
109: cvs_zlib_inflate(CVSZCTX *ctx, BUF *dst, u_char *src, size_t slen)
110: {
1.5 ! pat 111: struct zlib_ioctx zio;
1.1 xsa 112:
1.5 ! pat 113: zio.stream = &ctx->z_instrm;
! 114: zio.reset = inflateReset;
! 115: zio.io = inflate;
! 116: zio.ioflags = Z_FINISH;
1.1 xsa 117:
1.5 ! pat 118: return cvs_zlib_io(&zio, dst, src, slen);
1.1 xsa 119: }
120:
121: /*
122: * cvs_zlib_deflate()
123: *
124: * Compress the first <slen> bytes of <src> using the zlib context <ctx> and
125: * store the resulting data in <dst>.
126: * Returns the number of bytes deflated on success, or -1 on failure.
127: */
128: int
129: cvs_zlib_deflate(CVSZCTX *ctx, BUF *dst, u_char *src, size_t slen)
130: {
1.5 ! pat 131: struct zlib_ioctx zio;
! 132:
! 133: zio.stream = &ctx->z_destrm;
! 134: zio.reset = deflateReset;
! 135: zio.io = deflate;
! 136: zio.ioflags = Z_FINISH;
! 137:
! 138: return cvs_zlib_io(&zio, dst, src, slen);
! 139: }
! 140:
! 141: static int
! 142: cvs_zlib_io(struct zlib_ioctx *zio, BUF *dst, u_char *src, size_t slen)
! 143: {
1.1 xsa 144: int bytes, ret;
145: u_char buf[CVS_ZLIB_BUFSIZE];
1.5 ! pat 146: z_stream *zstream = zio->stream;
1.1 xsa 147:
148: bytes = 0;
149: cvs_buf_empty(dst);
1.5 ! pat 150: if ((*zio->reset)(zstream) == Z_STREAM_ERROR)
! 151: fatal("%s error: %s", (zio->reset == inflateReset) ?
! 152: "inflate" : "deflate", zstream->msg);
1.1 xsa 153:
1.5 ! pat 154: zstream->next_in = src;
! 155: zstream->avail_in = slen;
1.1 xsa 156:
157: do {
1.5 ! pat 158: zstream->next_out = buf;
! 159: zstream->avail_out = sizeof(buf);
! 160: ret = (*zio->io)(zstream, zio->ioflags);
! 161: if (ret == Z_MEM_ERROR || ret == Z_STREAM_ERROR ||
! 162: ret == Z_BUF_ERROR || ret == Z_DATA_ERROR)
! 163: fatal("%s error: %s", (zio->reset == inflateReset) ?
! 164: "inflate" : "deflate", zstream->msg);
1.1 xsa 165:
166: if (cvs_buf_append(dst, buf,
1.5 ! pat 167: sizeof(buf) - zstream->avail_out) < 0)
1.1 xsa 168: return (-1);
1.5 ! pat 169: bytes += sizeof(buf) - zstream->avail_out;
1.1 xsa 170: } while (ret != Z_STREAM_END);
171:
172: return (bytes);
173: }