Skip to content
Snippets Groups Projects
bzlib.c 42.6 KiB
Newer Older
  • Learn to ignore specific revisions
  •    BZ_SETERR(BZ_OK);
       if (bzf == NULL || buf == NULL || len < 0)
          { BZ_SETERR(BZ_PARAM_ERROR); return; };
       if (!(bzf->writing))
          { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
       if (ferror(bzf->handle))
          { BZ_SETERR(BZ_IO_ERROR); return; };
    
       if (len == 0)
          { BZ_SETERR(BZ_OK); return; };
    
       bzf->strm.avail_in = len;
       bzf->strm.next_in  = buf;
    
       while (True) {
          bzf->strm.avail_out = BZ_MAX_UNUSED;
          bzf->strm.next_out = bzf->buf;
          ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
          if (ret != BZ_RUN_OK)
    
    	 { BZ_SETERR(ret); return; };
    
    
          if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
    
    	 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
    	 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
    		       n, bzf->handle );
    	 if (n != n2 || ferror(bzf->handle))
    	    { BZ_SETERR(BZ_IO_ERROR); return; };
    
          }
    
          if (bzf->strm.avail_in == 0)
    
    	 { BZ_SETERR(BZ_OK); return; };
    
       }
    }
    
    
    /*---------------------------------------------------*/
    void BZ_API(BZ2_bzWriteClose)
    
    		  ( int*          bzerror,
    		    BZFILE*       b,
    		    int           abandon,
    		    unsigned int* nbytes_in,
    		    unsigned int* nbytes_out )
    
    {
       BZ2_bzWriteClose64 ( bzerror, b, abandon,
    
    			nbytes_in, NULL, nbytes_out, NULL );
    
    }
    
    
    void BZ_API(BZ2_bzWriteClose64)
    
    		  ( int*          bzerror,
    		    BZFILE*       b,
    		    int           abandon,
    		    unsigned int* nbytes_in_lo32,
    		    unsigned int* nbytes_in_hi32,
    		    unsigned int* nbytes_out_lo32,
    		    unsigned int* nbytes_out_hi32 )
    
    {
       Int32   n, n2, ret;
       bzFile* bzf = (bzFile*)b;
    
       if (bzf == NULL)
          { BZ_SETERR(BZ_OK); return; };
       if (!(bzf->writing))
          { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
       if (ferror(bzf->handle))
          { BZ_SETERR(BZ_IO_ERROR); return; };
    
       if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
       if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
       if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
       if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
    
       if ((!abandon) && bzf->lastErr == BZ_OK) {
          while (True) {
    
    	 bzf->strm.avail_out = BZ_MAX_UNUSED;
    	 bzf->strm.next_out = bzf->buf;
    	 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
    	 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
    	    { BZ_SETERR(ret); return; };
    
    	 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
    	    n = BZ_MAX_UNUSED - bzf->strm.avail_out;
    	    n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
    			  n, bzf->handle );
    	    if (n != n2 || ferror(bzf->handle))
    	       { BZ_SETERR(BZ_IO_ERROR); return; };
    	 }
    
    	 if (ret == BZ_STREAM_END) break;
    
          }
       }
    
       if ( !abandon && !ferror ( bzf->handle ) ) {
          fflush ( bzf->handle );
          if (ferror(bzf->handle))
    
    	 { BZ_SETERR(BZ_IO_ERROR); return; };
    
       }
    
       if (nbytes_in_lo32 != NULL)
          *nbytes_in_lo32 = bzf->strm.total_in_lo32;
       if (nbytes_in_hi32 != NULL)
          *nbytes_in_hi32 = bzf->strm.total_in_hi32;
       if (nbytes_out_lo32 != NULL)
          *nbytes_out_lo32 = bzf->strm.total_out_lo32;
       if (nbytes_out_hi32 != NULL)
          *nbytes_out_hi32 = bzf->strm.total_out_hi32;
    
       BZ_SETERR(BZ_OK);
       BZ2_bzCompressEnd ( &(bzf->strm) );
       free ( bzf );
    }
    
    
    /*---------------------------------------------------*/
    BZFILE* BZ_API(BZ2_bzReadOpen)
    
    		   ( int*  bzerror,
    		     FILE* f,
    		     int   verbosity,
    		     int   small,
    		     void* unused,
    		     int   nUnused )
    
    {
       bzFile* bzf = NULL;
       int     ret;
    
       BZ_SETERR(BZ_OK);
    
       if (f == NULL ||
           (small != 0 && small != 1) ||
           (verbosity < 0 || verbosity > 4) ||
           (unused == NULL && nUnused != 0) ||
           (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
          { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
    
       if (ferror(f))
          { BZ_SETERR(BZ_IO_ERROR); return NULL; };
    
       bzf = malloc ( sizeof(bzFile) );
       if (bzf == NULL)
          { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
    
       BZ_SETERR(BZ_OK);
    
       bzf->initialisedOk = False;
       bzf->handle        = f;
       bzf->bufN          = 0;
       bzf->writing       = False;
       bzf->strm.bzalloc  = NULL;
       bzf->strm.bzfree   = NULL;
       bzf->strm.opaque   = NULL;
    
       while (nUnused > 0) {
          bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
          unused = ((void*)( 1 + ((UChar*)(unused))  ));
          nUnused--;
       }
    
       ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
       if (ret != BZ_OK)
          { BZ_SETERR(ret); free(bzf); return NULL; };
    
       bzf->strm.avail_in = bzf->bufN;
       bzf->strm.next_in  = bzf->buf;
    
       bzf->initialisedOk = True;
       return bzf;
    }
    
    
    /*---------------------------------------------------*/
    void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
    {
       bzFile* bzf = (bzFile*)b;
    
       BZ_SETERR(BZ_OK);
       if (bzf == NULL)
          { BZ_SETERR(BZ_OK); return; };
    
       if (bzf->writing)
          { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
    
       if (bzf->initialisedOk)
          (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
       free ( bzf );
    }
    
    
    /*---------------------------------------------------*/
    int BZ_API(BZ2_bzRead)
    
    	   ( int*    bzerror,
    	     BZFILE* b,
    	     void*   buf,
    	     int     len )
    
    {
       Int32   n, ret;
       bzFile* bzf = (bzFile*)b;
    
       BZ_SETERR(BZ_OK);
    
       if (bzf == NULL || buf == NULL || len < 0)
          { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
    
       if (bzf->writing)
          { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
    
       if (len == 0)
          { BZ_SETERR(BZ_OK); return 0; };
    
       bzf->strm.avail_out = len;
       bzf->strm.next_out = buf;
    
       while (True) {
    
          if (ferror(bzf->handle))
    
    	 { BZ_SETERR(BZ_IO_ERROR); return 0; };
    
    
          if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
    
    	 n = fread ( bzf->buf, sizeof(UChar),
    		     BZ_MAX_UNUSED, bzf->handle );
    	 if (ferror(bzf->handle))
    	    { BZ_SETERR(BZ_IO_ERROR); return 0; };
    	 bzf->bufN = n;
    	 bzf->strm.avail_in = bzf->bufN;
    	 bzf->strm.next_in = bzf->buf;
    
          }
    
          ret = BZ2_bzDecompress ( &(bzf->strm) );
    
          if (ret != BZ_OK && ret != BZ_STREAM_END)
    
    	 { BZ_SETERR(ret); return 0; };
    
    
          if (ret == BZ_OK && myfeof(bzf->handle) &&
    
    	  bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
    	 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
    
    
          if (ret == BZ_STREAM_END)
    
    	 { BZ_SETERR(BZ_STREAM_END);
    	   return len - bzf->strm.avail_out; };
    
          if (bzf->strm.avail_out == 0)
    
    	 { BZ_SETERR(BZ_OK); return len; };
    
    
       }
    
       return 0; /*not reached*/
    }
    
    
    /*---------------------------------------------------*/
    void BZ_API(BZ2_bzReadGetUnused)
    
    		     ( int*    bzerror,
    		       BZFILE* b,
    		       void**  unused,
    		       int*    nUnused )
    
    {
       bzFile* bzf = (bzFile*)b;
       if (bzf == NULL)
          { BZ_SETERR(BZ_PARAM_ERROR); return; };
       if (bzf->lastErr != BZ_STREAM_END)
          { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
       if (unused == NULL || nUnused == NULL)
          { BZ_SETERR(BZ_PARAM_ERROR); return; };
    
       BZ_SETERR(BZ_OK);
       *nUnused = bzf->strm.avail_in;
       *unused = bzf->strm.next_in;
    }
    #endif
    
    
    /*---------------------------------------------------*/
    /*--- Misc convenience stuff                      ---*/
    /*---------------------------------------------------*/
    #ifndef BZ_NO_COMPRESS
    /*---------------------------------------------------*/
    int BZ_API(BZ2_bzBuffToBuffCompress)
    
    			 ( char*         dest,
    			   unsigned int* destLen,
    			   char*         source,
    			   unsigned int  sourceLen,
    			   int           blockSize100k,
    			   int           verbosity,
    			   int           workFactor )
    
    {
       bz_stream strm;
       int ret;
    
       if (dest == NULL || destLen == NULL ||
           source == NULL ||
           blockSize100k < 1 || blockSize100k > 9 ||
           verbosity < 0 || verbosity > 4 ||
           workFactor < 0 || workFactor > 250)
          return BZ_PARAM_ERROR;
    
       if (workFactor == 0) workFactor = 30;
       strm.bzalloc = NULL;
       strm.bzfree = NULL;
       strm.opaque = NULL;
       ret = BZ2_bzCompressInit ( &strm, blockSize100k,
    
    			      verbosity, workFactor );
    
       if (ret != BZ_OK) return ret;
    
       strm.next_in = source;
       strm.next_out = dest;
       strm.avail_in = sourceLen;
       strm.avail_out = *destLen;
    
       ret = BZ2_bzCompress ( &strm, BZ_FINISH );
       if (ret == BZ_FINISH_OK) goto output_overflow;
       if (ret != BZ_STREAM_END) goto errhandler;
    
       /* normal termination */
       *destLen -= strm.avail_out;
       BZ2_bzCompressEnd ( &strm );
       return BZ_OK;
    
       output_overflow:
       BZ2_bzCompressEnd ( &strm );
       return BZ_OUTBUFF_FULL;
    
       errhandler:
       BZ2_bzCompressEnd ( &strm );
       return ret;
    }
    #endif /* BZ_NO_COMPRESS */
    
    /*---------------------------------------------------*/
    int BZ_API(BZ2_bzBuffToBuffDecompress)
    
    			   ( char*         dest,
    			     unsigned int* destLen,
    			     char*         source,
    			     unsigned int  sourceLen,
    			     int           small,
    			     int           verbosity )
    
    {
       bz_stream strm;
       int ret;
    
       if (destLen == NULL || source == NULL)
    
    	  return BZ_PARAM_ERROR;
    
    
       strm.bzalloc = NULL;
       strm.bzfree = NULL;
       strm.opaque = NULL;
       ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
       if (ret != BZ_OK) return ret;
    
       strm.next_in = source;
       strm.next_out = dest;
       strm.avail_in = sourceLen;
       strm.avail_out = *destLen;
    
       ret = BZ2_bzDecompress ( &strm );
       if (ret == BZ_OK) goto output_overflow_or_eof;
       if (ret != BZ_STREAM_END) goto errhandler;
    
       /* normal termination */
       *destLen -= strm.avail_out;
       BZ2_bzDecompressEnd ( &strm );
       return BZ_OK;
    
       output_overflow_or_eof:
       if (strm.avail_out > 0) {
          BZ2_bzDecompressEnd ( &strm );
          return BZ_UNEXPECTED_EOF;
       } else {
          BZ2_bzDecompressEnd ( &strm );
          return BZ_OUTBUFF_FULL;
       };
    
       errhandler:
       BZ2_bzDecompressEnd ( &strm );
       return ret;
    }
    
    
    /*---------------------------------------------------*/
    /*--
       Code contributed by Yoshioka Tsuneo
       (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
       to support better zlib compatibility.
       This code is not _officially_ part of libbzip2 (yet);
       I haven't tested it, documented it, or considered the
       threading-safeness of it.
       If this code breaks, please contact both Yoshioka and me.
    --*/
    /*---------------------------------------------------*/
    
    /*---------------------------------------------------*/
    /*--
       return version like "0.9.0c".
    --*/
    const char * BZ_API(BZ2_bzlibVersion)(void)
    {
       return BZ_VERSION;
    }
    
    
    #ifndef BZ_NO_STDIO
    /*---------------------------------------------------*/
    
    #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
    #   include <fcntl.h>
    #   include <io.h>
    #   define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
    #else
    #   define SET_BINARY_MODE(file)
    #endif
    static
    BZFILE * bzopen_or_bzdopen
    
    	       ( const char *path,   /* no use when bzdopen */
    		 int fd,             /* no use when bzdopen */
    		 const char *mode,
    		 int open_mode)      /* bzopen: 0, bzdopen:1 */
    
    {
       int    bzerr;
       char   unused[BZ_MAX_UNUSED];
       int    blockSize100k = 9;
       int    writing       = 0;
       char   mode2[10]     = "";
       FILE   *fp           = NULL;
       BZFILE *bzfp         = NULL;
       int    verbosity     = 0;
       int    workFactor    = 30;
       int    smallMode     = 0;
       int    nUnused       = 0;
    
       if (mode == NULL) return NULL;
       while (*mode) {
          switch (*mode) {
          case 'r':
    
    	 writing = 0; break;
    
    	 writing = 1; break;
    
    	 smallMode = 1; break;
    
    	 if (isdigit((int)(*mode))) {
    	    blockSize100k = *mode-BZ_HDR_0;
    	 }
    
          }
          mode++;
       }
       strcat(mode2, writing ? "w" : "r" );
       strcat(mode2,"b");   /* binary mode */
    
       if (open_mode==0) {
          if (path==NULL || strcmp(path,"")==0) {
    
    	fp = (writing ? stdout : stdin);
    	SET_BINARY_MODE(fp);
    
    	fp = fopen(path,mode2);
    
          }
       } else {
    #ifdef BZ_STRICT_ANSI
          fp = NULL;
    #else
          fp = fdopen(fd,mode2);
    #endif
       }
       if (fp == NULL) return NULL;
    
       if (writing) {
          /* Guard against total chaos and anarchy -- JRS */
          if (blockSize100k < 1) blockSize100k = 1;
          if (blockSize100k > 9) blockSize100k = 9;
          bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
    
    			     verbosity,workFactor);
    
       } else {
          bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
    
    			    unused,nUnused);
    
       }
       if (bzfp == NULL) {
          if (fp != stdin && fp != stdout) fclose(fp);
          return NULL;
       }
       return bzfp;
    }
    
    
    /*---------------------------------------------------*/
    /*--
       open file for read or write.
          ex) bzopen("file","w9")
          case path="" or NULL => use stdin or stdout.
    --*/
    BZFILE * BZ_API(BZ2_bzopen)
    
    	       ( const char *path,
    		 const char *mode )
    
    {
       return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
    }
    
    
    /*---------------------------------------------------*/
    BZFILE * BZ_API(BZ2_bzdopen)
    
    	       ( int fd,
    		 const char *mode )
    
    {
       return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
    }
    
    
    /*---------------------------------------------------*/
    int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
    {
       int bzerr, nread;
       if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
       nread = BZ2_bzRead(&bzerr,b,buf,len);
       if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
          return nread;
       } else {
          return -1;
       }
    }
    
    
    /*---------------------------------------------------*/
    int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
    {
       int bzerr;
    
       BZ2_bzWrite(&bzerr,b,buf,len);
       if(bzerr == BZ_OK){
          return len;
       }else{
          return -1;
       }
    }
    
    
    /*---------------------------------------------------*/
    int BZ_API(BZ2_bzflush) (BZFILE *b)
    {
       /* do nothing now... */
       return 0;
    }
    
    
    /*---------------------------------------------------*/
    void BZ_API(BZ2_bzclose) (BZFILE* b)
    {
       int bzerr;
       FILE *fp = ((bzFile *)b)->handle;
    
       if (b==NULL) {return;}
       if(((bzFile*)b)->writing){
          BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
          if(bzerr != BZ_OK){
    
    	 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
    
          }
       }else{
          BZ2_bzReadClose(&bzerr,b);
       }
       if(fp!=stdin && fp!=stdout){
          fclose(fp);
       }
    }
    
    
    /*---------------------------------------------------*/
    /*--
       return last error code
    --*/
    static char *bzerrorstrings[] = {
           "OK"
          ,"SEQUENCE_ERROR"
          ,"PARAM_ERROR"
          ,"MEM_ERROR"
          ,"DATA_ERROR"
          ,"DATA_ERROR_MAGIC"
          ,"IO_ERROR"
          ,"UNEXPECTED_EOF"
          ,"OUTBUFF_FULL"
          ,"CONFIG_ERROR"
          ,"???"   /* for future */
          ,"???"   /* for future */
          ,"???"   /* for future */
          ,"???"   /* for future */
          ,"???"   /* for future */
          ,"???"   /* for future */
    };
    
    
    const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
    {
       int err = ((bzFile *)b)->lastErr;
    
       if(err>0) err = 0;
       *errnum = err;
       return bzerrorstrings[err*-1];
    }
    #endif
    
    
    void bz_internal_error(int errcode)
    {
    	printf ("BZIP2 internal error %d\n", errcode);
    }
    
    
    /*-------------------------------------------------------------*/
    /*--- end                                           bzlib.c ---*/
    /*-------------------------------------------------------------*/