📄 urarlib.c
字号:
/* *************************************************************************** ** ** UniquE RAR File Library ** The free file lib for the demoscene ** multi-OS version (Win32, Linux and SunOS) ** ***************************************************************************** ** ** ==> Please configure the program in "urarlib.h". <== ** ** RAR decompression code: ** (C) Eugene Roshal ** Modifications to a FileLib: ** (C) 2000-2001 Christian Scheurer aka. UniquE/Vantage (unique@vantage.ch) ** Linux port: ** (C) 2000-2001 Johannes Winkelmann (jw@tks6.net) **
** The UniquE RAR File Library gives you the ability to access RAR archives ** (any compression method supported in RAR v2.0 including Multimedia ** Compression and encryption) directly from your program with ease an by ** adding only 12kB (6kB UPX-compressed) additional code to your program. ** Both solid and normal (recommended for fast random access to the files!) ** archives are supported. This FileLib is made for the Demo scene, so it's ** designed for easy use within your demos and intros. ** Please read "licence.txt" to learn more about how you may use URARFileLib
** in your productions. ** ***************************************************************************** ** ** ** 0.0 14.02.2000 Christian Scheurer Begin of the URARFileLib project ** 0.1 17.08.2000 Christian Scheurer After many tests and versions, ** finally the first working release ** is out. ** 0.2b 20.08.2000 Christian Scheurer Support for solid and normal RARs ** added: decompression speed ** increased by factors! ** 0.2c 21.08.2000 Johannes Winkelmann first linux-beta port for gcc ** 0.2d 23.08.2000 Christian Scheurer merged all files into one, merged ** linux and win32 version ** >0.3 24.08.2000 JW&CS making library easier to use both ** with Win32, Linux and SunOS. First ** public release ** 0.3.0a 30.08.2000 Christian Scheurer UnpInitData() rewritten in i386 asm ** and stricomp() doesn't regard if a ** filename is 'bla/b.x' or 'bla\b.x'. ** 0.3.0b 04.09.2000 Christian Scheurer removed some unused structures, ** Bugs fixed: CRC32 is now computed ** correctly if '_DO_CRC32_CHECK' is ** defined and function UnstoreFile() ** is completely rewritten, memory ** management in case of failure ** improved ** >0.3.1 07.09.2000 Christian Scheurer bug fixed in Unpack() (check for ** buffer overflow added) ** >0.3.2 21.11.2000 Christian Scheurer Listing of RAR archives support ** added: urarlib_list(), memory bug ** in ExtrFile() fixed caused by debug ** code ** 0.3.2a 23.11.2000 Johannes Winkelmann DecodeNumber() ported to i386 asm in ** AT & T syntax (compiles w/gcc) ** 0.3.2b 24.11.2000 Johannes Winkelmann SetCryptKeys() ported to i386 asm in ** AT & T syntax as well ** 0.3.2c 25.11.2000 Johannes Winkelmann Guess: something in UnpInitData()
** >0.3.3 12.01.2001 JW&CS Making library ready for 4th release
** 0.3.3a 18.03.2001 Christian Scheurer Support for Memory-to-memory
** decompression added. Works fine with
** VisualC
** >0.3.4 18.03.2001 Christian Scheurer public release
** >0.3.4a 21.9.2001 JW & CS fclose()-bug fixed
**
** ** ************************************************************************** *//* -- include files ------------------------------------------------------- */#include "urarlib.h" /* include global configuration *//* ------------------------------------------------------------------------ *//* -- global stuff -------------------------------------------------------- */#ifdef _WIN_32#include <windows.h> /* WIN32 definitions */#include <stdio.h>#include <string.h>#define ENABLE_ACCESS#define HOST_OS WIN_32#define FM_NORMAL 0x00#define FM_RDONLY 0x01#define FM_HIDDEN 0x02#define FM_SYSTEM 0x04#define FM_LABEL 0x08#define FM_DIREC 0x10#define FM_ARCH 0x20#define PATHDIVIDER "\\"#define CPATHDIVIDER '\\'#define MASKALL "*.*"#define READBINARY "rb"#define READTEXT "rt"#define UPDATEBINARY "r+b"#define CREATEBINARY "w+b"#define CREATETEXT "w"#define APPENDTEXT "at"#endif#ifdef _UNIX#include <stdio.h> /* LINUX/UNIX definitions */#include <stdlib.h>#include <ctype.h>#include <string.h>#define ENABLE_ACCESS#define HOST_OS UNIX#define FM_LABEL 0x0000#define FM_DIREC 0x4000#define PATHDIVIDER "/"#define CPATHDIVIDER '/'#define MASKALL "*.*"#define READBINARY "r"#define READTEXT "r"#define UPDATEBINARY "r+"#define CREATEBINARY "w+"#define CREATETEXT "w"#define APPENDTEXT "a"/* emulation of the windows API and data types *//* 20-08-2000 Johannes Winkelmann, jw@tks6.net */typedef long DWORD;typedef short BOOL;#define TRUE 1#define FALSE 0#include <unistd.h>#include <sys/time.h>DWORD GetTickCount(){ struct timeval tv; gettimeofday( &tv, 0 ); return (tv.tv_usec / 1000);}#endif#ifdef _DEBUG_LOG /* define macros for debugging */BOOL debug_log_first_start = TRUE;#define debug_log(a); debug_log_proc(a, __FILE__, __LINE__);#define debug_init(a); debug_init_proc(a);void debug_log_proc(char *text, char *sourcefile, int sourceline);void debug_init_proc(char *file_name);#else#define debug_log(a); /* no debug this time */#define debug_init(a); /* no debug this time */#endif#define MAXWINSIZE 0x100000#define MAXWINMASK (MAXWINSIZE-1)#define UNP_MEMORY MAXWINSIZE#define Min(x,y) (((x)<(y)) ? (x):(y))#define Max(x,y) (((x)>(y)) ? (x):(y))#define NM 260#define SIZEOF_MARKHEAD 7#define SIZEOF_OLDMHD 7#define SIZEOF_NEWMHD 13#define SIZEOF_OLDLHD 21#define SIZEOF_NEWLHD 32#define SIZEOF_SHORTBLOCKHEAD 7#define SIZEOF_LONGBLOCKHEAD 11#define SIZEOF_COMMHEAD 13#define SIZEOF_PROTECTHEAD 26#define PACK_VER 20 /* version of decompression code*/#define UNP_VER 20#define PROTECT_VER 20enum { M_DENYREAD,M_DENYWRITE,M_DENYNONE,M_DENYALL };enum { FILE_EMPTY,FILE_ADD,FILE_UPDATE,FILE_COPYOLD,FILE_COPYBLOCK };enum { SUCCESS,WARNING,FATAL_ERROR,CRC_ERROR,LOCK_ERROR,WRITE_ERROR, OPEN_ERROR,USER_ERROR,MEMORY_ERROR,USER_BREAK=255,IMM_ABORT=0x8000 };enum { EN_LOCK=1,EN_VOL=2 };enum { SD_MEMORY=1,SD_FILES=2 };enum { NAMES_DONTCHANGE };enum { LOG_ARC=1,LOG_FILE=2 };enum { OLD_DECODE=0,OLD_ENCODE=1,NEW_CRYPT=2 };enum { OLD_UNPACK,NEW_UNPACK };#define MHD_COMMENT 2#define MHD_LOCK 4#define MHD_PACK_COMMENT 16#define MHD_AV 32#define MHD_PROTECT 64#define LHD_SPLIT_BEFORE 1#define LHD_SPLIT_AFTER 2#define LHD_PASSWORD 4#define LHD_COMMENT 8#define LHD_SOLID 16#define LHD_WINDOWMASK 0x00e0#define LHD_WINDOW64 0#define LHD_WINDOW128 32#define LHD_WINDOW256 64#define LHD_WINDOW512 96#define LHD_WINDOW1024 128#define LHD_DIRECTORY 0x00e0#define LONG_BLOCK 0x8000#define READSUBBLOCK 0x8000enum { ALL_HEAD=0,MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74, COMM_HEAD=0x75,AV_HEAD=0x76,SUB_HEAD=0x77,PROTECT_HEAD=0x78};enum { EA_HEAD=0x100 };enum { MS_DOS=0,OS2=1,WIN_32=2,UNIX=3 };struct MarkHeader{ UBYTE Mark[7];};struct NewMainArchiveHeader{ UWORD HeadCRC; UBYTE HeadType; UWORD Flags; UWORD HeadSize; UWORD Reserved; UDWORD Reserved1;};struct NewFileHeader{ UWORD HeadCRC; UBYTE HeadType; UWORD Flags; UWORD HeadSize; UDWORD PackSize; UDWORD UnpSize; UBYTE HostOS; UDWORD FileCRC; UDWORD FileTime; UBYTE UnpVer; UBYTE Method; UWORD NameSize; UDWORD FileAttr;};struct BlockHeader{ UWORD HeadCRC; UBYTE HeadType; UWORD Flags; UWORD HeadSize; UDWORD DataSize;};struct Decode{ unsigned int MaxNum; unsigned int DecodeLen[16]; unsigned int DecodePos[16]; unsigned int DecodeNum[2];};struct MarkHeader MarkHead;struct NewMainArchiveHeader NewMhd;struct NewFileHeader NewLhd;struct BlockHeader BlockHead;UBYTE *TempMemory; /* temporary unpack-buffer */char *CommMemory;UBYTE *UnpMemory;char ArgName[NM]; /* current file in rar archive */char ArcFileName[NM]; /* file to decompress */
#ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION /* mem-to-mem decompression */
MemoryFile *MemRARFile; /* pointer to RAR file in memory*/
#else
char ArcName[255]; /* RAR archive name */
FILE *ArcPtr; /* input RAR file handler */
#endif
char Password[255]; /* password to decrypt files */
char *temp_output_buffer; /* extract files to this pointer*/unsigned long *temp_output_buffer_offset; /* size of temp. extract buffer */BOOL FileFound; /* TRUE=use current extracted */ /* data FALSE=throw data away, */ /* wrong file */int MainHeadSize;long CurBlockPos,NextBlockPos;unsigned long CurUnpRead, CurUnpWrite;long UnpPackedSize;long DestUnpSize;UDWORD HeaderCRC;int Encryption;unsigned int UnpWrSize;unsigned char *UnpWrAddr; unsigned int UnpPtr,WrPtr;unsigned char PN1,PN2,PN3;unsigned short OldKey[4];/* function header definitions */int ReadHeader(int BlockType);BOOL ExtrFile(void);BOOL ListFile(void);int tread(void *stream,void *buf,unsigned len);int tseek(void *stream,long offset,int fromwhere);BOOL UnstoreFile(void);int IsArchive(void);int ReadBlock(int BlockType);unsigned int UnpRead(unsigned char *Addr,unsigned int Count);void UnpInitData(void);void Unpack(unsigned char *UnpAddr);UBYTE DecodeAudio(int Delta);static void DecodeNumber(struct Decode *Dec);void UpdKeys(UBYTE *Buf);void SetCryptKeys(char *Password);void SetOldKeys(char *Password);void DecryptBlock(unsigned char *Buf);void InitCRC(void);UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size);void UnpReadBuf(int FirstBuf);void ReadTables(void);static void ReadLastTables(void);static void MakeDecodeTables(unsigned char *LenTab, struct Decode *Dec, int Size);int stricomp(char *Str1,char *Str2);/* ------------------------------------------------------------------------ *//* -- 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 retcode = ExtrFile(); /* unpack file now! */ memset(Password,0,sizeof(Password)); /* clear password */
#ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
if (ArcPtr!=NULL){
fclose(ArcPtr);
ArcPtr = NULL;
}
#endif free(UnpMemory); /* free memory */ free(TempMemory); free(CommMemory); UnpMemory=NULL; TempMemory=NULL; CommMemory=NULL; if(retcode == FALSE) { free(temp_output_buffer); /* free memory and return NULL */ temp_output_buffer=NULL; *(DWORD*)output=0; /* pointer on errors */ *size=0;#ifdef _DEBUG_LOG /* sorry for this ugly code, but older SunOS gcc compilers don't support */ /* white spaces within strings */ str_offs = sprintf(DebugMsg, "Error - couldn't extract "); str_offs += sprintf(DebugMsg + str_offs, ">%s<", filename); str_offs += sprintf(DebugMsg + str_offs, " and allocated "); str_offs += sprintf(DebugMsg + str_offs, "%u Bytes", (unsigned int)*size); str_offs += sprintf(DebugMsg + str_offs, " of unused memory!"); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -