re PR bootstrap/15627 (Sun CC cannot bootstrap GCC)
[gcc.git] / fastjar / compress.c
1 /* $Id: compress.c,v 1.2 2000/12/14 18:45:35 ghazi Exp $
2
3 $Log: compress.c,v $
4 Revision 1.2 2000/12/14 18:45:35 ghazi
5 Warning fixes:
6
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.
12
13 * compress.h (init_compression, end_compression, init_inflation,
14 end_inflation): Prototype void arguments.
15
16 * dostime.c (rcsid): Delete.
17
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.
23
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.
29
30 * pushback.c (rcsid): Delete.
31
32 Revision 1.1 2000/12/09 03:08:23 apbianco
33 2000-12-08 Alexandre Petit-Bianco <apbianco@cygnus.com>
34
35 * fastjar: Imported.
36
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.
40
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.
44
45 Revision 1.1.1.1 1999/12/06 03:09:16 toast
46 initial checkin..
47
48
49
50 Revision 1.7 1999/05/10 08:50:05 burnsbr
51 *** empty log message ***
52
53 Revision 1.6 1999/05/10 08:38:44 burnsbr
54 *** empty log message ***
55
56 Revision 1.5 1999/05/10 08:30:29 burnsbr
57 added inflation code
58
59 Revision 1.4 1999/04/27 10:03:33 burnsbr
60 added configure support
61
62 Revision 1.3 1999/04/26 02:35:32 burnsbr
63 compression now works.. yahoo
64
65 Revision 1.2 1999/04/23 12:01:59 burnsbr
66 added licence stuff.
67
68 Revision 1.1 1999/04/23 11:58:25 burnsbr
69 Initial revision
70
71
72 */
73
74 /*
75 compress.c - code for handling deflation
76 Copyright (C) 1999 Bryan Burns
77
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.
82
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.
87
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.
91 */
92
93 #include "config.h"
94
95 #include <zlib.h>
96 #include <string.h>
97 #include <stdio.h>
98 #include <errno.h>
99
100 #ifdef HAVE_UNISTD_H
101 #include <unistd.h>
102 #endif
103 #ifdef STDC_HEADERS
104 #include <stdlib.h>
105 #endif
106
107 #include <sys/types.h>
108
109 #include "jartool.h"
110 #include "pushback.h"
111 #include "compress.h"
112
113 extern int seekable;
114
115 static z_stream zs;
116
117 void init_compression(){
118
119 memset(&zs, 0, sizeof(z_stream));
120
121 zs.zalloc = Z_NULL;
122 zs.zfree = Z_NULL;
123 zs.opaque = Z_NULL;
124
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){
130
131 fprintf(stderr, "Error initializing deflation!\n");
132 exit(1);
133 }
134 }
135
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;
142
143 rdamt = 0;
144
145 zs.avail_in = 0;
146 zs.next_in = in_buff;
147
148 zs.next_out = out_buff;
149 zs.avail_out = (uInt)RDSZ;
150
151 ze->crc = crc32(0L, Z_NULL, 0);
152
153 for(; ;){
154
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;
159
160 if(rtval == -1){
161 perror("read");
162 exit(1);
163 }
164
165 rdamt = rtval;
166
167 /* compute the CRC while we're at it */
168 ze->crc = crc32(ze->crc, in_buff, rdamt);
169
170 /* update the total amount read sofar */
171 tr += rdamt;
172
173 zs.next_in = in_buff;
174 zs.avail_in = rdamt;
175 }
176
177 /* deflate the data */
178 if(deflate(&zs, 0) != Z_OK){
179 fprintf(stderr, "Error deflating! %s:%d\n", __FILE__, __LINE__);
180 exit(1);
181 }
182
183 /* If the output buffer is full, dump it to disk */
184 if(zs.avail_out == 0){
185
186 if(write(out_fd, out_buff, RDSZ) != RDSZ){
187 perror("write");
188 exit(1);
189 }
190
191 /* clear the output buffer */
192 zs.next_out = out_buff;
193 zs.avail_out = (uInt)RDSZ;
194 }
195
196 }
197
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){
201
202 wramt = RDSZ - zs.avail_out;
203
204 if(write(out_fd, out_buff, wramt) != (int)wramt){
205 perror("write");
206 exit(1);
207 }
208 /* clear the output buffer */
209 zs.next_out = out_buff;
210 zs.avail_out = (uInt)RDSZ;
211 }
212
213
214 /* finish deflation. This purges zlib's internal data buffers */
215 while(deflate(&zs, Z_FINISH) == Z_OK){
216 wramt = RDSZ - zs.avail_out;
217
218 if(write(out_fd, out_buff, wramt) != (int)wramt){
219 perror("write");
220 exit(1);
221 }
222
223 zs.next_out = out_buff;
224 zs.avail_out = (uInt)RDSZ;
225 }
226
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;
230
231 if(write(out_fd, out_buff, wramt) != (int)wramt){
232 perror("write");
233 exit(1);
234 }
235 }
236
237 /* update fastjar's entry information */
238 ze->usize = (ub4)zs.total_in;
239 ze->csize = (ub4)zs.total_out;
240
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);
245 }
246
247 return 0;
248 }
249
250 void end_compression(){
251 int rtval;
252
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);
259 }
260 }
261
262
263 void init_inflation(){
264
265 memset(&zs, 0, sizeof(z_stream));
266
267 zs.zalloc = Z_NULL;
268 zs.zfree = Z_NULL;
269 zs.opaque = Z_NULL;
270
271 if(inflateInit2(&zs, -15) != Z_OK){
272 fprintf(stderr, "Error initializing deflation!\n");
273 exit(1);
274 }
275
276 }
277
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;
284
285 zs.avail_in = 0;
286
287 crc = crc32(crc, NULL, 0); /* initialize crc */
288
289 /* loop until we've consumed all the compressed data */
290 for(;;){
291
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);
298 }
299
300 #ifdef DEBUG
301 printf("%d bytes read\n", rdamt);
302 #endif
303
304 zs.next_in = in_buff;
305 zs.avail_in = rdamt;
306 }
307
308 zs.next_out = out_buff;
309 zs.avail_out = RDSZ;
310
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));
318
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);
324 }
325 }
326
327 break;
328 } else {
329 fprintf(stderr, "Error inflating file! (%d)\n", rtval);
330 exit(1);
331 }
332 } else {
333 if(zs.avail_out != RDSZ){
334 crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
335
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);
341 }
342 zs.next_out = out_buff;
343 zs.avail_out = RDSZ;
344 }
345 }
346 }
347 #ifdef DEBUG
348 printf("done inflating\n");
349 #endif
350
351 #ifdef DEBUG
352 printf("%d bytes left over\n", zs.avail_in);
353 #endif
354
355 #ifdef DEBUG
356 printf("CRC is %x\n", crc);
357 #endif
358
359 ze->crc = crc;
360
361 pb_push(pbf, zs.next_in, zs.avail_in);
362
363 ze->usize = zs.total_out;
364
365 inflateReset(&zs);
366 return 0;
367 }
368
369 /*
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.
374 */
375
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);
400 }
401 }
402
403 /*
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.
411 */
412
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;
417
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';
427 }
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);
434 }
435 }
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);
441 }
442 }
443 else {
444 fprintf(stderr, "Malloc of in_buff failed.\n");
445 fprintf(stderr, "Error: %s\n", strerror(errno));
446 exit(1);
447 }
448
449 return out_buff;
450 }
451
452 /*
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.
461 */
462
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;
470
471 i = 1;
472 out_buff = NULL;
473 zret = Z_OK;
474 while(zret != Z_STREAM_END && (rdamt = pb_read(pbf, in_buff, RDSZ)))
475 {
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++;
485 }
486 else {
487 fprintf(stderr, "Realloc of out_buff failed.\n");
488 fprintf(stderr, "Error: %s\n", strerror(errno));
489 exit(1);
490 }
491 } while((zret = inflate(&zs, 0)) == Z_OK);
492 report_str_error(zret);
493 }
494 pb_push(pbf, zs.next_in, zs.avail_in);
495
496 out_buff[(RDSZ * (i - 1)) - zs.avail_out] = '\0';
497 *usize = zs.total_out;
498 *csize = zs.total_in;
499
500 inflateReset(&zs);
501
502 return out_buff;
503 }
504
505 /*
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.
514 */
515
516 Bytef *inflate_string(pb_file *pbf, ub4 *csize, ub4 *usize) {
517 Bytef *ret_buf;
518
519 if(*csize && *usize) ret_buf = ez_inflate_str(pbf, *csize, *usize);
520 else ret_buf = hrd_inflate_str(pbf, csize, usize);
521
522 return ret_buf;
523 }