Coverage Report

Created: 2026-10-13 06:07

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