PR c/529
[official-gcc.git] / fastjar / compress.c
blob43d0884dc4061a6ae5a38390f857f59a9f514a9d
1 /* $Id: compress.c,v 1.2 2000/12/14 18:45:35 ghazi Exp $
3 $Log: compress.c,v $
4 Revision 1.2 2000/12/14 18:45:35 ghazi
5 Warning fixes:
7 * compress.c: Include stdlib.h and compress.h.
8 (rcsid): Delete.
9 (report_str_error): Make static.
10 (ez_inflate_str): Delete unused variable. Add parens in if-stmt.
11 (hrd_inflate_str): Likewise.
13 * compress.h (init_compression, end_compression, init_inflation,
14 end_inflation): Prototype void arguments.
16 * dostime.c (rcsid): Delete.
18 * jargrep.c: Include ctype.h, stdlib.h, zlib.h and compress.h.
19 Make functions static. Cast ctype function argument to `unsigned
20 char'. Add parens in if-stmts. Constify.
21 (Usage): Change into a macro.
22 (jargrep): Remove unused parameter.
24 * jartool.c: Constify. Add parens in if-stmts. Align
25 signed/unsigned char pointers in functions calls using casts.
26 (rcsid): Delete.
27 (list_jar): Fix printf format specifier.
28 (usage): Chop long string into bits. Reformat.
30 * pushback.c (rcsid): Delete.
32 Revision 1.1 2000/12/09 03:08:23 apbianco
33 2000-12-08 Alexandre Petit-Bianco <apbianco@cygnus.com>
35 * fastjar: Imported.
37 Revision 1.7 2000/09/13 14:02:02 cory
38 Reformatted some of the code to more closly match the layout of the orriginal
39 fastjar utility.
41 Revision 1.6 2000/09/12 22:29:36 cory
42 Jargrep now seems to do what I want it to do. Performs properly on Linux x86,
43 will test some other platforms later.
45 Revision 1.1.1.1 1999/12/06 03:09:16 toast
46 initial checkin..
50 Revision 1.7 1999/05/10 08:50:05 burnsbr
51 *** empty log message ***
53 Revision 1.6 1999/05/10 08:38:44 burnsbr
54 *** empty log message ***
56 Revision 1.5 1999/05/10 08:30:29 burnsbr
57 added inflation code
59 Revision 1.4 1999/04/27 10:03:33 burnsbr
60 added configure support
62 Revision 1.3 1999/04/26 02:35:32 burnsbr
63 compression now works.. yahoo
65 Revision 1.2 1999/04/23 12:01:59 burnsbr
66 added licence stuff.
68 Revision 1.1 1999/04/23 11:58:25 burnsbr
69 Initial revision
75 compress.c - code for handling deflation
76 Copyright (C) 1999 Bryan Burns
77 Copyright (C) 2004 Free Software Foundation, Inc.
79 This program is free software; you can redistribute it and/or
80 modify it under the terms of the GNU General Public License
81 as published by the Free Software Foundation; either version 2
82 of the License, or (at your option) any later version.
84 This program is distributed in the hope that it will be useful,
85 but WITHOUT ANY WARRANTY; without even the implied warranty of
86 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
87 GNU General Public License for more details.
89 You should have received a copy of the GNU General Public License
90 along with this program; if not, write to the Free Software
91 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
94 #include "config.h"
96 #include <zlib.h>
97 #include <string.h>
98 #include <stdio.h>
99 #include <errno.h>
101 #ifdef HAVE_UNISTD_H
102 #include <unistd.h>
103 #endif
104 #ifdef STDC_HEADERS
105 #include <stdlib.h>
106 #endif
108 #include <sys/types.h>
110 #include "jartool.h"
111 #include "pushback.h"
112 #include "compress.h"
113 #include "shift.h"
115 int write_data (int, void *, size_t, struct zipentry *);
117 extern int seekable;
118 extern off_t end_of_entries;
120 static z_stream zs;
122 void init_compression(){
124 memset(&zs, 0, sizeof(z_stream));
126 zs.zalloc = Z_NULL;
127 zs.zfree = Z_NULL;
128 zs.opaque = Z_NULL;
130 /* Why -MAX_WBITS? zlib has an undocumented feature, where if the windowbits
131 parameter is negative, it omits the zlib header, which seems to kill
132 any other zip/unzip program. This caused me SO much pain.. */
133 if(deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS,
134 9, Z_DEFAULT_STRATEGY) != Z_OK){
136 fprintf(stderr, "Error initializing deflation!\n");
137 exit(1);
142 write_data (int fd, void *buf, size_t len, struct zipentry *ze)
144 #ifdef WITH_SHIFT_DOWN
145 struct zipentry *next = NULL;
146 off_t here = lseek (fd, 0, SEEK_CUR);
148 * If we are updating and there is not enough space before the next
149 * entry, expand the file.
151 if (ze)
153 next = ze->next_entry;
154 if (next && here + len >= next->offset)
156 if (shift_down (fd, next->offset, (here + len) - next->offset, next))
158 perror ("can't expand file");
159 exit (1);
163 #endif /* WITH_SHIFT_DOWN */
165 return write (fd, buf, len);
168 int compress_file(int in_fd, int out_fd, struct zipentry *ze,
169 struct zipentry *existing)
171 Bytef in_buff[RDSZ];
172 Bytef out_buff[RDSZ];
173 unsigned int rdamt, wramt;
174 unsigned long tr = 0;
175 int rtval;
177 rdamt = 0;
179 zs.avail_in = 0;
180 zs.next_in = in_buff;
182 zs.next_out = out_buff;
183 zs.avail_out = (uInt)RDSZ;
185 ze->crc = crc32(0L, Z_NULL, 0);
187 for(; ;){
189 /* If deflate is out of input, fill the input buffer for it */
190 if(zs.avail_in == 0 && zs.avail_out > 0){
191 if((rtval = read(in_fd, in_buff, RDSZ)) == 0)
192 break;
194 if(rtval == -1){
195 perror("read");
196 exit(1);
199 rdamt = rtval;
201 /* compute the CRC while we're at it */
202 ze->crc = crc32(ze->crc, in_buff, rdamt);
204 /* update the total amount read sofar */
205 tr += rdamt;
207 zs.next_in = in_buff;
208 zs.avail_in = rdamt;
211 /* deflate the data */
212 if(deflate(&zs, 0) != Z_OK){
213 fprintf(stderr, "Error deflating! %s:%d\n", __FILE__, __LINE__);
214 exit(1);
217 /* If the output buffer is full, dump it to disk */
218 if(zs.avail_out == 0){
220 if (write_data (out_fd, out_buff, RDSZ, existing) != RDSZ)
222 perror("write");
223 exit(1);
226 /* clear the output buffer */
227 zs.next_out = out_buff;
228 zs.avail_out = (uInt)RDSZ;
233 /* If we have any data waiting in the buffer after we're done with the file
234 we can flush it */
235 if(zs.avail_out < RDSZ){
237 wramt = RDSZ - zs.avail_out;
239 if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
241 perror("write");
242 exit(1);
244 /* clear the output buffer */
245 zs.next_out = out_buff;
246 zs.avail_out = (uInt)RDSZ;
250 /* finish deflation. This purges zlib's internal data buffers */
251 while(deflate(&zs, Z_FINISH) == Z_OK){
252 wramt = RDSZ - zs.avail_out;
254 if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
256 perror("write");
257 exit(1);
260 zs.next_out = out_buff;
261 zs.avail_out = (uInt)RDSZ;
264 /* If there's any data left in the buffer, write it out */
265 if(zs.avail_out != RDSZ){
266 wramt = RDSZ - zs.avail_out;
268 if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
270 perror("write");
271 exit(1);
275 /* update fastjar's entry information */
276 ze->usize = (ub4)zs.total_in;
277 ze->csize = (ub4)zs.total_out;
279 /* Reset the deflation for the next time around */
280 if(deflateReset(&zs) != Z_OK){
281 fprintf(stderr, "Error resetting deflation\n");
282 exit(1);
285 return 0;
288 void end_compression(){
289 int rtval;
291 /* Oddly enough, zlib always returns Z_DATA_ERROR if you specify no
292 zlib header. Go fig. */
293 if((rtval = deflateEnd(&zs)) != Z_OK && rtval != Z_DATA_ERROR){
294 fprintf(stderr, "Error calling deflateEnd\n");
295 fprintf(stderr, "error: (%d) %s\n", rtval, zs.msg);
296 exit(1);
301 void init_inflation(){
303 memset(&zs, 0, sizeof(z_stream));
305 zs.zalloc = Z_NULL;
306 zs.zfree = Z_NULL;
307 zs.opaque = Z_NULL;
309 if(inflateInit2(&zs, -15) != Z_OK){
310 fprintf(stderr, "Error initializing deflation!\n");
311 exit(1);
316 int inflate_file(pb_file *pbf, int out_fd, struct zipentry *ze){
317 Bytef in_buff[RDSZ];
318 Bytef out_buff[RDSZ];
319 unsigned int rdamt;
320 int rtval;
321 ub4 crc = 0;
323 zs.avail_in = 0;
325 crc = crc32(crc, NULL, 0); /* initialize crc */
327 /* loop until we've consumed all the compressed data */
328 for(;;){
330 if(zs.avail_in == 0){
331 if((rdamt = pb_read(pbf, in_buff, RDSZ)) == 0)
332 break;
333 else if((int)rdamt < 0){
334 perror("read");
335 exit(1);
338 #ifdef DEBUG
339 printf("%d bytes read\n", rdamt);
340 #endif
342 zs.next_in = in_buff;
343 zs.avail_in = rdamt;
346 zs.next_out = out_buff;
347 zs.avail_out = RDSZ;
349 if((rtval = inflate(&zs, 0)) != Z_OK){
350 if(rtval == Z_STREAM_END){
351 #ifdef DEBUG
352 printf("end of stream\n");
353 #endif
354 if(zs.avail_out != RDSZ){
355 crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
357 if(out_fd >= 0)
358 if(write(out_fd, out_buff, (RDSZ - zs.avail_out)) !=
359 (int)(RDSZ - zs.avail_out)){
360 perror("write");
361 exit(1);
365 break;
366 } else {
367 fprintf(stderr, "Error inflating file! (%d)\n", rtval);
368 exit(1);
370 } else {
371 if(zs.avail_out != RDSZ){
372 crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
374 if(out_fd >= 0)
375 if(write(out_fd, out_buff, (RDSZ - zs.avail_out)) !=
376 (int)(RDSZ - zs.avail_out)){
377 perror("write");
378 exit(1);
380 zs.next_out = out_buff;
381 zs.avail_out = RDSZ;
385 #ifdef DEBUG
386 printf("done inflating\n");
387 #endif
389 #ifdef DEBUG
390 printf("%d bytes left over\n", zs.avail_in);
391 #endif
393 #ifdef DEBUG
394 printf("CRC is %x\n", crc);
395 #endif
397 ze->crc = crc;
399 pb_push(pbf, zs.next_in, zs.avail_in);
401 ze->usize = zs.total_out;
403 inflateReset(&zs);
404 return 0;
408 Function name: report_str_error
409 args: val Error code returned from zlib.
410 purpose: Put out an error message corresponding to error code returned from zlib.
411 Be suitably cryptic seeing I don't really know exactly what these errors mean.
414 static void report_str_error(int val) {
415 switch(val) {
416 case Z_STREAM_END:
417 break;
418 case Z_NEED_DICT:
419 fprintf(stderr, "Need a dictionary?\n");
420 exit(1);
421 case Z_DATA_ERROR:
422 fprintf(stderr, "Z_DATA_ERROR\n");
423 exit(1);
424 case Z_STREAM_ERROR:
425 fprintf(stderr, "Z_STREAM_ERROR\n");
426 exit(1);
427 case Z_MEM_ERROR:
428 fprintf(stderr, "Z_MEM_ERROR\n");
429 exit(1);
430 case Z_BUF_ERROR:
431 fprintf(stderr, "Z_BUF_ERROR\n");
432 exit(1);
433 case Z_OK:
434 break;
435 default:
436 fprintf(stderr, "Unknown behavior from inflate\n");
437 exit(1);
442 Function name: ez_inflate_str
443 args: pbf Pointer to pushback handle for file.
444 csize Compressed size of embedded file.
445 usize Uncompressed size of embedded file.
446 purpose: Read in and decompress the contents of an embedded file and store it in a
447 byte array.
448 returns: Byte array of uncompressed embedded file.
451 static Bytef *ez_inflate_str(pb_file *pbf, ub4 csize, ub4 usize) {
452 Bytef *out_buff;
453 Bytef *in_buff;
454 unsigned int rdamt;
456 if((zs.next_in = in_buff = (Bytef *) malloc(csize))) {
457 if((zs.next_out = out_buff = (Bytef *) malloc(usize + 1))) {
458 if((rdamt = pb_read(pbf, zs.next_in, csize)) == csize) {
459 zs.avail_in = csize;
460 zs.avail_out = usize;
461 report_str_error(inflate(&zs, 0));
462 free(in_buff);
463 inflateReset(&zs);
464 out_buff[usize] = '\0';
466 else {
467 fprintf(stderr, "Read failed on input file.\n");
468 fprintf(stderr, "Tried to read %u but read %u instead.\n", csize, rdamt);
469 free(in_buff);
470 free(out_buff);
471 exit(1);
474 else {
475 fprintf(stderr, "Malloc of out_buff failed.\n");
476 fprintf(stderr, "Error: %s\n", strerror(errno));
477 free(in_buff);
478 exit(1);
481 else {
482 fprintf(stderr, "Malloc of in_buff failed.\n");
483 fprintf(stderr, "Error: %s\n", strerror(errno));
484 exit(1);
487 return out_buff;
491 Function name: hrd_inflate_str
492 args: pbf Pointer to pushback handle for file.
493 csize Pointer to compressed size of embedded file.
494 usize Pointer to uncompressed size of embedded file.
495 purpose: Read and decompress an embedded file into a string. Set csize and usize
496 accordingly. This function does the reading for us in the case there is not size
497 information in the header for the embedded file.
498 returns: Byte array of the contents of the embedded file.
501 static Bytef *hrd_inflate_str(pb_file *pbf, ub4 *csize, ub4 *usize) {
502 Bytef *out_buff;
503 Bytef *tmp;
504 Bytef in_buff[RDSZ];
505 unsigned int rdamt;
506 int i;
507 int zret;
509 i = 1;
510 out_buff = NULL;
511 zret = Z_OK;
512 while(zret != Z_STREAM_END && (rdamt = pb_read(pbf, in_buff, RDSZ)))
514 zs.avail_in = rdamt;
515 zs.avail_out = 0;
516 zs.next_in = in_buff;
517 do {
518 if((tmp = (Bytef *) realloc(out_buff, (RDSZ * i) + 1))) {
519 out_buff = tmp;
520 zs.next_out = &(out_buff[(RDSZ * (i - 1)) - zs.avail_out]);
521 zs.avail_out += RDSZ;
522 i++;
524 else {
525 fprintf(stderr, "Realloc of out_buff failed.\n");
526 fprintf(stderr, "Error: %s\n", strerror(errno));
527 exit(1);
529 } while((zret = inflate(&zs, 0)) == Z_OK);
530 report_str_error(zret);
532 pb_push(pbf, zs.next_in, zs.avail_in);
534 out_buff[(RDSZ * (i - 1)) - zs.avail_out] = '\0';
535 *usize = zs.total_out;
536 *csize = zs.total_in;
538 inflateReset(&zs);
540 return out_buff;
544 Function name: inflate_string
545 args: pbf Pointer to pushback handle for file.
546 csize Pointer to compressed size of embedded file. May be 0 if not set.
547 usize Pointer to uncompressed size of embedded file. May be 0 if not set.
548 purpose: Decide the easiest (in computer terms) methos of decompressing this embedded
549 file to a string.
550 returns: Pointer to a string containing the decompressed contents of the embedded file.
551 If csize and usize are not set set them to correct numbers.
554 Bytef *inflate_string(pb_file *pbf, ub4 *csize, ub4 *usize) {
555 Bytef *ret_buf;
557 if(*csize && *usize) ret_buf = ez_inflate_str(pbf, *csize, *usize);
558 else ret_buf = hrd_inflate_str(pbf, csize, usize);
560 return ret_buf;