Blame bzip2recover.c

Packit 71fd91
/*-----------------------------------------------------------*/
Packit 71fd91
/*--- Block recoverer program for bzip2                   ---*/
Packit 71fd91
/*---                                      bzip2recover.c ---*/
Packit 71fd91
/*-----------------------------------------------------------*/
Packit 71fd91
Packit 71fd91
/* ------------------------------------------------------------------
Packit 71fd91
   This file is part of bzip2/libbzip2, a program and library for
Packit 71fd91
   lossless, block-sorting data compression.
Packit 71fd91
Packit 71fd91
   bzip2/libbzip2 version 1.0.6 of 6 September 2010
Packit 71fd91
   Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Packit 71fd91
Packit 71fd91
   Please read the WARNING, DISCLAIMER and PATENTS sections in the 
Packit 71fd91
   README file.
Packit 71fd91
Packit 71fd91
   This program is released under the terms of the license contained
Packit 71fd91
   in the file LICENSE.
Packit 71fd91
   ------------------------------------------------------------------ */
Packit 71fd91
Packit 71fd91
/* This program is a complete hack and should be rewritten properly.
Packit 71fd91
	 It isn't very complicated. */
Packit 71fd91
Packit 71fd91
#include <stdio.h>
Packit 71fd91
#include <errno.h>
Packit 71fd91
#include <stdlib.h>
Packit 71fd91
#include <string.h>
Packit 71fd91
Packit 71fd91
Packit 71fd91
/* This program records bit locations in the file to be recovered.
Packit 71fd91
   That means that if 64-bit ints are not supported, we will not
Packit 71fd91
   be able to recover .bz2 files over 512MB (2^32 bits) long.
Packit 71fd91
   On GNU supported platforms, we take advantage of the 64-bit
Packit 71fd91
   int support to circumvent this problem.  Ditto MSVC.
Packit 71fd91
Packit 71fd91
   This change occurred in version 1.0.2; all prior versions have
Packit 71fd91
   the 512MB limitation.
Packit 71fd91
*/
Packit 71fd91
#ifdef __GNUC__
Packit 71fd91
   typedef  unsigned long long int  MaybeUInt64;
Packit 71fd91
#  define MaybeUInt64_FMT "%Lu"
Packit 71fd91
#else
Packit 71fd91
#ifdef _MSC_VER
Packit 71fd91
   typedef  unsigned __int64  MaybeUInt64;
Packit 71fd91
#  define MaybeUInt64_FMT "%I64u"
Packit 71fd91
#else
Packit 71fd91
   typedef  unsigned int   MaybeUInt64;
Packit 71fd91
#  define MaybeUInt64_FMT "%u"
Packit 71fd91
#endif
Packit 71fd91
#endif
Packit 71fd91
Packit 71fd91
typedef  unsigned int   UInt32;
Packit 71fd91
typedef  int            Int32;
Packit 71fd91
typedef  unsigned char  UChar;
Packit 71fd91
typedef  char           Char;
Packit 71fd91
typedef  unsigned char  Bool;
Packit 71fd91
#define True    ((Bool)1)
Packit 71fd91
#define False   ((Bool)0)
Packit 71fd91
Packit 71fd91
Packit 71fd91
#define BZ_MAX_FILENAME 2000
Packit 71fd91
Packit 71fd91
Char inFileName[BZ_MAX_FILENAME];
Packit 71fd91
Char outFileName[BZ_MAX_FILENAME];
Packit 71fd91
Char progName[BZ_MAX_FILENAME];
Packit 71fd91
Packit 71fd91
MaybeUInt64 bytesOut = 0;
Packit 71fd91
MaybeUInt64 bytesIn  = 0;
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
/*--- Header bytes                                ---*/
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
Packit 71fd91
#define BZ_HDR_B 0x42                         /* 'B' */
Packit 71fd91
#define BZ_HDR_Z 0x5a                         /* 'Z' */
Packit 71fd91
#define BZ_HDR_h 0x68                         /* 'h' */
Packit 71fd91
#define BZ_HDR_0 0x30                         /* '0' */
Packit 71fd91
 
Packit 71fd91
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
/*--- I/O errors                                  ---*/
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static void readError ( void )
Packit 71fd91
{
Packit 71fd91
   fprintf ( stderr,
Packit 71fd91
             "%s: I/O error reading `%s', possible reason follows.\n",
Packit 71fd91
            progName, inFileName );
Packit 71fd91
   perror ( progName );
Packit 71fd91
   fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
Packit 71fd91
             progName );
Packit 71fd91
   exit ( 1 );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static void writeError ( void )
Packit 71fd91
{
Packit 71fd91
   fprintf ( stderr,
Packit 71fd91
             "%s: I/O error reading `%s', possible reason follows.\n",
Packit 71fd91
            progName, inFileName );
Packit 71fd91
   perror ( progName );
Packit 71fd91
   fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
Packit 71fd91
             progName );
Packit 71fd91
   exit ( 1 );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static void mallocFail ( Int32 n )
Packit 71fd91
{
Packit 71fd91
   fprintf ( stderr,
Packit 71fd91
             "%s: malloc failed on request for %d bytes.\n",
Packit 71fd91
            progName, n );
Packit 71fd91
   fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
Packit 71fd91
             progName );
Packit 71fd91
   exit ( 1 );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static void tooManyBlocks ( Int32 max_handled_blocks )
Packit 71fd91
{
Packit 71fd91
   fprintf ( stderr,
Packit 71fd91
             "%s: `%s' appears to contain more than %d blocks\n",
Packit 71fd91
            progName, inFileName, max_handled_blocks );
Packit 71fd91
   fprintf ( stderr,
Packit 71fd91
             "%s: and cannot be handled.  To fix, increase\n",
Packit 71fd91
             progName );
Packit 71fd91
   fprintf ( stderr, 
Packit 71fd91
             "%s: BZ_MAX_HANDLED_BLOCKS in bzip2recover.c, and recompile.\n",
Packit 71fd91
             progName );
Packit 71fd91
   exit ( 1 );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
/*--- Bit stream I/O                              ---*/
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
Packit 71fd91
typedef
Packit 71fd91
   struct {
Packit 71fd91
      FILE*  handle;
Packit 71fd91
      Int32  buffer;
Packit 71fd91
      Int32  buffLive;
Packit 71fd91
      Char   mode;
Packit 71fd91
   }
Packit 71fd91
   BitStream;
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static BitStream* bsOpenReadStream ( FILE* stream )
Packit 71fd91
{
Packit 71fd91
   BitStream *bs = malloc ( sizeof(BitStream) );
Packit 71fd91
   if (bs == NULL) mallocFail ( sizeof(BitStream) );
Packit 71fd91
   bs->handle = stream;
Packit 71fd91
   bs->buffer = 0;
Packit 71fd91
   bs->buffLive = 0;
Packit 71fd91
   bs->mode = 'r';
Packit 71fd91
   return bs;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static BitStream* bsOpenWriteStream ( FILE* stream )
Packit 71fd91
{
Packit 71fd91
   BitStream *bs = malloc ( sizeof(BitStream) );
Packit 71fd91
   if (bs == NULL) mallocFail ( sizeof(BitStream) );
Packit 71fd91
   bs->handle = stream;
Packit 71fd91
   bs->buffer = 0;
Packit 71fd91
   bs->buffLive = 0;
Packit 71fd91
   bs->mode = 'w';
Packit 71fd91
   return bs;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static void bsPutBit ( BitStream* bs, Int32 bit )
Packit 71fd91
{
Packit 71fd91
   if (bs->buffLive == 8) {
Packit 71fd91
      Int32 retVal = putc ( (UChar) bs->buffer, bs->handle );
Packit 71fd91
      if (retVal == EOF) writeError();
Packit 71fd91
      bytesOut++;
Packit 71fd91
      bs->buffLive = 1;
Packit 71fd91
      bs->buffer = bit & 0x1;
Packit 71fd91
   } else {
Packit 71fd91
      bs->buffer = ( (bs->buffer << 1) | (bit & 0x1) );
Packit 71fd91
      bs->buffLive++;
Packit 71fd91
   };
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/*--
Packit 71fd91
   Returns 0 or 1, or 2 to indicate EOF.
Packit 71fd91
--*/
Packit 71fd91
static Int32 bsGetBit ( BitStream* bs )
Packit 71fd91
{
Packit 71fd91
   if (bs->buffLive > 0) {
Packit 71fd91
      bs->buffLive --;
Packit 71fd91
      return ( ((bs->buffer) >> (bs->buffLive)) & 0x1 );
Packit 71fd91
   } else {
Packit 71fd91
      Int32 retVal = getc ( bs->handle );
Packit 71fd91
      if ( retVal == EOF ) {
Packit 71fd91
         if (errno != 0) readError();
Packit 71fd91
         return 2;
Packit 71fd91
      }
Packit 71fd91
      bs->buffLive = 7;
Packit 71fd91
      bs->buffer = retVal;
Packit 71fd91
      return ( ((bs->buffer) >> 7) & 0x1 );
Packit 71fd91
   }
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static void bsClose ( BitStream* bs )
Packit 71fd91
{
Packit 71fd91
   Int32 retVal;
Packit 71fd91
Packit 71fd91
   if ( bs->mode == 'w' ) {
Packit 71fd91
      while ( bs->buffLive < 8 ) {
Packit 71fd91
         bs->buffLive++;
Packit 71fd91
         bs->buffer <<= 1;
Packit 71fd91
      };
Packit 71fd91
      retVal = putc ( (UChar) (bs->buffer), bs->handle );
Packit 71fd91
      if (retVal == EOF) writeError();
Packit 71fd91
      bytesOut++;
Packit 71fd91
      retVal = fflush ( bs->handle );
Packit 71fd91
      if (retVal == EOF) writeError();
Packit 71fd91
   }
Packit 71fd91
   retVal = fclose ( bs->handle );
Packit 71fd91
   if (retVal == EOF) {
Packit 71fd91
      if (bs->mode == 'w') writeError(); else readError();
Packit 71fd91
   }
Packit 71fd91
   free ( bs );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static void bsPutUChar ( BitStream* bs, UChar c )
Packit 71fd91
{
Packit 71fd91
   Int32 i;
Packit 71fd91
   for (i = 7; i >= 0; i--)
Packit 71fd91
      bsPutBit ( bs, (((UInt32) c) >> i) & 0x1 );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static void bsPutUInt32 ( BitStream* bs, UInt32 c )
Packit 71fd91
{
Packit 71fd91
   Int32 i;
Packit 71fd91
Packit 71fd91
   for (i = 31; i >= 0; i--)
Packit 71fd91
      bsPutBit ( bs, (c >> i) & 0x1 );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static Bool endsInBz2 ( Char* name )
Packit 71fd91
{
Packit 71fd91
   Int32 n = strlen ( name );
Packit 71fd91
   if (n <= 4) return False;
Packit 71fd91
   return
Packit 71fd91
      (name[n-4] == '.' &&
Packit 71fd91
       name[n-3] == 'b' &&
Packit 71fd91
       name[n-2] == 'z' &&
Packit 71fd91
       name[n-1] == '2');
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
/*---                                             ---*/
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
Packit 71fd91
/* This logic isn't really right when it comes to Cygwin. */
Packit 71fd91
#ifdef _WIN32
Packit 71fd91
#  define  BZ_SPLIT_SYM  '\\'  /* path splitter on Windows platform */
Packit 71fd91
#else
Packit 71fd91
#  define  BZ_SPLIT_SYM  '/'   /* path splitter on Unix platform */
Packit 71fd91
#endif
Packit 71fd91
Packit 71fd91
#define BLOCK_HEADER_HI  0x00003141UL
Packit 71fd91
#define BLOCK_HEADER_LO  0x59265359UL
Packit 71fd91
Packit 71fd91
#define BLOCK_ENDMARK_HI 0x00001772UL
Packit 71fd91
#define BLOCK_ENDMARK_LO 0x45385090UL
Packit 71fd91
Packit 71fd91
/* Increase if necessary.  However, a .bz2 file with > 50000 blocks
Packit 71fd91
   would have an uncompressed size of at least 40GB, so the chances
Packit 71fd91
   are low you'll need to up this.
Packit 71fd91
*/
Packit 71fd91
#define BZ_MAX_HANDLED_BLOCKS 50000
Packit 71fd91
Packit 71fd91
MaybeUInt64 bStart [BZ_MAX_HANDLED_BLOCKS];
Packit 71fd91
MaybeUInt64 bEnd   [BZ_MAX_HANDLED_BLOCKS];
Packit 71fd91
MaybeUInt64 rbStart[BZ_MAX_HANDLED_BLOCKS];
Packit 71fd91
MaybeUInt64 rbEnd  [BZ_MAX_HANDLED_BLOCKS];
Packit 71fd91
Packit 71fd91
Int32 main ( Int32 argc, Char** argv )
Packit 71fd91
{
Packit 71fd91
   FILE*       inFile;
Packit 71fd91
   FILE*       outFile;
Packit 71fd91
   BitStream*  bsIn, *bsWr;
Packit 71fd91
   Int32       b, wrBlock, currBlock, rbCtr;
Packit 71fd91
   MaybeUInt64 bitsRead;
Packit 71fd91
Packit 71fd91
   UInt32      buffHi, buffLo, blockCRC;
Packit 71fd91
   Char*       p;
Packit 71fd91
Packit Service 59ec92
   strncpy ( progName, argv[0], BZ_MAX_FILENAME-1);
Packit Service 59ec92
   progName[BZ_MAX_FILENAME-1]='\0';
Packit 71fd91
   inFileName[0] = outFileName[0] = 0;
Packit 71fd91
Packit 71fd91
   fprintf ( stderr, 
Packit 71fd91
             "bzip2recover 1.0.6: extracts blocks from damaged .bz2 files.\n" );
Packit 71fd91
Packit 71fd91
   if (argc != 2) {
Packit 71fd91
      fprintf ( stderr, "%s: usage is `%s damaged_file_name'.\n",
Packit 71fd91
                        progName, progName );
Packit 71fd91
      switch (sizeof(MaybeUInt64)) {
Packit 71fd91
         case 8:
Packit 71fd91
            fprintf(stderr, 
Packit 71fd91
                    "\trestrictions on size of recovered file: None\n");
Packit 71fd91
            break;
Packit 71fd91
         case 4:
Packit 71fd91
            fprintf(stderr, 
Packit 71fd91
                    "\trestrictions on size of recovered file: 512 MB\n");
Packit 71fd91
            fprintf(stderr, 
Packit 71fd91
                    "\tto circumvent, recompile with MaybeUInt64 as an\n"
Packit 71fd91
                    "\tunsigned 64-bit int.\n");
Packit 71fd91
            break;
Packit 71fd91
         default:
Packit 71fd91
            fprintf(stderr, 
Packit 71fd91
                    "\tsizeof(MaybeUInt64) is not 4 or 8 -- "
Packit 71fd91
                    "configuration error.\n");
Packit 71fd91
            break;
Packit 71fd91
      }
Packit 71fd91
      exit(1);
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   if (strlen(argv[1]) >= BZ_MAX_FILENAME-20) {
Packit 71fd91
      fprintf ( stderr, 
Packit 71fd91
                "%s: supplied filename is suspiciously (>= %d chars) long.  Bye!\n",
Packit 71fd91
                progName, (int)strlen(argv[1]) );
Packit 71fd91
      exit(1);
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   strcpy ( inFileName, argv[1] );
Packit 71fd91
Packit 71fd91
   inFile = fopen ( inFileName, "rb" );
Packit 71fd91
   if (inFile == NULL) {
Packit 71fd91
      fprintf ( stderr, "%s: can't read `%s'\n", progName, inFileName );
Packit 71fd91
      exit(1);
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   bsIn = bsOpenReadStream ( inFile );
Packit 71fd91
   fprintf ( stderr, "%s: searching for block boundaries ...\n", progName );
Packit 71fd91
Packit 71fd91
   bitsRead = 0;
Packit 71fd91
   buffHi = buffLo = 0;
Packit 71fd91
   currBlock = 0;
Packit 71fd91
   bStart[currBlock] = 0;
Packit 71fd91
Packit 71fd91
   rbCtr = 0;
Packit 71fd91
Packit 71fd91
   while (True) {
Packit 71fd91
      b = bsGetBit ( bsIn );
Packit 71fd91
      bitsRead++;
Packit 71fd91
      if (b == 2) {
Packit 71fd91
         if (bitsRead >= bStart[currBlock] &&
Packit 71fd91
            (bitsRead - bStart[currBlock]) >= 40) {
Packit 71fd91
            bEnd[currBlock] = bitsRead-1;
Packit 71fd91
            if (currBlock > 0)
Packit 71fd91
               fprintf ( stderr, "   block %d runs from " MaybeUInt64_FMT 
Packit 71fd91
                                 " to " MaybeUInt64_FMT " (incomplete)\n",
Packit 71fd91
                         currBlock,  bStart[currBlock], bEnd[currBlock] );
Packit 71fd91
         } else
Packit 71fd91
            currBlock--;
Packit 71fd91
         break;
Packit 71fd91
      }
Packit 71fd91
      buffHi = (buffHi << 1) | (buffLo >> 31);
Packit 71fd91
      buffLo = (buffLo << 1) | (b & 1);
Packit 71fd91
      if ( ( (buffHi & 0x0000ffff) == BLOCK_HEADER_HI 
Packit 71fd91
             && buffLo == BLOCK_HEADER_LO)
Packit 71fd91
           || 
Packit 71fd91
           ( (buffHi & 0x0000ffff) == BLOCK_ENDMARK_HI 
Packit 71fd91
             && buffLo == BLOCK_ENDMARK_LO)
Packit 71fd91
         ) {
Packit 71fd91
         if (bitsRead > 49) {
Packit 71fd91
            bEnd[currBlock] = bitsRead-49;
Packit 71fd91
         } else {
Packit 71fd91
            bEnd[currBlock] = 0;
Packit 71fd91
         }
Packit 71fd91
         if (currBlock > 0 &&
Packit 71fd91
	     (bEnd[currBlock] - bStart[currBlock]) >= 130) {
Packit 71fd91
            fprintf ( stderr, "   block %d runs from " MaybeUInt64_FMT 
Packit 71fd91
                              " to " MaybeUInt64_FMT "\n",
Packit 71fd91
                      rbCtr+1,  bStart[currBlock], bEnd[currBlock] );
Packit 71fd91
            rbStart[rbCtr] = bStart[currBlock];
Packit 71fd91
            rbEnd[rbCtr] = bEnd[currBlock];
Packit 71fd91
            rbCtr++;
Packit 71fd91
         }
Packit 71fd91
         if (currBlock >= BZ_MAX_HANDLED_BLOCKS)
Packit 71fd91
            tooManyBlocks(BZ_MAX_HANDLED_BLOCKS);
Packit 71fd91
         currBlock++;
Packit 71fd91
Packit 71fd91
         bStart[currBlock] = bitsRead;
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   bsClose ( bsIn );
Packit 71fd91
Packit 71fd91
   /*-- identified blocks run from 1 to rbCtr inclusive. --*/
Packit 71fd91
Packit 71fd91
   if (rbCtr < 1) {
Packit 71fd91
      fprintf ( stderr,
Packit 71fd91
                "%s: sorry, I couldn't find any block boundaries.\n",
Packit 71fd91
                progName );
Packit 71fd91
      exit(1);
Packit 71fd91
   };
Packit 71fd91
Packit 71fd91
   fprintf ( stderr, "%s: splitting into blocks\n", progName );
Packit 71fd91
Packit 71fd91
   inFile = fopen ( inFileName, "rb" );
Packit 71fd91
   if (inFile == NULL) {
Packit 71fd91
      fprintf ( stderr, "%s: can't open `%s'\n", progName, inFileName );
Packit 71fd91
      exit(1);
Packit 71fd91
   }
Packit 71fd91
   bsIn = bsOpenReadStream ( inFile );
Packit 71fd91
Packit 71fd91
   /*-- placate gcc's dataflow analyser --*/
Packit 71fd91
   blockCRC = 0; bsWr = 0;
Packit 71fd91
Packit 71fd91
   bitsRead = 0;
Packit 71fd91
   outFile = NULL;
Packit 71fd91
   wrBlock = 0;
Packit 71fd91
   while (True) {
Packit 71fd91
      b = bsGetBit(bsIn);
Packit 71fd91
      if (b == 2) break;
Packit 71fd91
      buffHi = (buffHi << 1) | (buffLo >> 31);
Packit 71fd91
      buffLo = (buffLo << 1) | (b & 1);
Packit 71fd91
      if (bitsRead == 47+rbStart[wrBlock]) 
Packit 71fd91
         blockCRC = (buffHi << 16) | (buffLo >> 16);
Packit 71fd91
Packit 71fd91
      if (outFile != NULL && bitsRead >= rbStart[wrBlock]
Packit 71fd91
                          && bitsRead <= rbEnd[wrBlock]) {
Packit 71fd91
         bsPutBit ( bsWr, b );
Packit 71fd91
      }
Packit 71fd91
Packit 71fd91
      bitsRead++;
Packit 71fd91
Packit 71fd91
      if (bitsRead == rbEnd[wrBlock]+1) {
Packit 71fd91
         if (outFile != NULL) {
Packit 71fd91
            bsPutUChar ( bsWr, 0x17 ); bsPutUChar ( bsWr, 0x72 );
Packit 71fd91
            bsPutUChar ( bsWr, 0x45 ); bsPutUChar ( bsWr, 0x38 );
Packit 71fd91
            bsPutUChar ( bsWr, 0x50 ); bsPutUChar ( bsWr, 0x90 );
Packit 71fd91
            bsPutUInt32 ( bsWr, blockCRC );
Packit 71fd91
            bsClose ( bsWr );
Packit Service aedd59
            outFile = NULL;
Packit 71fd91
         }
Packit 71fd91
         if (wrBlock >= rbCtr) break;
Packit 71fd91
         wrBlock++;
Packit 71fd91
      } else
Packit 71fd91
      if (bitsRead == rbStart[wrBlock]) {
Packit 71fd91
         /* Create the output file name, correctly handling leading paths. 
Packit 71fd91
            (31.10.2001 by Sergey E. Kusikov) */
Packit 71fd91
         Char* split;
Packit 71fd91
         Int32 ofs, k;
Packit 71fd91
         for (k = 0; k < BZ_MAX_FILENAME; k++) 
Packit 71fd91
            outFileName[k] = 0;
Packit 71fd91
         strcpy (outFileName, inFileName);
Packit 71fd91
         split = strrchr (outFileName, BZ_SPLIT_SYM);
Packit 71fd91
         if (split == NULL) {
Packit 71fd91
            split = outFileName;
Packit 71fd91
         } else {
Packit 71fd91
            ++split;
Packit 71fd91
	 }
Packit 71fd91
	 /* Now split points to the start of the basename. */
Packit 71fd91
         ofs  = split - outFileName;
Packit 71fd91
         sprintf (split, "rec%5d", wrBlock+1);
Packit 71fd91
         for (p = split; *p != 0; p++) if (*p == ' ') *p = '0';
Packit 71fd91
         strcat (outFileName, inFileName + ofs);
Packit 71fd91
Packit 71fd91
         if ( !endsInBz2(outFileName)) strcat ( outFileName, ".bz2" );
Packit 71fd91
Packit 71fd91
         fprintf ( stderr, "   writing block %d to `%s' ...\n",
Packit 71fd91
                           wrBlock+1, outFileName );
Packit 71fd91
Packit 71fd91
         outFile = fopen ( outFileName, "wb" );
Packit 71fd91
         if (outFile == NULL) {
Packit 71fd91
            fprintf ( stderr, "%s: can't write `%s'\n",
Packit 71fd91
                      progName, outFileName );
Packit 71fd91
            exit(1);
Packit 71fd91
         }
Packit 71fd91
         bsWr = bsOpenWriteStream ( outFile );
Packit 71fd91
         bsPutUChar ( bsWr, BZ_HDR_B );    
Packit 71fd91
         bsPutUChar ( bsWr, BZ_HDR_Z );    
Packit 71fd91
         bsPutUChar ( bsWr, BZ_HDR_h );    
Packit 71fd91
         bsPutUChar ( bsWr, BZ_HDR_0 + 9 );
Packit 71fd91
         bsPutUChar ( bsWr, 0x31 ); bsPutUChar ( bsWr, 0x41 );
Packit 71fd91
         bsPutUChar ( bsWr, 0x59 ); bsPutUChar ( bsWr, 0x26 );
Packit 71fd91
         bsPutUChar ( bsWr, 0x53 ); bsPutUChar ( bsWr, 0x59 );
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   fprintf ( stderr, "%s: finished\n", progName );
Packit 71fd91
   return 0;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*-----------------------------------------------------------*/
Packit 71fd91
/*--- end                                  bzip2recover.c ---*/
Packit 71fd91
/*-----------------------------------------------------------*/