1 /* $Id: compress.c,v 1.1.1.1 2006/04/17 18:44:35 tromey Exp $
2
3 $Log: compress.c,v $
4 Revision 1.1.1.1 2006/04/17 18:44:35 tromey
5 Imported fastjar
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 Copyright (C) 2004 Free Software Foundation, Inc.
81
82 This program is free software; you can redistribute it and/or
83 modify it under the terms of the GNU General Public License
84 as published by the Free Software Foundation; either version 2
85 of the License, or (at your option) any later version.
86
87 This program is distributed in the hope that it will be useful,
88 but WITHOUT ANY WARRANTY; without even the implied warranty of
89 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
90 GNU General Public License for more details.
91
92 You should have received a copy of the GNU General Public License
93 along with this program; if not, write to the Free Software
94 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
95 */
96
97 #include "config.h"
98
99 #include <zlib.h>
100 #include <string.h>
101 #include <stdio.h>
102 #include <errno.h>
103
104 #ifdef HAVE_UNISTD_H
105 #include <unistd.h>
106 #endif
107 #ifdef STDC_HEADERS
108 #include <stdlib.h>
109 #endif
110
111 #include <sys/types.h>
112
113 #include "jartool.h"
114 #include "pushback.h"
115 #include "compress.h"
116 #include "shift.h"
117
118 int write_data (int, void *, size_t, struct zipentry *);
119
120 extern int seekable;
121 extern off_t end_of_entries;
122
123 static z_stream zs;
124
init_compression()125 void init_compression(){
126
127 memset(&zs, 0, sizeof(z_stream));
128
129 zs.zalloc = Z_NULL;
130 zs.zfree = Z_NULL;
131 zs.opaque = Z_NULL;
132
133 /* Why -MAX_WBITS? zlib has an undocumented feature, where if the windowbits
134 parameter is negative, it omits the zlib header, which seems to kill
135 any other zip/unzip program. This caused me SO much pain.. */
136 if(deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS,
137 9, Z_DEFAULT_STRATEGY) != Z_OK){
138
139 fprintf(stderr, "Error initializing deflation!\n");
140 exit(1);
141 }
142 }
143
144 int
write_data(int fd,void * buf,size_t len,struct zipentry * ze)145 write_data (int fd, void *buf, size_t len,
146 struct zipentry *ze __attribute__((unused)))
147 {
148 #ifdef WITH_SHIFT_DOWN
149 struct zipentry *next = NULL;
150 off_t here = lseek (fd, 0, SEEK_CUR);
151 /*
152 * If we are updating and there is not enough space before the next
153 * entry, expand the file.
154 */
155 if (ze)
156 {
157 next = ze->next_entry;
158 if (next && here + len >= next->offset)
159 {
160 if (shift_down (fd, next->offset, (here + len) - next->offset, next))
161 {
162 perror ("can't expand file");
163 exit (1);
164 }
165 }
166 }
167 #endif /* WITH_SHIFT_DOWN */
168
169 return write (fd, buf, len);
170 }
171
compress_file(int in_fd,int out_fd,struct zipentry * ze,struct zipentry * existing)172 int compress_file(int in_fd, int out_fd, struct zipentry *ze,
173 struct zipentry *existing)
174 {
175 Bytef in_buff[RDSZ];
176 Bytef out_buff[RDSZ];
177 unsigned int rdamt, wramt;
178 unsigned long tr = 0;
179 int rtval;
180
181 rdamt = 0;
182
183 zs.avail_in = 0;
184 zs.next_in = in_buff;
185
186 zs.next_out = out_buff;
187 zs.avail_out = (uInt)RDSZ;
188
189 ze->crc = crc32(0L, Z_NULL, 0);
190
191 for(; ;){
192
193 /* If deflate is out of input, fill the input buffer for it */
194 if(zs.avail_in == 0 && zs.avail_out > 0){
195 if((rtval = read(in_fd, in_buff, RDSZ)) == 0)
196 break;
197
198 if(rtval == -1){
199 perror("read");
200 exit(1);
201 }
202
203 rdamt = rtval;
204
205 /* compute the CRC while we're at it */
206 ze->crc = crc32(ze->crc, in_buff, rdamt);
207
208 /* update the total amount read sofar */
209 tr += rdamt;
210
211 zs.next_in = in_buff;
212 zs.avail_in = rdamt;
213 }
214
215 /* deflate the data */
216 if(deflate(&zs, 0) != Z_OK){
217 fprintf(stderr, "Error deflating! %s:%d\n", __FILE__, __LINE__);
218 exit(1);
219 }
220
221 /* If the output buffer is full, dump it to disk */
222 if(zs.avail_out == 0){
223
224 if (write_data (out_fd, out_buff, RDSZ, existing) != RDSZ)
225 {
226 perror("write");
227 exit(1);
228 }
229
230 /* clear the output buffer */
231 zs.next_out = out_buff;
232 zs.avail_out = (uInt)RDSZ;
233 }
234
235 }
236
237 /* If we have any data waiting in the buffer after we're done with the file
238 we can flush it */
239 if(zs.avail_out < RDSZ){
240
241 wramt = RDSZ - zs.avail_out;
242
243 if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
244 {
245 perror("write");
246 exit(1);
247 }
248 /* clear the output buffer */
249 zs.next_out = out_buff;
250 zs.avail_out = (uInt)RDSZ;
251 }
252
253
254 /* finish deflation. This purges zlib's internal data buffers */
255 while(deflate(&zs, Z_FINISH) == Z_OK){
256 wramt = RDSZ - zs.avail_out;
257
258 if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
259 {
260 perror("write");
261 exit(1);
262 }
263
264 zs.next_out = out_buff;
265 zs.avail_out = (uInt)RDSZ;
266 }
267
268 /* If there's any data left in the buffer, write it out */
269 if(zs.avail_out != RDSZ){
270 wramt = RDSZ - zs.avail_out;
271
272 if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
273 {
274 perror("write");
275 exit(1);
276 }
277 }
278
279 /* update fastjar's entry information */
280 ze->usize = (ub4)zs.total_in;
281 ze->csize = (ub4)zs.total_out;
282
283 /* Reset the deflation for the next time around */
284 if(deflateReset(&zs) != Z_OK){
285 fprintf(stderr, "Error resetting deflation\n");
286 exit(1);
287 }
288
289 return 0;
290 }
291
end_compression()292 void end_compression(){
293 int rtval;
294
295 /* Oddly enough, zlib always returns Z_DATA_ERROR if you specify no
296 zlib header. Go fig. */
297 if((rtval = deflateEnd(&zs)) != Z_OK && rtval != Z_DATA_ERROR){
298 fprintf(stderr, "Error calling deflateEnd\n");
299 fprintf(stderr, "error: (%d) %s\n", rtval, zs.msg);
300 exit(1);
301 }
302 }
303
304
init_inflation()305 void init_inflation(){
306
307 memset(&zs, 0, sizeof(z_stream));
308
309 zs.zalloc = Z_NULL;
310 zs.zfree = Z_NULL;
311 zs.opaque = Z_NULL;
312
313 if(inflateInit2(&zs, -15) != Z_OK){
314 fprintf(stderr, "Error initializing deflation!\n");
315 exit(1);
316 }
317
318 }
319
inflate_file(pb_file * pbf,int out_fd,struct zipentry * ze)320 int inflate_file(pb_file *pbf, int out_fd, struct zipentry *ze){
321 Bytef in_buff[RDSZ];
322 Bytef out_buff[RDSZ];
323 unsigned int rdamt;
324 int rtval;
325 ub4 crc = 0;
326
327 zs.avail_in = 0;
328
329 crc = crc32(crc, NULL, 0); /* initialize crc */
330
331 /* loop until we've consumed all the compressed data */
332 for(;;){
333
334 if(zs.avail_in == 0){
335 if((rdamt = pb_read(pbf, in_buff, RDSZ)) == 0)
336 break;
337 else if((int)rdamt < 0){
338 perror("read");
339 exit(1);
340 }
341
342 #ifdef DEBUG
343 printf("%d bytes read\n", rdamt);
344 #endif
345
346 zs.next_in = in_buff;
347 zs.avail_in = rdamt;
348 }
349
350 zs.next_out = out_buff;
351 zs.avail_out = RDSZ;
352
353 if((rtval = inflate(&zs, 0)) != Z_OK){
354 if(rtval == Z_STREAM_END){
355 #ifdef DEBUG
356 printf("end of stream\n");
357 #endif
358 if(zs.avail_out != RDSZ){
359 crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
360
361 if(out_fd >= 0)
362 if(write(out_fd, out_buff, (RDSZ - zs.avail_out)) !=
363 (int)(RDSZ - zs.avail_out)){
364 perror("write");
365 exit(1);
366 }
367 }
368
369 break;
370 } else {
371 fprintf(stderr, "Error inflating file! (%d)\n", rtval);
372 exit(1);
373 }
374 } else {
375 if(zs.avail_out != RDSZ){
376 crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
377
378 if(out_fd >= 0)
379 if(write(out_fd, out_buff, (RDSZ - zs.avail_out)) !=
380 (int)(RDSZ - zs.avail_out)){
381 perror("write");
382 exit(1);
383 }
384 zs.next_out = out_buff;
385 zs.avail_out = RDSZ;
386 }
387 }
388 }
389 #ifdef DEBUG
390 printf("done inflating\n");
391 #endif
392
393 #ifdef DEBUG
394 printf("%d bytes left over\n", zs.avail_in);
395 #endif
396
397 #ifdef DEBUG
398 printf("CRC is %x\n", crc);
399 #endif
400
401 ze->crc = crc;
402
403 pb_push(pbf, zs.next_in, zs.avail_in);
404
405 ze->usize = zs.total_out;
406
407 inflateReset(&zs);
408 return 0;
409 }
410
411 /*
412 Function name: report_str_error
413 args: val Error code returned from zlib.
414 purpose: Put out an error message corresponding to error code returned from zlib.
415 Be suitably cryptic seeing I don't really know exactly what these errors mean.
416 */
417
report_str_error(int val)418 static void report_str_error(int val) {
419 switch(val) {
420 case Z_STREAM_END:
421 break;
422 case Z_NEED_DICT:
423 fprintf(stderr, "Need a dictionary?\n");
424 exit(1);
425 case Z_DATA_ERROR:
426 fprintf(stderr, "Z_DATA_ERROR\n");
427 exit(1);
428 case Z_STREAM_ERROR:
429 fprintf(stderr, "Z_STREAM_ERROR\n");
430 exit(1);
431 case Z_MEM_ERROR:
432 fprintf(stderr, "Z_MEM_ERROR\n");
433 exit(1);
434 case Z_BUF_ERROR:
435 fprintf(stderr, "Z_BUF_ERROR\n");
436 exit(1);
437 case Z_OK:
438 break;
439 default:
440 fprintf(stderr, "Unknown behavior from inflate\n");
441 exit(1);
442 }
443 }
444
445 /*
446 Function name: ez_inflate_str
447 args: pbf Pointer to pushback handle for file.
448 csize Compressed size of embedded file.
449 usize Uncompressed size of embedded file.
450 purpose: Read in and decompress the contents of an embedded file and store it in a
451 byte array.
452 returns: Byte array of uncompressed embedded file.
453 */
454
ez_inflate_str(pb_file * pbf,ub4 csize,ub4 usize)455 static Bytef *ez_inflate_str(pb_file *pbf, ub4 csize, ub4 usize) {
456 Bytef *out_buff;
457 Bytef *in_buff;
458 unsigned int rdamt;
459
460 if((zs.next_in = in_buff = (Bytef *) malloc(csize))) {
461 if((zs.next_out = out_buff = (Bytef *) malloc(usize + 1))) {
462 if((rdamt = pb_read(pbf, zs.next_in, csize)) == csize) {
463 zs.avail_in = csize;
464 zs.avail_out = usize;
465 report_str_error(inflate(&zs, 0));
466 free(in_buff);
467 inflateReset(&zs);
468 out_buff[usize] = '\0';
469 }
470 else {
471 fprintf(stderr, "Read failed on input file.\n");
472 fprintf(stderr, "Tried to read %u but read %u instead.\n", csize, rdamt);
473 free(in_buff);
474 free(out_buff);
475 exit(1);
476 }
477 }
478 else {
479 fprintf(stderr, "Malloc of out_buff failed.\n");
480 fprintf(stderr, "Error: %s\n", strerror(errno));
481 free(in_buff);
482 exit(1);
483 }
484 }
485 else {
486 fprintf(stderr, "Malloc of in_buff failed.\n");
487 fprintf(stderr, "Error: %s\n", strerror(errno));
488 exit(1);
489 }
490
491 return out_buff;
492 }
493
494 /*
495 Function name: hrd_inflate_str
496 args: pbf Pointer to pushback handle for file.
497 csize Pointer to compressed size of embedded file.
498 usize Pointer to uncompressed size of embedded file.
499 purpose: Read and decompress an embedded file into a string. Set csize and usize
500 accordingly. This function does the reading for us in the case there is not size
501 information in the header for the embedded file.
502 returns: Byte array of the contents of the embedded file.
503 */
504
hrd_inflate_str(pb_file * pbf,ub4 * csize,ub4 * usize)505 static Bytef *hrd_inflate_str(pb_file *pbf, ub4 *csize, ub4 *usize) {
506 Bytef *out_buff;
507 Bytef *tmp;
508 Bytef in_buff[RDSZ];
509 unsigned int rdamt;
510 int i;
511 int zret;
512
513 i = 1;
514 out_buff = NULL;
515 zret = Z_OK;
516 while(zret != Z_STREAM_END && (rdamt = pb_read(pbf, in_buff, RDSZ)))
517 {
518 zs.avail_in = rdamt;
519 zs.avail_out = 0;
520 zs.next_in = in_buff;
521 do {
522 if((tmp = (Bytef *) realloc(out_buff, (RDSZ * i) + 1))) {
523 out_buff = tmp;
524 zs.next_out = &(out_buff[(RDSZ * (i - 1)) - zs.avail_out]);
525 zs.avail_out += RDSZ;
526 i++;
527 }
528 else {
529 fprintf(stderr, "Realloc of out_buff failed.\n");
530 fprintf(stderr, "Error: %s\n", strerror(errno));
531 exit(1);
532 }
533 } while((zret = inflate(&zs, 0)) == Z_OK);
534 report_str_error(zret);
535 }
536 pb_push(pbf, zs.next_in, zs.avail_in);
537
538 out_buff[(RDSZ * (i - 1)) - zs.avail_out] = '\0';
539 *usize = zs.total_out;
540 *csize = zs.total_in;
541
542 inflateReset(&zs);
543
544 return out_buff;
545 }
546
547 /*
548 Function name: inflate_string
549 args: pbf Pointer to pushback handle for file.
550 csize Pointer to compressed size of embedded file. May be 0 if not set.
551 usize Pointer to uncompressed size of embedded file. May be 0 if not set.
552 purpose: Decide the easiest (in computer terms) methos of decompressing this embedded
553 file to a string.
554 returns: Pointer to a string containing the decompressed contents of the embedded file.
555 If csize and usize are not set set them to correct numbers.
556 */
557
inflate_string(pb_file * pbf,ub4 * csize,ub4 * usize)558 Bytef *inflate_string(pb_file *pbf, ub4 *csize, ub4 *usize) {
559 Bytef *ret_buf;
560
561 if(*csize && *usize) ret_buf = ez_inflate_str(pbf, *csize, *usize);
562 else ret_buf = hrd_inflate_str(pbf, csize, usize);
563
564 return ret_buf;
565 }
566