bzip2recover.c revision 199767f8919635c4928607450d9e0abb932109ce
/*-----------------------------------------------------------*/
/*--- Block recoverer program for bzip2 ---*/
/*--- bzip2recover.c ---*/
/*-----------------------------------------------------------*/
/* ------------------------------------------------------------------
lossless, block-sorting data compression.
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.
This program is released under the terms of the license contained
in the file LICENSE.
------------------------------------------------------------------ */
/* This program is a complete hack and should be rewritten properly.
It isn't very complicated. */
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
/* This program records bit locations in the file to be recovered.
That means that if 64-bit ints are not supported, we will not
be able to recover .bz2 files over 512MB (2^32 bits) long.
On GNU supported platforms, we take advantage of the 64-bit
int support to circumvent this problem. Ditto MSVC.
This change occurred in version 1.0.2; all prior versions have
the 512MB limitation.
*/
#ifdef __GNUC__
typedef unsigned long long int MaybeUInt64;
# define MaybeUInt64_FMT "%llu"
#else
#ifdef _MSC_VER
typedef unsigned __int64 MaybeUInt64;
# define MaybeUInt64_FMT "%I64u"
#else
typedef unsigned int MaybeUInt64;
# define MaybeUInt64_FMT "%u"
#endif
#endif
typedef unsigned int UInt32;
typedef int Int32;
typedef unsigned char UChar;
typedef char Char;
typedef unsigned char Bool;
#define BZ_MAX_FILENAME 2000
MaybeUInt64 bytesOut = 0;
MaybeUInt64 bytesIn = 0;
/*---------------------------------------------------*/
/*--- Header bytes ---*/
/*---------------------------------------------------*/
/*---------------------------------------------------*/
/*--- I/O errors ---*/
/*---------------------------------------------------*/
/*---------------------------------------------*/
static void readError ( void )
{
"%s: I/O error reading `%s', possible reason follows.\n",
progName, inFileName );
progName );
exit ( 1 );
}
/*---------------------------------------------*/
static void writeError ( void )
{
"%s: I/O error reading `%s', possible reason follows.\n",
progName, inFileName );
progName );
exit ( 1 );
}
/*---------------------------------------------*/
static void mallocFail ( Int32 n )
{
"%s: malloc failed on request for %d bytes.\n",
progName, n );
progName );
exit ( 1 );
}
/*---------------------------------------------*/
{
"%s: `%s' appears to contain more than %d blocks\n",
"%s: and cannot be handled. To fix, increase\n",
progName );
"%s: BZ_MAX_HANDLED_BLOCKS in bzip2recover.c, and recompile.\n",
progName );
exit ( 1 );
}
/*---------------------------------------------------*/
/*--- Bit stream I/O ---*/
/*---------------------------------------------------*/
typedef
struct {
}
/*---------------------------------------------*/
{
return bs;
}
/*---------------------------------------------*/
{
return bs;
}
/*---------------------------------------------*/
{
bytesOut++;
} else {
};
}
/*---------------------------------------------*/
/*--
Returns 0 or 1, or 2 to indicate EOF.
--*/
{
} else {
return 2;
}
}
}
/*---------------------------------------------*/
{
};
bytesOut++;
}
}
}
/*---------------------------------------------*/
{
Int32 i;
for (i = 7; i >= 0; i--)
}
/*---------------------------------------------*/
{
Int32 i;
for (i = 31; i >= 0; i--)
}
/*---------------------------------------------*/
{
if (n <= 4) return False;
return
}
/*---------------------------------------------------*/
/*--- ---*/
/*---------------------------------------------------*/
/* This logic isn't really right when it comes to Cygwin. */
#ifdef _WIN32
#else
#endif
#define BLOCK_HEADER_HI 0x00003141UL
#define BLOCK_HEADER_LO 0x59265359UL
#define BLOCK_ENDMARK_HI 0x00001772UL
#define BLOCK_ENDMARK_LO 0x45385090UL
/* Increase if necessary. However, a .bz2 file with > 50000 blocks
would have an uncompressed size of at least 40GB, so the chances
are low you'll need to up this.
*/
#define BZ_MAX_HANDLED_BLOCKS 50000
{
Char* p;
inFileName[0] = outFileName[0] = 0;
"bzip2recover 1.0.6: extracts blocks from damaged .bz2 files.\n" );
if (argc != 2) {
switch (sizeof(MaybeUInt64)) {
case 8:
"\trestrictions on size of recovered file: None\n");
break;
case 4:
"\trestrictions on size of recovered file: 512 MB\n");
"\tto circumvent, recompile with MaybeUInt64 as an\n"
"\tunsigned 64-bit int.\n");
break;
default:
"\tsizeof(MaybeUInt64) is not 4 or 8 -- "
"configuration error.\n");
break;
}
exit(1);
}
"%s: supplied filename is suspiciously (>= %d chars) long. Bye!\n",
exit(1);
}
exit(1);
}
bitsRead = 0;
currBlock = 0;
rbCtr = 0;
while (True) {
bitsRead++;
if (b == 2) {
if (currBlock > 0)
} else
currBlock--;
break;
}
&& buffLo == BLOCK_HEADER_LO)
||
&& buffLo == BLOCK_ENDMARK_LO)
) {
if (bitsRead > 49) {
} else {
}
if (currBlock > 0 &&
rbCtr++;
}
if (currBlock >= BZ_MAX_HANDLED_BLOCKS)
currBlock++;
}
}
/*-- identified blocks run from 1 to rbCtr inclusive. --*/
if (rbCtr < 1) {
"%s: sorry, I couldn't find any block boundaries.\n",
progName );
exit(1);
};
exit(1);
}
/*-- placate gcc's dataflow analyser --*/
bitsRead = 0;
wrBlock = 0;
while (True) {
if (b == 2) break;
}
bitsRead++;
}
wrBlock++;
} else
/* Create the output file name, correctly handling leading paths.
(31.10.2001 by Sergey E. Kusikov) */
for (k = 0; k < BZ_MAX_FILENAME; k++)
outFileName[k] = 0;
split = outFileName;
} else {
++split;
}
/* Now split points to the start of the basename. */
progName, outFileName );
exit(1);
}
}
}
return 0;
}
/*-----------------------------------------------------------*/
/*--- end bzip2recover.c ---*/
/*-----------------------------------------------------------*/