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