configure.ac: Unconditionally disable decimal float by default.
[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 Copyright (C) 2004 Free Software Foundation, Inc.
78
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.
83
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.
88
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.
92 */
93
94 #include "config.h"
95
96 #include <zlib.h>
97 #include <string.h>
98 #include <stdio.h>
99 #include <errno.h>
100
101 #ifdef HAVE_UNISTD_H
102 #include <unistd.h>
103 #endif
104 #ifdef STDC_HEADERS
105 #include <stdlib.h>
106 #endif
107
108 #include <sys/types.h>
109
110 #include "jartool.h"
111 #include "pushback.h"
112 #include "compress.h"
113 #include "shift.h"
114
115 int write_data (int, void *, size_t, struct zipentry *);
116
117 extern int seekable;
118 extern off_t end_of_entries;
119
120 static z_stream zs;
121
122 void init_compression(){
123
124 memset(&zs, 0, sizeof(z_stream));
125
126 zs.zalloc = Z_NULL;
127 zs.zfree = Z_NULL;
128 zs.opaque = Z_NULL;
129
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){
135
136 fprintf(stderr, "Error initializing deflation!\n");
137 exit(1);
138 }
139 }
140
141 int
142 write_data (int fd, void *buf, size_t len,
143 struct zipentry *ze __attribute__((unused)))
144 {
145 #ifdef WITH_SHIFT_DOWN
146 struct zipentry *next = NULL;
147 off_t here = lseek (fd, 0, SEEK_CUR);
148 /*
149 * If we are updating and there is not enough space before the next
150 * entry, expand the file.
151 */
152 if (ze)
153 {
154 next = ze->next_entry;
155 if (next && here + len >= next->offset)
156 {
157 if (shift_down (fd, next->offset, (here + len) - next->offset, next))
158 {
159 perror ("can't expand file");
160 exit (1);
161 }
162 }
163 }
164 #endif /* WITH_SHIFT_DOWN */
165
166 return write (fd, buf, len);
167 }
168
169 int compress_file(int in_fd, int out_fd, struct zipentry *ze,
170 struct zipentry *existing)
171 {
172 Bytef in_buff[RDSZ];
173 Bytef out_buff[RDSZ];
174 unsigned int rdamt, wramt;
175 unsigned long tr = 0;
176 int rtval;
177
178 rdamt = 0;
179
180 zs.avail_in = 0;
181 zs.next_in = in_buff;
182
183 zs.next_out = out_buff;
184 zs.avail_out = (uInt)RDSZ;
185
186 ze->crc = crc32(0L, Z_NULL, 0);
187
188 for(; ;){
189
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;
194
195 if(rtval == -1){
196 perror("read");
197 exit(1);
198 }
199
200 rdamt = rtval;
201
202 /* compute the CRC while we're at it */
203 ze->crc = crc32(ze->crc, in_buff, rdamt);
204
205 /* update the total amount read sofar */
206 tr += rdamt;
207
208 zs.next_in = in_buff;
209 zs.avail_in = rdamt;
210 }
211
212 /* deflate the data */
213 if(deflate(&zs, 0) != Z_OK){
214 fprintf(stderr, "Error deflating! %s:%d\n", __FILE__, __LINE__);
215 exit(1);
216 }
217
218 /* If the output buffer is full, dump it to disk */
219 if(zs.avail_out == 0){
220
221 if (write_data (out_fd, out_buff, RDSZ, existing) != RDSZ)
222 {
223 perror("write");
224 exit(1);
225 }
226
227 /* clear the output buffer */
228 zs.next_out = out_buff;
229 zs.avail_out = (uInt)RDSZ;
230 }
231
232 }
233
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){
237
238 wramt = RDSZ - zs.avail_out;
239
240 if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
241 {
242 perror("write");
243 exit(1);
244 }
245 /* clear the output buffer */
246 zs.next_out = out_buff;
247 zs.avail_out = (uInt)RDSZ;
248 }
249
250
251 /* finish deflation. This purges zlib's internal data buffers */
252 while(deflate(&zs, Z_FINISH) == Z_OK){
253 wramt = RDSZ - zs.avail_out;
254
255 if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
256 {
257 perror("write");
258 exit(1);
259 }
260
261 zs.next_out = out_buff;
262 zs.avail_out = (uInt)RDSZ;
263 }
264
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;
268
269 if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
270 {
271 perror("write");
272 exit(1);
273 }
274 }
275
276 /* update fastjar's entry information */
277 ze->usize = (ub4)zs.total_in;
278 ze->csize = (ub4)zs.total_out;
279
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);
284 }
285
286 return 0;
287 }
288
289 void end_compression(){
290 int rtval;
291
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);
298 }
299 }
300
301
302 void init_inflation(){
303
304 memset(&zs, 0, sizeof(z_stream));
305
306 zs.zalloc = Z_NULL;
307 zs.zfree = Z_NULL;
308 zs.opaque = Z_NULL;
309
310 if(inflateInit2(&zs, -15) != Z_OK){
311 fprintf(stderr, "Error initializing deflation!\n");
312 exit(1);
313 }
314
315 }
316
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;
323
324 zs.avail_in = 0;
325
326 crc = crc32(crc, NULL, 0); /* initialize crc */
327
328 /* loop until we've consumed all the compressed data */
329 for(;;){
330
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);
337 }
338
339 #ifdef DEBUG
340 printf("%d bytes read\n", rdamt);
341 #endif
342
343 zs.next_in = in_buff;
344 zs.avail_in = rdamt;
345 }
346
347 zs.next_out = out_buff;
348 zs.avail_out = RDSZ;
349
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));
357
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);
363 }
364 }
365
366 break;
367 } else {
368 fprintf(stderr, "Error inflating file! (%d)\n", rtval);
369 exit(1);
370 }
371 } else {
372 if(zs.avail_out != RDSZ){
373 crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
374
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);
380 }
381 zs.next_out = out_buff;
382 zs.avail_out = RDSZ;
383 }
384 }
385 }
386 #ifdef DEBUG
387 printf("done inflating\n");
388 #endif
389
390 #ifdef DEBUG
391 printf("%d bytes left over\n", zs.avail_in);
392 #endif
393
394 #ifdef DEBUG
395 printf("CRC is %x\n", crc);
396 #endif
397
398 ze->crc = crc;
399
400 pb_push(pbf, zs.next_in, zs.avail_in);
401
402 ze->usize = zs.total_out;
403
404 inflateReset(&zs);
405 return 0;
406 }
407
408 /*
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.
413 */
414
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);
439 }
440 }
441
442 /*
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.
450 */
451
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;
456
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';
466 }
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);
473 }
474 }
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);
480 }
481 }
482 else {
483 fprintf(stderr, "Malloc of in_buff failed.\n");
484 fprintf(stderr, "Error: %s\n", strerror(errno));
485 exit(1);
486 }
487
488 return out_buff;
489 }
490
491 /*
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.
500 */
501
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;
509
510 i = 1;
511 out_buff = NULL;
512 zret = Z_OK;
513 while(zret != Z_STREAM_END && (rdamt = pb_read(pbf, in_buff, RDSZ)))
514 {
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++;
524 }
525 else {
526 fprintf(stderr, "Realloc of out_buff failed.\n");
527 fprintf(stderr, "Error: %s\n", strerror(errno));
528 exit(1);
529 }
530 } while((zret = inflate(&zs, 0)) == Z_OK);
531 report_str_error(zret);
532 }
533 pb_push(pbf, zs.next_in, zs.avail_in);
534
535 out_buff[(RDSZ * (i - 1)) - zs.avail_out] = '\0';
536 *usize = zs.total_out;
537 *csize = zs.total_in;
538
539 inflateReset(&zs);
540
541 return out_buff;
542 }
543
544 /*
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.
553 */
554
555 Bytef *inflate_string(pb_file *pbf, ub4 *csize, ub4 *usize) {
556 Bytef *ret_buf;
557
558 if(*csize && *usize) ret_buf = ez_inflate_str(pbf, *csize, *usize);
559 else ret_buf = hrd_inflate_str(pbf, csize, usize);
560
561 return ret_buf;
562 }