bzip2recover.c revision 90067
1155192Srwatson 2155192Srwatson/*-----------------------------------------------------------*/ 3155192Srwatson/*--- Block recoverer program for bzip2 ---*/ 4155192Srwatson/*--- bzip2recover.c ---*/ 5155192Srwatson/*-----------------------------------------------------------*/ 6155192Srwatson 7155192Srwatson/*-- 8155192Srwatson This program is bzip2recover, a program to attempt data 9155192Srwatson salvage from damaged files created by the accompanying 10155192Srwatson bzip2-1.0 program. 11155192Srwatson 12155192Srwatson Copyright (C) 1996-2002 Julian R Seward. All rights reserved. 13155192Srwatson 14155192Srwatson Redistribution and use in source and binary forms, with or without 15155192Srwatson modification, are permitted provided that the following conditions 16155192Srwatson are met: 17155192Srwatson 18155192Srwatson 1. Redistributions of source code must retain the above copyright 19155192Srwatson notice, this list of conditions and the following disclaimer. 20155192Srwatson 21155192Srwatson 2. The origin of this software must not be misrepresented; you must 22155192Srwatson not claim that you wrote the original software. If you use this 23155192Srwatson software in a product, an acknowledgment in the product 24155192Srwatson documentation would be appreciated but is not required. 25155192Srwatson 26155192Srwatson 3. Altered source versions must be plainly marked as such, and must 27155192Srwatson not be misrepresented as being the original software. 28155192Srwatson 29155192Srwatson 4. The name of the author may not be used to endorse or promote 30155192Srwatson products derived from this software without specific prior written 31155192Srwatson permission. 32155192Srwatson 33155192Srwatson THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 34155192Srwatson OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 35155192Srwatson WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 36155192Srwatson ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 37155192Srwatson DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 38155192Srwatson DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 39155192Srwatson GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 40155192Srwatson INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 41155192Srwatson WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 42155192Srwatson NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 43155192Srwatson SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 44155192Srwatson 45155192Srwatson Julian Seward, Cambridge, UK. 46155192Srwatson jseward@acm.org 47155192Srwatson bzip2/libbzip2 version 1.0 of 21 March 2000 48155192Srwatson--*/ 49155192Srwatson 50155192Srwatson/*-- 51155192Srwatson This program is a complete hack and should be rewritten 52155192Srwatson properly. It isn't very complicated. 53155192Srwatson--*/ 54155192Srwatson 55155192Srwatson#include <stdio.h> 56155192Srwatson#include <errno.h> 57155192Srwatson#include <stdlib.h> 58155192Srwatson#include <string.h> 59155192Srwatson 60155192Srwatson 61155192Srwatson/* This program records bit locations in the file to be recovered. 62155192Srwatson That means that if 64-bit ints are not supported, we will not 63155192Srwatson be able to recover .bz2 files over 512MB (2^32 bits) long. 64155192Srwatson On GNU supported platforms, we take advantage of the 64-bit 65155192Srwatson int support to circumvent this problem. Ditto MSVC. 66156889Srwatson 67156889Srwatson This change occurred in version 1.0.2; all prior versions have 68155192Srwatson the 512MB limitation. 69155192Srwatson*/ 70155192Srwatson#ifdef __GNUC__ 71155192Srwatson typedef unsigned long long int MaybeUInt64; 72155192Srwatson# define MaybeUInt64_FMT "%Lu" 73155192Srwatson#else 74155192Srwatson#ifdef _MSC_VER 75155192Srwatson typedef unsigned __int64 MaybeUInt64; 76155192Srwatson# define MaybeUInt64_FMT "%I64u" 77155192Srwatson#else 78155192Srwatson typedef unsigned int MaybeUInt64; 79155192Srwatson# define MaybeUInt64_FMT "%u" 80155192Srwatson#endif 81173142Srwatson#endif 82155192Srwatson 83155192Srwatsontypedef unsigned int UInt32; 84155192Srwatsontypedef int Int32; 85155192Srwatsontypedef unsigned char UChar; 86155192Srwatsontypedef char Char; 87155192Srwatsontypedef unsigned char Bool; 88155192Srwatson#define True ((Bool)1) 89155192Srwatson#define False ((Bool)0) 90155192Srwatson 91155192Srwatson 92155192Srwatson#define BZ_MAX_FILENAME 2000 93156889Srwatson 94155192SrwatsonChar inFileName[BZ_MAX_FILENAME]; 95155192SrwatsonChar outFileName[BZ_MAX_FILENAME]; 96156889SrwatsonChar progName[BZ_MAX_FILENAME]; 97155192Srwatson 98156889SrwatsonMaybeUInt64 bytesOut = 0; 99155192SrwatsonMaybeUInt64 bytesIn = 0; 100155192Srwatson 101156889Srwatson 102155192Srwatson/*---------------------------------------------------*/ 103155192Srwatson/*--- Header bytes ---*/ 104155192Srwatson/*---------------------------------------------------*/ 105155192Srwatson 106155192Srwatson#define BZ_HDR_B 0x42 /* 'B' */ 107155192Srwatson#define BZ_HDR_Z 0x5a /* 'Z' */ 108155192Srwatson#define BZ_HDR_h 0x68 /* 'h' */ 109155192Srwatson#define BZ_HDR_0 0x30 /* '0' */ 110155192Srwatson 111155192Srwatson 112155192Srwatson/*---------------------------------------------------*/ 113155192Srwatson/*--- I/O errors ---*/ 114155192Srwatson/*---------------------------------------------------*/ 115155192Srwatson 116155192Srwatson/*---------------------------------------------*/ 117155192Srwatsonvoid readError ( void ) 118155192Srwatson{ 119155192Srwatson fprintf ( stderr, 120155192Srwatson "%s: I/O error reading `%s', possible reason follows.\n", 121155192Srwatson progName, inFileName ); 122155192Srwatson perror ( progName ); 123155192Srwatson fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n", 124155192Srwatson progName ); 125155192Srwatson exit ( 1 ); 126155192Srwatson} 127155192Srwatson 128155192Srwatson 129155192Srwatson/*---------------------------------------------*/ 130156889Srwatsonvoid writeError ( void ) 131155192Srwatson{ 132155192Srwatson fprintf ( stderr, 133155192Srwatson "%s: I/O error reading `%s', possible reason follows.\n", 134155192Srwatson progName, inFileName ); 135155192Srwatson perror ( progName ); 136155192Srwatson fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n", 137155192Srwatson progName ); 138155192Srwatson exit ( 1 ); 139155192Srwatson} 140155192Srwatson 141155192Srwatson 142155192Srwatson/*---------------------------------------------*/ 143155192Srwatsonvoid mallocFail ( Int32 n ) 144155192Srwatson{ 145156889Srwatson fprintf ( stderr, 146155192Srwatson "%s: malloc failed on request for %d bytes.\n", 147155192Srwatson progName, n ); 148173142Srwatson fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n", 149155192Srwatson progName ); 150155192Srwatson exit ( 1 ); 151155192Srwatson} 152155192Srwatson 153155192Srwatson 154155192Srwatson/*---------------------------------------------*/ 155155192Srwatsonvoid tooManyBlocks ( Int32 max_handled_blocks ) 156155192Srwatson{ 157159269Srwatson fprintf ( stderr, 158155192Srwatson "%s: `%s' appears to contain more than %d blocks\n", 159155192Srwatson progName, inFileName, max_handled_blocks ); 160155192Srwatson fprintf ( stderr, 161155192Srwatson "%s: and cannot be handled. To fix, increase\n", 162155192Srwatson progName ); 163155192Srwatson fprintf ( stderr, 164156889Srwatson "%s: BZ_MAX_HANDLED_BLOCKS in bzip2recover.c, and recompile.\n", 165155192Srwatson progName ); 166155192Srwatson exit ( 1 ); 167155192Srwatson} 168159269Srwatson 169156889Srwatson 170155192Srwatson 171159269Srwatson/*---------------------------------------------------*/ 172156889Srwatson/*--- Bit stream I/O ---*/ 173155192Srwatson/*---------------------------------------------------*/ 174155192Srwatson 175156889Srwatsontypedef 176155192Srwatson struct { 177155192Srwatson FILE* handle; 178155192Srwatson Int32 buffer; 179155192Srwatson Int32 buffLive; 180156889Srwatson Char mode; 181155192Srwatson } 182155192Srwatson BitStream; 183155192Srwatson 184155192Srwatson 185155192Srwatson/*---------------------------------------------*/ 186155192SrwatsonBitStream* bsOpenReadStream ( FILE* stream ) 187156889Srwatson{ 188155192Srwatson BitStream *bs = malloc ( sizeof(BitStream) ); 189155192Srwatson if (bs == NULL) mallocFail ( sizeof(BitStream) ); 190155192Srwatson bs->handle = stream; 191155192Srwatson bs->buffer = 0; 192155192Srwatson bs->buffLive = 0; 193155192Srwatson bs->mode = 'r'; 194155192Srwatson return bs; 195155192Srwatson} 196155192Srwatson 197155192Srwatson 198155192Srwatson/*---------------------------------------------*/ 199155192SrwatsonBitStream* bsOpenWriteStream ( FILE* stream ) 200155192Srwatson{ 201155192Srwatson BitStream *bs = malloc ( sizeof(BitStream) ); 202155192Srwatson if (bs == NULL) mallocFail ( sizeof(BitStream) ); 203155192Srwatson bs->handle = stream; 204155192Srwatson bs->buffer = 0; 205155192Srwatson bs->buffLive = 0; 206155192Srwatson bs->mode = 'w'; 207155192Srwatson return bs; 208155192Srwatson} 209155192Srwatson 210155192Srwatson 211155192Srwatson/*---------------------------------------------*/ 212155192Srwatsonvoid bsPutBit ( BitStream* bs, Int32 bit ) 213155192Srwatson{ 214155192Srwatson if (bs->buffLive == 8) { 215155192Srwatson Int32 retVal = putc ( (UChar) bs->buffer, bs->handle ); 216155192Srwatson if (retVal == EOF) writeError(); 217155192Srwatson bytesOut++; 218155192Srwatson bs->buffLive = 1; 219155192Srwatson bs->buffer = bit & 0x1; 220155192Srwatson } else { 221155192Srwatson bs->buffer = ( (bs->buffer << 1) | (bit & 0x1) ); 222155192Srwatson bs->buffLive++; 223155192Srwatson }; 224155192Srwatson} 225155192Srwatson 226155192Srwatson 227155192Srwatson/*---------------------------------------------*/ 228155192Srwatson/*-- 229155192Srwatson Returns 0 or 1, or 2 to indicate EOF. 230155192Srwatson--*/ 231155192SrwatsonInt32 bsGetBit ( BitStream* bs ) 232155192Srwatson{ 233155192Srwatson if (bs->buffLive > 0) { 234155192Srwatson bs->buffLive --; 235155192Srwatson return ( ((bs->buffer) >> (bs->buffLive)) & 0x1 ); 236155192Srwatson } else { 237155192Srwatson Int32 retVal = getc ( bs->handle ); 238155192Srwatson if ( retVal == EOF ) { 239155192Srwatson if (errno != 0) readError(); 240155192Srwatson return 2; 241156889Srwatson } 242155192Srwatson bs->buffLive = 7; 243155192Srwatson bs->buffer = retVal; 244155192Srwatson return ( ((bs->buffer) >> 7) & 0x1 ); 245156889Srwatson } 246156889Srwatson} 247155192Srwatson 248155192Srwatson 249156889Srwatson/*---------------------------------------------*/ 250156889Srwatsonvoid bsClose ( BitStream* bs ) 251156889Srwatson{ 252155192Srwatson Int32 retVal; 253155192Srwatson 254155192Srwatson if ( bs->mode == 'w' ) { 255155192Srwatson while ( bs->buffLive < 8 ) { 256155192Srwatson bs->buffLive++; 257155192Srwatson bs->buffer <<= 1; 258155192Srwatson }; 259155192Srwatson retVal = putc ( (UChar) (bs->buffer), bs->handle ); 260155192Srwatson if (retVal == EOF) writeError(); 261155192Srwatson bytesOut++; 262155192Srwatson retVal = fflush ( bs->handle ); 263155192Srwatson if (retVal == EOF) writeError(); 264155192Srwatson } 265155192Srwatson retVal = fclose ( bs->handle ); 266155192Srwatson if (retVal == EOF) { 267155192Srwatson if (bs->mode == 'w') writeError(); else readError(); 268155192Srwatson } 269155192Srwatson free ( bs ); 270155192Srwatson} 271155192Srwatson 272155192Srwatson 273155192Srwatson/*---------------------------------------------*/ 274155192Srwatsonvoid bsPutUChar ( BitStream* bs, UChar c ) 275155192Srwatson{ 276155192Srwatson Int32 i; 277155192Srwatson for (i = 7; i >= 0; i--) 278155192Srwatson bsPutBit ( bs, (((UInt32) c) >> i) & 0x1 ); 279155192Srwatson} 280155192Srwatson 281155192Srwatson 282155192Srwatson/*---------------------------------------------*/ 283155192Srwatsonvoid bsPutUInt32 ( BitStream* bs, UInt32 c ) 284155192Srwatson{ 285155192Srwatson Int32 i; 286155192Srwatson 287155192Srwatson for (i = 31; i >= 0; i--) 288155192Srwatson bsPutBit ( bs, (c >> i) & 0x1 ); 289155192Srwatson} 290155192Srwatson 291155192Srwatson 292155192Srwatson/*---------------------------------------------*/ 293155192SrwatsonBool endsInBz2 ( Char* name ) 294155192Srwatson{ 295155192Srwatson Int32 n = strlen ( name ); 296155192Srwatson if (n <= 4) return False; 297155192Srwatson return 298155192Srwatson (name[n-4] == '.' && 299155192Srwatson name[n-3] == 'b' && 300155192Srwatson name[n-2] == 'z' && 301155192Srwatson name[n-1] == '2'); 302155192Srwatson} 303155192Srwatson 304155192Srwatson 305155192Srwatson/*---------------------------------------------------*/ 306155192Srwatson/*--- ---*/ 307155192Srwatson/*---------------------------------------------------*/ 308155192Srwatson 309155192Srwatson/* This logic isn't really right when it comes to Cygwin. */ 310155192Srwatson#ifdef _WIN32 311155192Srwatson# define BZ_SPLIT_SYM '\\' /* path splitter on Windows platform */ 312155192Srwatson#else 313156889Srwatson# define BZ_SPLIT_SYM '/' /* path splitter on Unix platform */ 314170196Srwatson#endif 315170196Srwatson 316170196Srwatson#define BLOCK_HEADER_HI 0x00003141UL 317155192Srwatson#define BLOCK_HEADER_LO 0x59265359UL 318155192Srwatson 319155192Srwatson#define BLOCK_ENDMARK_HI 0x00001772UL 320155192Srwatson#define BLOCK_ENDMARK_LO 0x45385090UL 321155192Srwatson 322155192Srwatson/* Increase if necessary. However, a .bz2 file with > 50000 blocks 323155192Srwatson would have an uncompressed size of at least 40GB, so the chances 324155192Srwatson are low you'll need to up this. 325155192Srwatson*/ 326155192Srwatson#define BZ_MAX_HANDLED_BLOCKS 50000 327155192Srwatson 328155192SrwatsonMaybeUInt64 bStart [BZ_MAX_HANDLED_BLOCKS]; 329155192SrwatsonMaybeUInt64 bEnd [BZ_MAX_HANDLED_BLOCKS]; 330155192SrwatsonMaybeUInt64 rbStart[BZ_MAX_HANDLED_BLOCKS]; 331155192SrwatsonMaybeUInt64 rbEnd [BZ_MAX_HANDLED_BLOCKS]; 332155192Srwatson 333155192SrwatsonInt32 main ( Int32 argc, Char** argv ) 334155192Srwatson{ 335155192Srwatson FILE* inFile; 336155192Srwatson FILE* outFile; 337155192Srwatson BitStream* bsIn, *bsWr; 338155192Srwatson Int32 b, wrBlock, currBlock, rbCtr; 339155192Srwatson MaybeUInt64 bitsRead; 340155192Srwatson 341176565Srwatson UInt32 buffHi, buffLo, blockCRC; 342155192Srwatson Char* p; 343155192Srwatson 344155192Srwatson strcpy ( progName, argv[0] ); 345155192Srwatson inFileName[0] = outFileName[0] = 0; 346155192Srwatson 347155192Srwatson fprintf ( stderr, 348155192Srwatson "bzip2recover 1.0.2: extracts blocks from damaged .bz2 files.\n" ); 349155192Srwatson 350155192Srwatson if (argc != 2) { 351155192Srwatson fprintf ( stderr, "%s: usage is `%s damaged_file_name'.\n", 352155192Srwatson progName, progName ); 353155192Srwatson switch (sizeof(MaybeUInt64)) { 354155192Srwatson case 8: 355170196Srwatson fprintf(stderr, 356155192Srwatson "\trestrictions on size of recovered file: None\n"); 357155192Srwatson break; 358155192Srwatson case 4: 359155192Srwatson fprintf(stderr, 360155192Srwatson "\trestrictions on size of recovered file: 512 MB\n"); 361155192Srwatson fprintf(stderr, 362155192Srwatson "\tto circumvent, recompile with MaybeUInt64 as an\n" 363155192Srwatson "\tunsigned 64-bit int.\n"); 364176565Srwatson break; 365155192Srwatson default: 366155192Srwatson fprintf(stderr, 367155192Srwatson "\tsizeof(MaybeUInt64) is not 4 or 8 -- " 368155192Srwatson "configuration error.\n"); 369155192Srwatson break; 370155192Srwatson } 371155192Srwatson exit(1); 372155192Srwatson } 373155192Srwatson 374155192Srwatson if (strlen(argv[1]) >= BZ_MAX_FILENAME-20) { 375155192Srwatson fprintf ( stderr, 376155192Srwatson "%s: supplied filename is suspiciously (>= %d chars) long. Bye!\n", 377155192Srwatson progName, strlen(argv[1]) ); 378155192Srwatson exit(1); 379155192Srwatson } 380155192Srwatson 381155192Srwatson strcpy ( inFileName, argv[1] ); 382155192Srwatson 383155192Srwatson inFile = fopen ( inFileName, "rb" ); 384155192Srwatson if (inFile == NULL) { 385155192Srwatson fprintf ( stderr, "%s: can't read `%s'\n", progName, inFileName ); 386155192Srwatson exit(1); 387155192Srwatson } 388155192Srwatson 389155192Srwatson bsIn = bsOpenReadStream ( inFile ); 390155192Srwatson fprintf ( stderr, "%s: searching for block boundaries ...\n", progName ); 391155192Srwatson 392155192Srwatson bitsRead = 0; 393155192Srwatson buffHi = buffLo = 0; 394155192Srwatson currBlock = 0; 395155192Srwatson bStart[currBlock] = 0; 396155192Srwatson 397155192Srwatson rbCtr = 0; 398155192Srwatson 399155192Srwatson while (True) { 400155192Srwatson b = bsGetBit ( bsIn ); 401155192Srwatson bitsRead++; 402155192Srwatson if (b == 2) { 403155192Srwatson if (bitsRead >= bStart[currBlock] && 404155192Srwatson (bitsRead - bStart[currBlock]) >= 40) { 405155192Srwatson bEnd[currBlock] = bitsRead-1; 406155192Srwatson if (currBlock > 0) 407155192Srwatson fprintf ( stderr, " block %d runs from " MaybeUInt64_FMT 408155192Srwatson " to " MaybeUInt64_FMT " (incomplete)\n", 409155192Srwatson currBlock, bStart[currBlock], bEnd[currBlock] ); 410155192Srwatson } else 411155192Srwatson currBlock--; 412155192Srwatson break; 413155192Srwatson } 414155192Srwatson buffHi = (buffHi << 1) | (buffLo >> 31); 415155192Srwatson buffLo = (buffLo << 1) | (b & 1); 416155192Srwatson if ( ( (buffHi & 0x0000ffff) == BLOCK_HEADER_HI 417155192Srwatson && buffLo == BLOCK_HEADER_LO) 418155192Srwatson || 419155192Srwatson ( (buffHi & 0x0000ffff) == BLOCK_ENDMARK_HI 420155192Srwatson && buffLo == BLOCK_ENDMARK_LO) 421155192Srwatson ) { 422155192Srwatson if (bitsRead > 49) { 423155192Srwatson bEnd[currBlock] = bitsRead-49; 424155192Srwatson } else { 425155192Srwatson bEnd[currBlock] = 0; 426155192Srwatson } 427155192Srwatson if (currBlock > 0 && 428155192Srwatson (bEnd[currBlock] - bStart[currBlock]) >= 130) { 429155192Srwatson fprintf ( stderr, " block %d runs from " MaybeUInt64_FMT 430155192Srwatson " to " MaybeUInt64_FMT "\n", 431155192Srwatson rbCtr+1, bStart[currBlock], bEnd[currBlock] ); 432155192Srwatson rbStart[rbCtr] = bStart[currBlock]; 433155192Srwatson rbEnd[rbCtr] = bEnd[currBlock]; 434155192Srwatson rbCtr++; 435155192Srwatson } 436155192Srwatson if (currBlock >= BZ_MAX_HANDLED_BLOCKS) 437155192Srwatson tooManyBlocks(BZ_MAX_HANDLED_BLOCKS); 438155192Srwatson currBlock++; 439155192Srwatson 440155192Srwatson bStart[currBlock] = bitsRead; 441155192Srwatson } 442155192Srwatson } 443155192Srwatson 444155192Srwatson bsClose ( bsIn ); 445155192Srwatson 446155192Srwatson /*-- identified blocks run from 1 to rbCtr inclusive. --*/ 447155192Srwatson 448155192Srwatson if (rbCtr < 1) { 449155192Srwatson fprintf ( stderr, 450155192Srwatson "%s: sorry, I couldn't find any block boundaries.\n", 451155192Srwatson progName ); 452155192Srwatson exit(1); 453155192Srwatson }; 454155192Srwatson 455155192Srwatson fprintf ( stderr, "%s: splitting into blocks\n", progName ); 456155192Srwatson 457155192Srwatson inFile = fopen ( inFileName, "rb" ); 458155192Srwatson if (inFile == NULL) { 459155192Srwatson fprintf ( stderr, "%s: can't open `%s'\n", progName, inFileName ); 460155192Srwatson exit(1); 461155192Srwatson } 462155192Srwatson bsIn = bsOpenReadStream ( inFile ); 463155192Srwatson 464155192Srwatson /*-- placate gcc's dataflow analyser --*/ 465155192Srwatson blockCRC = 0; bsWr = 0; 466155192Srwatson 467155192Srwatson bitsRead = 0; 468155192Srwatson outFile = NULL; 469155192Srwatson wrBlock = 0; 470155192Srwatson while (True) { 471155192Srwatson b = bsGetBit(bsIn); 472156889Srwatson if (b == 2) break; 473156889Srwatson buffHi = (buffHi << 1) | (buffLo >> 31); 474156889Srwatson buffLo = (buffLo << 1) | (b & 1); 475170196Srwatson if (bitsRead == 47+rbStart[wrBlock]) 476156889Srwatson blockCRC = (buffHi << 16) | (buffLo >> 16); 477156889Srwatson 478155192Srwatson if (outFile != NULL && bitsRead >= rbStart[wrBlock] 479155192Srwatson && bitsRead <= rbEnd[wrBlock]) { 480155192Srwatson bsPutBit ( bsWr, b ); 481155192Srwatson } 482155192Srwatson 483176565Srwatson bitsRead++; 484155192Srwatson 485155192Srwatson if (bitsRead == rbEnd[wrBlock]+1) { 486155192Srwatson if (outFile != NULL) { 487155192Srwatson bsPutUChar ( bsWr, 0x17 ); bsPutUChar ( bsWr, 0x72 ); 488155192Srwatson bsPutUChar ( bsWr, 0x45 ); bsPutUChar ( bsWr, 0x38 ); 489159143Scsjp bsPutUChar ( bsWr, 0x50 ); bsPutUChar ( bsWr, 0x90 ); 490155192Srwatson bsPutUInt32 ( bsWr, blockCRC ); 491165621Srwatson bsClose ( bsWr ); 492176565Srwatson } 493165621Srwatson if (wrBlock >= rbCtr) break; 494155192Srwatson wrBlock++; 495155192Srwatson } else 496159143Scsjp if (bitsRead == rbStart[wrBlock]) { 497168355Srwatson /* Create the output file name, correctly handling leading paths. 498155192Srwatson (31.10.2001 by Sergey E. Kusikov) */ 499156889Srwatson Char* split; 500156889Srwatson Int32 ofs, k; 501156889Srwatson for (k = 0; k < BZ_MAX_FILENAME; k++) 502156889Srwatson outFileName[k] = 0; 503155192Srwatson strcpy (outFileName, inFileName); 504155192Srwatson split = strrchr (outFileName, BZ_SPLIT_SYM); 505155192Srwatson if (split == NULL) { 506156889Srwatson split = outFileName; 507155192Srwatson } else { 508156889Srwatson ++split; 509155192Srwatson } 510156889Srwatson /* Now split points to the start of the basename. */ 511155192Srwatson ofs = split - outFileName; 512155192Srwatson sprintf (split, "rec%5d", wrBlock+1); 513155192Srwatson for (p = split; *p != 0; p++) if (*p == ' ') *p = '0'; 514156889Srwatson strcat (outFileName, inFileName + ofs); 515159143Scsjp 516155192Srwatson if ( !endsInBz2(outFileName)) strcat ( outFileName, ".bz2" ); 517155192Srwatson 518155192Srwatson fprintf ( stderr, " writing block %d to `%s' ...\n", 519168355Srwatson wrBlock+1, outFileName ); 520155192Srwatson 521155192Srwatson outFile = fopen ( outFileName, "wb" ); 522156889Srwatson if (outFile == NULL) { 523156889Srwatson fprintf ( stderr, "%s: can't write `%s'\n", 524156889Srwatson progName, outFileName ); 525156889Srwatson exit(1); 526156889Srwatson } 527155192Srwatson bsWr = bsOpenWriteStream ( outFile ); 528155192Srwatson bsPutUChar ( bsWr, BZ_HDR_B ); 529175202Sattilio bsPutUChar ( bsWr, BZ_HDR_Z ); 530155192Srwatson bsPutUChar ( bsWr, BZ_HDR_h ); 531155192Srwatson bsPutUChar ( bsWr, BZ_HDR_0 + 9 ); 532159143Scsjp bsPutUChar ( bsWr, 0x31 ); bsPutUChar ( bsWr, 0x41 ); 533159143Scsjp bsPutUChar ( bsWr, 0x59 ); bsPutUChar ( bsWr, 0x26 ); 534159143Scsjp bsPutUChar ( bsWr, 0x53 ); bsPutUChar ( bsWr, 0x59 ); 535159143Scsjp } 536159143Scsjp } 537159143Scsjp 538159143Scsjp fprintf ( stderr, "%s: finished\n", progName ); 539159143Scsjp return 0; 540156889Srwatson} 541156889Srwatson 542155192Srwatson 543155192Srwatson 544155192Srwatson/*-----------------------------------------------------------*/ 545170196Srwatson/*--- end bzip2recover.c ---*/ 546155192Srwatson/*-----------------------------------------------------------*/ 547155192Srwatson