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