Patch from Bernard Giroud.
[official-gcc.git] / fastjar / compress.c
blobfa7bc2ed3f1a80c6ebe754c18601dfefacebcdee
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
78 This program is free software; you can redistribute it and/or
79 modify it under the terms of the GNU General Public License
80 as published by the Free Software Foundation; either version 2
81 of the License, or (at your option) any later version.
83 This program is distributed in the hope that it will be useful,
84 but WITHOUT ANY WARRANTY; without even the implied warranty of
85 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
86 GNU General Public License for more details.
88 You should have received a copy of the GNU General Public License
89 along with this program; if not, write to the Free Software
90 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
93 #include "config.h"
95 #include <zlib.h>
96 #include <string.h>
97 #include <stdio.h>
98 #include <errno.h>
100 #ifdef HAVE_UNISTD_H
101 #include <unistd.h>
102 #endif
103 #ifdef STDC_HEADERS
104 #include <stdlib.h>
105 #endif
107 #include <sys/types.h>
109 #include "jartool.h"
110 #include "pushback.h"
111 #include "compress.h"
113 extern int seekable;
115 static z_stream zs;
117 void init_compression(){
119 memset(&zs, 0, sizeof(z_stream));
121 zs.zalloc = Z_NULL;
122 zs.zfree = Z_NULL;
123 zs.opaque = Z_NULL;
125 /* Why -MAX_WBITS? zlib has an undocumented feature, where if the windowbits
126 parameter is negative, it omits the zlib header, which seems to kill
127 any other zip/unzip program. This caused me SO much pain.. */
128 if(deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS,
129 9, Z_DEFAULT_STRATEGY) != Z_OK){
131 fprintf(stderr, "Error initializing deflation!\n");
132 exit(1);
136 int compress_file(int in_fd, int out_fd, struct zipentry *ze){
137 Bytef in_buff[RDSZ];
138 Bytef out_buff[RDSZ];
139 unsigned int rdamt, wramt;
140 unsigned long tr = 0;
141 int rtval;
143 rdamt = 0;
145 zs.avail_in = 0;
146 zs.next_in = in_buff;
148 zs.next_out = out_buff;
149 zs.avail_out = (uInt)RDSZ;
151 ze->crc = crc32(0L, Z_NULL, 0);
153 for(; ;){
155 /* If deflate is out of input, fill the input buffer for it */
156 if(zs.avail_in == 0 && zs.avail_out > 0){
157 if((rtval = read(in_fd, in_buff, RDSZ)) == 0)
158 break;
160 if(rtval == -1){
161 perror("read");
162 exit(1);
165 rdamt = rtval;
167 /* compute the CRC while we're at it */
168 ze->crc = crc32(ze->crc, in_buff, rdamt);
170 /* update the total amount read sofar */
171 tr += rdamt;
173 zs.next_in = in_buff;
174 zs.avail_in = rdamt;
177 /* deflate the data */
178 if(deflate(&zs, 0) != Z_OK){
179 fprintf(stderr, "Error deflating! %s:%d\n", __FILE__, __LINE__);
180 exit(1);
183 /* If the output buffer is full, dump it to disk */
184 if(zs.avail_out == 0){
186 if(write(out_fd, out_buff, RDSZ) != RDSZ){
187 perror("write");
188 exit(1);
191 /* clear the output buffer */
192 zs.next_out = out_buff;
193 zs.avail_out = (uInt)RDSZ;
198 /* If we have any data waiting in the buffer after we're done with the file
199 we can flush it */
200 if(zs.avail_out < RDSZ){
202 wramt = RDSZ - zs.avail_out;
204 if(write(out_fd, out_buff, wramt) != (int)wramt){
205 perror("write");
206 exit(1);
208 /* clear the output buffer */
209 zs.next_out = out_buff;
210 zs.avail_out = (uInt)RDSZ;
214 /* finish deflation. This purges zlib's internal data buffers */
215 while(deflate(&zs, Z_FINISH) == Z_OK){
216 wramt = RDSZ - zs.avail_out;
218 if(write(out_fd, out_buff, wramt) != (int)wramt){
219 perror("write");
220 exit(1);
223 zs.next_out = out_buff;
224 zs.avail_out = (uInt)RDSZ;
227 /* If there's any data left in the buffer, write it out */
228 if(zs.avail_out != RDSZ){
229 wramt = RDSZ - zs.avail_out;
231 if(write(out_fd, out_buff, wramt) != (int)wramt){
232 perror("write");
233 exit(1);
237 /* update fastjar's entry information */
238 ze->usize = (ub4)zs.total_in;
239 ze->csize = (ub4)zs.total_out;
241 /* Reset the deflation for the next time around */
242 if(deflateReset(&zs) != Z_OK){
243 fprintf(stderr, "Error resetting deflation\n");
244 exit(1);
247 return 0;
250 void end_compression(){
251 int rtval;
253 /* Oddly enough, zlib always returns Z_DATA_ERROR if you specify no
254 zlib header. Go fig. */
255 if((rtval = deflateEnd(&zs)) != Z_OK && rtval != Z_DATA_ERROR){
256 fprintf(stderr, "Error calling deflateEnd\n");
257 fprintf(stderr, "error: (%d) %s\n", rtval, zs.msg);
258 exit(1);
263 void init_inflation(){
265 memset(&zs, 0, sizeof(z_stream));
267 zs.zalloc = Z_NULL;
268 zs.zfree = Z_NULL;
269 zs.opaque = Z_NULL;
271 if(inflateInit2(&zs, -15) != Z_OK){
272 fprintf(stderr, "Error initializing deflation!\n");
273 exit(1);
278 int inflate_file(pb_file *pbf, int out_fd, struct zipentry *ze){
279 Bytef in_buff[RDSZ];
280 Bytef out_buff[RDSZ];
281 unsigned int rdamt;
282 int rtval;
283 ub4 crc = 0;
285 zs.avail_in = 0;
287 crc = crc32(crc, NULL, 0); /* initialize crc */
289 /* loop until we've consumed all the compressed data */
290 for(;;){
292 if(zs.avail_in == 0){
293 if((rdamt = pb_read(pbf, in_buff, RDSZ)) == 0)
294 break;
295 else if((int)rdamt < 0){
296 perror("read");
297 exit(1);
300 #ifdef DEBUG
301 printf("%d bytes read\n", rdamt);
302 #endif
304 zs.next_in = in_buff;
305 zs.avail_in = rdamt;
308 zs.next_out = out_buff;
309 zs.avail_out = RDSZ;
311 if((rtval = inflate(&zs, 0)) != Z_OK){
312 if(rtval == Z_STREAM_END){
313 #ifdef DEBUG
314 printf("end of stream\n");
315 #endif
316 if(zs.avail_out != RDSZ){
317 crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
319 if(out_fd >= 0)
320 if(write(out_fd, out_buff, (RDSZ - zs.avail_out)) !=
321 (int)(RDSZ - zs.avail_out)){
322 perror("write");
323 exit(1);
327 break;
328 } else {
329 fprintf(stderr, "Error inflating file! (%d)\n", rtval);
330 exit(1);
332 } else {
333 if(zs.avail_out != RDSZ){
334 crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
336 if(out_fd >= 0)
337 if(write(out_fd, out_buff, (RDSZ - zs.avail_out)) !=
338 (int)(RDSZ - zs.avail_out)){
339 perror("write");
340 exit(1);
342 zs.next_out = out_buff;
343 zs.avail_out = RDSZ;
347 #ifdef DEBUG
348 printf("done inflating\n");
349 #endif
351 #ifdef DEBUG
352 printf("%d bytes left over\n", zs.avail_in);
353 #endif
355 #ifdef DEBUG
356 printf("CRC is %x\n", crc);
357 #endif
359 ze->crc = crc;
361 pb_push(pbf, zs.next_in, zs.avail_in);
363 ze->usize = zs.total_out;
365 inflateReset(&zs);
366 return 0;
370 Function name: report_str_error
371 args: val Error code returned from zlib.
372 purpose: Put out an error message corresponding to error code returned from zlib.
373 Be suitably cryptic seeing I don't really know exactly what these errors mean.
376 static void report_str_error(int val) {
377 switch(val) {
378 case Z_STREAM_END:
379 break;
380 case Z_NEED_DICT:
381 fprintf(stderr, "Need a dictionary?\n");
382 exit(1);
383 case Z_DATA_ERROR:
384 fprintf(stderr, "Z_DATA_ERROR\n");
385 exit(1);
386 case Z_STREAM_ERROR:
387 fprintf(stderr, "Z_STREAM_ERROR\n");
388 exit(1);
389 case Z_MEM_ERROR:
390 fprintf(stderr, "Z_MEM_ERROR\n");
391 exit(1);
392 case Z_BUF_ERROR:
393 fprintf(stderr, "Z_BUF_ERROR\n");
394 exit(1);
395 case Z_OK:
396 break;
397 default:
398 fprintf(stderr, "Unknown behavior from inflate\n");
399 exit(1);
404 Function name: ez_inflate_str
405 args: pbf Pointer to pushback handle for file.
406 csize Compressed size of embedded file.
407 usize Uncompressed size of embedded file.
408 purpose: Read in and decompress the contents of an embedded file and store it in a
409 byte array.
410 returns: Byte array of uncompressed embedded file.
413 static Bytef *ez_inflate_str(pb_file *pbf, ub4 csize, ub4 usize) {
414 Bytef *out_buff;
415 Bytef *in_buff;
416 unsigned int rdamt;
418 if((zs.next_in = in_buff = (Bytef *) malloc(csize))) {
419 if((zs.next_out = out_buff = (Bytef *) malloc(usize + 1))) {
420 if((rdamt = pb_read(pbf, zs.next_in, csize)) == csize) {
421 zs.avail_in = csize;
422 zs.avail_out = usize;
423 report_str_error(inflate(&zs, 0));
424 free(in_buff);
425 inflateReset(&zs);
426 out_buff[usize] = '\0';
428 else {
429 fprintf(stderr, "Read failed on input file.\n");
430 fprintf(stderr, "Tried to read %u but read %u instead.\n", csize, rdamt);
431 free(in_buff);
432 free(out_buff);
433 exit(1);
436 else {
437 fprintf(stderr, "Malloc of out_buff failed.\n");
438 fprintf(stderr, "Error: %s\n", strerror(errno));
439 free(in_buff);
440 exit(1);
443 else {
444 fprintf(stderr, "Malloc of in_buff failed.\n");
445 fprintf(stderr, "Error: %s\n", strerror(errno));
446 exit(1);
449 return out_buff;
453 Function name: hrd_inflate_str
454 args: pbf Pointer to pushback handle for file.
455 csize Pointer to compressed size of embedded file.
456 usize Pointer to uncompressed size of embedded file.
457 purpose: Read and decompress an embedded file into a string. Set csize and usize
458 accordingly. This function does the reading for us in the case there is not size
459 information in the header for the embedded file.
460 returns: Byte array of the contents of the embedded file.
463 static Bytef *hrd_inflate_str(pb_file *pbf, ub4 *csize, ub4 *usize) {
464 Bytef *out_buff;
465 Bytef *tmp;
466 Bytef in_buff[RDSZ];
467 unsigned int rdamt;
468 int i;
469 int zret;
471 i = 1;
472 out_buff = NULL;
473 zret = Z_OK;
474 while(zret != Z_STREAM_END && (rdamt = pb_read(pbf, in_buff, RDSZ)))
476 zs.avail_in = rdamt;
477 zs.avail_out = 0;
478 zs.next_in = in_buff;
479 do {
480 if((tmp = (Bytef *) realloc(out_buff, (RDSZ * i) + 1))) {
481 out_buff = tmp;
482 zs.next_out = &(out_buff[(RDSZ * (i - 1)) - zs.avail_out]);
483 zs.avail_out += RDSZ;
484 i++;
486 else {
487 fprintf(stderr, "Realloc of out_buff failed.\n");
488 fprintf(stderr, "Error: %s\n", strerror(errno));
489 exit(1);
491 } while((zret = inflate(&zs, 0)) == Z_OK);
492 report_str_error(zret);
494 pb_push(pbf, zs.next_in, zs.avail_in);
496 out_buff[(RDSZ * (i - 1)) - zs.avail_out] = '\0';
497 *usize = zs.total_out;
498 *csize = zs.total_in;
500 inflateReset(&zs);
502 return out_buff;
506 Function name: inflate_string
507 args: pbf Pointer to pushback handle for file.
508 csize Pointer to compressed size of embedded file. May be 0 if not set.
509 usize Pointer to uncompressed size of embedded file. May be 0 if not set.
510 purpose: Decide the easiest (in computer terms) methos of decompressing this embedded
511 file to a string.
512 returns: Pointer to a string containing the decompressed contents of the embedded file.
513 If csize and usize are not set set them to correct numbers.
516 Bytef *inflate_string(pb_file *pbf, ub4 *csize, ub4 *usize) {
517 Bytef *ret_buf;
519 if(*csize && *usize) ret_buf = ez_inflate_str(pbf, *csize, *usize);
520 else ret_buf = hrd_inflate_str(pbf, csize, usize);
522 return ret_buf;