/* -- global functions ---------------------------------------------------- */
int urarlib_get(void *output,
unsigned long *size,
char *filename,
void *rarfile,
char *libpassword)
/* Get a file from a RAR file to the "output" buffer. The UniquE RAR FileLib
* does everything from allocating memory, decrypting and unpacking the file
* from the archive. TRUE is returned if the file could be successfully
* extracted, else a FALSE indicates a failure.
*/
{
BOOL retcode = FALSE;
#ifdef _DEBUG_LOG
int str_offs; /* used for debug-strings */
char DebugMsg[500]; /* used to compose debug msg */
if(debug_log_first_start)
{
debug_log_first_start=FALSE; /* only create a new log file */
debug_init(_DEBUG_LOG_FILE); /* on startup */
}
#endif
InitCRC(); /* init some vars */
strcpy(ArgName, filename); /* set file(s) to extract */
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
MemRARFile = rarfile; /* set pointer to mem-RAR file */
#else
strcpy(ArcName, rarfile); /* set RAR file name */
#endif
if(libpassword != NULL)
strcpy(Password, libpassword); /* init password */
temp_output_buffer = NULL;
temp_output_buffer_offset=size; /* set size of the temp buffer */
#ifdef _DEBUG_LOG
sprintf(DebugMsg, "Extracting >%s< from >%s< (password is >%s<)...",
filename, (char*)rarfile, libpassword);
debug_log(DebugMsg);
#endif
int urarlib_list(void *rarfile, ArchiveList_struct *list)
{
ArchiveList_struct *tmp_List = NULL;
int NoOfFilesInArchive = 0; /* number of files in archive */
#ifdef _DEBUG_LOG
if(debug_log_first_start)
{
debug_log_first_start=FALSE; /* only create a new log file */
debug_init(_DEBUG_LOG_FILE); /* on startup */
}
#endif
InitCRC(); /* init some vars */
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
MemRARFile = rarfile; /* assign pointer to RAR file */
MemRARFile->offset = 0;
if (!IsArchive())
{
debug_log("Not a RAR file");
return NoOfFilesInArchive; /* error => exit! */
}
#else
/* open and identify archive */
if ((ArcPtr=fopen(rarfile,READBINARY))!=NULL)
{
if (!IsArchive())
{
debug_log("Not a RAR file");
fclose(ArcPtr);
ArcPtr = NULL;
return NoOfFilesInArchive; /* error => exit! */
}
}
else {
debug_log("Error opening file.");
return NoOfFilesInArchive;
}
#endif
if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
{
debug_log("Can't allocate memory for decompression!");
return NoOfFilesInArchive;
}
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
#else
tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
#endif
(*(DWORD*)list) = (DWORD)NULL; /* init file list */
/* do while file is not extracted and there's no error */
while (TRUE)
{
if (ReadBlock(FILE_HEAD | READSUBBLOCK) <= 0) /* read name of the next */
{ /* file within the RAR archive */
debug_log("Couldn't read next filename from archive (I/O error).");
break; /* error, file not found in */
} /* archive or I/O error */
if (BlockHead.HeadType==SUB_HEAD)
{
debug_log("Sorry, sub-headers not supported.");
break; /* error => exit */
}
/* urarlib_freelist:
* (after the suggestion and code of Duy Nguyen, Sean O'Blarney
* and Johannes Winkelmann who independently wrote a patch)
* free the memory of a ArchiveList_struct created by urarlib_list.
*
* input: *list pointer to an ArchiveList_struct
* output: -
*/
/****************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************
******* *******
******* *******
******* *******
******* B L O C K I / O *******
******* *******
******* *******
******* *******
****************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************/
int ReadBlock(int BlockType)
{
struct NewFileHeader SaveFileHead;
int Size=0,ReadSubBlock=0;
static int LastBlock;
memcpy(&SaveFileHead,&NewLhd,sizeof(SaveFileHead));
if (BlockType & READSUBBLOCK)
ReadSubBlock=1;
BlockType &= 0xff;
{
while (1)
{
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
CurBlockPos=MemRARFile->offset; /* get offset of mem-file */
#else
CurBlockPos=ftell(ArcPtr);
#endif
Size=ReadHeader(FILE_HEAD);
if (Size!=0)
{
if (NewLhd.HeadSize<SIZEOF_SHORTBLOCKHEAD)
return(0);
NextBlockPos=CurBlockPos+NewLhd.HeadSize;
if (NewLhd.Flags & LONG_BLOCK)
NextBlockPos+=NewLhd.PackSize;
if (NextBlockPos<=CurBlockPos)
return(0);
}
#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)
{
#ifdef _DEBUG_LOG
int str_offs; /* used for debug-strings */
char DebugMsg[500]; /* used to compose debug msg */
#endif
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
if (tread(MemRARFile, MarkHead.Mark, SIZEOF_MARKHEAD) != SIZEOF_MARKHEAD)
return(FALSE);
#else
if (tread(ArcPtr,MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
return(FALSE);
#endif
/* Old archive => error */
if (MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x45 &&
MarkHead.Mark[2]==0x7e && MarkHead.Mark[3]==0x5e)
{
debug_log("Attention: format as OLD detected! Can't handel archive!");
}
else
/* original RAR v2.0 */
if ((MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x61 && /* original */
MarkHead.Mark[2]==0x72 && MarkHead.Mark[3]==0x21 && /* RAR header*/
MarkHead.Mark[4]==0x1a && MarkHead.Mark[5]==0x07 &&
MarkHead.Mark[6]==0x00) ||
/* "UniquE!" - header */
(MarkHead.Mark[0]=='U' && MarkHead.Mark[1]=='n' && /* "UniquE!" */
MarkHead.Mark[2]=='i' && MarkHead.Mark[3]=='q' && /* header */
MarkHead.Mark[4]=='u' && MarkHead.Mark[5]=='E' &&
MarkHead.Mark[6]=='!'))
{
if (ReadHeader(MAIN_HEAD)!=SIZEOF_NEWMHD)
return(FALSE);
} else
{
#ifdef _DEBUG_LOG
/* sorry for this ugly code, but older SunOS gcc compilers don't */
/* support white spaces within strings */
str_offs = sprintf(DebugMsg, "unknown archive type (only plain RAR ");
str_offs += sprintf(DebugMsg + str_offs, "supported (normal and solid ");
str_offs += sprintf(DebugMsg + str_offs, "archives), SFX and Volumes ");
str_offs += sprintf(DebugMsg + str_offs, "are NOT supported!)");
debug_log(DebugMsg);
#endif
}
MainHeadSize=SIZEOF_NEWMHD;
return(TRUE);
}
BOOL ExtrFile(void)
{
BOOL ReturnCode=TRUE;
FileFound=FALSE; /* no file found by default */
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
MemRARFile->offset = 0; /* start reading from offset 0 */
if (!IsArchive())
{
debug_log("Not a RAR file");
return FALSE; /* error => exit! */
}
#else
/* open and identify archive */
if ((ArcPtr=fopen(ArcName,READBINARY))!=NULL)
{
if (!IsArchive())
{
debug_log("Not a RAR file");
fclose(ArcPtr);
ArcPtr = NULL;
return FALSE; /* error => exit! */
}
} else
{
debug_log("Error opening file.");
return FALSE;
}
#endif
if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
{
debug_log("Can't allocate memory for decompression!");
return FALSE;
}
/* 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 */
}
if(TRUE == (FileFound=(stricomp(ArgName, ArcFileName) == 0)))
/* *** file found! *** */
{
{
temp_output_buffer=malloc(NewLhd.UnpSize);/* allocate memory for the*/
}
*temp_output_buffer_offset=0; /* file. The default offset */
/* within the buffer is 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((NewMhd.Flags & 0x08) || FileFound)
{
if (NewLhd.UnpVer<13 || NewLhd.UnpVer>UNP_VER)
{
debug_log("unknown compression method");
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);
/* **************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************
******* *******
******* *******
******* *******
******* U N P A C K C O D E *******
******* *******
******* *******
******* *******
****************************************************************************
****************************************************************************
****************************************************************************
************************************************************************** */
int UnpAudioBlock,UnpChannels,CurChannel,ChannelDelta;
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;
UnpBuf=UnpAddr; /* UnpAddr is a pointer to the */
UnpInitData(); /* unpack buffer */
UnpReadBuf(1);
if (!(NewLhd.Flags & LHD_SOLID))
ReadTables();
DestUnpSize--;
while (DestUnpSize>=0)
{
UnpPtr&=MAXWINMASK;
if (InAddr>sizeof(InBuf)-30)
UnpReadBuf(0);
if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
{
if (FileFound)
{
if (UnpPtr<WrPtr)
{
if((*temp_output_buffer_offset + UnpPtr) > NewLhd.UnpSize)
{
debug_log("Fatal! Buffer overrun during decompression!");
DestUnpSize=-1;
} else
{
/* copy extracted data to output buffer */
memcpy(temp_output_buffer + *temp_output_buffer_offset,
&UnpBuf[WrPtr], (0-WrPtr) & MAXWINMASK);
/* update offset within buffer */
*temp_output_buffer_offset+= (0-WrPtr) & MAXWINMASK;
/* copy extracted data to output buffer */
memcpy(temp_output_buffer + *temp_output_buffer_offset, UnpBuf,
UnpPtr);
/* update offset within buffer */
*temp_output_buffer_offset+=UnpPtr;
}
} else
{
if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
{
debug_log("Fatal! Buffer overrun during decompression!");
DestUnpSize=-1;
} else
{
/* copy extracted data to output buffer */
memcpy(temp_output_buffer + *temp_output_buffer_offset,
&UnpBuf[WrPtr], UnpPtr-WrPtr);
*temp_output_buffer_offset+=UnpPtr-WrPtr; /* update offset within buffer */
}
}
}
WrPtr=UnpPtr;
}
if (UnpAudioBlock)
{
DecodeNumber((struct Decode *)MDPtr[CurChannel]);
if (Number==256)
{
ReadTables();
continue;
}
UnpBuf[UnpPtr++]=DecodeAudio(Number);
if (++CurChannel==UnpChannels)
CurChannel=0;
DestUnpSize--;
continue;
}
DecodeNumber((struct Decode *)&LD);
if (Number<256)
{
UnpBuf[UnpPtr++]=(UBYTE)Number;
DestUnpSize--;
continue;
}
if (Number>269)
{
Length=LDecode[Number-=270]+3;
if ((Bits=LBits[Number])>0)
{
GetBits();
Length+=BitField>>(16-Bits);
AddBits(Bits);
}
unsigned int UnpRead(unsigned char *Addr,unsigned int Count)
{
int RetCode=0;
unsigned int I,ReadSize,TotalRead=0;
unsigned char *ReadAddr;
ReadAddr=Addr;
while (Count > 0)
{
ReadSize=(unsigned int)((Count>(unsigned long)UnpPackedSize) ?
UnpPackedSize : Count);
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
if(MemRARFile->data == NULL)
return(0);
RetCode=tread(MemRARFile, ReadAddr, ReadSize);
#else
if (ArcPtr==NULL)
return(0);
RetCode=tread(ArcPtr,ReadAddr,ReadSize);
#endif
CurUnpRead+=RetCode;
ReadAddr+=RetCode;
TotalRead+=RetCode;
Count-=RetCode;
UnpPackedSize-=RetCode;
break;
}
if (RetCode!= -1)
{
RetCode=TotalRead;
if (Encryption)
{
if (Encryption<20)
{
debug_log("Old Crypt() not supported!");
}
else
{
for (I=0;I<(unsigned int)RetCode;I+=16)
DecryptBlock(&Addr[I]);
}
}
}
return(RetCode);
}
void UnpReadBuf(int FirstBuf)
{
int RetCode;
if (FirstBuf)
{
ReadTop=UnpRead(InBuf,sizeof(InBuf));
InAddr=0;
}
else
{
memcpy(InBuf,&InBuf[sizeof(InBuf)-32],32);
InAddr&=0x1f;
RetCode=UnpRead(&InBuf[32],sizeof(InBuf)-32);
if (RetCode>0)
ReadTop=RetCode+32;
else
ReadTop=InAddr;
}
}
void ReadTables(void)
{
UBYTE BitLength[BC];
unsigned char Table[MC*4];
int TableSize,N,I;
if (InAddr>sizeof(InBuf)-25)
UnpReadBuf(0);
GetBits();
UnpAudioBlock=(BitField & 0x8000);
if (!(BitField & 0x4000))
memset(UnpOldTable,0,sizeof(UnpOldTable));
AddBits(2);
if (UnpAudioBlock)
{
UnpChannels=((BitField>>12) & 3)+1;
if (CurChannel>=UnpChannels)
CurChannel=0;
AddBits(2);
TableSize=MC*UnpChannels;
}
else
TableSize=NC+DC+RC;
for (I=0;I<BC;I++)
{
GetBits();
BitLength[I]=(UBYTE)(BitField >> 12);
AddBits(4);
}
MakeDecodeTables(BitLength,(struct Decode *)&BD,BC);
I=0;
while (I<TableSize)
{
if (InAddr>sizeof(InBuf)-5)
UnpReadBuf(0);
DecodeNumber((struct Decode *)&BD);
if (Number<16)
Table[I++]=(Number+UnpOldTable[I]) & 0xf;
else
if (Number==16)
{
GetBits();
N=(BitField >> 14)+3;
AddBits(2);
while (N-- > 0 && I<TableSize)
{
Table[I]=Table[I-1];
I++;
}
}
else
{
if (Number==17)
{
GetBits();
N=(BitField >> 13)+3;
AddBits(3);
}
else
{
GetBits();
N=(BitField >> 9)+11;
AddBits(7);
}
while (N-- > 0 && I<TableSize)
Table[I++]=0;
}
}
if (UnpAudioBlock)
for (I=0;I<UnpChannels;I++)
MakeDecodeTables(&Table[I*MC],(struct Decode *)MDPtr[I],MC);
else
{
MakeDecodeTables(&Table[0],(struct Decode *)&LD,NC);
MakeDecodeTables(&Table[NC],(struct Decode *)&DD,DC);
MakeDecodeTables(&Table[NC+DC],(struct Decode *)&RD,RC);
}
memcpy(UnpOldTable,Table,sizeof(UnpOldTable));
}
static void ReadLastTables(void)
{
if (ReadTop>=InAddr+5)
{
if (UnpAudioBlock)
{
DecodeNumber((struct Decode *)MDPtr[CurChannel]);
if (Number==256)
ReadTables();
}
else
{
DecodeNumber((struct Decode *)&LD);
if (Number==269)
ReadTables();
}
}
}
static void MakeDecodeTables(unsigned char *LenTab,
struct Decode *Dec,
int Size)
{
int LenCount[16],TmpPos[16],I;
long M,N;
memset(LenCount,0,sizeof(LenCount));
for (I=0;I<Size;I++)
LenCount[LenTab[I] & 0xF]++;
LenCount[0]=0;
for (TmpPos[0]=Dec->DecodePos[0]=Dec->DecodeLen[0]=0,N=0,I=1;I<16;I++)
{
N=2*(N+LenCount[I]);
M=N<<(15-I);
if (M>0xFFFF)
M=0xFFFF;
Dec->DecodeLen[I]=(unsigned int)M;
TmpPos[I]=Dec->DecodePos[I]=Dec->DecodePos[I-1]+LenCount[I-1];
}
for (I=0;I<Size;I++)
if (LenTab[I]!=0)
Dec->DecodeNum[TmpPos[LenTab[I] & 0xF]++]=I;
Dec->MaxNum=Size;
}
static void DecodeNumber(struct Decode *Deco)
/* *** 52.6% of all CPU time is spent within this function!!! */
{
unsigned int I;
register unsigned int N;
GetBits();
if ((V->ByteCount & 0x1F)==0)
{
MinDif=V->Dif[0];
NumMinDif=0;
V->Dif[0]=0;
for (I=1;(unsigned int)I<sizeof(V->Dif)/sizeof(V->Dif[0]);I++)
{
if (V->Dif[I]<MinDif)
{
MinDif=V->Dif[I];
NumMinDif=I;
}
V->Dif[I]=0;
}
switch(NumMinDif)
{
case 1:
if (V->K1>=-16)
V->K1--;
break;
case 2:
if (V->K1<16)
V->K1++;
break;
case 3:
if (V->K2>=-16)
V->K2--;
break;
case 4:
if (V->K2<16)
V->K2++;
break;
case 5:
if (V->K3>=-16)
V->K3--;
break;
case 6:
if (V->K3<16)
V->K3++;
break;
case 7:
if (V->K4>=-16)
V->K4--;
break;
case 8:
if (V->K4<16)
V->K4++;
break;
case 9:
if (V->K5>=-16)
V->K5--;
break;
case 10:
if (V->K5<16)
V->K5++;
break;
}
}
return((UBYTE)Ch);
}
void UpdKeys(UBYTE *Buf)
{
int I;
for (I=0;I<16;I+=4)
{
Key[0]^=CRCTab[Buf[I]]; /* xxx may be I'll rewrite this */
Key[1]^=CRCTab[Buf[I+1]]; /* in asm for speedup */
Key[2]^=CRCTab[Buf[I+2]];
Key[3]^=CRCTab[Buf[I+3]];
}
}
for (J=0;J<256;J++)
for (I=0;I<PswLength;I+=2)
{
N2=(unsigned char)CRCTab[(Psw[I+1]+J)&0xFF];
for (K=1, N1=(unsigned char)CRCTab[(Psw[I]-J)&0xFF];
(N1!=N2) && (N1 < 256); /* I had to add "&& (N1 < 256)", */
N1++, K++) /* because the system crashed with */
{ /* encrypted RARs */
#ifdef _USE_ASM
/* **************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************
******* *******
******* *******
******* *******
******* D E B U G F U N C T I O N S *******
******* *******
******* *******
******* *******
****************************************************************************
****************************************************************************
****************************************************************************
************************************************************************** */
#ifdef _DEBUG_LOG
/* -- global stuff -------------------------------------------------------- */
char log_file_name[256]; /* file name for the log file */
DWORD debug_start_time; /* starttime of debug */
BOOL debug_started = FALSE; /* debug_log writes only if */
/* this is TRUE */
/* ------------------------------------------------------------------------ */
/* ************************************************************************ */
/* ************************************************************************ */
/* ** ** */
/* ** CONFIGURATION of the UniquE RAR FileLib ** */
/* ** ==> you may change the setting for the lib HERE! ** */
/* ** ** */
/* ************************************************************************ */
/* ************************************************************************ */
#define _DEBUG_LOG /* generate debug messages */
#define _DO_CRC32_CHECK /* perform cyclical redundancy */
/* check (CRC32) - disable this */
/* for a little speed-up */
/*#define _USE_ASM*/ /*
* enable assembly extensions
* x86 cpus.
*/
/*#define _USE_MEMORY_TO_MEMORY_DECOMPRESSION*/ /* read file from memory or a */
/* resource instead of reading */
/* from a file. NOTE: you wont't*/
/* be able to decompress from */
/* file if you enable this */
/* option! */
#ifdef WIN32 /* autodetect Win32 and Linux */
#define _WIN_32 /* Win32 with VisualC */
#define _DEBUG_LOG_FILE "C:\\temp\\debug_unrar.txt" /* log file path */
#else
#define _UNIX /* Linux or Unix with GCC */
#define _DEBUG_LOG_FILE "/tmp/debug_unrar.txt" /* log file path */
/*#define NON_INTEL_BYTE_ORDER*/ /* GCC on motorola systems */
/* -- global type definitions --------------------------------------------- */
#ifdef NON_INTEL_BYTE_ORDER
#ifdef _USE_ASM
#warning Disabling assembly because NON_INTEL_BYTE_ORDER is set
#undef _USE_ASM
#endif
#endif
#ifdef _WIN_32
typedef unsigned char UBYTE; /* WIN32 definitions */
typedef unsigned short UWORD;
typedef unsigned long UDWORD;
#endif
#ifdef _UNIX /* LINUX/UNIX definitions */
typedef unsigned char UBYTE;
typedef unsigned short UWORD;
typedef unsigned long UDWORD;
#endif
/* This structure is used for listing archive content */
struct RAR20_archive_entry /* These infos about files are */
{ /* stored in RAR v2.0 archives */
char *Name;
UWORD NameSize;
UDWORD PackSize;
UDWORD UnpSize;
UBYTE HostOS; /* MSDOS=0,OS2=1,WIN32=2,UNIX=3 */
UDWORD FileCRC;
UDWORD FileTime;
UBYTE UnpVer;
UBYTE Method;
UDWORD FileAttr;
};
typedef struct archivelist /* used to list archives */
{
struct RAR20_archive_entry item;
struct archivelist *next;
} ArchiveList_struct;
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
typedef struct memory_file /* used to decompress files in */
{ /* memory */
void *data; /* pointer to the file data */
unsigned long size; /* total size of the file data */
unsigned long offset; /* offset within "memory-file" */
} MemoryFile;
#endif
/* -- global functions ---------------------------------------------------- */
/* urarlib_get:
* decompresses and decrypt data from a RAR file to a buffer in system memory.
*
* input: *output pointer to an empty char*. This pointer will show
* to the extracted data
* *size shows where to write the size of the decompressed
* file
* (**NOTE: URARLib _does_ memory allocation etc.!**)
* *filename pointer to string containing the file to decompress
* *rarfile pointer to a string with the full name and path of
* the RAR file or pointer to a RAR file in memory if
* memory-to-memory decompression is active.
* *libpassword pointer to a string with the password used to
* en-/decrypt the RAR
* output: int returns TRUE on success or FALSE on error
* (FALSE=0, TRUE=1)
*/
extern int urarlib_get(void *output,
unsigned long *size,
char *filename,
void *rarfile,
char *libpassword);
/* urarlib_list:
* list the content of a RAR archive.
*
* input: *rarfile pointer to a string with the full name and path of
* the RAR file or pointer to a RAR file in memory if
* memory-to-memory decompression is active.
* *list pointer to an ArchiveList_struct that can be
* filled with details about the archive
* to the extracted data
* output: int number of files/directories within archive
*/
extern int urarlib_list(void *rarfile, ArchiveList_struct *list);
/* urarlib_freelist:
* (after the suggestion and code of Duy Nguyen, Sean O'Blarney
* and Johannes Winkelmann who independently wrote a patch)
* free the memory of a ArchiveList_struct created by urarlib_list.
*
* input: *list pointer to an ArchiveList_struct
* output: -
*/