178556Sobrien 278556Sobrien/*-------------------------------------------------------------*/ 378556Sobrien/*--- Library top-level functions. ---*/ 478556Sobrien/*--- bzlib.c ---*/ 578556Sobrien/*-------------------------------------------------------------*/ 678556Sobrien 7167978Sdelphij/* ------------------------------------------------------------------ 8167978Sdelphij This file is part of bzip2/libbzip2, a program and library for 9167978Sdelphij lossless, block-sorting data compression. 1078556Sobrien 11351007Sdelphij bzip2/libbzip2 version 1.0.8 of 13 July 2019 12351007Sdelphij Copyright (C) 1996-2019 Julian Seward <jseward@acm.org> 1378556Sobrien 14167978Sdelphij Please read the WARNING, DISCLAIMER and PATENTS sections in the 15167978Sdelphij README file. 1678556Sobrien 17167978Sdelphij This program is released under the terms of the license contained 18167978Sdelphij in the file LICENSE. 19167978Sdelphij ------------------------------------------------------------------ */ 2078556Sobrien 21167978Sdelphij/* CHANGES 22167978Sdelphij 0.9.0 -- original version. 2378556Sobrien 0.9.0a/b -- no changes in this file. 24167978Sdelphij 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress(). 25167978Sdelphij fixed bzWrite/bzRead to ignore zero-length requests. 26167978Sdelphij fixed bzread to correctly handle read requests after EOF. 27167978Sdelphij wrong parameter order in call to bzDecompressInit in 28167978Sdelphij bzBuffToBuffDecompress. Fixed. 29167978Sdelphij*/ 3078556Sobrien 31146788Ssobomax#include <sys/cdefs.h> 32146788Ssobomax__FBSDID("$FreeBSD: stable/11/contrib/bzip2/bzlib.c 351007 2019-08-14 06:39:20Z delphij $"); 33146788Ssobomax 3478556Sobrien#include "bzlib_private.h" 3578556Sobrien 36146788Ssobomax#ifndef BZ_NO_COMPRESS 3778556Sobrien 3878556Sobrien/*---------------------------------------------------*/ 3978556Sobrien/*--- Compression stuff ---*/ 4078556Sobrien/*---------------------------------------------------*/ 4178556Sobrien 4278556Sobrien 4378556Sobrien/*---------------------------------------------------*/ 4478556Sobrien#ifndef BZ_NO_STDIO 4578556Sobrienvoid BZ2_bz__AssertH__fail ( int errcode ) 4678556Sobrien{ 4778556Sobrien fprintf(stderr, 4878556Sobrien "\n\nbzip2/libbzip2: internal error number %d.\n" 4978556Sobrien "This is a bug in bzip2/libbzip2, %s.\n" 50351007Sdelphij "Please report it to: bzip2-devel@sourceware.org. If this happened\n" 5178556Sobrien "when you were using some program which uses libbzip2 as a\n" 5278556Sobrien "component, you should also report this bug to the author(s)\n" 5378556Sobrien "of that program. Please make an effort to report this bug;\n" 5478556Sobrien "timely and accurate bug reports eventually lead to higher\n" 55351007Sdelphij "quality software. Thanks.\n\n", 5678556Sobrien errcode, 5778556Sobrien BZ2_bzlibVersion() 5878556Sobrien ); 5990067Ssobomax 6090067Ssobomax if (errcode == 1007) { 6190067Ssobomax fprintf(stderr, 6290067Ssobomax "\n*** A special note about internal error number 1007 ***\n" 6390067Ssobomax "\n" 6490067Ssobomax "Experience suggests that a common cause of i.e. 1007\n" 6590067Ssobomax "is unreliable memory or other hardware. The 1007 assertion\n" 6690067Ssobomax "just happens to cross-check the results of huge numbers of\n" 6790067Ssobomax "memory reads/writes, and so acts (unintendedly) as a stress\n" 6890067Ssobomax "test of your memory system.\n" 6990067Ssobomax "\n" 7090067Ssobomax "I suggest the following: try compressing the file again,\n" 7190067Ssobomax "possibly monitoring progress in detail with the -vv flag.\n" 7290067Ssobomax "\n" 7390067Ssobomax "* If the error cannot be reproduced, and/or happens at different\n" 7490067Ssobomax " points in compression, you may have a flaky memory system.\n" 7590067Ssobomax " Try a memory-test program. I have used Memtest86\n" 7690067Ssobomax " (www.memtest86.com). At the time of writing it is free (GPLd).\n" 7790067Ssobomax " Memtest86 tests memory much more thorougly than your BIOSs\n" 7890067Ssobomax " power-on test, and may find failures that the BIOS doesn't.\n" 7990067Ssobomax "\n" 8090067Ssobomax "* If the error can be repeatably reproduced, this is a bug in\n" 8190067Ssobomax " bzip2, and I would very much like to hear about it. Please\n" 8290067Ssobomax " let me know, and, ideally, save a copy of the file causing the\n" 8390067Ssobomax " problem -- without which I will be unable to investigate it.\n" 8490067Ssobomax "\n" 8590067Ssobomax ); 8690067Ssobomax } 8790067Ssobomax 8878556Sobrien exit(3); 8978556Sobrien} 9078556Sobrien#endif 9178556Sobrien 92146788Ssobomax#endif /* BZ_NO_COMPRESS */ 9378556Sobrien 9478556Sobrien/*---------------------------------------------------*/ 9578556Sobrienstatic 9678556Sobrienint bz_config_ok ( void ) 9778556Sobrien{ 9878556Sobrien if (sizeof(int) != 4) return 0; 9978556Sobrien if (sizeof(short) != 2) return 0; 10078556Sobrien if (sizeof(char) != 1) return 0; 10178556Sobrien return 1; 10278556Sobrien} 10378556Sobrien 10478556Sobrien 10578556Sobrien/*---------------------------------------------------*/ 10678556Sobrienstatic 10778556Sobrienvoid* default_bzalloc ( void* opaque, Int32 items, Int32 size ) 10878556Sobrien{ 10978556Sobrien void* v = malloc ( items * size ); 11078556Sobrien return v; 11178556Sobrien} 11278556Sobrien 11378556Sobrienstatic 11478556Sobrienvoid default_bzfree ( void* opaque, void* addr ) 11578556Sobrien{ 11678556Sobrien if (addr != NULL) free ( addr ); 11778556Sobrien} 11878556Sobrien 119146788Ssobomax#ifndef BZ_NO_COMPRESS 12078556Sobrien 12178556Sobrien/*---------------------------------------------------*/ 12278556Sobrienstatic 12378556Sobrienvoid prepare_new_block ( EState* s ) 12478556Sobrien{ 12578556Sobrien Int32 i; 12678556Sobrien s->nblock = 0; 12778556Sobrien s->numZ = 0; 12878556Sobrien s->state_out_pos = 0; 12978556Sobrien BZ_INITIALISE_CRC ( s->blockCRC ); 13078556Sobrien for (i = 0; i < 256; i++) s->inUse[i] = False; 13178556Sobrien s->blockNo++; 13278556Sobrien} 13378556Sobrien 13478556Sobrien 13578556Sobrien/*---------------------------------------------------*/ 13678556Sobrienstatic 13778556Sobrienvoid init_RL ( EState* s ) 13878556Sobrien{ 13978556Sobrien s->state_in_ch = 256; 14078556Sobrien s->state_in_len = 0; 14178556Sobrien} 14278556Sobrien 14378556Sobrien 14478556Sobrienstatic 14578556SobrienBool isempty_RL ( EState* s ) 14678556Sobrien{ 14778556Sobrien if (s->state_in_ch < 256 && s->state_in_len > 0) 14878556Sobrien return False; else 14978556Sobrien return True; 15078556Sobrien} 15178556Sobrien 15278556Sobrien 15378556Sobrien/*---------------------------------------------------*/ 15478556Sobrienint BZ_API(BZ2_bzCompressInit) 15578556Sobrien ( bz_stream* strm, 15678556Sobrien int blockSize100k, 15778556Sobrien int verbosity, 15878556Sobrien int workFactor ) 15978556Sobrien{ 16078556Sobrien Int32 n; 16178556Sobrien EState* s; 16278556Sobrien 16378556Sobrien if (!bz_config_ok()) return BZ_CONFIG_ERROR; 16478556Sobrien 16578556Sobrien if (strm == NULL || 16678556Sobrien blockSize100k < 1 || blockSize100k > 9 || 16778556Sobrien workFactor < 0 || workFactor > 250) 16878556Sobrien return BZ_PARAM_ERROR; 16978556Sobrien 17078556Sobrien if (workFactor == 0) workFactor = 30; 17178556Sobrien if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; 17278556Sobrien if (strm->bzfree == NULL) strm->bzfree = default_bzfree; 17378556Sobrien 17478556Sobrien s = BZALLOC( sizeof(EState) ); 17578556Sobrien if (s == NULL) return BZ_MEM_ERROR; 17678556Sobrien s->strm = strm; 17778556Sobrien 17878556Sobrien s->arr1 = NULL; 17978556Sobrien s->arr2 = NULL; 18078556Sobrien s->ftab = NULL; 18178556Sobrien 18278556Sobrien n = 100000 * blockSize100k; 18378556Sobrien s->arr1 = BZALLOC( n * sizeof(UInt32) ); 18478556Sobrien s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) ); 18578556Sobrien s->ftab = BZALLOC( 65537 * sizeof(UInt32) ); 18678556Sobrien 18778556Sobrien if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) { 18878556Sobrien if (s->arr1 != NULL) BZFREE(s->arr1); 18978556Sobrien if (s->arr2 != NULL) BZFREE(s->arr2); 19078556Sobrien if (s->ftab != NULL) BZFREE(s->ftab); 19178556Sobrien if (s != NULL) BZFREE(s); 19278556Sobrien return BZ_MEM_ERROR; 19378556Sobrien } 19478556Sobrien 19578556Sobrien s->blockNo = 0; 19678556Sobrien s->state = BZ_S_INPUT; 19778556Sobrien s->mode = BZ_M_RUNNING; 19878556Sobrien s->combinedCRC = 0; 19978556Sobrien s->blockSize100k = blockSize100k; 20078556Sobrien s->nblockMAX = 100000 * blockSize100k - 19; 20178556Sobrien s->verbosity = verbosity; 20278556Sobrien s->workFactor = workFactor; 20378556Sobrien 20478556Sobrien s->block = (UChar*)s->arr2; 20578556Sobrien s->mtfv = (UInt16*)s->arr1; 20678556Sobrien s->zbits = NULL; 20778556Sobrien s->ptr = (UInt32*)s->arr1; 20878556Sobrien 20978556Sobrien strm->state = s; 21078556Sobrien strm->total_in_lo32 = 0; 21178556Sobrien strm->total_in_hi32 = 0; 21278556Sobrien strm->total_out_lo32 = 0; 21378556Sobrien strm->total_out_hi32 = 0; 21478556Sobrien init_RL ( s ); 21578556Sobrien prepare_new_block ( s ); 21678556Sobrien return BZ_OK; 21778556Sobrien} 21878556Sobrien 21978556Sobrien 22078556Sobrien/*---------------------------------------------------*/ 22178556Sobrienstatic 22278556Sobrienvoid add_pair_to_block ( EState* s ) 22378556Sobrien{ 22478556Sobrien Int32 i; 22578556Sobrien UChar ch = (UChar)(s->state_in_ch); 22678556Sobrien for (i = 0; i < s->state_in_len; i++) { 22778556Sobrien BZ_UPDATE_CRC( s->blockCRC, ch ); 22878556Sobrien } 22978556Sobrien s->inUse[s->state_in_ch] = True; 23078556Sobrien switch (s->state_in_len) { 23178556Sobrien case 1: 23278556Sobrien s->block[s->nblock] = (UChar)ch; s->nblock++; 23378556Sobrien break; 23478556Sobrien case 2: 23578556Sobrien s->block[s->nblock] = (UChar)ch; s->nblock++; 23678556Sobrien s->block[s->nblock] = (UChar)ch; s->nblock++; 23778556Sobrien break; 23878556Sobrien case 3: 23978556Sobrien s->block[s->nblock] = (UChar)ch; s->nblock++; 24078556Sobrien s->block[s->nblock] = (UChar)ch; s->nblock++; 24178556Sobrien s->block[s->nblock] = (UChar)ch; s->nblock++; 24278556Sobrien break; 24378556Sobrien default: 24478556Sobrien s->inUse[s->state_in_len-4] = True; 24578556Sobrien s->block[s->nblock] = (UChar)ch; s->nblock++; 24678556Sobrien s->block[s->nblock] = (UChar)ch; s->nblock++; 24778556Sobrien s->block[s->nblock] = (UChar)ch; s->nblock++; 24878556Sobrien s->block[s->nblock] = (UChar)ch; s->nblock++; 24978556Sobrien s->block[s->nblock] = ((UChar)(s->state_in_len-4)); 25078556Sobrien s->nblock++; 25178556Sobrien break; 25278556Sobrien } 25378556Sobrien} 25478556Sobrien 25578556Sobrien 25678556Sobrien/*---------------------------------------------------*/ 25778556Sobrienstatic 25878556Sobrienvoid flush_RL ( EState* s ) 25978556Sobrien{ 26078556Sobrien if (s->state_in_ch < 256) add_pair_to_block ( s ); 26178556Sobrien init_RL ( s ); 26278556Sobrien} 26378556Sobrien 26478556Sobrien 26578556Sobrien/*---------------------------------------------------*/ 26678556Sobrien#define ADD_CHAR_TO_BLOCK(zs,zchh0) \ 26778556Sobrien{ \ 26878556Sobrien UInt32 zchh = (UInt32)(zchh0); \ 26978556Sobrien /*-- fast track the common case --*/ \ 27078556Sobrien if (zchh != zs->state_in_ch && \ 27178556Sobrien zs->state_in_len == 1) { \ 27278556Sobrien UChar ch = (UChar)(zs->state_in_ch); \ 27378556Sobrien BZ_UPDATE_CRC( zs->blockCRC, ch ); \ 27478556Sobrien zs->inUse[zs->state_in_ch] = True; \ 27578556Sobrien zs->block[zs->nblock] = (UChar)ch; \ 27678556Sobrien zs->nblock++; \ 27778556Sobrien zs->state_in_ch = zchh; \ 27878556Sobrien } \ 27978556Sobrien else \ 28078556Sobrien /*-- general, uncommon cases --*/ \ 28178556Sobrien if (zchh != zs->state_in_ch || \ 28278556Sobrien zs->state_in_len == 255) { \ 28378556Sobrien if (zs->state_in_ch < 256) \ 28478556Sobrien add_pair_to_block ( zs ); \ 28578556Sobrien zs->state_in_ch = zchh; \ 28678556Sobrien zs->state_in_len = 1; \ 28778556Sobrien } else { \ 28878556Sobrien zs->state_in_len++; \ 28978556Sobrien } \ 29078556Sobrien} 29178556Sobrien 29278556Sobrien 29378556Sobrien/*---------------------------------------------------*/ 29478556Sobrienstatic 29578556SobrienBool copy_input_until_stop ( EState* s ) 29678556Sobrien{ 29778556Sobrien Bool progress_in = False; 29878556Sobrien 29978556Sobrien if (s->mode == BZ_M_RUNNING) { 30078556Sobrien 30178556Sobrien /*-- fast track the common case --*/ 30278556Sobrien while (True) { 30378556Sobrien /*-- block full? --*/ 30478556Sobrien if (s->nblock >= s->nblockMAX) break; 30578556Sobrien /*-- no input? --*/ 30678556Sobrien if (s->strm->avail_in == 0) break; 30778556Sobrien progress_in = True; 30878556Sobrien ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 30978556Sobrien s->strm->next_in++; 31078556Sobrien s->strm->avail_in--; 31178556Sobrien s->strm->total_in_lo32++; 31278556Sobrien if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; 31378556Sobrien } 31478556Sobrien 31578556Sobrien } else { 31678556Sobrien 31778556Sobrien /*-- general, uncommon case --*/ 31878556Sobrien while (True) { 31978556Sobrien /*-- block full? --*/ 32078556Sobrien if (s->nblock >= s->nblockMAX) break; 32178556Sobrien /*-- no input? --*/ 32278556Sobrien if (s->strm->avail_in == 0) break; 32378556Sobrien /*-- flush/finish end? --*/ 32478556Sobrien if (s->avail_in_expect == 0) break; 32578556Sobrien progress_in = True; 32678556Sobrien ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 32778556Sobrien s->strm->next_in++; 32878556Sobrien s->strm->avail_in--; 32978556Sobrien s->strm->total_in_lo32++; 33078556Sobrien if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; 33178556Sobrien s->avail_in_expect--; 33278556Sobrien } 33378556Sobrien } 33478556Sobrien return progress_in; 33578556Sobrien} 33678556Sobrien 33778556Sobrien 33878556Sobrien/*---------------------------------------------------*/ 33978556Sobrienstatic 34078556SobrienBool copy_output_until_stop ( EState* s ) 34178556Sobrien{ 34278556Sobrien Bool progress_out = False; 34378556Sobrien 34478556Sobrien while (True) { 34578556Sobrien 34678556Sobrien /*-- no output space? --*/ 34778556Sobrien if (s->strm->avail_out == 0) break; 34878556Sobrien 34978556Sobrien /*-- block done? --*/ 35078556Sobrien if (s->state_out_pos >= s->numZ) break; 35178556Sobrien 35278556Sobrien progress_out = True; 35378556Sobrien *(s->strm->next_out) = s->zbits[s->state_out_pos]; 35478556Sobrien s->state_out_pos++; 35578556Sobrien s->strm->avail_out--; 35678556Sobrien s->strm->next_out++; 35778556Sobrien s->strm->total_out_lo32++; 35878556Sobrien if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; 35978556Sobrien } 36078556Sobrien 36178556Sobrien return progress_out; 36278556Sobrien} 36378556Sobrien 36478556Sobrien 36578556Sobrien/*---------------------------------------------------*/ 36678556Sobrienstatic 36778556SobrienBool handle_compress ( bz_stream* strm ) 36878556Sobrien{ 36978556Sobrien Bool progress_in = False; 37078556Sobrien Bool progress_out = False; 37178556Sobrien EState* s = strm->state; 37278556Sobrien 37378556Sobrien while (True) { 37478556Sobrien 37578556Sobrien if (s->state == BZ_S_OUTPUT) { 37678556Sobrien progress_out |= copy_output_until_stop ( s ); 37778556Sobrien if (s->state_out_pos < s->numZ) break; 37878556Sobrien if (s->mode == BZ_M_FINISHING && 37978556Sobrien s->avail_in_expect == 0 && 38078556Sobrien isempty_RL(s)) break; 38178556Sobrien prepare_new_block ( s ); 38278556Sobrien s->state = BZ_S_INPUT; 38378556Sobrien if (s->mode == BZ_M_FLUSHING && 38478556Sobrien s->avail_in_expect == 0 && 38578556Sobrien isempty_RL(s)) break; 38678556Sobrien } 38778556Sobrien 38878556Sobrien if (s->state == BZ_S_INPUT) { 38978556Sobrien progress_in |= copy_input_until_stop ( s ); 39078556Sobrien if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) { 39178556Sobrien flush_RL ( s ); 39278556Sobrien BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) ); 39378556Sobrien s->state = BZ_S_OUTPUT; 39478556Sobrien } 39578556Sobrien else 39678556Sobrien if (s->nblock >= s->nblockMAX) { 39778556Sobrien BZ2_compressBlock ( s, False ); 39878556Sobrien s->state = BZ_S_OUTPUT; 39978556Sobrien } 40078556Sobrien else 40178556Sobrien if (s->strm->avail_in == 0) { 40278556Sobrien break; 40378556Sobrien } 40478556Sobrien } 40578556Sobrien 40678556Sobrien } 40778556Sobrien 40878556Sobrien return progress_in || progress_out; 40978556Sobrien} 41078556Sobrien 41178556Sobrien 41278556Sobrien/*---------------------------------------------------*/ 41378556Sobrienint BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action ) 41478556Sobrien{ 41578556Sobrien Bool progress; 41678556Sobrien EState* s; 41778556Sobrien if (strm == NULL) return BZ_PARAM_ERROR; 41878556Sobrien s = strm->state; 41978556Sobrien if (s == NULL) return BZ_PARAM_ERROR; 42078556Sobrien if (s->strm != strm) return BZ_PARAM_ERROR; 42178556Sobrien 42278556Sobrien preswitch: 42378556Sobrien switch (s->mode) { 42478556Sobrien 42578556Sobrien case BZ_M_IDLE: 42678556Sobrien return BZ_SEQUENCE_ERROR; 42778556Sobrien 42878556Sobrien case BZ_M_RUNNING: 42978556Sobrien if (action == BZ_RUN) { 43078556Sobrien progress = handle_compress ( strm ); 43178556Sobrien return progress ? BZ_RUN_OK : BZ_PARAM_ERROR; 43278556Sobrien } 43378556Sobrien else 43478556Sobrien if (action == BZ_FLUSH) { 43578556Sobrien s->avail_in_expect = strm->avail_in; 43678556Sobrien s->mode = BZ_M_FLUSHING; 43778556Sobrien goto preswitch; 43878556Sobrien } 43978556Sobrien else 44078556Sobrien if (action == BZ_FINISH) { 44178556Sobrien s->avail_in_expect = strm->avail_in; 44278556Sobrien s->mode = BZ_M_FINISHING; 44378556Sobrien goto preswitch; 44478556Sobrien } 44578556Sobrien else 44678556Sobrien return BZ_PARAM_ERROR; 44778556Sobrien 44878556Sobrien case BZ_M_FLUSHING: 44978556Sobrien if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR; 45078556Sobrien if (s->avail_in_expect != s->strm->avail_in) 45178556Sobrien return BZ_SEQUENCE_ERROR; 45278556Sobrien progress = handle_compress ( strm ); 45378556Sobrien if (s->avail_in_expect > 0 || !isempty_RL(s) || 45478556Sobrien s->state_out_pos < s->numZ) return BZ_FLUSH_OK; 45578556Sobrien s->mode = BZ_M_RUNNING; 45678556Sobrien return BZ_RUN_OK; 45778556Sobrien 45878556Sobrien case BZ_M_FINISHING: 45978556Sobrien if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR; 46078556Sobrien if (s->avail_in_expect != s->strm->avail_in) 46178556Sobrien return BZ_SEQUENCE_ERROR; 46278556Sobrien progress = handle_compress ( strm ); 46378556Sobrien if (!progress) return BZ_SEQUENCE_ERROR; 46478556Sobrien if (s->avail_in_expect > 0 || !isempty_RL(s) || 46578556Sobrien s->state_out_pos < s->numZ) return BZ_FINISH_OK; 46678556Sobrien s->mode = BZ_M_IDLE; 46778556Sobrien return BZ_STREAM_END; 46878556Sobrien } 46978556Sobrien return BZ_OK; /*--not reached--*/ 47078556Sobrien} 47178556Sobrien 47278556Sobrien 47378556Sobrien/*---------------------------------------------------*/ 47478556Sobrienint BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm ) 47578556Sobrien{ 47678556Sobrien EState* s; 47778556Sobrien if (strm == NULL) return BZ_PARAM_ERROR; 47878556Sobrien s = strm->state; 47978556Sobrien if (s == NULL) return BZ_PARAM_ERROR; 48078556Sobrien if (s->strm != strm) return BZ_PARAM_ERROR; 48178556Sobrien 48278556Sobrien if (s->arr1 != NULL) BZFREE(s->arr1); 48378556Sobrien if (s->arr2 != NULL) BZFREE(s->arr2); 48478556Sobrien if (s->ftab != NULL) BZFREE(s->ftab); 48578556Sobrien BZFREE(strm->state); 48678556Sobrien 48778556Sobrien strm->state = NULL; 48878556Sobrien 48978556Sobrien return BZ_OK; 49078556Sobrien} 49178556Sobrien 492146788Ssobomax#endif /* BZ_NO_COMPRESS */ 49378556Sobrien 49478556Sobrien/*---------------------------------------------------*/ 49578556Sobrien/*--- Decompression stuff ---*/ 49678556Sobrien/*---------------------------------------------------*/ 49778556Sobrien 49878556Sobrien/*---------------------------------------------------*/ 49978556Sobrienint BZ_API(BZ2_bzDecompressInit) 50078556Sobrien ( bz_stream* strm, 50178556Sobrien int verbosity, 50278556Sobrien int small ) 50378556Sobrien{ 50478556Sobrien DState* s; 50578556Sobrien 50678556Sobrien if (!bz_config_ok()) return BZ_CONFIG_ERROR; 50778556Sobrien 50878556Sobrien if (strm == NULL) return BZ_PARAM_ERROR; 50978556Sobrien if (small != 0 && small != 1) return BZ_PARAM_ERROR; 51078556Sobrien if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR; 51178556Sobrien 51278556Sobrien if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; 51378556Sobrien if (strm->bzfree == NULL) strm->bzfree = default_bzfree; 51478556Sobrien 51578556Sobrien s = BZALLOC( sizeof(DState) ); 51678556Sobrien if (s == NULL) return BZ_MEM_ERROR; 51778556Sobrien s->strm = strm; 51878556Sobrien strm->state = s; 51978556Sobrien s->state = BZ_X_MAGIC_1; 52078556Sobrien s->bsLive = 0; 52178556Sobrien s->bsBuff = 0; 52278556Sobrien s->calculatedCombinedCRC = 0; 52378556Sobrien strm->total_in_lo32 = 0; 52478556Sobrien strm->total_in_hi32 = 0; 52578556Sobrien strm->total_out_lo32 = 0; 52678556Sobrien strm->total_out_hi32 = 0; 52778556Sobrien s->smallDecompress = (Bool)small; 52878556Sobrien s->ll4 = NULL; 52978556Sobrien s->ll16 = NULL; 53078556Sobrien s->tt = NULL; 53178556Sobrien s->currBlockNo = 0; 53278556Sobrien s->verbosity = verbosity; 53378556Sobrien 53478556Sobrien return BZ_OK; 53578556Sobrien} 53678556Sobrien 53778556Sobrien 53878556Sobrien/*---------------------------------------------------*/ 539146293Sobrien/* Return True iff data corruption is discovered. 540146293Sobrien Returns False if there is no problem. 541146293Sobrien*/ 54278556Sobrienstatic 543146293SobrienBool unRLE_obuf_to_output_FAST ( DState* s ) 54478556Sobrien{ 54578556Sobrien UChar k1; 54678556Sobrien 54778556Sobrien if (s->blockRandomised) { 54878556Sobrien 54978556Sobrien while (True) { 55078556Sobrien /* try to finish existing run */ 55178556Sobrien while (True) { 552146293Sobrien if (s->strm->avail_out == 0) return False; 55378556Sobrien if (s->state_out_len == 0) break; 55478556Sobrien *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; 55578556Sobrien BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); 55678556Sobrien s->state_out_len--; 55778556Sobrien s->strm->next_out++; 55878556Sobrien s->strm->avail_out--; 55978556Sobrien s->strm->total_out_lo32++; 56078556Sobrien if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; 56178556Sobrien } 562146293Sobrien 56378556Sobrien /* can a new run be started? */ 564146293Sobrien if (s->nblock_used == s->save_nblock+1) return False; 56578556Sobrien 566146293Sobrien /* Only caused by corrupt data stream? */ 567146293Sobrien if (s->nblock_used > s->save_nblock+1) 568146293Sobrien return True; 56978556Sobrien 57078556Sobrien s->state_out_len = 1; 57178556Sobrien s->state_out_ch = s->k0; 57278556Sobrien BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 57378556Sobrien k1 ^= BZ_RAND_MASK; s->nblock_used++; 57478556Sobrien if (s->nblock_used == s->save_nblock+1) continue; 57578556Sobrien if (k1 != s->k0) { s->k0 = k1; continue; }; 57678556Sobrien 57778556Sobrien s->state_out_len = 2; 57878556Sobrien BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 57978556Sobrien k1 ^= BZ_RAND_MASK; s->nblock_used++; 58078556Sobrien if (s->nblock_used == s->save_nblock+1) continue; 58178556Sobrien if (k1 != s->k0) { s->k0 = k1; continue; }; 58278556Sobrien 58378556Sobrien s->state_out_len = 3; 58478556Sobrien BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 58578556Sobrien k1 ^= BZ_RAND_MASK; s->nblock_used++; 58678556Sobrien if (s->nblock_used == s->save_nblock+1) continue; 58778556Sobrien if (k1 != s->k0) { s->k0 = k1; continue; }; 58878556Sobrien 58978556Sobrien BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 59078556Sobrien k1 ^= BZ_RAND_MASK; s->nblock_used++; 59178556Sobrien s->state_out_len = ((Int32)k1) + 4; 59278556Sobrien BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; 59378556Sobrien s->k0 ^= BZ_RAND_MASK; s->nblock_used++; 59478556Sobrien } 59578556Sobrien 59678556Sobrien } else { 59778556Sobrien 59878556Sobrien /* restore */ 59978556Sobrien UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC; 60078556Sobrien UChar c_state_out_ch = s->state_out_ch; 60178556Sobrien Int32 c_state_out_len = s->state_out_len; 60278556Sobrien Int32 c_nblock_used = s->nblock_used; 60378556Sobrien Int32 c_k0 = s->k0; 60478556Sobrien UInt32* c_tt = s->tt; 60578556Sobrien UInt32 c_tPos = s->tPos; 60678556Sobrien char* cs_next_out = s->strm->next_out; 60778556Sobrien unsigned int cs_avail_out = s->strm->avail_out; 608177424Sdelphij Int32 ro_blockSize100k = s->blockSize100k; 60978556Sobrien /* end restore */ 61078556Sobrien 61178556Sobrien UInt32 avail_out_INIT = cs_avail_out; 61278556Sobrien Int32 s_save_nblockPP = s->save_nblock+1; 61378556Sobrien unsigned int total_out_lo32_old; 61478556Sobrien 61578556Sobrien while (True) { 61678556Sobrien 61778556Sobrien /* try to finish existing run */ 61878556Sobrien if (c_state_out_len > 0) { 61978556Sobrien while (True) { 62078556Sobrien if (cs_avail_out == 0) goto return_notr; 62178556Sobrien if (c_state_out_len == 1) break; 62278556Sobrien *( (UChar*)(cs_next_out) ) = c_state_out_ch; 62378556Sobrien BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); 62478556Sobrien c_state_out_len--; 62578556Sobrien cs_next_out++; 62678556Sobrien cs_avail_out--; 62778556Sobrien } 62878556Sobrien s_state_out_len_eq_one: 62978556Sobrien { 63078556Sobrien if (cs_avail_out == 0) { 63178556Sobrien c_state_out_len = 1; goto return_notr; 63278556Sobrien }; 63378556Sobrien *( (UChar*)(cs_next_out) ) = c_state_out_ch; 63478556Sobrien BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); 63578556Sobrien cs_next_out++; 63678556Sobrien cs_avail_out--; 63778556Sobrien } 63878556Sobrien } 639146293Sobrien /* Only caused by corrupt data stream? */ 640146293Sobrien if (c_nblock_used > s_save_nblockPP) 641146293Sobrien return True; 642146293Sobrien 64378556Sobrien /* can a new run be started? */ 64478556Sobrien if (c_nblock_used == s_save_nblockPP) { 64578556Sobrien c_state_out_len = 0; goto return_notr; 64678556Sobrien }; 64778556Sobrien c_state_out_ch = c_k0; 64878556Sobrien BZ_GET_FAST_C(k1); c_nblock_used++; 64978556Sobrien if (k1 != c_k0) { 65078556Sobrien c_k0 = k1; goto s_state_out_len_eq_one; 65178556Sobrien }; 65278556Sobrien if (c_nblock_used == s_save_nblockPP) 65378556Sobrien goto s_state_out_len_eq_one; 65478556Sobrien 65578556Sobrien c_state_out_len = 2; 65678556Sobrien BZ_GET_FAST_C(k1); c_nblock_used++; 65778556Sobrien if (c_nblock_used == s_save_nblockPP) continue; 65878556Sobrien if (k1 != c_k0) { c_k0 = k1; continue; }; 65978556Sobrien 66078556Sobrien c_state_out_len = 3; 66178556Sobrien BZ_GET_FAST_C(k1); c_nblock_used++; 66278556Sobrien if (c_nblock_used == s_save_nblockPP) continue; 66378556Sobrien if (k1 != c_k0) { c_k0 = k1; continue; }; 66478556Sobrien 66578556Sobrien BZ_GET_FAST_C(k1); c_nblock_used++; 66678556Sobrien c_state_out_len = ((Int32)k1) + 4; 66778556Sobrien BZ_GET_FAST_C(c_k0); c_nblock_used++; 66878556Sobrien } 66978556Sobrien 67078556Sobrien return_notr: 67178556Sobrien total_out_lo32_old = s->strm->total_out_lo32; 67278556Sobrien s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out); 67378556Sobrien if (s->strm->total_out_lo32 < total_out_lo32_old) 67478556Sobrien s->strm->total_out_hi32++; 67578556Sobrien 67678556Sobrien /* save */ 67778556Sobrien s->calculatedBlockCRC = c_calculatedBlockCRC; 67878556Sobrien s->state_out_ch = c_state_out_ch; 67978556Sobrien s->state_out_len = c_state_out_len; 68078556Sobrien s->nblock_used = c_nblock_used; 68178556Sobrien s->k0 = c_k0; 68278556Sobrien s->tt = c_tt; 68378556Sobrien s->tPos = c_tPos; 68478556Sobrien s->strm->next_out = cs_next_out; 68578556Sobrien s->strm->avail_out = cs_avail_out; 68678556Sobrien /* end save */ 68778556Sobrien } 688146293Sobrien return False; 68978556Sobrien} 69078556Sobrien 69178556Sobrien 69278556Sobrien 69378556Sobrien/*---------------------------------------------------*/ 69478556Sobrien__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab ) 69578556Sobrien{ 69678556Sobrien Int32 nb, na, mid; 69778556Sobrien nb = 0; 69878556Sobrien na = 256; 69978556Sobrien do { 70078556Sobrien mid = (nb + na) >> 1; 70178556Sobrien if (indx >= cftab[mid]) nb = mid; else na = mid; 70278556Sobrien } 70378556Sobrien while (na - nb != 1); 70478556Sobrien return nb; 70578556Sobrien} 70678556Sobrien 70778556Sobrien 70878556Sobrien/*---------------------------------------------------*/ 709146293Sobrien/* Return True iff data corruption is discovered. 710146293Sobrien Returns False if there is no problem. 711146293Sobrien*/ 71278556Sobrienstatic 713146293SobrienBool unRLE_obuf_to_output_SMALL ( DState* s ) 71478556Sobrien{ 71578556Sobrien UChar k1; 71678556Sobrien 71778556Sobrien if (s->blockRandomised) { 71878556Sobrien 71978556Sobrien while (True) { 72078556Sobrien /* try to finish existing run */ 72178556Sobrien while (True) { 722146293Sobrien if (s->strm->avail_out == 0) return False; 72378556Sobrien if (s->state_out_len == 0) break; 72478556Sobrien *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; 72578556Sobrien BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); 72678556Sobrien s->state_out_len--; 72778556Sobrien s->strm->next_out++; 72878556Sobrien s->strm->avail_out--; 72978556Sobrien s->strm->total_out_lo32++; 73078556Sobrien if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; 73178556Sobrien } 73278556Sobrien 73378556Sobrien /* can a new run be started? */ 734146293Sobrien if (s->nblock_used == s->save_nblock+1) return False; 735146293Sobrien 736146293Sobrien /* Only caused by corrupt data stream? */ 737146293Sobrien if (s->nblock_used > s->save_nblock+1) 738146293Sobrien return True; 73978556Sobrien 74078556Sobrien s->state_out_len = 1; 74178556Sobrien s->state_out_ch = s->k0; 74278556Sobrien BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 74378556Sobrien k1 ^= BZ_RAND_MASK; s->nblock_used++; 74478556Sobrien if (s->nblock_used == s->save_nblock+1) continue; 74578556Sobrien if (k1 != s->k0) { s->k0 = k1; continue; }; 74678556Sobrien 74778556Sobrien s->state_out_len = 2; 74878556Sobrien BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 74978556Sobrien k1 ^= BZ_RAND_MASK; s->nblock_used++; 75078556Sobrien if (s->nblock_used == s->save_nblock+1) continue; 75178556Sobrien if (k1 != s->k0) { s->k0 = k1; continue; }; 75278556Sobrien 75378556Sobrien s->state_out_len = 3; 75478556Sobrien BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 75578556Sobrien k1 ^= BZ_RAND_MASK; s->nblock_used++; 75678556Sobrien if (s->nblock_used == s->save_nblock+1) continue; 75778556Sobrien if (k1 != s->k0) { s->k0 = k1; continue; }; 75878556Sobrien 75978556Sobrien BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 76078556Sobrien k1 ^= BZ_RAND_MASK; s->nblock_used++; 76178556Sobrien s->state_out_len = ((Int32)k1) + 4; 76278556Sobrien BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; 76378556Sobrien s->k0 ^= BZ_RAND_MASK; s->nblock_used++; 76478556Sobrien } 76578556Sobrien 76678556Sobrien } else { 76778556Sobrien 76878556Sobrien while (True) { 76978556Sobrien /* try to finish existing run */ 77078556Sobrien while (True) { 771146293Sobrien if (s->strm->avail_out == 0) return False; 77278556Sobrien if (s->state_out_len == 0) break; 77378556Sobrien *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; 77478556Sobrien BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); 77578556Sobrien s->state_out_len--; 77678556Sobrien s->strm->next_out++; 77778556Sobrien s->strm->avail_out--; 77878556Sobrien s->strm->total_out_lo32++; 77978556Sobrien if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; 78078556Sobrien } 78178556Sobrien 78278556Sobrien /* can a new run be started? */ 783146293Sobrien if (s->nblock_used == s->save_nblock+1) return False; 784146293Sobrien 785146293Sobrien /* Only caused by corrupt data stream? */ 786146293Sobrien if (s->nblock_used > s->save_nblock+1) 787146293Sobrien return True; 78878556Sobrien 78978556Sobrien s->state_out_len = 1; 79078556Sobrien s->state_out_ch = s->k0; 79178556Sobrien BZ_GET_SMALL(k1); s->nblock_used++; 79278556Sobrien if (s->nblock_used == s->save_nblock+1) continue; 79378556Sobrien if (k1 != s->k0) { s->k0 = k1; continue; }; 79478556Sobrien 79578556Sobrien s->state_out_len = 2; 79678556Sobrien BZ_GET_SMALL(k1); s->nblock_used++; 79778556Sobrien if (s->nblock_used == s->save_nblock+1) continue; 79878556Sobrien if (k1 != s->k0) { s->k0 = k1; continue; }; 79978556Sobrien 80078556Sobrien s->state_out_len = 3; 80178556Sobrien BZ_GET_SMALL(k1); s->nblock_used++; 80278556Sobrien if (s->nblock_used == s->save_nblock+1) continue; 80378556Sobrien if (k1 != s->k0) { s->k0 = k1; continue; }; 80478556Sobrien 80578556Sobrien BZ_GET_SMALL(k1); s->nblock_used++; 80678556Sobrien s->state_out_len = ((Int32)k1) + 4; 80778556Sobrien BZ_GET_SMALL(s->k0); s->nblock_used++; 80878556Sobrien } 80978556Sobrien 81078556Sobrien } 81178556Sobrien} 81278556Sobrien 81378556Sobrien 81478556Sobrien/*---------------------------------------------------*/ 81578556Sobrienint BZ_API(BZ2_bzDecompress) ( bz_stream *strm ) 81678556Sobrien{ 817146293Sobrien Bool corrupt; 81878556Sobrien DState* s; 81978556Sobrien if (strm == NULL) return BZ_PARAM_ERROR; 82078556Sobrien s = strm->state; 82178556Sobrien if (s == NULL) return BZ_PARAM_ERROR; 82278556Sobrien if (s->strm != strm) return BZ_PARAM_ERROR; 82378556Sobrien 82478556Sobrien while (True) { 82578556Sobrien if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; 82678556Sobrien if (s->state == BZ_X_OUTPUT) { 82778556Sobrien if (s->smallDecompress) 828146293Sobrien corrupt = unRLE_obuf_to_output_SMALL ( s ); else 829146293Sobrien corrupt = unRLE_obuf_to_output_FAST ( s ); 830146293Sobrien if (corrupt) return BZ_DATA_ERROR; 83178556Sobrien if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { 83278556Sobrien BZ_FINALISE_CRC ( s->calculatedBlockCRC ); 83378556Sobrien if (s->verbosity >= 3) 834146293Sobrien VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, 83578556Sobrien s->calculatedBlockCRC ); 83678556Sobrien if (s->verbosity >= 2) VPrintf0 ( "]" ); 83778556Sobrien if (s->calculatedBlockCRC != s->storedBlockCRC) 83878556Sobrien return BZ_DATA_ERROR; 83978556Sobrien s->calculatedCombinedCRC 84078556Sobrien = (s->calculatedCombinedCRC << 1) | 84178556Sobrien (s->calculatedCombinedCRC >> 31); 84278556Sobrien s->calculatedCombinedCRC ^= s->calculatedBlockCRC; 84378556Sobrien s->state = BZ_X_BLKHDR_1; 84478556Sobrien } else { 84578556Sobrien return BZ_OK; 84678556Sobrien } 84778556Sobrien } 84878556Sobrien if (s->state >= BZ_X_MAGIC_1) { 84978556Sobrien Int32 r = BZ2_decompress ( s ); 85078556Sobrien if (r == BZ_STREAM_END) { 85178556Sobrien if (s->verbosity >= 3) 852146293Sobrien VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x", 85378556Sobrien s->storedCombinedCRC, s->calculatedCombinedCRC ); 85478556Sobrien if (s->calculatedCombinedCRC != s->storedCombinedCRC) 85578556Sobrien return BZ_DATA_ERROR; 85678556Sobrien return r; 85778556Sobrien } 85878556Sobrien if (s->state != BZ_X_OUTPUT) return r; 85978556Sobrien } 86078556Sobrien } 86178556Sobrien 86278556Sobrien AssertH ( 0, 6001 ); 86378556Sobrien 86478556Sobrien return 0; /*NOTREACHED*/ 86578556Sobrien} 86678556Sobrien 86778556Sobrien 86878556Sobrien/*---------------------------------------------------*/ 86978556Sobrienint BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm ) 87078556Sobrien{ 87178556Sobrien DState* s; 87278556Sobrien if (strm == NULL) return BZ_PARAM_ERROR; 87378556Sobrien s = strm->state; 87478556Sobrien if (s == NULL) return BZ_PARAM_ERROR; 87578556Sobrien if (s->strm != strm) return BZ_PARAM_ERROR; 87678556Sobrien 87778556Sobrien if (s->tt != NULL) BZFREE(s->tt); 87878556Sobrien if (s->ll16 != NULL) BZFREE(s->ll16); 87978556Sobrien if (s->ll4 != NULL) BZFREE(s->ll4); 88078556Sobrien 88178556Sobrien BZFREE(strm->state); 88278556Sobrien strm->state = NULL; 88378556Sobrien 88478556Sobrien return BZ_OK; 88578556Sobrien} 88678556Sobrien 887146788Ssobomax#ifndef BZ_NO_COMPRESS 88878556Sobrien 88978556Sobrien#ifndef BZ_NO_STDIO 89078556Sobrien/*---------------------------------------------------*/ 89178556Sobrien/*--- File I/O stuff ---*/ 89278556Sobrien/*---------------------------------------------------*/ 89378556Sobrien 89478556Sobrien#define BZ_SETERR(eee) \ 89578556Sobrien{ \ 89678556Sobrien if (bzerror != NULL) *bzerror = eee; \ 89778556Sobrien if (bzf != NULL) bzf->lastErr = eee; \ 89878556Sobrien} 89978556Sobrien 90078556Sobrientypedef 90178556Sobrien struct { 90278556Sobrien FILE* handle; 90378556Sobrien Char buf[BZ_MAX_UNUSED]; 90478556Sobrien Int32 bufN; 90578556Sobrien Bool writing; 90678556Sobrien bz_stream strm; 90778556Sobrien Int32 lastErr; 90878556Sobrien Bool initialisedOk; 90978556Sobrien } 91078556Sobrien bzFile; 91178556Sobrien 91278556Sobrien 91378556Sobrien/*---------------------------------------------*/ 91478556Sobrienstatic Bool myfeof ( FILE* f ) 91578556Sobrien{ 91678556Sobrien Int32 c = fgetc ( f ); 91778556Sobrien if (c == EOF) return True; 91878556Sobrien ungetc ( c, f ); 91978556Sobrien return False; 92078556Sobrien} 92178556Sobrien 92278556Sobrien 92378556Sobrien/*---------------------------------------------------*/ 92478556SobrienBZFILE* BZ_API(BZ2_bzWriteOpen) 92578556Sobrien ( int* bzerror, 92678556Sobrien FILE* f, 92778556Sobrien int blockSize100k, 92878556Sobrien int verbosity, 92978556Sobrien int workFactor ) 93078556Sobrien{ 93178556Sobrien Int32 ret; 93278556Sobrien bzFile* bzf = NULL; 93378556Sobrien 93478556Sobrien BZ_SETERR(BZ_OK); 93578556Sobrien 93678556Sobrien if (f == NULL || 93778556Sobrien (blockSize100k < 1 || blockSize100k > 9) || 93878556Sobrien (workFactor < 0 || workFactor > 250) || 93978556Sobrien (verbosity < 0 || verbosity > 4)) 94078556Sobrien { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; 94178556Sobrien 94278556Sobrien if (ferror(f)) 94378556Sobrien { BZ_SETERR(BZ_IO_ERROR); return NULL; }; 94478556Sobrien 94578556Sobrien bzf = malloc ( sizeof(bzFile) ); 94678556Sobrien if (bzf == NULL) 94778556Sobrien { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; 94878556Sobrien 94978556Sobrien BZ_SETERR(BZ_OK); 95078556Sobrien bzf->initialisedOk = False; 95178556Sobrien bzf->bufN = 0; 95278556Sobrien bzf->handle = f; 95378556Sobrien bzf->writing = True; 95478556Sobrien bzf->strm.bzalloc = NULL; 95578556Sobrien bzf->strm.bzfree = NULL; 95678556Sobrien bzf->strm.opaque = NULL; 95778556Sobrien 95878556Sobrien if (workFactor == 0) workFactor = 30; 95978556Sobrien ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, 96078556Sobrien verbosity, workFactor ); 96178556Sobrien if (ret != BZ_OK) 96278556Sobrien { BZ_SETERR(ret); free(bzf); return NULL; }; 96378556Sobrien 96478556Sobrien bzf->strm.avail_in = 0; 96578556Sobrien bzf->initialisedOk = True; 96678556Sobrien return bzf; 96778556Sobrien} 96878556Sobrien 96978556Sobrien 97078556Sobrien 97178556Sobrien/*---------------------------------------------------*/ 97278556Sobrienvoid BZ_API(BZ2_bzWrite) 97378556Sobrien ( int* bzerror, 97478556Sobrien BZFILE* b, 97578556Sobrien void* buf, 97678556Sobrien int len ) 97778556Sobrien{ 97878556Sobrien Int32 n, n2, ret; 97978556Sobrien bzFile* bzf = (bzFile*)b; 98078556Sobrien 98178556Sobrien BZ_SETERR(BZ_OK); 98278556Sobrien if (bzf == NULL || buf == NULL || len < 0) 98378556Sobrien { BZ_SETERR(BZ_PARAM_ERROR); return; }; 98478556Sobrien if (!(bzf->writing)) 98578556Sobrien { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; 98678556Sobrien if (ferror(bzf->handle)) 98778556Sobrien { BZ_SETERR(BZ_IO_ERROR); return; }; 98878556Sobrien 98978556Sobrien if (len == 0) 99078556Sobrien { BZ_SETERR(BZ_OK); return; }; 99178556Sobrien 99278556Sobrien bzf->strm.avail_in = len; 99378556Sobrien bzf->strm.next_in = buf; 99478556Sobrien 99578556Sobrien while (True) { 99678556Sobrien bzf->strm.avail_out = BZ_MAX_UNUSED; 99778556Sobrien bzf->strm.next_out = bzf->buf; 99878556Sobrien ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN ); 99978556Sobrien if (ret != BZ_RUN_OK) 100078556Sobrien { BZ_SETERR(ret); return; }; 100178556Sobrien 100278556Sobrien if (bzf->strm.avail_out < BZ_MAX_UNUSED) { 100378556Sobrien n = BZ_MAX_UNUSED - bzf->strm.avail_out; 100478556Sobrien n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 100578556Sobrien n, bzf->handle ); 100678556Sobrien if (n != n2 || ferror(bzf->handle)) 100778556Sobrien { BZ_SETERR(BZ_IO_ERROR); return; }; 100878556Sobrien } 100978556Sobrien 101078556Sobrien if (bzf->strm.avail_in == 0) 101178556Sobrien { BZ_SETERR(BZ_OK); return; }; 101278556Sobrien } 101378556Sobrien} 101478556Sobrien 101578556Sobrien 101678556Sobrien/*---------------------------------------------------*/ 101778556Sobrienvoid BZ_API(BZ2_bzWriteClose) 101878556Sobrien ( int* bzerror, 101978556Sobrien BZFILE* b, 102078556Sobrien int abandon, 102178556Sobrien unsigned int* nbytes_in, 102278556Sobrien unsigned int* nbytes_out ) 102378556Sobrien{ 102478556Sobrien BZ2_bzWriteClose64 ( bzerror, b, abandon, 102578556Sobrien nbytes_in, NULL, nbytes_out, NULL ); 102678556Sobrien} 102778556Sobrien 102878556Sobrien 102978556Sobrienvoid BZ_API(BZ2_bzWriteClose64) 103078556Sobrien ( int* bzerror, 103178556Sobrien BZFILE* b, 103278556Sobrien int abandon, 103378556Sobrien unsigned int* nbytes_in_lo32, 103478556Sobrien unsigned int* nbytes_in_hi32, 103578556Sobrien unsigned int* nbytes_out_lo32, 103678556Sobrien unsigned int* nbytes_out_hi32 ) 103778556Sobrien{ 103878556Sobrien Int32 n, n2, ret; 103978556Sobrien bzFile* bzf = (bzFile*)b; 104078556Sobrien 104178556Sobrien if (bzf == NULL) 104278556Sobrien { BZ_SETERR(BZ_OK); return; }; 104378556Sobrien if (!(bzf->writing)) 104478556Sobrien { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; 104578556Sobrien if (ferror(bzf->handle)) 104678556Sobrien { BZ_SETERR(BZ_IO_ERROR); return; }; 104778556Sobrien 104878556Sobrien if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0; 104978556Sobrien if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0; 105078556Sobrien if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0; 105178556Sobrien if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0; 105278556Sobrien 105378556Sobrien if ((!abandon) && bzf->lastErr == BZ_OK) { 105478556Sobrien while (True) { 105578556Sobrien bzf->strm.avail_out = BZ_MAX_UNUSED; 105678556Sobrien bzf->strm.next_out = bzf->buf; 105778556Sobrien ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH ); 105878556Sobrien if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) 105978556Sobrien { BZ_SETERR(ret); return; }; 106078556Sobrien 106178556Sobrien if (bzf->strm.avail_out < BZ_MAX_UNUSED) { 106278556Sobrien n = BZ_MAX_UNUSED - bzf->strm.avail_out; 106378556Sobrien n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 106478556Sobrien n, bzf->handle ); 106578556Sobrien if (n != n2 || ferror(bzf->handle)) 106678556Sobrien { BZ_SETERR(BZ_IO_ERROR); return; }; 106778556Sobrien } 106878556Sobrien 106978556Sobrien if (ret == BZ_STREAM_END) break; 107078556Sobrien } 107178556Sobrien } 107278556Sobrien 107378556Sobrien if ( !abandon && !ferror ( bzf->handle ) ) { 107478556Sobrien fflush ( bzf->handle ); 107578556Sobrien if (ferror(bzf->handle)) 107678556Sobrien { BZ_SETERR(BZ_IO_ERROR); return; }; 107778556Sobrien } 107878556Sobrien 107978556Sobrien if (nbytes_in_lo32 != NULL) 108078556Sobrien *nbytes_in_lo32 = bzf->strm.total_in_lo32; 108178556Sobrien if (nbytes_in_hi32 != NULL) 108278556Sobrien *nbytes_in_hi32 = bzf->strm.total_in_hi32; 108378556Sobrien if (nbytes_out_lo32 != NULL) 108478556Sobrien *nbytes_out_lo32 = bzf->strm.total_out_lo32; 108578556Sobrien if (nbytes_out_hi32 != NULL) 108678556Sobrien *nbytes_out_hi32 = bzf->strm.total_out_hi32; 108778556Sobrien 108878556Sobrien BZ_SETERR(BZ_OK); 108978556Sobrien BZ2_bzCompressEnd ( &(bzf->strm) ); 109078556Sobrien free ( bzf ); 109178556Sobrien} 109278556Sobrien 109378556Sobrien 109478556Sobrien/*---------------------------------------------------*/ 109578556SobrienBZFILE* BZ_API(BZ2_bzReadOpen) 109678556Sobrien ( int* bzerror, 109778556Sobrien FILE* f, 109878556Sobrien int verbosity, 109978556Sobrien int small, 110078556Sobrien void* unused, 110178556Sobrien int nUnused ) 110278556Sobrien{ 110378556Sobrien bzFile* bzf = NULL; 110478556Sobrien int ret; 110578556Sobrien 110678556Sobrien BZ_SETERR(BZ_OK); 110778556Sobrien 110878556Sobrien if (f == NULL || 110978556Sobrien (small != 0 && small != 1) || 111078556Sobrien (verbosity < 0 || verbosity > 4) || 111178556Sobrien (unused == NULL && nUnused != 0) || 111278556Sobrien (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED))) 111378556Sobrien { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; 111478556Sobrien 111578556Sobrien if (ferror(f)) 111678556Sobrien { BZ_SETERR(BZ_IO_ERROR); return NULL; }; 111778556Sobrien 111878556Sobrien bzf = malloc ( sizeof(bzFile) ); 111978556Sobrien if (bzf == NULL) 112078556Sobrien { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; 112178556Sobrien 112278556Sobrien BZ_SETERR(BZ_OK); 112378556Sobrien 112478556Sobrien bzf->initialisedOk = False; 112578556Sobrien bzf->handle = f; 112678556Sobrien bzf->bufN = 0; 112778556Sobrien bzf->writing = False; 112878556Sobrien bzf->strm.bzalloc = NULL; 112978556Sobrien bzf->strm.bzfree = NULL; 113078556Sobrien bzf->strm.opaque = NULL; 113178556Sobrien 113278556Sobrien while (nUnused > 0) { 113378556Sobrien bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++; 113478556Sobrien unused = ((void*)( 1 + ((UChar*)(unused)) )); 113578556Sobrien nUnused--; 113678556Sobrien } 113778556Sobrien 113878556Sobrien ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small ); 113978556Sobrien if (ret != BZ_OK) 114078556Sobrien { BZ_SETERR(ret); free(bzf); return NULL; }; 114178556Sobrien 114278556Sobrien bzf->strm.avail_in = bzf->bufN; 114378556Sobrien bzf->strm.next_in = bzf->buf; 114478556Sobrien 114578556Sobrien bzf->initialisedOk = True; 114678556Sobrien return bzf; 114778556Sobrien} 114878556Sobrien 114978556Sobrien 115078556Sobrien/*---------------------------------------------------*/ 115178556Sobrienvoid BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b ) 115278556Sobrien{ 115378556Sobrien bzFile* bzf = (bzFile*)b; 115478556Sobrien 115578556Sobrien BZ_SETERR(BZ_OK); 115678556Sobrien if (bzf == NULL) 115778556Sobrien { BZ_SETERR(BZ_OK); return; }; 115878556Sobrien 115978556Sobrien if (bzf->writing) 116078556Sobrien { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; 116178556Sobrien 116278556Sobrien if (bzf->initialisedOk) 116378556Sobrien (void)BZ2_bzDecompressEnd ( &(bzf->strm) ); 116478556Sobrien free ( bzf ); 116578556Sobrien} 116678556Sobrien 116778556Sobrien 116878556Sobrien/*---------------------------------------------------*/ 116978556Sobrienint BZ_API(BZ2_bzRead) 117078556Sobrien ( int* bzerror, 117178556Sobrien BZFILE* b, 117278556Sobrien void* buf, 117378556Sobrien int len ) 117478556Sobrien{ 117578556Sobrien Int32 n, ret; 117678556Sobrien bzFile* bzf = (bzFile*)b; 117778556Sobrien 117878556Sobrien BZ_SETERR(BZ_OK); 117978556Sobrien 118078556Sobrien if (bzf == NULL || buf == NULL || len < 0) 118178556Sobrien { BZ_SETERR(BZ_PARAM_ERROR); return 0; }; 118278556Sobrien 118378556Sobrien if (bzf->writing) 118478556Sobrien { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; }; 118578556Sobrien 118678556Sobrien if (len == 0) 118778556Sobrien { BZ_SETERR(BZ_OK); return 0; }; 118878556Sobrien 118978556Sobrien bzf->strm.avail_out = len; 119078556Sobrien bzf->strm.next_out = buf; 119178556Sobrien 119278556Sobrien while (True) { 119378556Sobrien 119478556Sobrien if (ferror(bzf->handle)) 119578556Sobrien { BZ_SETERR(BZ_IO_ERROR); return 0; }; 119678556Sobrien 119778556Sobrien if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) { 119878556Sobrien n = fread ( bzf->buf, sizeof(UChar), 119978556Sobrien BZ_MAX_UNUSED, bzf->handle ); 120078556Sobrien if (ferror(bzf->handle)) 120178556Sobrien { BZ_SETERR(BZ_IO_ERROR); return 0; }; 120278556Sobrien bzf->bufN = n; 120378556Sobrien bzf->strm.avail_in = bzf->bufN; 120478556Sobrien bzf->strm.next_in = bzf->buf; 120578556Sobrien } 120678556Sobrien 120778556Sobrien ret = BZ2_bzDecompress ( &(bzf->strm) ); 120878556Sobrien 120978556Sobrien if (ret != BZ_OK && ret != BZ_STREAM_END) 121078556Sobrien { BZ_SETERR(ret); return 0; }; 121178556Sobrien 121278556Sobrien if (ret == BZ_OK && myfeof(bzf->handle) && 121378556Sobrien bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0) 121478556Sobrien { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; }; 121578556Sobrien 121678556Sobrien if (ret == BZ_STREAM_END) 121778556Sobrien { BZ_SETERR(BZ_STREAM_END); 121878556Sobrien return len - bzf->strm.avail_out; }; 121978556Sobrien if (bzf->strm.avail_out == 0) 122078556Sobrien { BZ_SETERR(BZ_OK); return len; }; 122178556Sobrien 122278556Sobrien } 122378556Sobrien 122478556Sobrien return 0; /*not reached*/ 122578556Sobrien} 122678556Sobrien 122778556Sobrien 122878556Sobrien/*---------------------------------------------------*/ 122978556Sobrienvoid BZ_API(BZ2_bzReadGetUnused) 123078556Sobrien ( int* bzerror, 123178556Sobrien BZFILE* b, 123278556Sobrien void** unused, 123378556Sobrien int* nUnused ) 123478556Sobrien{ 123578556Sobrien bzFile* bzf = (bzFile*)b; 123678556Sobrien if (bzf == NULL) 123778556Sobrien { BZ_SETERR(BZ_PARAM_ERROR); return; }; 123878556Sobrien if (bzf->lastErr != BZ_STREAM_END) 123978556Sobrien { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; 124078556Sobrien if (unused == NULL || nUnused == NULL) 124178556Sobrien { BZ_SETERR(BZ_PARAM_ERROR); return; }; 124278556Sobrien 124378556Sobrien BZ_SETERR(BZ_OK); 124478556Sobrien *nUnused = bzf->strm.avail_in; 124578556Sobrien *unused = bzf->strm.next_in; 124678556Sobrien} 124778556Sobrien#endif 124878556Sobrien 124978556Sobrien 125078556Sobrien/*---------------------------------------------------*/ 125178556Sobrien/*--- Misc convenience stuff ---*/ 125278556Sobrien/*---------------------------------------------------*/ 125378556Sobrien 125478556Sobrien/*---------------------------------------------------*/ 125578556Sobrienint BZ_API(BZ2_bzBuffToBuffCompress) 125678556Sobrien ( char* dest, 125778556Sobrien unsigned int* destLen, 125878556Sobrien char* source, 125978556Sobrien unsigned int sourceLen, 126078556Sobrien int blockSize100k, 126178556Sobrien int verbosity, 126278556Sobrien int workFactor ) 126378556Sobrien{ 126478556Sobrien bz_stream strm; 126578556Sobrien int ret; 126678556Sobrien 126778556Sobrien if (dest == NULL || destLen == NULL || 126878556Sobrien source == NULL || 126978556Sobrien blockSize100k < 1 || blockSize100k > 9 || 127078556Sobrien verbosity < 0 || verbosity > 4 || 127178556Sobrien workFactor < 0 || workFactor > 250) 127278556Sobrien return BZ_PARAM_ERROR; 127378556Sobrien 127478556Sobrien if (workFactor == 0) workFactor = 30; 127578556Sobrien strm.bzalloc = NULL; 127678556Sobrien strm.bzfree = NULL; 127778556Sobrien strm.opaque = NULL; 127878556Sobrien ret = BZ2_bzCompressInit ( &strm, blockSize100k, 127978556Sobrien verbosity, workFactor ); 128078556Sobrien if (ret != BZ_OK) return ret; 128178556Sobrien 128278556Sobrien strm.next_in = source; 128378556Sobrien strm.next_out = dest; 128478556Sobrien strm.avail_in = sourceLen; 128578556Sobrien strm.avail_out = *destLen; 128678556Sobrien 128778556Sobrien ret = BZ2_bzCompress ( &strm, BZ_FINISH ); 128878556Sobrien if (ret == BZ_FINISH_OK) goto output_overflow; 128978556Sobrien if (ret != BZ_STREAM_END) goto errhandler; 129078556Sobrien 129178556Sobrien /* normal termination */ 129278556Sobrien *destLen -= strm.avail_out; 129378556Sobrien BZ2_bzCompressEnd ( &strm ); 129478556Sobrien return BZ_OK; 129578556Sobrien 129678556Sobrien output_overflow: 129778556Sobrien BZ2_bzCompressEnd ( &strm ); 129878556Sobrien return BZ_OUTBUFF_FULL; 129978556Sobrien 130078556Sobrien errhandler: 130178556Sobrien BZ2_bzCompressEnd ( &strm ); 130278556Sobrien return ret; 130378556Sobrien} 130478556Sobrien 130578556Sobrien 130678556Sobrien/*---------------------------------------------------*/ 130778556Sobrienint BZ_API(BZ2_bzBuffToBuffDecompress) 130878556Sobrien ( char* dest, 130978556Sobrien unsigned int* destLen, 131078556Sobrien char* source, 131178556Sobrien unsigned int sourceLen, 131278556Sobrien int small, 131378556Sobrien int verbosity ) 131478556Sobrien{ 131578556Sobrien bz_stream strm; 131678556Sobrien int ret; 131778556Sobrien 131878556Sobrien if (dest == NULL || destLen == NULL || 131978556Sobrien source == NULL || 132078556Sobrien (small != 0 && small != 1) || 132178556Sobrien verbosity < 0 || verbosity > 4) 132278556Sobrien return BZ_PARAM_ERROR; 132378556Sobrien 132478556Sobrien strm.bzalloc = NULL; 132578556Sobrien strm.bzfree = NULL; 132678556Sobrien strm.opaque = NULL; 132778556Sobrien ret = BZ2_bzDecompressInit ( &strm, verbosity, small ); 132878556Sobrien if (ret != BZ_OK) return ret; 132978556Sobrien 133078556Sobrien strm.next_in = source; 133178556Sobrien strm.next_out = dest; 133278556Sobrien strm.avail_in = sourceLen; 133378556Sobrien strm.avail_out = *destLen; 133478556Sobrien 133578556Sobrien ret = BZ2_bzDecompress ( &strm ); 133678556Sobrien if (ret == BZ_OK) goto output_overflow_or_eof; 133778556Sobrien if (ret != BZ_STREAM_END) goto errhandler; 133878556Sobrien 133978556Sobrien /* normal termination */ 134078556Sobrien *destLen -= strm.avail_out; 134178556Sobrien BZ2_bzDecompressEnd ( &strm ); 134278556Sobrien return BZ_OK; 134378556Sobrien 134478556Sobrien output_overflow_or_eof: 134578556Sobrien if (strm.avail_out > 0) { 134678556Sobrien BZ2_bzDecompressEnd ( &strm ); 134778556Sobrien return BZ_UNEXPECTED_EOF; 134878556Sobrien } else { 134978556Sobrien BZ2_bzDecompressEnd ( &strm ); 135078556Sobrien return BZ_OUTBUFF_FULL; 135178556Sobrien }; 135278556Sobrien 135378556Sobrien errhandler: 135478556Sobrien BZ2_bzDecompressEnd ( &strm ); 135578556Sobrien return ret; 135678556Sobrien} 135778556Sobrien 135878556Sobrien 135978556Sobrien/*---------------------------------------------------*/ 136078556Sobrien/*-- 1361167978Sdelphij Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp) 136278556Sobrien to support better zlib compatibility. 136378556Sobrien This code is not _officially_ part of libbzip2 (yet); 136478556Sobrien I haven't tested it, documented it, or considered the 136578556Sobrien threading-safeness of it. 136678556Sobrien If this code breaks, please contact both Yoshioka and me. 136778556Sobrien--*/ 136878556Sobrien/*---------------------------------------------------*/ 136978556Sobrien 137078556Sobrien/*---------------------------------------------------*/ 137178556Sobrien/*-- 1372167978Sdelphij return version like "0.9.5d, 4-Sept-1999". 137378556Sobrien--*/ 137478556Sobrienconst char * BZ_API(BZ2_bzlibVersion)(void) 137578556Sobrien{ 137678556Sobrien return BZ_VERSION; 137778556Sobrien} 137878556Sobrien 137978556Sobrien 138078556Sobrien#ifndef BZ_NO_STDIO 138178556Sobrien/*---------------------------------------------------*/ 138278556Sobrien 138378556Sobrien#if defined(_WIN32) || defined(OS2) || defined(MSDOS) 138478556Sobrien# include <fcntl.h> 138578556Sobrien# include <io.h> 138678556Sobrien# define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) 138778556Sobrien#else 138878556Sobrien# define SET_BINARY_MODE(file) 138978556Sobrien#endif 139078556Sobrienstatic 139178556SobrienBZFILE * bzopen_or_bzdopen 139278556Sobrien ( const char *path, /* no use when bzdopen */ 139378556Sobrien int fd, /* no use when bzdopen */ 139478556Sobrien const char *mode, 139578556Sobrien int open_mode) /* bzopen: 0, bzdopen:1 */ 139678556Sobrien{ 139778556Sobrien int bzerr; 139878556Sobrien char unused[BZ_MAX_UNUSED]; 139978556Sobrien int blockSize100k = 9; 140078556Sobrien int writing = 0; 140178556Sobrien char mode2[10] = ""; 140278556Sobrien FILE *fp = NULL; 140378556Sobrien BZFILE *bzfp = NULL; 140478556Sobrien int verbosity = 0; 140578556Sobrien int workFactor = 30; 140678556Sobrien int smallMode = 0; 140778556Sobrien int nUnused = 0; 140878556Sobrien 140978556Sobrien if (mode == NULL) return NULL; 141078556Sobrien while (*mode) { 141178556Sobrien switch (*mode) { 141278556Sobrien case 'r': 141378556Sobrien writing = 0; break; 141478556Sobrien case 'w': 141578556Sobrien writing = 1; break; 141678556Sobrien case 's': 141778556Sobrien smallMode = 1; break; 141878556Sobrien default: 141978556Sobrien if (isdigit((int)(*mode))) { 142090067Ssobomax blockSize100k = *mode-BZ_HDR_0; 142178556Sobrien } 142278556Sobrien } 142378556Sobrien mode++; 142478556Sobrien } 142578556Sobrien strcat(mode2, writing ? "w" : "r" ); 142678556Sobrien strcat(mode2,"b"); /* binary mode */ 142778556Sobrien 142878556Sobrien if (open_mode==0) { 142978556Sobrien if (path==NULL || strcmp(path,"")==0) { 143078556Sobrien fp = (writing ? stdout : stdin); 143178556Sobrien SET_BINARY_MODE(fp); 143278556Sobrien } else { 143378556Sobrien fp = fopen(path,mode2); 143478556Sobrien } 143578556Sobrien } else { 143678556Sobrien#ifdef BZ_STRICT_ANSI 143778556Sobrien fp = NULL; 143878556Sobrien#else 143978556Sobrien fp = fdopen(fd,mode2); 144078556Sobrien#endif 144178556Sobrien } 144278556Sobrien if (fp == NULL) return NULL; 144378556Sobrien 144478556Sobrien if (writing) { 144578556Sobrien /* Guard against total chaos and anarchy -- JRS */ 144678556Sobrien if (blockSize100k < 1) blockSize100k = 1; 144778556Sobrien if (blockSize100k > 9) blockSize100k = 9; 144878556Sobrien bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k, 144978556Sobrien verbosity,workFactor); 145078556Sobrien } else { 145178556Sobrien bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode, 145278556Sobrien unused,nUnused); 145378556Sobrien } 145478556Sobrien if (bzfp == NULL) { 145578556Sobrien if (fp != stdin && fp != stdout) fclose(fp); 145678556Sobrien return NULL; 145778556Sobrien } 145878556Sobrien return bzfp; 145978556Sobrien} 146078556Sobrien 146178556Sobrien 146278556Sobrien/*---------------------------------------------------*/ 146378556Sobrien/*-- 146478556Sobrien open file for read or write. 146578556Sobrien ex) bzopen("file","w9") 146678556Sobrien case path="" or NULL => use stdin or stdout. 146778556Sobrien--*/ 146878556SobrienBZFILE * BZ_API(BZ2_bzopen) 146978556Sobrien ( const char *path, 147078556Sobrien const char *mode ) 147178556Sobrien{ 147278556Sobrien return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0); 147378556Sobrien} 147478556Sobrien 147578556Sobrien 147678556Sobrien/*---------------------------------------------------*/ 147778556SobrienBZFILE * BZ_API(BZ2_bzdopen) 147878556Sobrien ( int fd, 147978556Sobrien const char *mode ) 148078556Sobrien{ 148178556Sobrien return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1); 148278556Sobrien} 148378556Sobrien 148478556Sobrien 148578556Sobrien/*---------------------------------------------------*/ 148678556Sobrienint BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len ) 148778556Sobrien{ 148878556Sobrien int bzerr, nread; 148978556Sobrien if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0; 149078556Sobrien nread = BZ2_bzRead(&bzerr,b,buf,len); 149178556Sobrien if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) { 149278556Sobrien return nread; 149378556Sobrien } else { 149478556Sobrien return -1; 149578556Sobrien } 149678556Sobrien} 149778556Sobrien 149878556Sobrien 149978556Sobrien/*---------------------------------------------------*/ 150078556Sobrienint BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len ) 150178556Sobrien{ 150278556Sobrien int bzerr; 150378556Sobrien 150478556Sobrien BZ2_bzWrite(&bzerr,b,buf,len); 150578556Sobrien if(bzerr == BZ_OK){ 150678556Sobrien return len; 150778556Sobrien }else{ 150878556Sobrien return -1; 150978556Sobrien } 151078556Sobrien} 151178556Sobrien 151278556Sobrien 151378556Sobrien/*---------------------------------------------------*/ 151478556Sobrienint BZ_API(BZ2_bzflush) (BZFILE *b) 151578556Sobrien{ 151678556Sobrien /* do nothing now... */ 151778556Sobrien return 0; 151878556Sobrien} 151978556Sobrien 152078556Sobrien 152178556Sobrien/*---------------------------------------------------*/ 152278556Sobrienvoid BZ_API(BZ2_bzclose) (BZFILE* b) 152378556Sobrien{ 152478556Sobrien int bzerr; 1525167978Sdelphij FILE *fp; 152678556Sobrien 152778556Sobrien if (b==NULL) {return;} 1528167978Sdelphij fp = ((bzFile *)b)->handle; 152978556Sobrien if(((bzFile*)b)->writing){ 153078556Sobrien BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL); 153178556Sobrien if(bzerr != BZ_OK){ 153278556Sobrien BZ2_bzWriteClose(NULL,b,1,NULL,NULL); 153378556Sobrien } 153478556Sobrien }else{ 153578556Sobrien BZ2_bzReadClose(&bzerr,b); 153678556Sobrien } 153778556Sobrien if(fp!=stdin && fp!=stdout){ 153878556Sobrien fclose(fp); 153978556Sobrien } 154078556Sobrien} 154178556Sobrien 154278556Sobrien 154378556Sobrien/*---------------------------------------------------*/ 154478556Sobrien/*-- 154578556Sobrien return last error code 154678556Sobrien--*/ 1547167978Sdelphijstatic const char *bzerrorstrings[] = { 154878556Sobrien "OK" 154978556Sobrien ,"SEQUENCE_ERROR" 155078556Sobrien ,"PARAM_ERROR" 155178556Sobrien ,"MEM_ERROR" 155278556Sobrien ,"DATA_ERROR" 155378556Sobrien ,"DATA_ERROR_MAGIC" 155478556Sobrien ,"IO_ERROR" 155578556Sobrien ,"UNEXPECTED_EOF" 155678556Sobrien ,"OUTBUFF_FULL" 155778556Sobrien ,"CONFIG_ERROR" 155878556Sobrien ,"???" /* for future */ 155978556Sobrien ,"???" /* for future */ 156078556Sobrien ,"???" /* for future */ 156178556Sobrien ,"???" /* for future */ 156278556Sobrien ,"???" /* for future */ 156378556Sobrien ,"???" /* for future */ 156478556Sobrien}; 156578556Sobrien 156678556Sobrien 156778556Sobrienconst char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum) 156878556Sobrien{ 156978556Sobrien int err = ((bzFile *)b)->lastErr; 157078556Sobrien 157178556Sobrien if(err>0) err = 0; 157278556Sobrien *errnum = err; 157378556Sobrien return bzerrorstrings[err*-1]; 157478556Sobrien} 157578556Sobrien#endif 157678556Sobrien 1577146788Ssobomax#endif /* BZ_NO_COMPRESS */ 157878556Sobrien 157978556Sobrien/*-------------------------------------------------------------*/ 158078556Sobrien/*--- end bzlib.c ---*/ 158178556Sobrien/*-------------------------------------------------------------*/ 1582