1 /* xpkGZIP.c -- using zlib by Jean-loup Gailly and Mark Adler
2 * Copyright (C) 1996-2000 authors
3 * This file is part of the xpk package.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA.
19 */
20
21 /* Written by Gunther Nikl <gnikl@informatik.uni-rostock.de>
22 * UNIX version by Vesa Halttunen <vesuri@jormas.com>
23 */
24
25 #include <string.h>
26 #include <sys/types.h>
27 #include <xpk/xpksub.h>
28 #include <zlib.h>
29
30 /* common constants from zutil.h */
31 #ifndef DEF_WBITS
32 # define DEF_WBITS MAX_WBITS
33 #endif
34 /* default windowBits for decompression. MAX_WBITS is for compression only */
35
36 #if MAX_MEM_LEVEL >= 8
37 # define DEF_MEM_LEVEL 8
38 #else
39 # define DEF_MEM_LEVEL MAX_MEM_LEVEL
40 #endif
41 /* default memLevel */
42
43
44 /*
45 * a shortcut
46 */
47 typedef struct XpkSubParams XPAR;
48
49 /*
50 * required information structures
51 */
52 #define GZIPMODE(x) (struct XpkMode *)(GZIPModes+x)
53
54 static const struct XpkMode GZIPModes[] = {
55 { GZIPMODE(1), 9, 0, 0, 0, 1607, 4575, 0, 0, "store" },
56 { GZIPMODE(2), 19, 0, 0, 0, 269, 1451, 468, 0, "laziest" },
57 { GZIPMODE(3), 29, 0, 0, 0, 245, 1451, 473, 0, "lazier" },
58 { GZIPMODE(4), 39, 0, 0, 0, 198, 1451, 474, 0, "lazy" },
59 { GZIPMODE(5), 49, 0, 0, 0, 175, 1487, 486, 0, "calm" },
60 { GZIPMODE(6), 59, 0, 0, 0, 137, 1525, 493, 0, "average" },
61 { GZIPMODE(7), 69, 0, 0, 0, 98, 1525, 496, 0, "willing" },
62 { GZIPMODE(8), 79, 0, 0, 0, 86, 1525, 497, 0, "greedy" },
63 { GZIPMODE(9), 89, 0, 0, 0, 62, 1525, 497, 0, "greedier" },
64 { NULL, 100, 0, 0, 0, 52, 1525, 497, 0, "greediest" }
65 };
66
67 static const struct XpkInfo GZIPInfo = {
68 1, /* info version */
69 1, /* lib version */
70 0, /* master vers */
71 // 2, /* master vers */
72 0, /* pad */
73 "GZIP", /* short name */
74 "GZIP Version 1.1", /* long name */
75 "LZ77 class packer with hashing and dynamic Huffman coding", /* description */
76 0x475A4950, /* 4 letter ID */
77 XPKIF_PK_CHUNK | /* flags */
78 XPKIF_UP_CHUNK | XPKIF_MODES,
79 16*1024*1024, /* max in chunk */
80 0, /* min in chunk */
81 256*1024, /* def in chunk */
82 "deflating", /* pk message */
83 "inflating", /* up message */
84 "deflated", /* pk past msg */
85 "inflated", /* up past msg */
86 65, /* def mode */
87 0, /* pad */
88 GZIPMODE(0), /* modes */
89 {0,} /* reserved */
90 };
91
92 z_streamp ZStream;
93
94 /*
95 * return an info structure about our packer
96 */
LIBXpksPackerInfo(void)97 const struct XpkInfo *LIBXpksPackerInfo(void)
98 {
99 return &GZIPInfo;
100 }
101
102 /*
103 * utility functions for ZLIB
104 */
zcFree(voidpf opaque,voidpf ptr)105 static void zcFree(voidpf opaque, voidpf ptr)
106 {
107 /* struct XpkSubParams *xpar = (struct XpkSubParams *)opaque; */
108
109 if (ptr)
110 free(ptr-sizeof(unsigned int));
111 }
112
zcAlloc(voidpf opaque,unsigned items,unsigned itemsize)113 static voidpf zcAlloc(voidpf opaque,unsigned items,unsigned itemsize)
114 {
115 /* struct XpkSubParams *xpar = (struct XpkSubParams *)opaque; */
116 unsigned int size, *mem;
117
118 if ((mem=(unsigned int *)calloc(size=sizeof(*mem)+items*itemsize, 1)))
119 *mem++ = size;
120 return mem;
121 }
122
123 /*
124 * initialize a z_stream (either for compression or decompression)
125 */
init_stream(struct XpkSubParams * xpar)126 static z_streamp init_stream(struct XpkSubParams *xpar)
127 { z_streamp stream = ZStream;
128
129 for(;;) {
130 if (!stream) {
131 if ((ZStream=stream=zcAlloc(xpar,1,sizeof(*stream))) == NULL)
132 break;
133 stream->zalloc = zcAlloc;
134 stream->zfree = zcFree;
135 stream->opaque = xpar;
136 }
137 stream->next_in = (Bytef *)xpar->xsp_InBuf;
138 stream->avail_in = (uInt )xpar->xsp_InLen;
139 stream->next_out = (Bytef *)xpar->xsp_OutBuf;
140 stream->avail_out = (uInt )xpar->xsp_OutBufLen;
141 break;
142 }
143 return stream;
144 }
145
146 /*
147 * kill a z_stream
148 */
free_stream(struct XpkSubParams * xpar,z_streamp stream)149 static void free_stream(struct XpkSubParams *xpar, z_streamp stream)
150 {
151 zcFree(xpar, stream);
152 }
153
154 /*
155 * compress a chunk of memory
156 */
LIBXpksPackChunk(struct XpkSubParams * xpar)157 int LIBXpksPackChunk(struct XpkSubParams *xpar)
158 { int level, err = XPKERR_NOMEM;
159 z_streamp stream;
160
161 if ((stream=init_stream(xpar))) {
162 if ((level=xpar->xsp_Mode/10) != 10) {
163 if (level < Z_NO_COMPRESSION || level > Z_BEST_COMPRESSION)
164 level = Z_DEFAULT_COMPRESSION;
165 } else level = Z_BEST_COMPRESSION;
166 if (deflateInit2(stream,level,Z_DEFLATED,DEF_WBITS,DEF_MEM_LEVEL,Z_DEFAULT_STRATEGY) == Z_OK) {
167 if (deflate(stream,Z_FINISH) == Z_STREAM_END) {
168 xpar->xsp_OutLen = stream->total_out; err = XPKERR_OK;
169 } else err = XPKERR_UNKNOWN;
170 deflateEnd(stream);
171 }
172 free_stream(xpar, stream);
173 }
174 return err;
175 }
176
177 /*
178 * restore state information after a XPKERR_EXPANSION
179 */
180
LIBXpksPackReset(struct XpkSubParams * xpar)181 int LIBXpksPackReset(struct XpkSubParams *xpar)
182 {
183 int err;
184
185 if (!ZStream || (err=deflateReset(ZStream))!=Z_OK)
186 err = XPKERR_UNKNOWN;
187 else
188 err = XPKERR_OK;
189 return err;
190 }
191
192 /*
193 * uncompress a chunk of memory
194 */
LIBXpksUnpackChunk(struct XpkSubParams * xpar)195 int LIBXpksUnpackChunk(struct XpkSubParams *xpar)
196 {
197 int err = XPKERR_NOMEM;
198 z_streamp stream;
199
200 if ((stream=init_stream(xpar))) {
201 if (inflateInit2(stream,DEF_WBITS) == Z_OK) {
202 if (inflate(stream,Z_FINISH) == Z_STREAM_END) {
203 xpar->xsp_OutLen = stream->total_out; err = XPKERR_OK;
204 } else err = XPKERR_UNKNOWN;
205 inflateEnd(stream);
206 }
207 }
208 return err;
209 }
210