Coverage Report

Created: 2025-10-28 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/bzip2-sys-0.1.13+1.0.8/bzip2-1.0.8/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
{
43
   fprintf(stderr, 
44
      "\n\nbzip2/libbzip2: internal error number %d.\n"
45
      "This is a bug in bzip2/libbzip2, %s.\n"
46
      "Please report it to: bzip2-devel@sourceware.org.  If this happened\n"
47
      "when you were using some program which uses libbzip2 as a\n"
48
      "component, you should also report this bug to the author(s)\n"
49
      "of that program.  Please make an effort to report this bug;\n"
50
      "timely and accurate bug reports eventually lead to higher\n"
51
      "quality software.  Thanks.\n\n",
52
      errcode,
53
      BZ2_bzlibVersion()
54
   );
55
56
   if (errcode == 1007) {
57
   fprintf(stderr,
58
      "\n*** A special note about internal error number 1007 ***\n"
59
      "\n"
60
      "Experience suggests that a common cause of i.e. 1007\n"
61
      "is unreliable memory or other hardware.  The 1007 assertion\n"
62
      "just happens to cross-check the results of huge numbers of\n"
63
      "memory reads/writes, and so acts (unintendedly) as a stress\n"
64
      "test of your memory system.\n"
65
      "\n"
66
      "I suggest the following: try compressing the file again,\n"
67
      "possibly monitoring progress in detail with the -vv flag.\n"
68
      "\n"
69
      "* If the error cannot be reproduced, and/or happens at different\n"
70
      "  points in compression, you may have a flaky memory system.\n"
71
      "  Try a memory-test program.  I have used Memtest86\n"
72
      "  (www.memtest86.com).  At the time of writing it is free (GPLd).\n"
73
      "  Memtest86 tests memory much more thorougly than your BIOSs\n"
74
      "  power-on test, and may find failures that the BIOS doesn't.\n"
75
      "\n"
76
      "* If the error can be repeatably reproduced, this is a bug in\n"
77
      "  bzip2, and I would very much like to hear about it.  Please\n"
78
      "  let me know, and, ideally, save a copy of the file causing the\n"
79
      "  problem -- without which I will be unable to investigate it.\n"
80
      "\n"
81
   );
82
   }
83
84
   exit(3);
85
}
86
#endif
87
88
89
/*---------------------------------------------------*/
90
static
91
int bz_config_ok ( void )
92
5.48k
{
93
5.48k
   if (sizeof(int)   != 4) return 0;
94
5.48k
   if (sizeof(short) != 2) return 0;
95
5.48k
   if (sizeof(char)  != 1) return 0;
96
5.48k
   return 1;
97
5.48k
}
98
99
100
/*---------------------------------------------------*/
101
static
102
void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
103
17.8k
{
104
17.8k
   void* v = malloc ( items * size );
105
17.8k
   return v;
106
17.8k
}
107
108
static
109
void default_bzfree ( void* opaque, void* addr )
110
17.8k
{
111
17.8k
   if (addr != NULL) free ( addr );
112
17.8k
}
113
114
115
/*---------------------------------------------------*/
116
static
117
void prepare_new_block ( EState* s )
118
3.62k
{
119
3.62k
   Int32 i;
120
3.62k
   s->nblock = 0;
121
3.62k
   s->numZ = 0;
122
3.62k
   s->state_out_pos = 0;
123
3.62k
   BZ_INITIALISE_CRC ( s->blockCRC );
124
931k
   for (i = 0; i < 256; i++) s->inUse[i] = False;
125
3.62k
   s->blockNo++;
126
3.62k
}
127
128
129
/*---------------------------------------------------*/
130
static
131
void init_RL ( EState* s )
132
7.18k
{
133
7.18k
   s->state_in_ch  = 256;
134
7.18k
   s->state_in_len = 0;
135
7.18k
}
136
137
138
static
139
Bool isempty_RL ( EState* s )
140
7.18k
{
141
7.18k
   if (s->state_in_ch < 256 && s->state_in_len > 0)
142
0
      return False; else
143
7.18k
      return True;
144
7.18k
}
145
146
147
/*---------------------------------------------------*/
148
int BZ_API(BZ2_bzCompressInit) 
149
                    ( bz_stream* strm, 
150
                     int        blockSize100k,
151
                     int        verbosity,
152
                     int        workFactor )
153
3.59k
{
154
3.59k
   Int32   n;
155
3.59k
   EState* s;
156
157
3.59k
   if (!bz_config_ok()) return BZ_CONFIG_ERROR;
158
159
3.59k
   if (strm == NULL || 
160
3.59k
       blockSize100k < 1 || blockSize100k > 9 ||
161
3.59k
       workFactor < 0 || workFactor > 250)
162
0
     return BZ_PARAM_ERROR;
163
164
3.59k
   if (workFactor == 0) workFactor = 30;
165
3.59k
   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
166
3.59k
   if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
167
168
3.59k
   s = BZALLOC( sizeof(EState) );
169
3.59k
   if (s == NULL) return BZ_MEM_ERROR;
170
3.59k
   s->strm = strm;
171
172
3.59k
   s->arr1 = NULL;
173
3.59k
   s->arr2 = NULL;
174
3.59k
   s->ftab = NULL;
175
176
3.59k
   n       = 100000 * blockSize100k;
177
3.59k
   s->arr1 = BZALLOC( n                  * sizeof(UInt32) );
178
3.59k
   s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
179
3.59k
   s->ftab = BZALLOC( 65537              * sizeof(UInt32) );
180
181
3.59k
   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.59k
   s->blockNo           = 0;
190
3.59k
   s->state             = BZ_S_INPUT;
191
3.59k
   s->mode              = BZ_M_RUNNING;
192
3.59k
   s->combinedCRC       = 0;
193
3.59k
   s->blockSize100k     = blockSize100k;
194
3.59k
   s->nblockMAX         = 100000 * blockSize100k - 19;
195
3.59k
   s->verbosity         = verbosity;
196
3.59k
   s->workFactor        = workFactor;
197
198
3.59k
   s->block             = (UChar*)s->arr2;
199
3.59k
   s->mtfv              = (UInt16*)s->arr1;
200
3.59k
   s->zbits             = NULL;
201
3.59k
   s->ptr               = (UInt32*)s->arr1;
202
203
3.59k
   strm->state          = s;
204
3.59k
   strm->total_in_lo32  = 0;
205
3.59k
   strm->total_in_hi32  = 0;
206
3.59k
   strm->total_out_lo32 = 0;
207
3.59k
   strm->total_out_hi32 = 0;
208
3.59k
   init_RL ( s );
209
3.59k
   prepare_new_block ( s );
210
3.59k
   return BZ_OK;
211
3.59k
}
212
213
214
/*---------------------------------------------------*/
215
static
216
void add_pair_to_block ( EState* s )
217
3.24M
{
218
3.24M
   Int32 i;
219
3.24M
   UChar ch = (UChar)(s->state_in_ch);
220
25.7M
   for (i = 0; i < s->state_in_len; i++) {
221
22.4M
      BZ_UPDATE_CRC( s->blockCRC, ch );
222
22.4M
   }
223
3.24M
   s->inUse[s->state_in_ch] = True;
224
3.24M
   switch (s->state_in_len) {
225
2.85k
      case 1:
226
2.85k
         s->block[s->nblock] = (UChar)ch; s->nblock++;
227
2.85k
         break;
228
961k
      case 2:
229
961k
         s->block[s->nblock] = (UChar)ch; s->nblock++;
230
961k
         s->block[s->nblock] = (UChar)ch; s->nblock++;
231
961k
         break;
232
641k
      case 3:
233
641k
         s->block[s->nblock] = (UChar)ch; s->nblock++;
234
641k
         s->block[s->nblock] = (UChar)ch; s->nblock++;
235
641k
         s->block[s->nblock] = (UChar)ch; s->nblock++;
236
641k
         break;
237
1.63M
      default:
238
1.63M
         s->inUse[s->state_in_len-4] = True;
239
1.63M
         s->block[s->nblock] = (UChar)ch; s->nblock++;
240
1.63M
         s->block[s->nblock] = (UChar)ch; s->nblock++;
241
1.63M
         s->block[s->nblock] = (UChar)ch; s->nblock++;
242
1.63M
         s->block[s->nblock] = (UChar)ch; s->nblock++;
243
1.63M
         s->block[s->nblock] = ((UChar)(s->state_in_len-4));
244
1.63M
         s->nblock++;
245
1.63M
         break;
246
3.24M
   }
247
3.24M
}
248
249
250
/*---------------------------------------------------*/
251
static
252
void flush_RL ( EState* s )
253
3.59k
{
254
3.59k
   if (s->state_in_ch < 256) add_pair_to_block ( s );
255
3.59k
   init_RL ( s );
256
3.59k
}
257
258
259
/*---------------------------------------------------*/
260
24.5M
#define ADD_CHAR_TO_BLOCK(zs,zchh0)               \
261
24.5M
{                                                 \
262
24.5M
   UInt32 zchh = (UInt32)(zchh0);                 \
263
24.5M
   /*-- fast track the common case --*/           \
264
24.5M
   if (zchh != zs->state_in_ch &&                 \
265
24.5M
       zs->state_in_len == 1) {                   \
266
2.07M
      UChar ch = (UChar)(zs->state_in_ch);        \
267
2.07M
      BZ_UPDATE_CRC( zs->blockCRC, ch );          \
268
2.07M
      zs->inUse[zs->state_in_ch] = True;          \
269
2.07M
      zs->block[zs->nblock] = (UChar)ch;          \
270
2.07M
      zs->nblock++;                               \
271
2.07M
      zs->state_in_ch = zchh;                     \
272
2.07M
   }                                              \
273
24.5M
   else                                           \
274
24.5M
   /*-- general, uncommon cases --*/              \
275
24.5M
   if (zchh != zs->state_in_ch ||                 \
276
22.4M
      zs->state_in_len == 255) {                  \
277
3.24M
      if (zs->state_in_ch < 256)                  \
278
3.24M
         add_pair_to_block ( zs );                \
279
3.24M
      zs->state_in_ch = zchh;                     \
280
3.24M
      zs->state_in_len = 1;                       \
281
19.2M
   } else {                                       \
282
19.2M
      zs->state_in_len++;                         \
283
19.2M
   }                                              \
284
24.5M
}
285
286
287
/*---------------------------------------------------*/
288
static
289
Bool copy_input_until_stop ( EState* s )
290
7.21k
{
291
7.21k
   Bool progress_in = False;
292
293
7.21k
   if (s->mode == BZ_M_RUNNING) {
294
295
      /*-- fast track the common case --*/
296
24.5M
      while (True) {
297
         /*-- block full? --*/
298
24.5M
         if (s->nblock >= s->nblockMAX) break;
299
         /*-- no input? --*/
300
24.5M
         if (s->strm->avail_in == 0) break;
301
24.5M
         progress_in = True;
302
24.5M
         ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
303
24.5M
         s->strm->next_in++;
304
24.5M
         s->strm->avail_in--;
305
24.5M
         s->strm->total_in_lo32++;
306
24.5M
         if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
307
24.5M
      }
308
309
3.62k
   } else {
310
311
      /*-- general, uncommon case --*/
312
3.59k
      while (True) {
313
         /*-- block full? --*/
314
3.59k
         if (s->nblock >= s->nblockMAX) break;
315
         /*-- no input? --*/
316
3.59k
         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.59k
   }
328
7.21k
   return progress_in;
329
7.21k
}
330
331
332
/*---------------------------------------------------*/
333
static
334
Bool copy_output_until_stop ( EState* s )
335
3.62k
{
336
3.62k
   Bool progress_out = False;
337
338
623k
   while (True) {
339
340
      /*-- no output space? --*/
341
623k
      if (s->strm->avail_out == 0) break;
342
343
      /*-- block done? --*/
344
623k
      if (s->state_out_pos >= s->numZ) break;
345
346
619k
      progress_out = True;
347
619k
      *(s->strm->next_out) = s->zbits[s->state_out_pos];
348
619k
      s->state_out_pos++;
349
619k
      s->strm->avail_out--;
350
619k
      s->strm->next_out++;
351
619k
      s->strm->total_out_lo32++;
352
619k
      if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
353
619k
   }
354
355
3.62k
   return progress_out;
356
3.62k
}
357
358
359
/*---------------------------------------------------*/
360
static
361
Bool handle_compress ( bz_stream* strm )
362
7.18k
{
363
7.18k
   Bool progress_in  = False;
364
7.18k
   Bool progress_out = False;
365
7.18k
   EState* s = strm->state;
366
   
367
10.8k
   while (True) {
368
369
10.8k
      if (s->state == BZ_S_OUTPUT) {
370
3.62k
         progress_out |= copy_output_until_stop ( s );
371
3.62k
         if (s->state_out_pos < s->numZ) break;
372
3.62k
         if (s->mode == BZ_M_FINISHING && 
373
3.59k
             s->avail_in_expect == 0 &&
374
3.59k
             isempty_RL(s)) break;
375
30
         prepare_new_block ( s );
376
30
         s->state = BZ_S_INPUT;
377
30
         if (s->mode == BZ_M_FLUSHING && 
378
0
             s->avail_in_expect == 0 &&
379
0
             isempty_RL(s)) break;
380
30
      }
381
382
7.21k
      if (s->state == BZ_S_INPUT) {
383
7.21k
         progress_in |= copy_input_until_stop ( s );
384
7.21k
         if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
385
3.59k
            flush_RL ( s );
386
3.59k
            BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
387
3.59k
            s->state = BZ_S_OUTPUT;
388
3.59k
         }
389
3.62k
         else
390
3.62k
         if (s->nblock >= s->nblockMAX) {
391
30
            BZ2_compressBlock ( s, False );
392
30
            s->state = BZ_S_OUTPUT;
393
30
         }
394
3.59k
         else
395
3.59k
         if (s->strm->avail_in == 0) {
396
3.59k
            break;
397
3.59k
         }
398
7.21k
      }
399
400
7.21k
   }
401
402
7.18k
   return progress_in || progress_out;
403
7.18k
}
404
405
406
/*---------------------------------------------------*/
407
int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
408
7.18k
{
409
7.18k
   Bool progress;
410
7.18k
   EState* s;
411
7.18k
   if (strm == NULL) return BZ_PARAM_ERROR;
412
7.18k
   s = strm->state;
413
7.18k
   if (s == NULL) return BZ_PARAM_ERROR;
414
7.18k
   if (s->strm != strm) return BZ_PARAM_ERROR;
415
416
10.7k
   preswitch:
417
10.7k
   switch (s->mode) {
418
419
0
      case BZ_M_IDLE:
420
0
         return BZ_SEQUENCE_ERROR;
421
422
7.18k
      case BZ_M_RUNNING:
423
7.18k
         if (action == BZ_RUN) {
424
3.59k
            progress = handle_compress ( strm );
425
3.59k
            return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
426
3.59k
         } 
427
3.59k
         else
428
3.59k
   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.59k
         else
434
3.59k
         if (action == BZ_FINISH) {
435
3.59k
            s->avail_in_expect = strm->avail_in;
436
3.59k
            s->mode = BZ_M_FINISHING;
437
3.59k
            goto preswitch;
438
3.59k
         }
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
3.59k
      case BZ_M_FINISHING:
453
3.59k
         if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
454
3.59k
         if (s->avail_in_expect != s->strm->avail_in) 
455
0
            return BZ_SEQUENCE_ERROR;
456
3.59k
         progress = handle_compress ( strm );
457
3.59k
         if (!progress) return BZ_SEQUENCE_ERROR;
458
3.59k
         if (s->avail_in_expect > 0 || !isempty_RL(s) ||
459
3.59k
             s->state_out_pos < s->numZ) return BZ_FINISH_OK;
460
3.59k
         s->mode = BZ_M_IDLE;
461
3.59k
         return BZ_STREAM_END;
462
10.7k
   }
463
0
   return BZ_OK; /*--not reached--*/
464
10.7k
}
465
466
467
/*---------------------------------------------------*/
468
int BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm )
469
3.59k
{
470
3.59k
   EState* s;
471
3.59k
   if (strm == NULL) return BZ_PARAM_ERROR;
472
3.59k
   s = strm->state;
473
3.59k
   if (s == NULL) return BZ_PARAM_ERROR;
474
3.59k
   if (s->strm != strm) return BZ_PARAM_ERROR;
475
476
3.59k
   if (s->arr1 != NULL) BZFREE(s->arr1);
477
3.59k
   if (s->arr2 != NULL) BZFREE(s->arr2);
478
3.59k
   if (s->ftab != NULL) BZFREE(s->ftab);
479
3.59k
   BZFREE(strm->state);
480
481
3.59k
   strm->state = NULL;   
482
483
3.59k
   return BZ_OK;
484
3.59k
}
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
1.89k
{
497
1.89k
   DState* s;
498
499
1.89k
   if (!bz_config_ok()) return BZ_CONFIG_ERROR;
500
501
1.89k
   if (strm == NULL) return BZ_PARAM_ERROR;
502
1.89k
   if (small != 0 && small != 1) return BZ_PARAM_ERROR;
503
1.89k
   if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
504
505
1.89k
   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
506
1.89k
   if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
507
508
1.89k
   s = BZALLOC( sizeof(DState) );
509
1.89k
   if (s == NULL) return BZ_MEM_ERROR;
510
1.89k
   s->strm                  = strm;
511
1.89k
   strm->state              = s;
512
1.89k
   s->state                 = BZ_X_MAGIC_1;
513
1.89k
   s->bsLive                = 0;
514
1.89k
   s->bsBuff                = 0;
515
1.89k
   s->calculatedCombinedCRC = 0;
516
1.89k
   strm->total_in_lo32      = 0;
517
1.89k
   strm->total_in_hi32      = 0;
518
1.89k
   strm->total_out_lo32     = 0;
519
1.89k
   strm->total_out_hi32     = 0;
520
1.89k
   s->smallDecompress       = (Bool)small;
521
1.89k
   s->ll4                   = NULL;
522
1.89k
   s->ll16                  = NULL;
523
1.89k
   s->tt                    = NULL;
524
1.89k
   s->currBlockNo           = 0;
525
1.89k
   s->verbosity             = verbosity;
526
527
1.89k
   return BZ_OK;
528
1.89k
}
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
3.93k
{
538
3.93k
   UChar k1;
539
540
3.93k
   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
3.93k
   } else {
590
591
      /* restore */
592
3.93k
      UInt32        c_calculatedBlockCRC = s->calculatedBlockCRC;
593
3.93k
      UChar         c_state_out_ch       = s->state_out_ch;
594
3.93k
      Int32         c_state_out_len      = s->state_out_len;
595
3.93k
      Int32         c_nblock_used        = s->nblock_used;
596
3.93k
      Int32         c_k0                 = s->k0;
597
3.93k
      UInt32*       c_tt                 = s->tt;
598
3.93k
      UInt32        c_tPos               = s->tPos;
599
3.93k
      char*         cs_next_out          = s->strm->next_out;
600
3.93k
      unsigned int  cs_avail_out         = s->strm->avail_out;
601
3.93k
      Int32         ro_blockSize100k     = s->blockSize100k;
602
      /* end restore */
603
604
3.93k
      UInt32       avail_out_INIT = cs_avail_out;
605
3.93k
      Int32        s_save_nblockPP = s->save_nblock+1;
606
3.93k
      unsigned int total_out_lo32_old;
607
608
292k
      while (True) {
609
610
         /* try to finish existing run */
611
292k
         if (c_state_out_len > 0) {
612
3.94M
            while (True) {
613
3.94M
               if (cs_avail_out == 0) goto return_notr;
614
3.94M
               if (c_state_out_len == 1) break;
615
3.65M
               *( (UChar*)(cs_next_out) ) = c_state_out_ch;
616
3.65M
               BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
617
3.65M
               c_state_out_len--;
618
3.65M
               cs_next_out++;
619
3.65M
               cs_avail_out--;
620
3.65M
            }
621
495k
            s_state_out_len_eq_one:
622
495k
            {
623
495k
               if (cs_avail_out == 0) { 
624
310
                  c_state_out_len = 1; goto return_notr;
625
495k
               };
626
495k
               *( (UChar*)(cs_next_out) ) = c_state_out_ch;
627
495k
               BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
628
495k
               cs_next_out++;
629
495k
               cs_avail_out--;
630
495k
            }
631
495k
         }   
632
         /* Only caused by corrupt data stream? */
633
496k
         if (c_nblock_used > s_save_nblockPP)
634
0
            return True;
635
636
         /* can a new run be started? */
637
496k
         if (c_nblock_used == s_save_nblockPP) {
638
1.32k
            c_state_out_len = 0; goto return_notr;
639
495k
         };   
640
495k
         c_state_out_ch = c_k0;
641
495k
         BZ_GET_FAST_C(k1); c_nblock_used++;
642
495k
         if (k1 != c_k0) { 
643
206k
            c_k0 = k1; goto s_state_out_len_eq_one; 
644
288k
         };
645
288k
         if (c_nblock_used == s_save_nblockPP) 
646
94
            goto s_state_out_len_eq_one;
647
   
648
288k
         c_state_out_len = 2;
649
288k
         BZ_GET_FAST_C(k1); c_nblock_used++;
650
288k
         if (c_nblock_used == s_save_nblockPP) continue;
651
288k
         if (k1 != c_k0) { c_k0 = k1; continue; };
652
   
653
239k
         c_state_out_len = 3;
654
239k
         BZ_GET_FAST_C(k1); c_nblock_used++;
655
239k
         if (c_nblock_used == s_save_nblockPP) continue;
656
238k
         if (k1 != c_k0) { c_k0 = k1; continue; };
657
   
658
149k
         BZ_GET_FAST_C(k1); c_nblock_used++;
659
149k
         c_state_out_len = ((Int32)k1) + 4;
660
149k
         BZ_GET_FAST_C(c_k0); c_nblock_used++;
661
149k
      }
662
663
3.93k
      return_notr:
664
3.93k
      total_out_lo32_old = s->strm->total_out_lo32;
665
3.93k
      s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
666
3.93k
      if (s->strm->total_out_lo32 < total_out_lo32_old)
667
0
         s->strm->total_out_hi32++;
668
669
      /* save */
670
3.93k
      s->calculatedBlockCRC = c_calculatedBlockCRC;
671
3.93k
      s->state_out_ch       = c_state_out_ch;
672
3.93k
      s->state_out_len      = c_state_out_len;
673
3.93k
      s->nblock_used        = c_nblock_used;
674
3.93k
      s->k0                 = c_k0;
675
3.93k
      s->tt                 = c_tt;
676
3.93k
      s->tPos               = c_tPos;
677
3.93k
      s->strm->next_out     = cs_next_out;
678
3.93k
      s->strm->avail_out    = cs_avail_out;
679
      /* end save */
680
3.93k
   }
681
3.93k
   return False;
682
3.93k
}
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
4.60k
{
810
4.60k
   Bool    corrupt;
811
4.60k
   DState* s;
812
4.60k
   if (strm == NULL) return BZ_PARAM_ERROR;
813
4.60k
   s = strm->state;
814
4.60k
   if (s == NULL) return BZ_PARAM_ERROR;
815
4.60k
   if (s->strm != strm) return BZ_PARAM_ERROR;
816
817
5.93k
   while (True) {
818
5.93k
      if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
819
5.93k
      if (s->state == BZ_X_OUTPUT) {
820
3.93k
         if (s->smallDecompress)
821
0
            corrupt = unRLE_obuf_to_output_SMALL ( s ); else
822
3.93k
            corrupt = unRLE_obuf_to_output_FAST  ( s );
823
3.93k
         if (corrupt) return BZ_DATA_ERROR;
824
3.93k
         if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
825
1.32k
            BZ_FINALISE_CRC ( s->calculatedBlockCRC );
826
1.32k
            if (s->verbosity >= 3) 
827
0
               VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, 
828
1.32k
                          s->calculatedBlockCRC );
829
1.32k
            if (s->verbosity >= 2) VPrintf0 ( "]" );
830
1.32k
            if (s->calculatedBlockCRC != s->storedBlockCRC)
831
287
               return BZ_DATA_ERROR;
832
1.04k
            s->calculatedCombinedCRC 
833
1.04k
               = (s->calculatedCombinedCRC << 1) | 
834
1.04k
                    (s->calculatedCombinedCRC >> 31);
835
1.04k
            s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
836
1.04k
            s->state = BZ_X_BLKHDR_1;
837
2.60k
         } else {
838
2.60k
            return BZ_OK;
839
2.60k
         }
840
3.93k
      }
841
3.04k
      if (s->state >= BZ_X_MAGIC_1) {
842
3.04k
         Int32 r = BZ2_decompress ( s );
843
3.04k
         if (r == BZ_STREAM_END) {
844
1.03k
            if (s->verbosity >= 3)
845
0
               VPrintf2 ( "\n    combined CRCs: stored = 0x%08x, computed = 0x%08x", 
846
1.03k
                          s->storedCombinedCRC, s->calculatedCombinedCRC );
847
1.03k
            if (s->calculatedCombinedCRC != s->storedCombinedCRC)
848
0
               return BZ_DATA_ERROR;
849
1.03k
            return r;
850
1.03k
         }
851
2.00k
         if (s->state != BZ_X_OUTPUT) return r;
852
2.00k
      }
853
3.04k
   }
854
855
0
   AssertH ( 0, 6001 );
856
857
0
   return 0;  /*NOTREACHED*/
858
4.60k
}
859
860
861
/*---------------------------------------------------*/
862
int BZ_API(BZ2_bzDecompressEnd)  ( bz_stream *strm )
863
1.89k
{
864
1.89k
   DState* s;
865
1.89k
   if (strm == NULL) return BZ_PARAM_ERROR;
866
1.89k
   s = strm->state;
867
1.89k
   if (s == NULL) return BZ_PARAM_ERROR;
868
1.89k
   if (s->strm != strm) return BZ_PARAM_ERROR;
869
870
1.89k
   if (s->tt   != NULL) BZFREE(s->tt);
871
1.89k
   if (s->ll16 != NULL) BZFREE(s->ll16);
872
1.89k
   if (s->ll4  != NULL) BZFREE(s->ll4);
873
874
1.89k
   BZFREE(strm->state);
875
1.89k
   strm->state = NULL;
876
877
1.89k
   return BZ_OK;
878
1.89k
}
879
880
881
#ifndef BZ_NO_STDIO
882
/*---------------------------------------------------*/
883
/*--- File I/O stuff                              ---*/
884
/*---------------------------------------------------*/
885
886
#define BZ_SETERR(eee)                    \
887
{                                         \
888
   if (bzerror != NULL) *bzerror = eee;   \
889
   if (bzf != NULL) bzf->lastErr = eee;   \
890
}
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
{
908
   Int32 c = fgetc ( f );
909
   if (c == EOF) return True;
910
   ungetc ( c, f );
911
   return False;
912
}
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
{
923
   Int32   ret;
924
   bzFile* bzf = NULL;
925
926
   BZ_SETERR(BZ_OK);
927
928
   if (f == NULL ||
929
       (blockSize100k < 1 || blockSize100k > 9) ||
930
       (workFactor < 0 || workFactor > 250) ||
931
       (verbosity < 0 || verbosity > 4))
932
      { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
933
934
   if (ferror(f))
935
      { BZ_SETERR(BZ_IO_ERROR); return NULL; };
936
937
   bzf = malloc ( sizeof(bzFile) );
938
   if (bzf == NULL)
939
      { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
940
941
   BZ_SETERR(BZ_OK);
942
   bzf->initialisedOk = False;
943
   bzf->bufN          = 0;
944
   bzf->handle        = f;
945
   bzf->writing       = True;
946
   bzf->strm.bzalloc  = NULL;
947
   bzf->strm.bzfree   = NULL;
948
   bzf->strm.opaque   = NULL;
949
950
   if (workFactor == 0) workFactor = 30;
951
   ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, 
952
                              verbosity, workFactor );
953
   if (ret != BZ_OK)
954
      { BZ_SETERR(ret); free(bzf); return NULL; };
955
956
   bzf->strm.avail_in = 0;
957
   bzf->initialisedOk = True;
958
   return bzf;   
959
}
960
961
962
963
/*---------------------------------------------------*/
964
void BZ_API(BZ2_bzWrite)
965
             ( int*    bzerror, 
966
               BZFILE* b, 
967
               void*   buf, 
968
               int     len )
969
{
970
   Int32 n, n2, ret;
971
   bzFile* bzf = (bzFile*)b;
972
973
   BZ_SETERR(BZ_OK);
974
   if (bzf == NULL || buf == NULL || len < 0)
975
      { BZ_SETERR(BZ_PARAM_ERROR); return; };
976
   if (!(bzf->writing))
977
      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
978
   if (ferror(bzf->handle))
979
      { BZ_SETERR(BZ_IO_ERROR); return; };
980
981
   if (len == 0)
982
      { BZ_SETERR(BZ_OK); return; };
983
984
   bzf->strm.avail_in = len;
985
   bzf->strm.next_in  = buf;
986
987
   while (True) {
988
      bzf->strm.avail_out = BZ_MAX_UNUSED;
989
      bzf->strm.next_out = bzf->buf;
990
      ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
991
      if (ret != BZ_RUN_OK)
992
         { BZ_SETERR(ret); return; };
993
994
      if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
995
         n = BZ_MAX_UNUSED - bzf->strm.avail_out;
996
         n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
997
                       n, bzf->handle );
998
         if (n != n2 || ferror(bzf->handle))
999
            { BZ_SETERR(BZ_IO_ERROR); return; };
1000
      }
1001
1002
      if (bzf->strm.avail_in == 0)
1003
         { BZ_SETERR(BZ_OK); return; };
1004
   }
1005
}
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
{
1016
   BZ2_bzWriteClose64 ( bzerror, b, abandon, 
1017
                        nbytes_in, NULL, nbytes_out, NULL );
1018
}
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
{
1030
   Int32   n, n2, ret;
1031
   bzFile* bzf = (bzFile*)b;
1032
1033
   if (bzf == NULL)
1034
      { BZ_SETERR(BZ_OK); return; };
1035
   if (!(bzf->writing))
1036
      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1037
   if (ferror(bzf->handle))
1038
      { BZ_SETERR(BZ_IO_ERROR); return; };
1039
1040
   if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1041
   if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1042
   if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1043
   if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1044
1045
   if ((!abandon) && bzf->lastErr == BZ_OK) {
1046
      while (True) {
1047
         bzf->strm.avail_out = BZ_MAX_UNUSED;
1048
         bzf->strm.next_out = bzf->buf;
1049
         ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1050
         if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1051
            { BZ_SETERR(ret); return; };
1052
1053
         if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1054
            n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1055
            n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
1056
                          n, bzf->handle );
1057
            if (n != n2 || ferror(bzf->handle))
1058
               { BZ_SETERR(BZ_IO_ERROR); return; };
1059
         }
1060
1061
         if (ret == BZ_STREAM_END) break;
1062
      }
1063
   }
1064
1065
   if ( !abandon && !ferror ( bzf->handle ) ) {
1066
      fflush ( bzf->handle );
1067
      if (ferror(bzf->handle))
1068
         { BZ_SETERR(BZ_IO_ERROR); return; };
1069
   }
1070
1071
   if (nbytes_in_lo32 != NULL)
1072
      *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1073
   if (nbytes_in_hi32 != NULL)
1074
      *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1075
   if (nbytes_out_lo32 != NULL)
1076
      *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1077
   if (nbytes_out_hi32 != NULL)
1078
      *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1079
1080
   BZ_SETERR(BZ_OK);
1081
   BZ2_bzCompressEnd ( &(bzf->strm) );
1082
   free ( bzf );
1083
}
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
{
1095
   bzFile* bzf = NULL;
1096
   int     ret;
1097
1098
   BZ_SETERR(BZ_OK);
1099
1100
   if (f == NULL || 
1101
       (small != 0 && small != 1) ||
1102
       (verbosity < 0 || verbosity > 4) ||
1103
       (unused == NULL && nUnused != 0) ||
1104
       (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1105
      { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1106
1107
   if (ferror(f))
1108
      { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1109
1110
   bzf = malloc ( sizeof(bzFile) );
1111
   if (bzf == NULL) 
1112
      { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1113
1114
   BZ_SETERR(BZ_OK);
1115
1116
   bzf->initialisedOk = False;
1117
   bzf->handle        = f;
1118
   bzf->bufN          = 0;
1119
   bzf->writing       = False;
1120
   bzf->strm.bzalloc  = NULL;
1121
   bzf->strm.bzfree   = NULL;
1122
   bzf->strm.opaque   = NULL;
1123
   
1124
   while (nUnused > 0) {
1125
      bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1126
      unused = ((void*)( 1 + ((UChar*)(unused))  ));
1127
      nUnused--;
1128
   }
1129
1130
   ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1131
   if (ret != BZ_OK)
1132
      { BZ_SETERR(ret); free(bzf); return NULL; };
1133
1134
   bzf->strm.avail_in = bzf->bufN;
1135
   bzf->strm.next_in  = bzf->buf;
1136
1137
   bzf->initialisedOk = True;
1138
   return bzf;   
1139
}
1140
1141
1142
/*---------------------------------------------------*/
1143
void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1144
{
1145
   bzFile* bzf = (bzFile*)b;
1146
1147
   BZ_SETERR(BZ_OK);
1148
   if (bzf == NULL)
1149
      { BZ_SETERR(BZ_OK); return; };
1150
1151
   if (bzf->writing)
1152
      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1153
1154
   if (bzf->initialisedOk)
1155
      (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1156
   free ( bzf );
1157
}
1158
1159
1160
/*---------------------------------------------------*/
1161
int BZ_API(BZ2_bzRead) 
1162
           ( int*    bzerror, 
1163
             BZFILE* b, 
1164
             void*   buf, 
1165
             int     len )
1166
{
1167
   Int32   n, ret;
1168
   bzFile* bzf = (bzFile*)b;
1169
1170
   BZ_SETERR(BZ_OK);
1171
1172
   if (bzf == NULL || buf == NULL || len < 0)
1173
      { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1174
1175
   if (bzf->writing)
1176
      { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1177
1178
   if (len == 0)
1179
      { BZ_SETERR(BZ_OK); return 0; };
1180
1181
   bzf->strm.avail_out = len;
1182
   bzf->strm.next_out = buf;
1183
1184
   while (True) {
1185
1186
      if (ferror(bzf->handle)) 
1187
         { BZ_SETERR(BZ_IO_ERROR); return 0; };
1188
1189
      if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1190
         n = fread ( bzf->buf, sizeof(UChar), 
1191
                     BZ_MAX_UNUSED, bzf->handle );
1192
         if (ferror(bzf->handle))
1193
            { BZ_SETERR(BZ_IO_ERROR); return 0; };
1194
         bzf->bufN = n;
1195
         bzf->strm.avail_in = bzf->bufN;
1196
         bzf->strm.next_in = bzf->buf;
1197
      }
1198
1199
      ret = BZ2_bzDecompress ( &(bzf->strm) );
1200
1201
      if (ret != BZ_OK && ret != BZ_STREAM_END)
1202
         { BZ_SETERR(ret); return 0; };
1203
1204
      if (ret == BZ_OK && myfeof(bzf->handle) && 
1205
          bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1206
         { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1207
1208
      if (ret == BZ_STREAM_END)
1209
         { BZ_SETERR(BZ_STREAM_END);
1210
           return len - bzf->strm.avail_out; };
1211
      if (bzf->strm.avail_out == 0)
1212
         { BZ_SETERR(BZ_OK); return len; };
1213
      
1214
   }
1215
1216
   return 0; /*not reached*/
1217
}
1218
1219
1220
/*---------------------------------------------------*/
1221
void BZ_API(BZ2_bzReadGetUnused) 
1222
                     ( int*    bzerror, 
1223
                       BZFILE* b, 
1224
                       void**  unused, 
1225
                       int*    nUnused )
1226
{
1227
   bzFile* bzf = (bzFile*)b;
1228
   if (bzf == NULL)
1229
      { BZ_SETERR(BZ_PARAM_ERROR); return; };
1230
   if (bzf->lastErr != BZ_STREAM_END)
1231
      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1232
   if (unused == NULL || nUnused == NULL)
1233
      { BZ_SETERR(BZ_PARAM_ERROR); return; };
1234
1235
   BZ_SETERR(BZ_OK);
1236
   *nUnused = bzf->strm.avail_in;
1237
   *unused = bzf->strm.next_in;
1238
}
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
0
{
1368
0
   return BZ_VERSION;
1369
0
}
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
{
1389
   int    bzerr;
1390
   char   unused[BZ_MAX_UNUSED];
1391
   int    blockSize100k = 9;
1392
   int    writing       = 0;
1393
   char   mode2[10]     = "";
1394
   FILE   *fp           = NULL;
1395
   BZFILE *bzfp         = NULL;
1396
   int    verbosity     = 0;
1397
   int    workFactor    = 30;
1398
   int    smallMode     = 0;
1399
   int    nUnused       = 0; 
1400
1401
   if (mode == NULL) return NULL;
1402
   while (*mode) {
1403
      switch (*mode) {
1404
      case 'r':
1405
         writing = 0; break;
1406
      case 'w':
1407
         writing = 1; break;
1408
      case 's':
1409
         smallMode = 1; break;
1410
      default:
1411
         if (isdigit((int)(*mode))) {
1412
            blockSize100k = *mode-BZ_HDR_0;
1413
         }
1414
      }
1415
      mode++;
1416
   }
1417
   strcat(mode2, writing ? "w" : "r" );
1418
   strcat(mode2,"b");   /* binary mode */
1419
1420
   if (open_mode==0) {
1421
      if (path==NULL || strcmp(path,"")==0) {
1422
        fp = (writing ? stdout : stdin);
1423
        SET_BINARY_MODE(fp);
1424
      } else {
1425
        fp = fopen(path,mode2);
1426
      }
1427
   } else {
1428
#ifdef BZ_STRICT_ANSI
1429
      fp = NULL;
1430
#else
1431
      fp = fdopen(fd,mode2);
1432
#endif
1433
   }
1434
   if (fp == NULL) return NULL;
1435
1436
   if (writing) {
1437
      /* Guard against total chaos and anarchy -- JRS */
1438
      if (blockSize100k < 1) blockSize100k = 1;
1439
      if (blockSize100k > 9) blockSize100k = 9; 
1440
      bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1441
                             verbosity,workFactor);
1442
   } else {
1443
      bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1444
                            unused,nUnused);
1445
   }
1446
   if (bzfp == NULL) {
1447
      if (fp != stdin && fp != stdout) fclose(fp);
1448
      return NULL;
1449
   }
1450
   return bzfp;
1451
}
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
{
1464
   return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1465
}
1466
1467
1468
/*---------------------------------------------------*/
1469
BZFILE * BZ_API(BZ2_bzdopen)
1470
               ( int fd,
1471
                 const char *mode )
1472
{
1473
   return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1474
}
1475
1476
1477
/*---------------------------------------------------*/
1478
int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1479
{
1480
   int bzerr, nread;
1481
   if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1482
   nread = BZ2_bzRead(&bzerr,b,buf,len);
1483
   if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1484
      return nread;
1485
   } else {
1486
      return -1;
1487
   }
1488
}
1489
1490
1491
/*---------------------------------------------------*/
1492
int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1493
{
1494
   int bzerr;
1495
1496
   BZ2_bzWrite(&bzerr,b,buf,len);
1497
   if(bzerr == BZ_OK){
1498
      return len;
1499
   }else{
1500
      return -1;
1501
   }
1502
}
1503
1504
1505
/*---------------------------------------------------*/
1506
int BZ_API(BZ2_bzflush) (BZFILE *b)
1507
{
1508
   /* do nothing now... */
1509
   return 0;
1510
}
1511
1512
1513
/*---------------------------------------------------*/
1514
void BZ_API(BZ2_bzclose) (BZFILE* b)
1515
{
1516
   int bzerr;
1517
   FILE *fp;
1518
   
1519
   if (b==NULL) {return;}
1520
   fp = ((bzFile *)b)->handle;
1521
   if(((bzFile*)b)->writing){
1522
      BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1523
      if(bzerr != BZ_OK){
1524
         BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1525
      }
1526
   }else{
1527
      BZ2_bzReadClose(&bzerr,b);
1528
   }
1529
   if(fp!=stdin && fp!=stdout){
1530
      fclose(fp);
1531
   }
1532
}
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
{
1561
   int err = ((bzFile *)b)->lastErr;
1562
1563
   if(err>0) err = 0;
1564
   *errnum = err;
1565
   return bzerrorstrings[err*-1];
1566
}
1567
#endif
1568
1569
1570
/*-------------------------------------------------------------*/
1571
/*--- end                                           bzlib.c ---*/
1572
/*-------------------------------------------------------------*/