1184588Sdfr/*-----------------------------------------------------------*/ 2197583Sjamie/*--- Block recoverer program for bzip2 ---*/ 3197583Sjamie/*--- bzip2recover.c ---*/ 4184588Sdfr/*-----------------------------------------------------------*/ 5184588Sdfr 6184588Sdfr/* ------------------------------------------------------------------ 7184588Sdfr This file is part of bzip2/libbzip2, a program and library for 8184588Sdfr lossless, block-sorting data compression. 9184588Sdfr 10184588Sdfr bzip2/libbzip2 version 1.0.8 of 13 July 2019 11184588Sdfr Copyright (C) 1996-2019 Julian Seward <jseward@acm.org> 12184588Sdfr 13184588Sdfr Please read the WARNING, DISCLAIMER and PATENTS sections in the 14197583Sjamie README file. 15184588Sdfr 16184588Sdfr This program is released under the terms of the license contained 17197583Sjamie in the file LICENSE. 18184588Sdfr ------------------------------------------------------------------ */ 19184588Sdfr 20184588Sdfr/* This program is a complete hack and should be rewritten properly. 21184588Sdfr It isn't very complicated. */ 22184588Sdfr 23184588Sdfr#include <stdio.h> 24184588Sdfr#include <errno.h> 25184588Sdfr#include <stdlib.h> 26197583Sjamie#include <string.h> 27197583Sjamie 28197583Sjamie 29197583Sjamie/* This program records bit locations in the file to be recovered. 30197583Sjamie That means that if 64-bit ints are not supported, we will not 31184588Sdfr be able to recover .bz2 files over 512MB (2^32 bits) long. 32197583Sjamie On GNU supported platforms, we take advantage of the 64-bit 33197583Sjamie int support to circumvent this problem. Ditto MSVC. 34197583Sjamie 35197583Sjamie This change occurred in version 1.0.2; all prior versions have 36197583Sjamie the 512MB limitation. 37197583Sjamie*/ 38197583Sjamie#ifdef __GNUC__ 39197583Sjamie typedef unsigned long long int MaybeUInt64; 40197583Sjamie# define MaybeUInt64_FMT "%llu" 41197583Sjamie#else 42197583Sjamie#ifdef _MSC_VER 43197583Sjamie typedef unsigned __int64 MaybeUInt64; 44197583Sjamie# define MaybeUInt64_FMT "%I64u" 45197583Sjamie#else 46197583Sjamie typedef unsigned int MaybeUInt64; 47197583Sjamie# define MaybeUInt64_FMT "%u" 48197583Sjamie#endif 49197583Sjamie#endif 50197583Sjamie 51197583Sjamietypedef unsigned int UInt32; 52197583Sjamietypedef int Int32; 53197583Sjamietypedef unsigned char UChar; 54197583Sjamietypedef char Char; 55197583Sjamietypedef unsigned char Bool; 56197583Sjamie#define True ((Bool)1) 57197583Sjamie#define False ((Bool)0) 58197583Sjamie 59197583Sjamie 60197583Sjamie#define BZ_MAX_FILENAME 2000 61197583Sjamie 62197583SjamieChar inFileName[BZ_MAX_FILENAME]; 63184588SdfrChar outFileName[BZ_MAX_FILENAME]; 64184588SdfrChar progName[BZ_MAX_FILENAME]; 65184588Sdfr 66184588SdfrMaybeUInt64 bytesOut = 0; 67197583SjamieMaybeUInt64 bytesIn = 0; 68194239Srmacklem 69184588Sdfr 70197583Sjamie/*---------------------------------------------------*/ 71184588Sdfr/*--- Header bytes ---*/ 72184588Sdfr/*---------------------------------------------------*/ 73184588Sdfr 74184588Sdfr#define BZ_HDR_B 0x42 /* 'B' */ 75197583Sjamie#define BZ_HDR_Z 0x5a /* 'Z' */ 76197583Sjamie#define BZ_HDR_h 0x68 /* 'h' */ 77197583Sjamie#define BZ_HDR_0 0x30 /* '0' */ 78184588Sdfr 79197583Sjamie 80197583Sjamie/*---------------------------------------------------*/ 81184588Sdfr/*--- I/O errors ---*/ 82197583Sjamie/*---------------------------------------------------*/ 83184588Sdfr 84197583Sjamie/*---------------------------------------------*/ 85197583Sjamiestatic void readError ( void ) 86197583Sjamie{ 87197583Sjamie fprintf ( stderr, 88197583Sjamie "%s: I/O error reading `%s', possible reason follows.\n", 89184588Sdfr progName, inFileName ); 90197583Sjamie perror ( progName ); 91197583Sjamie fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n", 92197583Sjamie progName ); 93197583Sjamie exit ( 1 ); 94184588Sdfr} 95184588Sdfr 96197583Sjamie 97197583Sjamie/*---------------------------------------------*/ 98197583Sjamiestatic void writeError ( void ) 99197583Sjamie{ 100197583Sjamie fprintf ( stderr, 101197583Sjamie "%s: I/O error reading `%s', possible reason follows.\n", 102197583Sjamie progName, inFileName ); 103201145Santoine perror ( progName ); 104197583Sjamie fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n", 105197583Sjamie progName ); 106197583Sjamie exit ( 1 ); 107197583Sjamie} 108197583Sjamie 109197583Sjamie 110197583Sjamie/*---------------------------------------------*/ 111197583Sjamiestatic void mallocFail ( Int32 n ) 112197583Sjamie{ 113197583Sjamie fprintf ( stderr, 114197583Sjamie "%s: malloc failed on request for %d bytes.\n", 115201145Santoine progName, n ); 116197583Sjamie fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n", 117197583Sjamie progName ); 118197583Sjamie exit ( 1 ); 119197583Sjamie} 120197583Sjamie 121197583Sjamie 122197583Sjamie/*---------------------------------------------*/ 123197583Sjamiestatic void tooManyBlocks ( Int32 max_handled_blocks ) 124197583Sjamie{ 125197583Sjamie fprintf ( stderr, 126197583Sjamie "%s: `%s' appears to contain more than %d blocks\n", 127197583Sjamie progName, inFileName, max_handled_blocks ); 128197583Sjamie fprintf ( stderr, 129197583Sjamie "%s: and cannot be handled. To fix, increase\n", 130197583Sjamie progName ); 131197583Sjamie fprintf ( stderr, 132197583Sjamie "%s: BZ_MAX_HANDLED_BLOCKS in bzip2recover.c, and recompile.\n", 133197583Sjamie progName ); 134197583Sjamie exit ( 1 ); 135197583Sjamie} 136197583Sjamie 137197583Sjamie 138197583Sjamie 139197583Sjamie/*---------------------------------------------------*/ 140197583Sjamie/*--- Bit stream I/O ---*/ 141197583Sjamie/*---------------------------------------------------*/ 142197583Sjamie 143197583Sjamietypedef 144197583Sjamie struct { 145197583Sjamie FILE* handle; 146197583Sjamie Int32 buffer; 147197583Sjamie Int32 buffLive; 148197583Sjamie Char mode; 149197583Sjamie } 150288827Sjpaetzel BitStream; 151197583Sjamie 152197583Sjamie 153197583Sjamie/*---------------------------------------------*/ 154197583Sjamiestatic BitStream* bsOpenReadStream ( FILE* stream ) 155197583Sjamie{ 156197583Sjamie BitStream *bs = malloc ( sizeof(BitStream) ); 157197583Sjamie if (bs == NULL) mallocFail ( sizeof(BitStream) ); 158197581Sjamie bs->handle = stream; 159197583Sjamie bs->buffer = 0; 160197583Sjamie bs->buffLive = 0; 161197583Sjamie bs->mode = 'r'; 162197581Sjamie return bs; 163197583Sjamie} 164197583Sjamie 165197583Sjamie 166197583Sjamie/*---------------------------------------------*/ 167184588Sdfrstatic BitStream* bsOpenWriteStream ( FILE* stream ) 168184588Sdfr{ 169197583Sjamie BitStream *bs = malloc ( sizeof(BitStream) ); 170197583Sjamie if (bs == NULL) mallocFail ( sizeof(BitStream) ); 171197583Sjamie bs->handle = stream; 172197583Sjamie bs->buffer = 0; 173197583Sjamie bs->buffLive = 0; 174197583Sjamie bs->mode = 'w'; 175197583Sjamie return bs; 176197583Sjamie} 177197583Sjamie 178184588Sdfr 179197583Sjamie/*---------------------------------------------*/ 180184588Sdfrstatic void bsPutBit ( BitStream* bs, Int32 bit ) 181197583Sjamie{ 182197583Sjamie if (bs->buffLive == 8) { 183197583Sjamie Int32 retVal = putc ( (UChar) bs->buffer, bs->handle ); 184197583Sjamie if (retVal == EOF) writeError(); 185197583Sjamie bytesOut++; 186197583Sjamie bs->buffLive = 1; 187197583Sjamie bs->buffer = bit & 0x1; 188197583Sjamie } else { 189197583Sjamie bs->buffer = ( (bs->buffer << 1) | (bit & 0x1) ); 190197583Sjamie bs->buffLive++; 191197583Sjamie }; 192197583Sjamie} 193197583Sjamie 194197583Sjamie 195197583Sjamie/*---------------------------------------------*/ 196197583Sjamie/*-- 197197583Sjamie Returns 0 or 1, or 2 to indicate EOF. 198184588Sdfr--*/ 199197583Sjamiestatic Int32 bsGetBit ( BitStream* bs ) 200197583Sjamie{ 201197583Sjamie if (bs->buffLive > 0) { 202197583Sjamie bs->buffLive --; 203184588Sdfr return ( ((bs->buffer) >> (bs->buffLive)) & 0x1 ); 204197583Sjamie } else { 205197583Sjamie Int32 retVal = getc ( bs->handle ); 206197583Sjamie if ( retVal == EOF ) { 207197583Sjamie if (errno != 0) readError(); 208197583Sjamie return 2; 209197583Sjamie } 210197583Sjamie bs->buffLive = 7; 211197583Sjamie bs->buffer = retVal; 212197583Sjamie return ( ((bs->buffer) >> 7) & 0x1 ); 213197583Sjamie } 214197583Sjamie} 215197583Sjamie 216197583Sjamie 217197583Sjamie/*---------------------------------------------*/ 218197583Sjamiestatic void bsClose ( BitStream* bs ) 219197583Sjamie{ 220197583Sjamie Int32 retVal; 221197583Sjamie 222184588Sdfr if ( bs->mode == 'w' ) { 223184588Sdfr while ( bs->buffLive < 8 ) { 224197583Sjamie bs->buffLive++; 225197583Sjamie bs->buffer <<= 1; 226184588Sdfr }; 227197583Sjamie retVal = putc ( (UChar) (bs->buffer), bs->handle ); 228197583Sjamie if (retVal == EOF) writeError(); 229197583Sjamie bytesOut++; 230197583Sjamie retVal = fflush ( bs->handle ); 231197583Sjamie if (retVal == EOF) writeError(); 232197583Sjamie } 233197583Sjamie retVal = fclose ( bs->handle ); 234197583Sjamie if (retVal == EOF) { 235197583Sjamie if (bs->mode == 'w') writeError(); else readError(); 236197583Sjamie } 237197583Sjamie free ( bs ); 238197583Sjamie} 239197583Sjamie 240197583Sjamie 241197583Sjamie/*---------------------------------------------*/ 242197583Sjamiestatic void bsPutUChar ( BitStream* bs, UChar c ) 243197583Sjamie{ 244197583Sjamie Int32 i; 245197583Sjamie for (i = 7; i >= 0; i--) 246197583Sjamie bsPutBit ( bs, (((UInt32) c) >> i) & 0x1 ); 247197583Sjamie} 248197583Sjamie 249197583Sjamie 250197583Sjamie/*---------------------------------------------*/ 251197583Sjamiestatic void bsPutUInt32 ( BitStream* bs, UInt32 c ) 252197583Sjamie{ 253197583Sjamie Int32 i; 254197583Sjamie 255184588Sdfr for (i = 31; i >= 0; i--) 256197583Sjamie bsPutBit ( bs, (c >> i) & 0x1 ); 257184588Sdfr} 258197583Sjamie 259197583Sjamie 260197583Sjamie/*---------------------------------------------*/ 261197583Sjamiestatic Bool endsInBz2 ( Char* name ) 262197583Sjamie{ 263197583Sjamie Int32 n = strlen ( name ); 264197583Sjamie if (n <= 4) return False; 265197583Sjamie return 266197583Sjamie (name[n-4] == '.' && 267197583Sjamie name[n-3] == 'b' && 268197583Sjamie name[n-2] == 'z' && 269197583Sjamie name[n-1] == '2'); 270197583Sjamie} 271197583Sjamie 272197583Sjamie 273197583Sjamie/*---------------------------------------------------*/ 274197583Sjamie/*--- ---*/ 275197583Sjamie/*---------------------------------------------------*/ 276197583Sjamie 277197583Sjamie/* This logic isn't really right when it comes to Cygwin. */ 278197583Sjamie#ifdef _WIN32 279197583Sjamie# define BZ_SPLIT_SYM '\\' /* path splitter on Windows platform */ 280197583Sjamie#else 281197583Sjamie# define BZ_SPLIT_SYM '/' /* path splitter on Unix platform */ 282197583Sjamie#endif 283197583Sjamie 284197583Sjamie#define BLOCK_HEADER_HI 0x00003141UL 285184588Sdfr#define BLOCK_HEADER_LO 0x59265359UL 286197583Sjamie 287197583Sjamie#define BLOCK_ENDMARK_HI 0x00001772UL 288197583Sjamie#define BLOCK_ENDMARK_LO 0x45385090UL 289197583Sjamie 290197583Sjamie/* Increase if necessary. However, a .bz2 file with > 50000 blocks 291197583Sjamie would have an uncompressed size of at least 40GB, so the chances 292197583Sjamie are low you'll need to up this. 293197583Sjamie*/ 294197583Sjamie#define BZ_MAX_HANDLED_BLOCKS 50000 295197583Sjamie 296197583SjamieMaybeUInt64 bStart [BZ_MAX_HANDLED_BLOCKS]; 297197583SjamieMaybeUInt64 bEnd [BZ_MAX_HANDLED_BLOCKS]; 298197583SjamieMaybeUInt64 rbStart[BZ_MAX_HANDLED_BLOCKS]; 299197583SjamieMaybeUInt64 rbEnd [BZ_MAX_HANDLED_BLOCKS]; 300197583Sjamie 301197583SjamieInt32 main ( Int32 argc, Char** argv ) 302197583Sjamie{ 303197583Sjamie FILE* inFile; 304197583Sjamie FILE* outFile; 305197583Sjamie BitStream* bsIn, *bsWr; 306197583Sjamie Int32 b, wrBlock, currBlock, rbCtr; 307197583Sjamie MaybeUInt64 bitsRead; 308197583Sjamie 309197583Sjamie UInt32 buffHi, buffLo, blockCRC; 310197583Sjamie Char* p; 311184588Sdfr 312184588Sdfr strncpy ( progName, argv[0], BZ_MAX_FILENAME-1); 313197583Sjamie progName[BZ_MAX_FILENAME-1]='\0'; 314197583Sjamie inFileName[0] = outFileName[0] = 0; 315197583Sjamie 316197583Sjamie fprintf ( stderr, 317197583Sjamie "bzip2recover 1.0.8: extracts blocks from damaged .bz2 files.\n" ); 318197583Sjamie 319197583Sjamie if (argc != 2) { 320197583Sjamie fprintf ( stderr, "%s: usage is `%s damaged_file_name'.\n", 321197583Sjamie progName, progName ); 322197583Sjamie switch (sizeof(MaybeUInt64)) { 323197583Sjamie case 8: 324197583Sjamie fprintf(stderr, 325197583Sjamie "\trestrictions on size of recovered file: None\n"); 326197583Sjamie break; 327197583Sjamie case 4: 328197583Sjamie fprintf(stderr, 329197583Sjamie "\trestrictions on size of recovered file: 512 MB\n"); 330197583Sjamie fprintf(stderr, 331197583Sjamie "\tto circumvent, recompile with MaybeUInt64 as an\n" 332197583Sjamie "\tunsigned 64-bit int.\n"); 333197583Sjamie break; 334299619Sngie default: 335197583Sjamie fprintf(stderr, 336197583Sjamie "\tsizeof(MaybeUInt64) is not 4 or 8 -- " 337184588Sdfr "configuration error.\n"); 338197583Sjamie break; 339197583Sjamie } 340197583Sjamie exit(1); 341197583Sjamie } 342197583Sjamie 343197583Sjamie if (strlen(argv[1]) >= BZ_MAX_FILENAME-20) { 344197583Sjamie fprintf ( stderr, 345197583Sjamie "%s: supplied filename is suspiciously (>= %d chars) long. Bye!\n", 346197583Sjamie progName, (int)strlen(argv[1]) ); 347197583Sjamie exit(1); 348197583Sjamie } 349197583Sjamie 350197583Sjamie strcpy ( inFileName, argv[1] ); 351197583Sjamie 352197583Sjamie inFile = fopen ( inFileName, "rb" ); 353197583Sjamie if (inFile == NULL) { 354197583Sjamie fprintf ( stderr, "%s: can't read `%s'\n", progName, inFileName ); 355197583Sjamie exit(1); 356197583Sjamie } 357197583Sjamie 358197583Sjamie bsIn = bsOpenReadStream ( inFile ); 359197583Sjamie fprintf ( stderr, "%s: searching for block boundaries ...\n", progName ); 360197583Sjamie 361197583Sjamie bitsRead = 0; 362197583Sjamie buffHi = buffLo = 0; 363197583Sjamie currBlock = 0; 364197583Sjamie bStart[currBlock] = 0; 365197583Sjamie 366197583Sjamie rbCtr = 0; 367197583Sjamie 368197583Sjamie while (True) { 369197583Sjamie b = bsGetBit ( bsIn ); 370197583Sjamie bitsRead++; 371197583Sjamie if (b == 2) { 372197583Sjamie if (bitsRead >= bStart[currBlock] && 373197583Sjamie (bitsRead - bStart[currBlock]) >= 40) { 374197583Sjamie bEnd[currBlock] = bitsRead-1; 375197583Sjamie if (currBlock > 0) 376197583Sjamie fprintf ( stderr, " block %d runs from " MaybeUInt64_FMT 377197583Sjamie " to " MaybeUInt64_FMT " (incomplete)\n", 378197583Sjamie currBlock, bStart[currBlock], bEnd[currBlock] ); 379197583Sjamie } else 380197583Sjamie currBlock--; 381197583Sjamie break; 382197583Sjamie } 383197583Sjamie buffHi = (buffHi << 1) | (buffLo >> 31); 384197583Sjamie buffLo = (buffLo << 1) | (b & 1); 385197583Sjamie if ( ( (buffHi & 0x0000ffff) == BLOCK_HEADER_HI 386197583Sjamie && buffLo == BLOCK_HEADER_LO) 387197583Sjamie || 388197583Sjamie ( (buffHi & 0x0000ffff) == BLOCK_ENDMARK_HI 389197583Sjamie && buffLo == BLOCK_ENDMARK_LO) 390197583Sjamie ) { 391197583Sjamie if (bitsRead > 49) { 392197583Sjamie bEnd[currBlock] = bitsRead-49; 393197583Sjamie } else { 394197583Sjamie bEnd[currBlock] = 0; 395197583Sjamie } 396197583Sjamie if (currBlock > 0 && 397197583Sjamie (bEnd[currBlock] - bStart[currBlock]) >= 130) { 398184588Sdfr fprintf ( stderr, " block %d runs from " MaybeUInt64_FMT 399184588Sdfr " to " MaybeUInt64_FMT "\n", 400197583Sjamie rbCtr+1, bStart[currBlock], bEnd[currBlock] ); 401197583Sjamie rbStart[rbCtr] = bStart[currBlock]; 402197583Sjamie rbEnd[rbCtr] = bEnd[currBlock]; 403197583Sjamie rbCtr++; 404197583Sjamie } 405197583Sjamie if (currBlock >= BZ_MAX_HANDLED_BLOCKS) 406197583Sjamie tooManyBlocks(BZ_MAX_HANDLED_BLOCKS); 407197583Sjamie currBlock++; 408197583Sjamie 409197583Sjamie bStart[currBlock] = bitsRead; 410197583Sjamie } 411197583Sjamie } 412197583Sjamie 413197583Sjamie bsClose ( bsIn ); 414197583Sjamie 415197583Sjamie /*-- identified blocks run from 1 to rbCtr inclusive. --*/ 416197583Sjamie 417197583Sjamie if (rbCtr < 1) { 418197583Sjamie fprintf ( stderr, 419197583Sjamie "%s: sorry, I couldn't find any block boundaries.\n", 420197583Sjamie progName ); 421197583Sjamie exit(1); 422197583Sjamie }; 423197583Sjamie 424197583Sjamie fprintf ( stderr, "%s: splitting into blocks\n", progName ); 425184588Sdfr 426197583Sjamie inFile = fopen ( inFileName, "rb" ); 427184588Sdfr if (inFile == NULL) { 428197583Sjamie fprintf ( stderr, "%s: can't open `%s'\n", progName, inFileName ); 429197583Sjamie exit(1); 430197583Sjamie } 431197583Sjamie bsIn = bsOpenReadStream ( inFile ); 432184588Sdfr 433197583Sjamie /*-- placate gcc's dataflow analyser --*/ 434197583Sjamie blockCRC = 0; bsWr = 0; 435197583Sjamie 436197583Sjamie bitsRead = 0; 437197583Sjamie outFile = NULL; 438197583Sjamie wrBlock = 0; 439197583Sjamie while (True) { 440197583Sjamie b = bsGetBit(bsIn); 441197583Sjamie if (b == 2) break; 442197583Sjamie buffHi = (buffHi << 1) | (buffLo >> 31); 443197583Sjamie buffLo = (buffLo << 1) | (b & 1); 444197583Sjamie if (bitsRead == 47+rbStart[wrBlock]) 445197583Sjamie blockCRC = (buffHi << 16) | (buffLo >> 16); 446197583Sjamie 447197583Sjamie if (outFile != NULL && bitsRead >= rbStart[wrBlock] 448197583Sjamie && bitsRead <= rbEnd[wrBlock]) { 449197583Sjamie bsPutBit ( bsWr, b ); 450197583Sjamie } 451197583Sjamie 452197584Sjamie bitsRead++; 453197584Sjamie 454197583Sjamie if (bitsRead == rbEnd[wrBlock]+1) { 455197583Sjamie if (outFile != NULL) { 456197583Sjamie bsPutUChar ( bsWr, 0x17 ); bsPutUChar ( bsWr, 0x72 ); 457184588Sdfr bsPutUChar ( bsWr, 0x45 ); bsPutUChar ( bsWr, 0x38 ); 458184588Sdfr bsPutUChar ( bsWr, 0x50 ); bsPutUChar ( bsWr, 0x90 ); 459197583Sjamie bsPutUInt32 ( bsWr, blockCRC ); 460197583Sjamie bsClose ( bsWr ); 461197583Sjamie outFile = NULL; 462197583Sjamie } 463197583Sjamie if (wrBlock >= rbCtr) break; 464197583Sjamie wrBlock++; 465197583Sjamie } else 466197583Sjamie if (bitsRead == rbStart[wrBlock]) { 467197583Sjamie /* Create the output file name, correctly handling leading paths. 468197583Sjamie (31.10.2001 by Sergey E. Kusikov) */ 469197583Sjamie Char* split; 470197583Sjamie Int32 ofs, k; 471197583Sjamie for (k = 0; k < BZ_MAX_FILENAME; k++) 472197583Sjamie outFileName[k] = 0; 473197583Sjamie strcpy (outFileName, inFileName); 474197583Sjamie split = strrchr (outFileName, BZ_SPLIT_SYM); 475197583Sjamie if (split == NULL) { 476197583Sjamie split = outFileName; 477197583Sjamie } else { 478197583Sjamie ++split; 479197583Sjamie } 480197583Sjamie /* Now split points to the start of the basename. */ 481197583Sjamie ofs = split - outFileName; 482197583Sjamie sprintf (split, "rec%5d", wrBlock+1); 483197583Sjamie for (p = split; *p != 0; p++) if (*p == ' ') *p = '0'; 484197583Sjamie strcat (outFileName, inFileName + ofs); 485197583Sjamie 486197583Sjamie if ( !endsInBz2(outFileName)) strcat ( outFileName, ".bz2" ); 487197583Sjamie 488197583Sjamie fprintf ( stderr, " writing block %d to `%s' ...\n", 489197583Sjamie wrBlock+1, outFileName ); 490197583Sjamie 491197583Sjamie outFile = fopen ( outFileName, "wb" ); 492197583Sjamie if (outFile == NULL) { 493197583Sjamie fprintf ( stderr, "%s: can't write `%s'\n", 494197583Sjamie progName, outFileName ); 495197583Sjamie exit(1); 496197583Sjamie } 497197583Sjamie bsWr = bsOpenWriteStream ( outFile ); 498197583Sjamie bsPutUChar ( bsWr, BZ_HDR_B ); 499197583Sjamie bsPutUChar ( bsWr, BZ_HDR_Z ); 500197583Sjamie bsPutUChar ( bsWr, BZ_HDR_h ); 501197583Sjamie bsPutUChar ( bsWr, BZ_HDR_0 + 9 ); 502197583Sjamie bsPutUChar ( bsWr, 0x31 ); bsPutUChar ( bsWr, 0x41 ); 503197583Sjamie bsPutUChar ( bsWr, 0x59 ); bsPutUChar ( bsWr, 0x26 ); 504197583Sjamie bsPutUChar ( bsWr, 0x53 ); bsPutUChar ( bsWr, 0x59 ); 505197583Sjamie } 506197583Sjamie } 507197583Sjamie 508197583Sjamie fprintf ( stderr, "%s: finished\n", progName ); 509197583Sjamie return 0; 510197583Sjamie} 511197583Sjamie 512197583Sjamie 513197583Sjamie 514197583Sjamie/*-----------------------------------------------------------*/ 515197583Sjamie/*--- end bzip2recover.c ---*/ 516197583Sjamie/*-----------------------------------------------------------*/ 517197583Sjamie