1 /* $Id: compress.c,v 1.7 2000/09/13 14:02:02 cory Exp $
4 Revision 1.7 2000/09/13 14:02:02 cory
5 Reformatted some of the code to more closly match the layout of the orriginal
8 Revision 1.6 2000/09/12 22:29:36 cory
9 Jargrep now seems to do what I want it to do. Performs properly on Linux x86,
10 will test some other platforms later.
12 Revision 1.1.1.1 1999/12/06 03:09:16 toast
17 Revision 1.7 1999/05/10 08:50:05 burnsbr
18 *** empty log message ***
20 Revision 1.6 1999/05/10 08:38:44 burnsbr
21 *** empty log message ***
23 Revision 1.5 1999/05/10 08:30:29 burnsbr
26 Revision 1.4 1999/04/27 10:03:33 burnsbr
27 added configure support
29 Revision 1.3 1999/04/26 02:35:32 burnsbr
30 compression now works.. yahoo
32 Revision 1.2 1999/04/23 12:01:59 burnsbr
35 Revision 1.1 1999/04/23 11:58:25 burnsbr
42 compress.c - code for handling deflation
43 Copyright (C) 1999 Bryan Burns
45 This program is free software; you can redistribute it and/or
46 modify it under the terms of the GNU General Public License
47 as published by the Free Software Foundation; either version 2
48 of the License, or (at your option) any later version.
50 This program is distributed in the hope that it will be useful,
51 but WITHOUT ANY WARRANTY; without even the implied warranty of
52 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
53 GNU General Public License for more details.
55 You should have received a copy of the GNU General Public License
56 along with this program; if not, write to the Free Software
57 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
71 #include <sys/types.h>
78 static char rcsid
[] = "$Id: compress.c,v 1.7 2000/09/13 14:02:02 cory Exp $";
82 void init_compression(){
84 memset(&zs
, 0, sizeof(z_stream
));
90 /* Why -MAX_WBITS? zlib has an undocumented feature, where if the windowbits
91 parameter is negative, it omits the zlib header, which seems to kill
92 any other zip/unzip program. This caused me SO much pain.. */
93 if(deflateInit2(&zs
, Z_DEFAULT_COMPRESSION
, Z_DEFLATED
, -MAX_WBITS
,
94 9, Z_DEFAULT_STRATEGY
) != Z_OK
){
96 fprintf(stderr
, "Error initializing deflation!\n");
101 int compress_file(int in_fd
, int out_fd
, struct zipentry
*ze
){
103 Bytef out_buff
[RDSZ
];
104 unsigned int rdamt
, wramt
;
105 unsigned long tr
= 0;
110 zs
.next_in
= in_buff
;
112 zs
.next_out
= out_buff
;
113 zs
.avail_out
= (uInt
)RDSZ
;
115 ze
->crc
= crc32(0L, Z_NULL
, 0);
119 /* If deflate is out of input, fill the input buffer for it */
120 if(zs
.avail_in
== 0 && zs
.avail_out
> 0){
121 if((rdamt
= read(in_fd
, in_buff
, RDSZ
)) == 0)
129 /* compute the CRC while we're at it */
130 ze
->crc
= crc32(ze
->crc
, in_buff
, rdamt
);
132 /* update the total amount read sofar */
135 zs
.next_in
= in_buff
;
139 /* deflate the data */
140 if(deflate(&zs
, 0) != Z_OK
){
141 fprintf(stderr
, "Error deflating! %s:%d\n", __FILE__
, __LINE__
);
145 /* If the output buffer is full, dump it to disk */
146 if(zs
.avail_out
== 0){
148 if(write(out_fd
, out_buff
, RDSZ
) != RDSZ
){
153 /* clear the output buffer */
154 zs
.next_out
= out_buff
;
155 zs
.avail_out
= (uInt
)RDSZ
;
160 /* If we have any data waiting in the buffer after we're done with the file
162 if(zs
.avail_out
< RDSZ
){
164 wramt
= RDSZ
- zs
.avail_out
;
166 if(write(out_fd
, out_buff
, wramt
) != wramt
){
170 /* clear the output buffer */
171 zs
.next_out
= out_buff
;
172 zs
.avail_out
= (uInt
)RDSZ
;
176 /* finish deflation. This purges zlib's internal data buffers */
177 while(deflate(&zs
, Z_FINISH
) == Z_OK
){
178 wramt
= RDSZ
- zs
.avail_out
;
180 if(write(out_fd
, out_buff
, wramt
) != wramt
){
185 zs
.next_out
= out_buff
;
186 zs
.avail_out
= (uInt
)RDSZ
;
189 /* If there's any data left in the buffer, write it out */
190 if(zs
.avail_out
!= RDSZ
){
191 wramt
= RDSZ
- zs
.avail_out
;
193 if(write(out_fd
, out_buff
, wramt
) != wramt
){
199 /* update fastjar's entry information */
200 ze
->usize
= (ub4
)zs
.total_in
;
201 ze
->csize
= (ub4
)zs
.total_out
;
203 /* Reset the deflation for the next time around */
204 if(deflateReset(&zs
) != Z_OK
){
205 fprintf(stderr
, "Error resetting deflation\n");
212 void end_compression(){
215 /* Oddly enough, zlib always returns Z_DATA_ERROR if you specify no
216 zlib header. Go fig. */
217 if((rtval
= deflateEnd(&zs
)) != Z_OK
&& rtval
!= Z_DATA_ERROR
){
218 fprintf(stderr
, "Error calling deflateEnd\n");
219 fprintf(stderr
, "error: (%d) %s\n", rtval
, zs
.msg
);
225 void init_inflation(){
227 memset(&zs
, 0, sizeof(z_stream
));
233 if(inflateInit2(&zs
, -15) != Z_OK
){
234 fprintf(stderr
, "Error initializing deflation!\n");
240 int inflate_file(pb_file
*pbf
, int out_fd
, struct zipentry
*ze
){
242 Bytef out_buff
[RDSZ
];
249 crc
= crc32(crc
, NULL
, 0); /* initialize crc */
251 /* loop until we've consumed all the compressed data */
254 if(zs
.avail_in
== 0){
255 if((rdamt
= pb_read(pbf
, in_buff
, RDSZ
)) == 0)
263 printf("%d bytes read\n", rdamt
);
266 zs
.next_in
= in_buff
;
270 zs
.next_out
= out_buff
;
273 if((rtval
= inflate(&zs
, 0)) != Z_OK
){
274 if(rtval
== Z_STREAM_END
){
276 printf("end of stream\n");
278 if(zs
.avail_out
!= RDSZ
){
279 crc
= crc32(crc
, out_buff
, (RDSZ
- zs
.avail_out
));
282 if(write(out_fd
, out_buff
, (RDSZ
- zs
.avail_out
)) !=
283 (RDSZ
- zs
.avail_out
)){
291 fprintf(stderr
, "Error inflating file! (%d)\n", rtval
);
295 if(zs
.avail_out
!= RDSZ
){
296 crc
= crc32(crc
, out_buff
, (RDSZ
- zs
.avail_out
));
299 if(write(out_fd
, out_buff
, (RDSZ
- zs
.avail_out
)) !=
300 (RDSZ
- zs
.avail_out
)){
304 zs
.next_out
= out_buff
;
310 printf("done inflating\n");
314 printf("%d bytes left over\n", zs
.avail_in
);
318 printf("CRC is %x\n", crc
);
323 pb_push(pbf
, zs
.next_in
, zs
.avail_in
);
325 ze
->usize
= zs
.total_out
;
332 Function name: report_str_error
333 args: val Error code returned from zlib.
334 purpose: Put out an error message corresponding to error code returned from zlib.
335 Be suitably cryptic seeing I don't really know exactly what these errors mean.
338 void report_str_error(int val
) {
343 fprintf(stderr
, "Need a dictionary?\n");
346 fprintf(stderr
, "Z_DATA_ERROR\n");
349 fprintf(stderr
, "Z_STREAM_ERROR\n");
352 fprintf(stderr
, "Z_MEM_ERROR\n");
355 fprintf(stderr
, "Z_BUF_ERROR\n");
360 fprintf(stderr
, "Unknown behavior from inflate\n");
366 Function name: ez_inflate_str
367 args: pbf Pointer to pushback handle for file.
368 csize Compressed size of embedded file.
369 usize Uncompressed size of embedded file.
370 purpose: Read in and decompress the contents of an embedded file and store it in a
372 returns: Byte array of uncompressed embedded file.
375 static Bytef
*ez_inflate_str(pb_file
*pbf
, ub4 csize
, ub4 usize
) {
381 if(zs
.next_in
= in_buff
= (Bytef
*) malloc(csize
)) {
382 if(zs
.next_out
= out_buff
= (Bytef
*) malloc(usize
+ 1)) {
383 if((rdamt
= pb_read(pbf
, zs
.next_in
, csize
)) == csize
) {
385 zs
.avail_out
= usize
;
386 report_str_error(inflate(&zs
, 0));
389 out_buff
[usize
] = '\0';
392 fprintf(stderr
, "Read failed on input file.\n");
393 fprintf(stderr
, "Tried to read %u but read %u instead.\n", csize
, rdamt
);
400 fprintf(stderr
, "Malloc of out_buff failed.\n");
401 fprintf(stderr
, "Error: %s\n", strerror(errno
));
407 fprintf(stderr
, "Malloc of in_buff failed.\n");
408 fprintf(stderr
, "Error: %s\n", strerror(errno
));
416 Function name: hrd_inflate_str
417 args: pbf Pointer to pushback handle for file.
418 csize Pointer to compressed size of embedded file.
419 usize Pointer to uncompressed size of embedded file.
420 purpose: Read and decompress an embedded file into a string. Set csize and usize
421 accordingly. This function does the reading for us in the case there is not size
422 information in the header for the embedded file.
423 returns: Byte array of the contents of the embedded file.
426 static Bytef
*hrd_inflate_str(pb_file
*pbf
, ub4
*csize
, ub4
*usize
) {
438 while(zret
!= Z_STREAM_END
&& (rdamt
= pb_read(pbf
, in_buff
, RDSZ
)))
442 zs
.next_in
= in_buff
;
444 if(tmp
= (Bytef
*) realloc(out_buff
, (RDSZ
* i
) + 1)) {
446 zs
.next_out
= &(out_buff
[(RDSZ
* (i
- 1)) - zs
.avail_out
]);
447 zs
.avail_out
+= RDSZ
;
451 fprintf(stderr
, "Realloc of out_buff failed.\n");
452 fprintf(stderr
, "Error: %s\n", strerror(errno
));
455 } while((zret
= inflate(&zs
, 0)) == Z_OK
);
456 report_str_error(zret
);
458 pb_push(pbf
, zs
.next_in
, zs
.avail_in
);
460 out_buff
[(RDSZ
* (i
- 1)) - zs
.avail_out
] = '\0';
461 *usize
= zs
.total_out
;
462 *csize
= zs
.total_in
;
470 Function name: inflate_string
471 args: pbf Pointer to pushback handle for file.
472 csize Pointer to compressed size of embedded file. May be 0 if not set.
473 usize Pointer to uncompressed size of embedded file. May be 0 if not set.
474 purpose: Decide the easiest (in computer terms) methos of decompressing this embedded
476 returns: Pointer to a string containing the decompressed contents of the embedded file.
477 If csize and usize are not set set them to correct numbers.
480 Bytef
*inflate_string(pb_file
*pbf
, ub4
*csize
, ub4
*usize
) {
483 if(*csize
&& *usize
) ret_buf
= ez_inflate_str(pbf
, *csize
, *usize
);
484 else ret_buf
= hrd_inflate_str(pbf
, csize
, usize
);