OSDN Git Service

fa7bc2ed3f1a80c6ebe754c18601dfefacebcdee
[pf3gnuchains/gcc-fork.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 }