PR target/592
[official-gcc.git] / fastjar / compress.c
blob84b3dad17686a24fc9876d81dc74b3f45f117cea
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,
143 struct zipentry *ze __attribute__((unused)))
145 #ifdef WITH_SHIFT_DOWN
146 struct zipentry *next = NULL;
147 off_t here = lseek (fd, 0, SEEK_CUR);
149 * If we are updating and there is not enough space before the next
150 * entry, expand the file.
152 if (ze)
154 next = ze->next_entry;
155 if (next && here + len >= next->offset)
157 if (shift_down (fd, next->offset, (here + len) - next->offset, next))
159 perror ("can't expand file");
160 exit (1);
164 #endif /* WITH_SHIFT_DOWN */
166 return write (fd, buf, len);
169 int compress_file(int in_fd, int out_fd, struct zipentry *ze,
170 struct zipentry *existing)
172 Bytef in_buff[RDSZ];
173 Bytef out_buff[RDSZ];
174 unsigned int rdamt, wramt;
175 unsigned long tr = 0;
176 int rtval;
178 rdamt = 0;
180 zs.avail_in = 0;
181 zs.next_in = in_buff;
183 zs.next_out = out_buff;
184 zs.avail_out = (uInt)RDSZ;
186 ze->crc = crc32(0L, Z_NULL, 0);
188 for(; ;){
190 /* If deflate is out of input, fill the input buffer for it */
191 if(zs.avail_in == 0 && zs.avail_out > 0){
192 if((rtval = read(in_fd, in_buff, RDSZ)) == 0)
193 break;
195 if(rtval == -1){
196 perror("read");
197 exit(1);
200 rdamt = rtval;
202 /* compute the CRC while we're at it */
203 ze->crc = crc32(ze->crc, in_buff, rdamt);
205 /* update the total amount read sofar */
206 tr += rdamt;
208 zs.next_in = in_buff;
209 zs.avail_in = rdamt;
212 /* deflate the data */
213 if(deflate(&zs, 0) != Z_OK){
214 fprintf(stderr, "Error deflating! %s:%d\n", __FILE__, __LINE__);
215 exit(1);
218 /* If the output buffer is full, dump it to disk */
219 if(zs.avail_out == 0){
221 if (write_data (out_fd, out_buff, RDSZ, existing) != RDSZ)
223 perror("write");
224 exit(1);
227 /* clear the output buffer */
228 zs.next_out = out_buff;
229 zs.avail_out = (uInt)RDSZ;
234 /* If we have any data waiting in the buffer after we're done with the file
235 we can flush it */
236 if(zs.avail_out < RDSZ){
238 wramt = RDSZ - zs.avail_out;
240 if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
242 perror("write");
243 exit(1);
245 /* clear the output buffer */
246 zs.next_out = out_buff;
247 zs.avail_out = (uInt)RDSZ;
251 /* finish deflation. This purges zlib's internal data buffers */
252 while(deflate(&zs, Z_FINISH) == Z_OK){
253 wramt = RDSZ - zs.avail_out;
255 if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
257 perror("write");
258 exit(1);
261 zs.next_out = out_buff;
262 zs.avail_out = (uInt)RDSZ;
265 /* If there's any data left in the buffer, write it out */
266 if(zs.avail_out != RDSZ){
267 wramt = RDSZ - zs.avail_out;
269 if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
271 perror("write");
272 exit(1);
276 /* update fastjar's entry information */
277 ze->usize = (ub4)zs.total_in;
278 ze->csize = (ub4)zs.total_out;
280 /* Reset the deflation for the next time around */
281 if(deflateReset(&zs) != Z_OK){
282 fprintf(stderr, "Error resetting deflation\n");
283 exit(1);
286 return 0;
289 void end_compression(){
290 int rtval;
292 /* Oddly enough, zlib always returns Z_DATA_ERROR if you specify no
293 zlib header. Go fig. */
294 if((rtval = deflateEnd(&zs)) != Z_OK && rtval != Z_DATA_ERROR){
295 fprintf(stderr, "Error calling deflateEnd\n");
296 fprintf(stderr, "error: (%d) %s\n", rtval, zs.msg);
297 exit(1);
302 void init_inflation(){
304 memset(&zs, 0, sizeof(z_stream));
306 zs.zalloc = Z_NULL;
307 zs.zfree = Z_NULL;
308 zs.opaque = Z_NULL;
310 if(inflateInit2(&zs, -15) != Z_OK){
311 fprintf(stderr, "Error initializing deflation!\n");
312 exit(1);
317 int inflate_file(pb_file *pbf, int out_fd, struct zipentry *ze){
318 Bytef in_buff[RDSZ];
319 Bytef out_buff[RDSZ];
320 unsigned int rdamt;
321 int rtval;
322 ub4 crc = 0;
324 zs.avail_in = 0;
326 crc = crc32(crc, NULL, 0); /* initialize crc */
328 /* loop until we've consumed all the compressed data */
329 for(;;){
331 if(zs.avail_in == 0){
332 if((rdamt = pb_read(pbf, in_buff, RDSZ)) == 0)
333 break;
334 else if((int)rdamt < 0){
335 perror("read");
336 exit(1);
339 #ifdef DEBUG
340 printf("%d bytes read\n", rdamt);
341 #endif
343 zs.next_in = in_buff;
344 zs.avail_in = rdamt;
347 zs.next_out = out_buff;
348 zs.avail_out = RDSZ;
350 if((rtval = inflate(&zs, 0)) != Z_OK){
351 if(rtval == Z_STREAM_END){
352 #ifdef DEBUG
353 printf("end of stream\n");
354 #endif
355 if(zs.avail_out != RDSZ){
356 crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
358 if(out_fd >= 0)
359 if(write(out_fd, out_buff, (RDSZ - zs.avail_out)) !=
360 (int)(RDSZ - zs.avail_out)){
361 perror("write");
362 exit(1);
366 break;
367 } else {
368 fprintf(stderr, "Error inflating file! (%d)\n", rtval);
369 exit(1);
371 } else {
372 if(zs.avail_out != RDSZ){
373 crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
375 if(out_fd >= 0)
376 if(write(out_fd, out_buff, (RDSZ - zs.avail_out)) !=
377 (int)(RDSZ - zs.avail_out)){
378 perror("write");
379 exit(1);
381 zs.next_out = out_buff;
382 zs.avail_out = RDSZ;
386 #ifdef DEBUG
387 printf("done inflating\n");
388 #endif
390 #ifdef DEBUG
391 printf("%d bytes left over\n", zs.avail_in);
392 #endif
394 #ifdef DEBUG
395 printf("CRC is %x\n", crc);
396 #endif
398 ze->crc = crc;
400 pb_push(pbf, zs.next_in, zs.avail_in);
402 ze->usize = zs.total_out;
404 inflateReset(&zs);
405 return 0;
409 Function name: report_str_error
410 args: val Error code returned from zlib.
411 purpose: Put out an error message corresponding to error code returned from zlib.
412 Be suitably cryptic seeing I don't really know exactly what these errors mean.
415 static void report_str_error(int val) {
416 switch(val) {
417 case Z_STREAM_END:
418 break;
419 case Z_NEED_DICT:
420 fprintf(stderr, "Need a dictionary?\n");
421 exit(1);
422 case Z_DATA_ERROR:
423 fprintf(stderr, "Z_DATA_ERROR\n");
424 exit(1);
425 case Z_STREAM_ERROR:
426 fprintf(stderr, "Z_STREAM_ERROR\n");
427 exit(1);
428 case Z_MEM_ERROR:
429 fprintf(stderr, "Z_MEM_ERROR\n");
430 exit(1);
431 case Z_BUF_ERROR:
432 fprintf(stderr, "Z_BUF_ERROR\n");
433 exit(1);
434 case Z_OK:
435 break;
436 default:
437 fprintf(stderr, "Unknown behavior from inflate\n");
438 exit(1);
443 Function name: ez_inflate_str
444 args: pbf Pointer to pushback handle for file.
445 csize Compressed size of embedded file.
446 usize Uncompressed size of embedded file.
447 purpose: Read in and decompress the contents of an embedded file and store it in a
448 byte array.
449 returns: Byte array of uncompressed embedded file.
452 static Bytef *ez_inflate_str(pb_file *pbf, ub4 csize, ub4 usize) {
453 Bytef *out_buff;
454 Bytef *in_buff;
455 unsigned int rdamt;
457 if((zs.next_in = in_buff = (Bytef *) malloc(csize))) {
458 if((zs.next_out = out_buff = (Bytef *) malloc(usize + 1))) {
459 if((rdamt = pb_read(pbf, zs.next_in, csize)) == csize) {
460 zs.avail_in = csize;
461 zs.avail_out = usize;
462 report_str_error(inflate(&zs, 0));
463 free(in_buff);
464 inflateReset(&zs);
465 out_buff[usize] = '\0';
467 else {
468 fprintf(stderr, "Read failed on input file.\n");
469 fprintf(stderr, "Tried to read %u but read %u instead.\n", csize, rdamt);
470 free(in_buff);
471 free(out_buff);
472 exit(1);
475 else {
476 fprintf(stderr, "Malloc of out_buff failed.\n");
477 fprintf(stderr, "Error: %s\n", strerror(errno));
478 free(in_buff);
479 exit(1);
482 else {
483 fprintf(stderr, "Malloc of in_buff failed.\n");
484 fprintf(stderr, "Error: %s\n", strerror(errno));
485 exit(1);
488 return out_buff;
492 Function name: hrd_inflate_str
493 args: pbf Pointer to pushback handle for file.
494 csize Pointer to compressed size of embedded file.
495 usize Pointer to uncompressed size of embedded file.
496 purpose: Read and decompress an embedded file into a string. Set csize and usize
497 accordingly. This function does the reading for us in the case there is not size
498 information in the header for the embedded file.
499 returns: Byte array of the contents of the embedded file.
502 static Bytef *hrd_inflate_str(pb_file *pbf, ub4 *csize, ub4 *usize) {
503 Bytef *out_buff;
504 Bytef *tmp;
505 Bytef in_buff[RDSZ];
506 unsigned int rdamt;
507 int i;
508 int zret;
510 i = 1;
511 out_buff = NULL;
512 zret = Z_OK;
513 while(zret != Z_STREAM_END && (rdamt = pb_read(pbf, in_buff, RDSZ)))
515 zs.avail_in = rdamt;
516 zs.avail_out = 0;
517 zs.next_in = in_buff;
518 do {
519 if((tmp = (Bytef *) realloc(out_buff, (RDSZ * i) + 1))) {
520 out_buff = tmp;
521 zs.next_out = &(out_buff[(RDSZ * (i - 1)) - zs.avail_out]);
522 zs.avail_out += RDSZ;
523 i++;
525 else {
526 fprintf(stderr, "Realloc of out_buff failed.\n");
527 fprintf(stderr, "Error: %s\n", strerror(errno));
528 exit(1);
530 } while((zret = inflate(&zs, 0)) == Z_OK);
531 report_str_error(zret);
533 pb_push(pbf, zs.next_in, zs.avail_in);
535 out_buff[(RDSZ * (i - 1)) - zs.avail_out] = '\0';
536 *usize = zs.total_out;
537 *csize = zs.total_in;
539 inflateReset(&zs);
541 return out_buff;
545 Function name: inflate_string
546 args: pbf Pointer to pushback handle for file.
547 csize Pointer to compressed size of embedded file. May be 0 if not set.
548 usize Pointer to uncompressed size of embedded file. May be 0 if not set.
549 purpose: Decide the easiest (in computer terms) methos of decompressing this embedded
550 file to a string.
551 returns: Pointer to a string containing the decompressed contents of the embedded file.
552 If csize and usize are not set set them to correct numbers.
555 Bytef *inflate_string(pb_file *pbf, ub4 *csize, ub4 *usize) {
556 Bytef *ret_buf;
558 if(*csize && *usize) ret_buf = ez_inflate_str(pbf, *csize, *usize);
559 else ret_buf = hrd_inflate_str(pbf, csize, usize);
561 return ret_buf;