00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #include <stdio.h>
00056 #include <errno.h>
00057 #include <stdlib.h>
00058 #include <string.h>
00059
00060 typedef unsigned int UInt32;
00061 typedef int Int32;
00062 typedef unsigned char UChar;
00063 typedef char Char;
00064 typedef unsigned char Bool;
00065 #define True ((Bool)1)
00066 #define False ((Bool)0)
00067
00068
00069 Char inFileName[2000];
00070 Char outFileName[2000];
00071 Char progName[2000];
00072
00073 UInt32 bytesOut = 0;
00074 UInt32 bytesIn = 0;
00075
00076
00077
00078
00079
00080
00081
00082 void readError ( void )
00083 {
00084 fprintf ( stderr,
00085 "%s: I/O error reading `%s', possible reason follows.\n",
00086 progName, inFileName );
00087 perror ( progName );
00088 fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
00089 progName );
00090 exit ( 1 );
00091 }
00092
00093
00094
00095 void writeError ( void )
00096 {
00097 fprintf ( stderr,
00098 "%s: I/O error reading `%s', possible reason follows.\n",
00099 progName, inFileName );
00100 perror ( progName );
00101 fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
00102 progName );
00103 exit ( 1 );
00104 }
00105
00106
00107
00108 void mallocFail ( Int32 n )
00109 {
00110 fprintf ( stderr,
00111 "%s: malloc failed on request for %d bytes.\n",
00112 progName, n );
00113 fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
00114 progName );
00115 exit ( 1 );
00116 }
00117
00118
00119
00120
00121
00122
00123 typedef
00124 struct {
00125 FILE* handle;
00126 Int32 buffer;
00127 Int32 buffLive;
00128 Char mode;
00129 }
00130 BitStream;
00131
00132
00133
00134 BitStream* bsOpenReadStream ( FILE* stream )
00135 {
00136 BitStream *bs = malloc ( sizeof(BitStream) );
00137 if (bs == NULL) mallocFail ( sizeof(BitStream) );
00138 bs->handle = stream;
00139 bs->buffer = 0;
00140 bs->buffLive = 0;
00141 bs->mode = 'r';
00142 return bs;
00143 }
00144
00145
00146
00147 BitStream* bsOpenWriteStream ( FILE* stream )
00148 {
00149 BitStream *bs = malloc ( sizeof(BitStream) );
00150 if (bs == NULL) mallocFail ( sizeof(BitStream) );
00151 bs->handle = stream;
00152 bs->buffer = 0;
00153 bs->buffLive = 0;
00154 bs->mode = 'w';
00155 return bs;
00156 }
00157
00158
00159
00160 void bsPutBit ( BitStream* bs, Int32 bit )
00161 {
00162 if (bs->buffLive == 8) {
00163 Int32 retVal = putc ( (UChar) bs->buffer, bs->handle );
00164 if (retVal == EOF) writeError();
00165 bytesOut++;
00166 bs->buffLive = 1;
00167 bs->buffer = bit & 0x1;
00168 } else {
00169 bs->buffer = ( (bs->buffer << 1) | (bit & 0x1) );
00170 bs->buffLive++;
00171 };
00172 }
00173
00174
00175
00176
00177
00178
00179 Int32 bsGetBit ( BitStream* bs )
00180 {
00181 if (bs->buffLive > 0) {
00182 bs->buffLive --;
00183 return ( ((bs->buffer) >> (bs->buffLive)) & 0x1 );
00184 } else {
00185 Int32 retVal = getc ( bs->handle );
00186 if ( retVal == EOF ) {
00187 if (errno != 0) readError();
00188 return 2;
00189 }
00190 bs->buffLive = 7;
00191 bs->buffer = retVal;
00192 return ( ((bs->buffer) >> 7) & 0x1 );
00193 }
00194 }
00195
00196
00197
00198 void bsClose ( BitStream* bs )
00199 {
00200 Int32 retVal;
00201
00202 if ( bs->mode == 'w' ) {
00203 while ( bs->buffLive < 8 ) {
00204 bs->buffLive++;
00205 bs->buffer <<= 1;
00206 };
00207 retVal = putc ( (UChar) (bs->buffer), bs->handle );
00208 if (retVal == EOF) writeError();
00209 bytesOut++;
00210 retVal = fflush ( bs->handle );
00211 if (retVal == EOF) writeError();
00212 }
00213 retVal = fclose ( bs->handle );
00214 if (retVal == EOF) {
00215 if (bs->mode == 'w') writeError(); else readError();
00216 }
00217 free ( bs );
00218 }
00219
00220
00221
00222 void bsPutUChar ( BitStream* bs, UChar c )
00223 {
00224 Int32 i;
00225 for (i = 7; i >= 0; i--)
00226 bsPutBit ( bs, (((UInt32) c) >> i) & 0x1 );
00227 }
00228
00229
00230
00231 void bsPutUInt32 ( BitStream* bs, UInt32 c )
00232 {
00233 Int32 i;
00234
00235 for (i = 31; i >= 0; i--)
00236 bsPutBit ( bs, (c >> i) & 0x1 );
00237 }
00238
00239
00240
00241 Bool endsInBz2 ( Char* name )
00242 {
00243 Int32 n = strlen ( name );
00244 if (n <= 4) return False;
00245 return
00246 (name[n-4] == '.' &&
00247 name[n-3] == 'b' &&
00248 name[n-2] == 'z' &&
00249 name[n-1] == '2');
00250 }
00251
00252
00253
00254
00255
00256
00257 #define BLOCK_HEADER_HI 0x00003141UL
00258 #define BLOCK_HEADER_LO 0x59265359UL
00259
00260 #define BLOCK_ENDMARK_HI 0x00001772UL
00261 #define BLOCK_ENDMARK_LO 0x45385090UL
00262
00263
00264 UInt32 bStart[20000];
00265 UInt32 bEnd[20000];
00266 UInt32 rbStart[20000];
00267 UInt32 rbEnd[20000];
00268
00269 Int32 main ( Int32 argc, Char** argv )
00270 {
00271 FILE* inFile;
00272 FILE* outFile;
00273 BitStream* bsIn, *bsWr;
00274 Int32 currBlock, b, wrBlock;
00275 UInt32 bitsRead;
00276 Int32 rbCtr;
00277
00278
00279 UInt32 buffHi, buffLo, blockCRC;
00280 Char* p;
00281
00282 strcpy ( progName, argv[0] );
00283 inFileName[0] = outFileName[0] = 0;
00284
00285 fprintf ( stderr, "bzip2recover v0.9.5a: extracts blocks from damaged .bz2 files.\n" );
00286
00287 if (argc != 2) {
00288 fprintf ( stderr, "%s: usage is `%s damaged_file_name'.\n",
00289 progName, progName );
00290 exit(1);
00291 }
00292
00293 strcpy ( inFileName, argv[1] );
00294
00295 inFile = fopen ( inFileName, "rb" );
00296 if (inFile == NULL) {
00297 fprintf ( stderr, "%s: can't read `%s'\n", progName, inFileName );
00298 exit(1);
00299 }
00300
00301 bsIn = bsOpenReadStream ( inFile );
00302 fprintf ( stderr, "%s: searching for block boundaries ...\n", progName );
00303
00304 bitsRead = 0;
00305 buffHi = buffLo = 0;
00306 currBlock = 0;
00307 bStart[currBlock] = 0;
00308
00309 rbCtr = 0;
00310
00311 while (True) {
00312 b = bsGetBit ( bsIn );
00313 bitsRead++;
00314 if (b == 2) {
00315 if (bitsRead >= bStart[currBlock] &&
00316 (bitsRead - bStart[currBlock]) >= 40) {
00317 bEnd[currBlock] = bitsRead-1;
00318 if (currBlock > 0)
00319 fprintf ( stderr, " block %d runs from %d to %d (incomplete)\n",
00320 currBlock, bStart[currBlock], bEnd[currBlock] );
00321 } else
00322 currBlock--;
00323 break;
00324 }
00325 buffHi = (buffHi << 1) | (buffLo >> 31);
00326 buffLo = (buffLo << 1) | (b & 1);
00327 if ( ( (buffHi & 0x0000ffff) == BLOCK_HEADER_HI
00328 && buffLo == BLOCK_HEADER_LO)
00329 ||
00330 ( (buffHi & 0x0000ffff) == BLOCK_ENDMARK_HI
00331 && buffLo == BLOCK_ENDMARK_LO)
00332 ) {
00333 if (bitsRead > 49)
00334 bEnd[currBlock] = bitsRead-49; else
00335 bEnd[currBlock] = 0;
00336 if (currBlock > 0 &&
00337 (bEnd[currBlock] - bStart[currBlock]) >= 130) {
00338 fprintf ( stderr, " block %d runs from %d to %d\n",
00339 rbCtr+1, bStart[currBlock], bEnd[currBlock] );
00340 rbStart[rbCtr] = bStart[currBlock];
00341 rbEnd[rbCtr] = bEnd[currBlock];
00342 rbCtr++;
00343 }
00344 currBlock++;
00345
00346 bStart[currBlock] = bitsRead;
00347 }
00348 }
00349
00350 bsClose ( bsIn );
00351
00352
00353
00354 if (rbCtr < 1) {
00355 fprintf ( stderr,
00356 "%s: sorry, I couldn't find any block boundaries.\n",
00357 progName );
00358 exit(1);
00359 };
00360
00361 fprintf ( stderr, "%s: splitting into blocks\n", progName );
00362
00363 inFile = fopen ( inFileName, "rb" );
00364 if (inFile == NULL) {
00365 fprintf ( stderr, "%s: can't open `%s'\n", progName, inFileName );
00366 exit(1);
00367 }
00368 bsIn = bsOpenReadStream ( inFile );
00369
00370
00371 blockCRC = 0; bsWr = 0;
00372
00373 bitsRead = 0;
00374 outFile = NULL;
00375 wrBlock = 0;
00376 while (True) {
00377 b = bsGetBit(bsIn);
00378 if (b == 2) break;
00379 buffHi = (buffHi << 1) | (buffLo >> 31);
00380 buffLo = (buffLo << 1) | (b & 1);
00381 if (bitsRead == 47+rbStart[wrBlock])
00382 blockCRC = (buffHi << 16) | (buffLo >> 16);
00383
00384 if (outFile != NULL && bitsRead >= rbStart[wrBlock]
00385 && bitsRead <= rbEnd[wrBlock]) {
00386 bsPutBit ( bsWr, b );
00387 }
00388
00389 bitsRead++;
00390
00391 if (bitsRead == rbEnd[wrBlock]+1) {
00392 if (outFile != NULL) {
00393 bsPutUChar ( bsWr, 0x17 ); bsPutUChar ( bsWr, 0x72 );
00394 bsPutUChar ( bsWr, 0x45 ); bsPutUChar ( bsWr, 0x38 );
00395 bsPutUChar ( bsWr, 0x50 ); bsPutUChar ( bsWr, 0x90 );
00396 bsPutUInt32 ( bsWr, blockCRC );
00397 bsClose ( bsWr );
00398 }
00399 if (wrBlock >= rbCtr) break;
00400 wrBlock++;
00401 } else
00402 if (bitsRead == rbStart[wrBlock]) {
00403 outFileName[0] = 0;
00404 sprintf ( outFileName, "rec%4d", wrBlock+1 );
00405 for (p = outFileName; *p != 0; p++) if (*p == ' ') *p = '0';
00406 strcat ( outFileName, inFileName );
00407 if ( !endsInBz2(outFileName)) strcat ( outFileName, ".bz2" );
00408
00409 fprintf ( stderr, " writing block %d to `%s' ...\n",
00410 wrBlock+1, outFileName );
00411
00412 outFile = fopen ( outFileName, "wb" );
00413 if (outFile == NULL) {
00414 fprintf ( stderr, "%s: can't write `%s'\n",
00415 progName, outFileName );
00416 exit(1);
00417 }
00418 bsWr = bsOpenWriteStream ( outFile );
00419 bsPutUChar ( bsWr, 'B' ); bsPutUChar ( bsWr, 'Z' );
00420 bsPutUChar ( bsWr, 'h' ); bsPutUChar ( bsWr, '9' );
00421 bsPutUChar ( bsWr, 0x31 ); bsPutUChar ( bsWr, 0x41 );
00422 bsPutUChar ( bsWr, 0x59 ); bsPutUChar ( bsWr, 0x26 );
00423 bsPutUChar ( bsWr, 0x53 ); bsPutUChar ( bsWr, 0x59 );
00424 }
00425 }
00426
00427 fprintf ( stderr, "%s: finished\n", progName );
00428 return 0;
00429 }
00430
00431
00432
00433
00434
00435