OSDN Git Service

2005-02-26 Andrew Pinski <pinskia@physics.uc.edu>
[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   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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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, struct zipentry *ze)
143 {
144 #ifdef WITH_SHIFT_DOWN
145   struct zipentry *next = NULL;
146   off_t here = lseek (fd, 0, SEEK_CUR);
147   /*
148    * If we are updating and there is not enough space before the next
149    * entry, expand the file.
150    */
151   if (ze)
152     {
153       next = ze->next_entry;
154       if (next && here + len >= next->offset)
155         {
156           if (shift_down (fd, next->offset, (here + len) - next->offset, next))
157             {
158               perror ("can't expand file");
159               exit (1);
160             }
161         }
162     }
163 #endif /* WITH_SHIFT_DOWN */
164
165   return write (fd, buf, len);
166 }
167
168 int compress_file(int in_fd, int out_fd, struct zipentry *ze,
169                   struct zipentry *existing)
170 {
171   Bytef in_buff[RDSZ];
172   Bytef out_buff[RDSZ];
173   unsigned int rdamt, wramt;
174   unsigned long tr = 0;
175   int rtval;
176
177   rdamt = 0;
178
179   zs.avail_in = 0;
180   zs.next_in = in_buff;
181   
182   zs.next_out = out_buff;
183   zs.avail_out = (uInt)RDSZ;
184   
185   ze->crc = crc32(0L, Z_NULL, 0); 
186   
187   for(; ;){
188     
189     /* If deflate is out of input, fill the input buffer for it */
190     if(zs.avail_in == 0 && zs.avail_out > 0){
191       if((rtval = read(in_fd, in_buff, RDSZ)) == 0)
192         break;
193
194       if(rtval == -1){
195         perror("read");
196         exit(1);
197       }
198
199       rdamt = rtval;
200
201       /* compute the CRC while we're at it */
202       ze->crc = crc32(ze->crc, in_buff, rdamt); 
203
204       /* update the total amount read sofar */
205       tr += rdamt;
206
207       zs.next_in = in_buff;
208       zs.avail_in = rdamt;
209     }
210     
211     /* deflate the data */
212     if(deflate(&zs, 0) != Z_OK){
213       fprintf(stderr, "Error deflating! %s:%d\n", __FILE__, __LINE__);
214       exit(1);
215     }
216     
217     /* If the output buffer is full, dump it to disk */
218     if(zs.avail_out == 0){
219
220       if (write_data (out_fd, out_buff, RDSZ, existing) != RDSZ)
221         {
222           perror("write");
223           exit(1);
224         }
225
226       /* clear the output buffer */
227       zs.next_out = out_buff;
228       zs.avail_out = (uInt)RDSZ;
229     }
230
231   }
232   
233   /* If we have any data waiting in the buffer after we're done with the file
234      we can flush it */
235   if(zs.avail_out < RDSZ){
236
237     wramt = RDSZ - zs.avail_out;
238
239     if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
240       {
241         perror("write");
242         exit(1);
243       }
244     /* clear the output buffer */
245     zs.next_out = out_buff;
246     zs.avail_out = (uInt)RDSZ;
247   }
248   
249
250   /* finish deflation.  This purges zlib's internal data buffers */
251   while(deflate(&zs, Z_FINISH) == Z_OK){
252     wramt = RDSZ - zs.avail_out;
253
254     if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
255       {
256         perror("write");
257         exit(1);
258       }
259
260     zs.next_out = out_buff;
261     zs.avail_out = (uInt)RDSZ;
262   }
263
264   /* If there's any data left in the buffer, write it out */
265   if(zs.avail_out != RDSZ){
266     wramt = RDSZ - zs.avail_out;
267
268     if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
269       {
270         perror("write");
271         exit(1);
272       }
273   }
274
275   /* update fastjar's entry information */
276   ze->usize = (ub4)zs.total_in;
277   ze->csize = (ub4)zs.total_out;
278
279   /* Reset the deflation for the next time around */
280   if(deflateReset(&zs) != Z_OK){
281     fprintf(stderr, "Error resetting deflation\n");
282     exit(1);
283   }
284   
285   return 0;
286 }
287
288 void end_compression(){
289   int rtval;
290
291   /* Oddly enough, zlib always returns Z_DATA_ERROR if you specify no
292      zlib header.  Go fig. */
293   if((rtval = deflateEnd(&zs)) != Z_OK && rtval != Z_DATA_ERROR){
294     fprintf(stderr, "Error calling deflateEnd\n");
295     fprintf(stderr, "error: (%d) %s\n", rtval, zs.msg);
296     exit(1);
297   }
298 }
299
300
301 void init_inflation(){
302
303   memset(&zs, 0, sizeof(z_stream));
304     
305   zs.zalloc = Z_NULL;
306   zs.zfree = Z_NULL;
307   zs.opaque = Z_NULL;
308   
309   if(inflateInit2(&zs, -15) != Z_OK){
310     fprintf(stderr, "Error initializing deflation!\n");
311     exit(1);
312   }
313
314 }
315
316 int inflate_file(pb_file *pbf, int out_fd, struct zipentry *ze){
317   Bytef in_buff[RDSZ];
318   Bytef out_buff[RDSZ];
319   unsigned int rdamt;
320   int rtval;
321   ub4 crc = 0;
322
323   zs.avail_in = 0;
324
325   crc = crc32(crc, NULL, 0); /* initialize crc */
326
327   /* loop until we've consumed all the compressed data */
328   for(;;){
329     
330     if(zs.avail_in == 0){
331       if((rdamt = pb_read(pbf, in_buff, RDSZ)) == 0)
332         break;
333       else if((int)rdamt < 0){
334         perror("read");
335         exit(1);
336       }
337
338 #ifdef DEBUG
339       printf("%d bytes read\n", rdamt);
340 #endif
341
342       zs.next_in = in_buff;
343       zs.avail_in = rdamt;
344     }
345
346     zs.next_out = out_buff;
347     zs.avail_out = RDSZ;
348     
349     if((rtval = inflate(&zs, 0)) != Z_OK){
350       if(rtval == Z_STREAM_END){
351 #ifdef DEBUG
352         printf("end of stream\n");
353 #endif
354         if(zs.avail_out != RDSZ){
355           crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
356
357           if(out_fd >= 0)
358             if(write(out_fd, out_buff, (RDSZ - zs.avail_out)) != 
359                (int)(RDSZ - zs.avail_out)){
360               perror("write");
361               exit(1);
362             }
363         }
364         
365         break;
366       } else {
367         fprintf(stderr, "Error inflating file! (%d)\n", rtval);
368         exit(1);
369       }
370     } else {
371       if(zs.avail_out != RDSZ){
372         crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
373
374         if(out_fd >= 0)
375           if(write(out_fd, out_buff, (RDSZ - zs.avail_out)) != 
376              (int)(RDSZ - zs.avail_out)){
377             perror("write");
378             exit(1);
379           }
380         zs.next_out = out_buff;
381         zs.avail_out = RDSZ;
382       }
383     }
384   }
385 #ifdef DEBUG
386   printf("done inflating\n");
387 #endif
388
389 #ifdef DEBUG
390   printf("%d bytes left over\n", zs.avail_in);
391 #endif
392
393 #ifdef DEBUG    
394   printf("CRC is %x\n", crc);
395 #endif
396
397   ze->crc = crc;
398   
399   pb_push(pbf, zs.next_in, zs.avail_in);
400
401   ze->usize = zs.total_out;
402
403   inflateReset(&zs);
404   return 0;
405 }
406
407 /*
408 Function name: report_str_error
409 args:   val     Error code returned from zlib.
410 purpose: Put out an error message corresponding to error code returned from zlib.
411 Be suitably cryptic seeing I don't really know exactly what these errors mean.
412 */
413
414 static void report_str_error(int val) {
415         switch(val) {
416         case Z_STREAM_END:
417                 break;
418         case Z_NEED_DICT:
419                 fprintf(stderr, "Need a dictionary?\n");
420                 exit(1);
421         case Z_DATA_ERROR:
422                 fprintf(stderr, "Z_DATA_ERROR\n");
423                 exit(1);
424         case Z_STREAM_ERROR:
425                 fprintf(stderr, "Z_STREAM_ERROR\n");
426                 exit(1);
427         case Z_MEM_ERROR:
428                 fprintf(stderr, "Z_MEM_ERROR\n");
429                 exit(1);
430         case Z_BUF_ERROR:
431                 fprintf(stderr, "Z_BUF_ERROR\n");
432                 exit(1);
433         case Z_OK:
434                 break;
435         default:
436                 fprintf(stderr, "Unknown behavior from inflate\n");
437                 exit(1);
438         }
439 }
440
441 /*
442 Function name: ez_inflate_str
443 args:   pbf             Pointer to pushback handle for file.
444                 csize   Compressed size of embedded file.
445                 usize   Uncompressed size of embedded file.
446 purpose: Read in and decompress the contents of an embedded file and store it in a
447 byte array.
448 returns: Byte array of uncompressed embedded file.
449 */
450
451 static Bytef *ez_inflate_str(pb_file *pbf, ub4 csize, ub4 usize) {
452         Bytef *out_buff;
453         Bytef *in_buff;
454         unsigned int rdamt;
455
456         if((zs.next_in = in_buff = (Bytef *) malloc(csize))) {
457                 if((zs.next_out = out_buff = (Bytef *) malloc(usize + 1))) { 
458                         if((rdamt = pb_read(pbf, zs.next_in, csize)) == csize) {
459                                 zs.avail_in = csize;
460                                 zs.avail_out = usize;
461                                 report_str_error(inflate(&zs, 0));
462                                 free(in_buff);
463                                 inflateReset(&zs);
464                                 out_buff[usize] = '\0';
465                         }
466                         else {
467                                 fprintf(stderr, "Read failed on input file.\n");
468                                 fprintf(stderr, "Tried to read %u but read %u instead.\n", csize, rdamt);
469                                 free(in_buff);
470                                 free(out_buff);
471                                 exit(1);
472                         }
473                 }
474                 else {
475                         fprintf(stderr, "Malloc of out_buff failed.\n");
476                         fprintf(stderr, "Error: %s\n", strerror(errno));
477                         free(in_buff);
478                         exit(1);
479                 }
480         }
481         else {
482                 fprintf(stderr, "Malloc of in_buff failed.\n");
483                 fprintf(stderr, "Error: %s\n", strerror(errno));
484                 exit(1);
485         }
486
487         return out_buff;
488 }
489
490 /*
491 Function name: hrd_inflate_str
492 args:   pbf             Pointer to pushback handle for file.
493                 csize   Pointer to compressed size of embedded file.
494                 usize   Pointer to uncompressed size of embedded file.
495 purpose: Read and decompress an embedded file into a string.  Set csize and usize
496 accordingly.  This function does the reading for us in the case there is not size
497 information in the header for the embedded file.
498 returns: Byte array of the contents of the embedded file.
499 */
500
501 static Bytef *hrd_inflate_str(pb_file *pbf, ub4 *csize, ub4 *usize) {
502         Bytef *out_buff;
503         Bytef *tmp;
504         Bytef in_buff[RDSZ];
505         unsigned int rdamt;
506         int i;
507         int zret;
508
509         i = 1; 
510         out_buff = NULL;
511         zret = Z_OK;
512         while(zret != Z_STREAM_END && (rdamt = pb_read(pbf, in_buff, RDSZ)))
513         {
514                 zs.avail_in = rdamt;
515                 zs.avail_out = 0;
516                 zs.next_in = in_buff;
517                 do {
518                         if((tmp = (Bytef *) realloc(out_buff, (RDSZ * i) + 1))) {
519                                 out_buff = tmp;
520                                 zs.next_out = &(out_buff[(RDSZ * (i - 1)) - zs.avail_out]);
521                                 zs.avail_out += RDSZ;
522                                 i++;
523                         }
524                         else {
525                                 fprintf(stderr, "Realloc of out_buff failed.\n");
526                                 fprintf(stderr, "Error: %s\n", strerror(errno));
527                                 exit(1);
528                         }
529                 } while((zret = inflate(&zs, 0)) == Z_OK);
530                 report_str_error(zret);
531         }
532         pb_push(pbf, zs.next_in, zs.avail_in);
533
534         out_buff[(RDSZ * (i - 1)) - zs.avail_out] = '\0';
535         *usize = zs.total_out;
536         *csize = zs.total_in;
537
538         inflateReset(&zs);
539
540         return out_buff;
541 }
542
543 /*
544 Function name: inflate_string
545 args:   pbf             Pointer to pushback handle for file.
546                 csize   Pointer to compressed size of embedded file.  May be 0 if not set.
547                 usize   Pointer to uncompressed size of embedded file. May be 0 if not set.
548 purpose: Decide the easiest (in computer terms) methos of decompressing this embedded
549 file to a string.
550 returns: Pointer to a string containing the decompressed contents of the embedded file.
551 If csize and usize are not set set them to correct numbers.
552 */
553
554 Bytef *inflate_string(pb_file *pbf, ub4 *csize, ub4 *usize) {
555 Bytef *ret_buf;
556
557         if(*csize && *usize) ret_buf = ez_inflate_str(pbf, *csize, *usize);
558         else ret_buf = hrd_inflate_str(pbf, csize, usize);
559
560         return ret_buf;
561 }