Coverage Report

Created: 2026-10-22 06:36

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
6.81k
{
93
6.81k
   if (sizeof(int)   != 4) return 0;
94
6.81k
   if (sizeof(short) != 2) return 0;
95
6.81k
   if (sizeof(char)  != 1) return 0;
96
6.81k
   return 1;
97
6.81k
}
98
99
100
/*---------------------------------------------------*/
101
static
102
void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
103
20.9k
{
104
20.9k
   void* v = malloc ( items * size );
105
20.9k
   return v;
106
20.9k
}
107
108
static
109
void default_bzfree ( void* opaque, void* addr )
110
20.9k
{
111
20.9k
   if (addr != NULL) free ( addr );
112
20.9k
}
113
114
115
/*---------------------------------------------------*/
116
static
117
void prepare_new_block ( EState* s )
118
3.32k
{
119
3.32k
   Int32 i;
120
3.32k
   s->nblock = 0;
121
3.32k
   s->numZ = 0;
122
3.32k
   s->state_out_pos = 0;
123
3.32k
   BZ_INITIALISE_CRC ( s->blockCRC );
124
853k
   for (i = 0; i < 256; i++) s->inUse[i] = False;
125
3.32k
   s->blockNo++;
126
3.32k
}
127
128
129
/*---------------------------------------------------*/
130
static
131
void init_RL ( EState* s )
132
6.04k
{
133
6.04k
   s->state_in_ch  = 256;
134
6.04k
   s->state_in_len = 0;
135
6.04k
}
136
137
138
static
139
Bool isempty_RL ( EState* s )
140
17.9k
{
141
17.9k
   if (s->state_in_ch < 256 && s->state_in_len > 0)
142
1.12k
      return False; else
143
16.8k
      return True;
144
17.9k
}
145
146
147
/*---------------------------------------------------*/
148
int BZ_API(BZ2_bzCompressInit) 
149
                    ( bz_stream* strm, 
150
                     int        blockSize100k,
151
                     int        verbosity,
152
                     int        workFactor )
153
3.02k
{
154
3.02k
   Int32   n;
155
3.02k
   EState* s;
156
157
3.02k
   if (!bz_config_ok()) return BZ_CONFIG_ERROR;
158
159
3.02k
   if (strm == NULL || 
160
3.02k
       blockSize100k < 1 || blockSize100k > 9 ||
161
3.02k
       workFactor < 0 || workFactor > 250)
162
0
     return BZ_PARAM_ERROR;
163
164
3.02k
   if (workFactor == 0) workFactor = 30;
165
3.02k
   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
166
3.02k
   if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
167
168
3.02k
   s = BZALLOC( sizeof(EState) );
169
3.02k
   if (s == NULL) return BZ_MEM_ERROR;
170
3.02k
   s->strm = strm;
171
172
3.02k
   s->arr1 = NULL;
173
3.02k
   s->arr2 = NULL;
174
3.02k
   s->ftab = NULL;
175
176
3.02k
   n       = 100000 * blockSize100k;
177
3.02k
   s->arr1 = BZALLOC( n                  * sizeof(UInt32) );
178
3.02k
   s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
179
3.02k
   s->ftab = BZALLOC( 65537              * sizeof(UInt32) );
180
181
3.02k
   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
3.02k
   s->blockNo           = 0;
190
3.02k
   s->state             = BZ_S_INPUT;
191
3.02k
   s->mode              = BZ_M_RUNNING;
192
3.02k
   s->combinedCRC       = 0;
193
3.02k
   s->blockSize100k     = blockSize100k;
194
3.02k
   s->nblockMAX         = 100000 * blockSize100k - 19;
195
3.02k
   s->verbosity         = verbosity;
196
3.02k
   s->workFactor        = workFactor;
197
198
3.02k
   s->block             = (UChar*)s->arr2;
199
3.02k
   s->mtfv              = (UInt16*)s->arr1;
200
3.02k
   s->zbits             = NULL;
201
3.02k
   s->ptr               = (UInt32*)s->arr1;
202
203
3.02k
   strm->state          = s;
204
3.02k
   strm->total_in_lo32  = 0;
205
3.02k
   strm->total_in_hi32  = 0;
206
3.02k
   strm->total_out_lo32 = 0;
207
3.02k
   strm->total_out_hi32 = 0;
208
3.02k
   init_RL ( s );
209
3.02k
   prepare_new_block ( s );
210
3.02k
   return BZ_OK;
211
3.02k
}
212
213
214
/*---------------------------------------------------*/
215
static
216
void add_pair_to_block ( EState* s )
217
49.8M
{
218
49.8M
   Int32 i;
219
49.8M
   UChar ch = (UChar)(s->state_in_ch);
220
233M
   for (i = 0; i < s->state_in_len; i++) {
221
183M
      BZ_UPDATE_CRC( s->blockCRC, ch );
222
183M
   }
223
49.8M
   s->inUse[s->state_in_ch] = True;
224
49.8M
   switch (s->state_in_len) {
225
2.28k
      case 1:
226
2.28k
         s->block[s->nblock] = (UChar)ch; s->nblock++;
227
2.28k
         break;
228
9.16M
      case 2:
229
9.16M
         s->block[s->nblock] = (UChar)ch; s->nblock++;
230
9.16M
         s->block[s->nblock] = (UChar)ch; s->nblock++;
231
9.16M
         break;
232
2.97M
      case 3:
233
2.97M
         s->block[s->nblock] = (UChar)ch; s->nblock++;
234
2.97M
         s->block[s->nblock] = (UChar)ch; s->nblock++;
235
2.97M
         s->block[s->nblock] = (UChar)ch; s->nblock++;
236
2.97M
         break;
237
37.7M
      default:
238
37.7M
         s->inUse[s->state_in_len-4] = True;
239
37.7M
         s->block[s->nblock] = (UChar)ch; s->nblock++;
240
37.7M
         s->block[s->nblock] = (UChar)ch; s->nblock++;
241
37.7M
         s->block[s->nblock] = (UChar)ch; s->nblock++;
242
37.7M
         s->block[s->nblock] = (UChar)ch; s->nblock++;
243
37.7M
         s->block[s->nblock] = ((UChar)(s->state_in_len-4));
244
37.7M
         s->nblock++;
245
37.7M
         break;
246
49.8M
   }
247
49.8M
}
248
249
250
/*---------------------------------------------------*/
251
static
252
void flush_RL ( EState* s )
253
3.02k
{
254
3.02k
   if (s->state_in_ch < 256) add_pair_to_block ( s );
255
3.02k
   init_RL ( s );
256
3.02k
}
257
258
259
/*---------------------------------------------------*/
260
376M
#define ADD_CHAR_TO_BLOCK(zs,zchh0)               \
261
376M
{                                                 \
262
376M
   UInt32 zchh = (UInt32)(zchh0);                 \
263
376M
   /*-- fast track the common case --*/           \
264
376M
   if (zchh != zs->state_in_ch &&                 \
265
376M
       zs->state_in_len == 1) {                   \
266
193M
      UChar ch = (UChar)(zs->state_in_ch);        \
267
193M
      BZ_UPDATE_CRC( zs->blockCRC, ch );          \
268
193M
      zs->inUse[zs->state_in_ch] = True;          \
269
193M
      zs->block[zs->nblock] = (UChar)ch;          \
270
193M
      zs->nblock++;                               \
271
193M
      zs->state_in_ch = zchh;                     \
272
193M
   }                                              \
273
376M
   else                                           \
274
376M
   /*-- general, uncommon cases --*/              \
275
376M
   if (zchh != zs->state_in_ch ||                 \
276
183M
      zs->state_in_len == 255) {                  \
277
49.8M
      if (zs->state_in_ch < 256)                  \
278
49.8M
         add_pair_to_block ( zs );                \
279
49.8M
      zs->state_in_ch = zchh;                     \
280
49.8M
      zs->state_in_len = 1;                       \
281
133M
   } else {                                       \
282
133M
      zs->state_in_len++;                         \
283
133M
   }                                              \
284
376M
}
285
286
287
/*---------------------------------------------------*/
288
static
289
Bool copy_input_until_stop ( EState* s )
290
6.31k
{
291
6.31k
   Bool progress_in = False;
292
293
6.31k
   if (s->mode == BZ_M_RUNNING) {
294
295
      /*-- fast track the common case --*/
296
376M
      while (True) {
297
         /*-- block full? --*/
298
376M
         if (s->nblock >= s->nblockMAX) break;
299
         /*-- no input? --*/
300
376M
         if (s->strm->avail_in == 0) break;
301
376M
         progress_in = True;
302
376M
         ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
303
376M
         s->strm->next_in++;
304
376M
         s->strm->avail_in--;
305
376M
         s->strm->total_in_lo32++;
306
376M
         if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
307
376M
      }
308
309
3.29k
   } else {
310
311
      /*-- general, uncommon case --*/
312
3.02k
      while (True) {
313
         /*-- block full? --*/
314
3.02k
         if (s->nblock >= s->nblockMAX) break;
315
         /*-- no input? --*/
316
3.02k
         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
3.02k
   }
328
6.31k
   return progress_in;
329
6.31k
}
330
331
332
/*---------------------------------------------------*/
333
static
334
Bool copy_output_until_stop ( EState* s )
335
29.1k
{
336
29.1k
   Bool progress_out = False;
337
338
133M
   while (True) {
339
340
      /*-- no output space? --*/
341
133M
      if (s->strm->avail_out == 0) break;
342
343
      /*-- block done? --*/
344
133M
      if (s->state_out_pos >= s->numZ) break;
345
346
133M
      progress_out = True;
347
133M
      *(s->strm->next_out) = s->zbits[s->state_out_pos];
348
133M
      s->state_out_pos++;
349
133M
      s->strm->avail_out--;
350
133M
      s->strm->next_out++;
351
133M
      s->strm->total_out_lo32++;
352
133M
      if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
353
133M
   }
354
355
29.1k
   return progress_out;
356
29.1k
}
357
358
359
/*---------------------------------------------------*/
360
static
361
Bool handle_compress ( bz_stream* strm )
362
31.8k
{
363
31.8k
   Bool progress_in  = False;
364
31.8k
   Bool progress_out = False;
365
31.8k
   EState* s = strm->state;
366
   
367
35.2k
   while (True) {
368
369
35.2k
      if (s->state == BZ_S_OUTPUT) {
370
29.1k
         progress_out |= copy_output_until_stop ( s );
371
29.1k
         if (s->state_out_pos < s->numZ) break;
372
3.32k
         if (s->mode == BZ_M_FINISHING && 
373
3.04k
             s->avail_in_expect == 0 &&
374
3.04k
             isempty_RL(s)) break;
375
301
         prepare_new_block ( s );
376
301
         s->state = BZ_S_INPUT;
377
301
         if (s->mode == BZ_M_FLUSHING && 
378
0
             s->avail_in_expect == 0 &&
379
0
             isempty_RL(s)) break;
380
301
      }
381
382
6.31k
      if (s->state == BZ_S_INPUT) {
383
6.31k
         progress_in |= copy_input_until_stop ( s );
384
6.31k
         if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
385
3.02k
            flush_RL ( s );
386
3.02k
            BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
387
3.02k
            s->state = BZ_S_OUTPUT;
388
3.02k
         }
389
3.29k
         else
390
3.29k
         if (s->nblock >= s->nblockMAX) {
391
301
            BZ2_compressBlock ( s, False );
392
301
            s->state = BZ_S_OUTPUT;
393
301
         }
394
2.99k
         else
395
2.99k
         if (s->strm->avail_in == 0) {
396
2.99k
            break;
397
2.99k
         }
398
6.31k
      }
399
400
6.31k
   }
401
402
31.8k
   return progress_in || progress_out;
403
31.8k
}
404
405
406
/*---------------------------------------------------*/
407
int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
408
31.8k
{
409
31.8k
   Bool progress;
410
31.8k
   EState* s;
411
31.8k
   if (strm == NULL) return BZ_PARAM_ERROR;
412
31.8k
   s = strm->state;
413
31.8k
   if (s == NULL) return BZ_PARAM_ERROR;
414
31.8k
   if (s->strm != strm) return BZ_PARAM_ERROR;
415
416
34.9k
   preswitch:
417
34.9k
   switch (s->mode) {
418
419
0
      case BZ_M_IDLE:
420
0
         return BZ_SEQUENCE_ERROR;
421
422
19.9k
      case BZ_M_RUNNING:
423
19.9k
         if (action == BZ_RUN) {
424
16.9k
            progress = handle_compress ( strm );
425
16.9k
            return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
426
16.9k
         } 
427
3.02k
         else
428
3.02k
   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
3.02k
         else
434
3.02k
         if (action == BZ_FINISH) {
435
3.02k
            s->avail_in_expect = strm->avail_in;
436
3.02k
            s->mode = BZ_M_FINISHING;
437
3.02k
            goto preswitch;
438
3.02k
         }
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
14.9k
      case BZ_M_FINISHING:
453
14.9k
         if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
454
14.9k
         if (s->avail_in_expect != s->strm->avail_in) 
455
0
            return BZ_SEQUENCE_ERROR;
456
14.9k
         progress = handle_compress ( strm );
457
14.9k
         if (!progress) return BZ_SEQUENCE_ERROR;
458
14.9k
         if (s->avail_in_expect > 0 || !isempty_RL(s) ||
459
13.8k
             s->state_out_pos < s->numZ) return BZ_FINISH_OK;
460
3.02k
         s->mode = BZ_M_IDLE;
461
3.02k
         return BZ_STREAM_END;
462
34.9k
   }
463
0
   return BZ_OK; /*--not reached--*/
464
34.9k
}
465
466
467
/*---------------------------------------------------*/
468
int BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm )
469
3.02k
{
470
3.02k
   EState* s;
471
3.02k
   if (strm == NULL) return BZ_PARAM_ERROR;
472
3.02k
   s = strm->state;
473
3.02k
   if (s == NULL) return BZ_PARAM_ERROR;
474
3.02k
   if (s->strm != strm) return BZ_PARAM_ERROR;
475
476
3.02k
   if (s->arr1 != NULL) BZFREE(s->arr1);
477
3.02k
   if (s->arr2 != NULL) BZFREE(s->arr2);
478
3.02k
   if (s->ftab != NULL) BZFREE(s->ftab);
479
3.02k
   BZFREE(strm->state);
480
481
3.02k
   strm->state = NULL;   
482
483
3.02k
   return BZ_OK;
484
3.02k
}
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
3.79k
{
497
3.79k
   DState* s;
498
499
3.79k
   if (!bz_config_ok()) return BZ_CONFIG_ERROR;
500
501
3.79k
   if (strm == NULL) return BZ_PARAM_ERROR;
502
3.79k
   if (small != 0 && small != 1) return BZ_PARAM_ERROR;
503
3.79k
   if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
504
505
3.79k
   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
506
3.79k
   if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
507
508
3.79k
   s = BZALLOC( sizeof(DState) );
509
3.79k
   if (s == NULL) return BZ_MEM_ERROR;
510
3.79k
   s->strm                  = strm;
511
3.79k
   strm->state              = s;
512
3.79k
   s->state                 = BZ_X_MAGIC_1;
513
3.79k
   s->bsLive                = 0;
514
3.79k
   s->bsBuff                = 0;
515
3.79k
   s->calculatedCombinedCRC = 0;
516
3.79k
   strm->total_in_lo32      = 0;
517
3.79k
   strm->total_in_hi32      = 0;
518
3.79k
   strm->total_out_lo32     = 0;
519
3.79k
   strm->total_out_hi32     = 0;
520
3.79k
   s->smallDecompress       = (Bool)small;
521
3.79k
   s->ll4                   = NULL;
522
3.79k
   s->ll16                  = NULL;
523
3.79k
   s->tt                    = NULL;
524
3.79k
   s->currBlockNo           = 0;
525
3.79k
   s->verbosity             = verbosity;
526
527
3.79k
   return BZ_OK;
528
3.79k
}
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
108k
{
538
108k
   UChar k1;
539
540
108k
   if (s->blockRandomised) {
541
542
6.73M
      while (True) {
543
         /* try to finish existing run */
544
27.7M
         while (True) {
545
27.7M
            if (s->strm->avail_out == 0) return False;
546
27.7M
            if (s->state_out_len == 0) break;
547
20.9M
            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
548
20.9M
            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
549
20.9M
            s->state_out_len--;
550
20.9M
            s->strm->next_out++;
551
20.9M
            s->strm->avail_out--;
552
20.9M
            s->strm->total_out_lo32++;
553
20.9M
            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
554
20.9M
         }
555
556
         /* can a new run be started? */
557
6.73M
         if (s->nblock_used == s->save_nblock+1) return False;
558
               
559
         /* Only caused by corrupt data stream? */
560
6.72M
         if (s->nblock_used > s->save_nblock+1)
561
4
            return True;
562
   
563
6.72M
         s->state_out_len = 1;
564
6.72M
         s->state_out_ch = s->k0;
565
6.72M
         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
566
6.72M
         k1 ^= BZ_RAND_MASK; s->nblock_used++;
567
6.72M
         if (s->nblock_used == s->save_nblock+1) continue;
568
6.72M
         if (k1 != s->k0) { s->k0 = k1; continue; };
569
   
570
4.23M
         s->state_out_len = 2;
571
4.23M
         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
572
4.23M
         k1 ^= BZ_RAND_MASK; s->nblock_used++;
573
4.23M
         if (s->nblock_used == s->save_nblock+1) continue;
574
4.23M
         if (k1 != s->k0) { s->k0 = k1; continue; };
575
   
576
3.92M
         s->state_out_len = 3;
577
3.92M
         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
578
3.92M
         k1 ^= BZ_RAND_MASK; s->nblock_used++;
579
3.92M
         if (s->nblock_used == s->save_nblock+1) continue;
580
3.91M
         if (k1 != s->k0) { s->k0 = k1; continue; };
581
   
582
3.57M
         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
583
3.57M
         k1 ^= BZ_RAND_MASK; s->nblock_used++;
584
3.57M
         s->state_out_len = ((Int32)k1) + 4;
585
3.57M
         BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; 
586
3.57M
         s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
587
3.57M
      }
588
589
96.9k
   } else {
590
591
      /* restore */
592
96.9k
      UInt32        c_calculatedBlockCRC = s->calculatedBlockCRC;
593
96.9k
      UChar         c_state_out_ch       = s->state_out_ch;
594
96.9k
      Int32         c_state_out_len      = s->state_out_len;
595
96.9k
      Int32         c_nblock_used        = s->nblock_used;
596
96.9k
      Int32         c_k0                 = s->k0;
597
96.9k
      UInt32*       c_tt                 = s->tt;
598
96.9k
      UInt32        c_tPos               = s->tPos;
599
96.9k
      char*         cs_next_out          = s->strm->next_out;
600
96.9k
      unsigned int  cs_avail_out         = s->strm->avail_out;
601
96.9k
      Int32         ro_blockSize100k     = s->blockSize100k;
602
      /* end restore */
603
604
96.9k
      UInt32       avail_out_INIT = cs_avail_out;
605
96.9k
      Int32        s_save_nblockPP = s->save_nblock+1;
606
96.9k
      unsigned int total_out_lo32_old;
607
608
1.41M
      while (True) {
609
610
         /* try to finish existing run */
611
1.41M
         if (c_state_out_len > 0) {
612
14.3M
            while (True) {
613
14.3M
               if (cs_avail_out == 0) goto return_notr;
614
14.3M
               if (c_state_out_len == 1) break;
615
13.0M
               *( (UChar*)(cs_next_out) ) = c_state_out_ch;
616
13.0M
               BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
617
13.0M
               c_state_out_len--;
618
13.0M
               cs_next_out++;
619
13.0M
               cs_avail_out--;
620
13.0M
            }
621
2.22M
            s_state_out_len_eq_one:
622
2.22M
            {
623
2.22M
               if (cs_avail_out == 0) { 
624
6
                  c_state_out_len = 1; goto return_notr;
625
2.22M
               };
626
2.22M
               *( (UChar*)(cs_next_out) ) = c_state_out_ch;
627
2.22M
               BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
628
2.22M
               cs_next_out++;
629
2.22M
               cs_avail_out--;
630
2.22M
            }
631
2.22M
         }   
632
         /* Only caused by corrupt data stream? */
633
2.32M
         if (c_nblock_used > s_save_nblockPP)
634
10
            return True;
635
636
         /* can a new run be started? */
637
2.32M
         if (c_nblock_used == s_save_nblockPP) {
638
96.8k
            c_state_out_len = 0; goto return_notr;
639
2.22M
         };   
640
2.22M
         c_state_out_ch = c_k0;
641
2.22M
         BZ_GET_FAST_C(k1); c_nblock_used++;
642
2.22M
         if (k1 != c_k0) { 
643
905k
            c_k0 = k1; goto s_state_out_len_eq_one; 
644
1.31M
         };
645
1.31M
         if (c_nblock_used == s_save_nblockPP) 
646
855
            goto s_state_out_len_eq_one;
647
   
648
1.31M
         c_state_out_len = 2;
649
1.31M
         BZ_GET_FAST_C(k1); c_nblock_used++;
650
1.31M
         if (c_nblock_used == s_save_nblockPP) continue;
651
1.31M
         if (k1 != c_k0) { c_k0 = k1; continue; };
652
   
653
1.27M
         c_state_out_len = 3;
654
1.27M
         BZ_GET_FAST_C(k1); c_nblock_used++;
655
1.27M
         if (c_nblock_used == s_save_nblockPP) continue;
656
1.18M
         if (k1 != c_k0) { c_k0 = k1; continue; };
657
   
658
741k
         BZ_GET_FAST_C(k1); c_nblock_used++;
659
741k
         c_state_out_len = ((Int32)k1) + 4;
660
741k
         BZ_GET_FAST_C(c_k0); c_nblock_used++;
661
741k
      }
662
663
96.9k
      return_notr:
664
96.9k
      total_out_lo32_old = s->strm->total_out_lo32;
665
96.9k
      s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
666
96.9k
      if (s->strm->total_out_lo32 < total_out_lo32_old)
667
0
         s->strm->total_out_hi32++;
668
669
      /* save */
670
96.9k
      s->calculatedBlockCRC = c_calculatedBlockCRC;
671
96.9k
      s->state_out_ch       = c_state_out_ch;
672
96.9k
      s->state_out_len      = c_state_out_len;
673
96.9k
      s->nblock_used        = c_nblock_used;
674
96.9k
      s->k0                 = c_k0;
675
96.9k
      s->tt                 = c_tt;
676
96.9k
      s->tPos               = c_tPos;
677
96.9k
      s->strm->next_out     = cs_next_out;
678
96.9k
      s->strm->avail_out    = cs_avail_out;
679
      /* end save */
680
96.9k
   }
681
96.9k
   return False;
682
108k
}
683
684
685
686
/*---------------------------------------------------*/
687
__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
688
25.8M
{
689
25.8M
   Int32 nb, na, mid;
690
25.8M
   nb = 0;
691
25.8M
   na = 256;
692
206M
   do {
693
206M
      mid = (nb + na) >> 1;
694
206M
      if (indx >= cftab[mid]) nb = mid; else na = mid;
695
206M
   }
696
206M
   while (na - nb != 1);
697
25.8M
   return nb;
698
25.8M
}
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
97.9k
{
708
97.9k
   UChar k1;
709
710
97.9k
   if (s->blockRandomised) {
711
712
5.80M
      while (True) {
713
         /* try to finish existing run */
714
23.9M
         while (True) {
715
23.9M
            if (s->strm->avail_out == 0) return False;
716
23.9M
            if (s->state_out_len == 0) break;
717
18.1M
            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
718
18.1M
            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
719
18.1M
            s->state_out_len--;
720
18.1M
            s->strm->next_out++;
721
18.1M
            s->strm->avail_out--;
722
18.1M
            s->strm->total_out_lo32++;
723
18.1M
            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
724
18.1M
         }
725
   
726
         /* can a new run be started? */
727
5.80M
         if (s->nblock_used == s->save_nblock+1) return False;
728
729
         /* Only caused by corrupt data stream? */
730
5.79M
         if (s->nblock_used > s->save_nblock+1)
731
5
            return True;
732
   
733
5.79M
         s->state_out_len = 1;
734
5.79M
         s->state_out_ch = s->k0;
735
5.79M
         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
736
5.79M
         k1 ^= BZ_RAND_MASK; s->nblock_used++;
737
5.79M
         if (s->nblock_used == s->save_nblock+1) continue;
738
5.79M
         if (k1 != s->k0) { s->k0 = k1; continue; };
739
   
740
4.31M
         s->state_out_len = 2;
741
4.31M
         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
742
4.31M
         k1 ^= BZ_RAND_MASK; s->nblock_used++;
743
4.31M
         if (s->nblock_used == s->save_nblock+1) continue;
744
4.31M
         if (k1 != s->k0) { s->k0 = k1; continue; };
745
   
746
4.04M
         s->state_out_len = 3;
747
4.04M
         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
748
4.04M
         k1 ^= BZ_RAND_MASK; s->nblock_used++;
749
4.04M
         if (s->nblock_used == s->save_nblock+1) continue;
750
4.03M
         if (k1 != s->k0) { s->k0 = k1; continue; };
751
   
752
3.59M
         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
753
3.59M
         k1 ^= BZ_RAND_MASK; s->nblock_used++;
754
3.59M
         s->state_out_len = ((Int32)k1) + 4;
755
3.59M
         BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; 
756
3.59M
         s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
757
3.59M
      }
758
759
86.2k
   } else {
760
761
1.48M
      while (True) {
762
         /* try to finish existing run */
763
10.6M
         while (True) {
764
10.6M
            if (s->strm->avail_out == 0) return False;
765
10.6M
            if (s->state_out_len == 0) break;
766
9.18M
            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
767
9.18M
            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
768
9.18M
            s->state_out_len--;
769
9.18M
            s->strm->next_out++;
770
9.18M
            s->strm->avail_out--;
771
9.18M
            s->strm->total_out_lo32++;
772
9.18M
            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
773
9.18M
         }
774
   
775
         /* can a new run be started? */
776
1.48M
         if (s->nblock_used == s->save_nblock+1) return False;
777
778
         /* Only caused by corrupt data stream? */
779
1.39M
         if (s->nblock_used > s->save_nblock+1)
780
4
            return True;
781
   
782
1.39M
         s->state_out_len = 1;
783
1.39M
         s->state_out_ch = s->k0;
784
1.39M
         BZ_GET_SMALL(k1); s->nblock_used++;
785
1.39M
         if (s->nblock_used == s->save_nblock+1) continue;
786
1.39M
         if (k1 != s->k0) { s->k0 = k1; continue; };
787
   
788
934k
         s->state_out_len = 2;
789
934k
         BZ_GET_SMALL(k1); s->nblock_used++;
790
934k
         if (s->nblock_used == s->save_nblock+1) continue;
791
933k
         if (k1 != s->k0) { s->k0 = k1; continue; };
792
   
793
915k
         s->state_out_len = 3;
794
915k
         BZ_GET_SMALL(k1); s->nblock_used++;
795
915k
         if (s->nblock_used == s->save_nblock+1) continue;
796
830k
         if (k1 != s->k0) { s->k0 = k1; continue; };
797
   
798
565k
         BZ_GET_SMALL(k1); s->nblock_used++;
799
565k
         s->state_out_len = ((Int32)k1) + 4;
800
565k
         BZ_GET_SMALL(s->k0); s->nblock_used++;
801
565k
      }
802
803
86.2k
   }
804
97.9k
}
805
806
807
/*---------------------------------------------------*/
808
int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
809
3.79k
{
810
3.79k
   Bool    corrupt;
811
3.79k
   DState* s;
812
3.79k
   if (strm == NULL) return BZ_PARAM_ERROR;
813
3.79k
   s = strm->state;
814
3.79k
   if (s == NULL) return BZ_PARAM_ERROR;
815
3.79k
   if (s->strm != strm) return BZ_PARAM_ERROR;
816
817
210k
   while (True) {
818
210k
      if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
819
210k
      if (s->state == BZ_X_OUTPUT) {
820
206k
         if (s->smallDecompress)
821
97.9k
            corrupt = unRLE_obuf_to_output_SMALL ( s ); else
822
108k
            corrupt = unRLE_obuf_to_output_FAST  ( s );
823
206k
         if (corrupt) return BZ_DATA_ERROR;
824
206k
         if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
825
205k
            BZ_FINALISE_CRC ( s->calculatedBlockCRC );
826
205k
            if (s->verbosity >= 3) 
827
0
               VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, 
828
205k
                          s->calculatedBlockCRC );
829
205k
            if (s->verbosity >= 2) VPrintf0 ( "]" );
830
205k
            if (s->calculatedBlockCRC != s->storedBlockCRC)
831
260
               return BZ_DATA_ERROR;
832
205k
            s->calculatedCombinedCRC 
833
205k
               = (s->calculatedCombinedCRC << 1) | 
834
205k
                    (s->calculatedCombinedCRC >> 31);
835
205k
            s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
836
205k
            s->state = BZ_X_BLKHDR_1;
837
205k
         } else {
838
595
            return BZ_OK;
839
595
         }
840
206k
      }
841
209k
      if (s->state >= BZ_X_MAGIC_1) {
842
209k
         Int32 r = BZ2_decompress ( s );
843
209k
         if (r == BZ_STREAM_END) {
844
1.19k
            if (s->verbosity >= 3)
845
0
               VPrintf2 ( "\n    combined CRCs: stored = 0x%08x, computed = 0x%08x", 
846
1.19k
                          s->storedCombinedCRC, s->calculatedCombinedCRC );
847
1.19k
            if (s->calculatedCombinedCRC != s->storedCombinedCRC)
848
167
               return BZ_DATA_ERROR;
849
1.03k
            return r;
850
1.19k
         }
851
207k
         if (s->state != BZ_X_OUTPUT) return r;
852
207k
      }
853
209k
   }
854
855
0
   AssertH ( 0, 6001 );
856
857
0
   return 0;  /*NOTREACHED*/
858
3.79k
}
859
860
861
/*---------------------------------------------------*/
862
int BZ_API(BZ2_bzDecompressEnd)  ( bz_stream *strm )
863
3.79k
{
864
3.79k
   DState* s;
865
3.79k
   if (strm == NULL) return BZ_PARAM_ERROR;
866
3.79k
   s = strm->state;
867
3.79k
   if (s == NULL) return BZ_PARAM_ERROR;
868
3.79k
   if (s->strm != strm) return BZ_PARAM_ERROR;
869
870
3.79k
   if (s->tt   != NULL) BZFREE(s->tt);
871
3.79k
   if (s->ll16 != NULL) BZFREE(s->ll16);
872
3.79k
   if (s->ll4  != NULL) BZFREE(s->ll4);
873
874
3.79k
   BZFREE(strm->state);
875
3.79k
   strm->state = NULL;
876
877
3.79k
   return BZ_OK;
878
3.79k
}
879
880
881
#ifndef BZ_NO_STDIO
882
/*---------------------------------------------------*/
883
/*--- File I/O stuff                              ---*/
884
/*---------------------------------------------------*/
885
886
28.2k
#define BZ_SETERR(eee)                    \
887
28.2k
{                                         \
888
28.2k
   if (bzerror != NULL) *bzerror = eee;   \
889
28.2k
   if (bzf != NULL) bzf->lastErr = eee;   \
890
28.2k
}
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
1.01k
{
908
1.01k
   Int32 c = fgetc ( f );
909
1.01k
   if (c == EOF) return True;
910
1.01k
   ungetc ( c, f );
911
1.01k
   return False;
912
1.01k
}
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
3.02k
{
923
3.02k
   Int32   ret;
924
3.02k
   bzFile* bzf = NULL;
925
926
3.02k
   BZ_SETERR(BZ_OK);
927
928
3.02k
   if (f == NULL ||
929
3.02k
       (blockSize100k < 1 || blockSize100k > 9) ||
930
3.02k
       (workFactor < 0 || workFactor > 250) ||
931
3.02k
       (verbosity < 0 || verbosity > 4))
932
3.02k
      { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
933
934
3.02k
   if (ferror(f))
935
3.02k
      { BZ_SETERR(BZ_IO_ERROR); return NULL; };
936
937
3.02k
   bzf = malloc ( sizeof(bzFile) );
938
3.02k
   if (bzf == NULL)
939
3.02k
      { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
940
941
3.02k
   BZ_SETERR(BZ_OK);
942
3.02k
   bzf->initialisedOk = False;
943
3.02k
   bzf->bufN          = 0;
944
3.02k
   bzf->handle        = f;
945
3.02k
   bzf->writing       = True;
946
3.02k
   bzf->strm.bzalloc  = NULL;
947
3.02k
   bzf->strm.bzfree   = NULL;
948
3.02k
   bzf->strm.opaque   = NULL;
949
950
3.02k
   if (workFactor == 0) workFactor = 30;
951
3.02k
   ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, 
952
3.02k
                              verbosity, workFactor );
953
3.02k
   if (ret != BZ_OK)
954
3.02k
      { BZ_SETERR(ret); free(bzf); return NULL; };
955
956
3.02k
   bzf->strm.avail_in = 0;
957
3.02k
   bzf->initialisedOk = True;
958
3.02k
   return bzf;   
959
3.02k
}
960
961
962
963
/*---------------------------------------------------*/
964
void BZ_API(BZ2_bzWrite)
965
             ( int*    bzerror, 
966
               BZFILE* b, 
967
               void*   buf, 
968
               int     len )
969
3.02k
{
970
3.02k
   Int32 n, n2, ret;
971
3.02k
   bzFile* bzf = (bzFile*)b;
972
973
3.02k
   BZ_SETERR(BZ_OK);
974
3.02k
   if (bzf == NULL || buf == NULL || len < 0)
975
3.02k
      { BZ_SETERR(BZ_PARAM_ERROR); return; };
976
3.02k
   if (!(bzf->writing))
977
3.02k
      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
978
3.02k
   if (ferror(bzf->handle))
979
3.02k
      { BZ_SETERR(BZ_IO_ERROR); return; };
980
981
3.02k
   if (len == 0)
982
3.02k
      { BZ_SETERR(BZ_OK); return; };
983
984
3.02k
   bzf->strm.avail_in = len;
985
3.02k
   bzf->strm.next_in  = buf;
986
987
16.9k
   while (True) {
988
16.9k
      bzf->strm.avail_out = BZ_MAX_UNUSED;
989
16.9k
      bzf->strm.next_out = bzf->buf;
990
16.9k
      ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
991
16.9k
      if (ret != BZ_RUN_OK)
992
16.9k
         { BZ_SETERR(ret); return; };
993
994
16.9k
      if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
995
14.2k
         n = BZ_MAX_UNUSED - bzf->strm.avail_out;
996
14.2k
         n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
997
14.2k
                       n, bzf->handle );
998
14.2k
         if (n != n2 || ferror(bzf->handle))
999
14.2k
            { BZ_SETERR(BZ_IO_ERROR); return; };
1000
14.2k
      }
1001
1002
16.9k
      if (bzf->strm.avail_in == 0)
1003
13.9k
         { BZ_SETERR(BZ_OK); return; };
1004
13.9k
   }
1005
3.02k
}
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
3.02k
{
1030
3.02k
   Int32   n, n2, ret;
1031
3.02k
   bzFile* bzf = (bzFile*)b;
1032
1033
3.02k
   if (bzf == NULL)
1034
3.02k
      { BZ_SETERR(BZ_OK); return; };
1035
3.02k
   if (!(bzf->writing))
1036
3.02k
      { 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
3.02k
   if (!abandon && ferror(bzf->handle))
1041
3.02k
      { BZ_SETERR(BZ_IO_ERROR); return; };
1042
1043
3.02k
   if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1044
3.02k
   if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1045
3.02k
   if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1046
3.02k
   if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1047
1048
3.02k
   if ((!abandon) && bzf->lastErr == BZ_OK) {
1049
14.9k
      while (True) {
1050
14.9k
         bzf->strm.avail_out = BZ_MAX_UNUSED;
1051
14.9k
         bzf->strm.next_out = bzf->buf;
1052
14.9k
         ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1053
14.9k
         if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1054
14.9k
            { BZ_SETERR(ret); return; };
1055
1056
14.9k
         if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1057
14.9k
            n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1058
14.9k
            n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
1059
14.9k
                          n, bzf->handle );
1060
14.9k
            if (n != n2 || ferror(bzf->handle))
1061
14.9k
               { BZ_SETERR(BZ_IO_ERROR); return; };
1062
14.9k
         }
1063
1064
14.9k
         if (ret == BZ_STREAM_END) break;
1065
14.9k
      }
1066
3.02k
   }
1067
1068
3.02k
   if ( !abandon && !ferror ( bzf->handle ) ) {
1069
3.02k
      fflush ( bzf->handle );
1070
3.02k
      if (ferror(bzf->handle))
1071
3.02k
         { BZ_SETERR(BZ_IO_ERROR); return; };
1072
3.02k
   }
1073
1074
3.02k
   if (nbytes_in_lo32 != NULL)
1075
3.02k
      *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1076
3.02k
   if (nbytes_in_hi32 != NULL)
1077
3.02k
      *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1078
3.02k
   if (nbytes_out_lo32 != NULL)
1079
3.02k
      *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1080
3.02k
   if (nbytes_out_hi32 != NULL)
1081
3.02k
      *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1082
1083
3.02k
   BZ_SETERR(BZ_OK);
1084
3.02k
   BZ2_bzCompressEnd ( &(bzf->strm) );
1085
3.02k
   free ( bzf );
1086
3.02k
}
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
1.01k
{
1098
1.01k
   bzFile* bzf = NULL;
1099
1.01k
   int     ret;
1100
1101
1.01k
   BZ_SETERR(BZ_OK);
1102
1103
1.01k
   if (f == NULL || 
1104
1.01k
       (small != 0 && small != 1) ||
1105
1.01k
       (verbosity < 0 || verbosity > 4) ||
1106
1.01k
       (unused == NULL && nUnused != 0) ||
1107
1.01k
       (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1108
1.01k
      { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1109
1110
1.01k
   if (ferror(f))
1111
1.01k
      { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1112
1113
1.01k
   bzf = malloc ( sizeof(bzFile) );
1114
1.01k
   if (bzf == NULL) 
1115
1.01k
      { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1116
1117
1.01k
   BZ_SETERR(BZ_OK);
1118
1119
1.01k
   bzf->initialisedOk = False;
1120
1.01k
   bzf->handle        = f;
1121
1.01k
   bzf->bufN          = 0;
1122
1.01k
   bzf->writing       = False;
1123
1.01k
   bzf->strm.bzalloc  = NULL;
1124
1.01k
   bzf->strm.bzfree   = NULL;
1125
1.01k
   bzf->strm.opaque   = NULL;
1126
   
1127
1.01k
   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
1.01k
   ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1134
1.01k
   if (ret != BZ_OK)
1135
1.01k
      { BZ_SETERR(ret); free(bzf); return NULL; };
1136
1137
1.01k
   bzf->strm.avail_in = bzf->bufN;
1138
1.01k
   bzf->strm.next_in  = bzf->buf;
1139
1140
1.01k
   bzf->initialisedOk = True;
1141
1.01k
   return bzf;   
1142
1.01k
}
1143
1144
1145
/*---------------------------------------------------*/
1146
void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1147
3.02k
{
1148
3.02k
   bzFile* bzf = (bzFile*)b;
1149
1150
3.02k
   BZ_SETERR(BZ_OK);
1151
3.02k
   if (bzf == NULL)
1152
2.00k
      { BZ_SETERR(BZ_OK); return; };
1153
1154
1.01k
   if (bzf->writing)
1155
1.01k
      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1156
1157
1.01k
   if (bzf->initialisedOk)
1158
1.01k
      (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1159
1.01k
   free ( bzf );
1160
1.01k
}
1161
1162
1163
/*---------------------------------------------------*/
1164
int BZ_API(BZ2_bzRead) 
1165
           ( int*    bzerror, 
1166
             BZFILE* b, 
1167
             void*   buf, 
1168
             int     len )
1169
3.02k
{
1170
3.02k
   Int32   n, ret;
1171
3.02k
   bzFile* bzf = (bzFile*)b;
1172
1173
3.02k
   BZ_SETERR(BZ_OK);
1174
1175
3.02k
   if (bzf == NULL || buf == NULL || len < 0)
1176
2.00k
      { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1177
1178
1.01k
   if (bzf->writing)
1179
1.01k
      { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1180
1181
1.01k
   if (len == 0)
1182
1.01k
      { BZ_SETERR(BZ_OK); return 0; };
1183
1184
1.01k
   bzf->strm.avail_out = len;
1185
1.01k
   bzf->strm.next_out = buf;
1186
1187
1.01k
   while (True) {
1188
1189
1.01k
      if (ferror(bzf->handle)) 
1190
1.01k
         { BZ_SETERR(BZ_IO_ERROR); return 0; };
1191
1192
1.01k
      if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1193
1.01k
         n = fread ( bzf->buf, sizeof(UChar), 
1194
1.01k
                     BZ_MAX_UNUSED, bzf->handle );
1195
1.01k
         if (ferror(bzf->handle))
1196
1.01k
            { BZ_SETERR(BZ_IO_ERROR); return 0; };
1197
1.01k
         bzf->bufN = n;
1198
1.01k
         bzf->strm.avail_in = bzf->bufN;
1199
1.01k
         bzf->strm.next_in = bzf->buf;
1200
1.01k
      }
1201
1202
1.01k
      ret = BZ2_bzDecompress ( &(bzf->strm) );
1203
1204
1.01k
      if (ret != BZ_OK && ret != BZ_STREAM_END)
1205
1.01k
         { BZ_SETERR(ret); return 0; };
1206
1207
1.01k
      if (ret == BZ_OK && myfeof(bzf->handle) && 
1208
0
          bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1209
1.01k
         { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1210
1211
1.01k
      if (ret == BZ_STREAM_END)
1212
1.01k
         { BZ_SETERR(BZ_STREAM_END);
1213
1.01k
           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
1.01k
}
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
2.77k
{
1310
2.77k
   bz_stream strm;
1311
2.77k
   int ret;
1312
1313
2.77k
   if (dest == NULL || destLen == NULL || 
1314
2.77k
       source == NULL ||
1315
2.77k
       (small != 0 && small != 1) ||
1316
2.77k
       verbosity < 0 || verbosity > 4) 
1317
0
          return BZ_PARAM_ERROR;
1318
1319
2.77k
   strm.bzalloc = NULL;
1320
2.77k
   strm.bzfree = NULL;
1321
2.77k
   strm.opaque = NULL;
1322
2.77k
   ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1323
2.77k
   if (ret != BZ_OK) return ret;
1324
1325
2.77k
   strm.next_in = source;
1326
2.77k
   strm.next_out = dest;
1327
2.77k
   strm.avail_in = sourceLen;
1328
2.77k
   strm.avail_out = *destLen;
1329
1330
2.77k
   ret = BZ2_bzDecompress ( &strm );
1331
2.77k
   if (ret == BZ_OK) goto output_overflow_or_eof;
1332
1.02k
   if (ret != BZ_STREAM_END) goto errhandler;
1333
1334
   /* normal termination */
1335
11
   *destLen -= strm.avail_out;
1336
11
   BZ2_bzDecompressEnd ( &strm );
1337
11
   return BZ_OK;
1338
1339
1.75k
   output_overflow_or_eof:
1340
1.75k
   if (strm.avail_out > 0) {
1341
1.15k
      BZ2_bzDecompressEnd ( &strm );
1342
1.15k
      return BZ_UNEXPECTED_EOF;
1343
1.15k
   } else {
1344
595
      BZ2_bzDecompressEnd ( &strm );
1345
595
      return BZ_OUTBUFF_FULL;
1346
595
   };      
1347
1348
1.01k
   errhandler:
1349
1.01k
   BZ2_bzDecompressEnd ( &strm );
1350
1.01k
   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
3.02k
{
1371
3.02k
   return BZ_VERSION;
1372
3.02k
}
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
3.02k
{
1392
3.02k
   int    bzerr;
1393
3.02k
   char   unused[BZ_MAX_UNUSED];
1394
3.02k
   int    blockSize100k = 9;
1395
3.02k
   int    writing       = 0;
1396
3.02k
   char   mode2[10]     = "";
1397
3.02k
   FILE   *fp           = NULL;
1398
3.02k
   BZFILE *bzfp         = NULL;
1399
3.02k
   int    verbosity     = 0;
1400
3.02k
   int    workFactor    = 30;
1401
3.02k
   int    smallMode     = 0;
1402
3.02k
   int    nUnused       = 0; 
1403
1404
3.02k
   if (mode == NULL) return NULL;
1405
9.06k
   while (*mode) {
1406
6.04k
      switch (*mode) {
1407
3.02k
      case 'r':
1408
3.02k
         writing = 0; break;
1409
0
      case 'w':
1410
0
         writing = 1; break;
1411
0
      case 's':
1412
0
         smallMode = 1; break;
1413
3.02k
      default:
1414
3.02k
         if (isdigit((unsigned char)(*mode))) {
1415
0
            blockSize100k = *mode-BZ_HDR_0;
1416
0
         }
1417
6.04k
      }
1418
6.04k
      mode++;
1419
6.04k
   }
1420
3.02k
   strcat(mode2, writing ? "w" : "r" );
1421
3.02k
   strcat(mode2,"b");   /* binary mode */
1422
1423
3.02k
   if (open_mode==0) {
1424
3.02k
      if (path==NULL || strcmp(path,"")==0) {
1425
0
        fp = (writing ? stdout : stdin);
1426
0
        SET_BINARY_MODE(fp);
1427
3.02k
      } else {
1428
3.02k
        fp = fopen(path,mode2);
1429
3.02k
      }
1430
3.02k
   } else {
1431
#ifdef BZ_STRICT_ANSI
1432
      fp = NULL;
1433
#else
1434
0
      fp = fdopen(fd,mode2);
1435
0
#endif
1436
0
   }
1437
3.02k
   if (fp == NULL) return NULL;
1438
1439
1.01k
   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
1.01k
   } else {
1446
1.01k
      bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1447
1.01k
                            unused,nUnused);
1448
1.01k
   }
1449
1.01k
   if (bzfp == NULL) {
1450
0
      if (fp != stdin && fp != stdout) fclose(fp);
1451
0
      return NULL;
1452
0
   }
1453
1.01k
   return bzfp;
1454
1.01k
}
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
3.02k
{
1467
3.02k
   return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1468
3.02k
}
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
3.02k
{
1511
   /* do nothing now... */
1512
3.02k
   return 0;
1513
3.02k
}
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
/*-------------------------------------------------------------*/