Coverage Report

Created: 2025-08-26 06:45

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