]> granicus.if.org Git - postgresql/blob - contrib/pgcrypto/pgp-compress.c
Add missing pgcrypto files from previous commit.
[postgresql] / contrib / pgcrypto / pgp-compress.c
1 /*
2  * pgp-compress.c
3  *        ZIP and ZLIB compression via zlib.
4  *
5  * Copyright (c) 2005 Marko Kreen
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *        notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *        notice, this list of conditions and the following disclaimer in the
15  *        documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.      IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-compress.c,v 1.1 2005/07/10 13:46:28 momjian Exp $
30  */
31
32 #include <postgres.h>
33
34 #include "mbuf.h"
35 #include "px.h"
36 #include "pgp.h"
37
38
39 /*
40  * Compressed pkt writer
41  */
42
43 #ifndef DISABLE_ZLIB
44
45 #include <zlib.h>
46 #define ZIP_OUT_BUF 8192
47 #define ZIP_IN_BLOCK 8192
48
49 struct ZipStat
50 {
51         uint8           type;
52         int                     buf_len;
53         int                     hdr_done;
54         z_stream        stream;
55         uint8           buf[ZIP_OUT_BUF];
56 };
57
58 static void *
59 z_alloc(void *priv, unsigned n_items, unsigned item_len)
60 {
61         return px_alloc(n_items * item_len);
62 }
63
64 static void
65 z_free(void *priv, void *addr)
66 {
67         px_free(addr);
68 }
69
70 static int
71 compress_init(PushFilter * next, void *init_arg, void **priv_p)
72 {
73         int                     res;
74         struct ZipStat *st;
75         PGP_Context *ctx = init_arg;
76         uint8           type = ctx->compress_algo;
77
78         if (type != PGP_COMPR_ZLIB && type != PGP_COMPR_ZIP)
79                 return PXE_PGP_UNSUPPORTED_COMPR;
80
81         /*
82          * init
83          */
84         st = px_alloc(sizeof(*st));
85         memset(st, 0, sizeof(*st));
86         st->buf_len = ZIP_OUT_BUF;
87         st->stream.zalloc = z_alloc;
88         st->stream.zfree = z_free;
89
90         if (type == PGP_COMPR_ZIP)
91                 res = deflateInit2(&st->stream, ctx->compress_level,
92                                                    Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
93         else
94                 res = deflateInit(&st->stream, ctx->compress_level);
95         if (res != Z_OK)
96         {
97                 px_free(st);
98                 return PXE_PGP_COMPRESSION_ERROR;
99         }
100         *priv_p = st;
101
102         return ZIP_IN_BLOCK;
103 }
104
105 /* writes compressed data packet */
106
107 /* cant handle zero-len incoming data, but shouldnt */
108 static int
109 compress_process(PushFilter * next, void *priv, const uint8 *data, int len)
110 {
111         int                     res,
112                                 n_out;
113         struct ZipStat *st = priv;
114
115         /*
116          * process data
117          */
118         while (len > 0)
119         {
120                 st->stream.next_in = (void *) data;
121                 st->stream.avail_in = len;
122                 st->stream.next_out = st->buf;
123                 st->stream.avail_out = st->buf_len;
124                 res = deflate(&st->stream, 0);
125                 if (res != Z_OK)
126                         return PXE_PGP_COMPRESSION_ERROR;
127
128                 n_out = st->buf_len - st->stream.avail_out;
129                 if (n_out > 0)
130                 {
131                         res = pushf_write(next, st->buf, n_out);
132                         if (res < 0)
133                                 return res;
134                 }
135                 len = st->stream.avail_in;
136         }
137
138         return 0;
139 }
140
141 static int
142 compress_flush(PushFilter * next, void *priv)
143 {
144         int                     res,
145                                 zres,
146                                 n_out;
147         struct ZipStat *st = priv;
148
149         st->stream.next_in = NULL;
150         st->stream.avail_in = 0;
151         while (1)
152         {
153                 st->stream.next_out = st->buf;
154                 st->stream.avail_out = st->buf_len;
155                 zres = deflate(&st->stream, Z_FINISH);
156                 if (zres != Z_STREAM_END && zres != Z_OK)
157                         return PXE_PGP_COMPRESSION_ERROR;
158                 n_out = st->buf_len - st->stream.avail_out;
159                 if (n_out > 0)
160                 {
161                         res = pushf_write(next, st->buf, n_out);
162                         if (res < 0)
163                                 return res;
164                 }
165                 if (zres == Z_STREAM_END)
166                         break;
167         }
168         return 0;
169 }
170
171 static void
172 compress_free(void *priv)
173 {
174         struct ZipStat *st = priv;
175
176         deflateEnd(&st->stream);
177         memset(st, 0, sizeof(*st));
178         px_free(st);
179 }
180
181 static const PushFilterOps
182 compress_filter = {
183         compress_init, compress_process, compress_flush, compress_free
184 };
185
186 int
187 pgp_compress_filter(PushFilter **res, PGP_Context *ctx, PushFilter *dst)
188 {
189         return pushf_create(res, &compress_filter, ctx, dst);
190 }
191
192 /*
193  * Decompress
194  */
195 struct DecomprData
196 {
197         int                     buf_len;  /* = ZIP_OUT_BUF */
198         int                     buf_data; /* available data */
199         uint8      *pos;
200         z_stream        stream;
201         int                     eof;
202         uint8           buf[ZIP_OUT_BUF];
203 };
204
205 static int
206 decompress_init(void **priv_p, void *arg, PullFilter *src)
207 {
208         PGP_Context *ctx = arg;
209         struct DecomprData *dec;
210         int res;
211
212         if (ctx->compress_algo != PGP_COMPR_ZLIB
213                         && ctx->compress_algo != PGP_COMPR_ZIP)
214                 return PXE_PGP_UNSUPPORTED_COMPR;
215
216         dec = px_alloc(sizeof(*dec));
217         memset(dec, 0, sizeof(*dec));
218         dec->buf_len = ZIP_OUT_BUF;
219         *priv_p = dec;
220
221         dec->stream.zalloc = z_alloc;
222         dec->stream.zfree = z_free;
223
224         if (ctx->compress_algo == PGP_COMPR_ZIP)
225                 res = inflateInit2(&dec->stream, -15);
226         else
227                 res = inflateInit(&dec->stream);
228         if (res != Z_OK)
229         {
230                 px_free(dec);
231                 px_debug("decompress_init: inflateInit error");
232                 return PXE_PGP_COMPRESSION_ERROR;
233         }
234         
235         return 0;
236 }
237
238 static int decompress_read(void *priv, PullFilter *src, int len,
239                         uint8 **data_p, uint8 *buf, int buflen)
240 {
241         int res;
242         int flush;
243         struct DecomprData *dec = priv;
244
245 restart:
246         if (dec->buf_data > 0)
247         {
248                 if (len > dec->buf_data)
249                         len = dec->buf_data;
250                 *data_p = dec->pos;
251                 dec->pos += len;
252                 dec->buf_data -= len;
253                 return len;
254         }
255
256         if (dec->eof)
257                 return 0;
258         
259         if (dec->stream.avail_in == 0) {
260                 uint8 *tmp;
261                 res = pullf_read(src, 8192, &tmp);
262                 if (res < 0)
263                         return res;
264                 dec->stream.next_in = tmp;
265                 dec->stream.avail_in = res;
266         }
267         
268         dec->stream.next_out = dec->buf;
269         dec->stream.avail_out = dec->buf_len;
270         dec->pos = dec->buf;
271
272         // Z_NO_FLUSH, Z_SYNC_FLUSH,
273         flush = dec->stream.avail_in ? Z_SYNC_FLUSH : Z_FINISH;
274         res = inflate(&dec->stream, flush);
275         if (res != Z_OK && res != Z_STREAM_END)
276         {
277                 px_debug("decompress_read: inflate error: %d", res);
278                 return PXE_PGP_CORRUPT_DATA;
279         }
280
281         dec->buf_data = dec->buf_len - dec->stream.avail_out;
282         if (res == Z_STREAM_END)
283                 dec->eof = 1;
284         goto restart;
285 }
286
287 static void decompress_free(void *priv)
288 {
289         struct DecomprData *dec = priv;
290         inflateEnd(&dec->stream);
291         memset(dec, 0, sizeof(*dec));
292         px_free(dec);
293 }
294
295 static const PullFilterOps
296 decompress_filter = {
297         decompress_init, decompress_read, decompress_free
298 };
299
300 int
301 pgp_decompress_filter(PullFilter **res, PGP_Context *ctx, PullFilter *src)
302 {
303         return pullf_create(res, &decompress_filter, ctx, src);
304 }
305
306 #else /* DISABLE_ZLIB */
307
308 int
309 pgp_compress_filter(PushFilter **res, PGP_Context *ctx, PushFilter *dst)
310 {
311         return PXE_PGP_UNSUPPORTED_COMPR;
312 }
313
314 int
315 pgp_decompress_filter(PullFilter **res, PGP_Context *ctx, PullFilter *src)
316 {
317         return PXE_PGP_UNSUPPORTED_COMPR;
318 }
319
320 #endif
321
322