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