bzip2recover.c
资源名称:bzip.tar.gz [点击查看]
上传用户:zswatin
上传日期:2007-01-06
资源大小:440k
文件大小:12k
源码类别:
压缩解压
开发平台:
C/C++
- /*-----------------------------------------------------------*/
- /*--- Block recoverer program for bzip2 ---*/
- /*--- bzip2recover.c ---*/
- /*-----------------------------------------------------------*/
- /*--
- This program is bzip2recover, a program to attempt data
- salvage from damaged files created by the accompanying
- bzip2-0.9.0c program.
- Copyright (C) 1996-1998 Julian R Seward. All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. The origin of this software must not be misrepresented; you must
- not claim that you wrote the original software. If you use this
- software in a product, an acknowledgment in the product
- documentation would be appreciated but is not required.
- 3. Altered source versions must be plainly marked as such, and must
- not be misrepresented as being the original software.
- 4. The name of the author may not be used to endorse or promote
- products derived from this software without specific prior written
- permission.
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- Julian Seward, Guildford, Surrey, UK.
- jseward@acm.org
- bzip2/libbzip2 version 0.9.0c of 18 October 1998
- --*/
- /*--
- 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>
- typedef unsigned int UInt32;
- typedef int Int32;
- typedef unsigned char UChar;
- typedef char Char;
- typedef unsigned char Bool;
- #define True ((Bool)1)
- #define False ((Bool)0)
- Char inFileName[2000];
- Char outFileName[2000];
- Char progName[2000];
- UInt32 bytesOut = 0;
- UInt32 bytesIn = 0;
- /*---------------------------------------------------*/
- /*--- I/O errors ---*/
- /*---------------------------------------------------*/
- /*---------------------------------------------*/
- void readError ( void )
- {
- fprintf ( stderr,
- "%s: I/O error reading `%s', possible reason follows.n",
- progName, inFileName );
- perror ( progName );
- fprintf ( stderr, "%s: warning: output file(s) may be incomplete.n",
- progName );
- exit ( 1 );
- }
- /*---------------------------------------------*/
- void writeError ( void )
- {
- fprintf ( stderr,
- "%s: I/O error reading `%s', possible reason follows.n",
- progName, inFileName );
- perror ( progName );
- fprintf ( stderr, "%s: warning: output file(s) may be incomplete.n",
- progName );
- exit ( 1 );
- }
- /*---------------------------------------------*/
- void mallocFail ( Int32 n )
- {
- fprintf ( stderr,
- "%s: malloc failed on request for %d bytes.n",
- progName, n );
- fprintf ( stderr, "%s: warning: output file(s) may be incomplete.n",
- progName );
- exit ( 1 );
- }
- /*---------------------------------------------------*/
- /*--- Bit stream I/O ---*/
- /*---------------------------------------------------*/
- typedef
- struct {
- FILE* handle;
- Int32 buffer;
- Int32 buffLive;
- Char mode;
- }
- BitStream;
- /*---------------------------------------------*/
- BitStream* bsOpenReadStream ( FILE* stream )
- {
- BitStream *bs = malloc ( sizeof(BitStream) );
- if (bs == NULL) mallocFail ( sizeof(BitStream) );
- bs->handle = stream;
- bs->buffer = 0;
- bs->buffLive = 0;
- bs->mode = 'r';
- return bs;
- }
- /*---------------------------------------------*/
- BitStream* bsOpenWriteStream ( FILE* stream )
- {
- BitStream *bs = malloc ( sizeof(BitStream) );
- if (bs == NULL) mallocFail ( sizeof(BitStream) );
- bs->handle = stream;
- bs->buffer = 0;
- bs->buffLive = 0;
- bs->mode = 'w';
- return bs;
- }
- /*---------------------------------------------*/
- void bsPutBit ( BitStream* bs, Int32 bit )
- {
- if (bs->buffLive == 8) {
- Int32 retVal = putc ( (UChar) bs->buffer, bs->handle );
- if (retVal == EOF) writeError();
- bytesOut++;
- bs->buffLive = 1;
- bs->buffer = bit & 0x1;
- } else {
- bs->buffer = ( (bs->buffer << 1) | (bit & 0x1) );
- bs->buffLive++;
- };
- }
- /*---------------------------------------------*/
- /*--
- Returns 0 or 1, or 2 to indicate EOF.
- --*/
- Int32 bsGetBit ( BitStream* bs )
- {
- if (bs->buffLive > 0) {
- bs->buffLive --;
- return ( ((bs->buffer) >> (bs->buffLive)) & 0x1 );
- } else {
- Int32 retVal = getc ( bs->handle );
- if ( retVal == EOF ) {
- if (errno != 0) readError();
- return 2;
- }
- bs->buffLive = 7;
- bs->buffer = retVal;
- return ( ((bs->buffer) >> 7) & 0x1 );
- }
- }
- /*---------------------------------------------*/
- void bsClose ( BitStream* bs )
- {
- Int32 retVal;
- if ( bs->mode == 'w' ) {
- while ( bs->buffLive < 8 ) {
- bs->buffLive++;
- bs->buffer <<= 1;
- };
- retVal = putc ( (UChar) (bs->buffer), bs->handle );
- if (retVal == EOF) writeError();
- bytesOut++;
- retVal = fflush ( bs->handle );
- if (retVal == EOF) writeError();
- }
- retVal = fclose ( bs->handle );
- if (retVal == EOF) {
- if (bs->mode == 'w') writeError(); else readError();
- }
- free ( bs );
- }
- /*---------------------------------------------*/
- void bsPutUChar ( BitStream* bs, UChar c )
- {
- Int32 i;
- for (i = 7; i >= 0; i--)
- bsPutBit ( bs, (((UInt32) c) >> i) & 0x1 );
- }
- /*---------------------------------------------*/
- void bsPutUInt32 ( BitStream* bs, UInt32 c )
- {
- Int32 i;
- for (i = 31; i >= 0; i--)
- bsPutBit ( bs, (c >> i) & 0x1 );
- }
- /*---------------------------------------------*/
- Bool endsInBz2 ( Char* name )
- {
- Int32 n = strlen ( name );
- if (n <= 4) return False;
- return
- (name[n-4] == '.' &&
- name[n-3] == 'b' &&
- name[n-2] == 'z' &&
- name[n-1] == '2');
- }
- /*---------------------------------------------------*/
- /*--- ---*/
- /*---------------------------------------------------*/
- #define BLOCK_HEADER_HI 0x00003141UL
- #define BLOCK_HEADER_LO 0x59265359UL
- #define BLOCK_ENDMARK_HI 0x00001772UL
- #define BLOCK_ENDMARK_LO 0x45385090UL
- Int32 main ( Int32 argc, Char** argv )
- {
- FILE* inFile;
- FILE* outFile;
- BitStream* bsIn, *bsWr;
- Int32 currBlock, b, wrBlock;
- UInt32 bitsRead;
- UInt32 bStart[20000];
- UInt32 bEnd[20000];
- UInt32 rbStart[20000];
- UInt32 rbEnd[20000];
- Int32 rbCtr;
- UInt32 buffHi, buffLo, blockCRC;
- Char* p;
- strcpy ( progName, argv[0] );
- inFileName[0] = outFileName[0] = 0;
- fprintf ( stderr, "bzip2recover v0.9.0c: extracts blocks from damaged .bz2 files.n" );
- if (argc != 2) {
- fprintf ( stderr, "%s: usage is `%s damaged_file_name'.n",
- progName, progName );
- exit(1);
- }
- strcpy ( inFileName, argv[1] );
- inFile = fopen ( inFileName, "rb" );
- if (inFile == NULL) {
- fprintf ( stderr, "%s: can't read `%s'n", progName, inFileName );
- exit(1);
- }
- bsIn = bsOpenReadStream ( inFile );
- fprintf ( stderr, "%s: searching for block boundaries ...n", progName );
- bitsRead = 0;
- buffHi = buffLo = 0;
- currBlock = 0;
- bStart[currBlock] = 0;
- rbCtr = 0;
- while (True) {
- b = bsGetBit ( bsIn );
- bitsRead++;
- if (b == 2) {
- if (bitsRead >= bStart[currBlock] &&
- (bitsRead - bStart[currBlock]) >= 40) {
- bEnd[currBlock] = bitsRead-1;
- if (currBlock > 0)
- fprintf ( stderr, " block %d runs from %d to %d (incomplete)n",
- currBlock, bStart[currBlock], bEnd[currBlock] );
- } else
- currBlock--;
- break;
- }
- buffHi = (buffHi << 1) | (buffLo >> 31);
- buffLo = (buffLo << 1) | (b & 1);
- if ( ( (buffHi & 0x0000ffff) == BLOCK_HEADER_HI
- && buffLo == BLOCK_HEADER_LO)
- ||
- ( (buffHi & 0x0000ffff) == BLOCK_ENDMARK_HI
- && buffLo == BLOCK_ENDMARK_LO)
- ) {
- if (bitsRead > 49)
- bEnd[currBlock] = bitsRead-49; else
- bEnd[currBlock] = 0;
- if (currBlock > 0 &&
- (bEnd[currBlock] - bStart[currBlock]) >= 130) {
- fprintf ( stderr, " block %d runs from %d to %dn",
- rbCtr+1, bStart[currBlock], bEnd[currBlock] );
- rbStart[rbCtr] = bStart[currBlock];
- rbEnd[rbCtr] = bEnd[currBlock];
- rbCtr++;
- }
- currBlock++;
- bStart[currBlock] = bitsRead;
- }
- }
- bsClose ( bsIn );
- /*-- identified blocks run from 1 to rbCtr inclusive. --*/
- if (rbCtr < 1) {
- fprintf ( stderr,
- "%s: sorry, I couldn't find any block boundaries.n",
- progName );
- exit(1);
- };
- fprintf ( stderr, "%s: splitting into blocksn", progName );
- inFile = fopen ( inFileName, "rb" );
- if (inFile == NULL) {
- fprintf ( stderr, "%s: can't open `%s'n", progName, inFileName );
- exit(1);
- }
- bsIn = bsOpenReadStream ( inFile );
- /*-- placate gcc's dataflow analyser --*/
- blockCRC = 0; bsWr = 0;
- bitsRead = 0;
- outFile = NULL;
- wrBlock = 0;
- while (True) {
- b = bsGetBit(bsIn);
- if (b == 2) break;
- buffHi = (buffHi << 1) | (buffLo >> 31);
- buffLo = (buffLo << 1) | (b & 1);
- if (bitsRead == 47+rbStart[wrBlock])
- blockCRC = (buffHi << 16) | (buffLo >> 16);
- if (outFile != NULL && bitsRead >= rbStart[wrBlock]
- && bitsRead <= rbEnd[wrBlock]) {
- bsPutBit ( bsWr, b );
- }
- bitsRead++;
- if (bitsRead == rbEnd[wrBlock]+1) {
- if (outFile != NULL) {
- bsPutUChar ( bsWr, 0x17 ); bsPutUChar ( bsWr, 0x72 );
- bsPutUChar ( bsWr, 0x45 ); bsPutUChar ( bsWr, 0x38 );
- bsPutUChar ( bsWr, 0x50 ); bsPutUChar ( bsWr, 0x90 );
- bsPutUInt32 ( bsWr, blockCRC );
- bsClose ( bsWr );
- }
- if (wrBlock >= rbCtr) break;
- wrBlock++;
- } else
- if (bitsRead == rbStart[wrBlock]) {
- outFileName[0] = 0;
- sprintf ( outFileName, "rec%4d", wrBlock+1 );
- for (p = outFileName; *p != 0; p++) if (*p == ' ') *p = '0';
- strcat ( outFileName, inFileName );
- if ( !endsInBz2(outFileName)) strcat ( outFileName, ".bz2" );
- fprintf ( stderr, " writing block %d to `%s' ...n",
- wrBlock+1, outFileName );
- outFile = fopen ( outFileName, "wb" );
- if (outFile == NULL) {
- fprintf ( stderr, "%s: can't write `%s'n",
- progName, outFileName );
- exit(1);
- }
- bsWr = bsOpenWriteStream ( outFile );
- bsPutUChar ( bsWr, 'B' ); bsPutUChar ( bsWr, 'Z' );
- bsPutUChar ( bsWr, 'h' ); bsPutUChar ( bsWr, '9' );
- bsPutUChar ( bsWr, 0x31 ); bsPutUChar ( bsWr, 0x41 );
- bsPutUChar ( bsWr, 0x59 ); bsPutUChar ( bsWr, 0x26 );
- bsPutUChar ( bsWr, 0x53 ); bsPutUChar ( bsWr, 0x59 );
- }
- }
- fprintf ( stderr, "%s: finishedn", progName );
- return 0;
- }
- /*-----------------------------------------------------------*/
- /*--- end bzip2recover.c ---*/
- /*-----------------------------------------------------------*/