"Fossies" - the Fresh Open Source Software Archive

Member "cfitsio-4.0.0/zcompress.c" (20 May 2021, 18946 Bytes) of package /linux/misc/cfitsio-4.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "zcompress.c" see the Fossies "Dox" file reference documentation.

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