Coverage Report

Created: 2026-09-14 07:37

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