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