Makefile.am: Add HashSet.java and java/lang/ref classes.
[gcc.git] / fastjar / compress.c
1 /* $Id: compress.c,v 1.7 2000/09/13 14:02:02 cory Exp $
2
3 $Log: compress.c,v $
4 Revision 1.7 2000/09/13 14:02:02 cory
5 Reformatted some of the code to more closly match the layout of the orriginal
6 fastjar utility.
7
8 Revision 1.6 2000/09/12 22:29:36 cory
9 Jargrep now seems to do what I want it to do. Performs properly on Linux x86,
10 will test some other platforms later.
11
12 Revision 1.1.1.1 1999/12/06 03:09:16 toast
13 initial checkin..
14
15
16
17 Revision 1.7 1999/05/10 08:50:05 burnsbr
18 *** empty log message ***
19
20 Revision 1.6 1999/05/10 08:38:44 burnsbr
21 *** empty log message ***
22
23 Revision 1.5 1999/05/10 08:30:29 burnsbr
24 added inflation code
25
26 Revision 1.4 1999/04/27 10:03:33 burnsbr
27 added configure support
28
29 Revision 1.3 1999/04/26 02:35:32 burnsbr
30 compression now works.. yahoo
31
32 Revision 1.2 1999/04/23 12:01:59 burnsbr
33 added licence stuff.
34
35 Revision 1.1 1999/04/23 11:58:25 burnsbr
36 Initial revision
37
38
39 */
40
41 /*
42 compress.c - code for handling deflation
43 Copyright (C) 1999 Bryan Burns
44
45 This program is free software; you can redistribute it and/or
46 modify it under the terms of the GNU General Public License
47 as published by the Free Software Foundation; either version 2
48 of the License, or (at your option) any later version.
49
50 This program is distributed in the hope that it will be useful,
51 but WITHOUT ANY WARRANTY; without even the implied warranty of
52 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
53 GNU General Public License for more details.
54
55 You should have received a copy of the GNU General Public License
56 along with this program; if not, write to the Free Software
57 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
58 */
59
60 #include "config.h"
61
62 #include <zlib.h>
63 #include <string.h>
64 #include <stdio.h>
65 #include <errno.h>
66
67 #ifdef HAVE_UNISTD_H
68 #include <unistd.h>
69 #endif
70
71 #include <sys/types.h>
72
73 #include "jartool.h"
74 #include "pushback.h"
75
76 extern int seekable;
77
78 static char rcsid[] = "$Id: compress.c,v 1.7 2000/09/13 14:02:02 cory Exp $";
79
80 static z_stream zs;
81
82 void init_compression(){
83
84 memset(&zs, 0, sizeof(z_stream));
85
86 zs.zalloc = Z_NULL;
87 zs.zfree = Z_NULL;
88 zs.opaque = Z_NULL;
89
90 /* Why -MAX_WBITS? zlib has an undocumented feature, where if the windowbits
91 parameter is negative, it omits the zlib header, which seems to kill
92 any other zip/unzip program. This caused me SO much pain.. */
93 if(deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS,
94 9, Z_DEFAULT_STRATEGY) != Z_OK){
95
96 fprintf(stderr, "Error initializing deflation!\n");
97 exit(1);
98 }
99 }
100
101 int compress_file(int in_fd, int out_fd, struct zipentry *ze){
102 Bytef in_buff[RDSZ];
103 Bytef out_buff[RDSZ];
104 unsigned int rdamt, wramt;
105 unsigned long tr = 0;
106
107 rdamt = 0;
108
109 zs.avail_in = 0;
110 zs.next_in = in_buff;
111
112 zs.next_out = out_buff;
113 zs.avail_out = (uInt)RDSZ;
114
115 ze->crc = crc32(0L, Z_NULL, 0);
116
117 for(; ;){
118
119 /* If deflate is out of input, fill the input buffer for it */
120 if(zs.avail_in == 0 && zs.avail_out > 0){
121 if((rdamt = read(in_fd, in_buff, RDSZ)) == 0)
122 break;
123
124 if(rdamt == -1){
125 perror("read");
126 exit(1);
127 }
128
129 /* compute the CRC while we're at it */
130 ze->crc = crc32(ze->crc, in_buff, rdamt);
131
132 /* update the total amount read sofar */
133 tr += rdamt;
134
135 zs.next_in = in_buff;
136 zs.avail_in = rdamt;
137 }
138
139 /* deflate the data */
140 if(deflate(&zs, 0) != Z_OK){
141 fprintf(stderr, "Error deflating! %s:%d\n", __FILE__, __LINE__);
142 exit(1);
143 }
144
145 /* If the output buffer is full, dump it to disk */
146 if(zs.avail_out == 0){
147
148 if(write(out_fd, out_buff, RDSZ) != RDSZ){
149 perror("write");
150 exit(1);
151 }
152
153 /* clear the output buffer */
154 zs.next_out = out_buff;
155 zs.avail_out = (uInt)RDSZ;
156 }
157
158 }
159
160 /* If we have any data waiting in the buffer after we're done with the file
161 we can flush it */
162 if(zs.avail_out < RDSZ){
163
164 wramt = RDSZ - zs.avail_out;
165
166 if(write(out_fd, out_buff, wramt) != wramt){
167 perror("write");
168 exit(1);
169 }
170 /* clear the output buffer */
171 zs.next_out = out_buff;
172 zs.avail_out = (uInt)RDSZ;
173 }
174
175
176 /* finish deflation. This purges zlib's internal data buffers */
177 while(deflate(&zs, Z_FINISH) == Z_OK){
178 wramt = RDSZ - zs.avail_out;
179
180 if(write(out_fd, out_buff, wramt) != wramt){
181 perror("write");
182 exit(1);
183 }
184
185 zs.next_out = out_buff;
186 zs.avail_out = (uInt)RDSZ;
187 }
188
189 /* If there's any data left in the buffer, write it out */
190 if(zs.avail_out != RDSZ){
191 wramt = RDSZ - zs.avail_out;
192
193 if(write(out_fd, out_buff, wramt) != wramt){
194 perror("write");
195 exit(1);
196 }
197 }
198
199 /* update fastjar's entry information */
200 ze->usize = (ub4)zs.total_in;
201 ze->csize = (ub4)zs.total_out;
202
203 /* Reset the deflation for the next time around */
204 if(deflateReset(&zs) != Z_OK){
205 fprintf(stderr, "Error resetting deflation\n");
206 exit(1);
207 }
208
209 return 0;
210 }
211
212 void end_compression(){
213 int rtval;
214
215 /* Oddly enough, zlib always returns Z_DATA_ERROR if you specify no
216 zlib header. Go fig. */
217 if((rtval = deflateEnd(&zs)) != Z_OK && rtval != Z_DATA_ERROR){
218 fprintf(stderr, "Error calling deflateEnd\n");
219 fprintf(stderr, "error: (%d) %s\n", rtval, zs.msg);
220 exit(1);
221 }
222 }
223
224
225 void init_inflation(){
226
227 memset(&zs, 0, sizeof(z_stream));
228
229 zs.zalloc = Z_NULL;
230 zs.zfree = Z_NULL;
231 zs.opaque = Z_NULL;
232
233 if(inflateInit2(&zs, -15) != Z_OK){
234 fprintf(stderr, "Error initializing deflation!\n");
235 exit(1);
236 }
237
238 }
239
240 int inflate_file(pb_file *pbf, int out_fd, struct zipentry *ze){
241 Bytef in_buff[RDSZ];
242 Bytef out_buff[RDSZ];
243 unsigned int rdamt;
244 int rtval;
245 ub4 crc = 0;
246
247 zs.avail_in = 0;
248
249 crc = crc32(crc, NULL, 0); /* initialize crc */
250
251 /* loop until we've consumed all the compressed data */
252 for(;;){
253
254 if(zs.avail_in == 0){
255 if((rdamt = pb_read(pbf, in_buff, RDSZ)) == 0)
256 break;
257 else if(rdamt < 0){
258 perror("read");
259 exit(1);
260 }
261
262 #ifdef DEBUG
263 printf("%d bytes read\n", rdamt);
264 #endif
265
266 zs.next_in = in_buff;
267 zs.avail_in = rdamt;
268 }
269
270 zs.next_out = out_buff;
271 zs.avail_out = RDSZ;
272
273 if((rtval = inflate(&zs, 0)) != Z_OK){
274 if(rtval == Z_STREAM_END){
275 #ifdef DEBUG
276 printf("end of stream\n");
277 #endif
278 if(zs.avail_out != RDSZ){
279 crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
280
281 if(out_fd >= 0)
282 if(write(out_fd, out_buff, (RDSZ - zs.avail_out)) !=
283 (RDSZ - zs.avail_out)){
284 perror("write");
285 exit(1);
286 }
287 }
288
289 break;
290 } else {
291 fprintf(stderr, "Error inflating file! (%d)\n", rtval);
292 exit(1);
293 }
294 } else {
295 if(zs.avail_out != RDSZ){
296 crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
297
298 if(out_fd >= 0)
299 if(write(out_fd, out_buff, (RDSZ - zs.avail_out)) !=
300 (RDSZ - zs.avail_out)){
301 perror("write");
302 exit(1);
303 }
304 zs.next_out = out_buff;
305 zs.avail_out = RDSZ;
306 }
307 }
308 }
309 #ifdef DEBUG
310 printf("done inflating\n");
311 #endif
312
313 #ifdef DEBUG
314 printf("%d bytes left over\n", zs.avail_in);
315 #endif
316
317 #ifdef DEBUG
318 printf("CRC is %x\n", crc);
319 #endif
320
321 ze->crc = crc;
322
323 pb_push(pbf, zs.next_in, zs.avail_in);
324
325 ze->usize = zs.total_out;
326
327 inflateReset(&zs);
328 return 0;
329 }
330
331 /*
332 Function name: report_str_error
333 args: val Error code returned from zlib.
334 purpose: Put out an error message corresponding to error code returned from zlib.
335 Be suitably cryptic seeing I don't really know exactly what these errors mean.
336 */
337
338 void report_str_error(int val) {
339 switch(val) {
340 case Z_STREAM_END:
341 break;
342 case Z_NEED_DICT:
343 fprintf(stderr, "Need a dictionary?\n");
344 exit(1);
345 case Z_DATA_ERROR:
346 fprintf(stderr, "Z_DATA_ERROR\n");
347 exit(1);
348 case Z_STREAM_ERROR:
349 fprintf(stderr, "Z_STREAM_ERROR\n");
350 exit(1);
351 case Z_MEM_ERROR:
352 fprintf(stderr, "Z_MEM_ERROR\n");
353 exit(1);
354 case Z_BUF_ERROR:
355 fprintf(stderr, "Z_BUF_ERROR\n");
356 exit(1);
357 case Z_OK:
358 break;
359 default:
360 fprintf(stderr, "Unknown behavior from inflate\n");
361 exit(1);
362 }
363 }
364
365 /*
366 Function name: ez_inflate_str
367 args: pbf Pointer to pushback handle for file.
368 csize Compressed size of embedded file.
369 usize Uncompressed size of embedded file.
370 purpose: Read in and decompress the contents of an embedded file and store it in a
371 byte array.
372 returns: Byte array of uncompressed embedded file.
373 */
374
375 static Bytef *ez_inflate_str(pb_file *pbf, ub4 csize, ub4 usize) {
376 Bytef *out_buff;
377 Bytef *in_buff;
378 unsigned int rdamt;
379 ub4 crc = 0;
380
381 if(zs.next_in = in_buff = (Bytef *) malloc(csize)) {
382 if(zs.next_out = out_buff = (Bytef *) malloc(usize + 1)) {
383 if((rdamt = pb_read(pbf, zs.next_in, csize)) == csize) {
384 zs.avail_in = csize;
385 zs.avail_out = usize;
386 report_str_error(inflate(&zs, 0));
387 free(in_buff);
388 inflateReset(&zs);
389 out_buff[usize] = '\0';
390 }
391 else {
392 fprintf(stderr, "Read failed on input file.\n");
393 fprintf(stderr, "Tried to read %u but read %u instead.\n", csize, rdamt);
394 free(in_buff);
395 free(out_buff);
396 exit(1);
397 }
398 }
399 else {
400 fprintf(stderr, "Malloc of out_buff failed.\n");
401 fprintf(stderr, "Error: %s\n", strerror(errno));
402 free(in_buff);
403 exit(1);
404 }
405 }
406 else {
407 fprintf(stderr, "Malloc of in_buff failed.\n");
408 fprintf(stderr, "Error: %s\n", strerror(errno));
409 exit(1);
410 }
411
412 return out_buff;
413 }
414
415 /*
416 Function name: hrd_inflate_str
417 args: pbf Pointer to pushback handle for file.
418 csize Pointer to compressed size of embedded file.
419 usize Pointer to uncompressed size of embedded file.
420 purpose: Read and decompress an embedded file into a string. Set csize and usize
421 accordingly. This function does the reading for us in the case there is not size
422 information in the header for the embedded file.
423 returns: Byte array of the contents of the embedded file.
424 */
425
426 static Bytef *hrd_inflate_str(pb_file *pbf, ub4 *csize, ub4 *usize) {
427 Bytef *out_buff;
428 Bytef *tmp;
429 Bytef in_buff[RDSZ];
430 unsigned int rdamt;
431 int i;
432 int zret;
433 ub4 crc = 0;
434
435 i = 1;
436 out_buff = NULL;
437 zret = Z_OK;
438 while(zret != Z_STREAM_END && (rdamt = pb_read(pbf, in_buff, RDSZ)))
439 {
440 zs.avail_in = rdamt;
441 zs.avail_out = 0;
442 zs.next_in = in_buff;
443 do {
444 if(tmp = (Bytef *) realloc(out_buff, (RDSZ * i) + 1)) {
445 out_buff = tmp;
446 zs.next_out = &(out_buff[(RDSZ * (i - 1)) - zs.avail_out]);
447 zs.avail_out += RDSZ;
448 i++;
449 }
450 else {
451 fprintf(stderr, "Realloc of out_buff failed.\n");
452 fprintf(stderr, "Error: %s\n", strerror(errno));
453 exit(1);
454 }
455 } while((zret = inflate(&zs, 0)) == Z_OK);
456 report_str_error(zret);
457 }
458 pb_push(pbf, zs.next_in, zs.avail_in);
459
460 out_buff[(RDSZ * (i - 1)) - zs.avail_out] = '\0';
461 *usize = zs.total_out;
462 *csize = zs.total_in;
463
464 inflateReset(&zs);
465
466 return out_buff;
467 }
468
469 /*
470 Function name: inflate_string
471 args: pbf Pointer to pushback handle for file.
472 csize Pointer to compressed size of embedded file. May be 0 if not set.
473 usize Pointer to uncompressed size of embedded file. May be 0 if not set.
474 purpose: Decide the easiest (in computer terms) methos of decompressing this embedded
475 file to a string.
476 returns: Pointer to a string containing the decompressed contents of the embedded file.
477 If csize and usize are not set set them to correct numbers.
478 */
479
480 Bytef *inflate_string(pb_file *pbf, ub4 *csize, ub4 *usize) {
481 Bytef *ret_buf;
482
483 if(*csize && *usize) ret_buf = ez_inflate_str(pbf, *csize, *usize);
484 else ret_buf = hrd_inflate_str(pbf, csize, usize);
485
486 return ret_buf;
487 }