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: }