📄 unrarlib.c
字号:
BlockHead.DataSize = NewLhd.PackSize;
if (BlockType != NewLhd.HeadType)
BlockType = ALL_HEAD;
if ((FILE_HEAD == BlockType) && (Size > 0))
{
ArcFileName = realloc (ArcFileName, NewLhd.NameSize + 1);
fread (ArcFileName, 1, NewLhd.NameSize, inputfile);
ArcFileName[NewLhd.NameSize] = 0;
#ifdef _DEBUG_LOG
if (NewLhd.HeadCRC !=
(UWORD) ~ CalcCRC32 (HeaderCRC, (UBYTE *) & ArcFileName[0],
NewLhd.NameSize))
{
debug_log ("file header broken");
}
#endif
Size += NewLhd.NameSize;
}
else
{
memcpy (&NewLhd, &SaveFileHead, sizeof (NewLhd));
fseek (inputfile, CurBlockPos, SEEK_SET);
}
return Size;
}
int
ReadHeader (int BlockType)
{
int Size = 0;
unsigned char Header[64];
switch (BlockType)
{
case MAIN_HEAD:
Size = fread (Header, 1, SIZEOF_NEWMHD, inputfile);
archiveheader.head_crc = (unsigned short) GetHeaderWord (0);
archiveheader.head_type = GetHeaderByte (2);
archiveheader.head_flags = (unsigned short) GetHeaderWord (3);
archiveheader.head_size = (unsigned short) GetHeaderWord (5);
archiveheader.reserved1 = (unsigned short) GetHeaderWord (7);
archiveheader.reserved2 = GetHeaderDword (9);
HeaderCRC = CalcCRC32 (0xFFFFFFFFL, &Header[2], SIZEOF_NEWMHD - 2);
break;
case FILE_HEAD:
Size = fread (Header, 1, SIZEOF_NEWLHD, inputfile);
NewLhd.HeadCRC = (unsigned short) GetHeaderWord (0);
NewLhd.HeadType = GetHeaderByte (2);
NewLhd.Flags = (unsigned short) GetHeaderWord (3);
NewLhd.HeadSize = (unsigned short) GetHeaderWord (5);
NewLhd.PackSize = GetHeaderDword (7);
NewLhd.UnpSize = GetHeaderDword (11);
NewLhd.HostOS = GetHeaderByte (15);
NewLhd.FileCRC = GetHeaderDword (16);
NewLhd.FileTime = GetHeaderDword (20);
NewLhd.UnpVer = GetHeaderByte (24);
NewLhd.Method = GetHeaderByte (25);
NewLhd.NameSize = (unsigned short) GetHeaderWord (26);
NewLhd.FileAttr = GetHeaderDword (28);
HeaderCRC = CalcCRC32 (0xFFFFFFFFL, &Header[2], SIZEOF_NEWLHD - 2);
break;
#ifdef _DEBUG_LOG
case COMM_HEAD: /* log errors in case of debug */
debug_log ("Comment headers not supported! "
"Please create archives without comments.");
break;
case PROTECT_HEAD:
debug_log ("Protected headers not supported!");
break;
case ALL_HEAD:
debug_log ("ShortBlockHeader not supported!");
break;
default:
debug_log ("Unknown//unsupported !");
#else
default: /* else do nothing */
break;
#endif
}
return Size;
}
/* E X T R A C T L O O P */
int
IsArchive (void)
{
if (fread (&markheader, 1, sizeof (markheader), inputfile) !=
sizeof (markheader))
return 0;
/* original RAR v2.0 header */
/* FIXME: Endian */
if (!(markheader.head_crc == 0x6152 && markheader.head_type == 0x72
&& markheader.head_flags == 0x1a21 && markheader.head_size == 0x0007))
{
fputs ("unknown archive type, only plain RAR 2.0 supported"
"(normal and solid archives), "
"SFX and Volumes are NOT supported!\n", stderr);
return 0;
}
if (ReadHeader (MAIN_HEAD) != SIZEOF_NEWMHD)
return 0;
return 1;
}
bool
ExtrFile (void)
{
bool ReturnCode = true;
FileFound = false; /* no file found by default */
/* open and identify archive */
if ((inputfile = fopen (ArcName, "r")) != NULL)
{
if (!IsArchive ())
{
debug_log ("Not a RAR file");
fclose (inputfile);
inputfile = NULL;
return false; /* error => exit! */
}
}
else
{
debug_log ("Error opening file.");
return false;
}
if ((UnpMemory = malloc (UNP_MEMORY)) == NULL)
{
debug_log ("Can't allocate memory for decompression!");
return false;
}
fseek (inputfile, archiveheader.head_size - SIZEOF_NEWMHD, SEEK_CUR);
/* do while file is not extracted and there's no error */
do
{
if (ReadBlock (FILE_HEAD | READSUBBLOCK) <= 0) /* read name of the next */
{ /* file within the RAR archive */
/*
*
* 21.11.2000 UnQ There's a problem with some linux distros when a file
* can not be found in an archive.
*
* debug_log("Couldn't read next filename from archive (I/O error).");
*
*/
ReturnCode = false;
break; /* error, file not found in */
} /* archive or I/O error */
if (BlockHead.HeadType == SUB_HEAD)
{
debug_log ("Sorry, sub-headers not supported.");
ReturnCode = false;
break; /* error => exit */
}
FileFound = (stricomp (ArgName, ArcFileName) == 0);
if (FileFound)
/* file found! */
{
/* Allocate memory for the file. The default offset within
the buffer is 0. */
temp_output_buffer = malloc (NewLhd.UnpSize);
*temp_output_buffer_offset = 0;
if (temp_output_buffer == NULL)
{
debug_log ("can't allocate memory for the file decompression");
ReturnCode = false;
break; /* error, can't extract file! */
}
}
/* in case of a solid archive, we need to decompress any single file till
* we have found the one we are looking for. In case of normal archives
* (recommended!!), we skip the files until we are sure that it is the
* one we want.
*/
if ((archiveheader.head_flags & 0x08) || FileFound)
{
if (NewLhd.UnpVer < 13 || NewLhd.UnpVer > UNP_VER)
{
char DebugMsg[64];
snprintf (DebugMsg, sizeof DebugMsg,
"unknown compression method: %d", NewLhd.UnpVer);
debug_log (DebugMsg);
ReturnCode = false;
break; /* error, can't extract file! */
}
CurUnpRead = CurUnpWrite = 0;
if ((*Password != 0) && (NewLhd.Flags & LHD_PASSWORD))
Encryption = NewLhd.UnpVer;
else
Encryption = 0;
if (Encryption)
SetCryptKeys (Password);
UnpPackedSize = NewLhd.PackSize;
DestUnpSize = NewLhd.UnpSize;
if (NewLhd.Method == 0x30)
{
UnstoreFile ();
}
else
{
Unpack (UnpMemory);
}
#ifdef _DO_CRC32_CHECK /* calculate CRC32 */
if ((UBYTE *) temp_output_buffer != NULL)
{
if (NewLhd.FileCRC != ~CalcCRC32 (0xFFFFFFFFL,
(UBYTE *) temp_output_buffer,
NewLhd.UnpSize))
{
debug_log
("CRC32 error - file couldn't be decompressed correctly!");
ReturnCode = false;
break; /* error, can't extract file! */
}
}
#endif
}
if (inputfile != NULL)
fseek (inputfile, NextBlockPos, SEEK_SET);
}
while (stricomp (ArgName, ArcFileName) != 0); /* exit if file is extracted */
/* free memory, clear password and close archive */
free (UnpMemory);
UnpMemory = NULL;
if (inputfile != NULL)
{
fclose (inputfile);
inputfile = NULL;
}
return ReturnCode; /* file extracted successful! */
}
/* G L O B A L F U N C T I O N S */
int
stricomp (char *Str1, char *Str2)
/* compare strings without regard of '\' and '/' */
{
char S1[512], S2[512];
char *chptr;
strncpy (S1, Str1, sizeof (S1));
strncpy (S2, Str2, sizeof (S2));
while ((chptr = strchr (S1, '\\')) != NULL) /* ignore backslash */
{
*chptr = '_';
}
while ((chptr = strchr (S2, '\\')) != NULL) /* ignore backslash */
{
*chptr = '_';
}
while ((chptr = strchr (S1, '/')) != NULL) /* ignore slash */
{
*chptr = '_';
}
while ((chptr = strchr (S2, '/')) != NULL) /* ignore slash */
{
*chptr = '_';
}
return strcasecmp (S1, S2);
}
/* U N P A C K C O D E */
/* *****************************
* ** unpack stored RAR files **
* *****************************/
bool
UnstoreFile (void)
{
if ((long) (*temp_output_buffer_offset = UnpRead (temp_output_buffer,
NewLhd.UnpSize)) == -1)
{
debug_log ("Read error of stored file!");
return false;
}
return true;
}
/* ****************************************
* ** RAR decompression code starts here **
* ****************************************/
#define NC 298 /* alphabet = {0,1,2, .,NC - 1} */
#define DC 48
#define RC 28
#define BC 19
#define MC 257
enum
{
CODE_HUFFMAN = 0,
CODE_LZ = 1,
CODE_LZ2 = 2,
CODE_REPEATLZ = 3,
CODE_CACHELZ = 4,
CODE_STARTFILE = 5,
CODE_ENDFILE = 6,
CODE_ENDMM = 7,
CODE_STARTMM = 8,
CODE_MMDELTA = 9
};
struct AudioVariables
{
int K1, K2, K3, K4, K5;
int D1, D2, D3, D4;
int LastDelta;
unsigned int Dif[11];
unsigned int ByteCount;
int LastChar;
};
struct AudioVariables AudV[4];
#define GetBits() \
BitField = ( ( ( (UDWORD)InBuf[InAddr] << 16 ) | \
( (UWORD) InBuf[InAddr+1] << 8 ) | \
( InBuf[InAddr+2] ) ) \
>> (8-InBit) ) & 0xffff;
#define AddBits(Bits) \
InAddr += ( InBit + (Bits) ) >> 3; \
InBit = ( InBit + (Bits) ) & 7;
static unsigned char *UnpBuf;
static unsigned int BitField;
static unsigned int Number;
unsigned char InBuf[8192]; /* input read buffer */
unsigned char UnpOldTable[MC * 4];
unsigned int InAddr, InBit, ReadTop;
unsigned int LastDist, LastLength;
static unsigned int Length, Distance;
unsigned int OldDist[4], OldDistPtr;
struct LitDecode
{
unsigned int MaxNum;
unsigned int DecodeLen[16];
unsigned int DecodePos[16];
unsigned int DecodeNum[NC];
} LD;
struct DistDecode
{
unsigned int MaxNum;
unsigned int DecodeLen[16];
unsigned int DecodePos[16];
unsigned int DecodeNum[DC];
} DD;
struct RepDecode
{
unsigned int MaxNum;
unsigned int DecodeLen[16];
unsigned int DecodePos[16];
unsigned int DecodeNum[RC];
} RD;
struct MultDecode
{
unsigned int MaxNum;
unsigned int DecodeLen[16];
unsigned int DecodePos[16];
unsigned int DecodeNum[MC];
} MD[4];
struct BitDecode
{
unsigned int MaxNum;
unsigned int DecodeLen[16];
unsigned int DecodePos[16];
unsigned int DecodeNum[BC];
} BD;
static struct MultDecode *MDPtr[4] = { &MD[0], &MD[1], &MD[2], &MD[3] };
int UnpAudioBlock, UnpChannels, CurChannel, ChannelDelta;
struct Decode Decode_tmp;
struct Decode *
LitDecode2Decode (struct LitDecode *ld)
{
Decode_tmp.MaxNum = ld->MaxNum;
Decode_tmp.DecodeLen = ld->DecodeLen;
Decode_tmp.DecodePos = ld->DecodePos;
Decode_tmp.DecodeNum = ld->DecodeNum;
return &Decode_tmp;
}
struct Decode *
DistDecode2Decode (struct DistDecode *ld)
{
Decode_tmp.MaxNum = ld->MaxNum;
Decode_tmp.DecodeLen = ld->DecodeLen;
Decode_tmp.DecodePos = ld->DecodePos;
Decode_tmp.DecodeNum = ld->DecodeNum;
return &Decode_tmp;
}
struct Decode *
RepDecode2Decode (struct RepDecode *ld)
{
Decode_tmp.MaxNum = ld->MaxNum;
Decode_tmp.DecodeLen = ld->DecodeLen;
Decode_tmp.DecodePos = ld->DecodePos;
Decode_tmp.DecodeNum = ld->DecodeNum;
return &Decode_tmp;
}
struct Decode *
MultDecode2Decode (struct MultDecode *ld)
{
Decode_tmp.MaxNum = ld->MaxNum;
Decode_tmp.DecodeLen = ld->DecodeLen;
Decode_tmp.DecodePos = ld->DecodePos;
Decode_tmp.DecodeNum = ld->DecodeNum;
return &Decode_tmp;
}
struct Decode *
BitDecode2Decode (struct BitDecode *ld)
{
Decode_tmp.MaxNum = ld->MaxNum;
Decode_tmp.DecodeLen = ld->DecodeLen;
Decode_tmp.DecodePos = ld->DecodePos;
Decode_tmp.DecodeNum = ld->DecodeNum;
return &Decode_tmp;
}
void
Decode2LitDecode (struct LitDecode *ld)
{
ld->MaxNum = Decode_tmp.MaxNum;
}
void
Decode2DistDecode (struct DistDecode *ld)
{
ld->MaxNum = Decode_tmp.MaxNum;
}
void
Decode2RepDecode (struct RepDecode *ld)
{
ld->MaxNum = Decode_tmp.MaxNum;
}
void
Decode2MultDecode (struct MultDecode *ld)
{
ld->MaxNum = Decode_tmp.MaxNum;
}
void
Decode2BitDecode (struct BitDecode *ld)
{
ld->MaxNum = Decode_tmp.MaxNum;
}
void
Unpack (unsigned char *UnpAddr)
/* *** 38.3% of all CPU time is spent within this function!!! */
{
static unsigned char LDecode[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32,
40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224
};
static unsigned char LBits[] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3,
3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
};
static int DDecode[] =
{ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384,
512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288,
16384, 24576, 32768U, 49152U, 65536, 98304, 131072, 196608,
262144, 327680, 393216, 458752, 524288, 589824, 655360,
720896, 786432, 851968, 917504, 983040
};
static unsigned char DBits[] =
{ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9,
9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
};
static unsigned char SDDecode[] = { 0, 4, 8, 16, 32, 64, 128, 192 };
static unsigned char SDBits[] = { 2, 2, 3, 4, 5, 6, 6, 6 };
unsigned int Bits;
/* UnpAddr is a pointer to the unpack buffer */
UnpBuf = UnpAddr;
UnpInitData ();
UnpReadBuf (1);
if (!(NewLhd.Flags & LHD_SOLID))
ReadTables ();
DestUnpSize--;
while (DestUnpSize >= 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -