1 /* $Id: compress.c,v 1.1 2000/12/09 03:08:23 apbianco Exp $
4 Revision 1.1 2000/12/09 03:08:23 apbianco
5 2000-12-08 Alexandre Petit-Bianco <apbianco@cygnus.com>
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
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.
17 Revision 1.1.1.1 1999/12/06 03:09:16 toast
22 Revision 1.7 1999/05/10 08:50:05 burnsbr
23 *** empty log message ***
25 Revision 1.6 1999/05/10 08:38:44 burnsbr
26 *** empty log message ***
28 Revision 1.5 1999/05/10 08:30:29 burnsbr
31 Revision 1.4 1999/04/27 10:03:33 burnsbr
32 added configure support
34 Revision 1.3 1999/04/26 02:35:32 burnsbr
35 compression now works.. yahoo
37 Revision 1.2 1999/04/23 12:01:59 burnsbr
40 Revision 1.1 1999/04/23 11:58:25 burnsbr
47 compress.c - code for handling deflation
48 Copyright (C) 1999 Bryan Burns
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.
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.
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.
79 #include <sys/types.h>
89 void init_compression(){
91 memset(&zs
, 0, sizeof(z_stream
));
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
){
103 fprintf(stderr
, "Error initializing deflation!\n");
108 int compress_file(int in_fd
, int out_fd
, struct zipentry
*ze
){
110 Bytef out_buff
[RDSZ
];
111 unsigned int rdamt
, wramt
;
112 unsigned long tr
= 0;
117 zs
.next_in
= in_buff
;
119 zs
.next_out
= out_buff
;
120 zs
.avail_out
= (uInt
)RDSZ
;
122 ze
->crc
= crc32(0L, Z_NULL
, 0);
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)
136 /* compute the CRC while we're at it */
137 ze
->crc
= crc32(ze
->crc
, in_buff
, rdamt
);
139 /* update the total amount read sofar */
142 zs
.next_in
= in_buff
;
146 /* deflate the data */
147 if(deflate(&zs
, 0) != Z_OK
){
148 fprintf(stderr
, "Error deflating! %s:%d\n", __FILE__
, __LINE__
);
152 /* If the output buffer is full, dump it to disk */
153 if(zs
.avail_out
== 0){
155 if(write(out_fd
, out_buff
, RDSZ
) != RDSZ
){
160 /* clear the output buffer */
161 zs
.next_out
= out_buff
;
162 zs
.avail_out
= (uInt
)RDSZ
;
167 /* If we have any data waiting in the buffer after we're done with the file
169 if(zs
.avail_out
< RDSZ
){
171 wramt
= RDSZ
- zs
.avail_out
;
173 if(write(out_fd
, out_buff
, wramt
) != wramt
){
177 /* clear the output buffer */
178 zs
.next_out
= out_buff
;
179 zs
.avail_out
= (uInt
)RDSZ
;
183 /* finish deflation. This purges zlib's internal data buffers */
184 while(deflate(&zs
, Z_FINISH
) == Z_OK
){
185 wramt
= RDSZ
- zs
.avail_out
;
187 if(write(out_fd
, out_buff
, wramt
) != wramt
){
192 zs
.next_out
= out_buff
;
193 zs
.avail_out
= (uInt
)RDSZ
;
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
;
200 if(write(out_fd
, out_buff
, wramt
) != wramt
){
206 /* update fastjar's entry information */
207 ze
->usize
= (ub4
)zs
.total_in
;
208 ze
->csize
= (ub4
)zs
.total_out
;
210 /* Reset the deflation for the next time around */
211 if(deflateReset(&zs
) != Z_OK
){
212 fprintf(stderr
, "Error resetting deflation\n");
219 void end_compression(){
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
);
232 void init_inflation(){
234 memset(&zs
, 0, sizeof(z_stream
));
240 if(inflateInit2(&zs
, -15) != Z_OK
){
241 fprintf(stderr
, "Error initializing deflation!\n");
247 int inflate_file(pb_file
*pbf
, int out_fd
, struct zipentry
*ze
){
249 Bytef out_buff
[RDSZ
];
256 crc
= crc32(crc
, NULL
, 0); /* initialize crc */
258 /* loop until we've consumed all the compressed data */
261 if(zs
.avail_in
== 0){
262 if((rdamt
= pb_read(pbf
, in_buff
, RDSZ
)) == 0)
270 printf("%d bytes read\n", rdamt
);
273 zs
.next_in
= in_buff
;
277 zs
.next_out
= out_buff
;
280 if((rtval
= inflate(&zs
, 0)) != Z_OK
){
281 if(rtval
== Z_STREAM_END
){
283 printf("end of stream\n");
285 if(zs
.avail_out
!= RDSZ
){
286 crc
= crc32(crc
, out_buff
, (RDSZ
- zs
.avail_out
));
289 if(write(out_fd
, out_buff
, (RDSZ
- zs
.avail_out
)) !=
290 (RDSZ
- zs
.avail_out
)){
298 fprintf(stderr
, "Error inflating file! (%d)\n", rtval
);
302 if(zs
.avail_out
!= RDSZ
){
303 crc
= crc32(crc
, out_buff
, (RDSZ
- zs
.avail_out
));
306 if(write(out_fd
, out_buff
, (RDSZ
- zs
.avail_out
)) !=
307 (RDSZ
- zs
.avail_out
)){
311 zs
.next_out
= out_buff
;
317 printf("done inflating\n");
321 printf("%d bytes left over\n", zs
.avail_in
);
325 printf("CRC is %x\n", crc
);
330 pb_push(pbf
, zs
.next_in
, zs
.avail_in
);
332 ze
->usize
= zs
.total_out
;
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.
345 static void report_str_error(int val
) {
350 fprintf(stderr
, "Need a dictionary?\n");
353 fprintf(stderr
, "Z_DATA_ERROR\n");
356 fprintf(stderr
, "Z_STREAM_ERROR\n");
359 fprintf(stderr
, "Z_MEM_ERROR\n");
362 fprintf(stderr
, "Z_BUF_ERROR\n");
367 fprintf(stderr
, "Unknown behavior from inflate\n");
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
379 returns: Byte array of uncompressed embedded file.
382 static Bytef
*ez_inflate_str(pb_file
*pbf
, ub4 csize
, ub4 usize
) {
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
) {
391 zs
.avail_out
= usize
;
392 report_str_error(inflate(&zs
, 0));
395 out_buff
[usize
] = '\0';
398 fprintf(stderr
, "Read failed on input file.\n");
399 fprintf(stderr
, "Tried to read %u but read %u instead.\n", csize
, rdamt
);
406 fprintf(stderr
, "Malloc of out_buff failed.\n");
407 fprintf(stderr
, "Error: %s\n", strerror(errno
));
413 fprintf(stderr
, "Malloc of in_buff failed.\n");
414 fprintf(stderr
, "Error: %s\n", strerror(errno
));
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.
432 static Bytef
*hrd_inflate_str(pb_file
*pbf
, ub4
*csize
, ub4
*usize
) {
443 while(zret
!= Z_STREAM_END
&& (rdamt
= pb_read(pbf
, in_buff
, RDSZ
)))
447 zs
.next_in
= in_buff
;
449 if((tmp
= (Bytef
*) realloc(out_buff
, (RDSZ
* i
) + 1))) {
451 zs
.next_out
= &(out_buff
[(RDSZ
* (i
- 1)) - zs
.avail_out
]);
452 zs
.avail_out
+= RDSZ
;
456 fprintf(stderr
, "Realloc of out_buff failed.\n");
457 fprintf(stderr
, "Error: %s\n", strerror(errno
));
460 } while((zret
= inflate(&zs
, 0)) == Z_OK
);
461 report_str_error(zret
);
463 pb_push(pbf
, zs
.next_in
, zs
.avail_in
);
465 out_buff
[(RDSZ
* (i
- 1)) - zs
.avail_out
] = '\0';
466 *usize
= zs
.total_out
;
467 *csize
= zs
.total_in
;
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
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.
485 Bytef
*inflate_string(pb_file
*pbf
, ub4
*csize
, ub4
*usize
) {
488 if(*csize
&& *usize
) ret_buf
= ez_inflate_str(pbf
, *csize
, *usize
);
489 else ret_buf
= hrd_inflate_str(pbf
, csize
, usize
);