OSDN Git Service

* java/lang/String.java (String): New constructor.
[pf3gnuchains/gcc-fork.git] / fastjar / compress.c
1 /* $Id: compress.c,v 1.1 2000/12/09 03:08:23 apbianco Exp $
2
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>
6
7            * fastjar: Imported.
8
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.
12
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.
16
17    Revision 1.1.1.1  1999/12/06 03:09:16  toast
18    initial checkin..
19
20
21
22    Revision 1.7  1999/05/10 08:50:05  burnsbr
23    *** empty log message ***
24
25    Revision 1.6  1999/05/10 08:38:44  burnsbr
26    *** empty log message ***
27
28    Revision 1.5  1999/05/10 08:30:29  burnsbr
29    added inflation code
30
31    Revision 1.4  1999/04/27 10:03:33  burnsbr
32    added configure support
33
34    Revision 1.3  1999/04/26 02:35:32  burnsbr
35    compression now works.. yahoo
36
37    Revision 1.2  1999/04/23 12:01:59  burnsbr
38    added licence stuff.
39
40    Revision 1.1  1999/04/23 11:58:25  burnsbr
41    Initial revision
42
43
44 */
45
46 /*
47   compress.c - code for handling deflation
48   Copyright (C) 1999  Bryan Burns
49   
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.
54   
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.
59   
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.
63  */
64
65 #include "config.h"
66
67 #include <zlib.h>
68 #include <string.h>
69 #include <stdio.h>
70 #include <errno.h>
71
72 #ifdef HAVE_UNISTD_H
73 #include <unistd.h>
74 #endif
75 #ifdef STDC_HEADERS
76 #include <stdlib.h>
77 #endif
78
79 #include <sys/types.h>
80
81 #include "jartool.h"
82 #include "pushback.h"
83 #include "compress.h"
84
85 extern int seekable;
86
87 static z_stream zs;
88
89 void init_compression(){
90
91   memset(&zs, 0, sizeof(z_stream));
92
93   zs.zalloc = Z_NULL;
94   zs.zfree = Z_NULL;
95   zs.opaque = Z_NULL;
96
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){
102     
103     fprintf(stderr, "Error initializing deflation!\n");
104     exit(1);
105   }
106 }
107
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;
113
114   rdamt = 0;
115
116   zs.avail_in = 0;
117   zs.next_in = in_buff;
118   
119   zs.next_out = out_buff;
120   zs.avail_out = (uInt)RDSZ;
121   
122   ze->crc = crc32(0L, Z_NULL, 0); 
123   
124   for(; ;){
125     
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;
130
131       if(rdamt == -1){
132         perror("read");
133         exit(1);
134       }
135       
136       /* compute the CRC while we're at it */
137       ze->crc = crc32(ze->crc, in_buff, rdamt); 
138
139       /* update the total amount read sofar */
140       tr += rdamt;
141
142       zs.next_in = in_buff;
143       zs.avail_in = rdamt;
144     }
145     
146     /* deflate the data */
147     if(deflate(&zs, 0) != Z_OK){
148       fprintf(stderr, "Error deflating! %s:%d\n", __FILE__, __LINE__);
149       exit(1);
150     }
151     
152     /* If the output buffer is full, dump it to disk */
153     if(zs.avail_out == 0){
154
155       if(write(out_fd, out_buff, RDSZ) != RDSZ){
156         perror("write");
157         exit(1);
158       }
159
160       /* clear the output buffer */
161       zs.next_out = out_buff;
162       zs.avail_out = (uInt)RDSZ;
163     }
164
165   }
166   
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){
170
171     wramt = RDSZ - zs.avail_out;
172
173     if(write(out_fd, out_buff, wramt) != wramt){
174       perror("write");
175       exit(1);
176     }
177     /* clear the output buffer */
178     zs.next_out = out_buff;
179     zs.avail_out = (uInt)RDSZ;
180   }
181   
182
183   /* finish deflation.  This purges zlib's internal data buffers */
184   while(deflate(&zs, Z_FINISH) == Z_OK){
185     wramt = RDSZ - zs.avail_out;
186
187     if(write(out_fd, out_buff, wramt) != wramt){
188       perror("write");
189       exit(1);
190     }
191
192     zs.next_out = out_buff;
193     zs.avail_out = (uInt)RDSZ;
194   }
195
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;
199
200     if(write(out_fd, out_buff, wramt) != wramt){
201       perror("write");
202       exit(1);
203     }
204   }
205
206   /* update fastjar's entry information */
207   ze->usize = (ub4)zs.total_in;
208   ze->csize = (ub4)zs.total_out;
209
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);
214   }
215   
216   return 0;
217 }
218
219 void end_compression(){
220   int rtval;
221
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);
228   }
229 }
230
231
232 void init_inflation(){
233
234   memset(&zs, 0, sizeof(z_stream));
235     
236   zs.zalloc = Z_NULL;
237   zs.zfree = Z_NULL;
238   zs.opaque = Z_NULL;
239   
240   if(inflateInit2(&zs, -15) != Z_OK){
241     fprintf(stderr, "Error initializing deflation!\n");
242     exit(1);
243   }
244
245 }
246
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;
253
254   zs.avail_in = 0;
255
256   crc = crc32(crc, NULL, 0); /* initialize crc */
257
258   /* loop until we've consumed all the compressed data */
259   for(;;){
260     
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);
267       }
268
269 #ifdef DEBUG
270       printf("%d bytes read\n", rdamt);
271 #endif
272
273       zs.next_in = in_buff;
274       zs.avail_in = rdamt;
275     }
276
277     zs.next_out = out_buff;
278     zs.avail_out = RDSZ;
279     
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));
287
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);
293             }
294         }
295         
296         break;
297       } else {
298         fprintf(stderr, "Error inflating file! (%d)\n", rtval);
299         exit(1);
300       }
301     } else {
302       if(zs.avail_out != RDSZ){
303         crc = crc32(crc, out_buff, (RDSZ - zs.avail_out));
304
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);
310           }
311         zs.next_out = out_buff;
312         zs.avail_out = RDSZ;
313       }
314     }
315   }
316 #ifdef DEBUG
317   printf("done inflating\n");
318 #endif
319
320 #ifdef DEBUG
321   printf("%d bytes left over\n", zs.avail_in);
322 #endif
323
324 #ifdef DEBUG    
325   printf("CRC is %x\n", crc);
326 #endif
327
328   ze->crc = crc;
329   
330   pb_push(pbf, zs.next_in, zs.avail_in);
331
332   ze->usize = zs.total_out;
333
334   inflateReset(&zs);
335   return 0;
336 }
337
338 /*
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.
343 */
344
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);
369         }
370 }
371
372 /*
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.
380 */
381
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;
386
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';
396                         }
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);
403                         }
404                 }
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);
410                 }
411         }
412         else {
413                 fprintf(stderr, "Malloc of in_buff failed.\n");
414                 fprintf(stderr, "Error: %s\n", strerror(errno));
415                 exit(1);
416         }
417
418         return out_buff;
419 }
420
421 /*
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.
430 */
431
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;
439
440         i = 1; 
441         out_buff = NULL;
442         zret = Z_OK;
443         while(zret != Z_STREAM_END && (rdamt = pb_read(pbf, in_buff, RDSZ)))
444         {
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++;
454                         }
455                         else {
456                                 fprintf(stderr, "Realloc of out_buff failed.\n");
457                                 fprintf(stderr, "Error: %s\n", strerror(errno));
458                                 exit(1);
459                         }
460                 } while((zret = inflate(&zs, 0)) == Z_OK);
461                 report_str_error(zret);
462         }
463         pb_push(pbf, zs.next_in, zs.avail_in);
464
465         out_buff[(RDSZ * (i - 1)) - zs.avail_out] = '\0';
466         *usize = zs.total_out;
467         *csize = zs.total_in;
468
469         inflateReset(&zs);
470
471         return out_buff;
472 }
473
474 /*
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.
483 */
484
485 Bytef *inflate_string(pb_file *pbf, ub4 *csize, ub4 *usize) {
486 Bytef *ret_buf;
487
488         if(*csize && *usize) ret_buf = ez_inflate_str(pbf, *csize, *usize);
489         else ret_buf = hrd_inflate_str(pbf, csize, usize);
490
491         return ret_buf;
492 }