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