1 /* $Id: compress.c 119 2004-10-05 20:38:42Z oyvind $
2
3 $Log$
4 Revision 1.1 2004/10/05 20:31:35 oyvind
5 * added GCC to repository
6
7 Revision 1.2 2000/12/14 18:45:35 ghazi
8 Warning fixes:
9
10 * compress.c: Include stdlib.h and compress.h.
11 (rcsid): Delete.
12 (report_str_error): Make static.
13 (ez_inflate_str): Delete unused variable. Add parens in if-stmt.
14 (hrd_inflate_str): Likewise.
15
16 * compress.h (init_compression, end_compression, init_inflation,
17 end_inflation): Prototype void arguments.
18
19 * dostime.c (rcsid): Delete.
20
21 * jargrep.c: Include ctype.h, stdlib.h, zlib.h and compress.h.
22 Make functions static. Cast ctype function argument to `unsigned
23 char'. Add parens in if-stmts. Constify.
24 (Usage): Change into a macro.
25 (jargrep): Remove unused parameter.
26
27 * jartool.c: Constify. Add parens in if-stmts. Align
28 signed/unsigned char pointers in functions calls using casts.
29 (rcsid): Delete.
30 (list_jar): Fix printf format specifier.
31 (usage): Chop long string into bits. Reformat.
32
33 * pushback.c (rcsid): Delete.
34
35 Revision 1.1 2000/12/09 03:08:23 apbianco
36 2000-12-08 Alexandre Petit-Bianco <apbianco@cygnus.com>
37
38 * fastjar: Imported.
39
40 Revision 1.7 2000/09/13 14:02:02 cory
41 Reformatted some of the code to more closly match the layout of the orriginal
42 fastjar utility.
43
44 Revision 1.6 2000/09/12 22:29:36 cory
45 Jargrep now seems to do what I want it to do. Performs properly on Linux x86,
46 will test some other platforms later.
47
48 Revision 1.1.1.1 1999/12/06 03:09:16 toast
49 initial checkin..
50
51
52
53 Revision 1.7 1999/05/10 08:50:05 burnsbr
54 *** empty log message ***
55
56 Revision 1.6 1999/05/10 08:38:44 burnsbr
57 *** empty log message ***
58
59 Revision 1.5 1999/05/10 08:30:29 burnsbr
60 added inflation code
61
62 Revision 1.4 1999/04/27 10:03:33 burnsbr
63 added configure support
64
65 Revision 1.3 1999/04/26 02:35:32 burnsbr
66 compression now works.. yahoo
67
68 Revision 1.2 1999/04/23 12:01:59 burnsbr
69 added licence stuff.
70
71 Revision 1.1 1999/04/23 11:58:25 burnsbr
72 Initial revision
73
74
75 */
76
77 /*
78 compress.c - code for handling deflation
79 Copyright (C) 1999 Bryan Burns
80
81 This program is free software; you can redistribute it and/or
82 modify it under the terms of the GNU General Public License
83 as published by the Free Software Foundation; either version 2
84 of the License, or (at your option) any later version.
85
86 This program is distributed in the hope that it will be useful,
87 but WITHOUT ANY WARRANTY; without even the implied warranty of
88 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
89 GNU General Public License for more details.
90
91 You should have received a copy of the GNU General Public License
92 along with this program; if not, write to the Free Software
93 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
94 */
95
96 #include "config.h"
97
98 #include <zlib.h>
99 #include <string.h>
100 #include <stdio.h>
101 #include <errno.h>
102
103 #ifdef HAVE_UNISTD_H
104 #include <unistd.h>
105 #endif
106 #ifdef STDC_HEADERS
107 #include <stdlib.h>
108 #endif
109
110 #include <sys/types.h>
111
112 #include "jartool.h"
113 #include "pushback.h"
114 #include "compress.h"
115
116 extern int seekable;
117
118 static z_stream zs;
119
init_compression()120 void init_compression(){
121
122 memset(&zs, 0, sizeof(z_stream));
123
124 zs.zalloc = Z_NULL;
125 zs.zfree = Z_NULL;
126 zs.opaque = Z_NULL;
127
128 /* Why -MAX_WBITS? zlib has an undocumented feature, where if the windowbits
129 parameter is negative, it omits the zlib header, which seems to kill
130 any other zip/unzip program. This caused me SO much pain.. */
131 if(deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS,
132 9, Z_DEFAULT_STRATEGY) != Z_OK){
133
134 fprintf(stderr, "Error initializing deflation!\n");
135 exit(1);
136 }
137 }
138
compress_file(int in_fd,int out_fd,struct zipentry * ze)139 int compress_file(int in_fd, int out_fd, struct zipentry *ze){
140 Bytef in_buff[RDSZ];
141 Bytef out_buff[RDSZ];
142 unsigned int rdamt, wramt;
143 unsigned long tr = 0;
144 int rtval;
145
146 rdamt = 0;
147
148 zs.avail_in = 0;
149 zs.next_in = in_buff;
150
151 zs.next_out = out_buff;
152 zs.avail_out = (uInt)RDSZ;
153
154 ze->crc = crc32(0L, Z_NULL, 0);
155
156 for(; ;){
157
158 /* If deflate is out of input, fill the input buffer for it */
159 if(zs.avail_in == 0 && zs.avail_out > 0){
160 if((rtval = read(in_fd, in_buff, RDSZ)) == 0)
161 break;
162
163 if(rtval == -1){
164 perror("read");
165 exit(1);
166 }
167
168 rdamt = rtval;
169
170 /* compute the CRC while we're at it */
171 ze->crc = crc32(ze->crc, in_buff, rdamt);
172
173 /* update the total amount read sofar */
174 tr += rdamt;
175
176 zs.next_in = in_buff;
177 zs.avail_in = rdamt;
178 }
179
180 /* deflate the data */
181 if(deflate(&zs, 0) != Z_OK){
182 fprintf(stderr, "Error deflating! %s:%d\n", __FILE__, __LINE__);
183 exit(1);
184 }
185
186 /* If the output buffer is full, dump it to disk */
187 if(zs.avail_out == 0){
188
189 if(write(out_fd, out_buff, RDSZ) != RDSZ){
190 perror("write");
191 exit(1);
192 }
193
194 /* clear the output buffer */
195 zs.next_out = out_buff;
196 zs.avail_out = (uInt)RDSZ;
197 }
198
199 }
200
201 /* If we have any data waiting in the buffer after we're done with the file
202 we can flush it */
203 if(zs.avail_out < RDSZ){
204
205 wramt = RDSZ - zs.avail_out;
206
207 if(write(out_fd, out_buff, wramt) != (int)wramt){
208 perror("write");
209 exit(1);
210 }
211 /* clear the output buffer */
212 zs.next_out = out_buff;
213 zs.avail_out = (uInt)RDSZ;
214 }
215
216
217 /* finish deflation. This purges zlib's internal data buffers */
218 while(deflate(&zs, Z_FINISH) == Z_OK){
219 wramt = RDSZ - zs.avail_out;
220
221 if(write(out_fd, out_buff, wramt) != (int)wramt){
222 perror("write");
223 exit(1);
224 }
225
226 zs.next_out = out_buff;
227 zs.avail_out = (uInt)RDSZ;
228 }
229
230 /* If there's any data left in the buffer, write it out */
231 if(zs.avail_out != RDSZ){
232 wramt = RDSZ - zs.avail_out;
233
234 if(write(out_fd, out_buff, wramt) != (int)wramt){
235 perror("write");
236 exit(1);
237 }
238 }
239
240 /* update fastjar's entry information */
241 ze->usize = (ub4)zs.total_in;
242 ze->csize = (ub4)zs.total_out;
243
244 /* Reset the deflation for the next time around */
245 if(deflateReset(&zs) != Z_OK){
246 fprintf(stderr, "Error resetting deflation\n");
247 exit(1);
248 }
249
250 return 0;
251 }
252
end_compression()253 void end_compression(){
254 int rtval;
255
256 /* Oddly enough, zlib always returns Z_DATA_ERROR if you specify no
257 zlib header. Go fig. */
258 if((rtval = deflateEnd(&zs)) != Z_OK && rtval != Z_DATA_ERROR){
259 fprintf(stderr, "Error calling deflateEnd\n");
260 fprintf(stderr, "error: (%d) %s\n", rtval, zs.msg);
261 exit(1);
262 }
263 }
264
265
init_inflation()266 void init_inflation(){
267
268 memset(&zs, 0, sizeof(z_stream));
269
270 zs.zalloc = Z_NULL;
271 zs.zfree = Z_NULL;
272 zs.opaque = Z_NULL;
273
274 if(inflateInit2(&zs, -15) != Z_OK){
275 fprintf(stderr, "Error initializing deflation!\n");
276 exit(1);
277 }
278
279 }
280
inflate_file(pb_file * pbf,int out_fd,struct zipentry * ze)281 int inflate_file(pb_file *pbf, int out_fd, struct zipentry *ze){
282 Bytef in_buff[RDSZ];
283 Bytef out_buff[RDSZ];
284 unsigned int rdamt;
285 int rtval;
286 ub4 crc = 0;
287
288 zs.avail_in = 0;
289
290 crc = crc32(crc, NULL, 0); /* initialize crc */
291
292 /* loop until we've consumed all the compressed data */
293 for(;;){
294
295 if(zs.avail_in == 0){
296 if((rdamt = pb_read(pbf, in_buff, RDSZ)) == 0)
297 break;
298 else if((int)rdamt < 0){
299 perror("read");
300 exit(1);
301 }
302
303 #ifdef DEBUG
304 printf("%d bytes read\n", rdamt);
305 #endif
306
307 zs.next_in = in_buff;
308 zs.avail_in = rdamt;
309 }
310
311 zs.next_out = out_buff;
312 zs.avail_out = RDSZ;
313
314 if((rtval = inflate(&zs, 0)) != Z_OK){
315 if(rtval == Z_STREAM_END){
316 #ifdef DEBUG
317 printf("end of stream\n");
318 #endif
319 if(zs.avail_out != RDSZ){
320 crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
321
322 if(out_fd >= 0)
323 if(write(out_fd, out_buff, (RDSZ - zs.avail_out)) !=
324 (int)(RDSZ - zs.avail_out)){
325 perror("write");
326 exit(1);
327 }
328 }
329
330 break;
331 } else {
332 fprintf(stderr, "Error inflating file! (%d)\n", rtval);
333 exit(1);
334 }
335 } else {
336 if(zs.avail_out != RDSZ){
337 crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
338
339 if(out_fd >= 0)
340 if(write(out_fd, out_buff, (RDSZ - zs.avail_out)) !=
341 (int)(RDSZ - zs.avail_out)){
342 perror("write");
343 exit(1);
344 }
345 zs.next_out = out_buff;
346 zs.avail_out = RDSZ;
347 }
348 }
349 }
350 #ifdef DEBUG
351 printf("done inflating\n");
352 #endif
353
354 #ifdef DEBUG
355 printf("%d bytes left over\n", zs.avail_in);
356 #endif
357
358 #ifdef DEBUG
359 printf("CRC is %x\n", crc);
360 #endif
361
362 ze->crc = crc;
363
364 pb_push(pbf, zs.next_in, zs.avail_in);
365
366 ze->usize = zs.total_out;
367
368 inflateReset(&zs);
369 return 0;
370 }
371
372 /*
373 Function name: report_str_error
374 args: val Error code returned from zlib.
375 purpose: Put out an error message corresponding to error code returned from zlib.
376 Be suitably cryptic seeing I don't really know exactly what these errors mean.
377 */
378
report_str_error(int val)379 static void report_str_error(int val) {
380 switch(val) {
381 case Z_STREAM_END:
382 break;
383 case Z_NEED_DICT:
384 fprintf(stderr, "Need a dictionary?\n");
385 exit(1);
386 case Z_DATA_ERROR:
387 fprintf(stderr, "Z_DATA_ERROR\n");
388 exit(1);
389 case Z_STREAM_ERROR:
390 fprintf(stderr, "Z_STREAM_ERROR\n");
391 exit(1);
392 case Z_MEM_ERROR:
393 fprintf(stderr, "Z_MEM_ERROR\n");
394 exit(1);
395 case Z_BUF_ERROR:
396 fprintf(stderr, "Z_BUF_ERROR\n");
397 exit(1);
398 case Z_OK:
399 break;
400 default:
401 fprintf(stderr, "Unknown behavior from inflate\n");
402 exit(1);
403 }
404 }
405
406 /*
407 Function name: ez_inflate_str
408 args: pbf Pointer to pushback handle for file.
409 csize Compressed size of embedded file.
410 usize Uncompressed size of embedded file.
411 purpose: Read in and decompress the contents of an embedded file and store it in a
412 byte array.
413 returns: Byte array of uncompressed embedded file.
414 */
415
ez_inflate_str(pb_file * pbf,ub4 csize,ub4 usize)416 static Bytef *ez_inflate_str(pb_file *pbf, ub4 csize, ub4 usize) {
417 Bytef *out_buff;
418 Bytef *in_buff;
419 unsigned int rdamt;
420
421 if((zs.next_in = in_buff = (Bytef *) malloc(csize))) {
422 if((zs.next_out = out_buff = (Bytef *) malloc(usize + 1))) {
423 if((rdamt = pb_read(pbf, zs.next_in, csize)) == csize) {
424 zs.avail_in = csize;
425 zs.avail_out = usize;
426 report_str_error(inflate(&zs, 0));
427 free(in_buff);
428 inflateReset(&zs);
429 out_buff[usize] = '\0';
430 }
431 else {
432 fprintf(stderr, "Read failed on input file.\n");
433 fprintf(stderr, "Tried to read %u but read %u instead.\n", csize, rdamt);
434 free(in_buff);
435 free(out_buff);
436 exit(1);
437 }
438 }
439 else {
440 fprintf(stderr, "Malloc of out_buff failed.\n");
441 fprintf(stderr, "Error: %s\n", strerror(errno));
442 free(in_buff);
443 exit(1);
444 }
445 }
446 else {
447 fprintf(stderr, "Malloc of in_buff failed.\n");
448 fprintf(stderr, "Error: %s\n", strerror(errno));
449 exit(1);
450 }
451
452 return out_buff;
453 }
454
455 /*
456 Function name: hrd_inflate_str
457 args: pbf Pointer to pushback handle for file.
458 csize Pointer to compressed size of embedded file.
459 usize Pointer to uncompressed size of embedded file.
460 purpose: Read and decompress an embedded file into a string. Set csize and usize
461 accordingly. This function does the reading for us in the case there is not size
462 information in the header for the embedded file.
463 returns: Byte array of the contents of the embedded file.
464 */
465
hrd_inflate_str(pb_file * pbf,ub4 * csize,ub4 * usize)466 static Bytef *hrd_inflate_str(pb_file *pbf, ub4 *csize, ub4 *usize) {
467 Bytef *out_buff;
468 Bytef *tmp;
469 Bytef in_buff[RDSZ];
470 unsigned int rdamt;
471 int i;
472 int zret;
473
474 i = 1;
475 out_buff = NULL;
476 zret = Z_OK;
477 while(zret != Z_STREAM_END && (rdamt = pb_read(pbf, in_buff, RDSZ)))
478 {
479 zs.avail_in = rdamt;
480 zs.avail_out = 0;
481 zs.next_in = in_buff;
482 do {
483 if((tmp = (Bytef *) realloc(out_buff, (RDSZ * i) + 1))) {
484 out_buff = tmp;
485 zs.next_out = &(out_buff[(RDSZ * (i - 1)) - zs.avail_out]);
486 zs.avail_out += RDSZ;
487 i++;
488 }
489 else {
490 fprintf(stderr, "Realloc of out_buff failed.\n");
491 fprintf(stderr, "Error: %s\n", strerror(errno));
492 exit(1);
493 }
494 } while((zret = inflate(&zs, 0)) == Z_OK);
495 report_str_error(zret);
496 }
497 pb_push(pbf, zs.next_in, zs.avail_in);
498
499 out_buff[(RDSZ * (i - 1)) - zs.avail_out] = '\0';
500 *usize = zs.total_out;
501 *csize = zs.total_in;
502
503 inflateReset(&zs);
504
505 return out_buff;
506 }
507
508 /*
509 Function name: inflate_string
510 args: pbf Pointer to pushback handle for file.
511 csize Pointer to compressed size of embedded file. May be 0 if not set.
512 usize Pointer to uncompressed size of embedded file. May be 0 if not set.
513 purpose: Decide the easiest (in computer terms) methos of decompressing this embedded
514 file to a string.
515 returns: Pointer to a string containing the decompressed contents of the embedded file.
516 If csize and usize are not set set them to correct numbers.
517 */
518
inflate_string(pb_file * pbf,ub4 * csize,ub4 * usize)519 Bytef *inflate_string(pb_file *pbf, ub4 *csize, ub4 *usize) {
520 Bytef *ret_buf;
521
522 if(*csize && *usize) ret_buf = ez_inflate_str(pbf, *csize, *usize);
523 else ret_buf = hrd_inflate_str(pbf, csize, usize);
524
525 return ret_buf;
526 }
527