📄 unrar.c
字号:
/****** ***** ******
** ** ** ** ** ** unRAR utility version 1.01
****** ******* ****** ~~~~~~~~~~~~~~~~~~~~~~~~~~~
** ** ** ** ** ** FREE portable version
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~
Main code
YOU CAN CHANGE FOLLOWING CODE IN ORDER TO ACHIEVE
COMPATIBILITY WITH YOUR OPERATING MEDIA.
PLEASE SEND ALL NOTES, PATCHES TO andrey@vybor.chel.su
OR TO Andrey Spasibozhko, 2:5010/23@fidonet.
VOICE PHONE: +7-3512-130-231
*/
#include "unrar.h" /* definitions */
#include "unpack.c" /* unpacking procedures */
void SplitCommandLine(); /* parses command string */
int CmpName(); /* checks name for mask */
char* PointToName(); /* returns pathname */
void NextVolumeName(); /* gets next volume name */
void SplitName(); /* splits pathname */
void ExecuteCommand(); /* executes extr. command */
void ListArchive(); /* lists archive contents */
int ExtrFile(); /* extracts single file */
void Help(); /* prints usage help */
void ShutDown(); /* stops working */
void ErrExit(); /* exits with error code */
void CreatePath(); /* creates path */
int tread(); /* reads with checking */
void tclose(); /* closes with checking */
void MergeArc(); /* to next volume */
void UnstoreFile(); /* unpacks non-compressed file */
int IsArchive(); /* checks for RAR archive signature */
void CheckArc(); /* similar but with exit */
int strnicomp(); /* compares strings */
char* strtolwr(); /* convert string to lowercase
int ToPercent(); /* calculates percentage */
int ReadBlock(); /* reads archive block */
int IsProcessFile(); /* should file be processed */
int UnpRead(); /* reading while unpacking */
int UnpWrite(); /* writing while unpacking */
void InitCRC(); /* initializes CRC table */
UDWORD CRC(); /* calculates CRC */
struct MarkHeader MarkHead;
struct ArchiveHeader Mhd;
struct FileHeader Lhd;
UDWORD CRC32_Table[256],UnpFileCRC;
HPBYTE TmpMemory;
int ArgCount=0;
char ArgNames[16][80],MainCommand;
char CurExtrFile[80]={0},ArcName[80],ArcFileName[80],ExtrPath[80];
int SolidType,UnpVolume,TestMode,ExitCode=0;
FILE *ArcFPtr=NULL,*FileFPtr=NULL,*RdUnpFPtr,*WrUnpFPtr;
long NextBlockPos,UnpPackedSize;
main(Argc,Argv)
int Argc;
char *Argv[];
{
printf("\n UNRAR 1.01 freeware portable version (C) 1994-95 Eugene Roshal\n");
if ((TmpMemory=(HPBYTE)MEMALLOC(UNP_MEMORY))==NULL)
ErrExit(EMEMORY,MEMORY_ERROR);
MakeTbl();
SplitCommandLine(Argc,Argv);
ExecuteCommand();
ShutDown(SD_MEMORY);
exit(ExitCode);
}
int CmpName(Mask,Name)
char *Mask;
char *Name;
{
while (1)
{
if (*Mask=='*')
{
while (*Mask!='.' && *Mask!=0)
Mask++;
while (*Name!='.' && *Name!=0)
Name++;
}
if (*Mask==0)
return(*Name==0);
if (*Name==0 && *Mask=='.')
{
Mask++;
continue;
}
if (toupper(*Mask)==toupper(*Name) || *Mask=='?' && *Name!=0)
{
Mask++;
Name++;
}
else
return(0);
}
}
void ErrExit(ErrCode,Code)
int ErrCode;
int Code;
{
char ErrMsg[80];
switch(ErrCode)
{
case EEMPTY:
strcpy(ErrMsg,"");
break;
case EWRITE:
strcpy(ErrMsg,"Write error. Disk full ?");
break;
case EREAD:
strcpy(ErrMsg,"Read error");
break;
case EOPEN:
strcpy(ErrMsg,"File open error");
break;
case ECLOSE:
strcpy(ErrMsg,"File close error");
break;
case EMEMORY:
strcpy(ErrMsg,"Not enough memory");
break;
case EARCH:
strcpy(ErrMsg,"Broken archive");
break;
}
if (ErrCode!=EEMPTY)
printf("\n Program aborted\n %s",ErrMsg);
ShutDown(SD_FILES | SD_MEMORY);
exit(Code);
}
void CreatePath(fpath)
char *fpath;
{
char *ChPtr;
ChPtr=fpath;
while(*ChPtr!=0 && (ChPtr=strchr(ChPtr,PATHDIV))!=NULL)
{
*ChPtr=0;
if (MAKEDIR(fpath)==0)
printf("\n Creating %-55s",fpath);
*ChPtr=PATHDIV;
ChPtr++;
}
}
void NextVolumeName()
{
char *ChPtr;
ChPtr=strrchr(ArcName,'.');
if (!isdigit(*(ChPtr+2)) || !isdigit(*(ChPtr+3)))
strcpy(ChPtr+2,"00");
else
{
ChPtr+=3;
while ((++(*ChPtr))=='9'+1)
{
if (*(ChPtr-1)=='.')
{
*ChPtr='A';
break;
}
else
{
*ChPtr='0';
ChPtr--;
}
}
}
}
void MergeArc(ShowFileName)
int ShowFileName;
{
int Ch;
tclose(ArcFPtr);
NextVolumeName();
while ((ArcFPtr=fopen(ArcName,FOPENREADMODE))==NULL)
{
printf("\n Disk with %s required. Continue ? ",ArcName);
Ch=getchar();
if (toupper(Ch)=='N')
ErrExit(EEMPTY,USER_BREAK);
}
if (MainCommand=='T')
printf("\n\n Testing archive %s",ArcName);
else
if (MainCommand!='P')
printf("\n\n Extracting from %s",ArcName);
CheckArc();
ReadBlock(FILE_HEAD);
if (ShowFileName)
printf("\n ... %-55s",ArcFileName);
UnpVolume=(Lhd.Flags & LHD_SPLIT_AFTER);
fseek(ArcFPtr,NextBlockPos-Lhd.PackSize,SEEK_SET);
UnpPackedSize=Lhd.PackSize;
RdUnpFPtr=ArcFPtr;
}
void UnstoreFile()
{
int Code;
while ( 1 )
{
if ((Code=UnpRead((UBYTE *)TmpMemory,0x7f00))==-1)
ErrExit(EWRITE,WRITE_ERROR);
if (Code==0)
break;
if (UnpWrite((UBYTE *)TmpMemory,(UWORD)Code)==-1)
ErrExit(EWRITE,WRITE_ERROR);
}
}
int IsArchive()
{
UBYTE Mark[7],Header[13];
SolidType=0;
if (tread(ArcFPtr,Mark,7)!=7)
return(0);
if (Mark[0]!=0x52 || Mark[1]!=0x61 || Mark[2]!=0x72 || Mark[3]!=0x21 ||
Mark[4]!=0x1a || Mark[5]!=0x07 || Mark[6]!=0x00)
return(0);
if (tread(ArcFPtr,Header,13) != 13)
return(0);
Mhd.HeadCRC = Header[0]+(UWORD)Header[1]*0x100;
Mhd.HeadType = Header[2];
Mhd.Flags = Header[3]+(UWORD)Header[4]*0x100;
Mhd.HeadSize = Header[5]+(UWORD)Header[6]*0x100;
if (!(Mhd.HeadCRC==(UWORD)~CRC(0xFFFFFFFFL,&Header[2],11)))
printf("\n Archive header broken");
SolidType=(Mhd.Flags & MHD_SOLID);
fseek(ArcFPtr,Mhd.HeadSize-13,SEEK_CUR);
return(1);
}
void CheckArc()
{
if (!IsArchive())
{
printf("\nBad archive %s",ArcName);
ErrExit(EEMPTY,FATAL_ERROR);
}
}
int tread(FPtr,buf,len)
FILE *FPtr;
void *buf;
unsigned len;
{
int Code;
Code=fread(buf,1,len,FPtr);
if (Code==-1)
ErrExit(EREAD,FATAL_ERROR);
return(Code);
}
void tclose(FPtr)
FILE *FPtr;
{
if (fclose(FPtr)==EOF)
ErrExit(ECLOSE,FATAL_ERROR);
}
char* PointToName(Path)
char *Path;
{
char *ChPtr;
if ((ChPtr=strrchr(Path,PATHDIV))!=NULL)
return(ChPtr+1);
else
if ((ChPtr=strrchr(Path,':'))!=NULL)
return(ChPtr+1);
else
return(Path);
}
int strnicomp(Str1,Str2,MaxLen)
char *Str1;
char *Str2;
int MaxLen;
{
if (MaxLen==0)
return(0);
while (MaxLen-- > 0)
{
if (toupper(*Str1)!=toupper(*Str2))
return(1);
if (*Str1==0)
return(0);
Str1++;
Str2++;
}
return(0);
}
char* strtolwr(Str)
char *Str;
{
char *ChPtr;
for (ChPtr=Str;*ChPtr!=0;ChPtr++)
*ChPtr=tolower(*ChPtr);
return(Str);
}
void SplitName(Path,Dir,Name)
char *Path;
char *Dir;
char *Name;
{
char *ChPtr,*ChPtr1;
if ((ChPtr=strrchr(Path,':'))!=NULL)
ChPtr++;
else
ChPtr=Path;
if ((ChPtr1=strrchr(ChPtr,PATHDIV))!=NULL)
{
*ChPtr1=0;
strcpy(Dir,ChPtr);
*ChPtr1=PATHDIV;
ChPtr=ChPtr1+1;
}
else
*Dir=0;
strcpy(Name,ChPtr);
}
int ToPercent(N1,N2)
long N1;
long N2;
{
if (N1 > 10000)
{
N1/=100;
N2/=100;
}
if (N2==0)
return(0);
if (N2<N1)
return(100);
return((int)(N1*100/N2));
}
void SplitCommandLine(Argc,Argv)
int Argc;
char *Argv[];
{
int I,Len;
ArgCount = MainCommand = *ArcName = *ExtrPath = 0;
if (Argc==2)
{
MainCommand='X';
strcpy(ArcName,Argv[1]);
}
else
for (I=1;I<Argc;I++)
{
if (MainCommand==0)
MainCommand=toupper(Argv[I][0]);
else
{
if (*ArcName==0)
strncpy(ArcName,Argv[I],80);
else
{
Len=strlen(Argv[I]);
if (Len>0 && (Argv[I][Len-1]==':' || (Argv[I][Len-1]=='\\' || Argv[I][Len-1]=='/')))
{
strcpy(ExtrPath,Argv[I]);
ExtrPath[Len-1]=PATHDIV;
}
else
strncpy(ArgNames[(ArgCount++) & 0x0f],Argv[I],80);
}
}
}
if (ArgCount==0 && *ArcName!=0)
strcpy(ArgNames[(ArgCount++) & 0x0f],"*.*");
if (strrchr(PointToName(ArcName),'.')==NULL)
strcat(ArcName,isupper(*ArcName) ? ".RAR":".rar");
ArgCount &= 0xF;
}
void ExecuteCommand()
{
switch(MainCommand)
{
case 'E':
case 'X':
case 'T':
ExtrFile();
break;
case 'V':
case 'L':
ListArchive();
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -