OSDN Git Service

2005-12-16 Richard Guenther <rguenther@suse.de>
[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., 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 }