xref: /aosp_15_r20/external/bzip2/bzip2recover.c (revision 0ac9a9daea5cce2e775d5da949508593e2ee9206)
1*0ac9a9daSXin Li /*-----------------------------------------------------------*/
2*0ac9a9daSXin Li /*--- Block recoverer program for bzip2                   ---*/
3*0ac9a9daSXin Li /*---                                      bzip2recover.c ---*/
4*0ac9a9daSXin Li /*-----------------------------------------------------------*/
5*0ac9a9daSXin Li 
6*0ac9a9daSXin Li /* ------------------------------------------------------------------
7*0ac9a9daSXin Li    This file is part of bzip2/libbzip2, a program and library for
8*0ac9a9daSXin Li    lossless, block-sorting data compression.
9*0ac9a9daSXin Li 
10*0ac9a9daSXin Li    bzip2/libbzip2 version 1.0.8 of 13 July 2019
11*0ac9a9daSXin Li    Copyright (C) 1996-2019 Julian Seward <[email protected]>
12*0ac9a9daSXin Li 
13*0ac9a9daSXin Li    Please read the WARNING, DISCLAIMER and PATENTS sections in the
14*0ac9a9daSXin Li    README file.
15*0ac9a9daSXin Li 
16*0ac9a9daSXin Li    This program is released under the terms of the license contained
17*0ac9a9daSXin Li    in the file LICENSE.
18*0ac9a9daSXin Li    ------------------------------------------------------------------ */
19*0ac9a9daSXin Li 
20*0ac9a9daSXin Li /* This program is a complete hack and should be rewritten properly.
21*0ac9a9daSXin Li 	 It isn't very complicated. */
22*0ac9a9daSXin Li 
23*0ac9a9daSXin Li #include <stdio.h>
24*0ac9a9daSXin Li #include <errno.h>
25*0ac9a9daSXin Li #include <stdlib.h>
26*0ac9a9daSXin Li #include <string.h>
27*0ac9a9daSXin Li 
28*0ac9a9daSXin Li 
29*0ac9a9daSXin Li /* This program records bit locations in the file to be recovered.
30*0ac9a9daSXin Li    That means that if 64-bit ints are not supported, we will not
31*0ac9a9daSXin Li    be able to recover .bz2 files over 512MB (2^32 bits) long.
32*0ac9a9daSXin Li    On GNU supported platforms, we take advantage of the 64-bit
33*0ac9a9daSXin Li    int support to circumvent this problem.  Ditto MSVC.
34*0ac9a9daSXin Li 
35*0ac9a9daSXin Li    This change occurred in version 1.0.2; all prior versions have
36*0ac9a9daSXin Li    the 512MB limitation.
37*0ac9a9daSXin Li */
38*0ac9a9daSXin Li #ifdef __GNUC__
39*0ac9a9daSXin Li    typedef  unsigned long long int  MaybeUInt64;
40*0ac9a9daSXin Li #  define MaybeUInt64_FMT "%Lu"
41*0ac9a9daSXin Li #else
42*0ac9a9daSXin Li #ifdef _MSC_VER
43*0ac9a9daSXin Li    typedef  unsigned __int64  MaybeUInt64;
44*0ac9a9daSXin Li #  define MaybeUInt64_FMT "%I64u"
45*0ac9a9daSXin Li #else
46*0ac9a9daSXin Li    typedef  unsigned int   MaybeUInt64;
47*0ac9a9daSXin Li #  define MaybeUInt64_FMT "%u"
48*0ac9a9daSXin Li #endif
49*0ac9a9daSXin Li #endif
50*0ac9a9daSXin Li 
51*0ac9a9daSXin Li typedef  unsigned int   UInt32;
52*0ac9a9daSXin Li typedef  int            Int32;
53*0ac9a9daSXin Li typedef  unsigned char  UChar;
54*0ac9a9daSXin Li typedef  char           Char;
55*0ac9a9daSXin Li typedef  unsigned char  Bool;
56*0ac9a9daSXin Li #define True    ((Bool)1)
57*0ac9a9daSXin Li #define False   ((Bool)0)
58*0ac9a9daSXin Li 
59*0ac9a9daSXin Li 
60*0ac9a9daSXin Li #define BZ_MAX_FILENAME 2000
61*0ac9a9daSXin Li 
62*0ac9a9daSXin Li Char inFileName[BZ_MAX_FILENAME];
63*0ac9a9daSXin Li Char outFileName[BZ_MAX_FILENAME];
64*0ac9a9daSXin Li Char progName[BZ_MAX_FILENAME];
65*0ac9a9daSXin Li 
66*0ac9a9daSXin Li MaybeUInt64 bytesOut = 0;
67*0ac9a9daSXin Li MaybeUInt64 bytesIn  = 0;
68*0ac9a9daSXin Li 
69*0ac9a9daSXin Li 
70*0ac9a9daSXin Li /*---------------------------------------------------*/
71*0ac9a9daSXin Li /*--- Header bytes                                ---*/
72*0ac9a9daSXin Li /*---------------------------------------------------*/
73*0ac9a9daSXin Li 
74*0ac9a9daSXin Li #define BZ_HDR_B 0x42                         /* 'B' */
75*0ac9a9daSXin Li #define BZ_HDR_Z 0x5a                         /* 'Z' */
76*0ac9a9daSXin Li #define BZ_HDR_h 0x68                         /* 'h' */
77*0ac9a9daSXin Li #define BZ_HDR_0 0x30                         /* '0' */
78*0ac9a9daSXin Li 
79*0ac9a9daSXin Li 
80*0ac9a9daSXin Li /*---------------------------------------------------*/
81*0ac9a9daSXin Li /*--- I/O errors                                  ---*/
82*0ac9a9daSXin Li /*---------------------------------------------------*/
83*0ac9a9daSXin Li 
84*0ac9a9daSXin Li /*---------------------------------------------*/
readError(void)85*0ac9a9daSXin Li static void readError ( void )
86*0ac9a9daSXin Li {
87*0ac9a9daSXin Li    fprintf ( stderr,
88*0ac9a9daSXin Li              "%s: I/O error reading `%s', possible reason follows.\n",
89*0ac9a9daSXin Li             progName, inFileName );
90*0ac9a9daSXin Li    perror ( progName );
91*0ac9a9daSXin Li    fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
92*0ac9a9daSXin Li              progName );
93*0ac9a9daSXin Li    exit ( 1 );
94*0ac9a9daSXin Li }
95*0ac9a9daSXin Li 
96*0ac9a9daSXin Li 
97*0ac9a9daSXin Li /*---------------------------------------------*/
writeError(void)98*0ac9a9daSXin Li static void writeError ( void )
99*0ac9a9daSXin Li {
100*0ac9a9daSXin Li    fprintf ( stderr,
101*0ac9a9daSXin Li              "%s: I/O error reading `%s', possible reason follows.\n",
102*0ac9a9daSXin Li             progName, inFileName );
103*0ac9a9daSXin Li    perror ( progName );
104*0ac9a9daSXin Li    fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
105*0ac9a9daSXin Li              progName );
106*0ac9a9daSXin Li    exit ( 1 );
107*0ac9a9daSXin Li }
108*0ac9a9daSXin Li 
109*0ac9a9daSXin Li 
110*0ac9a9daSXin Li /*---------------------------------------------*/
mallocFail(Int32 n)111*0ac9a9daSXin Li static void mallocFail ( Int32 n )
112*0ac9a9daSXin Li {
113*0ac9a9daSXin Li    fprintf ( stderr,
114*0ac9a9daSXin Li              "%s: malloc failed on request for %d bytes.\n",
115*0ac9a9daSXin Li             progName, n );
116*0ac9a9daSXin Li    fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
117*0ac9a9daSXin Li              progName );
118*0ac9a9daSXin Li    exit ( 1 );
119*0ac9a9daSXin Li }
120*0ac9a9daSXin Li 
121*0ac9a9daSXin Li 
122*0ac9a9daSXin Li /*---------------------------------------------*/
tooManyBlocks(Int32 max_handled_blocks)123*0ac9a9daSXin Li static void tooManyBlocks ( Int32 max_handled_blocks )
124*0ac9a9daSXin Li {
125*0ac9a9daSXin Li    fprintf ( stderr,
126*0ac9a9daSXin Li              "%s: `%s' appears to contain more than %d blocks\n",
127*0ac9a9daSXin Li             progName, inFileName, max_handled_blocks );
128*0ac9a9daSXin Li    fprintf ( stderr,
129*0ac9a9daSXin Li              "%s: and cannot be handled.  To fix, increase\n",
130*0ac9a9daSXin Li              progName );
131*0ac9a9daSXin Li    fprintf ( stderr,
132*0ac9a9daSXin Li              "%s: BZ_MAX_HANDLED_BLOCKS in bzip2recover.c, and recompile.\n",
133*0ac9a9daSXin Li              progName );
134*0ac9a9daSXin Li    exit ( 1 );
135*0ac9a9daSXin Li }
136*0ac9a9daSXin Li 
137*0ac9a9daSXin Li 
138*0ac9a9daSXin Li 
139*0ac9a9daSXin Li /*---------------------------------------------------*/
140*0ac9a9daSXin Li /*--- Bit stream I/O                              ---*/
141*0ac9a9daSXin Li /*---------------------------------------------------*/
142*0ac9a9daSXin Li 
143*0ac9a9daSXin Li typedef
144*0ac9a9daSXin Li    struct {
145*0ac9a9daSXin Li       FILE*  handle;
146*0ac9a9daSXin Li       Int32  buffer;
147*0ac9a9daSXin Li       Int32  buffLive;
148*0ac9a9daSXin Li       Char   mode;
149*0ac9a9daSXin Li    }
150*0ac9a9daSXin Li    BitStream;
151*0ac9a9daSXin Li 
152*0ac9a9daSXin Li 
153*0ac9a9daSXin Li /*---------------------------------------------*/
bsOpenReadStream(FILE * stream)154*0ac9a9daSXin Li static BitStream* bsOpenReadStream ( FILE* stream )
155*0ac9a9daSXin Li {
156*0ac9a9daSXin Li    BitStream *bs = malloc ( sizeof(BitStream) );
157*0ac9a9daSXin Li    if (bs == NULL) mallocFail ( sizeof(BitStream) );
158*0ac9a9daSXin Li    bs->handle = stream;
159*0ac9a9daSXin Li    bs->buffer = 0;
160*0ac9a9daSXin Li    bs->buffLive = 0;
161*0ac9a9daSXin Li    bs->mode = 'r';
162*0ac9a9daSXin Li    return bs;
163*0ac9a9daSXin Li }
164*0ac9a9daSXin Li 
165*0ac9a9daSXin Li 
166*0ac9a9daSXin Li /*---------------------------------------------*/
bsOpenWriteStream(FILE * stream)167*0ac9a9daSXin Li static BitStream* bsOpenWriteStream ( FILE* stream )
168*0ac9a9daSXin Li {
169*0ac9a9daSXin Li    BitStream *bs = malloc ( sizeof(BitStream) );
170*0ac9a9daSXin Li    if (bs == NULL) mallocFail ( sizeof(BitStream) );
171*0ac9a9daSXin Li    bs->handle = stream;
172*0ac9a9daSXin Li    bs->buffer = 0;
173*0ac9a9daSXin Li    bs->buffLive = 0;
174*0ac9a9daSXin Li    bs->mode = 'w';
175*0ac9a9daSXin Li    return bs;
176*0ac9a9daSXin Li }
177*0ac9a9daSXin Li 
178*0ac9a9daSXin Li 
179*0ac9a9daSXin Li /*---------------------------------------------*/
bsPutBit(BitStream * bs,Int32 bit)180*0ac9a9daSXin Li static void bsPutBit ( BitStream* bs, Int32 bit )
181*0ac9a9daSXin Li {
182*0ac9a9daSXin Li    if (bs->buffLive == 8) {
183*0ac9a9daSXin Li       Int32 retVal = putc ( (UChar) bs->buffer, bs->handle );
184*0ac9a9daSXin Li       if (retVal == EOF) writeError();
185*0ac9a9daSXin Li       bytesOut++;
186*0ac9a9daSXin Li       bs->buffLive = 1;
187*0ac9a9daSXin Li       bs->buffer = bit & 0x1;
188*0ac9a9daSXin Li    } else {
189*0ac9a9daSXin Li       bs->buffer = ( (bs->buffer << 1) | (bit & 0x1) );
190*0ac9a9daSXin Li       bs->buffLive++;
191*0ac9a9daSXin Li    };
192*0ac9a9daSXin Li }
193*0ac9a9daSXin Li 
194*0ac9a9daSXin Li 
195*0ac9a9daSXin Li /*---------------------------------------------*/
196*0ac9a9daSXin Li /*--
197*0ac9a9daSXin Li    Returns 0 or 1, or 2 to indicate EOF.
198*0ac9a9daSXin Li --*/
bsGetBit(BitStream * bs)199*0ac9a9daSXin Li static Int32 bsGetBit ( BitStream* bs )
200*0ac9a9daSXin Li {
201*0ac9a9daSXin Li    if (bs->buffLive > 0) {
202*0ac9a9daSXin Li       bs->buffLive --;
203*0ac9a9daSXin Li       return ( ((bs->buffer) >> (bs->buffLive)) & 0x1 );
204*0ac9a9daSXin Li    } else {
205*0ac9a9daSXin Li       Int32 retVal = getc ( bs->handle );
206*0ac9a9daSXin Li       if ( retVal == EOF ) {
207*0ac9a9daSXin Li          if (errno != 0) readError();
208*0ac9a9daSXin Li          return 2;
209*0ac9a9daSXin Li       }
210*0ac9a9daSXin Li       bs->buffLive = 7;
211*0ac9a9daSXin Li       bs->buffer = retVal;
212*0ac9a9daSXin Li       return ( ((bs->buffer) >> 7) & 0x1 );
213*0ac9a9daSXin Li    }
214*0ac9a9daSXin Li }
215*0ac9a9daSXin Li 
216*0ac9a9daSXin Li 
217*0ac9a9daSXin Li /*---------------------------------------------*/
bsClose(BitStream * bs)218*0ac9a9daSXin Li static void bsClose ( BitStream* bs )
219*0ac9a9daSXin Li {
220*0ac9a9daSXin Li    Int32 retVal;
221*0ac9a9daSXin Li 
222*0ac9a9daSXin Li    if ( bs->mode == 'w' ) {
223*0ac9a9daSXin Li       while ( bs->buffLive < 8 ) {
224*0ac9a9daSXin Li          bs->buffLive++;
225*0ac9a9daSXin Li          bs->buffer <<= 1;
226*0ac9a9daSXin Li       };
227*0ac9a9daSXin Li       retVal = putc ( (UChar) (bs->buffer), bs->handle );
228*0ac9a9daSXin Li       if (retVal == EOF) writeError();
229*0ac9a9daSXin Li       bytesOut++;
230*0ac9a9daSXin Li       retVal = fflush ( bs->handle );
231*0ac9a9daSXin Li       if (retVal == EOF) writeError();
232*0ac9a9daSXin Li    }
233*0ac9a9daSXin Li    retVal = fclose ( bs->handle );
234*0ac9a9daSXin Li    if (retVal == EOF) {
235*0ac9a9daSXin Li       if (bs->mode == 'w') writeError(); else readError();
236*0ac9a9daSXin Li    }
237*0ac9a9daSXin Li    free ( bs );
238*0ac9a9daSXin Li }
239*0ac9a9daSXin Li 
240*0ac9a9daSXin Li 
241*0ac9a9daSXin Li /*---------------------------------------------*/
bsPutUChar(BitStream * bs,UChar c)242*0ac9a9daSXin Li static void bsPutUChar ( BitStream* bs, UChar c )
243*0ac9a9daSXin Li {
244*0ac9a9daSXin Li    Int32 i;
245*0ac9a9daSXin Li    for (i = 7; i >= 0; i--)
246*0ac9a9daSXin Li       bsPutBit ( bs, (((UInt32) c) >> i) & 0x1 );
247*0ac9a9daSXin Li }
248*0ac9a9daSXin Li 
249*0ac9a9daSXin Li 
250*0ac9a9daSXin Li /*---------------------------------------------*/
bsPutUInt32(BitStream * bs,UInt32 c)251*0ac9a9daSXin Li static void bsPutUInt32 ( BitStream* bs, UInt32 c )
252*0ac9a9daSXin Li {
253*0ac9a9daSXin Li    Int32 i;
254*0ac9a9daSXin Li 
255*0ac9a9daSXin Li    for (i = 31; i >= 0; i--)
256*0ac9a9daSXin Li       bsPutBit ( bs, (c >> i) & 0x1 );
257*0ac9a9daSXin Li }
258*0ac9a9daSXin Li 
259*0ac9a9daSXin Li 
260*0ac9a9daSXin Li /*---------------------------------------------*/
endsInBz2(Char * name)261*0ac9a9daSXin Li static Bool endsInBz2 ( Char* name )
262*0ac9a9daSXin Li {
263*0ac9a9daSXin Li    Int32 n = strlen ( name );
264*0ac9a9daSXin Li    if (n <= 4) return False;
265*0ac9a9daSXin Li    return
266*0ac9a9daSXin Li       (name[n-4] == '.' &&
267*0ac9a9daSXin Li        name[n-3] == 'b' &&
268*0ac9a9daSXin Li        name[n-2] == 'z' &&
269*0ac9a9daSXin Li        name[n-1] == '2');
270*0ac9a9daSXin Li }
271*0ac9a9daSXin Li 
272*0ac9a9daSXin Li 
273*0ac9a9daSXin Li /*---------------------------------------------------*/
274*0ac9a9daSXin Li /*---                                             ---*/
275*0ac9a9daSXin Li /*---------------------------------------------------*/
276*0ac9a9daSXin Li 
277*0ac9a9daSXin Li /* This logic isn't really right when it comes to Cygwin. */
278*0ac9a9daSXin Li #ifdef _WIN32
279*0ac9a9daSXin Li #  define  BZ_SPLIT_SYM  '\\'  /* path splitter on Windows platform */
280*0ac9a9daSXin Li #else
281*0ac9a9daSXin Li #  define  BZ_SPLIT_SYM  '/'   /* path splitter on Unix platform */
282*0ac9a9daSXin Li #endif
283*0ac9a9daSXin Li 
284*0ac9a9daSXin Li #define BLOCK_HEADER_HI  0x00003141UL
285*0ac9a9daSXin Li #define BLOCK_HEADER_LO  0x59265359UL
286*0ac9a9daSXin Li 
287*0ac9a9daSXin Li #define BLOCK_ENDMARK_HI 0x00001772UL
288*0ac9a9daSXin Li #define BLOCK_ENDMARK_LO 0x45385090UL
289*0ac9a9daSXin Li 
290*0ac9a9daSXin Li /* Increase if necessary.  However, a .bz2 file with > 50000 blocks
291*0ac9a9daSXin Li    would have an uncompressed size of at least 40GB, so the chances
292*0ac9a9daSXin Li    are low you'll need to up this.
293*0ac9a9daSXin Li */
294*0ac9a9daSXin Li #define BZ_MAX_HANDLED_BLOCKS 50000
295*0ac9a9daSXin Li 
296*0ac9a9daSXin Li MaybeUInt64 bStart [BZ_MAX_HANDLED_BLOCKS];
297*0ac9a9daSXin Li MaybeUInt64 bEnd   [BZ_MAX_HANDLED_BLOCKS];
298*0ac9a9daSXin Li MaybeUInt64 rbStart[BZ_MAX_HANDLED_BLOCKS];
299*0ac9a9daSXin Li MaybeUInt64 rbEnd  [BZ_MAX_HANDLED_BLOCKS];
300*0ac9a9daSXin Li 
main(Int32 argc,Char ** argv)301*0ac9a9daSXin Li Int32 main ( Int32 argc, Char** argv )
302*0ac9a9daSXin Li {
303*0ac9a9daSXin Li    FILE*       inFile;
304*0ac9a9daSXin Li    FILE*       outFile;
305*0ac9a9daSXin Li    BitStream*  bsIn, *bsWr;
306*0ac9a9daSXin Li    Int32       b, wrBlock, currBlock, rbCtr;
307*0ac9a9daSXin Li    MaybeUInt64 bitsRead;
308*0ac9a9daSXin Li 
309*0ac9a9daSXin Li    UInt32      buffHi, buffLo, blockCRC;
310*0ac9a9daSXin Li    Char*       p;
311*0ac9a9daSXin Li 
312*0ac9a9daSXin Li    strncpy ( progName, argv[0], BZ_MAX_FILENAME-1);
313*0ac9a9daSXin Li    progName[BZ_MAX_FILENAME-1]='\0';
314*0ac9a9daSXin Li    inFileName[0] = outFileName[0] = 0;
315*0ac9a9daSXin Li 
316*0ac9a9daSXin Li    fprintf ( stderr,
317*0ac9a9daSXin Li              "bzip2recover 1.0.8: extracts blocks from damaged .bz2 files.\n" );
318*0ac9a9daSXin Li 
319*0ac9a9daSXin Li    if (argc != 2) {
320*0ac9a9daSXin Li       fprintf ( stderr, "%s: usage is `%s damaged_file_name'.\n",
321*0ac9a9daSXin Li                         progName, progName );
322*0ac9a9daSXin Li       switch (sizeof(MaybeUInt64)) {
323*0ac9a9daSXin Li          case 8:
324*0ac9a9daSXin Li             fprintf(stderr,
325*0ac9a9daSXin Li                     "\trestrictions on size of recovered file: None\n");
326*0ac9a9daSXin Li             break;
327*0ac9a9daSXin Li          case 4:
328*0ac9a9daSXin Li             fprintf(stderr,
329*0ac9a9daSXin Li                     "\trestrictions on size of recovered file: 512 MB\n");
330*0ac9a9daSXin Li             fprintf(stderr,
331*0ac9a9daSXin Li                     "\tto circumvent, recompile with MaybeUInt64 as an\n"
332*0ac9a9daSXin Li                     "\tunsigned 64-bit int.\n");
333*0ac9a9daSXin Li             break;
334*0ac9a9daSXin Li          default:
335*0ac9a9daSXin Li             fprintf(stderr,
336*0ac9a9daSXin Li                     "\tsizeof(MaybeUInt64) is not 4 or 8 -- "
337*0ac9a9daSXin Li                     "configuration error.\n");
338*0ac9a9daSXin Li             break;
339*0ac9a9daSXin Li       }
340*0ac9a9daSXin Li       exit(1);
341*0ac9a9daSXin Li    }
342*0ac9a9daSXin Li 
343*0ac9a9daSXin Li    if (strlen(argv[1]) >= BZ_MAX_FILENAME-20) {
344*0ac9a9daSXin Li       fprintf ( stderr,
345*0ac9a9daSXin Li                 "%s: supplied filename is suspiciously (>= %d chars) long.  Bye!\n",
346*0ac9a9daSXin Li                 progName, (int)strlen(argv[1]) );
347*0ac9a9daSXin Li       exit(1);
348*0ac9a9daSXin Li    }
349*0ac9a9daSXin Li 
350*0ac9a9daSXin Li    strcpy ( inFileName, argv[1] );
351*0ac9a9daSXin Li 
352*0ac9a9daSXin Li    inFile = fopen ( inFileName, "rb" );
353*0ac9a9daSXin Li    if (inFile == NULL) {
354*0ac9a9daSXin Li       fprintf ( stderr, "%s: can't read `%s'\n", progName, inFileName );
355*0ac9a9daSXin Li       exit(1);
356*0ac9a9daSXin Li    }
357*0ac9a9daSXin Li 
358*0ac9a9daSXin Li    bsIn = bsOpenReadStream ( inFile );
359*0ac9a9daSXin Li    fprintf ( stderr, "%s: searching for block boundaries ...\n", progName );
360*0ac9a9daSXin Li 
361*0ac9a9daSXin Li    bitsRead = 0;
362*0ac9a9daSXin Li    buffHi = buffLo = 0;
363*0ac9a9daSXin Li    currBlock = 0;
364*0ac9a9daSXin Li    bStart[currBlock] = 0;
365*0ac9a9daSXin Li 
366*0ac9a9daSXin Li    rbCtr = 0;
367*0ac9a9daSXin Li 
368*0ac9a9daSXin Li    while (True) {
369*0ac9a9daSXin Li       b = bsGetBit ( bsIn );
370*0ac9a9daSXin Li       bitsRead++;
371*0ac9a9daSXin Li       if (b == 2) {
372*0ac9a9daSXin Li          if (bitsRead >= bStart[currBlock] &&
373*0ac9a9daSXin Li             (bitsRead - bStart[currBlock]) >= 40) {
374*0ac9a9daSXin Li             bEnd[currBlock] = bitsRead-1;
375*0ac9a9daSXin Li             if (currBlock > 0)
376*0ac9a9daSXin Li                fprintf ( stderr, "   block %d runs from " MaybeUInt64_FMT
377*0ac9a9daSXin Li                                  " to " MaybeUInt64_FMT " (incomplete)\n",
378*0ac9a9daSXin Li                          currBlock,  bStart[currBlock], bEnd[currBlock] );
379*0ac9a9daSXin Li          } else
380*0ac9a9daSXin Li             currBlock--;
381*0ac9a9daSXin Li          break;
382*0ac9a9daSXin Li       }
383*0ac9a9daSXin Li       buffHi = (buffHi << 1) | (buffLo >> 31);
384*0ac9a9daSXin Li       buffLo = (buffLo << 1) | (b & 1);
385*0ac9a9daSXin Li       if ( ( (buffHi & 0x0000ffff) == BLOCK_HEADER_HI
386*0ac9a9daSXin Li              && buffLo == BLOCK_HEADER_LO)
387*0ac9a9daSXin Li            ||
388*0ac9a9daSXin Li            ( (buffHi & 0x0000ffff) == BLOCK_ENDMARK_HI
389*0ac9a9daSXin Li              && buffLo == BLOCK_ENDMARK_LO)
390*0ac9a9daSXin Li          ) {
391*0ac9a9daSXin Li          if (bitsRead > 49) {
392*0ac9a9daSXin Li             bEnd[currBlock] = bitsRead-49;
393*0ac9a9daSXin Li          } else {
394*0ac9a9daSXin Li             bEnd[currBlock] = 0;
395*0ac9a9daSXin Li          }
396*0ac9a9daSXin Li          if (currBlock > 0 &&
397*0ac9a9daSXin Li 	     (bEnd[currBlock] - bStart[currBlock]) >= 130) {
398*0ac9a9daSXin Li             fprintf ( stderr, "   block %d runs from " MaybeUInt64_FMT
399*0ac9a9daSXin Li                               " to " MaybeUInt64_FMT "\n",
400*0ac9a9daSXin Li                       rbCtr+1,  bStart[currBlock], bEnd[currBlock] );
401*0ac9a9daSXin Li             rbStart[rbCtr] = bStart[currBlock];
402*0ac9a9daSXin Li             rbEnd[rbCtr] = bEnd[currBlock];
403*0ac9a9daSXin Li             rbCtr++;
404*0ac9a9daSXin Li          }
405*0ac9a9daSXin Li          if (currBlock >= BZ_MAX_HANDLED_BLOCKS)
406*0ac9a9daSXin Li             tooManyBlocks(BZ_MAX_HANDLED_BLOCKS);
407*0ac9a9daSXin Li          currBlock++;
408*0ac9a9daSXin Li 
409*0ac9a9daSXin Li          bStart[currBlock] = bitsRead;
410*0ac9a9daSXin Li       }
411*0ac9a9daSXin Li    }
412*0ac9a9daSXin Li 
413*0ac9a9daSXin Li    bsClose ( bsIn );
414*0ac9a9daSXin Li 
415*0ac9a9daSXin Li    /*-- identified blocks run from 1 to rbCtr inclusive. --*/
416*0ac9a9daSXin Li 
417*0ac9a9daSXin Li    if (rbCtr < 1) {
418*0ac9a9daSXin Li       fprintf ( stderr,
419*0ac9a9daSXin Li                 "%s: sorry, I couldn't find any block boundaries.\n",
420*0ac9a9daSXin Li                 progName );
421*0ac9a9daSXin Li       exit(1);
422*0ac9a9daSXin Li    };
423*0ac9a9daSXin Li 
424*0ac9a9daSXin Li    fprintf ( stderr, "%s: splitting into blocks\n", progName );
425*0ac9a9daSXin Li 
426*0ac9a9daSXin Li    inFile = fopen ( inFileName, "rb" );
427*0ac9a9daSXin Li    if (inFile == NULL) {
428*0ac9a9daSXin Li       fprintf ( stderr, "%s: can't open `%s'\n", progName, inFileName );
429*0ac9a9daSXin Li       exit(1);
430*0ac9a9daSXin Li    }
431*0ac9a9daSXin Li    bsIn = bsOpenReadStream ( inFile );
432*0ac9a9daSXin Li 
433*0ac9a9daSXin Li    /*-- placate gcc's dataflow analyser --*/
434*0ac9a9daSXin Li    blockCRC = 0; bsWr = 0;
435*0ac9a9daSXin Li 
436*0ac9a9daSXin Li    bitsRead = 0;
437*0ac9a9daSXin Li    outFile = NULL;
438*0ac9a9daSXin Li    wrBlock = 0;
439*0ac9a9daSXin Li    while (True) {
440*0ac9a9daSXin Li       b = bsGetBit(bsIn);
441*0ac9a9daSXin Li       if (b == 2) break;
442*0ac9a9daSXin Li       buffHi = (buffHi << 1) | (buffLo >> 31);
443*0ac9a9daSXin Li       buffLo = (buffLo << 1) | (b & 1);
444*0ac9a9daSXin Li       if (bitsRead == 47+rbStart[wrBlock])
445*0ac9a9daSXin Li          blockCRC = (buffHi << 16) | (buffLo >> 16);
446*0ac9a9daSXin Li 
447*0ac9a9daSXin Li       if (outFile != NULL && bitsRead >= rbStart[wrBlock]
448*0ac9a9daSXin Li                           && bitsRead <= rbEnd[wrBlock]) {
449*0ac9a9daSXin Li          bsPutBit ( bsWr, b );
450*0ac9a9daSXin Li       }
451*0ac9a9daSXin Li 
452*0ac9a9daSXin Li       bitsRead++;
453*0ac9a9daSXin Li 
454*0ac9a9daSXin Li       if (bitsRead == rbEnd[wrBlock]+1) {
455*0ac9a9daSXin Li          if (outFile != NULL) {
456*0ac9a9daSXin Li             bsPutUChar ( bsWr, 0x17 ); bsPutUChar ( bsWr, 0x72 );
457*0ac9a9daSXin Li             bsPutUChar ( bsWr, 0x45 ); bsPutUChar ( bsWr, 0x38 );
458*0ac9a9daSXin Li             bsPutUChar ( bsWr, 0x50 ); bsPutUChar ( bsWr, 0x90 );
459*0ac9a9daSXin Li             bsPutUInt32 ( bsWr, blockCRC );
460*0ac9a9daSXin Li             bsClose ( bsWr );
461*0ac9a9daSXin Li             outFile = NULL;
462*0ac9a9daSXin Li          }
463*0ac9a9daSXin Li          if (wrBlock >= rbCtr) break;
464*0ac9a9daSXin Li          wrBlock++;
465*0ac9a9daSXin Li       } else
466*0ac9a9daSXin Li       if (bitsRead == rbStart[wrBlock]) {
467*0ac9a9daSXin Li          /* Create the output file name, correctly handling leading paths.
468*0ac9a9daSXin Li             (31.10.2001 by Sergey E. Kusikov) */
469*0ac9a9daSXin Li          Char* split;
470*0ac9a9daSXin Li          Int32 ofs, k;
471*0ac9a9daSXin Li          for (k = 0; k < BZ_MAX_FILENAME; k++)
472*0ac9a9daSXin Li             outFileName[k] = 0;
473*0ac9a9daSXin Li          strcpy (outFileName, inFileName);
474*0ac9a9daSXin Li          split = strrchr (outFileName, BZ_SPLIT_SYM);
475*0ac9a9daSXin Li          if (split == NULL) {
476*0ac9a9daSXin Li             split = outFileName;
477*0ac9a9daSXin Li          } else {
478*0ac9a9daSXin Li             ++split;
479*0ac9a9daSXin Li 	 }
480*0ac9a9daSXin Li 	 /* Now split points to the start of the basename. */
481*0ac9a9daSXin Li          ofs  = split - outFileName;
482*0ac9a9daSXin Li          sprintf (split, "rec%5d", wrBlock+1);
483*0ac9a9daSXin Li          for (p = split; *p != 0; p++) if (*p == ' ') *p = '0';
484*0ac9a9daSXin Li          strcat (outFileName, inFileName + ofs);
485*0ac9a9daSXin Li 
486*0ac9a9daSXin Li          if ( !endsInBz2(outFileName)) strcat ( outFileName, ".bz2" );
487*0ac9a9daSXin Li 
488*0ac9a9daSXin Li          fprintf ( stderr, "   writing block %d to `%s' ...\n",
489*0ac9a9daSXin Li                            wrBlock+1, outFileName );
490*0ac9a9daSXin Li 
491*0ac9a9daSXin Li          outFile = fopen ( outFileName, "wb" );
492*0ac9a9daSXin Li          if (outFile == NULL) {
493*0ac9a9daSXin Li             fprintf ( stderr, "%s: can't write `%s'\n",
494*0ac9a9daSXin Li                       progName, outFileName );
495*0ac9a9daSXin Li             exit(1);
496*0ac9a9daSXin Li          }
497*0ac9a9daSXin Li          bsWr = bsOpenWriteStream ( outFile );
498*0ac9a9daSXin Li          bsPutUChar ( bsWr, BZ_HDR_B );
499*0ac9a9daSXin Li          bsPutUChar ( bsWr, BZ_HDR_Z );
500*0ac9a9daSXin Li          bsPutUChar ( bsWr, BZ_HDR_h );
501*0ac9a9daSXin Li          bsPutUChar ( bsWr, BZ_HDR_0 + 9 );
502*0ac9a9daSXin Li          bsPutUChar ( bsWr, 0x31 ); bsPutUChar ( bsWr, 0x41 );
503*0ac9a9daSXin Li          bsPutUChar ( bsWr, 0x59 ); bsPutUChar ( bsWr, 0x26 );
504*0ac9a9daSXin Li          bsPutUChar ( bsWr, 0x53 ); bsPutUChar ( bsWr, 0x59 );
505*0ac9a9daSXin Li       }
506*0ac9a9daSXin Li    }
507*0ac9a9daSXin Li 
508*0ac9a9daSXin Li    fprintf ( stderr, "%s: finished\n", progName );
509*0ac9a9daSXin Li    return 0;
510*0ac9a9daSXin Li }
511*0ac9a9daSXin Li 
512*0ac9a9daSXin Li 
513*0ac9a9daSXin Li 
514*0ac9a9daSXin Li /*-----------------------------------------------------------*/
515*0ac9a9daSXin Li /*--- end                                  bzip2recover.c ---*/
516*0ac9a9daSXin Li /*-----------------------------------------------------------*/
517