1 #include <stdio.h>
2 #include <errno.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "zlib.h"
6
7 #define GZBUFSIZE 115200 /* 40 FITS blocks */
8 #define BUFFINCR 28800 /* 10 FITS blocks */
9
10 /* prototype for the following functions */
11 int uncompress2mem(char *filename,
12 FILE *diskfile,
13 char **buffptr,
14 size_t *buffsize,
15 void *(*mem_realloc)(void *p, size_t newsize),
16 size_t *filesize,
17 int *status);
18
19 int uncompress2mem_from_mem(
20 char *inmemptr,
21 size_t inmemsize,
22 char **buffptr,
23 size_t *buffsize,
24 void *(*mem_realloc)(void *p, size_t newsize),
25 size_t *filesize,
26 int *status);
27
28 int uncompress2file(char *filename,
29 FILE *indiskfile,
30 FILE *outdiskfile,
31 int *status);
32
33
34 int compress2mem_from_mem(
35 char *inmemptr,
36 size_t inmemsize,
37 char **buffptr,
38 size_t *buffsize,
39 void *(*mem_realloc)(void *p, size_t newsize),
40 size_t *filesize,
41 int *status);
42
43 int compress2file_from_mem(
44 char *inmemptr,
45 size_t inmemsize,
46 FILE *outdiskfile,
47 size_t *filesize, /* O - size of file, in bytes */
48 int *status);
49
50
51 /*--------------------------------------------------------------------------*/
uncompress2mem(char * filename,FILE * diskfile,char ** buffptr,size_t * buffsize,void * (* mem_realloc)(void * p,size_t newsize),size_t * filesize,int * status)52 int uncompress2mem(char *filename, /* name of input file */
53 FILE *diskfile, /* I - file pointer */
54 char **buffptr, /* IO - memory pointer */
55 size_t *buffsize, /* IO - size of buffer, in bytes */
56 void *(*mem_realloc)(void *p, size_t newsize), /* function */
57 size_t *filesize, /* O - size of file, in bytes */
58 int *status) /* IO - error status */
59
60 /*
61 Uncompress the disk file into memory. Fill whatever amount of memory has
62 already been allocated, then realloc more memory, using the supplied
63 input function, if necessary.
64 */
65 {
66 int err, len;
67 char *filebuff;
68 z_stream d_stream; /* decompression stream */
69
70 if (*status > 0)
71 return(*status);
72
73 /* Allocate memory to hold compressed bytes read from the file. */
74 filebuff = (char*)malloc(GZBUFSIZE);
75 if (!filebuff) return(*status = 113); /* memory error */
76
77 d_stream.zalloc = (alloc_func)0;
78 d_stream.zfree = (free_func)0;
79 d_stream.opaque = (voidpf)0;
80 d_stream.next_out = (unsigned char*) *buffptr;
81 d_stream.avail_out = *buffsize;
82
83 /* Initialize the decompression. The argument (15+16) tells the
84 decompressor that we are to use the gzip algorithm */
85
86 err = inflateInit2(&d_stream, (15+16));
87 if (err != Z_OK) return(*status = 414);
88
89 /* loop through the file, reading a buffer and uncompressing it */
90 for (;;)
91 {
92 len = fread(filebuff, 1, GZBUFSIZE, diskfile);
93 if (ferror(diskfile)) {
94 inflateEnd(&d_stream);
95 free(filebuff);
96 return(*status = 414);
97 }
98
99 if (len == 0) break; /* no more data */
100
101 d_stream.next_in = (unsigned char*)filebuff;
102 d_stream.avail_in = len;
103
104 for (;;) {
105 /* uncompress as much of the input as will fit in the output */
106 err = inflate(&d_stream, Z_NO_FLUSH);
107
108 if (err == Z_STREAM_END ) { /* We reached the end of the input */
109 break;
110 } else if (err == Z_OK ) {
111
112 if (!d_stream.avail_in) break; /* need more input */
113
114 /* need more space in output buffer */
115 if (mem_realloc) {
116 *buffptr = mem_realloc(*buffptr,*buffsize + BUFFINCR);
117 if (*buffptr == NULL){
118 inflateEnd(&d_stream);
119 free(filebuff);
120 return(*status = 414); /* memory allocation failed */
121 }
122
123 d_stream.avail_out = BUFFINCR;
124 d_stream.next_out = (unsigned char*) (*buffptr + *buffsize);
125 *buffsize = *buffsize + BUFFINCR;
126 } else { /* error: no realloc function available */
127 inflateEnd(&d_stream);
128 free(filebuff);
129 return(*status = 414);
130 }
131 } else { /* some other error */
132 inflateEnd(&d_stream);
133 free(filebuff);
134 return(*status = 414);
135 }
136 }
137
138 if (feof(diskfile)) break;
139
140 d_stream.next_out = (unsigned char*) (*buffptr + d_stream.total_out);
141 d_stream.avail_out = *buffsize - d_stream.total_out;
142 }
143
144 /* Set the output file size to be the total output data */
145 *filesize = d_stream.total_out;
146
147 free(filebuff); /* free temporary output data buffer */
148
149 err = inflateEnd(&d_stream); /* End the decompression */
150 if (err != Z_OK) return(*status = 414);
151
152 return(*status);
153 }
154 /*--------------------------------------------------------------------------*/
uncompress2mem_from_mem(char * inmemptr,size_t inmemsize,char ** buffptr,size_t * buffsize,void * (* mem_realloc)(void * p,size_t newsize),size_t * filesize,int * status)155 int uncompress2mem_from_mem(
156 char *inmemptr, /* I - memory pointer to compressed bytes */
157 size_t inmemsize, /* I - size of input compressed file */
158 char **buffptr, /* IO - memory pointer */
159 size_t *buffsize, /* IO - size of buffer, in bytes */
160 void *(*mem_realloc)(void *p, size_t newsize), /* function */
161 size_t *filesize, /* O - size of file, in bytes */
162 int *status) /* IO - error status */
163
164 /*
165 Uncompress the file in memory into memory. Fill whatever amount of memory has
166 already been allocated, then realloc more memory, using the supplied
167 input function, if necessary.
168 */
169 {
170 int err;
171 z_stream d_stream; /* decompression stream */
172
173 if (*status > 0)
174 return(*status);
175
176 d_stream.zalloc = (alloc_func)0;
177 d_stream.zfree = (free_func)0;
178 d_stream.opaque = (voidpf)0;
179
180 /* Initialize the decompression. The argument (15+16) tells the
181 decompressor that we are to use the gzip algorithm */
182 err = inflateInit2(&d_stream, (15+16));
183 if (err != Z_OK) return(*status = 414);
184
185 d_stream.next_in = (unsigned char*)inmemptr;
186 d_stream.avail_in = inmemsize;
187
188 d_stream.next_out = (unsigned char*) *buffptr;
189 d_stream.avail_out = *buffsize;
190
191 for (;;) {
192 /* uncompress as much of the input as will fit in the output */
193 err = inflate(&d_stream, Z_NO_FLUSH);
194
195 if (err == Z_STREAM_END) { /* We reached the end of the input */
196 break;
197 } else if (err == Z_OK ) { /* need more space in output buffer */
198
199 if (mem_realloc) {
200 *buffptr = mem_realloc(*buffptr,*buffsize + BUFFINCR);
201 if (*buffptr == NULL){
202 inflateEnd(&d_stream);
203 return(*status = 414); /* memory allocation failed */
204 }
205
206 d_stream.avail_out = BUFFINCR;
207 d_stream.next_out = (unsigned char*) (*buffptr + *buffsize);
208 *buffsize = *buffsize + BUFFINCR;
209
210 } else { /* error: no realloc function available */
211 inflateEnd(&d_stream);
212 return(*status = 414);
213 }
214 } else { /* some other error */
215 inflateEnd(&d_stream);
216 return(*status = 414);
217 }
218 }
219
220 /* Set the output file size to be the total output data */
221 if (filesize) *filesize = d_stream.total_out;
222
223 /* End the decompression */
224 err = inflateEnd(&d_stream);
225
226 if (err != Z_OK) return(*status = 414);
227
228 return(*status);
229 }
230 /*--------------------------------------------------------------------------*/
uncompress2file(char * filename,FILE * indiskfile,FILE * outdiskfile,int * status)231 int uncompress2file(char *filename, /* name of input file */
232 FILE *indiskfile, /* I - input file pointer */
233 FILE *outdiskfile, /* I - output file pointer */
234 int *status) /* IO - error status */
235 /*
236 Uncompress the file into another file.
237 */
238 {
239 int err, len;
240 unsigned long bytes_out = 0;
241 char *infilebuff, *outfilebuff;
242 z_stream d_stream; /* decompression stream */
243
244 if (*status > 0)
245 return(*status);
246
247 /* Allocate buffers to hold compressed and uncompressed */
248 infilebuff = (char*)malloc(GZBUFSIZE);
249 if (!infilebuff) return(*status = 113); /* memory error */
250
251 outfilebuff = (char*)malloc(GZBUFSIZE);
252 if (!outfilebuff) return(*status = 113); /* memory error */
253
254 d_stream.zalloc = (alloc_func)0;
255 d_stream.zfree = (free_func)0;
256 d_stream.opaque = (voidpf)0;
257
258 d_stream.next_out = (unsigned char*) outfilebuff;
259 d_stream.avail_out = GZBUFSIZE;
260
261 /* Initialize the decompression. The argument (15+16) tells the
262 decompressor that we are to use the gzip algorithm */
263
264 err = inflateInit2(&d_stream, (15+16));
265 if (err != Z_OK) return(*status = 414);
266
267 /* loop through the file, reading a buffer and uncompressing it */
268 for (;;)
269 {
270 len = fread(infilebuff, 1, GZBUFSIZE, indiskfile);
271 if (ferror(indiskfile)) {
272 inflateEnd(&d_stream);
273 free(infilebuff);
274 free(outfilebuff);
275 return(*status = 414);
276 }
277
278 if (len == 0) break; /* no more data */
279
280 d_stream.next_in = (unsigned char*)infilebuff;
281 d_stream.avail_in = len;
282
283 for (;;) {
284 /* uncompress as much of the input as will fit in the output */
285 err = inflate(&d_stream, Z_NO_FLUSH);
286
287 if (err == Z_STREAM_END ) { /* We reached the end of the input */
288 break;
289 } else if (err == Z_OK ) {
290
291 if (!d_stream.avail_in) break; /* need more input */
292
293 /* flush out the full output buffer */
294 if ((int)fwrite(outfilebuff, 1, GZBUFSIZE, outdiskfile) != GZBUFSIZE) {
295 inflateEnd(&d_stream);
296 free(infilebuff);
297 free(outfilebuff);
298 return(*status = 414);
299 }
300 bytes_out += GZBUFSIZE;
301 d_stream.next_out = (unsigned char*) outfilebuff;
302 d_stream.avail_out = GZBUFSIZE;
303
304 } else { /* some other error */
305 inflateEnd(&d_stream);
306 free(infilebuff);
307 free(outfilebuff);
308 return(*status = 414);
309 }
310 }
311
312 if (feof(indiskfile)) break;
313 }
314
315 /* write out any remaining bytes in the buffer */
316 if (d_stream.total_out > bytes_out) {
317 if ((int)fwrite(outfilebuff, 1, (d_stream.total_out - bytes_out), outdiskfile)
318 != (d_stream.total_out - bytes_out)) {
319 inflateEnd(&d_stream);
320 free(infilebuff);
321 free(outfilebuff);
322 return(*status = 414);
323 }
324 }
325
326 free(infilebuff); /* free temporary output data buffer */
327 free(outfilebuff); /* free temporary output data buffer */
328
329 err = inflateEnd(&d_stream); /* End the decompression */
330 if (err != Z_OK) return(*status = 414);
331
332 return(*status);
333 }
334 /*--------------------------------------------------------------------------*/
compress2mem_from_mem(char * inmemptr,size_t inmemsize,char ** buffptr,size_t * buffsize,void * (* mem_realloc)(void * p,size_t newsize),size_t * filesize,int * status)335 int compress2mem_from_mem(
336 char *inmemptr, /* I - memory pointer to uncompressed bytes */
337 size_t inmemsize, /* I - size of input uncompressed file */
338 char **buffptr, /* IO - memory pointer for compressed file */
339 size_t *buffsize, /* IO - size of buffer, in bytes */
340 void *(*mem_realloc)(void *p, size_t newsize), /* function */
341 size_t *filesize, /* O - size of file, in bytes */
342 int *status) /* IO - error status */
343
344 /*
345 Compress the file into memory. Fill whatever amount of memory has
346 already been allocated, then realloc more memory, using the supplied
347 input function, if necessary.
348 */
349 {
350 int err;
351 z_stream c_stream; /* compression stream */
352
353 if (*status > 0)
354 return(*status);
355
356 c_stream.zalloc = (alloc_func)0;
357 c_stream.zfree = (free_func)0;
358 c_stream.opaque = (voidpf)0;
359
360 /* Initialize the compression. The argument (15+16) tells the
361 compressor that we are to use the gzip algorythm.
362 Also use Z_BEST_SPEED for maximum speed with very minor loss
363 in compression factor. */
364 err = deflateInit2(&c_stream, Z_BEST_SPEED, Z_DEFLATED,
365 (15+16), 8, Z_DEFAULT_STRATEGY);
366
367 if (err != Z_OK) return(*status = 413);
368
369 c_stream.next_in = (unsigned char*)inmemptr;
370 c_stream.avail_in = inmemsize;
371
372 c_stream.next_out = (unsigned char*) *buffptr;
373 c_stream.avail_out = *buffsize;
374
375 for (;;) {
376 /* compress as much of the input as will fit in the output */
377 err = deflate(&c_stream, Z_FINISH);
378
379 if (err == Z_STREAM_END) { /* We reached the end of the input */
380 break;
381 } else if (err == Z_OK ) { /* need more space in output buffer */
382
383 if (mem_realloc) {
384 *buffptr = mem_realloc(*buffptr,*buffsize + BUFFINCR);
385 if (*buffptr == NULL){
386 deflateEnd(&c_stream);
387 return(*status = 413); /* memory allocation failed */
388 }
389
390 c_stream.avail_out = BUFFINCR;
391 c_stream.next_out = (unsigned char*) (*buffptr + *buffsize);
392 *buffsize = *buffsize + BUFFINCR;
393
394 } else { /* error: no realloc function available */
395 deflateEnd(&c_stream);
396 return(*status = 413);
397 }
398 } else { /* some other error */
399 deflateEnd(&c_stream);
400 return(*status = 413);
401 }
402 }
403
404 /* Set the output file size to be the total output data */
405 if (filesize) *filesize = c_stream.total_out;
406
407 /* End the compression */
408 err = deflateEnd(&c_stream);
409
410 if (err != Z_OK) return(*status = 413);
411
412 return(*status);
413 }
414 /*--------------------------------------------------------------------------*/
compress2file_from_mem(char * inmemptr,size_t inmemsize,FILE * outdiskfile,size_t * filesize,int * status)415 int compress2file_from_mem(
416 char *inmemptr, /* I - memory pointer to uncompressed bytes */
417 size_t inmemsize, /* I - size of input uncompressed file */
418 FILE *outdiskfile,
419 size_t *filesize, /* O - size of file, in bytes */
420 int *status)
421
422 /*
423 Compress the memory file into disk file.
424 */
425 {
426 int err;
427 unsigned long bytes_out = 0;
428 char *outfilebuff;
429 z_stream c_stream; /* compression stream */
430
431 if (*status > 0)
432 return(*status);
433
434 /* Allocate buffer to hold compressed bytes */
435 outfilebuff = (char*)malloc(GZBUFSIZE);
436 if (!outfilebuff) return(*status = 113); /* memory error */
437
438 c_stream.zalloc = (alloc_func)0;
439 c_stream.zfree = (free_func)0;
440 c_stream.opaque = (voidpf)0;
441
442 /* Initialize the compression. The argument (15+16) tells the
443 compressor that we are to use the gzip algorythm.
444 Also use Z_BEST_SPEED for maximum speed with very minor loss
445 in compression factor. */
446 err = deflateInit2(&c_stream, Z_BEST_SPEED, Z_DEFLATED,
447 (15+16), 8, Z_DEFAULT_STRATEGY);
448
449 if (err != Z_OK) return(*status = 413);
450
451 c_stream.next_in = (unsigned char*)inmemptr;
452 c_stream.avail_in = inmemsize;
453
454 c_stream.next_out = (unsigned char*) outfilebuff;
455 c_stream.avail_out = GZBUFSIZE;
456
457 for (;;) {
458 /* compress as much of the input as will fit in the output */
459 err = deflate(&c_stream, Z_FINISH);
460
461 if (err == Z_STREAM_END) { /* We reached the end of the input */
462 break;
463 } else if (err == Z_OK ) { /* need more space in output buffer */
464
465 /* flush out the full output buffer */
466 if ((int)fwrite(outfilebuff, 1, GZBUFSIZE, outdiskfile) != GZBUFSIZE) {
467 deflateEnd(&c_stream);
468 free(outfilebuff);
469 return(*status = 413);
470 }
471 bytes_out += GZBUFSIZE;
472 c_stream.next_out = (unsigned char*) outfilebuff;
473 c_stream.avail_out = GZBUFSIZE;
474
475
476 } else { /* some other error */
477 deflateEnd(&c_stream);
478 free(outfilebuff);
479 return(*status = 413);
480 }
481 }
482
483 /* write out any remaining bytes in the buffer */
484 if (c_stream.total_out > bytes_out) {
485 if ((int)fwrite(outfilebuff, 1, (c_stream.total_out - bytes_out), outdiskfile)
486 != (c_stream.total_out - bytes_out)) {
487 deflateEnd(&c_stream);
488 free(outfilebuff);
489 return(*status = 413);
490 }
491 }
492
493 free(outfilebuff); /* free temporary output data buffer */
494
495 /* Set the output file size to be the total output data */
496 if (filesize) *filesize = c_stream.total_out;
497
498 /* End the compression */
499 err = deflateEnd(&c_stream);
500
501 if (err != Z_OK) return(*status = 413);
502
503 return(*status);
504 }
505