1 1.5 rillig /* $NetBSD: bzlib.c,v 1.5 2021/08/27 17:31:48 rillig Exp $ */ 2 1.1 wiz 3 1.1 wiz 4 1.1 wiz /*-------------------------------------------------------------*/ 5 1.1 wiz /*--- Library top-level functions. ---*/ 6 1.1 wiz /*--- bzlib.c ---*/ 7 1.1 wiz /*-------------------------------------------------------------*/ 8 1.1 wiz 9 1.1 wiz /* ------------------------------------------------------------------ 10 1.1 wiz This file is part of bzip2/libbzip2, a program and library for 11 1.1 wiz lossless, block-sorting data compression. 12 1.1 wiz 13 1.4 maya bzip2/libbzip2 version 1.0.8 of 13 July 2019 14 1.4 maya Copyright (C) 1996-2019 Julian Seward <jseward (at) acm.org> 15 1.1 wiz 16 1.1 wiz Please read the WARNING, DISCLAIMER and PATENTS sections in the 17 1.1 wiz README file. 18 1.1 wiz 19 1.1 wiz This program is released under the terms of the license contained 20 1.1 wiz in the file LICENSE. 21 1.1 wiz ------------------------------------------------------------------ */ 22 1.1 wiz 23 1.1 wiz /* CHANGES 24 1.1 wiz 0.9.0 -- original version. 25 1.1 wiz 0.9.0a/b -- no changes in this file. 26 1.1 wiz 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress(). 27 1.1 wiz fixed bzWrite/bzRead to ignore zero-length requests. 28 1.1 wiz fixed bzread to correctly handle read requests after EOF. 29 1.1 wiz wrong parameter order in call to bzDecompressInit in 30 1.1 wiz bzBuffToBuffDecompress. Fixed. 31 1.1 wiz */ 32 1.1 wiz 33 1.1 wiz #include "bzlib_private.h" 34 1.1 wiz 35 1.1 wiz 36 1.1 wiz /*---------------------------------------------------*/ 37 1.1 wiz /*--- Compression stuff ---*/ 38 1.1 wiz /*---------------------------------------------------*/ 39 1.1 wiz 40 1.1 wiz 41 1.1 wiz /*---------------------------------------------------*/ 42 1.1 wiz #ifndef BZ_NO_STDIO 43 1.1 wiz void BZ2_bz__AssertH__fail ( int errcode ) 44 1.1 wiz { 45 1.1 wiz fprintf(stderr, 46 1.1 wiz "\n\nbzip2/libbzip2: internal error number %d.\n" 47 1.1 wiz "This is a bug in bzip2/libbzip2, %s.\n" 48 1.4 maya "Please report it to: bzip2-devel (at) sourceware.org. If this happened\n" 49 1.1 wiz "when you were using some program which uses libbzip2 as a\n" 50 1.1 wiz "component, you should also report this bug to the author(s)\n" 51 1.1 wiz "of that program. Please make an effort to report this bug;\n" 52 1.1 wiz "timely and accurate bug reports eventually lead to higher\n" 53 1.4 maya "quality software. Thanks.\n\n", 54 1.1 wiz errcode, 55 1.1 wiz BZ2_bzlibVersion() 56 1.1 wiz ); 57 1.1 wiz 58 1.1 wiz if (errcode == 1007) { 59 1.1 wiz fprintf(stderr, 60 1.1 wiz "\n*** A special note about internal error number 1007 ***\n" 61 1.1 wiz "\n" 62 1.1 wiz "Experience suggests that a common cause of i.e. 1007\n" 63 1.1 wiz "is unreliable memory or other hardware. The 1007 assertion\n" 64 1.1 wiz "just happens to cross-check the results of huge numbers of\n" 65 1.1 wiz "memory reads/writes, and so acts (unintendedly) as a stress\n" 66 1.1 wiz "test of your memory system.\n" 67 1.1 wiz "\n" 68 1.1 wiz "I suggest the following: try compressing the file again,\n" 69 1.1 wiz "possibly monitoring progress in detail with the -vv flag.\n" 70 1.1 wiz "\n" 71 1.1 wiz "* If the error cannot be reproduced, and/or happens at different\n" 72 1.1 wiz " points in compression, you may have a flaky memory system.\n" 73 1.1 wiz " Try a memory-test program. I have used Memtest86\n" 74 1.1 wiz " (www.memtest86.com). At the time of writing it is free (GPLd).\n" 75 1.1 wiz " Memtest86 tests memory much more thorougly than your BIOSs\n" 76 1.1 wiz " power-on test, and may find failures that the BIOS doesn't.\n" 77 1.1 wiz "\n" 78 1.1 wiz "* If the error can be repeatably reproduced, this is a bug in\n" 79 1.1 wiz " bzip2, and I would very much like to hear about it. Please\n" 80 1.1 wiz " let me know, and, ideally, save a copy of the file causing the\n" 81 1.1 wiz " problem -- without which I will be unable to investigate it.\n" 82 1.1 wiz "\n" 83 1.1 wiz ); 84 1.1 wiz } 85 1.1 wiz 86 1.1 wiz exit(3); 87 1.1 wiz } 88 1.1 wiz #endif 89 1.1 wiz 90 1.1 wiz 91 1.1 wiz /*---------------------------------------------------*/ 92 1.1 wiz static 93 1.1 wiz int bz_config_ok ( void ) 94 1.1 wiz { 95 1.1 wiz if (sizeof(int) != 4) return 0; 96 1.1 wiz if (sizeof(short) != 2) return 0; 97 1.1 wiz if (sizeof(char) != 1) return 0; 98 1.1 wiz return 1; 99 1.1 wiz } 100 1.1 wiz 101 1.1 wiz 102 1.1 wiz /*---------------------------------------------------*/ 103 1.1 wiz static 104 1.1 wiz void* default_bzalloc ( void* opaque, Int32 items, Int32 size ) 105 1.1 wiz { 106 1.1 wiz void* v = malloc ( items * size ); 107 1.1 wiz return v; 108 1.1 wiz } 109 1.1 wiz 110 1.1 wiz static 111 1.1 wiz void default_bzfree ( void* opaque, void* addr ) 112 1.1 wiz { 113 1.1 wiz if (addr != NULL) free ( addr ); 114 1.1 wiz } 115 1.1 wiz 116 1.1 wiz 117 1.1 wiz /*---------------------------------------------------*/ 118 1.1 wiz static 119 1.1 wiz void prepare_new_block ( EState* s ) 120 1.1 wiz { 121 1.1 wiz Int32 i; 122 1.1 wiz s->nblock = 0; 123 1.1 wiz s->numZ = 0; 124 1.1 wiz s->state_out_pos = 0; 125 1.1 wiz BZ_INITIALISE_CRC ( s->blockCRC ); 126 1.1 wiz for (i = 0; i < 256; i++) s->inUse[i] = False; 127 1.1 wiz s->blockNo++; 128 1.1 wiz } 129 1.1 wiz 130 1.1 wiz 131 1.1 wiz /*---------------------------------------------------*/ 132 1.1 wiz static 133 1.1 wiz void init_RL ( EState* s ) 134 1.1 wiz { 135 1.1 wiz s->state_in_ch = 256; 136 1.1 wiz s->state_in_len = 0; 137 1.1 wiz } 138 1.1 wiz 139 1.1 wiz 140 1.1 wiz static 141 1.1 wiz Bool isempty_RL ( EState* s ) 142 1.1 wiz { 143 1.1 wiz if (s->state_in_ch < 256 && s->state_in_len > 0) 144 1.1 wiz return False; else 145 1.1 wiz return True; 146 1.1 wiz } 147 1.1 wiz 148 1.1 wiz 149 1.1 wiz /*---------------------------------------------------*/ 150 1.1 wiz int BZ_API(BZ2_bzCompressInit) 151 1.1 wiz ( bz_stream* strm, 152 1.1 wiz int blockSize100k, 153 1.1 wiz int verbosity, 154 1.1 wiz int workFactor ) 155 1.1 wiz { 156 1.1 wiz Int32 n; 157 1.1 wiz EState* s; 158 1.1 wiz 159 1.1 wiz if (!bz_config_ok()) return BZ_CONFIG_ERROR; 160 1.1 wiz 161 1.1 wiz if (strm == NULL || 162 1.1 wiz blockSize100k < 1 || blockSize100k > 9 || 163 1.1 wiz workFactor < 0 || workFactor > 250) 164 1.1 wiz return BZ_PARAM_ERROR; 165 1.1 wiz 166 1.1 wiz if (workFactor == 0) workFactor = 30; 167 1.1 wiz if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; 168 1.1 wiz if (strm->bzfree == NULL) strm->bzfree = default_bzfree; 169 1.1 wiz 170 1.1 wiz s = BZALLOC( sizeof(EState) ); 171 1.1 wiz if (s == NULL) return BZ_MEM_ERROR; 172 1.1 wiz s->strm = strm; 173 1.1 wiz 174 1.1 wiz s->arr1 = NULL; 175 1.1 wiz s->arr2 = NULL; 176 1.1 wiz s->ftab = NULL; 177 1.1 wiz 178 1.1 wiz n = 100000 * blockSize100k; 179 1.1 wiz s->arr1 = BZALLOC( n * sizeof(UInt32) ); 180 1.1 wiz s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) ); 181 1.1 wiz s->ftab = BZALLOC( 65537 * sizeof(UInt32) ); 182 1.1 wiz 183 1.1 wiz if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) { 184 1.1 wiz if (s->arr1 != NULL) BZFREE(s->arr1); 185 1.1 wiz if (s->arr2 != NULL) BZFREE(s->arr2); 186 1.1 wiz if (s->ftab != NULL) BZFREE(s->ftab); 187 1.1 wiz if (s != NULL) BZFREE(s); 188 1.1 wiz return BZ_MEM_ERROR; 189 1.1 wiz } 190 1.1 wiz 191 1.1 wiz s->blockNo = 0; 192 1.1 wiz s->state = BZ_S_INPUT; 193 1.1 wiz s->mode = BZ_M_RUNNING; 194 1.1 wiz s->combinedCRC = 0; 195 1.1 wiz s->blockSize100k = blockSize100k; 196 1.1 wiz s->nblockMAX = 100000 * blockSize100k - 19; 197 1.1 wiz s->verbosity = verbosity; 198 1.1 wiz s->workFactor = workFactor; 199 1.1 wiz 200 1.1 wiz s->block = (UChar*)s->arr2; 201 1.1 wiz s->mtfv = (UInt16*)s->arr1; 202 1.1 wiz s->zbits = NULL; 203 1.1 wiz s->ptr = (UInt32*)s->arr1; 204 1.1 wiz 205 1.1 wiz strm->state = s; 206 1.1 wiz strm->total_in_lo32 = 0; 207 1.1 wiz strm->total_in_hi32 = 0; 208 1.1 wiz strm->total_out_lo32 = 0; 209 1.1 wiz strm->total_out_hi32 = 0; 210 1.1 wiz init_RL ( s ); 211 1.1 wiz prepare_new_block ( s ); 212 1.1 wiz return BZ_OK; 213 1.1 wiz } 214 1.1 wiz 215 1.1 wiz 216 1.1 wiz /*---------------------------------------------------*/ 217 1.1 wiz static 218 1.1 wiz void add_pair_to_block ( EState* s ) 219 1.1 wiz { 220 1.1 wiz Int32 i; 221 1.1 wiz UChar ch = (UChar)(s->state_in_ch); 222 1.1 wiz for (i = 0; i < s->state_in_len; i++) { 223 1.1 wiz BZ_UPDATE_CRC( s->blockCRC, ch ); 224 1.1 wiz } 225 1.1 wiz s->inUse[s->state_in_ch] = True; 226 1.1 wiz switch (s->state_in_len) { 227 1.1 wiz case 1: 228 1.1 wiz s->block[s->nblock] = (UChar)ch; s->nblock++; 229 1.1 wiz break; 230 1.1 wiz case 2: 231 1.1 wiz s->block[s->nblock] = (UChar)ch; s->nblock++; 232 1.1 wiz s->block[s->nblock] = (UChar)ch; s->nblock++; 233 1.1 wiz break; 234 1.1 wiz case 3: 235 1.1 wiz s->block[s->nblock] = (UChar)ch; s->nblock++; 236 1.1 wiz s->block[s->nblock] = (UChar)ch; s->nblock++; 237 1.1 wiz s->block[s->nblock] = (UChar)ch; s->nblock++; 238 1.1 wiz break; 239 1.1 wiz default: 240 1.1 wiz s->inUse[s->state_in_len-4] = True; 241 1.1 wiz s->block[s->nblock] = (UChar)ch; s->nblock++; 242 1.1 wiz s->block[s->nblock] = (UChar)ch; s->nblock++; 243 1.1 wiz s->block[s->nblock] = (UChar)ch; s->nblock++; 244 1.1 wiz s->block[s->nblock] = (UChar)ch; s->nblock++; 245 1.1 wiz s->block[s->nblock] = ((UChar)(s->state_in_len-4)); 246 1.1 wiz s->nblock++; 247 1.1 wiz break; 248 1.1 wiz } 249 1.1 wiz } 250 1.1 wiz 251 1.1 wiz 252 1.1 wiz /*---------------------------------------------------*/ 253 1.1 wiz static 254 1.1 wiz void flush_RL ( EState* s ) 255 1.1 wiz { 256 1.1 wiz if (s->state_in_ch < 256) add_pair_to_block ( s ); 257 1.1 wiz init_RL ( s ); 258 1.1 wiz } 259 1.1 wiz 260 1.1 wiz 261 1.1 wiz /*---------------------------------------------------*/ 262 1.1 wiz #define ADD_CHAR_TO_BLOCK(zs,zchh0) \ 263 1.1 wiz { \ 264 1.1 wiz UInt32 zchh = (UInt32)(zchh0); \ 265 1.1 wiz /*-- fast track the common case --*/ \ 266 1.1 wiz if (zchh != zs->state_in_ch && \ 267 1.1 wiz zs->state_in_len == 1) { \ 268 1.1 wiz UChar ch = (UChar)(zs->state_in_ch); \ 269 1.1 wiz BZ_UPDATE_CRC( zs->blockCRC, ch ); \ 270 1.1 wiz zs->inUse[zs->state_in_ch] = True; \ 271 1.1 wiz zs->block[zs->nblock] = (UChar)ch; \ 272 1.1 wiz zs->nblock++; \ 273 1.1 wiz zs->state_in_ch = zchh; \ 274 1.1 wiz } \ 275 1.1 wiz else \ 276 1.1 wiz /*-- general, uncommon cases --*/ \ 277 1.1 wiz if (zchh != zs->state_in_ch || \ 278 1.1 wiz zs->state_in_len == 255) { \ 279 1.1 wiz if (zs->state_in_ch < 256) \ 280 1.1 wiz add_pair_to_block ( zs ); \ 281 1.1 wiz zs->state_in_ch = zchh; \ 282 1.1 wiz zs->state_in_len = 1; \ 283 1.1 wiz } else { \ 284 1.1 wiz zs->state_in_len++; \ 285 1.1 wiz } \ 286 1.1 wiz } 287 1.1 wiz 288 1.1 wiz 289 1.1 wiz /*---------------------------------------------------*/ 290 1.1 wiz static 291 1.1 wiz Bool copy_input_until_stop ( EState* s ) 292 1.1 wiz { 293 1.1 wiz Bool progress_in = False; 294 1.1 wiz 295 1.1 wiz if (s->mode == BZ_M_RUNNING) { 296 1.1 wiz 297 1.1 wiz /*-- fast track the common case --*/ 298 1.1 wiz while (True) { 299 1.1 wiz /*-- block full? --*/ 300 1.1 wiz if (s->nblock >= s->nblockMAX) break; 301 1.1 wiz /*-- no input? --*/ 302 1.1 wiz if (s->strm->avail_in == 0) break; 303 1.1 wiz progress_in = True; 304 1.1 wiz ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 305 1.1 wiz s->strm->next_in++; 306 1.1 wiz s->strm->avail_in--; 307 1.1 wiz s->strm->total_in_lo32++; 308 1.1 wiz if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; 309 1.1 wiz } 310 1.1 wiz 311 1.1 wiz } else { 312 1.1 wiz 313 1.1 wiz /*-- general, uncommon case --*/ 314 1.1 wiz while (True) { 315 1.1 wiz /*-- block full? --*/ 316 1.1 wiz if (s->nblock >= s->nblockMAX) break; 317 1.1 wiz /*-- no input? --*/ 318 1.1 wiz if (s->strm->avail_in == 0) break; 319 1.1 wiz /*-- flush/finish end? --*/ 320 1.1 wiz if (s->avail_in_expect == 0) break; 321 1.1 wiz progress_in = True; 322 1.1 wiz ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 323 1.1 wiz s->strm->next_in++; 324 1.1 wiz s->strm->avail_in--; 325 1.1 wiz s->strm->total_in_lo32++; 326 1.1 wiz if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; 327 1.1 wiz s->avail_in_expect--; 328 1.1 wiz } 329 1.1 wiz } 330 1.1 wiz return progress_in; 331 1.1 wiz } 332 1.1 wiz 333 1.1 wiz 334 1.1 wiz /*---------------------------------------------------*/ 335 1.1 wiz static 336 1.1 wiz Bool copy_output_until_stop ( EState* s ) 337 1.1 wiz { 338 1.1 wiz Bool progress_out = False; 339 1.1 wiz 340 1.1 wiz while (True) { 341 1.1 wiz 342 1.1 wiz /*-- no output space? --*/ 343 1.1 wiz if (s->strm->avail_out == 0) break; 344 1.1 wiz 345 1.1 wiz /*-- block done? --*/ 346 1.1 wiz if (s->state_out_pos >= s->numZ) break; 347 1.1 wiz 348 1.1 wiz progress_out = True; 349 1.1 wiz *(s->strm->next_out) = s->zbits[s->state_out_pos]; 350 1.1 wiz s->state_out_pos++; 351 1.1 wiz s->strm->avail_out--; 352 1.1 wiz s->strm->next_out++; 353 1.1 wiz s->strm->total_out_lo32++; 354 1.1 wiz if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; 355 1.1 wiz } 356 1.1 wiz 357 1.1 wiz return progress_out; 358 1.1 wiz } 359 1.1 wiz 360 1.1 wiz 361 1.1 wiz /*---------------------------------------------------*/ 362 1.1 wiz static 363 1.1 wiz Bool handle_compress ( bz_stream* strm ) 364 1.1 wiz { 365 1.1 wiz Bool progress_in = False; 366 1.1 wiz Bool progress_out = False; 367 1.1 wiz EState* s = strm->state; 368 1.1 wiz 369 1.1 wiz while (True) { 370 1.1 wiz 371 1.1 wiz if (s->state == BZ_S_OUTPUT) { 372 1.1 wiz progress_out |= copy_output_until_stop ( s ); 373 1.1 wiz if (s->state_out_pos < s->numZ) break; 374 1.1 wiz if (s->mode == BZ_M_FINISHING && 375 1.1 wiz s->avail_in_expect == 0 && 376 1.1 wiz isempty_RL(s)) break; 377 1.1 wiz prepare_new_block ( s ); 378 1.1 wiz s->state = BZ_S_INPUT; 379 1.1 wiz if (s->mode == BZ_M_FLUSHING && 380 1.1 wiz s->avail_in_expect == 0 && 381 1.1 wiz isempty_RL(s)) break; 382 1.1 wiz } 383 1.1 wiz 384 1.1 wiz if (s->state == BZ_S_INPUT) { 385 1.1 wiz progress_in |= copy_input_until_stop ( s ); 386 1.1 wiz if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) { 387 1.1 wiz flush_RL ( s ); 388 1.1 wiz BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) ); 389 1.1 wiz s->state = BZ_S_OUTPUT; 390 1.1 wiz } 391 1.1 wiz else 392 1.1 wiz if (s->nblock >= s->nblockMAX) { 393 1.1 wiz BZ2_compressBlock ( s, False ); 394 1.1 wiz s->state = BZ_S_OUTPUT; 395 1.1 wiz } 396 1.1 wiz else 397 1.1 wiz if (s->strm->avail_in == 0) { 398 1.1 wiz break; 399 1.1 wiz } 400 1.1 wiz } 401 1.1 wiz 402 1.1 wiz } 403 1.1 wiz 404 1.1 wiz return progress_in || progress_out; 405 1.1 wiz } 406 1.1 wiz 407 1.1 wiz 408 1.1 wiz /*---------------------------------------------------*/ 409 1.1 wiz int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action ) 410 1.1 wiz { 411 1.1 wiz Bool progress; 412 1.1 wiz EState* s; 413 1.1 wiz if (strm == NULL) return BZ_PARAM_ERROR; 414 1.1 wiz s = strm->state; 415 1.1 wiz if (s == NULL) return BZ_PARAM_ERROR; 416 1.1 wiz if (s->strm != strm) return BZ_PARAM_ERROR; 417 1.1 wiz 418 1.1 wiz preswitch: 419 1.1 wiz switch (s->mode) { 420 1.1 wiz 421 1.1 wiz case BZ_M_IDLE: 422 1.1 wiz return BZ_SEQUENCE_ERROR; 423 1.1 wiz 424 1.1 wiz case BZ_M_RUNNING: 425 1.1 wiz if (action == BZ_RUN) { 426 1.1 wiz progress = handle_compress ( strm ); 427 1.1 wiz return progress ? BZ_RUN_OK : BZ_PARAM_ERROR; 428 1.1 wiz } 429 1.1 wiz else 430 1.1 wiz if (action == BZ_FLUSH) { 431 1.1 wiz s->avail_in_expect = strm->avail_in; 432 1.1 wiz s->mode = BZ_M_FLUSHING; 433 1.1 wiz goto preswitch; 434 1.1 wiz } 435 1.1 wiz else 436 1.1 wiz if (action == BZ_FINISH) { 437 1.1 wiz s->avail_in_expect = strm->avail_in; 438 1.1 wiz s->mode = BZ_M_FINISHING; 439 1.1 wiz goto preswitch; 440 1.1 wiz } 441 1.1 wiz else 442 1.1 wiz return BZ_PARAM_ERROR; 443 1.1 wiz 444 1.1 wiz case BZ_M_FLUSHING: 445 1.1 wiz if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR; 446 1.1 wiz if (s->avail_in_expect != s->strm->avail_in) 447 1.1 wiz return BZ_SEQUENCE_ERROR; 448 1.1 wiz progress = handle_compress ( strm ); 449 1.1 wiz if (s->avail_in_expect > 0 || !isempty_RL(s) || 450 1.1 wiz s->state_out_pos < s->numZ) return BZ_FLUSH_OK; 451 1.1 wiz s->mode = BZ_M_RUNNING; 452 1.1 wiz return BZ_RUN_OK; 453 1.1 wiz 454 1.1 wiz case BZ_M_FINISHING: 455 1.1 wiz if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR; 456 1.1 wiz if (s->avail_in_expect != s->strm->avail_in) 457 1.1 wiz return BZ_SEQUENCE_ERROR; 458 1.1 wiz progress = handle_compress ( strm ); 459 1.1 wiz if (!progress) return BZ_SEQUENCE_ERROR; 460 1.1 wiz if (s->avail_in_expect > 0 || !isempty_RL(s) || 461 1.1 wiz s->state_out_pos < s->numZ) return BZ_FINISH_OK; 462 1.1 wiz s->mode = BZ_M_IDLE; 463 1.1 wiz return BZ_STREAM_END; 464 1.1 wiz } 465 1.1 wiz return BZ_OK; /*--not reached--*/ 466 1.1 wiz } 467 1.1 wiz 468 1.1 wiz 469 1.1 wiz /*---------------------------------------------------*/ 470 1.1 wiz int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm ) 471 1.1 wiz { 472 1.1 wiz EState* s; 473 1.1 wiz if (strm == NULL) return BZ_PARAM_ERROR; 474 1.1 wiz s = strm->state; 475 1.1 wiz if (s == NULL) return BZ_PARAM_ERROR; 476 1.1 wiz if (s->strm != strm) return BZ_PARAM_ERROR; 477 1.1 wiz 478 1.1 wiz if (s->arr1 != NULL) BZFREE(s->arr1); 479 1.1 wiz if (s->arr2 != NULL) BZFREE(s->arr2); 480 1.1 wiz if (s->ftab != NULL) BZFREE(s->ftab); 481 1.1 wiz BZFREE(strm->state); 482 1.1 wiz 483 1.1 wiz strm->state = NULL; 484 1.1 wiz 485 1.1 wiz return BZ_OK; 486 1.1 wiz } 487 1.1 wiz 488 1.1 wiz 489 1.1 wiz /*---------------------------------------------------*/ 490 1.1 wiz /*--- Decompression stuff ---*/ 491 1.1 wiz /*---------------------------------------------------*/ 492 1.1 wiz 493 1.1 wiz /*---------------------------------------------------*/ 494 1.1 wiz int BZ_API(BZ2_bzDecompressInit) 495 1.1 wiz ( bz_stream* strm, 496 1.1 wiz int verbosity, 497 1.1 wiz int small ) 498 1.1 wiz { 499 1.1 wiz DState* s; 500 1.1 wiz 501 1.1 wiz if (!bz_config_ok()) return BZ_CONFIG_ERROR; 502 1.1 wiz 503 1.1 wiz if (strm == NULL) return BZ_PARAM_ERROR; 504 1.1 wiz if (small != 0 && small != 1) return BZ_PARAM_ERROR; 505 1.1 wiz if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR; 506 1.1 wiz 507 1.1 wiz if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; 508 1.1 wiz if (strm->bzfree == NULL) strm->bzfree = default_bzfree; 509 1.1 wiz 510 1.1 wiz s = BZALLOC( sizeof(DState) ); 511 1.1 wiz if (s == NULL) return BZ_MEM_ERROR; 512 1.1 wiz s->strm = strm; 513 1.1 wiz strm->state = s; 514 1.1 wiz s->state = BZ_X_MAGIC_1; 515 1.1 wiz s->bsLive = 0; 516 1.1 wiz s->bsBuff = 0; 517 1.1 wiz s->calculatedCombinedCRC = 0; 518 1.1 wiz strm->total_in_lo32 = 0; 519 1.1 wiz strm->total_in_hi32 = 0; 520 1.1 wiz strm->total_out_lo32 = 0; 521 1.1 wiz strm->total_out_hi32 = 0; 522 1.1 wiz s->smallDecompress = (Bool)small; 523 1.1 wiz s->ll4 = NULL; 524 1.1 wiz s->ll16 = NULL; 525 1.1 wiz s->tt = NULL; 526 1.1 wiz s->currBlockNo = 0; 527 1.1 wiz s->verbosity = verbosity; 528 1.1 wiz 529 1.1 wiz return BZ_OK; 530 1.1 wiz } 531 1.1 wiz 532 1.1 wiz 533 1.1 wiz /*---------------------------------------------------*/ 534 1.1 wiz /* Return True iff data corruption is discovered. 535 1.1 wiz Returns False if there is no problem. 536 1.1 wiz */ 537 1.1 wiz static 538 1.1 wiz Bool unRLE_obuf_to_output_FAST ( DState* s ) 539 1.1 wiz { 540 1.1 wiz UChar k1; 541 1.1 wiz 542 1.1 wiz if (s->blockRandomised) { 543 1.1 wiz 544 1.1 wiz while (True) { 545 1.1 wiz /* try to finish existing run */ 546 1.1 wiz while (True) { 547 1.1 wiz if (s->strm->avail_out == 0) return False; 548 1.1 wiz if (s->state_out_len == 0) break; 549 1.1 wiz *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; 550 1.1 wiz BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); 551 1.1 wiz s->state_out_len--; 552 1.1 wiz s->strm->next_out++; 553 1.1 wiz s->strm->avail_out--; 554 1.1 wiz s->strm->total_out_lo32++; 555 1.1 wiz if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; 556 1.1 wiz } 557 1.1 wiz 558 1.1 wiz /* can a new run be started? */ 559 1.1 wiz if (s->nblock_used == s->save_nblock+1) return False; 560 1.1 wiz 561 1.1 wiz /* Only caused by corrupt data stream? */ 562 1.1 wiz if (s->nblock_used > s->save_nblock+1) 563 1.1 wiz return True; 564 1.1 wiz 565 1.1 wiz s->state_out_len = 1; 566 1.1 wiz s->state_out_ch = s->k0; 567 1.1 wiz BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 568 1.1 wiz k1 ^= BZ_RAND_MASK; s->nblock_used++; 569 1.1 wiz if (s->nblock_used == s->save_nblock+1) continue; 570 1.1 wiz if (k1 != s->k0) { s->k0 = k1; continue; }; 571 1.1 wiz 572 1.1 wiz s->state_out_len = 2; 573 1.1 wiz BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 574 1.1 wiz k1 ^= BZ_RAND_MASK; s->nblock_used++; 575 1.1 wiz if (s->nblock_used == s->save_nblock+1) continue; 576 1.1 wiz if (k1 != s->k0) { s->k0 = k1; continue; }; 577 1.1 wiz 578 1.1 wiz s->state_out_len = 3; 579 1.1 wiz BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 580 1.1 wiz k1 ^= BZ_RAND_MASK; s->nblock_used++; 581 1.1 wiz if (s->nblock_used == s->save_nblock+1) continue; 582 1.1 wiz if (k1 != s->k0) { s->k0 = k1; continue; }; 583 1.1 wiz 584 1.1 wiz BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 585 1.1 wiz k1 ^= BZ_RAND_MASK; s->nblock_used++; 586 1.1 wiz s->state_out_len = ((Int32)k1) + 4; 587 1.1 wiz BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; 588 1.1 wiz s->k0 ^= BZ_RAND_MASK; s->nblock_used++; 589 1.1 wiz } 590 1.1 wiz 591 1.1 wiz } else { 592 1.1 wiz 593 1.1 wiz /* restore */ 594 1.1 wiz UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC; 595 1.1 wiz UChar c_state_out_ch = s->state_out_ch; 596 1.1 wiz Int32 c_state_out_len = s->state_out_len; 597 1.1 wiz Int32 c_nblock_used = s->nblock_used; 598 1.1 wiz Int32 c_k0 = s->k0; 599 1.1 wiz UInt32* c_tt = s->tt; 600 1.1 wiz UInt32 c_tPos = s->tPos; 601 1.1 wiz char* cs_next_out = s->strm->next_out; 602 1.1 wiz unsigned int cs_avail_out = s->strm->avail_out; 603 1.1 wiz Int32 ro_blockSize100k = s->blockSize100k; 604 1.1 wiz /* end restore */ 605 1.1 wiz 606 1.1 wiz UInt32 avail_out_INIT = cs_avail_out; 607 1.1 wiz Int32 s_save_nblockPP = s->save_nblock+1; 608 1.1 wiz unsigned int total_out_lo32_old; 609 1.1 wiz 610 1.1 wiz while (True) { 611 1.1 wiz 612 1.1 wiz /* try to finish existing run */ 613 1.1 wiz if (c_state_out_len > 0) { 614 1.1 wiz while (True) { 615 1.1 wiz if (cs_avail_out == 0) goto return_notr; 616 1.1 wiz if (c_state_out_len == 1) break; 617 1.1 wiz *( (UChar*)(cs_next_out) ) = c_state_out_ch; 618 1.1 wiz BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); 619 1.1 wiz c_state_out_len--; 620 1.1 wiz cs_next_out++; 621 1.1 wiz cs_avail_out--; 622 1.1 wiz } 623 1.1 wiz s_state_out_len_eq_one: 624 1.1 wiz { 625 1.1 wiz if (cs_avail_out == 0) { 626 1.1 wiz c_state_out_len = 1; goto return_notr; 627 1.1 wiz }; 628 1.1 wiz *( (UChar*)(cs_next_out) ) = c_state_out_ch; 629 1.1 wiz BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); 630 1.1 wiz cs_next_out++; 631 1.1 wiz cs_avail_out--; 632 1.1 wiz } 633 1.1 wiz } 634 1.1 wiz /* Only caused by corrupt data stream? */ 635 1.1 wiz if (c_nblock_used > s_save_nblockPP) 636 1.1 wiz return True; 637 1.1 wiz 638 1.1 wiz /* can a new run be started? */ 639 1.1 wiz if (c_nblock_used == s_save_nblockPP) { 640 1.1 wiz c_state_out_len = 0; goto return_notr; 641 1.1 wiz }; 642 1.1 wiz c_state_out_ch = c_k0; 643 1.1 wiz BZ_GET_FAST_C(k1); c_nblock_used++; 644 1.1 wiz if (k1 != c_k0) { 645 1.1 wiz c_k0 = k1; goto s_state_out_len_eq_one; 646 1.1 wiz }; 647 1.1 wiz if (c_nblock_used == s_save_nblockPP) 648 1.1 wiz goto s_state_out_len_eq_one; 649 1.1 wiz 650 1.1 wiz c_state_out_len = 2; 651 1.1 wiz BZ_GET_FAST_C(k1); c_nblock_used++; 652 1.1 wiz if (c_nblock_used == s_save_nblockPP) continue; 653 1.1 wiz if (k1 != c_k0) { c_k0 = k1; continue; }; 654 1.1 wiz 655 1.1 wiz c_state_out_len = 3; 656 1.1 wiz BZ_GET_FAST_C(k1); c_nblock_used++; 657 1.1 wiz if (c_nblock_used == s_save_nblockPP) continue; 658 1.1 wiz if (k1 != c_k0) { c_k0 = k1; continue; }; 659 1.1 wiz 660 1.1 wiz BZ_GET_FAST_C(k1); c_nblock_used++; 661 1.1 wiz c_state_out_len = ((Int32)k1) + 4; 662 1.1 wiz BZ_GET_FAST_C(c_k0); c_nblock_used++; 663 1.1 wiz } 664 1.1 wiz 665 1.1 wiz return_notr: 666 1.1 wiz total_out_lo32_old = s->strm->total_out_lo32; 667 1.1 wiz s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out); 668 1.1 wiz if (s->strm->total_out_lo32 < total_out_lo32_old) 669 1.1 wiz s->strm->total_out_hi32++; 670 1.1 wiz 671 1.1 wiz /* save */ 672 1.1 wiz s->calculatedBlockCRC = c_calculatedBlockCRC; 673 1.1 wiz s->state_out_ch = c_state_out_ch; 674 1.1 wiz s->state_out_len = c_state_out_len; 675 1.1 wiz s->nblock_used = c_nblock_used; 676 1.1 wiz s->k0 = c_k0; 677 1.1 wiz s->tt = c_tt; 678 1.1 wiz s->tPos = c_tPos; 679 1.1 wiz s->strm->next_out = cs_next_out; 680 1.1 wiz s->strm->avail_out = cs_avail_out; 681 1.1 wiz /* end save */ 682 1.1 wiz } 683 1.1 wiz return False; 684 1.1 wiz } 685 1.1 wiz 686 1.1 wiz 687 1.1 wiz 688 1.1 wiz /*---------------------------------------------------*/ 689 1.1 wiz __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab ) 690 1.1 wiz { 691 1.1 wiz Int32 nb, na, mid; 692 1.1 wiz nb = 0; 693 1.1 wiz na = 256; 694 1.1 wiz do { 695 1.1 wiz mid = (nb + na) >> 1; 696 1.1 wiz if (indx >= cftab[mid]) nb = mid; else na = mid; 697 1.1 wiz } 698 1.1 wiz while (na - nb != 1); 699 1.1 wiz return nb; 700 1.1 wiz } 701 1.1 wiz 702 1.1 wiz 703 1.1 wiz /*---------------------------------------------------*/ 704 1.1 wiz /* Return True iff data corruption is discovered. 705 1.1 wiz Returns False if there is no problem. 706 1.1 wiz */ 707 1.1 wiz static 708 1.1 wiz Bool unRLE_obuf_to_output_SMALL ( DState* s ) 709 1.1 wiz { 710 1.1 wiz UChar k1; 711 1.1 wiz 712 1.1 wiz if (s->blockRandomised) { 713 1.1 wiz 714 1.1 wiz while (True) { 715 1.1 wiz /* try to finish existing run */ 716 1.1 wiz while (True) { 717 1.1 wiz if (s->strm->avail_out == 0) return False; 718 1.1 wiz if (s->state_out_len == 0) break; 719 1.1 wiz *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; 720 1.1 wiz BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); 721 1.1 wiz s->state_out_len--; 722 1.1 wiz s->strm->next_out++; 723 1.1 wiz s->strm->avail_out--; 724 1.1 wiz s->strm->total_out_lo32++; 725 1.1 wiz if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; 726 1.1 wiz } 727 1.1 wiz 728 1.1 wiz /* can a new run be started? */ 729 1.1 wiz if (s->nblock_used == s->save_nblock+1) return False; 730 1.1 wiz 731 1.1 wiz /* Only caused by corrupt data stream? */ 732 1.1 wiz if (s->nblock_used > s->save_nblock+1) 733 1.1 wiz return True; 734 1.1 wiz 735 1.1 wiz s->state_out_len = 1; 736 1.1 wiz s->state_out_ch = s->k0; 737 1.1 wiz BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 738 1.1 wiz k1 ^= BZ_RAND_MASK; s->nblock_used++; 739 1.1 wiz if (s->nblock_used == s->save_nblock+1) continue; 740 1.1 wiz if (k1 != s->k0) { s->k0 = k1; continue; }; 741 1.1 wiz 742 1.1 wiz s->state_out_len = 2; 743 1.1 wiz BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 744 1.1 wiz k1 ^= BZ_RAND_MASK; s->nblock_used++; 745 1.1 wiz if (s->nblock_used == s->save_nblock+1) continue; 746 1.1 wiz if (k1 != s->k0) { s->k0 = k1; continue; }; 747 1.1 wiz 748 1.1 wiz s->state_out_len = 3; 749 1.1 wiz BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 750 1.1 wiz k1 ^= BZ_RAND_MASK; s->nblock_used++; 751 1.1 wiz if (s->nblock_used == s->save_nblock+1) continue; 752 1.1 wiz if (k1 != s->k0) { s->k0 = k1; continue; }; 753 1.1 wiz 754 1.1 wiz BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 755 1.1 wiz k1 ^= BZ_RAND_MASK; s->nblock_used++; 756 1.1 wiz s->state_out_len = ((Int32)k1) + 4; 757 1.1 wiz BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; 758 1.1 wiz s->k0 ^= BZ_RAND_MASK; s->nblock_used++; 759 1.1 wiz } 760 1.1 wiz 761 1.1 wiz } else { 762 1.1 wiz 763 1.1 wiz while (True) { 764 1.1 wiz /* try to finish existing run */ 765 1.1 wiz while (True) { 766 1.1 wiz if (s->strm->avail_out == 0) return False; 767 1.1 wiz if (s->state_out_len == 0) break; 768 1.1 wiz *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; 769 1.1 wiz BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); 770 1.1 wiz s->state_out_len--; 771 1.1 wiz s->strm->next_out++; 772 1.1 wiz s->strm->avail_out--; 773 1.1 wiz s->strm->total_out_lo32++; 774 1.1 wiz if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; 775 1.1 wiz } 776 1.1 wiz 777 1.1 wiz /* can a new run be started? */ 778 1.1 wiz if (s->nblock_used == s->save_nblock+1) return False; 779 1.1 wiz 780 1.1 wiz /* Only caused by corrupt data stream? */ 781 1.1 wiz if (s->nblock_used > s->save_nblock+1) 782 1.1 wiz return True; 783 1.1 wiz 784 1.1 wiz s->state_out_len = 1; 785 1.1 wiz s->state_out_ch = s->k0; 786 1.1 wiz BZ_GET_SMALL(k1); s->nblock_used++; 787 1.1 wiz if (s->nblock_used == s->save_nblock+1) continue; 788 1.1 wiz if (k1 != s->k0) { s->k0 = k1; continue; }; 789 1.1 wiz 790 1.1 wiz s->state_out_len = 2; 791 1.1 wiz BZ_GET_SMALL(k1); s->nblock_used++; 792 1.1 wiz if (s->nblock_used == s->save_nblock+1) continue; 793 1.1 wiz if (k1 != s->k0) { s->k0 = k1; continue; }; 794 1.1 wiz 795 1.1 wiz s->state_out_len = 3; 796 1.1 wiz BZ_GET_SMALL(k1); s->nblock_used++; 797 1.1 wiz if (s->nblock_used == s->save_nblock+1) continue; 798 1.1 wiz if (k1 != s->k0) { s->k0 = k1; continue; }; 799 1.1 wiz 800 1.1 wiz BZ_GET_SMALL(k1); s->nblock_used++; 801 1.1 wiz s->state_out_len = ((Int32)k1) + 4; 802 1.1 wiz BZ_GET_SMALL(s->k0); s->nblock_used++; 803 1.1 wiz } 804 1.1 wiz 805 1.1 wiz } 806 1.1 wiz } 807 1.1 wiz 808 1.1 wiz 809 1.1 wiz /*---------------------------------------------------*/ 810 1.1 wiz int BZ_API(BZ2_bzDecompress) ( bz_stream *strm ) 811 1.1 wiz { 812 1.1 wiz Bool corrupt; 813 1.1 wiz DState* s; 814 1.1 wiz if (strm == NULL) return BZ_PARAM_ERROR; 815 1.1 wiz s = strm->state; 816 1.1 wiz if (s == NULL) return BZ_PARAM_ERROR; 817 1.1 wiz if (s->strm != strm) return BZ_PARAM_ERROR; 818 1.1 wiz 819 1.1 wiz while (True) { 820 1.1 wiz if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; 821 1.1 wiz if (s->state == BZ_X_OUTPUT) { 822 1.1 wiz if (s->smallDecompress) 823 1.1 wiz corrupt = unRLE_obuf_to_output_SMALL ( s ); else 824 1.1 wiz corrupt = unRLE_obuf_to_output_FAST ( s ); 825 1.1 wiz if (corrupt) return BZ_DATA_ERROR; 826 1.1 wiz if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { 827 1.1 wiz BZ_FINALISE_CRC ( s->calculatedBlockCRC ); 828 1.1 wiz if (s->verbosity >= 3) 829 1.1 wiz VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, 830 1.1 wiz s->calculatedBlockCRC ); 831 1.1 wiz if (s->verbosity >= 2) VPrintf0 ( "]" ); 832 1.1 wiz if (s->calculatedBlockCRC != s->storedBlockCRC) 833 1.1 wiz return BZ_DATA_ERROR; 834 1.1 wiz s->calculatedCombinedCRC 835 1.1 wiz = (s->calculatedCombinedCRC << 1) | 836 1.1 wiz (s->calculatedCombinedCRC >> 31); 837 1.1 wiz s->calculatedCombinedCRC ^= s->calculatedBlockCRC; 838 1.1 wiz s->state = BZ_X_BLKHDR_1; 839 1.1 wiz } else { 840 1.1 wiz return BZ_OK; 841 1.1 wiz } 842 1.1 wiz } 843 1.1 wiz if (s->state >= BZ_X_MAGIC_1) { 844 1.1 wiz Int32 r = BZ2_decompress ( s ); 845 1.1 wiz if (r == BZ_STREAM_END) { 846 1.1 wiz if (s->verbosity >= 3) 847 1.1 wiz VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x", 848 1.1 wiz s->storedCombinedCRC, s->calculatedCombinedCRC ); 849 1.1 wiz if (s->calculatedCombinedCRC != s->storedCombinedCRC) 850 1.1 wiz return BZ_DATA_ERROR; 851 1.1 wiz return r; 852 1.1 wiz } 853 1.1 wiz if (s->state != BZ_X_OUTPUT) return r; 854 1.1 wiz } 855 1.1 wiz } 856 1.1 wiz 857 1.1 wiz AssertH ( 0, 6001 ); 858 1.1 wiz 859 1.1 wiz return 0; /*NOTREACHED*/ 860 1.1 wiz } 861 1.1 wiz 862 1.1 wiz 863 1.1 wiz /*---------------------------------------------------*/ 864 1.1 wiz int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm ) 865 1.1 wiz { 866 1.1 wiz DState* s; 867 1.1 wiz if (strm == NULL) return BZ_PARAM_ERROR; 868 1.1 wiz s = strm->state; 869 1.1 wiz if (s == NULL) return BZ_PARAM_ERROR; 870 1.1 wiz if (s->strm != strm) return BZ_PARAM_ERROR; 871 1.1 wiz 872 1.1 wiz if (s->tt != NULL) BZFREE(s->tt); 873 1.1 wiz if (s->ll16 != NULL) BZFREE(s->ll16); 874 1.1 wiz if (s->ll4 != NULL) BZFREE(s->ll4); 875 1.1 wiz 876 1.1 wiz BZFREE(strm->state); 877 1.1 wiz strm->state = NULL; 878 1.1 wiz 879 1.1 wiz return BZ_OK; 880 1.1 wiz } 881 1.1 wiz 882 1.1 wiz 883 1.1 wiz #ifndef BZ_NO_STDIO 884 1.1 wiz /*---------------------------------------------------*/ 885 1.1 wiz /*--- File I/O stuff ---*/ 886 1.1 wiz /*---------------------------------------------------*/ 887 1.1 wiz 888 1.1 wiz #define BZ_SETERR(eee) \ 889 1.1 wiz { \ 890 1.1 wiz if (bzerror != NULL) *bzerror = eee; \ 891 1.1 wiz if (bzf != NULL) bzf->lastErr = eee; \ 892 1.1 wiz } 893 1.1 wiz 894 1.1 wiz typedef 895 1.1 wiz struct { 896 1.1 wiz FILE* handle; 897 1.1 wiz Char buf[BZ_MAX_UNUSED]; 898 1.1 wiz Int32 bufN; 899 1.1 wiz Bool writing; 900 1.1 wiz bz_stream strm; 901 1.1 wiz Int32 lastErr; 902 1.1 wiz Bool initialisedOk; 903 1.1 wiz } 904 1.1 wiz bzFile; 905 1.1 wiz 906 1.1 wiz 907 1.1 wiz /*---------------------------------------------*/ 908 1.1 wiz static Bool myfeof ( FILE* f ) 909 1.1 wiz { 910 1.1 wiz Int32 c = fgetc ( f ); 911 1.1 wiz if (c == EOF) return True; 912 1.1 wiz ungetc ( c, f ); 913 1.1 wiz return False; 914 1.1 wiz } 915 1.1 wiz 916 1.1 wiz 917 1.1 wiz /*---------------------------------------------------*/ 918 1.1 wiz BZFILE* BZ_API(BZ2_bzWriteOpen) 919 1.1 wiz ( int* bzerror, 920 1.1 wiz FILE* f, 921 1.1 wiz int blockSize100k, 922 1.1 wiz int verbosity, 923 1.1 wiz int workFactor ) 924 1.1 wiz { 925 1.1 wiz Int32 ret; 926 1.1 wiz bzFile* bzf = NULL; 927 1.1 wiz 928 1.1 wiz BZ_SETERR(BZ_OK); 929 1.1 wiz 930 1.1 wiz if (f == NULL || 931 1.1 wiz (blockSize100k < 1 || blockSize100k > 9) || 932 1.1 wiz (workFactor < 0 || workFactor > 250) || 933 1.1 wiz (verbosity < 0 || verbosity > 4)) 934 1.1 wiz { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; 935 1.1 wiz 936 1.1 wiz if (ferror(f)) 937 1.1 wiz { BZ_SETERR(BZ_IO_ERROR); return NULL; }; 938 1.1 wiz 939 1.1 wiz bzf = malloc ( sizeof(bzFile) ); 940 1.1 wiz if (bzf == NULL) 941 1.1 wiz { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; 942 1.1 wiz 943 1.1 wiz BZ_SETERR(BZ_OK); 944 1.1 wiz bzf->initialisedOk = False; 945 1.1 wiz bzf->bufN = 0; 946 1.1 wiz bzf->handle = f; 947 1.1 wiz bzf->writing = True; 948 1.1 wiz bzf->strm.bzalloc = NULL; 949 1.1 wiz bzf->strm.bzfree = NULL; 950 1.1 wiz bzf->strm.opaque = NULL; 951 1.1 wiz 952 1.1 wiz if (workFactor == 0) workFactor = 30; 953 1.1 wiz ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, 954 1.1 wiz verbosity, workFactor ); 955 1.1 wiz if (ret != BZ_OK) 956 1.1 wiz { BZ_SETERR(ret); free(bzf); return NULL; }; 957 1.1 wiz 958 1.1 wiz bzf->strm.avail_in = 0; 959 1.1 wiz bzf->initialisedOk = True; 960 1.1 wiz return bzf; 961 1.1 wiz } 962 1.1 wiz 963 1.1 wiz 964 1.1 wiz 965 1.1 wiz /*---------------------------------------------------*/ 966 1.1 wiz void BZ_API(BZ2_bzWrite) 967 1.1 wiz ( int* bzerror, 968 1.1 wiz BZFILE* b, 969 1.1 wiz void* buf, 970 1.1 wiz int len ) 971 1.1 wiz { 972 1.1 wiz Int32 n, n2, ret; 973 1.1 wiz bzFile* bzf = (bzFile*)b; 974 1.1 wiz 975 1.1 wiz BZ_SETERR(BZ_OK); 976 1.1 wiz if (bzf == NULL || buf == NULL || len < 0) 977 1.1 wiz { BZ_SETERR(BZ_PARAM_ERROR); return; }; 978 1.1 wiz if (!(bzf->writing)) 979 1.1 wiz { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; 980 1.1 wiz if (ferror(bzf->handle)) 981 1.1 wiz { BZ_SETERR(BZ_IO_ERROR); return; }; 982 1.1 wiz 983 1.1 wiz if (len == 0) 984 1.1 wiz { BZ_SETERR(BZ_OK); return; }; 985 1.1 wiz 986 1.1 wiz bzf->strm.avail_in = len; 987 1.1 wiz bzf->strm.next_in = buf; 988 1.1 wiz 989 1.1 wiz while (True) { 990 1.1 wiz bzf->strm.avail_out = BZ_MAX_UNUSED; 991 1.1 wiz bzf->strm.next_out = bzf->buf; 992 1.1 wiz ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN ); 993 1.1 wiz if (ret != BZ_RUN_OK) 994 1.1 wiz { BZ_SETERR(ret); return; }; 995 1.1 wiz 996 1.1 wiz if (bzf->strm.avail_out < BZ_MAX_UNUSED) { 997 1.1 wiz n = BZ_MAX_UNUSED - bzf->strm.avail_out; 998 1.1 wiz n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 999 1.1 wiz n, bzf->handle ); 1000 1.1 wiz if (n != n2 || ferror(bzf->handle)) 1001 1.1 wiz { BZ_SETERR(BZ_IO_ERROR); return; }; 1002 1.1 wiz } 1003 1.1 wiz 1004 1.1 wiz if (bzf->strm.avail_in == 0) 1005 1.1 wiz { BZ_SETERR(BZ_OK); return; }; 1006 1.1 wiz } 1007 1.1 wiz } 1008 1.1 wiz 1009 1.1 wiz 1010 1.1 wiz /*---------------------------------------------------*/ 1011 1.1 wiz void BZ_API(BZ2_bzWriteClose) 1012 1.1 wiz ( int* bzerror, 1013 1.1 wiz BZFILE* b, 1014 1.1 wiz int abandon, 1015 1.1 wiz unsigned int* nbytes_in, 1016 1.1 wiz unsigned int* nbytes_out ) 1017 1.1 wiz { 1018 1.1 wiz BZ2_bzWriteClose64 ( bzerror, b, abandon, 1019 1.1 wiz nbytes_in, NULL, nbytes_out, NULL ); 1020 1.1 wiz } 1021 1.1 wiz 1022 1.1 wiz 1023 1.1 wiz void BZ_API(BZ2_bzWriteClose64) 1024 1.1 wiz ( int* bzerror, 1025 1.1 wiz BZFILE* b, 1026 1.1 wiz int abandon, 1027 1.1 wiz unsigned int* nbytes_in_lo32, 1028 1.1 wiz unsigned int* nbytes_in_hi32, 1029 1.1 wiz unsigned int* nbytes_out_lo32, 1030 1.1 wiz unsigned int* nbytes_out_hi32 ) 1031 1.1 wiz { 1032 1.1 wiz Int32 n, n2, ret; 1033 1.1 wiz bzFile* bzf = (bzFile*)b; 1034 1.1 wiz 1035 1.1 wiz if (bzf == NULL) 1036 1.1 wiz { BZ_SETERR(BZ_OK); return; }; 1037 1.1 wiz if (!(bzf->writing)) 1038 1.1 wiz { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; 1039 1.1 wiz if (ferror(bzf->handle)) 1040 1.1 wiz { BZ_SETERR(BZ_IO_ERROR); return; }; 1041 1.1 wiz 1042 1.1 wiz if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0; 1043 1.1 wiz if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0; 1044 1.1 wiz if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0; 1045 1.1 wiz if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0; 1046 1.1 wiz 1047 1.1 wiz if ((!abandon) && bzf->lastErr == BZ_OK) { 1048 1.1 wiz while (True) { 1049 1.1 wiz bzf->strm.avail_out = BZ_MAX_UNUSED; 1050 1.1 wiz bzf->strm.next_out = bzf->buf; 1051 1.1 wiz ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH ); 1052 1.1 wiz if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) 1053 1.1 wiz { BZ_SETERR(ret); return; }; 1054 1.1 wiz 1055 1.1 wiz if (bzf->strm.avail_out < BZ_MAX_UNUSED) { 1056 1.1 wiz n = BZ_MAX_UNUSED - bzf->strm.avail_out; 1057 1.1 wiz n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 1058 1.1 wiz n, bzf->handle ); 1059 1.1 wiz if (n != n2 || ferror(bzf->handle)) 1060 1.1 wiz { BZ_SETERR(BZ_IO_ERROR); return; }; 1061 1.1 wiz } 1062 1.1 wiz 1063 1.1 wiz if (ret == BZ_STREAM_END) break; 1064 1.1 wiz } 1065 1.1 wiz } 1066 1.1 wiz 1067 1.1 wiz if ( !abandon && !ferror ( bzf->handle ) ) { 1068 1.1 wiz fflush ( bzf->handle ); 1069 1.1 wiz if (ferror(bzf->handle)) 1070 1.1 wiz { BZ_SETERR(BZ_IO_ERROR); return; }; 1071 1.1 wiz } 1072 1.1 wiz 1073 1.1 wiz if (nbytes_in_lo32 != NULL) 1074 1.1 wiz *nbytes_in_lo32 = bzf->strm.total_in_lo32; 1075 1.1 wiz if (nbytes_in_hi32 != NULL) 1076 1.1 wiz *nbytes_in_hi32 = bzf->strm.total_in_hi32; 1077 1.1 wiz if (nbytes_out_lo32 != NULL) 1078 1.1 wiz *nbytes_out_lo32 = bzf->strm.total_out_lo32; 1079 1.1 wiz if (nbytes_out_hi32 != NULL) 1080 1.1 wiz *nbytes_out_hi32 = bzf->strm.total_out_hi32; 1081 1.1 wiz 1082 1.1 wiz BZ_SETERR(BZ_OK); 1083 1.1 wiz BZ2_bzCompressEnd ( &(bzf->strm) ); 1084 1.1 wiz free ( bzf ); 1085 1.1 wiz } 1086 1.1 wiz 1087 1.1 wiz 1088 1.1 wiz /*---------------------------------------------------*/ 1089 1.1 wiz BZFILE* BZ_API(BZ2_bzReadOpen) 1090 1.1 wiz ( int* bzerror, 1091 1.1 wiz FILE* f, 1092 1.1 wiz int verbosity, 1093 1.1 wiz int small, 1094 1.1 wiz void* unused, 1095 1.1 wiz int nUnused ) 1096 1.1 wiz { 1097 1.1 wiz bzFile* bzf = NULL; 1098 1.1 wiz int ret; 1099 1.1 wiz 1100 1.1 wiz BZ_SETERR(BZ_OK); 1101 1.1 wiz 1102 1.1 wiz if (f == NULL || 1103 1.1 wiz (small != 0 && small != 1) || 1104 1.1 wiz (verbosity < 0 || verbosity > 4) || 1105 1.1 wiz (unused == NULL && nUnused != 0) || 1106 1.1 wiz (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED))) 1107 1.1 wiz { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; 1108 1.1 wiz 1109 1.1 wiz if (ferror(f)) 1110 1.1 wiz { BZ_SETERR(BZ_IO_ERROR); return NULL; }; 1111 1.1 wiz 1112 1.1 wiz bzf = malloc ( sizeof(bzFile) ); 1113 1.1 wiz if (bzf == NULL) 1114 1.1 wiz { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; 1115 1.1 wiz 1116 1.1 wiz BZ_SETERR(BZ_OK); 1117 1.1 wiz 1118 1.1 wiz bzf->initialisedOk = False; 1119 1.1 wiz bzf->handle = f; 1120 1.1 wiz bzf->bufN = 0; 1121 1.1 wiz bzf->writing = False; 1122 1.1 wiz bzf->strm.bzalloc = NULL; 1123 1.1 wiz bzf->strm.bzfree = NULL; 1124 1.1 wiz bzf->strm.opaque = NULL; 1125 1.1 wiz 1126 1.1 wiz while (nUnused > 0) { 1127 1.1 wiz bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++; 1128 1.1 wiz unused = ((void*)( 1 + ((UChar*)(unused)) )); 1129 1.1 wiz nUnused--; 1130 1.1 wiz } 1131 1.1 wiz 1132 1.1 wiz ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small ); 1133 1.1 wiz if (ret != BZ_OK) 1134 1.1 wiz { BZ_SETERR(ret); free(bzf); return NULL; }; 1135 1.1 wiz 1136 1.1 wiz bzf->strm.avail_in = bzf->bufN; 1137 1.1 wiz bzf->strm.next_in = bzf->buf; 1138 1.1 wiz 1139 1.1 wiz bzf->initialisedOk = True; 1140 1.1 wiz return bzf; 1141 1.1 wiz } 1142 1.1 wiz 1143 1.1 wiz 1144 1.1 wiz /*---------------------------------------------------*/ 1145 1.1 wiz void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b ) 1146 1.1 wiz { 1147 1.1 wiz bzFile* bzf = (bzFile*)b; 1148 1.1 wiz 1149 1.1 wiz BZ_SETERR(BZ_OK); 1150 1.1 wiz if (bzf == NULL) 1151 1.1 wiz { BZ_SETERR(BZ_OK); return; }; 1152 1.1 wiz 1153 1.1 wiz if (bzf->writing) 1154 1.1 wiz { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; 1155 1.1 wiz 1156 1.1 wiz if (bzf->initialisedOk) 1157 1.1 wiz (void)BZ2_bzDecompressEnd ( &(bzf->strm) ); 1158 1.1 wiz free ( bzf ); 1159 1.1 wiz } 1160 1.1 wiz 1161 1.1 wiz 1162 1.1 wiz /*---------------------------------------------------*/ 1163 1.1 wiz int BZ_API(BZ2_bzRead) 1164 1.1 wiz ( int* bzerror, 1165 1.1 wiz BZFILE* b, 1166 1.1 wiz void* buf, 1167 1.1 wiz int len ) 1168 1.1 wiz { 1169 1.1 wiz Int32 n, ret; 1170 1.1 wiz bzFile* bzf = (bzFile*)b; 1171 1.1 wiz 1172 1.1 wiz BZ_SETERR(BZ_OK); 1173 1.1 wiz 1174 1.1 wiz if (bzf == NULL || buf == NULL || len < 0) 1175 1.1 wiz { BZ_SETERR(BZ_PARAM_ERROR); return 0; }; 1176 1.1 wiz 1177 1.1 wiz if (bzf->writing) 1178 1.1 wiz { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; }; 1179 1.1 wiz 1180 1.1 wiz if (len == 0) 1181 1.1 wiz { BZ_SETERR(BZ_OK); return 0; }; 1182 1.1 wiz 1183 1.1 wiz bzf->strm.avail_out = len; 1184 1.1 wiz bzf->strm.next_out = buf; 1185 1.1 wiz 1186 1.1 wiz while (True) { 1187 1.1 wiz 1188 1.1 wiz if (ferror(bzf->handle)) 1189 1.1 wiz { BZ_SETERR(BZ_IO_ERROR); return 0; }; 1190 1.1 wiz 1191 1.1 wiz if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) { 1192 1.1 wiz n = fread ( bzf->buf, sizeof(UChar), 1193 1.1 wiz BZ_MAX_UNUSED, bzf->handle ); 1194 1.1 wiz if (ferror(bzf->handle)) 1195 1.1 wiz { BZ_SETERR(BZ_IO_ERROR); return 0; }; 1196 1.1 wiz bzf->bufN = n; 1197 1.1 wiz bzf->strm.avail_in = bzf->bufN; 1198 1.1 wiz bzf->strm.next_in = bzf->buf; 1199 1.1 wiz } 1200 1.1 wiz 1201 1.1 wiz ret = BZ2_bzDecompress ( &(bzf->strm) ); 1202 1.1 wiz 1203 1.1 wiz if (ret != BZ_OK && ret != BZ_STREAM_END) 1204 1.1 wiz { BZ_SETERR(ret); return 0; }; 1205 1.1 wiz 1206 1.1 wiz if (ret == BZ_OK && myfeof(bzf->handle) && 1207 1.1 wiz bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0) 1208 1.1 wiz { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; }; 1209 1.1 wiz 1210 1.1 wiz if (ret == BZ_STREAM_END) 1211 1.1 wiz { BZ_SETERR(BZ_STREAM_END); 1212 1.1 wiz return len - bzf->strm.avail_out; }; 1213 1.1 wiz if (bzf->strm.avail_out == 0) 1214 1.1 wiz { BZ_SETERR(BZ_OK); return len; }; 1215 1.1 wiz 1216 1.1 wiz } 1217 1.1 wiz 1218 1.1 wiz return 0; /*not reached*/ 1219 1.1 wiz } 1220 1.1 wiz 1221 1.1 wiz 1222 1.1 wiz /*---------------------------------------------------*/ 1223 1.1 wiz void BZ_API(BZ2_bzReadGetUnused) 1224 1.1 wiz ( int* bzerror, 1225 1.1 wiz BZFILE* b, 1226 1.1 wiz void** unused, 1227 1.1 wiz int* nUnused ) 1228 1.1 wiz { 1229 1.1 wiz bzFile* bzf = (bzFile*)b; 1230 1.1 wiz if (bzf == NULL) 1231 1.1 wiz { BZ_SETERR(BZ_PARAM_ERROR); return; }; 1232 1.1 wiz if (bzf->lastErr != BZ_STREAM_END) 1233 1.1 wiz { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; 1234 1.1 wiz if (unused == NULL || nUnused == NULL) 1235 1.1 wiz { BZ_SETERR(BZ_PARAM_ERROR); return; }; 1236 1.1 wiz 1237 1.1 wiz BZ_SETERR(BZ_OK); 1238 1.1 wiz *nUnused = bzf->strm.avail_in; 1239 1.1 wiz *unused = bzf->strm.next_in; 1240 1.1 wiz } 1241 1.1 wiz #endif 1242 1.1 wiz 1243 1.1 wiz 1244 1.1 wiz /*---------------------------------------------------*/ 1245 1.1 wiz /*--- Misc convenience stuff ---*/ 1246 1.1 wiz /*---------------------------------------------------*/ 1247 1.1 wiz 1248 1.1 wiz /*---------------------------------------------------*/ 1249 1.1 wiz int BZ_API(BZ2_bzBuffToBuffCompress) 1250 1.1 wiz ( char* dest, 1251 1.1 wiz unsigned int* destLen, 1252 1.1 wiz char* source, 1253 1.1 wiz unsigned int sourceLen, 1254 1.1 wiz int blockSize100k, 1255 1.1 wiz int verbosity, 1256 1.1 wiz int workFactor ) 1257 1.1 wiz { 1258 1.1 wiz bz_stream strm; 1259 1.1 wiz int ret; 1260 1.1 wiz 1261 1.1 wiz if (dest == NULL || destLen == NULL || 1262 1.1 wiz source == NULL || 1263 1.1 wiz blockSize100k < 1 || blockSize100k > 9 || 1264 1.1 wiz verbosity < 0 || verbosity > 4 || 1265 1.1 wiz workFactor < 0 || workFactor > 250) 1266 1.1 wiz return BZ_PARAM_ERROR; 1267 1.1 wiz 1268 1.1 wiz if (workFactor == 0) workFactor = 30; 1269 1.1 wiz strm.bzalloc = NULL; 1270 1.1 wiz strm.bzfree = NULL; 1271 1.1 wiz strm.opaque = NULL; 1272 1.1 wiz ret = BZ2_bzCompressInit ( &strm, blockSize100k, 1273 1.1 wiz verbosity, workFactor ); 1274 1.1 wiz if (ret != BZ_OK) return ret; 1275 1.1 wiz 1276 1.1 wiz strm.next_in = source; 1277 1.1 wiz strm.next_out = dest; 1278 1.1 wiz strm.avail_in = sourceLen; 1279 1.1 wiz strm.avail_out = *destLen; 1280 1.1 wiz 1281 1.1 wiz ret = BZ2_bzCompress ( &strm, BZ_FINISH ); 1282 1.1 wiz if (ret == BZ_FINISH_OK) goto output_overflow; 1283 1.1 wiz if (ret != BZ_STREAM_END) goto errhandler; 1284 1.1 wiz 1285 1.1 wiz /* normal termination */ 1286 1.1 wiz *destLen -= strm.avail_out; 1287 1.1 wiz BZ2_bzCompressEnd ( &strm ); 1288 1.1 wiz return BZ_OK; 1289 1.1 wiz 1290 1.1 wiz output_overflow: 1291 1.1 wiz BZ2_bzCompressEnd ( &strm ); 1292 1.1 wiz return BZ_OUTBUFF_FULL; 1293 1.1 wiz 1294 1.1 wiz errhandler: 1295 1.1 wiz BZ2_bzCompressEnd ( &strm ); 1296 1.1 wiz return ret; 1297 1.1 wiz } 1298 1.1 wiz 1299 1.1 wiz 1300 1.1 wiz /*---------------------------------------------------*/ 1301 1.1 wiz int BZ_API(BZ2_bzBuffToBuffDecompress) 1302 1.1 wiz ( char* dest, 1303 1.1 wiz unsigned int* destLen, 1304 1.1 wiz char* source, 1305 1.1 wiz unsigned int sourceLen, 1306 1.1 wiz int small, 1307 1.1 wiz int verbosity ) 1308 1.1 wiz { 1309 1.1 wiz bz_stream strm; 1310 1.1 wiz int ret; 1311 1.1 wiz 1312 1.1 wiz if (dest == NULL || destLen == NULL || 1313 1.1 wiz source == NULL || 1314 1.1 wiz (small != 0 && small != 1) || 1315 1.1 wiz verbosity < 0 || verbosity > 4) 1316 1.1 wiz return BZ_PARAM_ERROR; 1317 1.1 wiz 1318 1.1 wiz strm.bzalloc = NULL; 1319 1.1 wiz strm.bzfree = NULL; 1320 1.1 wiz strm.opaque = NULL; 1321 1.1 wiz ret = BZ2_bzDecompressInit ( &strm, verbosity, small ); 1322 1.1 wiz if (ret != BZ_OK) return ret; 1323 1.1 wiz 1324 1.1 wiz strm.next_in = source; 1325 1.1 wiz strm.next_out = dest; 1326 1.1 wiz strm.avail_in = sourceLen; 1327 1.1 wiz strm.avail_out = *destLen; 1328 1.1 wiz 1329 1.1 wiz ret = BZ2_bzDecompress ( &strm ); 1330 1.1 wiz if (ret == BZ_OK) goto output_overflow_or_eof; 1331 1.1 wiz if (ret != BZ_STREAM_END) goto errhandler; 1332 1.1 wiz 1333 1.1 wiz /* normal termination */ 1334 1.1 wiz *destLen -= strm.avail_out; 1335 1.1 wiz BZ2_bzDecompressEnd ( &strm ); 1336 1.1 wiz return BZ_OK; 1337 1.1 wiz 1338 1.1 wiz output_overflow_or_eof: 1339 1.1 wiz if (strm.avail_out > 0) { 1340 1.1 wiz BZ2_bzDecompressEnd ( &strm ); 1341 1.1 wiz return BZ_UNEXPECTED_EOF; 1342 1.1 wiz } else { 1343 1.1 wiz BZ2_bzDecompressEnd ( &strm ); 1344 1.1 wiz return BZ_OUTBUFF_FULL; 1345 1.1 wiz }; 1346 1.1 wiz 1347 1.1 wiz errhandler: 1348 1.1 wiz BZ2_bzDecompressEnd ( &strm ); 1349 1.1 wiz return ret; 1350 1.1 wiz } 1351 1.1 wiz 1352 1.1 wiz 1353 1.1 wiz /*---------------------------------------------------*/ 1354 1.1 wiz /*-- 1355 1.1 wiz Code contributed by Yoshioka Tsuneo (tsuneo (at) rr.iij4u.or.jp) 1356 1.1 wiz to support better zlib compatibility. 1357 1.1 wiz This code is not _officially_ part of libbzip2 (yet); 1358 1.1 wiz I haven't tested it, documented it, or considered the 1359 1.1 wiz threading-safeness of it. 1360 1.1 wiz If this code breaks, please contact both Yoshioka and me. 1361 1.1 wiz --*/ 1362 1.1 wiz /*---------------------------------------------------*/ 1363 1.1 wiz 1364 1.1 wiz /*---------------------------------------------------*/ 1365 1.1 wiz /*-- 1366 1.1 wiz return version like "0.9.5d, 4-Sept-1999". 1367 1.1 wiz --*/ 1368 1.1 wiz const char * BZ_API(BZ2_bzlibVersion)(void) 1369 1.1 wiz { 1370 1.1 wiz return BZ_VERSION; 1371 1.1 wiz } 1372 1.1 wiz 1373 1.1 wiz 1374 1.1 wiz #ifndef BZ_NO_STDIO 1375 1.1 wiz /*---------------------------------------------------*/ 1376 1.1 wiz 1377 1.1 wiz #if defined(_WIN32) || defined(OS2) || defined(MSDOS) 1378 1.1 wiz # include <fcntl.h> 1379 1.1 wiz # include <io.h> 1380 1.1 wiz # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) 1381 1.1 wiz #else 1382 1.1 wiz # define SET_BINARY_MODE(file) 1383 1.1 wiz #endif 1384 1.1 wiz static 1385 1.1 wiz BZFILE * bzopen_or_bzdopen 1386 1.1 wiz ( const char *path, /* no use when bzdopen */ 1387 1.1 wiz int fd, /* no use when bzdopen */ 1388 1.1 wiz const char *mode, 1389 1.1 wiz int open_mode) /* bzopen: 0, bzdopen:1 */ 1390 1.1 wiz { 1391 1.1 wiz int bzerr; 1392 1.1 wiz char unused[BZ_MAX_UNUSED]; 1393 1.1 wiz int blockSize100k = 9; 1394 1.1 wiz int writing = 0; 1395 1.1 wiz char mode2[10] = ""; 1396 1.1 wiz FILE *fp = NULL; 1397 1.1 wiz BZFILE *bzfp = NULL; 1398 1.1 wiz int verbosity = 0; 1399 1.1 wiz int workFactor = 30; 1400 1.1 wiz int smallMode = 0; 1401 1.1 wiz int nUnused = 0; 1402 1.1 wiz 1403 1.1 wiz if (mode == NULL) return NULL; 1404 1.1 wiz while (*mode) { 1405 1.1 wiz switch (*mode) { 1406 1.1 wiz case 'r': 1407 1.1 wiz writing = 0; break; 1408 1.1 wiz case 'w': 1409 1.1 wiz writing = 1; break; 1410 1.1 wiz case 's': 1411 1.1 wiz smallMode = 1; break; 1412 1.1 wiz default: 1413 1.5 rillig if (isdigit((UChar)(*mode))) { 1414 1.1 wiz blockSize100k = *mode-BZ_HDR_0; 1415 1.1 wiz } 1416 1.1 wiz } 1417 1.1 wiz mode++; 1418 1.1 wiz } 1419 1.1 wiz strcat(mode2, writing ? "w" : "r" ); 1420 1.1 wiz strcat(mode2,"b"); /* binary mode */ 1421 1.1 wiz 1422 1.1 wiz if (open_mode==0) { 1423 1.1 wiz if (path==NULL || strcmp(path,"")==0) { 1424 1.1 wiz fp = (writing ? stdout : stdin); 1425 1.1 wiz SET_BINARY_MODE(fp); 1426 1.1 wiz } else { 1427 1.1 wiz fp = fopen(path,mode2); 1428 1.1 wiz } 1429 1.1 wiz } else { 1430 1.1 wiz #ifdef BZ_STRICT_ANSI 1431 1.1 wiz fp = NULL; 1432 1.1 wiz #else 1433 1.1 wiz fp = fdopen(fd,mode2); 1434 1.1 wiz #endif 1435 1.1 wiz } 1436 1.1 wiz if (fp == NULL) return NULL; 1437 1.1 wiz 1438 1.1 wiz if (writing) { 1439 1.1 wiz /* Guard against total chaos and anarchy -- JRS */ 1440 1.1 wiz if (blockSize100k < 1) blockSize100k = 1; 1441 1.1 wiz if (blockSize100k > 9) blockSize100k = 9; 1442 1.1 wiz bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k, 1443 1.1 wiz verbosity,workFactor); 1444 1.1 wiz } else { 1445 1.1 wiz bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode, 1446 1.1 wiz unused,nUnused); 1447 1.1 wiz } 1448 1.1 wiz if (bzfp == NULL) { 1449 1.1 wiz if (fp != stdin && fp != stdout) fclose(fp); 1450 1.1 wiz return NULL; 1451 1.1 wiz } 1452 1.1 wiz return bzfp; 1453 1.1 wiz } 1454 1.1 wiz 1455 1.1 wiz 1456 1.1 wiz /*---------------------------------------------------*/ 1457 1.1 wiz /*-- 1458 1.1 wiz open file for read or write. 1459 1.1 wiz ex) bzopen("file","w9") 1460 1.1 wiz case path="" or NULL => use stdin or stdout. 1461 1.1 wiz --*/ 1462 1.1 wiz BZFILE * BZ_API(BZ2_bzopen) 1463 1.1 wiz ( const char *path, 1464 1.1 wiz const char *mode ) 1465 1.1 wiz { 1466 1.1 wiz return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0); 1467 1.1 wiz } 1468 1.1 wiz 1469 1.1 wiz 1470 1.1 wiz /*---------------------------------------------------*/ 1471 1.1 wiz BZFILE * BZ_API(BZ2_bzdopen) 1472 1.1 wiz ( int fd, 1473 1.1 wiz const char *mode ) 1474 1.1 wiz { 1475 1.1 wiz return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1); 1476 1.1 wiz } 1477 1.1 wiz 1478 1.1 wiz 1479 1.1 wiz /*---------------------------------------------------*/ 1480 1.1 wiz int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len ) 1481 1.1 wiz { 1482 1.1 wiz int bzerr, nread; 1483 1.1 wiz if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0; 1484 1.1 wiz nread = BZ2_bzRead(&bzerr,b,buf,len); 1485 1.1 wiz if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) { 1486 1.1 wiz return nread; 1487 1.1 wiz } else { 1488 1.1 wiz return -1; 1489 1.1 wiz } 1490 1.1 wiz } 1491 1.1 wiz 1492 1.1 wiz 1493 1.1 wiz /*---------------------------------------------------*/ 1494 1.1 wiz int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len ) 1495 1.1 wiz { 1496 1.1 wiz int bzerr; 1497 1.1 wiz 1498 1.1 wiz BZ2_bzWrite(&bzerr,b,buf,len); 1499 1.1 wiz if(bzerr == BZ_OK){ 1500 1.1 wiz return len; 1501 1.1 wiz }else{ 1502 1.1 wiz return -1; 1503 1.1 wiz } 1504 1.1 wiz } 1505 1.1 wiz 1506 1.1 wiz 1507 1.1 wiz /*---------------------------------------------------*/ 1508 1.1 wiz int BZ_API(BZ2_bzflush) (BZFILE *b) 1509 1.1 wiz { 1510 1.1 wiz /* do nothing now... */ 1511 1.1 wiz return 0; 1512 1.1 wiz } 1513 1.1 wiz 1514 1.1 wiz 1515 1.1 wiz /*---------------------------------------------------*/ 1516 1.1 wiz void BZ_API(BZ2_bzclose) (BZFILE* b) 1517 1.1 wiz { 1518 1.1 wiz int bzerr; 1519 1.1 wiz FILE *fp; 1520 1.1 wiz 1521 1.1 wiz if (b==NULL) {return;} 1522 1.1 wiz fp = ((bzFile *)b)->handle; 1523 1.1 wiz if(((bzFile*)b)->writing){ 1524 1.1 wiz BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL); 1525 1.1 wiz if(bzerr != BZ_OK){ 1526 1.1 wiz BZ2_bzWriteClose(NULL,b,1,NULL,NULL); 1527 1.1 wiz } 1528 1.1 wiz }else{ 1529 1.1 wiz BZ2_bzReadClose(&bzerr,b); 1530 1.1 wiz } 1531 1.1 wiz if(fp!=stdin && fp!=stdout){ 1532 1.1 wiz fclose(fp); 1533 1.1 wiz } 1534 1.1 wiz } 1535 1.1 wiz 1536 1.1 wiz 1537 1.1 wiz /*---------------------------------------------------*/ 1538 1.1 wiz /*-- 1539 1.1 wiz return last error code 1540 1.1 wiz --*/ 1541 1.1 wiz static const char *bzerrorstrings[] = { 1542 1.1 wiz "OK" 1543 1.1 wiz ,"SEQUENCE_ERROR" 1544 1.1 wiz ,"PARAM_ERROR" 1545 1.1 wiz ,"MEM_ERROR" 1546 1.1 wiz ,"DATA_ERROR" 1547 1.1 wiz ,"DATA_ERROR_MAGIC" 1548 1.1 wiz ,"IO_ERROR" 1549 1.1 wiz ,"UNEXPECTED_EOF" 1550 1.1 wiz ,"OUTBUFF_FULL" 1551 1.1 wiz ,"CONFIG_ERROR" 1552 1.1 wiz ,"???" /* for future */ 1553 1.1 wiz ,"???" /* for future */ 1554 1.1 wiz ,"???" /* for future */ 1555 1.1 wiz ,"???" /* for future */ 1556 1.1 wiz ,"???" /* for future */ 1557 1.1 wiz ,"???" /* for future */ 1558 1.1 wiz }; 1559 1.1 wiz 1560 1.1 wiz 1561 1.1 wiz const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum) 1562 1.1 wiz { 1563 1.1 wiz int err = ((bzFile *)b)->lastErr; 1564 1.1 wiz 1565 1.1 wiz if(err>0) err = 0; 1566 1.1 wiz *errnum = err; 1567 1.1 wiz return bzerrorstrings[err*-1]; 1568 1.1 wiz } 1569 1.1 wiz #endif 1570 1.1 wiz 1571 1.1 wiz 1572 1.1 wiz /*-------------------------------------------------------------*/ 1573 1.1 wiz /*--- end bzlib.c ---*/ 1574 1.1 wiz /*-------------------------------------------------------------*/ 1575