1 /* $Id: compress.c,v 1.2 2000/12/14 18:45:35 ghazi Exp $
4 Revision 1.2 2000/12/14 18:45:35 ghazi
7 * compress.c: Include stdlib.h and compress.h.
9 (report_str_error): Make static.
10 (ez_inflate_str): Delete unused variable. Add parens in if-stmt.
11 (hrd_inflate_str): Likewise.
13 * compress.h (init_compression, end_compression, init_inflation,
14 end_inflation): Prototype void arguments.
16 * dostime.c (rcsid): Delete.
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.
24 * jartool.c: Constify. Add parens in if-stmts. Align
25 signed/unsigned char pointers in functions calls using casts.
27 (list_jar): Fix printf format specifier.
28 (usage): Chop long string into bits. Reformat.
30 * pushback.c (rcsid): Delete.
32 Revision 1.1 2000/12/09 03:08:23 apbianco
33 2000-12-08 Alexandre Petit-Bianco <apbianco@cygnus.com>
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
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.
45 Revision 1.1.1.1 1999/12/06 03:09:16 toast
50 Revision 1.7 1999/05/10 08:50:05 burnsbr
51 *** empty log message ***
53 Revision 1.6 1999/05/10 08:38:44 burnsbr
54 *** empty log message ***
56 Revision 1.5 1999/05/10 08:30:29 burnsbr
59 Revision 1.4 1999/04/27 10:03:33 burnsbr
60 added configure support
62 Revision 1.3 1999/04/26 02:35:32 burnsbr
63 compression now works.. yahoo
65 Revision 1.2 1999/04/23 12:01:59 burnsbr
68 Revision 1.1 1999/04/23 11:58:25 burnsbr
75 compress.c - code for handling deflation
76 Copyright (C) 1999 Bryan Burns
77 Copyright (C) 2004 Free Software Foundation, Inc.
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.
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.
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.
108 #include <sys/types.h>
111 #include "pushback.h"
112 #include "compress.h"
115 int write_data (int, void *, size_t, struct zipentry
*);
118 extern off_t end_of_entries
;
122 void init_compression(){
124 memset(&zs
, 0, sizeof(z_stream
));
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
){
136 fprintf(stderr
, "Error initializing deflation!\n");
142 write_data (int fd
, void *buf
, size_t len
, struct zipentry
*ze
)
144 #ifdef WITH_SHIFT_DOWN
145 struct zipentry
*next
= NULL
;
146 off_t here
= lseek (fd
, 0, SEEK_CUR
);
148 * If we are updating and there is not enough space before the next
149 * entry, expand the file.
153 next
= ze
->next_entry
;
154 if (next
&& here
+ len
>= next
->offset
)
156 if (shift_down (fd
, next
->offset
, (here
+ len
) - next
->offset
, next
))
158 perror ("can't expand file");
163 #endif /* WITH_SHIFT_DOWN */
165 return write (fd
, buf
, len
);
168 int compress_file(int in_fd
, int out_fd
, struct zipentry
*ze
,
169 struct zipentry
*existing
)
172 Bytef out_buff
[RDSZ
];
173 unsigned int rdamt
, wramt
;
174 unsigned long tr
= 0;
180 zs
.next_in
= in_buff
;
182 zs
.next_out
= out_buff
;
183 zs
.avail_out
= (uInt
)RDSZ
;
185 ze
->crc
= crc32(0L, Z_NULL
, 0);
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)
201 /* compute the CRC while we're at it */
202 ze
->crc
= crc32(ze
->crc
, in_buff
, rdamt
);
204 /* update the total amount read sofar */
207 zs
.next_in
= in_buff
;
211 /* deflate the data */
212 if(deflate(&zs
, 0) != Z_OK
){
213 fprintf(stderr
, "Error deflating! %s:%d\n", __FILE__
, __LINE__
);
217 /* If the output buffer is full, dump it to disk */
218 if(zs
.avail_out
== 0){
220 if (write_data (out_fd
, out_buff
, RDSZ
, existing
) != RDSZ
)
226 /* clear the output buffer */
227 zs
.next_out
= out_buff
;
228 zs
.avail_out
= (uInt
)RDSZ
;
233 /* If we have any data waiting in the buffer after we're done with the file
235 if(zs
.avail_out
< RDSZ
){
237 wramt
= RDSZ
- zs
.avail_out
;
239 if (write_data (out_fd
, out_buff
, wramt
, existing
) != (int)wramt
)
244 /* clear the output buffer */
245 zs
.next_out
= out_buff
;
246 zs
.avail_out
= (uInt
)RDSZ
;
250 /* finish deflation. This purges zlib's internal data buffers */
251 while(deflate(&zs
, Z_FINISH
) == Z_OK
){
252 wramt
= RDSZ
- zs
.avail_out
;
254 if (write_data (out_fd
, out_buff
, wramt
, existing
) != (int)wramt
)
260 zs
.next_out
= out_buff
;
261 zs
.avail_out
= (uInt
)RDSZ
;
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
;
268 if (write_data (out_fd
, out_buff
, wramt
, existing
) != (int)wramt
)
275 /* update fastjar's entry information */
276 ze
->usize
= (ub4
)zs
.total_in
;
277 ze
->csize
= (ub4
)zs
.total_out
;
279 /* Reset the deflation for the next time around */
280 if(deflateReset(&zs
) != Z_OK
){
281 fprintf(stderr
, "Error resetting deflation\n");
288 void end_compression(){
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
);
301 void init_inflation(){
303 memset(&zs
, 0, sizeof(z_stream
));
309 if(inflateInit2(&zs
, -15) != Z_OK
){
310 fprintf(stderr
, "Error initializing deflation!\n");
316 int inflate_file(pb_file
*pbf
, int out_fd
, struct zipentry
*ze
){
318 Bytef out_buff
[RDSZ
];
325 crc
= crc32(crc
, NULL
, 0); /* initialize crc */
327 /* loop until we've consumed all the compressed data */
330 if(zs
.avail_in
== 0){
331 if((rdamt
= pb_read(pbf
, in_buff
, RDSZ
)) == 0)
333 else if((int)rdamt
< 0){
339 printf("%d bytes read\n", rdamt
);
342 zs
.next_in
= in_buff
;
346 zs
.next_out
= out_buff
;
349 if((rtval
= inflate(&zs
, 0)) != Z_OK
){
350 if(rtval
== Z_STREAM_END
){
352 printf("end of stream\n");
354 if(zs
.avail_out
!= RDSZ
){
355 crc
= crc32(crc
, out_buff
, (RDSZ
- zs
.avail_out
));
358 if(write(out_fd
, out_buff
, (RDSZ
- zs
.avail_out
)) !=
359 (int)(RDSZ
- zs
.avail_out
)){
367 fprintf(stderr
, "Error inflating file! (%d)\n", rtval
);
371 if(zs
.avail_out
!= RDSZ
){
372 crc
= crc32(crc
, out_buff
, (RDSZ
- zs
.avail_out
));
375 if(write(out_fd
, out_buff
, (RDSZ
- zs
.avail_out
)) !=
376 (int)(RDSZ
- zs
.avail_out
)){
380 zs
.next_out
= out_buff
;
386 printf("done inflating\n");
390 printf("%d bytes left over\n", zs
.avail_in
);
394 printf("CRC is %x\n", crc
);
399 pb_push(pbf
, zs
.next_in
, zs
.avail_in
);
401 ze
->usize
= zs
.total_out
;
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.
414 static void report_str_error(int val
) {
419 fprintf(stderr
, "Need a dictionary?\n");
422 fprintf(stderr
, "Z_DATA_ERROR\n");
425 fprintf(stderr
, "Z_STREAM_ERROR\n");
428 fprintf(stderr
, "Z_MEM_ERROR\n");
431 fprintf(stderr
, "Z_BUF_ERROR\n");
436 fprintf(stderr
, "Unknown behavior from inflate\n");
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
448 returns: Byte array of uncompressed embedded file.
451 static Bytef
*ez_inflate_str(pb_file
*pbf
, ub4 csize
, ub4 usize
) {
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
) {
460 zs
.avail_out
= usize
;
461 report_str_error(inflate(&zs
, 0));
464 out_buff
[usize
] = '\0';
467 fprintf(stderr
, "Read failed on input file.\n");
468 fprintf(stderr
, "Tried to read %u but read %u instead.\n", csize
, rdamt
);
475 fprintf(stderr
, "Malloc of out_buff failed.\n");
476 fprintf(stderr
, "Error: %s\n", strerror(errno
));
482 fprintf(stderr
, "Malloc of in_buff failed.\n");
483 fprintf(stderr
, "Error: %s\n", strerror(errno
));
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.
501 static Bytef
*hrd_inflate_str(pb_file
*pbf
, ub4
*csize
, ub4
*usize
) {
512 while(zret
!= Z_STREAM_END
&& (rdamt
= pb_read(pbf
, in_buff
, RDSZ
)))
516 zs
.next_in
= in_buff
;
518 if((tmp
= (Bytef
*) realloc(out_buff
, (RDSZ
* i
) + 1))) {
520 zs
.next_out
= &(out_buff
[(RDSZ
* (i
- 1)) - zs
.avail_out
]);
521 zs
.avail_out
+= RDSZ
;
525 fprintf(stderr
, "Realloc of out_buff failed.\n");
526 fprintf(stderr
, "Error: %s\n", strerror(errno
));
529 } while((zret
= inflate(&zs
, 0)) == Z_OK
);
530 report_str_error(zret
);
532 pb_push(pbf
, zs
.next_in
, zs
.avail_in
);
534 out_buff
[(RDSZ
* (i
- 1)) - zs
.avail_out
] = '\0';
535 *usize
= zs
.total_out
;
536 *csize
= zs
.total_in
;
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
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.
554 Bytef
*inflate_string(pb_file
*pbf
, ub4
*csize
, ub4
*usize
) {
557 if(*csize
&& *usize
) ret_buf
= ez_inflate_str(pbf
, *csize
, *usize
);
558 else ret_buf
= hrd_inflate_str(pbf
, csize
, usize
);