bzlib.c revision 215041
1215976Sjmallett 2232812Sjmallett/*-------------------------------------------------------------*/ 3215976Sjmallett/*--- Library top-level functions. ---*/ 4215976Sjmallett/*--- bzlib.c ---*/ 5215976Sjmallett/*-------------------------------------------------------------*/ 6215976Sjmallett 7215976Sjmallett/* ------------------------------------------------------------------ 8215976Sjmallett This file is part of bzip2/libbzip2, a program and library for 9215976Sjmallett lossless, block-sorting data compression. 10215976Sjmallett 11215976Sjmallett bzip2/libbzip2 version 1.0.6 of 6 September 2010 12215976Sjmallett Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org> 13215976Sjmallett 14215976Sjmallett Please read the WARNING, DISCLAIMER and PATENTS sections in the 15215976Sjmallett README file. 16215976Sjmallett 17215976Sjmallett This program is released under the terms of the license contained 18232812Sjmallett in the file LICENSE. 19215976Sjmallett ------------------------------------------------------------------ */ 20215976Sjmallett 21215976Sjmallett/* CHANGES 22215976Sjmallett 0.9.0 -- original version. 23215976Sjmallett 0.9.0a/b -- no changes in this file. 24215976Sjmallett 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress(). 25215976Sjmallett fixed bzWrite/bzRead to ignore zero-length requests. 26215976Sjmallett fixed bzread to correctly handle read requests after EOF. 27215976Sjmallett wrong parameter order in call to bzDecompressInit in 28215976Sjmallett bzBuffToBuffDecompress. Fixed. 29232812Sjmallett*/ 30215976Sjmallett 31215976Sjmallett#include <sys/cdefs.h> 32215976Sjmallett__FBSDID("$FreeBSD: head/contrib/bzip2/bzlib.c 215041 2010-11-09 18:32:57Z obrien $"); 33215976Sjmallett 34215976Sjmallett#include "bzlib_private.h" 35215976Sjmallett 36215976Sjmallett#ifndef BZ_NO_COMPRESS 37215976Sjmallett 38215976Sjmallett/*---------------------------------------------------*/ 39215976Sjmallett/*--- Compression stuff ---*/ 40215976Sjmallett/*---------------------------------------------------*/ 41215976Sjmallett 42215976Sjmallett 43215976Sjmallett/*---------------------------------------------------*/ 44215976Sjmallett#ifndef BZ_NO_STDIO 45215976Sjmallettvoid BZ2_bz__AssertH__fail ( int errcode ) 46215976Sjmallett{ 47215976Sjmallett fprintf(stderr, 48215976Sjmallett "\n\nbzip2/libbzip2: internal error number %d.\n" 49215976Sjmallett "This is a bug in bzip2/libbzip2, %s.\n" 50215976Sjmallett "Please report it to me at: jseward@bzip.org. If this happened\n" 51215976Sjmallett "when you were using some program which uses libbzip2 as a\n" 52232812Sjmallett "component, you should also report this bug to the author(s)\n" 53232812Sjmallett "of that program. Please make an effort to report this bug;\n" 54215976Sjmallett "timely and accurate bug reports eventually lead to higher\n" 55215976Sjmallett "quality software. Thanks. Julian Seward, 10 December 2007.\n\n", 56215976Sjmallett errcode, 57215976Sjmallett BZ2_bzlibVersion() 58215976Sjmallett ); 59232812Sjmallett 60232812Sjmallett if (errcode == 1007) { 61232812Sjmallett fprintf(stderr, 62232812Sjmallett "\n*** A special note about internal error number 1007 ***\n" 63232812Sjmallett "\n" 64215976Sjmallett "Experience suggests that a common cause of i.e. 1007\n" 65215976Sjmallett "is unreliable memory or other hardware. The 1007 assertion\n" 66215976Sjmallett "just happens to cross-check the results of huge numbers of\n" 67215976Sjmallett "memory reads/writes, and so acts (unintendedly) as a stress\n" 68215976Sjmallett "test of your memory system.\n" 69215976Sjmallett "\n" 70215976Sjmallett "I suggest the following: try compressing the file again,\n" 71215976Sjmallett "possibly monitoring progress in detail with the -vv flag.\n" 72215976Sjmallett "\n" 73215976Sjmallett "* If the error cannot be reproduced, and/or happens at different\n" 74232812Sjmallett " points in compression, you may have a flaky memory system.\n" 75232812Sjmallett " Try a memory-test program. I have used Memtest86\n" 76232812Sjmallett " (www.memtest86.com). At the time of writing it is free (GPLd).\n" 77232812Sjmallett " Memtest86 tests memory much more thorougly than your BIOSs\n" 78232812Sjmallett " power-on test, and may find failures that the BIOS doesn't.\n" 79215976Sjmallett "\n" 80215976Sjmallett "* If the error can be repeatably reproduced, this is a bug in\n" 81215976Sjmallett " bzip2, and I would very much like to hear about it. Please\n" 82215976Sjmallett " let me know, and, ideally, save a copy of the file causing the\n" 83215976Sjmallett " problem -- without which I will be unable to investigate it.\n" 84215976Sjmallett "\n" 85215976Sjmallett ); 86215976Sjmallett } 87215976Sjmallett 88215976Sjmallett exit(3); 89232812Sjmallett} 90232812Sjmallett#endif 91232812Sjmallett 92232812Sjmallett#endif /* BZ_NO_COMPRESS */ 93232812Sjmallett 94215976Sjmallett/*---------------------------------------------------*/ 95215976Sjmallettstatic 96215976Sjmallettint bz_config_ok ( void ) 97215976Sjmallett{ 98215976Sjmallett if (sizeof(int) != 4) return 0; 99215976Sjmallett if (sizeof(short) != 2) return 0; 100215976Sjmallett if (sizeof(char) != 1) return 0; 101215976Sjmallett return 1; 102215976Sjmallett} 103215976Sjmallett 104232812Sjmallett 105232812Sjmallett/*---------------------------------------------------*/ 106232812Sjmallettstatic 107232812Sjmallettvoid* default_bzalloc ( void* opaque, Int32 items, Int32 size ) 108232812Sjmallett{ 109215976Sjmallett void* v = malloc ( items * size ); 110215976Sjmallett return v; 111215976Sjmallett} 112215976Sjmallett 113215976Sjmallettstatic 114215976Sjmallettvoid default_bzfree ( void* opaque, void* addr ) 115215976Sjmallett{ 116215976Sjmallett if (addr != NULL) free ( addr ); 117215976Sjmallett} 118215976Sjmallett 119232812Sjmallett#ifndef BZ_NO_COMPRESS 120232812Sjmallett 121232812Sjmallett/*---------------------------------------------------*/ 122232812Sjmallettstatic 123232812Sjmallettvoid prepare_new_block ( EState* s ) 124215976Sjmallett{ 125215976Sjmallett Int32 i; 126215976Sjmallett s->nblock = 0; 127215976Sjmallett s->numZ = 0; 128215976Sjmallett s->state_out_pos = 0; 129215976Sjmallett BZ_INITIALISE_CRC ( s->blockCRC ); 130215976Sjmallett for (i = 0; i < 256; i++) s->inUse[i] = False; 131215976Sjmallett s->blockNo++; 132215976Sjmallett} 133215976Sjmallett 134232812Sjmallett 135232812Sjmallett/*---------------------------------------------------*/ 136232812Sjmallettstatic 137232812Sjmallettvoid init_RL ( EState* s ) 138232812Sjmallett{ 139215976Sjmallett s->state_in_ch = 256; 140215976Sjmallett s->state_in_len = 0; 141215976Sjmallett} 142215976Sjmallett 143215976Sjmallett 144215976Sjmallettstatic 145215976SjmallettBool isempty_RL ( EState* s ) 146215976Sjmallett{ 147215976Sjmallett if (s->state_in_ch < 256 && s->state_in_len > 0) 148215976Sjmallett return False; else 149232812Sjmallett return True; 150232812Sjmallett} 151232812Sjmallett 152232812Sjmallett 153232812Sjmallett/*---------------------------------------------------*/ 154215976Sjmallettint BZ_API(BZ2_bzCompressInit) 155215976Sjmallett ( bz_stream* strm, 156215976Sjmallett int blockSize100k, 157215976Sjmallett int verbosity, 158215976Sjmallett int workFactor ) 159215976Sjmallett{ 160215976Sjmallett Int32 n; 161215976Sjmallett EState* s; 162215976Sjmallett 163215976Sjmallett if (!bz_config_ok()) return BZ_CONFIG_ERROR; 164232812Sjmallett 165232812Sjmallett if (strm == NULL || 166232812Sjmallett blockSize100k < 1 || blockSize100k > 9 || 167232812Sjmallett workFactor < 0 || workFactor > 250) 168232812Sjmallett return BZ_PARAM_ERROR; 169215976Sjmallett 170215976Sjmallett if (workFactor == 0) workFactor = 30; 171215976Sjmallett if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; 172215976Sjmallett if (strm->bzfree == NULL) strm->bzfree = default_bzfree; 173215976Sjmallett 174215976Sjmallett s = BZALLOC( sizeof(EState) ); 175215976Sjmallett if (s == NULL) return BZ_MEM_ERROR; 176215976Sjmallett s->strm = strm; 177215976Sjmallett 178215976Sjmallett s->arr1 = NULL; 179232812Sjmallett s->arr2 = NULL; 180232812Sjmallett s->ftab = NULL; 181232812Sjmallett 182232812Sjmallett n = 100000 * blockSize100k; 183232812Sjmallett s->arr1 = BZALLOC( n * sizeof(UInt32) ); 184215976Sjmallett s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) ); 185215976Sjmallett s->ftab = BZALLOC( 65537 * sizeof(UInt32) ); 186215976Sjmallett 187215976Sjmallett if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) { 188215976Sjmallett if (s->arr1 != NULL) BZFREE(s->arr1); 189215976Sjmallett if (s->arr2 != NULL) BZFREE(s->arr2); 190215976Sjmallett if (s->ftab != NULL) BZFREE(s->ftab); 191215976Sjmallett if (s != NULL) BZFREE(s); 192215976Sjmallett return BZ_MEM_ERROR; 193215976Sjmallett } 194232812Sjmallett 195232812Sjmallett s->blockNo = 0; 196232812Sjmallett s->state = BZ_S_INPUT; 197232812Sjmallett s->mode = BZ_M_RUNNING; 198232812Sjmallett s->combinedCRC = 0; 199215976Sjmallett s->blockSize100k = blockSize100k; 200215976Sjmallett s->nblockMAX = 100000 * blockSize100k - 19; 201215976Sjmallett s->verbosity = verbosity; 202215976Sjmallett s->workFactor = workFactor; 203215976Sjmallett 204215976Sjmallett s->block = (UChar*)s->arr2; 205215976Sjmallett s->mtfv = (UInt16*)s->arr1; 206215976Sjmallett s->zbits = NULL; 207215976Sjmallett s->ptr = (UInt32*)s->arr1; 208215976Sjmallett 209232812Sjmallett strm->state = s; 210232812Sjmallett strm->total_in_lo32 = 0; 211232812Sjmallett strm->total_in_hi32 = 0; 212232812Sjmallett strm->total_out_lo32 = 0; 213215976Sjmallett strm->total_out_hi32 = 0; 214215976Sjmallett init_RL ( s ); 215215976Sjmallett prepare_new_block ( s ); 216215976Sjmallett return BZ_OK; 217215976Sjmallett} 218215976Sjmallett 219215976Sjmallett 220215976Sjmallett/*---------------------------------------------------*/ 221215976Sjmallettstatic 222215976Sjmallettvoid add_pair_to_block ( EState* s ) 223232812Sjmallett{ 224232812Sjmallett Int32 i; 225232812Sjmallett UChar ch = (UChar)(s->state_in_ch); 226232812Sjmallett for (i = 0; i < s->state_in_len; i++) { 227232812Sjmallett BZ_UPDATE_CRC( s->blockCRC, ch ); 228215976Sjmallett } 229215976Sjmallett s->inUse[s->state_in_ch] = True; 230215976Sjmallett switch (s->state_in_len) { 231215976Sjmallett case 1: 232215976Sjmallett s->block[s->nblock] = (UChar)ch; s->nblock++; 233215976Sjmallett break; 234215976Sjmallett case 2: 235215976Sjmallett s->block[s->nblock] = (UChar)ch; s->nblock++; 236215976Sjmallett s->block[s->nblock] = (UChar)ch; s->nblock++; 237215976Sjmallett break; 238232812Sjmallett case 3: 239232812Sjmallett s->block[s->nblock] = (UChar)ch; s->nblock++; 240232812Sjmallett s->block[s->nblock] = (UChar)ch; s->nblock++; 241232812Sjmallett s->block[s->nblock] = (UChar)ch; s->nblock++; 242232812Sjmallett break; 243215976Sjmallett default: 244215976Sjmallett s->inUse[s->state_in_len-4] = True; 245215976Sjmallett s->block[s->nblock] = (UChar)ch; s->nblock++; 246215976Sjmallett s->block[s->nblock] = (UChar)ch; s->nblock++; 247215976Sjmallett s->block[s->nblock] = (UChar)ch; s->nblock++; 248215976Sjmallett s->block[s->nblock] = (UChar)ch; s->nblock++; 249215976Sjmallett s->block[s->nblock] = ((UChar)(s->state_in_len-4)); 250215976Sjmallett s->nblock++; 251215976Sjmallett break; 252215976Sjmallett } 253215976Sjmallett} 254215976Sjmallett 255215976Sjmallett 256215976Sjmallett/*---------------------------------------------------*/ 257232812Sjmallettstatic 258215976Sjmallettvoid flush_RL ( EState* s ) 259232812Sjmallett{ 260232812Sjmallett if (s->state_in_ch < 256) add_pair_to_block ( s ); 261215976Sjmallett init_RL ( s ); 262215976Sjmallett} 263215976Sjmallett 264215976Sjmallett 265215976Sjmallett/*---------------------------------------------------*/ 266215976Sjmallett#define ADD_CHAR_TO_BLOCK(zs,zchh0) \ 267215976Sjmallett{ \ 268215976Sjmallett UInt32 zchh = (UInt32)(zchh0); \ 269215976Sjmallett /*-- fast track the common case --*/ \ 270215976Sjmallett if (zchh != zs->state_in_ch && \ 271215976Sjmallett zs->state_in_len == 1) { \ 272215976Sjmallett UChar ch = (UChar)(zs->state_in_ch); \ 273215976Sjmallett BZ_UPDATE_CRC( zs->blockCRC, ch ); \ 274215976Sjmallett zs->inUse[zs->state_in_ch] = True; \ 275215976Sjmallett zs->block[zs->nblock] = (UChar)ch; \ 276215976Sjmallett zs->nblock++; \ 277215976Sjmallett zs->state_in_ch = zchh; \ 278232812Sjmallett } \ 279215976Sjmallett else \ 280215976Sjmallett /*-- general, uncommon cases --*/ \ 281232812Sjmallett if (zchh != zs->state_in_ch || \ 282232812Sjmallett zs->state_in_len == 255) { \ 283232812Sjmallett if (zs->state_in_ch < 256) \ 284232812Sjmallett add_pair_to_block ( zs ); \ 285215976Sjmallett zs->state_in_ch = zchh; \ 286215976Sjmallett zs->state_in_len = 1; \ 287215976Sjmallett } else { \ 288215976Sjmallett zs->state_in_len++; \ 289215976Sjmallett } \ 290215976Sjmallett} 291215976Sjmallett 292215976Sjmallett 293215976Sjmallett/*---------------------------------------------------*/ 294232812Sjmallettstatic 295215976SjmallettBool copy_input_until_stop ( EState* s ) 296232812Sjmallett{ 297232812Sjmallett Bool progress_in = False; 298215976Sjmallett 299215976Sjmallett if (s->mode == BZ_M_RUNNING) { 300215976Sjmallett 301215976Sjmallett /*-- fast track the common case --*/ 302215976Sjmallett while (True) { 303215976Sjmallett /*-- block full? --*/ 304215976Sjmallett if (s->nblock >= s->nblockMAX) break; 305215976Sjmallett /*-- no input? --*/ 306215976Sjmallett if (s->strm->avail_in == 0) break; 307215976Sjmallett progress_in = True; 308215976Sjmallett ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 309215976Sjmallett s->strm->next_in++; 310215976Sjmallett s->strm->avail_in--; 311215976Sjmallett s->strm->total_in_lo32++; 312215976Sjmallett if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; 313215976Sjmallett } 314215976Sjmallett 315215976Sjmallett } else { 316215976Sjmallett 317215976Sjmallett /*-- general, uncommon case --*/ 318215976Sjmallett while (True) { 319215976Sjmallett /*-- block full? --*/ 320215976Sjmallett if (s->nblock >= s->nblockMAX) break; 321215976Sjmallett /*-- no input? --*/ 322215976Sjmallett if (s->strm->avail_in == 0) break; 323215976Sjmallett /*-- flush/finish end? --*/ 324215976Sjmallett if (s->avail_in_expect == 0) break; 325215976Sjmallett progress_in = True; 326215976Sjmallett ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 327215976Sjmallett s->strm->next_in++; 328215976Sjmallett s->strm->avail_in--; 329215976Sjmallett s->strm->total_in_lo32++; 330215976Sjmallett if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; 331215976Sjmallett s->avail_in_expect--; 332215976Sjmallett } 333215976Sjmallett } 334215976Sjmallett return progress_in; 335215976Sjmallett} 336215976Sjmallett 337215976Sjmallett 338215976Sjmallett/*---------------------------------------------------*/ 339215976Sjmallettstatic 340215976SjmallettBool copy_output_until_stop ( EState* s ) 341215976Sjmallett{ 342215976Sjmallett Bool progress_out = False; 343215976Sjmallett 344215976Sjmallett while (True) { 345215976Sjmallett 346215976Sjmallett /*-- no output space? --*/ 347215976Sjmallett if (s->strm->avail_out == 0) break; 348215976Sjmallett 349215976Sjmallett /*-- block done? --*/ 350215976Sjmallett if (s->state_out_pos >= s->numZ) break; 351215976Sjmallett 352215976Sjmallett progress_out = True; 353215976Sjmallett *(s->strm->next_out) = s->zbits[s->state_out_pos]; 354215976Sjmallett s->state_out_pos++; 355232812Sjmallett s->strm->avail_out--; 356215976Sjmallett s->strm->next_out++; 357215976Sjmallett s->strm->total_out_lo32++; 358232812Sjmallett if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; 359232812Sjmallett } 360232812Sjmallett 361232812Sjmallett return progress_out; 362215976Sjmallett} 363215976Sjmallett 364215976Sjmallett 365215976Sjmallett/*---------------------------------------------------*/ 366215976Sjmallettstatic 367215976SjmallettBool handle_compress ( bz_stream* strm ) 368215976Sjmallett{ 369215976Sjmallett Bool progress_in = False; 370215976Sjmallett Bool progress_out = False; 371215976Sjmallett EState* s = strm->state; 372215976Sjmallett 373215976Sjmallett while (True) { 374215976Sjmallett 375215976Sjmallett if (s->state == BZ_S_OUTPUT) { 376215976Sjmallett progress_out |= copy_output_until_stop ( s ); 377215976Sjmallett if (s->state_out_pos < s->numZ) break; 378215976Sjmallett if (s->mode == BZ_M_FINISHING && 379215976Sjmallett s->avail_in_expect == 0 && 380215976Sjmallett isempty_RL(s)) break; 381215976Sjmallett prepare_new_block ( s ); 382215976Sjmallett s->state = BZ_S_INPUT; 383215976Sjmallett if (s->mode == BZ_M_FLUSHING && 384215976Sjmallett s->avail_in_expect == 0 && 385215976Sjmallett isempty_RL(s)) break; 386215976Sjmallett } 387215976Sjmallett 388215976Sjmallett if (s->state == BZ_S_INPUT) { 389215976Sjmallett progress_in |= copy_input_until_stop ( s ); 390215976Sjmallett if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) { 391215976Sjmallett flush_RL ( s ); 392215976Sjmallett BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) ); 393215976Sjmallett s->state = BZ_S_OUTPUT; 394215976Sjmallett } 395215976Sjmallett else 396215976Sjmallett if (s->nblock >= s->nblockMAX) { 397215976Sjmallett BZ2_compressBlock ( s, False ); 398215976Sjmallett s->state = BZ_S_OUTPUT; 399215976Sjmallett } 400215976Sjmallett else 401215976Sjmallett if (s->strm->avail_in == 0) { 402215976Sjmallett break; 403215976Sjmallett } 404215976Sjmallett } 405215976Sjmallett 406215976Sjmallett } 407215976Sjmallett 408215976Sjmallett return progress_in || progress_out; 409232812Sjmallett} 410215976Sjmallett 411215976Sjmallett 412232812Sjmallett/*---------------------------------------------------*/ 413232812Sjmallettint BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action ) 414232812Sjmallett{ 415232812Sjmallett Bool progress; 416215976Sjmallett EState* s; 417215976Sjmallett if (strm == NULL) return BZ_PARAM_ERROR; 418215976Sjmallett s = strm->state; 419215976Sjmallett if (s == NULL) return BZ_PARAM_ERROR; 420215976Sjmallett if (s->strm != strm) return BZ_PARAM_ERROR; 421215976Sjmallett 422215976Sjmallett preswitch: 423215976Sjmallett switch (s->mode) { 424215976Sjmallett 425232812Sjmallett case BZ_M_IDLE: 426215976Sjmallett return BZ_SEQUENCE_ERROR; 427232812Sjmallett 428232812Sjmallett case BZ_M_RUNNING: 429215976Sjmallett if (action == BZ_RUN) { 430215976Sjmallett progress = handle_compress ( strm ); 431215976Sjmallett return progress ? BZ_RUN_OK : BZ_PARAM_ERROR; 432215976Sjmallett } 433215976Sjmallett else 434215976Sjmallett if (action == BZ_FLUSH) { 435215976Sjmallett s->avail_in_expect = strm->avail_in; 436215976Sjmallett s->mode = BZ_M_FLUSHING; 437215976Sjmallett goto preswitch; 438215976Sjmallett } 439215976Sjmallett else 440215976Sjmallett if (action == BZ_FINISH) { 441215976Sjmallett s->avail_in_expect = strm->avail_in; 442215976Sjmallett s->mode = BZ_M_FINISHING; 443215976Sjmallett goto preswitch; 444215976Sjmallett } 445215976Sjmallett else 446215976Sjmallett return BZ_PARAM_ERROR; 447215976Sjmallett 448215976Sjmallett case BZ_M_FLUSHING: 449215976Sjmallett if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR; 450215976Sjmallett if (s->avail_in_expect != s->strm->avail_in) 451215976Sjmallett return BZ_SEQUENCE_ERROR; 452215976Sjmallett progress = handle_compress ( strm ); 453215976Sjmallett if (s->avail_in_expect > 0 || !isempty_RL(s) || 454215976Sjmallett s->state_out_pos < s->numZ) return BZ_FLUSH_OK; 455215976Sjmallett s->mode = BZ_M_RUNNING; 456215976Sjmallett return BZ_RUN_OK; 457215976Sjmallett 458215976Sjmallett case BZ_M_FINISHING: 459215976Sjmallett if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR; 460215976Sjmallett if (s->avail_in_expect != s->strm->avail_in) 461215976Sjmallett return BZ_SEQUENCE_ERROR; 462215976Sjmallett progress = handle_compress ( strm ); 463215976Sjmallett if (!progress) return BZ_SEQUENCE_ERROR; 464215976Sjmallett if (s->avail_in_expect > 0 || !isempty_RL(s) || 465215976Sjmallett s->state_out_pos < s->numZ) return BZ_FINISH_OK; 466215976Sjmallett s->mode = BZ_M_IDLE; 467215976Sjmallett return BZ_STREAM_END; 468215976Sjmallett } 469215976Sjmallett return BZ_OK; /*--not reached--*/ 470215976Sjmallett} 471215976Sjmallett 472215976Sjmallett 473215976Sjmallett/*---------------------------------------------------*/ 474215976Sjmallettint BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm ) 475215976Sjmallett{ 476215976Sjmallett EState* s; 477215976Sjmallett if (strm == NULL) return BZ_PARAM_ERROR; 478215976Sjmallett s = strm->state; 479215976Sjmallett if (s == NULL) return BZ_PARAM_ERROR; 480215976Sjmallett if (s->strm != strm) return BZ_PARAM_ERROR; 481215976Sjmallett 482215976Sjmallett if (s->arr1 != NULL) BZFREE(s->arr1); 483215976Sjmallett if (s->arr2 != NULL) BZFREE(s->arr2); 484232812Sjmallett if (s->ftab != NULL) BZFREE(s->ftab); 485215976Sjmallett BZFREE(strm->state); 486215976Sjmallett 487232812Sjmallett strm->state = NULL; 488232812Sjmallett 489232812Sjmallett return BZ_OK; 490232812Sjmallett} 491215976Sjmallett 492215976Sjmallett#endif /* BZ_NO_COMPRESS */ 493215976Sjmallett 494215976Sjmallett/*---------------------------------------------------*/ 495215976Sjmallett/*--- Decompression stuff ---*/ 496215976Sjmallett/*---------------------------------------------------*/ 497215976Sjmallett 498215976Sjmallett/*---------------------------------------------------*/ 499215976Sjmallettint BZ_API(BZ2_bzDecompressInit) 500232812Sjmallett ( bz_stream* strm, 501215976Sjmallett int verbosity, 502232812Sjmallett int small ) 503232812Sjmallett{ 504215976Sjmallett DState* s; 505215976Sjmallett 506215976Sjmallett if (!bz_config_ok()) return BZ_CONFIG_ERROR; 507232812Sjmallett 508232812Sjmallett if (strm == NULL) return BZ_PARAM_ERROR; 509232812Sjmallett if (small != 0 && small != 1) return BZ_PARAM_ERROR; 510232812Sjmallett if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR; 511232812Sjmallett 512232812Sjmallett if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; 513232812Sjmallett if (strm->bzfree == NULL) strm->bzfree = default_bzfree; 514232812Sjmallett 515232812Sjmallett s = BZALLOC( sizeof(DState) ); 516232812Sjmallett if (s == NULL) return BZ_MEM_ERROR; 517232812Sjmallett s->strm = strm; 518232812Sjmallett strm->state = s; 519232812Sjmallett s->state = BZ_X_MAGIC_1; 520232812Sjmallett s->bsLive = 0; 521232812Sjmallett s->bsBuff = 0; 522232812Sjmallett s->calculatedCombinedCRC = 0; 523232812Sjmallett strm->total_in_lo32 = 0; 524232812Sjmallett strm->total_in_hi32 = 0; 525215976Sjmallett strm->total_out_lo32 = 0; 526215976Sjmallett strm->total_out_hi32 = 0; 527215976Sjmallett s->smallDecompress = (Bool)small; 528215976Sjmallett s->ll4 = NULL; 529215976Sjmallett s->ll16 = NULL; 530215976Sjmallett s->tt = NULL; 531215976Sjmallett s->currBlockNo = 0; 532232812Sjmallett s->verbosity = verbosity; 533215976Sjmallett 534215976Sjmallett return BZ_OK; 535232812Sjmallett} 536232812Sjmallett 537232812Sjmallett 538232812Sjmallett/*---------------------------------------------------*/ 539215976Sjmallett/* Return True iff data corruption is discovered. 540215976Sjmallett Returns False if there is no problem. 541215976Sjmallett*/ 542215976Sjmallettstatic 543215976SjmallettBool unRLE_obuf_to_output_FAST ( DState* s ) 544215976Sjmallett{ 545215976Sjmallett UChar k1; 546215976Sjmallett 547215976Sjmallett if (s->blockRandomised) { 548232812Sjmallett 549215976Sjmallett while (True) { 550232812Sjmallett /* try to finish existing run */ 551232812Sjmallett while (True) { 552215976Sjmallett if (s->strm->avail_out == 0) return False; 553215976Sjmallett if (s->state_out_len == 0) break; 554215976Sjmallett *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; 555215976Sjmallett BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); 556215976Sjmallett s->state_out_len--; 557215976Sjmallett s->strm->next_out++; 558215976Sjmallett s->strm->avail_out--; 559215976Sjmallett s->strm->total_out_lo32++; 560215976Sjmallett if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; 561215976Sjmallett } 562232812Sjmallett 563215976Sjmallett /* can a new run be started? */ 564215976Sjmallett if (s->nblock_used == s->save_nblock+1) return False; 565232812Sjmallett 566232812Sjmallett /* Only caused by corrupt data stream? */ 567232812Sjmallett if (s->nblock_used > s->save_nblock+1) 568232812Sjmallett return True; 569215976Sjmallett 570215976Sjmallett s->state_out_len = 1; 571215976Sjmallett s->state_out_ch = s->k0; 572215976Sjmallett BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 573215976Sjmallett k1 ^= BZ_RAND_MASK; s->nblock_used++; 574215976Sjmallett if (s->nblock_used == s->save_nblock+1) continue; 575215976Sjmallett if (k1 != s->k0) { s->k0 = k1; continue; }; 576215976Sjmallett 577215976Sjmallett s->state_out_len = 2; 578215976Sjmallett BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 579232812Sjmallett k1 ^= BZ_RAND_MASK; s->nblock_used++; 580215976Sjmallett if (s->nblock_used == s->save_nblock+1) continue; 581232812Sjmallett if (k1 != s->k0) { s->k0 = k1; continue; }; 582232812Sjmallett 583215976Sjmallett s->state_out_len = 3; 584215976Sjmallett BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 585215976Sjmallett k1 ^= BZ_RAND_MASK; s->nblock_used++; 586215976Sjmallett if (s->nblock_used == s->save_nblock+1) continue; 587215976Sjmallett if (k1 != s->k0) { s->k0 = k1; continue; }; 588215976Sjmallett 589215976Sjmallett BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 590232812Sjmallett k1 ^= BZ_RAND_MASK; s->nblock_used++; 591215976Sjmallett s->state_out_len = ((Int32)k1) + 4; 592215976Sjmallett BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; 593232812Sjmallett s->k0 ^= BZ_RAND_MASK; s->nblock_used++; 594232812Sjmallett } 595232812Sjmallett 596232812Sjmallett } else { 597215976Sjmallett 598215976Sjmallett /* restore */ 599215976Sjmallett UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC; 600215976Sjmallett UChar c_state_out_ch = s->state_out_ch; 601215976Sjmallett Int32 c_state_out_len = s->state_out_len; 602215976Sjmallett Int32 c_nblock_used = s->nblock_used; 603215976Sjmallett Int32 c_k0 = s->k0; 604215976Sjmallett UInt32* c_tt = s->tt; 605215976Sjmallett UInt32 c_tPos = s->tPos; 606215976Sjmallett char* cs_next_out = s->strm->next_out; 607232812Sjmallett unsigned int cs_avail_out = s->strm->avail_out; 608215976Sjmallett Int32 ro_blockSize100k = s->blockSize100k; 609232812Sjmallett /* end restore */ 610232812Sjmallett 611215976Sjmallett UInt32 avail_out_INIT = cs_avail_out; 612215976Sjmallett Int32 s_save_nblockPP = s->save_nblock+1; 613215976Sjmallett unsigned int total_out_lo32_old; 614215976Sjmallett 615215976Sjmallett while (True) { 616215976Sjmallett 617215976Sjmallett /* try to finish existing run */ 618215976Sjmallett if (c_state_out_len > 0) { 619215976Sjmallett while (True) { 620215976Sjmallett if (cs_avail_out == 0) goto return_notr; 621215976Sjmallett if (c_state_out_len == 1) break; 622215976Sjmallett *( (UChar*)(cs_next_out) ) = c_state_out_ch; 623215976Sjmallett BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); 624215976Sjmallett c_state_out_len--; 625215976Sjmallett cs_next_out++; 626215976Sjmallett cs_avail_out--; 627215976Sjmallett } 628215976Sjmallett s_state_out_len_eq_one: 629215976Sjmallett { 630215976Sjmallett if (cs_avail_out == 0) { 631215976Sjmallett c_state_out_len = 1; goto return_notr; 632232812Sjmallett }; 633215976Sjmallett *( (UChar*)(cs_next_out) ) = c_state_out_ch; 634215976Sjmallett BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); 635232812Sjmallett cs_next_out++; 636232812Sjmallett cs_avail_out--; 637232812Sjmallett } 638232812Sjmallett } 639215976Sjmallett /* Only caused by corrupt data stream? */ 640215976Sjmallett if (c_nblock_used > s_save_nblockPP) 641215976Sjmallett return True; 642215976Sjmallett 643215976Sjmallett /* can a new run be started? */ 644215976Sjmallett if (c_nblock_used == s_save_nblockPP) { 645215976Sjmallett c_state_out_len = 0; goto return_notr; 646215976Sjmallett }; 647215976Sjmallett c_state_out_ch = c_k0; 648215976Sjmallett BZ_GET_FAST_C(k1); c_nblock_used++; 649232812Sjmallett if (k1 != c_k0) { 650215976Sjmallett c_k0 = k1; goto s_state_out_len_eq_one; 651232812Sjmallett }; 652232812Sjmallett if (c_nblock_used == s_save_nblockPP) 653215976Sjmallett goto s_state_out_len_eq_one; 654215976Sjmallett 655215976Sjmallett c_state_out_len = 2; 656215976Sjmallett BZ_GET_FAST_C(k1); c_nblock_used++; 657215976Sjmallett if (c_nblock_used == s_save_nblockPP) continue; 658215976Sjmallett if (k1 != c_k0) { c_k0 = k1; continue; }; 659215976Sjmallett 660215976Sjmallett c_state_out_len = 3; 661215976Sjmallett BZ_GET_FAST_C(k1); c_nblock_used++; 662215976Sjmallett if (c_nblock_used == s_save_nblockPP) continue; 663215976Sjmallett if (k1 != c_k0) { c_k0 = k1; continue; }; 664215976Sjmallett 665215976Sjmallett BZ_GET_FAST_C(k1); c_nblock_used++; 666215976Sjmallett c_state_out_len = ((Int32)k1) + 4; 667215976Sjmallett BZ_GET_FAST_C(c_k0); c_nblock_used++; 668215976Sjmallett } 669215976Sjmallett 670215976Sjmallett return_notr: 671215976Sjmallett total_out_lo32_old = s->strm->total_out_lo32; 672215976Sjmallett s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out); 673215976Sjmallett if (s->strm->total_out_lo32 < total_out_lo32_old) 674215976Sjmallett s->strm->total_out_hi32++; 675215976Sjmallett 676215976Sjmallett /* save */ 677215976Sjmallett s->calculatedBlockCRC = c_calculatedBlockCRC; 678232812Sjmallett s->state_out_ch = c_state_out_ch; 679215976Sjmallett s->state_out_len = c_state_out_len; 680215976Sjmallett s->nblock_used = c_nblock_used; 681232812Sjmallett s->k0 = c_k0; 682232812Sjmallett s->tt = c_tt; 683232812Sjmallett s->tPos = c_tPos; 684232812Sjmallett s->strm->next_out = cs_next_out; 685215976Sjmallett s->strm->avail_out = cs_avail_out; 686215976Sjmallett /* end save */ 687215976Sjmallett } 688215976Sjmallett return False; 689215976Sjmallett} 690215976Sjmallett 691215976Sjmallett 692215976Sjmallett 693215976Sjmallett/*---------------------------------------------------*/ 694215976Sjmallett__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab ) 695215976Sjmallett{ 696232812Sjmallett Int32 nb, na, mid; 697215976Sjmallett nb = 0; 698232812Sjmallett na = 256; 699232812Sjmallett do { 700215976Sjmallett mid = (nb + na) >> 1; 701215976Sjmallett if (indx >= cftab[mid]) nb = mid; else na = mid; 702215976Sjmallett } 703215976Sjmallett while (na - nb != 1); 704215976Sjmallett return nb; 705215976Sjmallett} 706215976Sjmallett 707215976Sjmallett 708215976Sjmallett/*---------------------------------------------------*/ 709215976Sjmallett/* Return True iff data corruption is discovered. 710215976Sjmallett Returns False if there is no problem. 711215976Sjmallett*/ 712215976Sjmallettstatic 713215976SjmallettBool unRLE_obuf_to_output_SMALL ( DState* s ) 714215976Sjmallett{ 715215976Sjmallett UChar k1; 716215976Sjmallett 717215976Sjmallett if (s->blockRandomised) { 718215976Sjmallett 719215976Sjmallett while (True) { 720215976Sjmallett /* try to finish existing run */ 721215976Sjmallett while (True) { 722215976Sjmallett if (s->strm->avail_out == 0) return False; 723215976Sjmallett if (s->state_out_len == 0) break; 724215976Sjmallett *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; 725215976Sjmallett BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); 726215976Sjmallett s->state_out_len--; 727215976Sjmallett s->strm->next_out++; 728215976Sjmallett s->strm->avail_out--; 729215976Sjmallett s->strm->total_out_lo32++; 730215976Sjmallett if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; 731215976Sjmallett } 732215976Sjmallett 733215976Sjmallett /* can a new run be started? */ 734215976Sjmallett if (s->nblock_used == s->save_nblock+1) return False; 735215976Sjmallett 736215976Sjmallett /* Only caused by corrupt data stream? */ 737215976Sjmallett if (s->nblock_used > s->save_nblock+1) 738215976Sjmallett return True; 739215976Sjmallett 740215976Sjmallett s->state_out_len = 1; 741215976Sjmallett s->state_out_ch = s->k0; 742215976Sjmallett BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 743215976Sjmallett k1 ^= BZ_RAND_MASK; s->nblock_used++; 744232812Sjmallett if (s->nblock_used == s->save_nblock+1) continue; 745215976Sjmallett if (k1 != s->k0) { s->k0 = k1; continue; }; 746215976Sjmallett 747232812Sjmallett s->state_out_len = 2; 748232812Sjmallett BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 749232812Sjmallett k1 ^= BZ_RAND_MASK; s->nblock_used++; 750232812Sjmallett if (s->nblock_used == s->save_nblock+1) continue; 751215976Sjmallett if (k1 != s->k0) { s->k0 = k1; continue; }; 752215976Sjmallett 753215976Sjmallett s->state_out_len = 3; 754215976Sjmallett BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 755215976Sjmallett k1 ^= BZ_RAND_MASK; s->nblock_used++; 756215976Sjmallett if (s->nblock_used == s->save_nblock+1) continue; 757215976Sjmallett if (k1 != s->k0) { s->k0 = k1; continue; }; 758215976Sjmallett 759215976Sjmallett BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 760232812Sjmallett k1 ^= BZ_RAND_MASK; s->nblock_used++; 761215976Sjmallett s->state_out_len = ((Int32)k1) + 4; 762232812Sjmallett BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; 763232812Sjmallett s->k0 ^= BZ_RAND_MASK; s->nblock_used++; 764215976Sjmallett } 765215976Sjmallett 766215976Sjmallett } else { 767215976Sjmallett 768215976Sjmallett while (True) { 769215976Sjmallett /* try to finish existing run */ 770215976Sjmallett while (True) { 771215976Sjmallett if (s->strm->avail_out == 0) return False; 772215976Sjmallett if (s->state_out_len == 0) break; 773215976Sjmallett *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; 774232812Sjmallett BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); 775215976Sjmallett s->state_out_len--; 776215976Sjmallett s->strm->next_out++; 777232812Sjmallett s->strm->avail_out--; 778232812Sjmallett s->strm->total_out_lo32++; 779232812Sjmallett if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; 780232812Sjmallett } 781215976Sjmallett 782215976Sjmallett /* can a new run be started? */ 783215976Sjmallett if (s->nblock_used == s->save_nblock+1) return False; 784215976Sjmallett 785215976Sjmallett /* Only caused by corrupt data stream? */ 786215976Sjmallett if (s->nblock_used > s->save_nblock+1) 787215976Sjmallett return True; 788215976Sjmallett 789215976Sjmallett s->state_out_len = 1; 790215976Sjmallett s->state_out_ch = s->k0; 791232812Sjmallett BZ_GET_SMALL(k1); s->nblock_used++; 792215976Sjmallett if (s->nblock_used == s->save_nblock+1) continue; 793232812Sjmallett if (k1 != s->k0) { s->k0 = k1; continue; }; 794232812Sjmallett 795215976Sjmallett s->state_out_len = 2; 796215976Sjmallett BZ_GET_SMALL(k1); s->nblock_used++; 797215976Sjmallett if (s->nblock_used == s->save_nblock+1) continue; 798215976Sjmallett if (k1 != s->k0) { s->k0 = k1; continue; }; 799215976Sjmallett 800215976Sjmallett s->state_out_len = 3; 801215976Sjmallett BZ_GET_SMALL(k1); s->nblock_used++; 802215976Sjmallett if (s->nblock_used == s->save_nblock+1) continue; 803232812Sjmallett if (k1 != s->k0) { s->k0 = k1; continue; }; 804215976Sjmallett 805215976Sjmallett BZ_GET_SMALL(k1); s->nblock_used++; 806232812Sjmallett s->state_out_len = ((Int32)k1) + 4; 807232812Sjmallett BZ_GET_SMALL(s->k0); s->nblock_used++; 808215976Sjmallett } 809215976Sjmallett 810215976Sjmallett } 811215976Sjmallett} 812215976Sjmallett 813215976Sjmallett 814215976Sjmallett/*---------------------------------------------------*/ 815215976Sjmallettint BZ_API(BZ2_bzDecompress) ( bz_stream *strm ) 816215976Sjmallett{ 817232812Sjmallett Bool corrupt; 818215976Sjmallett DState* s; 819232812Sjmallett if (strm == NULL) return BZ_PARAM_ERROR; 820232812Sjmallett s = strm->state; 821215976Sjmallett if (s == NULL) return BZ_PARAM_ERROR; 822215976Sjmallett if (s->strm != strm) return BZ_PARAM_ERROR; 823215976Sjmallett 824215976Sjmallett while (True) { 825215976Sjmallett if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; 826215976Sjmallett if (s->state == BZ_X_OUTPUT) { 827215976Sjmallett if (s->smallDecompress) 828215976Sjmallett corrupt = unRLE_obuf_to_output_SMALL ( s ); else 829215976Sjmallett corrupt = unRLE_obuf_to_output_FAST ( s ); 830215976Sjmallett if (corrupt) return BZ_DATA_ERROR; 831215976Sjmallett if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { 832215976Sjmallett BZ_FINALISE_CRC ( s->calculatedBlockCRC ); 833215976Sjmallett if (s->verbosity >= 3) 834215976Sjmallett VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, 835215976Sjmallett s->calculatedBlockCRC ); 836232812Sjmallett if (s->verbosity >= 2) VPrintf0 ( "]" ); 837215976Sjmallett if (s->calculatedBlockCRC != s->storedBlockCRC) 838215976Sjmallett return BZ_DATA_ERROR; 839215976Sjmallett s->calculatedCombinedCRC 840215976Sjmallett = (s->calculatedCombinedCRC << 1) | 841215976Sjmallett (s->calculatedCombinedCRC >> 31); 842215976Sjmallett s->calculatedCombinedCRC ^= s->calculatedBlockCRC; 843215976Sjmallett s->state = BZ_X_BLKHDR_1; 844215976Sjmallett } else { 845215976Sjmallett return BZ_OK; 846215976Sjmallett } 847215976Sjmallett } 848215976Sjmallett if (s->state >= BZ_X_MAGIC_1) { 849215976Sjmallett Int32 r = BZ2_decompress ( s ); 850215976Sjmallett if (r == BZ_STREAM_END) { 851215976Sjmallett if (s->verbosity >= 3) 852215976Sjmallett VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x", 853215976Sjmallett s->storedCombinedCRC, s->calculatedCombinedCRC ); 854215976Sjmallett if (s->calculatedCombinedCRC != s->storedCombinedCRC) 855215976Sjmallett return BZ_DATA_ERROR; 856215976Sjmallett return r; 857215976Sjmallett } 858215976Sjmallett if (s->state != BZ_X_OUTPUT) return r; 859215976Sjmallett } 860215976Sjmallett } 861215976Sjmallett 862215976Sjmallett AssertH ( 0, 6001 ); 863215976Sjmallett 864215976Sjmallett return 0; /*NOTREACHED*/ 865232812Sjmallett} 866215976Sjmallett 867215976Sjmallett 868232812Sjmallett/*---------------------------------------------------*/ 869232812Sjmallettint BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm ) 870232812Sjmallett{ 871232812Sjmallett DState* s; 872215976Sjmallett if (strm == NULL) return BZ_PARAM_ERROR; 873215976Sjmallett s = strm->state; 874215976Sjmallett if (s == NULL) return BZ_PARAM_ERROR; 875215976Sjmallett if (s->strm != strm) return BZ_PARAM_ERROR; 876215976Sjmallett 877215976Sjmallett if (s->tt != NULL) BZFREE(s->tt); 878215976Sjmallett if (s->ll16 != NULL) BZFREE(s->ll16); 879215976Sjmallett if (s->ll4 != NULL) BZFREE(s->ll4); 880215976Sjmallett 881232812Sjmallett BZFREE(strm->state); 882215976Sjmallett strm->state = NULL; 883232812Sjmallett 884232812Sjmallett return BZ_OK; 885215976Sjmallett} 886215976Sjmallett 887215976Sjmallett#ifndef BZ_NO_COMPRESS 888215976Sjmallett 889215976Sjmallett#ifndef BZ_NO_STDIO 890215976Sjmallett/*---------------------------------------------------*/ 891215976Sjmallett/*--- File I/O stuff ---*/ 892215976Sjmallett/*---------------------------------------------------*/ 893215976Sjmallett 894215976Sjmallett#define BZ_SETERR(eee) \ 895215976Sjmallett{ \ 896215976Sjmallett if (bzerror != NULL) *bzerror = eee; \ 897215976Sjmallett if (bzf != NULL) bzf->lastErr = eee; \ 898215976Sjmallett} 899215976Sjmallett 900215976Sjmalletttypedef 901232812Sjmallett struct { 902232812Sjmallett FILE* handle; 903232812Sjmallett Char buf[BZ_MAX_UNUSED]; 904232812Sjmallett Int32 bufN; 905232812Sjmallett Bool writing; 906232812Sjmallett bz_stream strm; 907232812Sjmallett Int32 lastErr; 908232812Sjmallett Bool initialisedOk; 909232812Sjmallett } 910232812Sjmallett bzFile; 911215976Sjmallett 912215976Sjmallett 913215976Sjmallett/*---------------------------------------------*/ 914215976Sjmallettstatic Bool myfeof ( FILE* f ) 915215976Sjmallett{ 916215976Sjmallett Int32 c = fgetc ( f ); 917215976Sjmallett if (c == EOF) return True; 918215976Sjmallett ungetc ( c, f ); 919215976Sjmallett return False; 920215976Sjmallett} 921215976Sjmallett 922215976Sjmallett 923215976Sjmallett/*---------------------------------------------------*/ 924215976SjmallettBZFILE* BZ_API(BZ2_bzWriteOpen) 925215976Sjmallett ( int* bzerror, 926215976Sjmallett FILE* f, 927215976Sjmallett int blockSize100k, 928215976Sjmallett int verbosity, 929215976Sjmallett int workFactor ) 930215976Sjmallett{ 931215976Sjmallett Int32 ret; 932215976Sjmallett bzFile* bzf = NULL; 933215976Sjmallett 934215976Sjmallett BZ_SETERR(BZ_OK); 935215976Sjmallett 936215976Sjmallett if (f == NULL || 937215976Sjmallett (blockSize100k < 1 || blockSize100k > 9) || 938215976Sjmallett (workFactor < 0 || workFactor > 250) || 939215976Sjmallett (verbosity < 0 || verbosity > 4)) 940215976Sjmallett { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; 941215976Sjmallett 942215976Sjmallett if (ferror(f)) 943215976Sjmallett { BZ_SETERR(BZ_IO_ERROR); return NULL; }; 944215976Sjmallett 945215976Sjmallett bzf = malloc ( sizeof(bzFile) ); 946215976Sjmallett if (bzf == NULL) 947215976Sjmallett { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; 948215976Sjmallett 949215976Sjmallett BZ_SETERR(BZ_OK); 950215976Sjmallett bzf->initialisedOk = False; 951215976Sjmallett bzf->bufN = 0; 952215976Sjmallett bzf->handle = f; 953232812Sjmallett bzf->writing = True; 954215976Sjmallett bzf->strm.bzalloc = NULL; 955215976Sjmallett bzf->strm.bzfree = NULL; 956232812Sjmallett bzf->strm.opaque = NULL; 957232812Sjmallett 958232812Sjmallett if (workFactor == 0) workFactor = 30; 959232812Sjmallett ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, 960215976Sjmallett verbosity, workFactor ); 961215976Sjmallett if (ret != BZ_OK) 962215976Sjmallett { BZ_SETERR(ret); free(bzf); return NULL; }; 963215976Sjmallett 964 bzf->strm.avail_in = 0; 965 bzf->initialisedOk = True; 966 return bzf; 967} 968 969 970 971/*---------------------------------------------------*/ 972void BZ_API(BZ2_bzWrite) 973 ( int* bzerror, 974 BZFILE* b, 975 void* buf, 976 int len ) 977{ 978 Int32 n, n2, ret; 979 bzFile* bzf = (bzFile*)b; 980 981 BZ_SETERR(BZ_OK); 982 if (bzf == NULL || buf == NULL || len < 0) 983 { BZ_SETERR(BZ_PARAM_ERROR); return; }; 984 if (!(bzf->writing)) 985 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; 986 if (ferror(bzf->handle)) 987 { BZ_SETERR(BZ_IO_ERROR); return; }; 988 989 if (len == 0) 990 { BZ_SETERR(BZ_OK); return; }; 991 992 bzf->strm.avail_in = len; 993 bzf->strm.next_in = buf; 994 995 while (True) { 996 bzf->strm.avail_out = BZ_MAX_UNUSED; 997 bzf->strm.next_out = bzf->buf; 998 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN ); 999 if (ret != BZ_RUN_OK) 1000 { BZ_SETERR(ret); return; }; 1001 1002 if (bzf->strm.avail_out < BZ_MAX_UNUSED) { 1003 n = BZ_MAX_UNUSED - bzf->strm.avail_out; 1004 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 1005 n, bzf->handle ); 1006 if (n != n2 || ferror(bzf->handle)) 1007 { BZ_SETERR(BZ_IO_ERROR); return; }; 1008 } 1009 1010 if (bzf->strm.avail_in == 0) 1011 { BZ_SETERR(BZ_OK); return; }; 1012 } 1013} 1014 1015 1016/*---------------------------------------------------*/ 1017void BZ_API(BZ2_bzWriteClose) 1018 ( int* bzerror, 1019 BZFILE* b, 1020 int abandon, 1021 unsigned int* nbytes_in, 1022 unsigned int* nbytes_out ) 1023{ 1024 BZ2_bzWriteClose64 ( bzerror, b, abandon, 1025 nbytes_in, NULL, nbytes_out, NULL ); 1026} 1027 1028 1029void BZ_API(BZ2_bzWriteClose64) 1030 ( int* bzerror, 1031 BZFILE* b, 1032 int abandon, 1033 unsigned int* nbytes_in_lo32, 1034 unsigned int* nbytes_in_hi32, 1035 unsigned int* nbytes_out_lo32, 1036 unsigned int* nbytes_out_hi32 ) 1037{ 1038 Int32 n, n2, ret; 1039 bzFile* bzf = (bzFile*)b; 1040 1041 if (bzf == NULL) 1042 { BZ_SETERR(BZ_OK); return; }; 1043 if (!(bzf->writing)) 1044 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; 1045 if (ferror(bzf->handle)) 1046 { BZ_SETERR(BZ_IO_ERROR); return; }; 1047 1048 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0; 1049 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0; 1050 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0; 1051 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0; 1052 1053 if ((!abandon) && bzf->lastErr == BZ_OK) { 1054 while (True) { 1055 bzf->strm.avail_out = BZ_MAX_UNUSED; 1056 bzf->strm.next_out = bzf->buf; 1057 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH ); 1058 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) 1059 { BZ_SETERR(ret); return; }; 1060 1061 if (bzf->strm.avail_out < BZ_MAX_UNUSED) { 1062 n = BZ_MAX_UNUSED - bzf->strm.avail_out; 1063 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 1064 n, bzf->handle ); 1065 if (n != n2 || ferror(bzf->handle)) 1066 { BZ_SETERR(BZ_IO_ERROR); return; }; 1067 } 1068 1069 if (ret == BZ_STREAM_END) break; 1070 } 1071 } 1072 1073 if ( !abandon && !ferror ( bzf->handle ) ) { 1074 fflush ( bzf->handle ); 1075 if (ferror(bzf->handle)) 1076 { BZ_SETERR(BZ_IO_ERROR); return; }; 1077 } 1078 1079 if (nbytes_in_lo32 != NULL) 1080 *nbytes_in_lo32 = bzf->strm.total_in_lo32; 1081 if (nbytes_in_hi32 != NULL) 1082 *nbytes_in_hi32 = bzf->strm.total_in_hi32; 1083 if (nbytes_out_lo32 != NULL) 1084 *nbytes_out_lo32 = bzf->strm.total_out_lo32; 1085 if (nbytes_out_hi32 != NULL) 1086 *nbytes_out_hi32 = bzf->strm.total_out_hi32; 1087 1088 BZ_SETERR(BZ_OK); 1089 BZ2_bzCompressEnd ( &(bzf->strm) ); 1090 free ( bzf ); 1091} 1092 1093 1094/*---------------------------------------------------*/ 1095BZFILE* BZ_API(BZ2_bzReadOpen) 1096 ( int* bzerror, 1097 FILE* f, 1098 int verbosity, 1099 int small, 1100 void* unused, 1101 int nUnused ) 1102{ 1103 bzFile* bzf = NULL; 1104 int ret; 1105 1106 BZ_SETERR(BZ_OK); 1107 1108 if (f == NULL || 1109 (small != 0 && small != 1) || 1110 (verbosity < 0 || verbosity > 4) || 1111 (unused == NULL && nUnused != 0) || 1112 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED))) 1113 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; 1114 1115 if (ferror(f)) 1116 { BZ_SETERR(BZ_IO_ERROR); return NULL; }; 1117 1118 bzf = malloc ( sizeof(bzFile) ); 1119 if (bzf == NULL) 1120 { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; 1121 1122 BZ_SETERR(BZ_OK); 1123 1124 bzf->initialisedOk = False; 1125 bzf->handle = f; 1126 bzf->bufN = 0; 1127 bzf->writing = False; 1128 bzf->strm.bzalloc = NULL; 1129 bzf->strm.bzfree = NULL; 1130 bzf->strm.opaque = NULL; 1131 1132 while (nUnused > 0) { 1133 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++; 1134 unused = ((void*)( 1 + ((UChar*)(unused)) )); 1135 nUnused--; 1136 } 1137 1138 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small ); 1139 if (ret != BZ_OK) 1140 { BZ_SETERR(ret); free(bzf); return NULL; }; 1141 1142 bzf->strm.avail_in = bzf->bufN; 1143 bzf->strm.next_in = bzf->buf; 1144 1145 bzf->initialisedOk = True; 1146 return bzf; 1147} 1148 1149 1150/*---------------------------------------------------*/ 1151void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b ) 1152{ 1153 bzFile* bzf = (bzFile*)b; 1154 1155 BZ_SETERR(BZ_OK); 1156 if (bzf == NULL) 1157 { BZ_SETERR(BZ_OK); return; }; 1158 1159 if (bzf->writing) 1160 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; 1161 1162 if (bzf->initialisedOk) 1163 (void)BZ2_bzDecompressEnd ( &(bzf->strm) ); 1164 free ( bzf ); 1165} 1166 1167 1168/*---------------------------------------------------*/ 1169int BZ_API(BZ2_bzRead) 1170 ( int* bzerror, 1171 BZFILE* b, 1172 void* buf, 1173 int len ) 1174{ 1175 Int32 n, ret; 1176 bzFile* bzf = (bzFile*)b; 1177 1178 BZ_SETERR(BZ_OK); 1179 1180 if (bzf == NULL || buf == NULL || len < 0) 1181 { BZ_SETERR(BZ_PARAM_ERROR); return 0; }; 1182 1183 if (bzf->writing) 1184 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; }; 1185 1186 if (len == 0) 1187 { BZ_SETERR(BZ_OK); return 0; }; 1188 1189 bzf->strm.avail_out = len; 1190 bzf->strm.next_out = buf; 1191 1192 while (True) { 1193 1194 if (ferror(bzf->handle)) 1195 { BZ_SETERR(BZ_IO_ERROR); return 0; }; 1196 1197 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) { 1198 n = fread ( bzf->buf, sizeof(UChar), 1199 BZ_MAX_UNUSED, bzf->handle ); 1200 if (ferror(bzf->handle)) 1201 { BZ_SETERR(BZ_IO_ERROR); return 0; }; 1202 bzf->bufN = n; 1203 bzf->strm.avail_in = bzf->bufN; 1204 bzf->strm.next_in = bzf->buf; 1205 } 1206 1207 ret = BZ2_bzDecompress ( &(bzf->strm) ); 1208 1209 if (ret != BZ_OK && ret != BZ_STREAM_END) 1210 { BZ_SETERR(ret); return 0; }; 1211 1212 if (ret == BZ_OK && myfeof(bzf->handle) && 1213 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0) 1214 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; }; 1215 1216 if (ret == BZ_STREAM_END) 1217 { BZ_SETERR(BZ_STREAM_END); 1218 return len - bzf->strm.avail_out; }; 1219 if (bzf->strm.avail_out == 0) 1220 { BZ_SETERR(BZ_OK); return len; }; 1221 1222 } 1223 1224 return 0; /*not reached*/ 1225} 1226 1227 1228/*---------------------------------------------------*/ 1229void BZ_API(BZ2_bzReadGetUnused) 1230 ( int* bzerror, 1231 BZFILE* b, 1232 void** unused, 1233 int* nUnused ) 1234{ 1235 bzFile* bzf = (bzFile*)b; 1236 if (bzf == NULL) 1237 { BZ_SETERR(BZ_PARAM_ERROR); return; }; 1238 if (bzf->lastErr != BZ_STREAM_END) 1239 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; 1240 if (unused == NULL || nUnused == NULL) 1241 { BZ_SETERR(BZ_PARAM_ERROR); return; }; 1242 1243 BZ_SETERR(BZ_OK); 1244 *nUnused = bzf->strm.avail_in; 1245 *unused = bzf->strm.next_in; 1246} 1247#endif 1248 1249 1250/*---------------------------------------------------*/ 1251/*--- Misc convenience stuff ---*/ 1252/*---------------------------------------------------*/ 1253 1254/*---------------------------------------------------*/ 1255int BZ_API(BZ2_bzBuffToBuffCompress) 1256 ( char* dest, 1257 unsigned int* destLen, 1258 char* source, 1259 unsigned int sourceLen, 1260 int blockSize100k, 1261 int verbosity, 1262 int workFactor ) 1263{ 1264 bz_stream strm; 1265 int ret; 1266 1267 if (dest == NULL || destLen == NULL || 1268 source == NULL || 1269 blockSize100k < 1 || blockSize100k > 9 || 1270 verbosity < 0 || verbosity > 4 || 1271 workFactor < 0 || workFactor > 250) 1272 return BZ_PARAM_ERROR; 1273 1274 if (workFactor == 0) workFactor = 30; 1275 strm.bzalloc = NULL; 1276 strm.bzfree = NULL; 1277 strm.opaque = NULL; 1278 ret = BZ2_bzCompressInit ( &strm, blockSize100k, 1279 verbosity, workFactor ); 1280 if (ret != BZ_OK) return ret; 1281 1282 strm.next_in = source; 1283 strm.next_out = dest; 1284 strm.avail_in = sourceLen; 1285 strm.avail_out = *destLen; 1286 1287 ret = BZ2_bzCompress ( &strm, BZ_FINISH ); 1288 if (ret == BZ_FINISH_OK) goto output_overflow; 1289 if (ret != BZ_STREAM_END) goto errhandler; 1290 1291 /* normal termination */ 1292 *destLen -= strm.avail_out; 1293 BZ2_bzCompressEnd ( &strm ); 1294 return BZ_OK; 1295 1296 output_overflow: 1297 BZ2_bzCompressEnd ( &strm ); 1298 return BZ_OUTBUFF_FULL; 1299 1300 errhandler: 1301 BZ2_bzCompressEnd ( &strm ); 1302 return ret; 1303} 1304 1305 1306/*---------------------------------------------------*/ 1307int BZ_API(BZ2_bzBuffToBuffDecompress) 1308 ( char* dest, 1309 unsigned int* destLen, 1310 char* source, 1311 unsigned int sourceLen, 1312 int small, 1313 int verbosity ) 1314{ 1315 bz_stream strm; 1316 int ret; 1317 1318 if (dest == NULL || destLen == NULL || 1319 source == NULL || 1320 (small != 0 && small != 1) || 1321 verbosity < 0 || verbosity > 4) 1322 return BZ_PARAM_ERROR; 1323 1324 strm.bzalloc = NULL; 1325 strm.bzfree = NULL; 1326 strm.opaque = NULL; 1327 ret = BZ2_bzDecompressInit ( &strm, verbosity, small ); 1328 if (ret != BZ_OK) return ret; 1329 1330 strm.next_in = source; 1331 strm.next_out = dest; 1332 strm.avail_in = sourceLen; 1333 strm.avail_out = *destLen; 1334 1335 ret = BZ2_bzDecompress ( &strm ); 1336 if (ret == BZ_OK) goto output_overflow_or_eof; 1337 if (ret != BZ_STREAM_END) goto errhandler; 1338 1339 /* normal termination */ 1340 *destLen -= strm.avail_out; 1341 BZ2_bzDecompressEnd ( &strm ); 1342 return BZ_OK; 1343 1344 output_overflow_or_eof: 1345 if (strm.avail_out > 0) { 1346 BZ2_bzDecompressEnd ( &strm ); 1347 return BZ_UNEXPECTED_EOF; 1348 } else { 1349 BZ2_bzDecompressEnd ( &strm ); 1350 return BZ_OUTBUFF_FULL; 1351 }; 1352 1353 errhandler: 1354 BZ2_bzDecompressEnd ( &strm ); 1355 return ret; 1356} 1357 1358 1359/*---------------------------------------------------*/ 1360/*-- 1361 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp) 1362 to support better zlib compatibility. 1363 This code is not _officially_ part of libbzip2 (yet); 1364 I haven't tested it, documented it, or considered the 1365 threading-safeness of it. 1366 If this code breaks, please contact both Yoshioka and me. 1367--*/ 1368/*---------------------------------------------------*/ 1369 1370/*---------------------------------------------------*/ 1371/*-- 1372 return version like "0.9.5d, 4-Sept-1999". 1373--*/ 1374const char * BZ_API(BZ2_bzlibVersion)(void) 1375{ 1376 return BZ_VERSION; 1377} 1378 1379 1380#ifndef BZ_NO_STDIO 1381/*---------------------------------------------------*/ 1382 1383#if defined(_WIN32) || defined(OS2) || defined(MSDOS) 1384# include <fcntl.h> 1385# include <io.h> 1386# define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) 1387#else 1388# define SET_BINARY_MODE(file) 1389#endif 1390static 1391BZFILE * bzopen_or_bzdopen 1392 ( const char *path, /* no use when bzdopen */ 1393 int fd, /* no use when bzdopen */ 1394 const char *mode, 1395 int open_mode) /* bzopen: 0, bzdopen:1 */ 1396{ 1397 int bzerr; 1398 char unused[BZ_MAX_UNUSED]; 1399 int blockSize100k = 9; 1400 int writing = 0; 1401 char mode2[10] = ""; 1402 FILE *fp = NULL; 1403 BZFILE *bzfp = NULL; 1404 int verbosity = 0; 1405 int workFactor = 30; 1406 int smallMode = 0; 1407 int nUnused = 0; 1408 1409 if (mode == NULL) return NULL; 1410 while (*mode) { 1411 switch (*mode) { 1412 case 'r': 1413 writing = 0; break; 1414 case 'w': 1415 writing = 1; break; 1416 case 's': 1417 smallMode = 1; break; 1418 default: 1419 if (isdigit((int)(*mode))) { 1420 blockSize100k = *mode-BZ_HDR_0; 1421 } 1422 } 1423 mode++; 1424 } 1425 strcat(mode2, writing ? "w" : "r" ); 1426 strcat(mode2,"b"); /* binary mode */ 1427 1428 if (open_mode==0) { 1429 if (path==NULL || strcmp(path,"")==0) { 1430 fp = (writing ? stdout : stdin); 1431 SET_BINARY_MODE(fp); 1432 } else { 1433 fp = fopen(path,mode2); 1434 } 1435 } else { 1436#ifdef BZ_STRICT_ANSI 1437 fp = NULL; 1438#else 1439 fp = fdopen(fd,mode2); 1440#endif 1441 } 1442 if (fp == NULL) return NULL; 1443 1444 if (writing) { 1445 /* Guard against total chaos and anarchy -- JRS */ 1446 if (blockSize100k < 1) blockSize100k = 1; 1447 if (blockSize100k > 9) blockSize100k = 9; 1448 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k, 1449 verbosity,workFactor); 1450 } else { 1451 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode, 1452 unused,nUnused); 1453 } 1454 if (bzfp == NULL) { 1455 if (fp != stdin && fp != stdout) fclose(fp); 1456 return NULL; 1457 } 1458 return bzfp; 1459} 1460 1461 1462/*---------------------------------------------------*/ 1463/*-- 1464 open file for read or write. 1465 ex) bzopen("file","w9") 1466 case path="" or NULL => use stdin or stdout. 1467--*/ 1468BZFILE * BZ_API(BZ2_bzopen) 1469 ( const char *path, 1470 const char *mode ) 1471{ 1472 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0); 1473} 1474 1475 1476/*---------------------------------------------------*/ 1477BZFILE * BZ_API(BZ2_bzdopen) 1478 ( int fd, 1479 const char *mode ) 1480{ 1481 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1); 1482} 1483 1484 1485/*---------------------------------------------------*/ 1486int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len ) 1487{ 1488 int bzerr, nread; 1489 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0; 1490 nread = BZ2_bzRead(&bzerr,b,buf,len); 1491 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) { 1492 return nread; 1493 } else { 1494 return -1; 1495 } 1496} 1497 1498 1499/*---------------------------------------------------*/ 1500int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len ) 1501{ 1502 int bzerr; 1503 1504 BZ2_bzWrite(&bzerr,b,buf,len); 1505 if(bzerr == BZ_OK){ 1506 return len; 1507 }else{ 1508 return -1; 1509 } 1510} 1511 1512 1513/*---------------------------------------------------*/ 1514int BZ_API(BZ2_bzflush) (BZFILE *b) 1515{ 1516 /* do nothing now... */ 1517 return 0; 1518} 1519 1520 1521/*---------------------------------------------------*/ 1522void BZ_API(BZ2_bzclose) (BZFILE* b) 1523{ 1524 int bzerr; 1525 FILE *fp; 1526 1527 if (b==NULL) {return;} 1528 fp = ((bzFile *)b)->handle; 1529 if(((bzFile*)b)->writing){ 1530 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL); 1531 if(bzerr != BZ_OK){ 1532 BZ2_bzWriteClose(NULL,b,1,NULL,NULL); 1533 } 1534 }else{ 1535 BZ2_bzReadClose(&bzerr,b); 1536 } 1537 if(fp!=stdin && fp!=stdout){ 1538 fclose(fp); 1539 } 1540} 1541 1542 1543/*---------------------------------------------------*/ 1544/*-- 1545 return last error code 1546--*/ 1547static const char *bzerrorstrings[] = { 1548 "OK" 1549 ,"SEQUENCE_ERROR" 1550 ,"PARAM_ERROR" 1551 ,"MEM_ERROR" 1552 ,"DATA_ERROR" 1553 ,"DATA_ERROR_MAGIC" 1554 ,"IO_ERROR" 1555 ,"UNEXPECTED_EOF" 1556 ,"OUTBUFF_FULL" 1557 ,"CONFIG_ERROR" 1558 ,"???" /* for future */ 1559 ,"???" /* for future */ 1560 ,"???" /* for future */ 1561 ,"???" /* for future */ 1562 ,"???" /* for future */ 1563 ,"???" /* for future */ 1564}; 1565 1566 1567const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum) 1568{ 1569 int err = ((bzFile *)b)->lastErr; 1570 1571 if(err>0) err = 0; 1572 *errnum = err; 1573 return bzerrorstrings[err*-1]; 1574} 1575#endif 1576 1577#endif /* BZ_NO_COMPRESS */ 1578 1579/*-------------------------------------------------------------*/ 1580/*--- end bzlib.c ---*/ 1581/*-------------------------------------------------------------*/ 1582