xref: /plan9/sys/src/cmd/bzip2/bzip2recover.c (revision 4d44ba9b9ee4246ddbd96c7fcaf0918ab92ab35a)
159cc4ca5SDavid du Colombier 
259cc4ca5SDavid du Colombier /*-----------------------------------------------------------*/
359cc4ca5SDavid du Colombier /*--- Block recoverer program for bzip2                   ---*/
459cc4ca5SDavid du Colombier /*---                                      bzip2recover.c ---*/
559cc4ca5SDavid du Colombier /*-----------------------------------------------------------*/
659cc4ca5SDavid du Colombier 
759cc4ca5SDavid du Colombier /*--
859cc4ca5SDavid du Colombier   This program is bzip2recover, a program to attempt data
959cc4ca5SDavid du Colombier   salvage from damaged files created by the accompanying
1059cc4ca5SDavid du Colombier   bzip2-1.0 program.
1159cc4ca5SDavid du Colombier 
1259cc4ca5SDavid du Colombier   Copyright (C) 1996-2000 Julian R Seward.  All rights reserved.
1359cc4ca5SDavid du Colombier 
1459cc4ca5SDavid du Colombier   Redistribution and use in source and binary forms, with or without
1559cc4ca5SDavid du Colombier   modification, are permitted provided that the following conditions
1659cc4ca5SDavid du Colombier   are met:
1759cc4ca5SDavid du Colombier 
1859cc4ca5SDavid du Colombier   1. Redistributions of source code must retain the above copyright
1959cc4ca5SDavid du Colombier      notice, this list of conditions and the following disclaimer.
2059cc4ca5SDavid du Colombier 
2159cc4ca5SDavid du Colombier   2. The origin of this software must not be misrepresented; you must
2259cc4ca5SDavid du Colombier      not claim that you wrote the original software.  If you use this
2359cc4ca5SDavid du Colombier      software in a product, an acknowledgment in the product
2459cc4ca5SDavid du Colombier      documentation would be appreciated but is not required.
2559cc4ca5SDavid du Colombier 
2659cc4ca5SDavid du Colombier   3. Altered source versions must be plainly marked as such, and must
2759cc4ca5SDavid du Colombier      not be misrepresented as being the original software.
2859cc4ca5SDavid du Colombier 
2959cc4ca5SDavid du Colombier   4. The name of the author may not be used to endorse or promote
3059cc4ca5SDavid du Colombier      products derived from this software without specific prior written
3159cc4ca5SDavid du Colombier      permission.
3259cc4ca5SDavid du Colombier 
3359cc4ca5SDavid du Colombier   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
3459cc4ca5SDavid du Colombier   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3559cc4ca5SDavid du Colombier   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3659cc4ca5SDavid du Colombier   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
3759cc4ca5SDavid du Colombier   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3859cc4ca5SDavid du Colombier   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3959cc4ca5SDavid du Colombier   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
4059cc4ca5SDavid du Colombier   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
4159cc4ca5SDavid du Colombier   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4259cc4ca5SDavid du Colombier   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
4359cc4ca5SDavid du Colombier   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4459cc4ca5SDavid du Colombier 
4559cc4ca5SDavid du Colombier   Julian Seward, Cambridge, UK.
4659cc4ca5SDavid du Colombier   jseward@acm.org
4759cc4ca5SDavid du Colombier   bzip2/libbzip2 version 1.0 of 21 March 2000
4859cc4ca5SDavid du Colombier --*/
4959cc4ca5SDavid du Colombier 
5059cc4ca5SDavid du Colombier /*--
5159cc4ca5SDavid du Colombier   This program is a complete hack and should be rewritten
5259cc4ca5SDavid du Colombier   properly.  It isn't very complicated.
5359cc4ca5SDavid du Colombier --*/
5459cc4ca5SDavid du Colombier 
5559cc4ca5SDavid du Colombier #include <stdio.h>
5659cc4ca5SDavid du Colombier #include <errno.h>
5759cc4ca5SDavid du Colombier #include <stdlib.h>
5859cc4ca5SDavid du Colombier #include <string.h>
5959cc4ca5SDavid du Colombier 
6059cc4ca5SDavid du Colombier typedef  unsigned int   UInt32;
6159cc4ca5SDavid du Colombier typedef  int            Int32;
6259cc4ca5SDavid du Colombier typedef  unsigned char  UChar;
6359cc4ca5SDavid du Colombier typedef  char           Char;
6459cc4ca5SDavid du Colombier typedef  unsigned char  Bool;
6559cc4ca5SDavid du Colombier #define True    ((Bool)1)
6659cc4ca5SDavid du Colombier #define False   ((Bool)0)
6759cc4ca5SDavid du Colombier 
6859cc4ca5SDavid du Colombier 
6959cc4ca5SDavid du Colombier Char inFileName[2000];
7059cc4ca5SDavid du Colombier Char outFileName[2000];
7159cc4ca5SDavid du Colombier Char progName[2000];
7259cc4ca5SDavid du Colombier 
7359cc4ca5SDavid du Colombier UInt32 bytesOut = 0;
7459cc4ca5SDavid du Colombier UInt32 bytesIn  = 0;
7559cc4ca5SDavid du Colombier 
7659cc4ca5SDavid du Colombier 
7759cc4ca5SDavid du Colombier /*---------------------------------------------------*/
7859cc4ca5SDavid du Colombier /*--- I/O errors                                  ---*/
7959cc4ca5SDavid du Colombier /*---------------------------------------------------*/
8059cc4ca5SDavid du Colombier 
8159cc4ca5SDavid du Colombier /*---------------------------------------------*/
readError(void)8259cc4ca5SDavid du Colombier void readError ( void )
8359cc4ca5SDavid du Colombier {
8459cc4ca5SDavid du Colombier    fprintf ( stderr,
8559cc4ca5SDavid du Colombier              "%s: I/O error reading `%s', possible reason follows.\n",
8659cc4ca5SDavid du Colombier             progName, inFileName );
8759cc4ca5SDavid du Colombier    perror ( progName );
8859cc4ca5SDavid du Colombier    fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
8959cc4ca5SDavid du Colombier              progName );
9059cc4ca5SDavid du Colombier    exit ( 1 );
9159cc4ca5SDavid du Colombier }
9259cc4ca5SDavid du Colombier 
9359cc4ca5SDavid du Colombier 
9459cc4ca5SDavid du Colombier /*---------------------------------------------*/
writeError(void)9559cc4ca5SDavid du Colombier void writeError ( void )
9659cc4ca5SDavid du Colombier {
9759cc4ca5SDavid du Colombier    fprintf ( stderr,
9859cc4ca5SDavid du Colombier              "%s: I/O error reading `%s', possible reason follows.\n",
9959cc4ca5SDavid du Colombier             progName, inFileName );
10059cc4ca5SDavid du Colombier    perror ( progName );
10159cc4ca5SDavid du Colombier    fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
10259cc4ca5SDavid du Colombier              progName );
10359cc4ca5SDavid du Colombier    exit ( 1 );
10459cc4ca5SDavid du Colombier }
10559cc4ca5SDavid du Colombier 
10659cc4ca5SDavid du Colombier 
10759cc4ca5SDavid du Colombier /*---------------------------------------------*/
mallocFail(Int32 n)10859cc4ca5SDavid du Colombier void mallocFail ( Int32 n )
10959cc4ca5SDavid du Colombier {
11059cc4ca5SDavid du Colombier    fprintf ( stderr,
11159cc4ca5SDavid du Colombier              "%s: malloc failed on request for %d bytes.\n",
11259cc4ca5SDavid du Colombier             progName, n );
11359cc4ca5SDavid du Colombier    fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
11459cc4ca5SDavid du Colombier              progName );
11559cc4ca5SDavid du Colombier    exit ( 1 );
11659cc4ca5SDavid du Colombier }
11759cc4ca5SDavid du Colombier 
11859cc4ca5SDavid du Colombier 
11959cc4ca5SDavid du Colombier /*---------------------------------------------------*/
12059cc4ca5SDavid du Colombier /*--- Bit stream I/O                              ---*/
12159cc4ca5SDavid du Colombier /*---------------------------------------------------*/
12259cc4ca5SDavid du Colombier 
12359cc4ca5SDavid du Colombier typedef
12459cc4ca5SDavid du Colombier    struct {
12559cc4ca5SDavid du Colombier       FILE*  handle;
12659cc4ca5SDavid du Colombier       Int32  buffer;
12759cc4ca5SDavid du Colombier       Int32  buffLive;
12859cc4ca5SDavid du Colombier       Char   mode;
12959cc4ca5SDavid du Colombier    }
13059cc4ca5SDavid du Colombier    BitStream;
13159cc4ca5SDavid du Colombier 
13259cc4ca5SDavid du Colombier 
13359cc4ca5SDavid du Colombier /*---------------------------------------------*/
bsOpenReadStream(FILE * stream)13459cc4ca5SDavid du Colombier BitStream* bsOpenReadStream ( FILE* stream )
13559cc4ca5SDavid du Colombier {
13659cc4ca5SDavid du Colombier    BitStream *bs = malloc ( sizeof(BitStream) );
13759cc4ca5SDavid du Colombier    if (bs == NULL) mallocFail ( sizeof(BitStream) );
13859cc4ca5SDavid du Colombier    bs->handle = stream;
13959cc4ca5SDavid du Colombier    bs->buffer = 0;
14059cc4ca5SDavid du Colombier    bs->buffLive = 0;
14159cc4ca5SDavid du Colombier    bs->mode = 'r';
14259cc4ca5SDavid du Colombier    return bs;
14359cc4ca5SDavid du Colombier }
14459cc4ca5SDavid du Colombier 
14559cc4ca5SDavid du Colombier 
14659cc4ca5SDavid du Colombier /*---------------------------------------------*/
bsOpenWriteStream(FILE * stream)14759cc4ca5SDavid du Colombier BitStream* bsOpenWriteStream ( FILE* stream )
14859cc4ca5SDavid du Colombier {
14959cc4ca5SDavid du Colombier    BitStream *bs = malloc ( sizeof(BitStream) );
15059cc4ca5SDavid du Colombier    if (bs == NULL) mallocFail ( sizeof(BitStream) );
15159cc4ca5SDavid du Colombier    bs->handle = stream;
15259cc4ca5SDavid du Colombier    bs->buffer = 0;
15359cc4ca5SDavid du Colombier    bs->buffLive = 0;
15459cc4ca5SDavid du Colombier    bs->mode = 'w';
15559cc4ca5SDavid du Colombier    return bs;
15659cc4ca5SDavid du Colombier }
15759cc4ca5SDavid du Colombier 
15859cc4ca5SDavid du Colombier 
15959cc4ca5SDavid du Colombier /*---------------------------------------------*/
bsPutBit(BitStream * bs,Int32 bit)16059cc4ca5SDavid du Colombier void bsPutBit ( BitStream* bs, Int32 bit )
16159cc4ca5SDavid du Colombier {
16259cc4ca5SDavid du Colombier    if (bs->buffLive == 8) {
16359cc4ca5SDavid du Colombier       Int32 retVal = putc ( (UChar) bs->buffer, bs->handle );
16459cc4ca5SDavid du Colombier       if (retVal == EOF) writeError();
16559cc4ca5SDavid du Colombier       bytesOut++;
16659cc4ca5SDavid du Colombier       bs->buffLive = 1;
16759cc4ca5SDavid du Colombier       bs->buffer = bit & 0x1;
16859cc4ca5SDavid du Colombier    } else {
16959cc4ca5SDavid du Colombier       bs->buffer = ( (bs->buffer << 1) | (bit & 0x1) );
17059cc4ca5SDavid du Colombier       bs->buffLive++;
17159cc4ca5SDavid du Colombier    };
17259cc4ca5SDavid du Colombier }
17359cc4ca5SDavid du Colombier 
17459cc4ca5SDavid du Colombier 
17559cc4ca5SDavid du Colombier /*---------------------------------------------*/
17659cc4ca5SDavid du Colombier /*--
17759cc4ca5SDavid du Colombier    Returns 0 or 1, or 2 to indicate EOF.
17859cc4ca5SDavid du Colombier --*/
bsGetBit(BitStream * bs)17959cc4ca5SDavid du Colombier Int32 bsGetBit ( BitStream* bs )
18059cc4ca5SDavid du Colombier {
18159cc4ca5SDavid du Colombier    if (bs->buffLive > 0) {
18259cc4ca5SDavid du Colombier       bs->buffLive --;
18359cc4ca5SDavid du Colombier       return ( ((bs->buffer) >> (bs->buffLive)) & 0x1 );
18459cc4ca5SDavid du Colombier    } else {
18559cc4ca5SDavid du Colombier       Int32 retVal = getc ( bs->handle );
18659cc4ca5SDavid du Colombier       if ( retVal == EOF ) {
18759cc4ca5SDavid du Colombier          if (errno != 0) readError();
18859cc4ca5SDavid du Colombier          return 2;
18959cc4ca5SDavid du Colombier       }
19059cc4ca5SDavid du Colombier       bs->buffLive = 7;
19159cc4ca5SDavid du Colombier       bs->buffer = retVal;
19259cc4ca5SDavid du Colombier       return ( ((bs->buffer) >> 7) & 0x1 );
19359cc4ca5SDavid du Colombier    }
19459cc4ca5SDavid du Colombier }
19559cc4ca5SDavid du Colombier 
19659cc4ca5SDavid du Colombier 
19759cc4ca5SDavid du Colombier /*---------------------------------------------*/
bsClose(BitStream * bs)19859cc4ca5SDavid du Colombier void bsClose ( BitStream* bs )
19959cc4ca5SDavid du Colombier {
20059cc4ca5SDavid du Colombier    Int32 retVal;
20159cc4ca5SDavid du Colombier 
20259cc4ca5SDavid du Colombier    if ( bs->mode == 'w' ) {
20359cc4ca5SDavid du Colombier       while ( bs->buffLive < 8 ) {
20459cc4ca5SDavid du Colombier          bs->buffLive++;
20559cc4ca5SDavid du Colombier          bs->buffer <<= 1;
20659cc4ca5SDavid du Colombier       };
20759cc4ca5SDavid du Colombier       retVal = putc ( (UChar) (bs->buffer), bs->handle );
20859cc4ca5SDavid du Colombier       if (retVal == EOF) writeError();
20959cc4ca5SDavid du Colombier       bytesOut++;
21059cc4ca5SDavid du Colombier       retVal = fflush ( bs->handle );
21159cc4ca5SDavid du Colombier       if (retVal == EOF) writeError();
21259cc4ca5SDavid du Colombier    }
21359cc4ca5SDavid du Colombier    retVal = fclose ( bs->handle );
21459cc4ca5SDavid du Colombier    if (retVal == EOF) {
21559cc4ca5SDavid du Colombier       if (bs->mode == 'w') writeError(); else readError();
21659cc4ca5SDavid du Colombier    }
21759cc4ca5SDavid du Colombier    free ( bs );
21859cc4ca5SDavid du Colombier }
21959cc4ca5SDavid du Colombier 
22059cc4ca5SDavid du Colombier 
22159cc4ca5SDavid du Colombier /*---------------------------------------------*/
bsPutUChar(BitStream * bs,UChar c)22259cc4ca5SDavid du Colombier void bsPutUChar ( BitStream* bs, UChar c )
22359cc4ca5SDavid du Colombier {
22459cc4ca5SDavid du Colombier    Int32 i;
22559cc4ca5SDavid du Colombier    for (i = 7; i >= 0; i--)
22659cc4ca5SDavid du Colombier       bsPutBit ( bs, (((UInt32) c) >> i) & 0x1 );
22759cc4ca5SDavid du Colombier }
22859cc4ca5SDavid du Colombier 
22959cc4ca5SDavid du Colombier 
23059cc4ca5SDavid du Colombier /*---------------------------------------------*/
bsPutUInt32(BitStream * bs,UInt32 c)23159cc4ca5SDavid du Colombier void bsPutUInt32 ( BitStream* bs, UInt32 c )
23259cc4ca5SDavid du Colombier {
23359cc4ca5SDavid du Colombier    Int32 i;
23459cc4ca5SDavid du Colombier 
23559cc4ca5SDavid du Colombier    for (i = 31; i >= 0; i--)
23659cc4ca5SDavid du Colombier       bsPutBit ( bs, (c >> i) & 0x1 );
23759cc4ca5SDavid du Colombier }
23859cc4ca5SDavid du Colombier 
23959cc4ca5SDavid du Colombier 
24059cc4ca5SDavid du Colombier /*---------------------------------------------*/
endsInBz2(Char * name)24159cc4ca5SDavid du Colombier Bool endsInBz2 ( Char* name )
24259cc4ca5SDavid du Colombier {
24359cc4ca5SDavid du Colombier    Int32 n = strlen ( name );
24459cc4ca5SDavid du Colombier    if (n <= 4) return False;
24559cc4ca5SDavid du Colombier    return
24659cc4ca5SDavid du Colombier       (name[n-4] == '.' &&
24759cc4ca5SDavid du Colombier        name[n-3] == 'b' &&
24859cc4ca5SDavid du Colombier        name[n-2] == 'z' &&
24959cc4ca5SDavid du Colombier        name[n-1] == '2');
25059cc4ca5SDavid du Colombier }
25159cc4ca5SDavid du Colombier 
25259cc4ca5SDavid du Colombier 
25359cc4ca5SDavid du Colombier /*---------------------------------------------------*/
25459cc4ca5SDavid du Colombier /*---                                             ---*/
25559cc4ca5SDavid du Colombier /*---------------------------------------------------*/
25659cc4ca5SDavid du Colombier 
25759cc4ca5SDavid du Colombier #define BLOCK_HEADER_HI  0x00003141UL
25859cc4ca5SDavid du Colombier #define BLOCK_HEADER_LO  0x59265359UL
25959cc4ca5SDavid du Colombier 
26059cc4ca5SDavid du Colombier #define BLOCK_ENDMARK_HI 0x00001772UL
26159cc4ca5SDavid du Colombier #define BLOCK_ENDMARK_LO 0x45385090UL
26259cc4ca5SDavid du Colombier 
26359cc4ca5SDavid du Colombier 
26459cc4ca5SDavid du Colombier UInt32 bStart[20000];
26559cc4ca5SDavid du Colombier UInt32 bEnd[20000];
26659cc4ca5SDavid du Colombier UInt32 rbStart[20000];
26759cc4ca5SDavid du Colombier UInt32 rbEnd[20000];
26859cc4ca5SDavid du Colombier 
main(Int32 argc,Char ** argv)26959cc4ca5SDavid du Colombier Int32 main ( Int32 argc, Char** argv )
27059cc4ca5SDavid du Colombier {
27159cc4ca5SDavid du Colombier    FILE*       inFile;
27259cc4ca5SDavid du Colombier    FILE*       outFile;
27359cc4ca5SDavid du Colombier    BitStream*  bsIn, *bsWr;
27459cc4ca5SDavid du Colombier    Int32       currBlock, b, wrBlock;
27559cc4ca5SDavid du Colombier    UInt32      bitsRead;
27659cc4ca5SDavid du Colombier    Int32       rbCtr;
27759cc4ca5SDavid du Colombier 
27859cc4ca5SDavid du Colombier 
27959cc4ca5SDavid du Colombier    UInt32      buffHi, buffLo, blockCRC;
28059cc4ca5SDavid du Colombier    Char*       p;
28159cc4ca5SDavid du Colombier 
282*4d44ba9bSDavid du Colombier    strncpy ( progName, argv[0], sizeof progName );
283*4d44ba9bSDavid du Colombier    progName[sizeof progName-1] = 0;
28459cc4ca5SDavid du Colombier    inFileName[0] = outFileName[0] = 0;
28559cc4ca5SDavid du Colombier 
28659cc4ca5SDavid du Colombier    fprintf ( stderr, "bzip2recover 1.0: extracts blocks from damaged .bz2 files.\n" );
28759cc4ca5SDavid du Colombier 
28859cc4ca5SDavid du Colombier    if (argc != 2) {
28959cc4ca5SDavid du Colombier       fprintf ( stderr, "%s: usage is `%s damaged_file_name'.\n",
29059cc4ca5SDavid du Colombier                         progName, progName );
29159cc4ca5SDavid du Colombier       exit(1);
29259cc4ca5SDavid du Colombier    }
29359cc4ca5SDavid du Colombier 
29459cc4ca5SDavid du Colombier    strcpy ( inFileName, argv[1] );
29559cc4ca5SDavid du Colombier 
29659cc4ca5SDavid du Colombier    inFile = fopen ( inFileName, "rb" );
29759cc4ca5SDavid du Colombier    if (inFile == NULL) {
29859cc4ca5SDavid du Colombier       fprintf ( stderr, "%s: can't read `%s'\n", progName, inFileName );
29959cc4ca5SDavid du Colombier       exit(1);
30059cc4ca5SDavid du Colombier    }
30159cc4ca5SDavid du Colombier 
30259cc4ca5SDavid du Colombier    bsIn = bsOpenReadStream ( inFile );
30359cc4ca5SDavid du Colombier    fprintf ( stderr, "%s: searching for block boundaries ...\n", progName );
30459cc4ca5SDavid du Colombier 
30559cc4ca5SDavid du Colombier    bitsRead = 0;
30659cc4ca5SDavid du Colombier    buffHi = buffLo = 0;
30759cc4ca5SDavid du Colombier    currBlock = 0;
30859cc4ca5SDavid du Colombier    bStart[currBlock] = 0;
30959cc4ca5SDavid du Colombier 
31059cc4ca5SDavid du Colombier    rbCtr = 0;
31159cc4ca5SDavid du Colombier 
31259cc4ca5SDavid du Colombier    while (True) {
31359cc4ca5SDavid du Colombier       b = bsGetBit ( bsIn );
31459cc4ca5SDavid du Colombier       bitsRead++;
31559cc4ca5SDavid du Colombier       if (b == 2) {
31659cc4ca5SDavid du Colombier          if (bitsRead >= bStart[currBlock] &&
31759cc4ca5SDavid du Colombier             (bitsRead - bStart[currBlock]) >= 40) {
31859cc4ca5SDavid du Colombier             bEnd[currBlock] = bitsRead-1;
31959cc4ca5SDavid du Colombier             if (currBlock > 0)
32059cc4ca5SDavid du Colombier                fprintf ( stderr, "   block %d runs from %d to %d (incomplete)\n",
32159cc4ca5SDavid du Colombier                          currBlock,  bStart[currBlock], bEnd[currBlock] );
32259cc4ca5SDavid du Colombier          } else
32359cc4ca5SDavid du Colombier             currBlock--;
32459cc4ca5SDavid du Colombier          break;
32559cc4ca5SDavid du Colombier       }
32659cc4ca5SDavid du Colombier       buffHi = (buffHi << 1) | (buffLo >> 31);
32759cc4ca5SDavid du Colombier       buffLo = (buffLo << 1) | (b & 1);
32859cc4ca5SDavid du Colombier       if ( ( (buffHi & 0x0000ffff) == BLOCK_HEADER_HI
32959cc4ca5SDavid du Colombier              && buffLo == BLOCK_HEADER_LO)
33059cc4ca5SDavid du Colombier            ||
33159cc4ca5SDavid du Colombier            ( (buffHi & 0x0000ffff) == BLOCK_ENDMARK_HI
33259cc4ca5SDavid du Colombier              && buffLo == BLOCK_ENDMARK_LO)
33359cc4ca5SDavid du Colombier          ) {
33459cc4ca5SDavid du Colombier          if (bitsRead > 49)
33559cc4ca5SDavid du Colombier             bEnd[currBlock] = bitsRead-49; else
33659cc4ca5SDavid du Colombier             bEnd[currBlock] = 0;
33759cc4ca5SDavid du Colombier          if (currBlock > 0 &&
33859cc4ca5SDavid du Colombier 	     (bEnd[currBlock] - bStart[currBlock]) >= 130) {
33959cc4ca5SDavid du Colombier             fprintf ( stderr, "   block %d runs from %d to %d\n",
34059cc4ca5SDavid du Colombier                       rbCtr+1,  bStart[currBlock], bEnd[currBlock] );
34159cc4ca5SDavid du Colombier             rbStart[rbCtr] = bStart[currBlock];
34259cc4ca5SDavid du Colombier             rbEnd[rbCtr] = bEnd[currBlock];
34359cc4ca5SDavid du Colombier             rbCtr++;
34459cc4ca5SDavid du Colombier          }
34559cc4ca5SDavid du Colombier          currBlock++;
34659cc4ca5SDavid du Colombier 
34759cc4ca5SDavid du Colombier          bStart[currBlock] = bitsRead;
34859cc4ca5SDavid du Colombier       }
34959cc4ca5SDavid du Colombier    }
35059cc4ca5SDavid du Colombier 
35159cc4ca5SDavid du Colombier    bsClose ( bsIn );
35259cc4ca5SDavid du Colombier 
35359cc4ca5SDavid du Colombier    /*-- identified blocks run from 1 to rbCtr inclusive. --*/
35459cc4ca5SDavid du Colombier 
35559cc4ca5SDavid du Colombier    if (rbCtr < 1) {
35659cc4ca5SDavid du Colombier       fprintf ( stderr,
35759cc4ca5SDavid du Colombier                 "%s: sorry, I couldn't find any block boundaries.\n",
35859cc4ca5SDavid du Colombier                 progName );
35959cc4ca5SDavid du Colombier       exit(1);
36059cc4ca5SDavid du Colombier    };
36159cc4ca5SDavid du Colombier 
36259cc4ca5SDavid du Colombier    fprintf ( stderr, "%s: splitting into blocks\n", progName );
36359cc4ca5SDavid du Colombier 
36459cc4ca5SDavid du Colombier    inFile = fopen ( inFileName, "rb" );
36559cc4ca5SDavid du Colombier    if (inFile == NULL) {
36659cc4ca5SDavid du Colombier       fprintf ( stderr, "%s: can't open `%s'\n", progName, inFileName );
36759cc4ca5SDavid du Colombier       exit(1);
36859cc4ca5SDavid du Colombier    }
36959cc4ca5SDavid du Colombier    bsIn = bsOpenReadStream ( inFile );
37059cc4ca5SDavid du Colombier 
37159cc4ca5SDavid du Colombier    /*-- placate gcc's dataflow analyser --*/
37259cc4ca5SDavid du Colombier    blockCRC = 0; bsWr = 0;
37359cc4ca5SDavid du Colombier 
37459cc4ca5SDavid du Colombier    bitsRead = 0;
37559cc4ca5SDavid du Colombier    outFile = NULL;
37659cc4ca5SDavid du Colombier    wrBlock = 0;
37759cc4ca5SDavid du Colombier    while (True) {
37859cc4ca5SDavid du Colombier       b = bsGetBit(bsIn);
37959cc4ca5SDavid du Colombier       if (b == 2) break;
38059cc4ca5SDavid du Colombier       buffHi = (buffHi << 1) | (buffLo >> 31);
38159cc4ca5SDavid du Colombier       buffLo = (buffLo << 1) | (b & 1);
38259cc4ca5SDavid du Colombier       if (bitsRead == 47+rbStart[wrBlock])
38359cc4ca5SDavid du Colombier          blockCRC = (buffHi << 16) | (buffLo >> 16);
38459cc4ca5SDavid du Colombier 
38559cc4ca5SDavid du Colombier       if (outFile != NULL && bitsRead >= rbStart[wrBlock]
38659cc4ca5SDavid du Colombier                           && bitsRead <= rbEnd[wrBlock]) {
38759cc4ca5SDavid du Colombier          bsPutBit ( bsWr, b );
38859cc4ca5SDavid du Colombier       }
38959cc4ca5SDavid du Colombier 
39059cc4ca5SDavid du Colombier       bitsRead++;
39159cc4ca5SDavid du Colombier 
39259cc4ca5SDavid du Colombier       if (bitsRead == rbEnd[wrBlock]+1) {
39359cc4ca5SDavid du Colombier          if (outFile != NULL) {
39459cc4ca5SDavid du Colombier             bsPutUChar ( bsWr, 0x17 ); bsPutUChar ( bsWr, 0x72 );
39559cc4ca5SDavid du Colombier             bsPutUChar ( bsWr, 0x45 ); bsPutUChar ( bsWr, 0x38 );
39659cc4ca5SDavid du Colombier             bsPutUChar ( bsWr, 0x50 ); bsPutUChar ( bsWr, 0x90 );
39759cc4ca5SDavid du Colombier             bsPutUInt32 ( bsWr, blockCRC );
39859cc4ca5SDavid du Colombier             bsClose ( bsWr );
39959cc4ca5SDavid du Colombier          }
40059cc4ca5SDavid du Colombier          if (wrBlock >= rbCtr) break;
40159cc4ca5SDavid du Colombier          wrBlock++;
40259cc4ca5SDavid du Colombier       } else
40359cc4ca5SDavid du Colombier       if (bitsRead == rbStart[wrBlock]) {
40459cc4ca5SDavid du Colombier          outFileName[0] = 0;
40559cc4ca5SDavid du Colombier          sprintf ( outFileName, "rec%4d", wrBlock+1 );
40659cc4ca5SDavid du Colombier          for (p = outFileName; *p != 0; p++) if (*p == ' ') *p = '0';
40759cc4ca5SDavid du Colombier          strcat ( outFileName, inFileName );
40859cc4ca5SDavid du Colombier          if ( !endsInBz2(outFileName)) strcat ( outFileName, ".bz2" );
40959cc4ca5SDavid du Colombier 
41059cc4ca5SDavid du Colombier          fprintf ( stderr, "   writing block %d to `%s' ...\n",
41159cc4ca5SDavid du Colombier                            wrBlock+1, outFileName );
41259cc4ca5SDavid du Colombier 
41359cc4ca5SDavid du Colombier          outFile = fopen ( outFileName, "wb" );
41459cc4ca5SDavid du Colombier          if (outFile == NULL) {
41559cc4ca5SDavid du Colombier             fprintf ( stderr, "%s: can't write `%s'\n",
41659cc4ca5SDavid du Colombier                       progName, outFileName );
41759cc4ca5SDavid du Colombier             exit(1);
41859cc4ca5SDavid du Colombier          }
41959cc4ca5SDavid du Colombier          bsWr = bsOpenWriteStream ( outFile );
42059cc4ca5SDavid du Colombier          bsPutUChar ( bsWr, 'B' ); bsPutUChar ( bsWr, 'Z' );
42159cc4ca5SDavid du Colombier          bsPutUChar ( bsWr, 'h' ); bsPutUChar ( bsWr, '9' );
42259cc4ca5SDavid du Colombier          bsPutUChar ( bsWr, 0x31 ); bsPutUChar ( bsWr, 0x41 );
42359cc4ca5SDavid du Colombier          bsPutUChar ( bsWr, 0x59 ); bsPutUChar ( bsWr, 0x26 );
42459cc4ca5SDavid du Colombier          bsPutUChar ( bsWr, 0x53 ); bsPutUChar ( bsWr, 0x59 );
42559cc4ca5SDavid du Colombier       }
42659cc4ca5SDavid du Colombier    }
42759cc4ca5SDavid du Colombier 
42859cc4ca5SDavid du Colombier    fprintf ( stderr, "%s: finished\n", progName );
42959cc4ca5SDavid du Colombier    return 0;
43059cc4ca5SDavid du Colombier }
43159cc4ca5SDavid du Colombier 
43259cc4ca5SDavid du Colombier 
43359cc4ca5SDavid du Colombier 
43459cc4ca5SDavid du Colombier /*-----------------------------------------------------------*/
43559cc4ca5SDavid du Colombier /*--- end                                  bzip2recover.c ---*/
43659cc4ca5SDavid du Colombier /*-----------------------------------------------------------*/
437