blob: 356895b3293435ad7705c95ee14a24c0bf8e03d2 [file] [log] [blame]
Glenn L McGrath24e28332001-10-05 03:48:57 +00001/* Modified for busybox by Glenn McGrath <bug1@optushome.com.au> */
Glenn L McGrathfff11f12001-11-18 14:20:25 +00002/* Added support output to stdout by Thomas Lundquist <thomasez@zelow.no> */
Glenn L McGrath24e28332001-10-05 03:48:57 +00003/*--
4 This file is a part of bzip2 and/or libbzip2, a program and
5 library for lossless, block-sorting data compression.
6
7 Copyright (C) 1996-2000 Julian R Seward. All rights reserved.
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12
13 1. Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16 2. The origin of this software must not be misrepresented; you must
17 not claim that you wrote the original software. If you use this
18 software in a product, an acknowledgment in the product
19 documentation would be appreciated but is not required.
20
21 3. Altered source versions must be plainly marked as such, and must
22 not be misrepresented as being the original software.
23
24 4. The name of the author may not be used to endorse or promote
25 products derived from this software without specific prior written
26 permission.
27
28 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
29 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
32 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
34 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
37 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
38 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
40 Julian Seward, Cambridge, UK.
41 jseward@acm.org
42 bzip2/libbzip2 version 1.0 of 21 March 2000
43
44 This program is based on (at least) the work of:
45 Mike Burrows
46 David Wheeler
47 Peter Fenwick
48 Alistair Moffat
49 Radford Neal
50 Ian H. Witten
51 Robert Sedgewick
52 Jon L. Bentley
53
54 For more information on these sources, see the manual.
55--*/
56
57#include <stdlib.h>
58#include <stdio.h>
59#include <string.h>
Glenn L McGrathfff11f12001-11-18 14:20:25 +000060#include <getopt.h>
Matt Kraai9cdb0602002-03-27 17:31:01 +000061#include <unistd.h>
Glenn L McGrath24e28332001-10-05 03:48:57 +000062#include <busybox.h>
63
64//#define TRUE 1
65//#define FALSE 0
66
67#define MTFA_SIZE 4096
68#define MTFL_SIZE 16
69#define BZ_N_GROUPS 6
70#define BZ_G_SIZE 50
71#define BZ_MAX_ALPHA_SIZE 258
72
73#define BZ_OK 0
Glenn L McGrath24e28332001-10-05 03:48:57 +000074#define BZ_STREAM_END 4
75#define BZ_SEQUENCE_ERROR (-1)
Glenn L McGrath24e28332001-10-05 03:48:57 +000076#define BZ_DATA_ERROR (-4)
77#define BZ_DATA_ERROR_MAGIC (-5)
78#define BZ_IO_ERROR (-6)
79#define BZ_UNEXPECTED_EOF (-7)
Glenn L McGrath24e28332001-10-05 03:48:57 +000080
81#define BZ_RUNA 0
82#define BZ_RUNB 1
83
84#define BZ_MAX_UNUSED 5000
85#define FILE_NAME_LEN 1034
86/*-- states for decompression. --*/
87
88#define BZ_X_IDLE 1
89#define BZ_X_OUTPUT 2
90
91#define BZ_X_MAGIC_1 10
92#define BZ_X_MAGIC_2 11
93#define BZ_X_MAGIC_3 12
94#define BZ_X_MAGIC_4 13
95#define BZ_X_BLKHDR_1 14
96#define BZ_X_BLKHDR_2 15
97#define BZ_X_BLKHDR_3 16
98#define BZ_X_BLKHDR_4 17
99#define BZ_X_BLKHDR_5 18
100#define BZ_X_BLKHDR_6 19
101#define BZ_X_BCRC_1 20
102#define BZ_X_BCRC_2 21
103#define BZ_X_BCRC_3 22
104#define BZ_X_BCRC_4 23
105#define BZ_X_RANDBIT 24
106#define BZ_X_ORIGPTR_1 25
107#define BZ_X_ORIGPTR_2 26
108#define BZ_X_ORIGPTR_3 27
109#define BZ_X_MAPPING_1 28
110#define BZ_X_MAPPING_2 29
111#define BZ_X_SELECTOR_1 30
112#define BZ_X_SELECTOR_2 31
113#define BZ_X_SELECTOR_3 32
114#define BZ_X_CODING_1 33
115#define BZ_X_CODING_2 34
116#define BZ_X_CODING_3 35
117#define BZ_X_MTF_1 36
118#define BZ_X_MTF_2 37
119#define BZ_X_MTF_3 38
120#define BZ_X_MTF_4 39
121#define BZ_X_MTF_5 40
122#define BZ_X_MTF_6 41
123#define BZ_X_ENDHDR_2 42
124#define BZ_X_ENDHDR_3 43
125#define BZ_X_ENDHDR_4 44
126#define BZ_X_ENDHDR_5 45
127#define BZ_X_ENDHDR_6 46
128#define BZ_X_CCRC_1 47
129#define BZ_X_CCRC_2 48
130#define BZ_X_CCRC_3 49
131#define BZ_X_CCRC_4 50
132
133#define BZ_MAX_CODE_LEN 23
Glenn L McGrath24e28332001-10-05 03:48:57 +0000134#define OM_TEST 3
Glenn L McGrath24e28332001-10-05 03:48:57 +0000135
136typedef struct {
137 char *next_in;
138 unsigned int avail_in;
Glenn L McGrath24e28332001-10-05 03:48:57 +0000139
140 char *next_out;
141 unsigned int avail_out;
Glenn L McGrath24e28332001-10-05 03:48:57 +0000142
143 void *state;
144
Glenn L McGrath24e28332001-10-05 03:48:57 +0000145} bz_stream;
146
147typedef struct {
148 bz_stream strm;
149 FILE *handle;
150 unsigned char initialisedOk;
Glenn L McGrath24e28332001-10-05 03:48:57 +0000151 char buf[BZ_MAX_UNUSED];
152 int lastErr;
153 int bufN;
154} bzFile;
155
156/*-- Structure holding all the decompression-side stuff. --*/
157typedef struct {
158 /* pointer back to the struct bz_stream */
159 bz_stream* strm;
160
161 /* state indicator for this stream */
162 int state;
163
164 /* for doing the final run-length decoding */
165 unsigned char state_out_ch;
166 int state_out_len;
167 unsigned char blockRandomised;
168 int rNToGo;
169 int rTPos;
170
171 /* the buffer for bit stream reading */
172 unsigned int bsBuff;
173 int bsLive;
174
175 /* misc administratium */
176 int blockSize100k;
Glenn L McGrath24e28332001-10-05 03:48:57 +0000177 int currBlockNo;
Glenn L McGrath24e28332001-10-05 03:48:57 +0000178
179 /* for undoing the Burrows-Wheeler transform */
180 int origPtr;
181 unsigned int tPos;
182 int k0;
183 int unzftab[256];
184 int nblock_used;
185 int cftab[257];
186 int cftabCopy[257];
187
188 /* for undoing the Burrows-Wheeler transform (FAST) */
189 unsigned int *tt;
190
Glenn L McGrath24e28332001-10-05 03:48:57 +0000191 /* stored and calculated CRCs */
192 unsigned int storedBlockCRC;
193 unsigned int storedCombinedCRC;
194 unsigned int calculatedBlockCRC;
195 unsigned int calculatedCombinedCRC;
196
197 /* map of bytes used in block */
198 int nInUse;
199 unsigned char inUse[256];
200 unsigned char inUse16[16];
201 unsigned char seqToUnseq[256];
202
203 /* for decoding the MTF values */
204 unsigned char mtfa [MTFA_SIZE];
205 unsigned char selector [2 + (900000 / BZ_G_SIZE)];
206 unsigned char selectorMtf[2 + (900000 / BZ_G_SIZE)];
207 unsigned char len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
208 int mtfbase[256 / MTFL_SIZE];
209
210 int limit [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
211 int base [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
212 int perm [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
213 int minLens[BZ_N_GROUPS];
214
215 /* save area for scalars in the main decompress code */
216 int save_i;
217 int save_j;
218 int save_t;
219 int save_alphaSize;
220 int save_nGroups;
221 int save_nSelectors;
222 int save_EOB;
223 int save_groupNo;
224 int save_groupPos;
225 int save_nextSym;
226 int save_nblockMAX;
227 int save_nblock;
228 int save_es;
229 int save_N;
230 int save_curr;
231 int save_zt;
232 int save_zn;
233 int save_zvec;
234 int save_zj;
235 int save_gSel;
236 int save_gMinlen;
237 int *save_gLimit;
238 int *save_gBase;
239 int *save_gPerm;
240} DState;
241
242int BZ2_rNums[512];
Glenn L McGrath24e28332001-10-05 03:48:57 +0000243char inName[FILE_NAME_LEN];
244char outName[FILE_NAME_LEN];
245int srcMode;
246int opMode;
247unsigned char deleteOutputOnInterrupt;
248FILE *outputHandleJustInCase;
249int numFileNames;
250int numFilesProcessed;
251int exitValue;
252
Aaron Lehmannb9df4702001-12-06 03:22:43 +0000253const unsigned int BZ2_crc32Table[256] = {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000254
255 /*-- Ugly, innit? --*/
256
257 0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L,
258 0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L,
259 0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L,
260 0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL,
261 0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L,
262 0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L,
263 0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L,
264 0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL,
265 0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L,
266 0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L,
267 0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L,
268 0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL,
269 0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L,
270 0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L,
271 0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L,
272 0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL,
273 0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL,
274 0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L,
275 0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L,
276 0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL,
277 0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL,
278 0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L,
279 0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L,
280 0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL,
281 0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL,
282 0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L,
283 0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L,
284 0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL,
285 0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL,
286 0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L,
287 0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L,
288 0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL,
289 0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L,
290 0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL,
291 0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL,
292 0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L,
293 0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L,
294 0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL,
295 0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL,
296 0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L,
297 0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L,
298 0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL,
299 0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL,
300 0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L,
301 0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L,
302 0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL,
303 0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL,
304 0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L,
305 0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L,
306 0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL,
307 0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L,
308 0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L,
309 0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L,
310 0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL,
311 0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L,
312 0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L,
313 0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L,
314 0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL,
315 0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L,
316 0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L,
317 0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L,
318 0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL,
319 0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L,
320 0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L
321};
322
Aaron Lehmann90314812002-06-23 22:13:22 +0000323static void bz_rand_udp_mask(DState *s)
Glenn L McGrath24e28332001-10-05 03:48:57 +0000324{
325 if (s->rNToGo == 0) {
326 s->rNToGo = BZ2_rNums[s->rTPos];
327 s->rTPos++;
328 if (s->rTPos == 512) {
329 s->rTPos = 0;
330 }
331 }
332 s->rNToGo--;
333}
334
335static unsigned char myfeof(FILE *f)
336{
337 int c = fgetc(f);
338 if (c == EOF) {
339 return(TRUE);
340 }
341 ungetc(c, f);
342 return(FALSE);
343}
344
Aaron Lehmann90314812002-06-23 22:13:22 +0000345static void BZ2_hbCreateDecodeTables(int *limit, int *base, int *perm, unsigned char *length, int minLen, int maxLen, int alphaSize )
Glenn L McGrath24e28332001-10-05 03:48:57 +0000346{
347 int pp, i, j, vec;
348
349 pp = 0;
350 for (i = minLen; i <= maxLen; i++) {
351 for (j = 0; j < alphaSize; j++) {
352 if (length[j] == i) {
353 perm[pp] = j;
354 pp++;
355 }
356 }
357 }
358
359 for (i = 0; i < BZ_MAX_CODE_LEN; i++) {
360 base[i] = 0;
361 }
362
363 for (i = 0; i < alphaSize; i++) {
364 base[length[i]+1]++;
365 }
366
367 for (i = 1; i < BZ_MAX_CODE_LEN; i++) {
368 base[i] += base[i-1];
369 }
370
371 for (i = 0; i < BZ_MAX_CODE_LEN; i++) {
372 limit[i] = 0;
373 }
374 vec = 0;
375
376 for (i = minLen; i <= maxLen; i++) {
377 vec += (base[i+1] - base[i]);
378 limit[i] = vec-1;
379 vec <<= 1;
380 }
381 for (i = minLen + 1; i <= maxLen; i++) {
382 base[i] = ((limit[i-1] + 1) << 1) - base[i];
383 }
384}
385
Glenn L McGrath24e28332001-10-05 03:48:57 +0000386
387static int get_bits(DState *s, int *vvv, char nnn)
388{
389 while (1) {
390 if (s->bsLive >= nnn) {
391 *vvv = (s->bsBuff >> (s->bsLive-nnn)) & ((1 << nnn)-1);
392 s->bsLive -= nnn;
393 break;
394 }
395 if (s->strm->avail_in == 0) {
396 return(FALSE);
397 }
398 s->bsBuff = (s->bsBuff << 8) | ((unsigned int) (*((unsigned char*)(s->strm->next_in))));
399 s->bsLive += 8;
400 s->strm->next_in++;
401 s->strm->avail_in--;
Glenn L McGrath24e28332001-10-05 03:48:57 +0000402 }
403 return(TRUE);
404}
405
Aaron Lehmann90314812002-06-23 22:13:22 +0000406static int bz_get_fast(DState *s)
Glenn L McGrath24e28332001-10-05 03:48:57 +0000407{
408 int cccc;
409 s->tPos = s->tt[s->tPos];
410 cccc = (unsigned char)(s->tPos & 0xff);
411 s->tPos >>= 8;
412 return(cccc);
413}
414
415/*---------------------------------------------------*/
Aaron Lehmann90314812002-06-23 22:13:22 +0000416static inline int BZ2_decompress(DState *s)
Glenn L McGrath24e28332001-10-05 03:48:57 +0000417{
418 int uc = 0;
419 int retVal;
420 int minLen, maxLen;
Glenn L McGrath24e28332001-10-05 03:48:57 +0000421
422 /* stuff that needs to be saved/restored */
423 int i;
424 int j;
425 int t;
426 int alphaSize;
427 int nGroups;
428 int nSelectors;
429 int EOB;
430 int groupNo;
431 int groupPos;
432 int nextSym;
433 int nblockMAX;
434 int nblock;
435 int es;
436 int N;
437 int curr;
438 int zt;
439 int zn;
440 int zvec;
441 int zj;
442 int gSel;
443 int gMinlen;
444 int *gLimit;
445 int *gBase;
446 int *gPerm;
447 int switch_val;
448
449 int get_mtf_val_init(void)
450 {
451 if (groupPos == 0) {
452 groupNo++;
453 if (groupNo >= nSelectors) {
454 retVal = BZ_DATA_ERROR;
455 return(FALSE);
456 }
457 groupPos = BZ_G_SIZE;
458 gSel = s->selector[groupNo];
459 gMinlen = s->minLens[gSel];
460 gLimit = &(s->limit[gSel][0]);
461 gPerm = &(s->perm[gSel][0]);
462 gBase = &(s->base[gSel][0]);
463 }
464 groupPos--;
465 zn = gMinlen;
466 return(TRUE);
467 }
468
469 if (s->state == BZ_X_MAGIC_1) {
470 /*initialise the save area*/
471 s->save_i = 0;
472 s->save_j = 0;
473 s->save_t = 0;
474 s->save_alphaSize = 0;
475 s->save_nGroups = 0;
476 s->save_nSelectors = 0;
477 s->save_EOB = 0;
478 s->save_groupNo = 0;
479 s->save_groupPos = 0;
480 s->save_nextSym = 0;
481 s->save_nblockMAX = 0;
482 s->save_nblock = 0;
483 s->save_es = 0;
484 s->save_N = 0;
485 s->save_curr = 0;
486 s->save_zt = 0;
487 s->save_zn = 0;
488 s->save_zvec = 0;
489 s->save_zj = 0;
490 s->save_gSel = 0;
491 s->save_gMinlen = 0;
492 s->save_gLimit = NULL;
493 s->save_gBase = NULL;
494 s->save_gPerm = NULL;
495 }
496
497 /*restore from the save area*/
498 i = s->save_i;
499 j = s->save_j;
500 t = s->save_t;
501 alphaSize = s->save_alphaSize;
502 nGroups = s->save_nGroups;
503 nSelectors = s->save_nSelectors;
504 EOB = s->save_EOB;
505 groupNo = s->save_groupNo;
506 groupPos = s->save_groupPos;
507 nextSym = s->save_nextSym;
508 nblockMAX = s->save_nblockMAX;
509 nblock = s->save_nblock;
510 es = s->save_es;
511 N = s->save_N;
512 curr = s->save_curr;
513 zt = s->save_zt;
514 zn = s->save_zn;
515 zvec = s->save_zvec;
516 zj = s->save_zj;
517 gSel = s->save_gSel;
518 gMinlen = s->save_gMinlen;
519 gLimit = s->save_gLimit;
520 gBase = s->save_gBase;
521 gPerm = s->save_gPerm;
522
523 retVal = BZ_OK;
524 switch_val = s->state;
525 switch (switch_val) {
526 case BZ_X_MAGIC_1:
527 s->state = BZ_X_MAGIC_1;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000528 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000529 retVal = BZ_OK;
530 goto save_state_and_return;
531 }
532 if (uc != 'B') {
533 retVal = BZ_DATA_ERROR_MAGIC;
534 goto save_state_and_return;
535 }
536
537 case BZ_X_MAGIC_2:
538 s->state = BZ_X_MAGIC_2;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000539 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000540 retVal = BZ_OK;
541 goto save_state_and_return;
542 }
543 if (uc != 'Z') {
544 retVal = BZ_DATA_ERROR_MAGIC;
545 goto save_state_and_return;
546 }
547
548 case BZ_X_MAGIC_3:
549 s->state = BZ_X_MAGIC_3;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000550 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000551 retVal = BZ_OK;
552 goto save_state_and_return;
553 }
554 if (uc != 'h') {
555 retVal = BZ_DATA_ERROR_MAGIC;
556 goto save_state_and_return;
557 }
558
559 case BZ_X_MAGIC_4:
560 s->state = BZ_X_MAGIC_4;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000561 if (! get_bits(s, &s->blockSize100k, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000562 retVal = BZ_OK;
563 goto save_state_and_return;
564 }
565 if ((s->blockSize100k < '1') || (s->blockSize100k > '9')) {
566 retVal = BZ_DATA_ERROR_MAGIC;
567 goto save_state_and_return;
568 }
569 s->blockSize100k -= '0';
570
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +0000571 s->tt = xmalloc(s->blockSize100k * 100000 * sizeof(int));
Glenn L McGrath24e28332001-10-05 03:48:57 +0000572
573 case BZ_X_BLKHDR_1:
574 s->state = BZ_X_BLKHDR_1;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000575 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000576 retVal = BZ_OK;
577 goto save_state_and_return;
578 }
579
580 if (uc == 0x17) {
581 goto endhdr_2;
582 }
583 if (uc != 0x31) {
584 retVal = BZ_DATA_ERROR;
585 goto save_state_and_return;
586 }
587
588 case BZ_X_BLKHDR_2:
589 s->state = BZ_X_BLKHDR_2;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000590 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000591 retVal = BZ_OK;
592 goto save_state_and_return;
593 }
594 if (uc != 0x41) {
595 retVal = BZ_DATA_ERROR;
596 goto save_state_and_return;
597 }
598
599 case BZ_X_BLKHDR_3:
600 s->state = BZ_X_BLKHDR_3;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000601 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000602 retVal = BZ_OK;
603 goto save_state_and_return;
604 }
605 if (uc != 0x59) {
606 retVal = BZ_DATA_ERROR;
607 goto save_state_and_return;
608 }
609
610 case BZ_X_BLKHDR_4:
611 s->state = BZ_X_BLKHDR_4;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000612 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000613 retVal = BZ_OK;
614 goto save_state_and_return;
615 }
616 if (uc != 0x26) {
617 retVal = BZ_DATA_ERROR;
618 goto save_state_and_return;
619 }
620
621 case BZ_X_BLKHDR_5:
622 s->state = BZ_X_BLKHDR_5;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000623 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000624 retVal = BZ_OK;
625 goto save_state_and_return;
626 }
627 if (uc != 0x53) {
628 retVal = BZ_DATA_ERROR;
629 goto save_state_and_return;
630 }
631
632 case BZ_X_BLKHDR_6:
633 s->state = BZ_X_BLKHDR_6;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000634 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000635 retVal = BZ_OK;
636 goto save_state_and_return;
637 }
638 if (uc != 0x59) {
639 retVal = BZ_DATA_ERROR;
640 goto save_state_and_return;
641 }
642
643 s->currBlockNo++;
Glenn L McGrath24e28332001-10-05 03:48:57 +0000644 s->storedBlockCRC = 0;
645
646 case BZ_X_BCRC_1:
647 s->state = BZ_X_BCRC_1;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000648 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000649 retVal = BZ_OK;
650 goto save_state_and_return;
651 }
652 s->storedBlockCRC = (s->storedBlockCRC << 8) | ((unsigned int)uc);
653
654 case BZ_X_BCRC_2:
655 s->state = BZ_X_BCRC_2;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000656 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000657 retVal = BZ_OK;
658 goto save_state_and_return;
659 }
660 s->storedBlockCRC = (s->storedBlockCRC << 8) | ((unsigned int)uc);
661
662 case BZ_X_BCRC_3:
663 s->state = BZ_X_BCRC_3;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000664 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000665 retVal = BZ_OK;
666 goto save_state_and_return;
667 }
668 s->storedBlockCRC = (s->storedBlockCRC << 8) | ((unsigned int)uc);
669
670 case BZ_X_BCRC_4:
671 s->state = BZ_X_BCRC_4;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000672 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000673 retVal = BZ_OK;
674 goto save_state_and_return;
675 }
676 s->storedBlockCRC = (s->storedBlockCRC << 8) | ((unsigned int)uc);
677
678 case BZ_X_RANDBIT:
679 s->state = BZ_X_RANDBIT;
680 {
681 int tmp = s->blockRandomised;
682 const int ret = get_bits(s, &tmp, 1);
683 s->blockRandomised = tmp;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000684 if (! ret) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000685 retVal = BZ_OK;
686 goto save_state_and_return;
687 }
688 }
689
690 s->origPtr = 0;
691
692 case BZ_X_ORIGPTR_1:
693 s->state = BZ_X_ORIGPTR_1;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000694 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000695 retVal = BZ_OK;
696 goto save_state_and_return;
697 }
698 s->origPtr = (s->origPtr << 8) | ((int)uc);
699
700 case BZ_X_ORIGPTR_2:
701 s->state = BZ_X_ORIGPTR_2;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000702 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000703 retVal = BZ_OK;
704 goto save_state_and_return;
705 }
706 s->origPtr = (s->origPtr << 8) | ((int)uc);
707
708 case BZ_X_ORIGPTR_3:
709 s->state = BZ_X_ORIGPTR_3;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000710 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000711 retVal = BZ_OK;
712 goto save_state_and_return;
713 }
714 s->origPtr = (s->origPtr << 8) | ((int)uc);
715
716 if (s->origPtr < 0) {
717 retVal = BZ_DATA_ERROR;
718 goto save_state_and_return;
719 }
720 if (s->origPtr > 10 + 100000*s->blockSize100k) {
721 retVal = BZ_DATA_ERROR;
722 goto save_state_and_return;
723 }
724
725 /*--- Receive the mapping table ---*/
726 case BZ_X_MAPPING_1:
727 for (i = 0; i < 16; i++) {
728 s->state = BZ_X_MAPPING_1;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000729 if (! get_bits(s, &uc, 1)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000730 retVal = BZ_OK;
731 goto save_state_and_return;
732 }
733 if (uc == 1) {
734 s->inUse16[i] = TRUE;
735 } else {
736 s->inUse16[i] = FALSE;
737 }
738 }
739
740 for (i = 0; i < 256; i++) {
741 s->inUse[i] = FALSE;
742 }
743
744 for (i = 0; i < 16; i++) {
745 if (s->inUse16[i]) {
746 for (j = 0; j < 16; j++) {
747 case BZ_X_MAPPING_2:
748 s->state = BZ_X_MAPPING_2;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000749 if (! get_bits(s, &uc, 1)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000750 retVal = BZ_OK;
751 goto save_state_and_return;
752 }
753 if (uc == 1) {
754 s->inUse[i * 16 + j] = TRUE;
755 }
756 }
757 }
758 }
759
760 s->nInUse = 0;
761 for (i = 0; i < 256; i++) {
762 if (s->inUse[i]) {
763 s->seqToUnseq[s->nInUse] = i;
764 s->nInUse++;
765 }
766 }
767 if (s->nInUse == 0) {
768 retVal = BZ_DATA_ERROR;
769 goto save_state_and_return;
770 }
771 alphaSize = s->nInUse+2;
772
773 /*--- Now the selectors ---*/
774 case BZ_X_SELECTOR_1:
775 s->state = BZ_X_SELECTOR_1;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000776 if (! get_bits(s, &nGroups, 3)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000777 retVal = BZ_OK;
778 goto save_state_and_return;
779 }
780 if (nGroups < 2 || nGroups > 6) {
781 retVal = BZ_DATA_ERROR;
782 goto save_state_and_return;
783 }
784
785 case BZ_X_SELECTOR_2:
786 s->state = BZ_X_SELECTOR_2;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000787 if (! get_bits(s, &nSelectors, 15)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000788 retVal = BZ_OK;
789 goto save_state_and_return;
790 }
791 if (nSelectors < 1) {
792 retVal = BZ_DATA_ERROR;
793 goto save_state_and_return;
794 }
795
796
797
798 for (i = 0; i < nSelectors; i++) {
799 j = 0;
800 while (1) {
801 case BZ_X_SELECTOR_3:
802 s->state = BZ_X_SELECTOR_3;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000803 if (! get_bits(s, &uc, 1)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000804 retVal = BZ_OK;
805 goto save_state_and_return;
806 }
807 if (uc == 0) {
808 break;
809 }
810 j++;
811 if (j >= nGroups) {
812 retVal = BZ_DATA_ERROR;
813 goto save_state_and_return;
814 }
815 }
816 s->selectorMtf[i] = j;
817 }
818
819 /*--- Undo the MTF values for the selectors. ---*/
820 {
821 unsigned char pos[BZ_N_GROUPS], tmp, v;
822 for (v = 0; v < nGroups; v++) {
823 pos[v] = v;
824 }
825 for (i = 0; i < nSelectors; i++) {
826 v = s->selectorMtf[i];
827 tmp = pos[v];
828 while (v > 0) {
829 pos[v] = pos[v-1];
830 v--;
831 }
832 pos[0] = tmp;
833 s->selector[i] = tmp;
834 }
835 }
836
837 /*--- Now the coding tables ---*/
838 for (t = 0; t < nGroups; t++) {
839 case BZ_X_CODING_1:
840 s->state = BZ_X_CODING_1;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000841 if (! get_bits(s, &curr, 5)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000842 retVal = BZ_OK;
843 goto save_state_and_return;
844 }
845 for (i = 0; i < alphaSize; i++) {
846 while (TRUE) {
847 if (curr < 1 || curr > 20) {
848 retVal = BZ_DATA_ERROR;
849 goto save_state_and_return;
850 }
851
852 case BZ_X_CODING_2:
853 s->state = BZ_X_CODING_2;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000854 if (! get_bits(s, &uc, 1)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000855 retVal = BZ_OK;
856 goto save_state_and_return;
857 }
858 if (uc == 0) {
859 break;
860 }
861
862 case BZ_X_CODING_3:
863 s->state = BZ_X_CODING_3;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000864 if (! get_bits(s, &uc, 1)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000865 retVal = BZ_OK;
866 goto save_state_and_return;
867 }
868 if (uc == 0) {
869 curr++;
870 } else {
871 curr--;
872 }
873 }
874 s->len[t][i] = curr;
875 }
876 }
877
878 /*--- Create the Huffman decoding tables ---*/
879 for (t = 0; t < nGroups; t++) {
880 minLen = 32;
881 maxLen = 0;
882 for (i = 0; i < alphaSize; i++) {
883 if (s->len[t][i] > maxLen) {
884 maxLen = s->len[t][i];
885 }
886 if (s->len[t][i] < minLen) {
887 minLen = s->len[t][i];
888 }
889 }
890
891 BZ2_hbCreateDecodeTables (
892 &(s->limit[t][0]),
893 &(s->base[t][0]),
894 &(s->perm[t][0]),
895 &(s->len[t][0]),
896 minLen, maxLen, alphaSize
897 );
898
899
900 s->minLens[t] = minLen;
901 }
902
903 /*--- Now the MTF values ---*/
904
905 EOB = s->nInUse+1;
906 nblockMAX = 100000 * s->blockSize100k;
907 groupNo = -1;
908 groupPos = 0;
909
910 for (i = 0; i <= 255; i++) {
911 s->unzftab[i] = 0;
912 }
913 /*-- MTF init --*/
914 {
915 int ii, jj, kk;
916 kk = MTFA_SIZE-1;
917 for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
918 for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
919 s->mtfa[kk] = (unsigned char)(ii * MTFL_SIZE + jj);
920 kk--;
921 }
922 s->mtfbase[ii] = kk + 1;
923 }
924 }
925 /*-- end MTF init --*/
926
927 nblock = 0;
928
Matt Kraai1f0c4362001-12-20 23:13:26 +0000929 if (! get_mtf_val_init()) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000930 goto save_state_and_return;
931 }
932 case BZ_X_MTF_1:
933 s->state = BZ_X_MTF_1;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000934 if (! get_bits(s, &zvec, zn)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000935 retVal = BZ_OK;
936 goto save_state_and_return;
937 }
938 while (1) {
939 if (zn > 20 /* the longest code */) {
940 retVal = BZ_DATA_ERROR;
941 goto save_state_and_return;
942 }
943 if (zvec <= gLimit[zn]) {
944 break;
945 }
946 zn++;
947
948 case BZ_X_MTF_2:
949 s->state = BZ_X_MTF_2;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000950 if (! get_bits(s, &zj, 1)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000951 retVal = BZ_OK;
952 goto save_state_and_return;
953 }
954 zvec = (zvec << 1) | zj;
955 }
956 if (zvec - gBase[zn] < 0 || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) {
957 retVal = BZ_DATA_ERROR;
958 goto save_state_and_return;
959 }
960 nextSym = gPerm[zvec - gBase[zn]];
961
962 while (1) {
963 if (nextSym == EOB) {
964 break;
965 }
966
967 if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
968 es = -1;
969 N = 1;
970 do {
971 if (nextSym == BZ_RUNA) {
972 es = es + (0+1) * N;
973 } else {
974 if (nextSym == BZ_RUNB) {
975 es = es + (1+1) * N;
976 }
977 }
978 N = N * 2;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000979 if (! get_mtf_val_init()) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000980 goto save_state_and_return;
981 }
982 case BZ_X_MTF_3:
983 s->state = BZ_X_MTF_3;
Matt Kraai1f0c4362001-12-20 23:13:26 +0000984 if (! get_bits(s, &zvec, zn)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +0000985 retVal = BZ_OK;
986 goto save_state_and_return;
987 }
988 while (1) {
989 if (zn > 20 /* the longest code */) {
990 retVal = BZ_DATA_ERROR;
991 goto save_state_and_return;
992 }
993 if (zvec <= gLimit[zn]) {
994 break;
995 }
996 zn++;
997
998 case BZ_X_MTF_4:
999 s->state = BZ_X_MTF_4;
Matt Kraai1f0c4362001-12-20 23:13:26 +00001000 if (! get_bits(s, &zj, 1)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +00001001 retVal = BZ_OK;
1002 goto save_state_and_return;
1003 }
1004 zvec = (zvec << 1) | zj;
1005 }
1006 if (zvec - gBase[zn] < 0 || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) {
1007 retVal = BZ_DATA_ERROR;
1008 goto save_state_and_return;
1009
1010 }
1011 nextSym = gPerm[zvec - gBase[zn]];
1012 }
1013 while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
1014
1015 es++;
1016 uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
1017 s->unzftab[uc] += es;
1018
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001019 while (es > 0) {
1020 if (nblock >= nblockMAX) {
1021 retVal = BZ_DATA_ERROR;
1022 goto save_state_and_return;
Glenn L McGrath24e28332001-10-05 03:48:57 +00001023 }
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001024 s->tt[nblock] = (unsigned int)uc;
1025 nblock++;
1026 es--;
Glenn L McGrath24e28332001-10-05 03:48:57 +00001027 }
1028 continue;
1029 } else {
1030 if (nblock >= nblockMAX) {
1031 retVal = BZ_DATA_ERROR;
1032 goto save_state_and_return;
1033 }
1034 /*-- uc = MTF ( nextSym-1 ) --*/
1035 {
1036 int ii, jj, kk, pp, lno, off;
1037 unsigned int nn;
1038 nn = (unsigned int)(nextSym - 1);
1039
1040 if (nn < MTFL_SIZE) {
1041 /* avoid general-case expense */
1042 pp = s->mtfbase[0];
1043 uc = s->mtfa[pp+nn];
1044 while (nn > 3) {
1045 int z = pp+nn;
1046 s->mtfa[(z) ] = s->mtfa[(z)-1];
1047 s->mtfa[(z)-1] = s->mtfa[(z)-2];
1048 s->mtfa[(z)-2] = s->mtfa[(z)-3];
1049 s->mtfa[(z)-3] = s->mtfa[(z)-4];
1050 nn -= 4;
1051 }
1052 while (nn > 0) {
1053 s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--;
1054 }
1055 s->mtfa[pp] = uc;
1056 } else {
1057 /* general case */
1058 lno = nn / MTFL_SIZE;
1059 off = nn % MTFL_SIZE;
1060 pp = s->mtfbase[lno] + off;
1061 uc = s->mtfa[pp];
1062 while (pp > s->mtfbase[lno]) {
1063 s->mtfa[pp] = s->mtfa[pp-1];
1064 pp--;
1065 }
1066 s->mtfbase[lno]++;
1067 while (lno > 0) {
1068 s->mtfbase[lno]--;
1069 s->mtfa[s->mtfbase[lno]] = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
1070 lno--;
1071 }
1072 s->mtfbase[0]--;
1073 s->mtfa[s->mtfbase[0]] = uc;
1074 if (s->mtfbase[0] == 0) {
1075 kk = MTFA_SIZE-1;
1076 for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
1077 for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
1078 s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
1079 kk--;
1080 }
1081 s->mtfbase[ii] = kk + 1;
1082 }
1083 }
1084 }
1085 }
1086 /*-- end uc = MTF ( nextSym-1 ) --*/
1087
1088 s->unzftab[s->seqToUnseq[uc]]++;
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001089 s->tt[nblock] = (unsigned int)(s->seqToUnseq[uc]);
Glenn L McGrath24e28332001-10-05 03:48:57 +00001090 nblock++;
1091
Matt Kraai1f0c4362001-12-20 23:13:26 +00001092 if (! get_mtf_val_init()) {
Glenn L McGrath24e28332001-10-05 03:48:57 +00001093 goto save_state_and_return;
1094 }
1095 case BZ_X_MTF_5:
1096 s->state = BZ_X_MTF_5;
Matt Kraai1f0c4362001-12-20 23:13:26 +00001097 if (! get_bits(s, &zvec, zn)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +00001098 retVal = BZ_OK;
1099 goto save_state_and_return;
1100 }
1101 while (1) {
1102 if (zn > 20 /* the longest code */) {
1103 retVal = BZ_DATA_ERROR;
1104 goto save_state_and_return;
1105 }
1106 if (zvec <= gLimit[zn]) {
1107 break;
1108 }
1109 zn++;
1110
1111 case BZ_X_MTF_6:
1112 s->state = BZ_X_MTF_6;
Matt Kraai1f0c4362001-12-20 23:13:26 +00001113 if (! get_bits(s, &zj, 1)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +00001114 retVal = BZ_OK;
1115 goto save_state_and_return;
1116 }
1117 zvec = (zvec << 1) | zj;
1118 }
1119 if (zvec - gBase[zn] < 0 || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) {
1120 retVal = BZ_DATA_ERROR;
1121 goto save_state_and_return;
1122 }
1123 nextSym = gPerm[zvec - gBase[zn]];
1124 continue;
1125 }
1126 }
1127
1128 /* Now we know what nblock is, we can do a better sanity
1129 check on s->origPtr.
1130 */
1131 if (s->origPtr < 0 || s->origPtr >= nblock) {
1132 retVal = BZ_DATA_ERROR;
1133 goto save_state_and_return;
1134 }
1135 s->state_out_len = 0;
1136 s->state_out_ch = 0;
1137 s->calculatedBlockCRC = 0xffffffffL;
1138 s->state = BZ_X_OUTPUT;
Glenn L McGrath24e28332001-10-05 03:48:57 +00001139
1140 /*-- Set up cftab to facilitate generation of T^(-1) --*/
1141 s->cftab[0] = 0;
1142 for (i = 1; i <= 256; i++) {
1143 s->cftab[i] = s->unzftab[i-1];
1144 }
1145 for (i = 1; i <= 256; i++) {
1146 s->cftab[i] += s->cftab[i-1];
1147 }
1148
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001149 /*-- compute the T^(-1) vector --*/
1150 for (i = 0; i < nblock; i++) {
1151 uc = (unsigned char)(s->tt[i] & 0xff);
1152 s->tt[s->cftab[uc]] |= (i << 8);
1153 s->cftab[uc]++;
1154 }
Glenn L McGrath24e28332001-10-05 03:48:57 +00001155
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001156 s->tPos = s->tt[s->origPtr] >> 8;
1157 s->nblock_used = 0;
1158 if (s->blockRandomised) {
1159 s->rNToGo = 0;
1160 s->rTPos = 0;
1161 s->k0 = bz_get_fast(s);
Glenn L McGrath24e28332001-10-05 03:48:57 +00001162
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001163 s->nblock_used++;
1164 bz_rand_udp_mask(s);
1165 s->k0 ^= ((s->rNToGo == 1) ? 1 : 0);
1166 } else {
1167 s->k0 = bz_get_fast(s);
1168 s->nblock_used++;
1169 }
Glenn L McGrath24e28332001-10-05 03:48:57 +00001170
1171 retVal = BZ_OK;
1172 goto save_state_and_return;
1173
1174endhdr_2:
1175 case BZ_X_ENDHDR_2:
1176 s->state = BZ_X_ENDHDR_2;
Matt Kraai1f0c4362001-12-20 23:13:26 +00001177 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +00001178 retVal = BZ_OK;
1179 goto save_state_and_return;
1180 }
1181 if (uc != 0x72) {
1182 retVal = BZ_DATA_ERROR;
1183 goto save_state_and_return;
1184 }
1185
1186 case BZ_X_ENDHDR_3:
1187 s->state = BZ_X_ENDHDR_3;
Matt Kraai1f0c4362001-12-20 23:13:26 +00001188 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +00001189 retVal = BZ_OK;
1190 goto save_state_and_return;
1191 }
1192 if (uc != 0x45) {
1193 retVal = BZ_DATA_ERROR;
1194 goto save_state_and_return;
1195 }
1196
1197 case BZ_X_ENDHDR_4:
1198 s->state = BZ_X_ENDHDR_4;
Matt Kraai1f0c4362001-12-20 23:13:26 +00001199 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +00001200 retVal = BZ_OK;
1201 goto save_state_and_return;
1202 }
1203 if (uc != 0x38) {
1204 retVal = BZ_DATA_ERROR;
1205 goto save_state_and_return;
1206 }
1207
1208 case BZ_X_ENDHDR_5:
1209 s->state = BZ_X_ENDHDR_5;
Matt Kraai1f0c4362001-12-20 23:13:26 +00001210 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +00001211 retVal = BZ_OK;
1212 goto save_state_and_return;
1213 }
1214 if (uc != 0x50) {
1215 retVal = BZ_DATA_ERROR;
1216 goto save_state_and_return;
1217 }
1218
1219 case BZ_X_ENDHDR_6:
1220 s->state = BZ_X_ENDHDR_6;
Matt Kraai1f0c4362001-12-20 23:13:26 +00001221 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +00001222 retVal = BZ_OK;
1223 goto save_state_and_return;
1224 }
1225 if (uc != 0x90) {
1226 retVal = BZ_DATA_ERROR;
1227 goto save_state_and_return;
1228 }
1229 s->storedCombinedCRC = 0;
1230
1231 case BZ_X_CCRC_1:
1232 s->state = BZ_X_CCRC_1;
Matt Kraai1f0c4362001-12-20 23:13:26 +00001233 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +00001234 retVal = BZ_OK;
1235 goto save_state_and_return;
1236 }
1237 s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((unsigned int)uc);
1238 case BZ_X_CCRC_2:
1239 s->state = BZ_X_CCRC_2;
Matt Kraai1f0c4362001-12-20 23:13:26 +00001240 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +00001241 retVal = BZ_OK;
1242 goto save_state_and_return;
1243 }
1244 s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((unsigned int)uc);
1245
1246 case BZ_X_CCRC_3:
1247 s->state = BZ_X_CCRC_3;
Matt Kraai1f0c4362001-12-20 23:13:26 +00001248 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +00001249 retVal = BZ_OK;
1250 goto save_state_and_return;
1251 }
1252 s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((unsigned int)uc);
1253
1254 case BZ_X_CCRC_4:
1255 s->state = BZ_X_CCRC_4;
Matt Kraai1f0c4362001-12-20 23:13:26 +00001256 if (! get_bits(s, &uc, 8)) {
Glenn L McGrath24e28332001-10-05 03:48:57 +00001257 retVal = BZ_OK;
1258 goto save_state_and_return;
1259 }
1260 s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((unsigned int)uc);
1261
1262 s->state = BZ_X_IDLE;
1263 retVal = BZ_STREAM_END;
1264 goto save_state_and_return;
1265
Glenn L McGrath24e28332001-10-05 03:48:57 +00001266 }
1267
Glenn L McGrath24e28332001-10-05 03:48:57 +00001268save_state_and_return:
1269 s->save_i = i;
1270 s->save_j = j;
1271 s->save_t = t;
1272 s->save_alphaSize = alphaSize;
1273 s->save_nGroups = nGroups;
1274 s->save_nSelectors = nSelectors;
1275 s->save_EOB = EOB;
1276 s->save_groupNo = groupNo;
1277 s->save_groupPos = groupPos;
1278 s->save_nextSym = nextSym;
1279 s->save_nblockMAX = nblockMAX;
1280 s->save_nblock = nblock;
1281 s->save_es = es;
1282 s->save_N = N;
1283 s->save_curr = curr;
1284 s->save_zt = zt;
1285 s->save_zn = zn;
1286 s->save_zvec = zvec;
1287 s->save_zj = zj;
1288 s->save_gSel = gSel;
1289 s->save_gMinlen = gMinlen;
1290 s->save_gLimit = gLimit;
1291 s->save_gBase = gBase;
1292 s->save_gPerm = gPerm;
1293
1294 return retVal;
1295}
1296
Glenn L McGrath24e28332001-10-05 03:48:57 +00001297//int BZ2_bzDecompressInit(bz_stream* strm, int verbosity_level, int small)
Aaron Lehmann90314812002-06-23 22:13:22 +00001298static inline int BZ2_bzDecompressInit(bz_stream* strm)
Glenn L McGrath24e28332001-10-05 03:48:57 +00001299{
1300 DState* s;
1301
Glenn L McGrath24e28332001-10-05 03:48:57 +00001302// if (verbosity_level < 0 || verbosity_level > 4) {
1303// return BZ_PARAM_ERROR;
1304// }
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001305 s = xmalloc(sizeof(DState));
Glenn L McGrath24e28332001-10-05 03:48:57 +00001306 s->strm = strm;
1307 strm->state = s;
1308 s->state = BZ_X_MAGIC_1;
1309 s->bsLive = 0;
1310 s->bsBuff = 0;
1311 s->calculatedCombinedCRC = 0;
Glenn L McGrath24e28332001-10-05 03:48:57 +00001312 s->tt = NULL;
1313 s->currBlockNo = 0;
Glenn L McGrath24e28332001-10-05 03:48:57 +00001314
1315 return BZ_OK;
1316}
1317
Aaron Lehmann90314812002-06-23 22:13:22 +00001318static void bz_seterr(int eee, int *bzerror, bzFile **bzf)
Glenn L McGrath24e28332001-10-05 03:48:57 +00001319{
1320 if (bzerror != NULL) {
1321 *bzerror = eee;
1322 }
1323 if (*bzf != NULL) {
1324 (*bzf)->lastErr = eee;
1325 }
1326}
1327
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001328static void BZ2_bzReadClose(int *bzerror, void *b)
Glenn L McGrath24e28332001-10-05 03:48:57 +00001329{
1330 bzFile* bzf = (bzFile*)b;
1331
1332 bz_seterr(BZ_OK, bzerror, &bzf);
Glenn L McGrath24e28332001-10-05 03:48:57 +00001333
1334 if (bzf->initialisedOk) {
1335 bz_stream *strm = &(bzf->strm);
1336 DState *s;
1337 if (strm == NULL) {
1338 return;
1339 }
1340 s = strm->state;
1341 if ((s == NULL) || (s->strm != strm)) {
1342 return;
1343 }
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001344 free(s->tt);
1345 free(strm->state);
Glenn L McGrath24e28332001-10-05 03:48:57 +00001346 strm->state = NULL;
1347 return;
1348 }
1349 free(bzf);
1350}
1351
1352static void unRLE_obuf_to_output_FAST(DState *s)
1353{
1354 unsigned char k1;
1355
1356 if (s->blockRandomised) {
1357 while (1) {
1358 /* try to finish existing run */
1359 while (1) {
1360 if (s->strm->avail_out == 0) {
1361 return;
1362 }
1363 if (s->state_out_len == 0) {
1364 break;
1365 }
1366 *((unsigned char *)(s->strm->next_out)) = s->state_out_ch;
1367 s->calculatedBlockCRC = (s->calculatedBlockCRC << 8) ^
1368 BZ2_crc32Table[(s->calculatedBlockCRC >> 24) ^
1369 ((unsigned char)s->state_out_ch)];
1370 s->state_out_len--;
1371 s->strm->next_out++;
1372 s->strm->avail_out--;
Glenn L McGrath24e28332001-10-05 03:48:57 +00001373 }
1374
1375 /* can a new run be started? */
1376 if (s->nblock_used == s->save_nblock+1) {
1377 return;
1378 }
1379 s->state_out_len = 1;
1380 s->state_out_ch = s->k0;
1381 k1 = bz_get_fast(s);
1382 bz_rand_udp_mask(s);
1383 k1 ^= ((s->rNToGo == 1) ? 1 : 0);
1384 s->nblock_used++;
1385 if (s->nblock_used == s->save_nblock+1) {
1386 continue;
1387 }
1388 if (k1 != s->k0) {
1389 s->k0 = k1;
1390 continue;
1391 }
1392
1393 s->state_out_len = 2;
1394 k1 = bz_get_fast(s);
1395 bz_rand_udp_mask(s);
1396 k1 ^= ((s->rNToGo == 1) ? 1 : 0);
1397 s->nblock_used++;
1398 if (s->nblock_used == s->save_nblock+1) {
1399 continue;
1400 }
1401 if (k1 != s->k0) {
1402 s->k0 = k1;
1403 continue;
1404 }
1405 s->state_out_len = 3;
1406 k1 = bz_get_fast(s);
1407 bz_rand_udp_mask(s);
1408 k1 ^= ((s->rNToGo == 1) ? 1 : 0);
1409 s->nblock_used++;
1410 if (s->nblock_used == s->save_nblock+1) {
1411 continue;
1412 }
1413 if (k1 != s->k0) {
1414 s->k0 = k1;
1415 continue;
1416 }
1417
1418 k1 = bz_get_fast(s);
1419 bz_rand_udp_mask(s);
1420 k1 ^= ((s->rNToGo == 1) ? 1 : 0);
1421 s->nblock_used++;
1422 s->state_out_len = ((int)k1) + 4;
1423 s->k0 = bz_get_fast(s);
1424 bz_rand_udp_mask(s);
1425 s->k0 ^= ((s->rNToGo == 1) ? 1 : 0);
1426 s->nblock_used++;
1427 }
1428 } else {
1429 /* restore */
1430 unsigned int c_calculatedBlockCRC = s->calculatedBlockCRC;
1431 unsigned char c_state_out_ch = s->state_out_ch;
1432 int c_state_out_len = s->state_out_len;
1433 int c_nblock_used = s->nblock_used;
1434 int c_k0 = s->k0;
1435 unsigned int *c_tt = s->tt;
1436 unsigned int c_tPos = s->tPos;
1437 char *cs_next_out = s->strm->next_out;
1438 unsigned int cs_avail_out = s->strm->avail_out;
1439 /* end restore */
1440
Glenn L McGrath24e28332001-10-05 03:48:57 +00001441 int s_save_nblockPP = s->save_nblock+1;
Glenn L McGrath24e28332001-10-05 03:48:57 +00001442
1443 while (1) {
1444 /* try to finish existing run */
1445 if (c_state_out_len > 0) {
1446 while (TRUE) {
1447 if (cs_avail_out == 0) {
1448 goto return_notr;
1449 }
1450 if (c_state_out_len == 1) {
1451 break;
1452 }
1453 *((unsigned char *)(cs_next_out)) = c_state_out_ch;
1454 c_calculatedBlockCRC = (c_calculatedBlockCRC << 8) ^
1455 BZ2_crc32Table[(c_calculatedBlockCRC >> 24) ^
1456 ((unsigned char)c_state_out_ch)];
1457 c_state_out_len--;
1458 cs_next_out++;
1459 cs_avail_out--;
1460 }
1461s_state_out_len_eq_one:
1462 {
1463 if (cs_avail_out == 0) {
1464 c_state_out_len = 1;
1465 goto return_notr;
1466 }
1467 *((unsigned char *)(cs_next_out)) = c_state_out_ch;
1468 c_calculatedBlockCRC = (c_calculatedBlockCRC << 8) ^
1469 BZ2_crc32Table[(c_calculatedBlockCRC >> 24) ^
1470 ((unsigned char)c_state_out_ch)];
1471 cs_next_out++;
1472 cs_avail_out--;
1473 }
1474 }
1475 /* can a new run be started? */
1476 if (c_nblock_used == s_save_nblockPP) {
1477 c_state_out_len = 0; goto return_notr;
1478 }
1479 c_state_out_ch = c_k0;
1480 c_tPos = c_tt[c_tPos];
1481 k1 = (unsigned char)(c_tPos & 0xff);
1482 c_tPos >>= 8;
1483
1484 c_nblock_used++;
1485
1486 if (k1 != c_k0) {
1487 c_k0 = k1;
1488 goto s_state_out_len_eq_one;
1489 }
1490
1491 if (c_nblock_used == s_save_nblockPP) {
1492 goto s_state_out_len_eq_one;
1493 }
1494
1495 c_state_out_len = 2;
1496 c_tPos = c_tt[c_tPos];
1497 k1 = (unsigned char)(c_tPos & 0xff);
1498 c_tPos >>= 8;
1499
1500 c_nblock_used++;
1501 if (c_nblock_used == s_save_nblockPP) {
1502 continue;
1503 }
1504 if (k1 != c_k0) {
1505 c_k0 = k1;
1506 continue;
1507 }
1508
1509 c_state_out_len = 3;
1510 c_tPos = c_tt[c_tPos];
1511 k1 = (unsigned char)(c_tPos & 0xff);
1512 c_tPos >>= 8;
1513
1514 c_nblock_used++;
1515 if (c_nblock_used == s_save_nblockPP) {
1516 continue;
1517 }
1518 if (k1 != c_k0) {
1519 c_k0 = k1;
1520 continue;
1521 }
1522
1523 c_tPos = c_tt[c_tPos];
1524 k1 = (unsigned char)(c_tPos & 0xff);
1525 c_tPos >>= 8;
1526
1527 c_nblock_used++;
1528 c_state_out_len = ((int)k1) + 4;
1529
1530 c_tPos = c_tt[c_tPos];
1531 c_k0 = (unsigned char)(c_tPos & 0xff);
1532 c_tPos >>= 8;
1533
1534 c_nblock_used++;
1535 }
1536
1537return_notr:
Glenn L McGrath24e28332001-10-05 03:48:57 +00001538
1539 /* save */
1540 s->calculatedBlockCRC = c_calculatedBlockCRC;
1541 s->state_out_ch = c_state_out_ch;
1542 s->state_out_len = c_state_out_len;
1543 s->nblock_used = c_nblock_used;
1544 s->k0 = c_k0;
1545 s->tt = c_tt;
1546 s->tPos = c_tPos;
1547 s->strm->next_out = cs_next_out;
1548 s->strm->avail_out = cs_avail_out;
1549 /* end save */
1550 }
1551}
Aaron Lehmann90314812002-06-23 22:13:22 +00001552static inline
Glenn L McGrath24e28332001-10-05 03:48:57 +00001553int BZ2_bzDecompress(bz_stream *strm)
1554{
1555 DState* s;
Glenn L McGrath24e28332001-10-05 03:48:57 +00001556 s = strm->state;
Glenn L McGrath24e28332001-10-05 03:48:57 +00001557
1558 while (1) {
1559 if (s->state == BZ_X_IDLE) {
1560 return BZ_SEQUENCE_ERROR;
1561 }
1562 if (s->state == BZ_X_OUTPUT) {
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001563 unRLE_obuf_to_output_FAST(s);
Glenn L McGrath24e28332001-10-05 03:48:57 +00001564 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
1565 s->calculatedBlockCRC = ~(s->calculatedBlockCRC);
Glenn L McGrath24e28332001-10-05 03:48:57 +00001566 if (s->calculatedBlockCRC != s->storedBlockCRC) {
1567 return BZ_DATA_ERROR;
1568 }
1569 s->calculatedCombinedCRC = (s->calculatedCombinedCRC << 1) | (s->calculatedCombinedCRC >> 31);
1570 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
1571 s->state = BZ_X_BLKHDR_1;
1572 } else {
1573 return BZ_OK;
1574 }
1575 }
1576 if (s->state >= BZ_X_MAGIC_1) {
1577 int r = BZ2_decompress(s);
1578 if (r == BZ_STREAM_END) {
Glenn L McGrath24e28332001-10-05 03:48:57 +00001579 if (s->calculatedCombinedCRC != s->storedCombinedCRC) {
1580 return BZ_DATA_ERROR;
1581 }
1582 return r;
1583 }
1584 if (s->state != BZ_X_OUTPUT) {
1585 return r;
1586 }
1587 }
1588 }
1589
Glenn L McGrath24e28332001-10-05 03:48:57 +00001590 return(0); /*NOTREACHED*/
1591}
1592
Aaron Lehmann90314812002-06-23 22:13:22 +00001593static inline int BZ2_bzRead(int *bzerror, void *b, void *buf, int len)
Glenn L McGrath24e28332001-10-05 03:48:57 +00001594{
1595 int n, ret;
1596 bzFile *bzf = (bzFile*)b;
1597
1598 bz_seterr(BZ_OK, bzerror, &bzf);
1599
Glenn L McGrath24e28332001-10-05 03:48:57 +00001600 if (len == 0) {
1601 bz_seterr(BZ_OK, bzerror, &bzf);
1602 return 0;
1603 }
1604
1605 bzf->strm.avail_out = len;
1606 bzf->strm.next_out = buf;
1607
1608 while (1) {
1609 if (ferror(bzf->handle)) {
1610 bz_seterr(BZ_IO_ERROR, bzerror, &bzf);
1611 return 0;
1612 }
1613 if ((bzf->strm.avail_in == 0) && !myfeof(bzf->handle)) {
1614 n = fread(bzf->buf, sizeof(unsigned char), BZ_MAX_UNUSED, bzf->handle);
1615 if (ferror(bzf->handle)) {
1616 bz_seterr(BZ_IO_ERROR, bzerror, &bzf);
1617 return 0;
1618 }
1619 bzf->bufN = n;
1620 bzf->strm.avail_in = bzf->bufN;
1621 bzf->strm.next_in = bzf->buf;
1622 }
1623
1624 ret = BZ2_bzDecompress(&(bzf->strm));
1625
1626 if ((ret != BZ_OK) && (ret != BZ_STREAM_END)) {
1627 bz_seterr(ret, bzerror, &bzf);
1628 return 0;
1629 }
1630
1631 if ((ret == BZ_OK) && myfeof(bzf->handle) &&
1632 (bzf->strm.avail_in == 0) && (bzf->strm.avail_out > 0)) {
1633 bz_seterr(BZ_UNEXPECTED_EOF, bzerror, &bzf);
1634 return(0);
1635 }
1636
1637 if (ret == BZ_STREAM_END) {
1638 bz_seterr(BZ_STREAM_END, bzerror, &bzf);
1639 return(len - bzf->strm.avail_out);
1640 }
1641 if (bzf->strm.avail_out == 0) {
1642 bz_seterr(BZ_OK, bzerror, &bzf);
1643 return(len);
1644 }
1645 }
1646 return(0); /*not reached*/
1647}
1648
Aaron Lehmann90314812002-06-23 22:13:22 +00001649static inline void *BZ2_bzReadOpen(int *bzerror, FILE *f, void *unused, int nUnused)
Glenn L McGrath24e28332001-10-05 03:48:57 +00001650{
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001651 bzFile *bzf = xmalloc(sizeof(bzFile));
Glenn L McGrath24e28332001-10-05 03:48:57 +00001652 int ret;
1653
1654 bz_seterr(BZ_OK, bzerror, &bzf);
1655
Glenn L McGrath24e28332001-10-05 03:48:57 +00001656 bzf->initialisedOk = FALSE;
1657 bzf->handle = f;
1658 bzf->bufN = 0;
Glenn L McGrath24e28332001-10-05 03:48:57 +00001659
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001660 ret = BZ2_bzDecompressInit(&(bzf->strm));
Glenn L McGrath24e28332001-10-05 03:48:57 +00001661 if (ret != BZ_OK) {
1662 bz_seterr(ret, bzerror, &bzf);
1663 free(bzf);
1664 return NULL;
1665 }
1666
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001667 while (nUnused > 0) {
1668 bzf->buf[bzf->bufN] = *((unsigned char *)(unused)); bzf->bufN++;
1669 unused = ((void *)( 1 + ((unsigned char *)(unused)) ));
1670 nUnused--;
1671 }
Glenn L McGrath24e28332001-10-05 03:48:57 +00001672 bzf->strm.avail_in = bzf->bufN;
1673 bzf->strm.next_in = bzf->buf;
1674
1675 bzf->initialisedOk = TRUE;
1676 return bzf;
1677}
1678
Aaron Lehmann90314812002-06-23 22:13:22 +00001679static inline unsigned char uncompressStream(FILE *zStream, FILE *stream)
Glenn L McGrath24e28332001-10-05 03:48:57 +00001680{
1681 unsigned char unused[BZ_MAX_UNUSED];
1682 unsigned char *unusedTmp;
1683 unsigned char obuf[5000];
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001684 bzFile *bzf = NULL;
Glenn L McGrath24e28332001-10-05 03:48:57 +00001685 int bzerr_dummy;
1686 int bzerr;
1687 int nread;
1688 int nUnused;
1689 int streamNo;
1690 int ret;
1691 int i;
1692
1693 nUnused = 0;
1694 streamNo = 0;
1695
1696 if (ferror(stream)) {
1697 goto errhandler_io;
1698 }
1699 if (ferror(zStream)) {
1700 goto errhandler_io;
1701 }
1702
1703 while(1) {
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001704 bzf = BZ2_bzReadOpen(&bzerr, zStream, unused, nUnused);
Glenn L McGrath24e28332001-10-05 03:48:57 +00001705 if (bzf == NULL || bzerr != BZ_OK) {
1706 goto errhandler;
1707 }
1708 streamNo++;
1709
1710 while (bzerr == BZ_OK) {
1711 nread = BZ2_bzRead(&bzerr, bzf, obuf, 5000);
1712 if (bzerr == BZ_DATA_ERROR_MAGIC) {
1713 goto errhandler;
1714 }
1715 if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0) {
1716 fwrite(obuf, sizeof(unsigned char), nread, stream);
1717 }
1718 if (ferror(stream)) {
1719 goto errhandler_io;
1720 }
1721 }
1722 if (bzerr != BZ_STREAM_END) {
1723 goto errhandler;
1724 }
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001725 nUnused = bzf->strm.avail_in;
1726 unusedTmp = bzf->strm.next_in;
1727 bz_seterr(BZ_OK, &bzerr, &bzf);
Glenn L McGrath24e28332001-10-05 03:48:57 +00001728 for (i = 0; i < nUnused; i++) {
1729 unused[i] = unusedTmp[i];
1730 }
1731 BZ2_bzReadClose(&bzerr, bzf);
Glenn L McGrath24e28332001-10-05 03:48:57 +00001732 if ((nUnused == 0) && myfeof(zStream)) {
1733 break;
1734 }
1735 }
1736
1737 if (ferror(zStream)) {
1738 goto errhandler_io;
1739 }
1740 ret = fclose(zStream);
1741 if (ret == EOF) {
1742 goto errhandler_io;
1743 }
1744 if (ferror(stream)) {
1745 goto errhandler_io;
1746 }
1747 ret = fflush(stream);
1748 if (ret != 0) {
1749 goto errhandler_io;
1750 }
1751 if (stream != stdout) {
1752 ret = fclose(stream);
1753 if (ret == EOF) {
1754 goto errhandler_io;
1755 }
1756 }
Glenn L McGrath24e28332001-10-05 03:48:57 +00001757 return TRUE;
1758
1759errhandler:
1760 BZ2_bzReadClose ( &bzerr_dummy, bzf );
1761 switch (bzerr) {
Glenn L McGrath24e28332001-10-05 03:48:57 +00001762 case BZ_IO_ERROR:
1763errhandler_io:
1764 error_msg("\n%s: I/O or other error, bailing out. "
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001765 "Possible reason follows.\n", applet_name);
1766 perror(applet_name);
Aaron Lehmann8c26fbe2002-06-23 21:56:13 +00001767 exit(1);
Glenn L McGrath24e28332001-10-05 03:48:57 +00001768 case BZ_DATA_ERROR:
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001769 error_msg("\n%s: Data integrity error when decompressing.\n", applet_name);
Aaron Lehmann8c26fbe2002-06-23 21:56:13 +00001770 exit(2);
Glenn L McGrath24e28332001-10-05 03:48:57 +00001771 case BZ_UNEXPECTED_EOF:
1772 error_msg("\n%s: Compressed file ends unexpectedly;\n\t"
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001773 "perhaps it is corrupted? *Possible* reason follows.\n", applet_name);
1774 perror(applet_name);
Aaron Lehmann8c26fbe2002-06-23 21:56:13 +00001775 exit(2);
Glenn L McGrath24e28332001-10-05 03:48:57 +00001776 case BZ_DATA_ERROR_MAGIC:
1777 if (zStream != stdin) {
1778 fclose(zStream);
1779 }
1780 if (stream != stdout) {
1781 fclose(stream);
1782 }
1783 if (streamNo == 1) {
1784 return FALSE;
1785 } else {
Aaron Lehmann9f92d5f2002-06-22 06:35:29 +00001786 return TRUE;
Glenn L McGrath24e28332001-10-05 03:48:57 +00001787 }
Glenn L McGrath24e28332001-10-05 03:48:57 +00001788 }
1789
Glenn L McGrath24e28332001-10-05 03:48:57 +00001790 return(TRUE); /*notreached*/
1791}
1792
1793int bunzip2_main(int argc, char **argv)
1794{
Glenn L McGrathfff11f12001-11-18 14:20:25 +00001795 const int bunzip_to_stdout = 1;
Matt Kraai9cdb0602002-03-27 17:31:01 +00001796 const int bunzip_force = 2;
Glenn L McGrathfff11f12001-11-18 14:20:25 +00001797 int flags = 0;
1798 int opt = 0;
Matt Kraaicf32ac52002-03-27 17:46:44 +00001799 int status;
Glenn L McGrathfff11f12001-11-18 14:20:25 +00001800
Glenn L McGrath24e28332001-10-05 03:48:57 +00001801 FILE *src_stream;
1802 FILE *dst_stream;
Matt Kraai9cdb0602002-03-27 17:31:01 +00001803 char *save_name = NULL;
Matt Kraaicf32ac52002-03-27 17:46:44 +00001804 char *delete_name = NULL;
Glenn L McGrathfff11f12001-11-18 14:20:25 +00001805
1806 /* if called as bzcat */
1807 if (strcmp(applet_name, "bzcat") == 0)
1808 flags |= bunzip_to_stdout;
1809
Matt Kraai9cdb0602002-03-27 17:31:01 +00001810 while ((opt = getopt(argc, argv, "cfh")) != -1) {
Glenn L McGrathfff11f12001-11-18 14:20:25 +00001811 switch (opt) {
1812 case 'c':
1813 flags |= bunzip_to_stdout;
1814 break;
Matt Kraai9cdb0602002-03-27 17:31:01 +00001815 case 'f':
1816 flags |= bunzip_force;
1817 break;
Glenn L McGrathfff11f12001-11-18 14:20:25 +00001818 case 'h':
1819 default:
1820 show_usage(); /* exit's inside usage */
1821 }
1822 }
1823
Matt Kraai9cdb0602002-03-27 17:31:01 +00001824 /* Set input filename and number */
1825 if (argv[optind] == NULL || strcmp(argv[optind], "-") == 0) {
1826 flags |= bunzip_to_stdout;
1827 src_stream = stdin;
1828 } else {
1829 /* Open input file */
1830 src_stream = xfopen(argv[optind], "r");
1831
1832 save_name = xstrdup(argv[optind]);
1833 if (strcmp(save_name + strlen(save_name) - 4, ".bz2") != 0)
1834 error_msg_and_die("Invalid extension");
1835 save_name[strlen(save_name) - 4] = '\0';
Glenn L McGrath24e28332001-10-05 03:48:57 +00001836 }
Glenn L McGrathfff11f12001-11-18 14:20:25 +00001837
Matt Kraai9cdb0602002-03-27 17:31:01 +00001838 /* Check that the input is sane. */
1839 if (isatty(fileno(src_stream)) && (flags & bunzip_force) == 0)
1840 error_msg_and_die("compressed data not read from terminal. Use -f to force it.");
Glenn L McGrathfff11f12001-11-18 14:20:25 +00001841
1842 if (flags & bunzip_to_stdout) {
1843 dst_stream = stdout;
1844 } else {
1845 dst_stream = xfopen(save_name, "w");
1846 }
Glenn L McGrath24e28332001-10-05 03:48:57 +00001847
Matt Kraaicf32ac52002-03-27 17:46:44 +00001848 if (uncompressStream(src_stream, dst_stream)) {
Matt Kraaia0782682002-04-15 15:01:37 +00001849 if (!(flags & bunzip_to_stdout))
Matt Kraaicf32ac52002-03-27 17:46:44 +00001850 delete_name = argv[optind];
1851 status = EXIT_SUCCESS;
1852 } else {
Matt Kraaia0782682002-04-15 15:01:37 +00001853 if (!(flags & bunzip_to_stdout))
Matt Kraaicf32ac52002-03-27 17:46:44 +00001854 delete_name = save_name;
1855 status = EXIT_FAILURE;
1856 }
1857
1858 if (delete_name) {
1859 if (unlink(delete_name) < 0) {
1860 error_msg_and_die("Couldn't remove %s", delete_name);
1861 }
1862 }
1863
1864 return status;
Glenn L McGrath24e28332001-10-05 03:48:57 +00001865}