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