annotate src/bzip2-1.0.6/bzip2recover.c @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents e13257ea84a4
children
rev   line source
Chris@4 1 /*-----------------------------------------------------------*/
Chris@4 2 /*--- Block recoverer program for bzip2 ---*/
Chris@4 3 /*--- bzip2recover.c ---*/
Chris@4 4 /*-----------------------------------------------------------*/
Chris@4 5
Chris@4 6 /* ------------------------------------------------------------------
Chris@4 7 This file is part of bzip2/libbzip2, a program and library for
Chris@4 8 lossless, block-sorting data compression.
Chris@4 9
Chris@4 10 bzip2/libbzip2 version 1.0.6 of 6 September 2010
Chris@4 11 Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Chris@4 12
Chris@4 13 Please read the WARNING, DISCLAIMER and PATENTS sections in the
Chris@4 14 README file.
Chris@4 15
Chris@4 16 This program is released under the terms of the license contained
Chris@4 17 in the file LICENSE.
Chris@4 18 ------------------------------------------------------------------ */
Chris@4 19
Chris@4 20 /* This program is a complete hack and should be rewritten properly.
Chris@4 21 It isn't very complicated. */
Chris@4 22
Chris@4 23 #include <stdio.h>
Chris@4 24 #include <errno.h>
Chris@4 25 #include <stdlib.h>
Chris@4 26 #include <string.h>
Chris@4 27
Chris@4 28
Chris@4 29 /* This program records bit locations in the file to be recovered.
Chris@4 30 That means that if 64-bit ints are not supported, we will not
Chris@4 31 be able to recover .bz2 files over 512MB (2^32 bits) long.
Chris@4 32 On GNU supported platforms, we take advantage of the 64-bit
Chris@4 33 int support to circumvent this problem. Ditto MSVC.
Chris@4 34
Chris@4 35 This change occurred in version 1.0.2; all prior versions have
Chris@4 36 the 512MB limitation.
Chris@4 37 */
Chris@4 38 #ifdef __GNUC__
Chris@4 39 typedef unsigned long long int MaybeUInt64;
Chris@4 40 # define MaybeUInt64_FMT "%Lu"
Chris@4 41 #else
Chris@4 42 #ifdef _MSC_VER
Chris@4 43 typedef unsigned __int64 MaybeUInt64;
Chris@4 44 # define MaybeUInt64_FMT "%I64u"
Chris@4 45 #else
Chris@4 46 typedef unsigned int MaybeUInt64;
Chris@4 47 # define MaybeUInt64_FMT "%u"
Chris@4 48 #endif
Chris@4 49 #endif
Chris@4 50
Chris@4 51 typedef unsigned int UInt32;
Chris@4 52 typedef int Int32;
Chris@4 53 typedef unsigned char UChar;
Chris@4 54 typedef char Char;
Chris@4 55 typedef unsigned char Bool;
Chris@4 56 #define True ((Bool)1)
Chris@4 57 #define False ((Bool)0)
Chris@4 58
Chris@4 59
Chris@4 60 #define BZ_MAX_FILENAME 2000
Chris@4 61
Chris@4 62 Char inFileName[BZ_MAX_FILENAME];
Chris@4 63 Char outFileName[BZ_MAX_FILENAME];
Chris@4 64 Char progName[BZ_MAX_FILENAME];
Chris@4 65
Chris@4 66 MaybeUInt64 bytesOut = 0;
Chris@4 67 MaybeUInt64 bytesIn = 0;
Chris@4 68
Chris@4 69
Chris@4 70 /*---------------------------------------------------*/
Chris@4 71 /*--- Header bytes ---*/
Chris@4 72 /*---------------------------------------------------*/
Chris@4 73
Chris@4 74 #define BZ_HDR_B 0x42 /* 'B' */
Chris@4 75 #define BZ_HDR_Z 0x5a /* 'Z' */
Chris@4 76 #define BZ_HDR_h 0x68 /* 'h' */
Chris@4 77 #define BZ_HDR_0 0x30 /* '0' */
Chris@4 78
Chris@4 79
Chris@4 80 /*---------------------------------------------------*/
Chris@4 81 /*--- I/O errors ---*/
Chris@4 82 /*---------------------------------------------------*/
Chris@4 83
Chris@4 84 /*---------------------------------------------*/
Chris@4 85 static void readError ( void )
Chris@4 86 {
Chris@4 87 fprintf ( stderr,
Chris@4 88 "%s: I/O error reading `%s', possible reason follows.\n",
Chris@4 89 progName, inFileName );
Chris@4 90 perror ( progName );
Chris@4 91 fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
Chris@4 92 progName );
Chris@4 93 exit ( 1 );
Chris@4 94 }
Chris@4 95
Chris@4 96
Chris@4 97 /*---------------------------------------------*/
Chris@4 98 static void writeError ( void )
Chris@4 99 {
Chris@4 100 fprintf ( stderr,
Chris@4 101 "%s: I/O error reading `%s', possible reason follows.\n",
Chris@4 102 progName, inFileName );
Chris@4 103 perror ( progName );
Chris@4 104 fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
Chris@4 105 progName );
Chris@4 106 exit ( 1 );
Chris@4 107 }
Chris@4 108
Chris@4 109
Chris@4 110 /*---------------------------------------------*/
Chris@4 111 static void mallocFail ( Int32 n )
Chris@4 112 {
Chris@4 113 fprintf ( stderr,
Chris@4 114 "%s: malloc failed on request for %d bytes.\n",
Chris@4 115 progName, n );
Chris@4 116 fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
Chris@4 117 progName );
Chris@4 118 exit ( 1 );
Chris@4 119 }
Chris@4 120
Chris@4 121
Chris@4 122 /*---------------------------------------------*/
Chris@4 123 static void tooManyBlocks ( Int32 max_handled_blocks )
Chris@4 124 {
Chris@4 125 fprintf ( stderr,
Chris@4 126 "%s: `%s' appears to contain more than %d blocks\n",
Chris@4 127 progName, inFileName, max_handled_blocks );
Chris@4 128 fprintf ( stderr,
Chris@4 129 "%s: and cannot be handled. To fix, increase\n",
Chris@4 130 progName );
Chris@4 131 fprintf ( stderr,
Chris@4 132 "%s: BZ_MAX_HANDLED_BLOCKS in bzip2recover.c, and recompile.\n",
Chris@4 133 progName );
Chris@4 134 exit ( 1 );
Chris@4 135 }
Chris@4 136
Chris@4 137
Chris@4 138
Chris@4 139 /*---------------------------------------------------*/
Chris@4 140 /*--- Bit stream I/O ---*/
Chris@4 141 /*---------------------------------------------------*/
Chris@4 142
Chris@4 143 typedef
Chris@4 144 struct {
Chris@4 145 FILE* handle;
Chris@4 146 Int32 buffer;
Chris@4 147 Int32 buffLive;
Chris@4 148 Char mode;
Chris@4 149 }
Chris@4 150 BitStream;
Chris@4 151
Chris@4 152
Chris@4 153 /*---------------------------------------------*/
Chris@4 154 static BitStream* bsOpenReadStream ( FILE* stream )
Chris@4 155 {
Chris@4 156 BitStream *bs = malloc ( sizeof(BitStream) );
Chris@4 157 if (bs == NULL) mallocFail ( sizeof(BitStream) );
Chris@4 158 bs->handle = stream;
Chris@4 159 bs->buffer = 0;
Chris@4 160 bs->buffLive = 0;
Chris@4 161 bs->mode = 'r';
Chris@4 162 return bs;
Chris@4 163 }
Chris@4 164
Chris@4 165
Chris@4 166 /*---------------------------------------------*/
Chris@4 167 static BitStream* bsOpenWriteStream ( FILE* stream )
Chris@4 168 {
Chris@4 169 BitStream *bs = malloc ( sizeof(BitStream) );
Chris@4 170 if (bs == NULL) mallocFail ( sizeof(BitStream) );
Chris@4 171 bs->handle = stream;
Chris@4 172 bs->buffer = 0;
Chris@4 173 bs->buffLive = 0;
Chris@4 174 bs->mode = 'w';
Chris@4 175 return bs;
Chris@4 176 }
Chris@4 177
Chris@4 178
Chris@4 179 /*---------------------------------------------*/
Chris@4 180 static void bsPutBit ( BitStream* bs, Int32 bit )
Chris@4 181 {
Chris@4 182 if (bs->buffLive == 8) {
Chris@4 183 Int32 retVal = putc ( (UChar) bs->buffer, bs->handle );
Chris@4 184 if (retVal == EOF) writeError();
Chris@4 185 bytesOut++;
Chris@4 186 bs->buffLive = 1;
Chris@4 187 bs->buffer = bit & 0x1;
Chris@4 188 } else {
Chris@4 189 bs->buffer = ( (bs->buffer << 1) | (bit & 0x1) );
Chris@4 190 bs->buffLive++;
Chris@4 191 };
Chris@4 192 }
Chris@4 193
Chris@4 194
Chris@4 195 /*---------------------------------------------*/
Chris@4 196 /*--
Chris@4 197 Returns 0 or 1, or 2 to indicate EOF.
Chris@4 198 --*/
Chris@4 199 static Int32 bsGetBit ( BitStream* bs )
Chris@4 200 {
Chris@4 201 if (bs->buffLive > 0) {
Chris@4 202 bs->buffLive --;
Chris@4 203 return ( ((bs->buffer) >> (bs->buffLive)) & 0x1 );
Chris@4 204 } else {
Chris@4 205 Int32 retVal = getc ( bs->handle );
Chris@4 206 if ( retVal == EOF ) {
Chris@4 207 if (errno != 0) readError();
Chris@4 208 return 2;
Chris@4 209 }
Chris@4 210 bs->buffLive = 7;
Chris@4 211 bs->buffer = retVal;
Chris@4 212 return ( ((bs->buffer) >> 7) & 0x1 );
Chris@4 213 }
Chris@4 214 }
Chris@4 215
Chris@4 216
Chris@4 217 /*---------------------------------------------*/
Chris@4 218 static void bsClose ( BitStream* bs )
Chris@4 219 {
Chris@4 220 Int32 retVal;
Chris@4 221
Chris@4 222 if ( bs->mode == 'w' ) {
Chris@4 223 while ( bs->buffLive < 8 ) {
Chris@4 224 bs->buffLive++;
Chris@4 225 bs->buffer <<= 1;
Chris@4 226 };
Chris@4 227 retVal = putc ( (UChar) (bs->buffer), bs->handle );
Chris@4 228 if (retVal == EOF) writeError();
Chris@4 229 bytesOut++;
Chris@4 230 retVal = fflush ( bs->handle );
Chris@4 231 if (retVal == EOF) writeError();
Chris@4 232 }
Chris@4 233 retVal = fclose ( bs->handle );
Chris@4 234 if (retVal == EOF) {
Chris@4 235 if (bs->mode == 'w') writeError(); else readError();
Chris@4 236 }
Chris@4 237 free ( bs );
Chris@4 238 }
Chris@4 239
Chris@4 240
Chris@4 241 /*---------------------------------------------*/
Chris@4 242 static void bsPutUChar ( BitStream* bs, UChar c )
Chris@4 243 {
Chris@4 244 Int32 i;
Chris@4 245 for (i = 7; i >= 0; i--)
Chris@4 246 bsPutBit ( bs, (((UInt32) c) >> i) & 0x1 );
Chris@4 247 }
Chris@4 248
Chris@4 249
Chris@4 250 /*---------------------------------------------*/
Chris@4 251 static void bsPutUInt32 ( BitStream* bs, UInt32 c )
Chris@4 252 {
Chris@4 253 Int32 i;
Chris@4 254
Chris@4 255 for (i = 31; i >= 0; i--)
Chris@4 256 bsPutBit ( bs, (c >> i) & 0x1 );
Chris@4 257 }
Chris@4 258
Chris@4 259
Chris@4 260 /*---------------------------------------------*/
Chris@4 261 static Bool endsInBz2 ( Char* name )
Chris@4 262 {
Chris@4 263 Int32 n = strlen ( name );
Chris@4 264 if (n <= 4) return False;
Chris@4 265 return
Chris@4 266 (name[n-4] == '.' &&
Chris@4 267 name[n-3] == 'b' &&
Chris@4 268 name[n-2] == 'z' &&
Chris@4 269 name[n-1] == '2');
Chris@4 270 }
Chris@4 271
Chris@4 272
Chris@4 273 /*---------------------------------------------------*/
Chris@4 274 /*--- ---*/
Chris@4 275 /*---------------------------------------------------*/
Chris@4 276
Chris@4 277 /* This logic isn't really right when it comes to Cygwin. */
Chris@4 278 #ifdef _WIN32
Chris@4 279 # define BZ_SPLIT_SYM '\\' /* path splitter on Windows platform */
Chris@4 280 #else
Chris@4 281 # define BZ_SPLIT_SYM '/' /* path splitter on Unix platform */
Chris@4 282 #endif
Chris@4 283
Chris@4 284 #define BLOCK_HEADER_HI 0x00003141UL
Chris@4 285 #define BLOCK_HEADER_LO 0x59265359UL
Chris@4 286
Chris@4 287 #define BLOCK_ENDMARK_HI 0x00001772UL
Chris@4 288 #define BLOCK_ENDMARK_LO 0x45385090UL
Chris@4 289
Chris@4 290 /* Increase if necessary. However, a .bz2 file with > 50000 blocks
Chris@4 291 would have an uncompressed size of at least 40GB, so the chances
Chris@4 292 are low you'll need to up this.
Chris@4 293 */
Chris@4 294 #define BZ_MAX_HANDLED_BLOCKS 50000
Chris@4 295
Chris@4 296 MaybeUInt64 bStart [BZ_MAX_HANDLED_BLOCKS];
Chris@4 297 MaybeUInt64 bEnd [BZ_MAX_HANDLED_BLOCKS];
Chris@4 298 MaybeUInt64 rbStart[BZ_MAX_HANDLED_BLOCKS];
Chris@4 299 MaybeUInt64 rbEnd [BZ_MAX_HANDLED_BLOCKS];
Chris@4 300
Chris@4 301 Int32 main ( Int32 argc, Char** argv )
Chris@4 302 {
Chris@4 303 FILE* inFile;
Chris@4 304 FILE* outFile;
Chris@4 305 BitStream* bsIn, *bsWr;
Chris@4 306 Int32 b, wrBlock, currBlock, rbCtr;
Chris@4 307 MaybeUInt64 bitsRead;
Chris@4 308
Chris@4 309 UInt32 buffHi, buffLo, blockCRC;
Chris@4 310 Char* p;
Chris@4 311
Chris@4 312 strcpy ( progName, argv[0] );
Chris@4 313 inFileName[0] = outFileName[0] = 0;
Chris@4 314
Chris@4 315 fprintf ( stderr,
Chris@4 316 "bzip2recover 1.0.6: extracts blocks from damaged .bz2 files.\n" );
Chris@4 317
Chris@4 318 if (argc != 2) {
Chris@4 319 fprintf ( stderr, "%s: usage is `%s damaged_file_name'.\n",
Chris@4 320 progName, progName );
Chris@4 321 switch (sizeof(MaybeUInt64)) {
Chris@4 322 case 8:
Chris@4 323 fprintf(stderr,
Chris@4 324 "\trestrictions on size of recovered file: None\n");
Chris@4 325 break;
Chris@4 326 case 4:
Chris@4 327 fprintf(stderr,
Chris@4 328 "\trestrictions on size of recovered file: 512 MB\n");
Chris@4 329 fprintf(stderr,
Chris@4 330 "\tto circumvent, recompile with MaybeUInt64 as an\n"
Chris@4 331 "\tunsigned 64-bit int.\n");
Chris@4 332 break;
Chris@4 333 default:
Chris@4 334 fprintf(stderr,
Chris@4 335 "\tsizeof(MaybeUInt64) is not 4 or 8 -- "
Chris@4 336 "configuration error.\n");
Chris@4 337 break;
Chris@4 338 }
Chris@4 339 exit(1);
Chris@4 340 }
Chris@4 341
Chris@4 342 if (strlen(argv[1]) >= BZ_MAX_FILENAME-20) {
Chris@4 343 fprintf ( stderr,
Chris@4 344 "%s: supplied filename is suspiciously (>= %d chars) long. Bye!\n",
Chris@4 345 progName, (int)strlen(argv[1]) );
Chris@4 346 exit(1);
Chris@4 347 }
Chris@4 348
Chris@4 349 strcpy ( inFileName, argv[1] );
Chris@4 350
Chris@4 351 inFile = fopen ( inFileName, "rb" );
Chris@4 352 if (inFile == NULL) {
Chris@4 353 fprintf ( stderr, "%s: can't read `%s'\n", progName, inFileName );
Chris@4 354 exit(1);
Chris@4 355 }
Chris@4 356
Chris@4 357 bsIn = bsOpenReadStream ( inFile );
Chris@4 358 fprintf ( stderr, "%s: searching for block boundaries ...\n", progName );
Chris@4 359
Chris@4 360 bitsRead = 0;
Chris@4 361 buffHi = buffLo = 0;
Chris@4 362 currBlock = 0;
Chris@4 363 bStart[currBlock] = 0;
Chris@4 364
Chris@4 365 rbCtr = 0;
Chris@4 366
Chris@4 367 while (True) {
Chris@4 368 b = bsGetBit ( bsIn );
Chris@4 369 bitsRead++;
Chris@4 370 if (b == 2) {
Chris@4 371 if (bitsRead >= bStart[currBlock] &&
Chris@4 372 (bitsRead - bStart[currBlock]) >= 40) {
Chris@4 373 bEnd[currBlock] = bitsRead-1;
Chris@4 374 if (currBlock > 0)
Chris@4 375 fprintf ( stderr, " block %d runs from " MaybeUInt64_FMT
Chris@4 376 " to " MaybeUInt64_FMT " (incomplete)\n",
Chris@4 377 currBlock, bStart[currBlock], bEnd[currBlock] );
Chris@4 378 } else
Chris@4 379 currBlock--;
Chris@4 380 break;
Chris@4 381 }
Chris@4 382 buffHi = (buffHi << 1) | (buffLo >> 31);
Chris@4 383 buffLo = (buffLo << 1) | (b & 1);
Chris@4 384 if ( ( (buffHi & 0x0000ffff) == BLOCK_HEADER_HI
Chris@4 385 && buffLo == BLOCK_HEADER_LO)
Chris@4 386 ||
Chris@4 387 ( (buffHi & 0x0000ffff) == BLOCK_ENDMARK_HI
Chris@4 388 && buffLo == BLOCK_ENDMARK_LO)
Chris@4 389 ) {
Chris@4 390 if (bitsRead > 49) {
Chris@4 391 bEnd[currBlock] = bitsRead-49;
Chris@4 392 } else {
Chris@4 393 bEnd[currBlock] = 0;
Chris@4 394 }
Chris@4 395 if (currBlock > 0 &&
Chris@4 396 (bEnd[currBlock] - bStart[currBlock]) >= 130) {
Chris@4 397 fprintf ( stderr, " block %d runs from " MaybeUInt64_FMT
Chris@4 398 " to " MaybeUInt64_FMT "\n",
Chris@4 399 rbCtr+1, bStart[currBlock], bEnd[currBlock] );
Chris@4 400 rbStart[rbCtr] = bStart[currBlock];
Chris@4 401 rbEnd[rbCtr] = bEnd[currBlock];
Chris@4 402 rbCtr++;
Chris@4 403 }
Chris@4 404 if (currBlock >= BZ_MAX_HANDLED_BLOCKS)
Chris@4 405 tooManyBlocks(BZ_MAX_HANDLED_BLOCKS);
Chris@4 406 currBlock++;
Chris@4 407
Chris@4 408 bStart[currBlock] = bitsRead;
Chris@4 409 }
Chris@4 410 }
Chris@4 411
Chris@4 412 bsClose ( bsIn );
Chris@4 413
Chris@4 414 /*-- identified blocks run from 1 to rbCtr inclusive. --*/
Chris@4 415
Chris@4 416 if (rbCtr < 1) {
Chris@4 417 fprintf ( stderr,
Chris@4 418 "%s: sorry, I couldn't find any block boundaries.\n",
Chris@4 419 progName );
Chris@4 420 exit(1);
Chris@4 421 };
Chris@4 422
Chris@4 423 fprintf ( stderr, "%s: splitting into blocks\n", progName );
Chris@4 424
Chris@4 425 inFile = fopen ( inFileName, "rb" );
Chris@4 426 if (inFile == NULL) {
Chris@4 427 fprintf ( stderr, "%s: can't open `%s'\n", progName, inFileName );
Chris@4 428 exit(1);
Chris@4 429 }
Chris@4 430 bsIn = bsOpenReadStream ( inFile );
Chris@4 431
Chris@4 432 /*-- placate gcc's dataflow analyser --*/
Chris@4 433 blockCRC = 0; bsWr = 0;
Chris@4 434
Chris@4 435 bitsRead = 0;
Chris@4 436 outFile = NULL;
Chris@4 437 wrBlock = 0;
Chris@4 438 while (True) {
Chris@4 439 b = bsGetBit(bsIn);
Chris@4 440 if (b == 2) break;
Chris@4 441 buffHi = (buffHi << 1) | (buffLo >> 31);
Chris@4 442 buffLo = (buffLo << 1) | (b & 1);
Chris@4 443 if (bitsRead == 47+rbStart[wrBlock])
Chris@4 444 blockCRC = (buffHi << 16) | (buffLo >> 16);
Chris@4 445
Chris@4 446 if (outFile != NULL && bitsRead >= rbStart[wrBlock]
Chris@4 447 && bitsRead <= rbEnd[wrBlock]) {
Chris@4 448 bsPutBit ( bsWr, b );
Chris@4 449 }
Chris@4 450
Chris@4 451 bitsRead++;
Chris@4 452
Chris@4 453 if (bitsRead == rbEnd[wrBlock]+1) {
Chris@4 454 if (outFile != NULL) {
Chris@4 455 bsPutUChar ( bsWr, 0x17 ); bsPutUChar ( bsWr, 0x72 );
Chris@4 456 bsPutUChar ( bsWr, 0x45 ); bsPutUChar ( bsWr, 0x38 );
Chris@4 457 bsPutUChar ( bsWr, 0x50 ); bsPutUChar ( bsWr, 0x90 );
Chris@4 458 bsPutUInt32 ( bsWr, blockCRC );
Chris@4 459 bsClose ( bsWr );
Chris@4 460 }
Chris@4 461 if (wrBlock >= rbCtr) break;
Chris@4 462 wrBlock++;
Chris@4 463 } else
Chris@4 464 if (bitsRead == rbStart[wrBlock]) {
Chris@4 465 /* Create the output file name, correctly handling leading paths.
Chris@4 466 (31.10.2001 by Sergey E. Kusikov) */
Chris@4 467 Char* split;
Chris@4 468 Int32 ofs, k;
Chris@4 469 for (k = 0; k < BZ_MAX_FILENAME; k++)
Chris@4 470 outFileName[k] = 0;
Chris@4 471 strcpy (outFileName, inFileName);
Chris@4 472 split = strrchr (outFileName, BZ_SPLIT_SYM);
Chris@4 473 if (split == NULL) {
Chris@4 474 split = outFileName;
Chris@4 475 } else {
Chris@4 476 ++split;
Chris@4 477 }
Chris@4 478 /* Now split points to the start of the basename. */
Chris@4 479 ofs = split - outFileName;
Chris@4 480 sprintf (split, "rec%5d", wrBlock+1);
Chris@4 481 for (p = split; *p != 0; p++) if (*p == ' ') *p = '0';
Chris@4 482 strcat (outFileName, inFileName + ofs);
Chris@4 483
Chris@4 484 if ( !endsInBz2(outFileName)) strcat ( outFileName, ".bz2" );
Chris@4 485
Chris@4 486 fprintf ( stderr, " writing block %d to `%s' ...\n",
Chris@4 487 wrBlock+1, outFileName );
Chris@4 488
Chris@4 489 outFile = fopen ( outFileName, "wb" );
Chris@4 490 if (outFile == NULL) {
Chris@4 491 fprintf ( stderr, "%s: can't write `%s'\n",
Chris@4 492 progName, outFileName );
Chris@4 493 exit(1);
Chris@4 494 }
Chris@4 495 bsWr = bsOpenWriteStream ( outFile );
Chris@4 496 bsPutUChar ( bsWr, BZ_HDR_B );
Chris@4 497 bsPutUChar ( bsWr, BZ_HDR_Z );
Chris@4 498 bsPutUChar ( bsWr, BZ_HDR_h );
Chris@4 499 bsPutUChar ( bsWr, BZ_HDR_0 + 9 );
Chris@4 500 bsPutUChar ( bsWr, 0x31 ); bsPutUChar ( bsWr, 0x41 );
Chris@4 501 bsPutUChar ( bsWr, 0x59 ); bsPutUChar ( bsWr, 0x26 );
Chris@4 502 bsPutUChar ( bsWr, 0x53 ); bsPutUChar ( bsWr, 0x59 );
Chris@4 503 }
Chris@4 504 }
Chris@4 505
Chris@4 506 fprintf ( stderr, "%s: finished\n", progName );
Chris@4 507 return 0;
Chris@4 508 }
Chris@4 509
Chris@4 510
Chris@4 511
Chris@4 512 /*-----------------------------------------------------------*/
Chris@4 513 /*--- end bzip2recover.c ---*/
Chris@4 514 /*-----------------------------------------------------------*/