📄 unrar.c
字号:
case 0:
Help();
exit(0);
default:
Help();
exit(USER_ERROR);
}
}
void ShutDown(Mode)
int Mode;
{
if (Mode & SD_FILES)
{
if (ArcFPtr!=NULL)
fclose(ArcFPtr);
if (FileFPtr!=NULL)
fclose(FileFPtr);
}
if (Mode & SD_MEMORY)
{
if (TmpMemory!=NULL)
MEMFREE(TmpMemory);
printf("\n");
}
}
void Help()
{
printf("\n Usage: UNRAR <command> <archive> <files...>\n");
printf("\n <Commands>\n");
printf("\n x Extract files with full path");
printf("\n e Extract files to current directory");
printf("\n t Test archive files");
printf("\n v Verbosely list contents of archive");
printf("\n l List contents of archive");
printf("\n");
}
int ExtrFile()
{
char DestFileName[80];
long FileCount=0,TotalFileCount=0,DirCount=0,ErrCount=0;
int ExtrFile=0,Size,SkipSolid=0,UnpSolid;
if ((ArcFPtr=fopen(ArcName,FOPENREADMODE))==NULL)
ErrExit(EOPEN,FATAL_ERROR);
CheckArc();
CreateEncTbl(TmpMemory);
UnpVolume=UnpSolid=0;
if (MainCommand=='T')
printf("\n Testing archive %s\n",ArcName);
else
printf("\n Extracting from %s\n",ArcName);
while (1)
{
Size=ReadBlock(FILE_HEAD);
if (Size<=0 && UnpVolume==0)
break;
if ((Lhd.Flags & LHD_SPLIT_BEFORE) && SolidType)
{
printf("\nSolid archive: first volume required");
ErrExit(EEMPTY,FATAL_ERROR);
}
if (UnpVolume && Size==0)
MergeArc(0);
UnpVolume=(Lhd.Flags & LHD_SPLIT_AFTER);
fseek(ArcFPtr,NextBlockPos-Lhd.PackSize,SEEK_SET);
TestMode=0;
ExtrFile=0;
SkipSolid=0;
if (IsProcessFile(COMPARE_PATH) && (Lhd.Flags & LHD_SPLIT_BEFORE)==0
|| (SkipSolid=SolidType)!=0)
{
strcpy(DestFileName,ExtrPath);
strcat(DestFileName,(MainCommand!='E') ? ArcFileName : PointToName(ArcFileName));
ExtrFile=!SkipSolid;
if (Lhd.UnpVer<15 || Lhd.UnpVer>UNP_VER)
{
printf("\n %s: unknown method",ArcFileName);
ExtrFile=0;
ErrCount++;
ExitCode=WARNING;
}
if (Lhd.Flags & LHD_PASSWORD)
{
printf("\n %s: cannot process encrypted file",ArcFileName);
if (SolidType)
ErrExit(EEMPTY,FATAL_ERROR);
ExtrFile=0;
ErrCount++;
ExitCode=WARNING;
}
if (Lhd.HostOS==MS_DOS && (Lhd.FileAttr & DOSFA_DIREC))
{
if (MainCommand=='E')
continue;
if (SkipSolid)
{
printf("\n Skipping %-55s Ok",ArcFileName);
continue;
}
if (MainCommand=='T')
{
printf("\n Testing %-55s Ok",ArcFileName);
continue;
}
CreatePath(DestFileName);
if (MAKEDIR(DestFileName)==0)
printf("\n Creating %-55s",ArcFileName);
continue;
}
else
{
if (MainCommand=='T' && ExtrFile)
TestMode=1;
if ((MainCommand=='E' || MainCommand=='X') && ExtrFile)
{
CreatePath(DestFileName);
if ((FileFPtr=fopen(DestFileName,FOPENWRITEMODE))==NULL)
{
printf("\n Cannot create %s",DestFileName);
ExitCode=WARNING;
ExtrFile=0;
}
}
}
if (!ExtrFile && SolidType)
SkipSolid=TestMode=ExtrFile=1;
if (ExtrFile)
{
TotalFileCount++;
if (SkipSolid)
printf("\n Skipping %-55s",ArcFileName);
else
{
FileCount++;
switch(MainCommand)
{
case 'T':
printf("\n Testing %-55s",ArcFileName);
break;
case 'X':
case 'E':
printf("\n Extracting %-55s",DestFileName);
break;
}
}
strcpy(CurExtrFile,DestFileName);
UnpFileCRC=0xFFFFFFFFL;
UnpPackedSize=Lhd.PackSize;
DestUnpSize=Lhd.UnpSize;
RdUnpFPtr=ArcFPtr;
WrUnpFPtr=FileFPtr;
if (Lhd.Method==0x30)
UnstoreFile();
else
if (unpack(TmpMemory,UnpRead,UnpWrite,UnpSolid)==-1)
ErrExit(EWRITE,WRITE_ERROR);
if (TotalFileCount>0 && SolidType)
UnpSolid=1;
if (UnpFileCRC==~Lhd.FileCRC)
{
if (MainCommand!='P')
printf(" Ok");
}
else
{
fseek(ArcFPtr,NextBlockPos,SEEK_SET);
printf("\n %-15s : CRC failed",ArcFileName);
ExitCode=CRC_ERROR;
ErrCount++;
}
if (!TestMode)
{
SETFILETIME(FileFPtr,(void *)&Lhd.FileTime);
tclose(FileFPtr);
}
TestMode=0;
*CurExtrFile=0;
}
}
if (!ExtrFile && !SolidType)
fseek(ArcFPtr,NextBlockPos,SEEK_SET);
}
tclose(ArcFPtr);
if ((FileCount+DirCount)==0)
{
printf("\n No files");
ExitCode=WARNING;
}
else
if (ErrCount==0)
printf("\n All OK");
else
printf("\n Total errors: %ld",ErrCount);
return(0);
}
void ListArchive()
{
unsigned long TotalPackSize,TotalUnpSize,FileCount;
int I;
TotalPackSize=TotalUnpSize=FileCount=0;
if ((ArcFPtr=fopen(ArcName,FOPENREADMODE))==NULL)
ErrExit(EOPEN,FATAL_ERROR);
CheckArc();
printf("\n ");
if (SolidType)
printf("Solid ");
if (Mhd.Flags & MHD_MULT_VOL)
printf("%colume ",(SolidType) ? 'v':'V');
else
printf("%crchive ",(SolidType) ? 'a':'A');
printf("%s\n",ArcName);
if (MainCommand=='V')
printf("\n Pathname/Comment\n%12.12s","");
else
printf("\n Name ");
printf(" Size Packed Ratio Date Time Attr CRC-32 Meth Ver\n");
for (I=0;I<77;I++)
printf("-");
while(ReadBlock(FILE_HEAD) > 0)
{
if (IsProcessFile(NOT_COMPARE_PATH))
{
printf("\n%c",(Lhd.Flags & LHD_PASSWORD) ? '*' : ' ');
if (MainCommand=='V')
{
printf("%-s",ArcFileName);
printf("\n%12s ","");
}
else
printf("%-12s",PointToName(ArcFileName));
printf(" %8ld %8ld ",Lhd.UnpSize,Lhd.PackSize);
if (Lhd.Flags & (LHD_SPLIT_AFTER | LHD_SPLIT_BEFORE))
printf(" Split");
else
printf(" %3d%% ",ToPercent(Lhd.PackSize,Lhd.UnpSize));
printf(" %02d-%02d-%02d %02d:%02d ",(int)(Lhd.FileTime>>16) & 0x1f,
(int)(Lhd.FileTime>>21) & 0xf,(int)((Lhd.FileTime>>25)+1980)%100,
(int)(Lhd.FileTime>>11) & 0x1f,(int)(Lhd.FileTime>>5) & 0x3f);
if (Lhd.HostOS==MS_DOS)
printf("%c%c%c%c%c",
(Lhd.FileAttr & DOSFA_DIREC ) ? 'D' : '.',
(Lhd.FileAttr & DOSFA_RDONLY) ? 'R' : '.',
(Lhd.FileAttr & DOSFA_HIDDEN) ? 'H' : '.',
(Lhd.FileAttr & DOSFA_SYSTEM) ? 'S' : '.',
(Lhd.FileAttr & DOSFA_ARCH ) ? 'A' : '.');
else
printf(" ");
printf(" %8.8lX m%d %d.%d",Lhd.FileCRC,Lhd.Method-0x30,Lhd.UnpVer/10,Lhd.UnpVer%10);
if (!(Lhd.Flags & LHD_SPLIT_BEFORE))
{
TotalUnpSize+=Lhd.UnpSize;
FileCount++;
}
TotalPackSize+=Lhd.PackSize;
}
fseek(ArcFPtr,NextBlockPos,SEEK_SET);
}
printf("\n");
for (I=0;I<77;I++)
printf("-");
printf("\n%5ld %16ld %8ld %4d%%\n",FileCount,TotalUnpSize,TotalPackSize,ToPercent(TotalPackSize,TotalUnpSize));
tclose(ArcFPtr);
}
int IsProcessFile(ComparePath)
int ComparePath;
{
int NumName,WildCards;
char ArgName[80],dir1[80],name1[15],dir2[80],name2[15];
for (NumName=0;NumName<ArgCount;NumName++)
{
memcpy((void *)ArgName,(void *)ArgNames[NumName],sizeof(ArgName));
WildCards=(strchr(ArgName,'?')!=NULL || strchr(ArgName,'*')!=NULL);
SplitName(ArgName,dir1,name1);
SplitName(ArcFileName,dir2,name2);
if (CmpName(name1,name2) && ((ComparePath==NOT_COMPARE_PATH && *dir1==0) ||
WildCards && strnicomp(dir1,dir2,strlen(dir1))==0 ||
strnicomp(dir1,dir2,1000)==0))
return(1);
}
return(0);
}
int ReadBlock(BlockType)
int BlockType;
{
UDWORD HeadCRC;
UBYTE Header[32];
int Size,I;
memset(&Lhd,0,sizeof(Lhd));
memset(Header,0,sizeof(Header));
while (1)
{
Size=tread(ArcFPtr,Header,32);
Lhd.HeadCRC = Header[0] +(UWORD)Header[1]*0x100;
Lhd.HeadType = Header[2];
Lhd.Flags = Header[3] +(UWORD)Header[4]*0x100;
Lhd.HeadSize = Header[5] +(UWORD)Header[6]*0x100;;
Lhd.PackSize = Header[7] +(UWORD)Header[8]*0x100+(UDWORD)Header[9]*0x10000L+(UDWORD)Header[10]*0x1000000L;
Lhd.UnpSize = Header[11]+(UWORD)Header[12]*0x100+(UDWORD)Header[13]*0x10000L+(UDWORD)Header[14]*0x1000000L;
Lhd.HostOS = Header[15];
Lhd.FileCRC = Header[16]+(UWORD)Header[17]*0x100+(UDWORD)Header[18]*0x10000L+(UDWORD)Header[19]*0x1000000L;
Lhd.FileTime = Header[20]+(UWORD)Header[21]*0x100+(UDWORD)Header[22]*0x10000L+(UDWORD)Header[23]*0x1000000L;
Lhd.UnpVer = Header[24];
Lhd.Method = Header[25];
Lhd.NameSize = Header[26]+(UWORD)Header[27]*0x100;
Lhd.FileAttr = Header[28]+(UWORD)Header[29]*0x100+(UDWORD)Header[30]*0x10000L+(UDWORD)Header[31]*0x1000000L;
if (Size != 0 && (Size<7 || Lhd.HeadSize<7))
ErrExit(EARCH,FATAL_ERROR);
NextBlockPos=ftell(ArcFPtr)-Size+Lhd.HeadSize;
if (Lhd.Flags & LONG_BLOCK)
NextBlockPos+=Lhd.PackSize;
if (Size==0 || BlockType==ALL_HEAD || Lhd.HeadType==BlockType)
break;
fseek(ArcFPtr,NextBlockPos,SEEK_SET);
}
if (Size>0 && BlockType==FILE_HEAD)
{
tread(ArcFPtr,ArcFileName,Lhd.NameSize);
ArcFileName[Lhd.NameSize]=0;
Size+=Lhd.NameSize;
HeadCRC=CRC(0xFFFFFFFFL,&Header[2],30);
if (!(Lhd.HeadCRC==(UWORD)~CRC(HeadCRC,&ArcFileName[0],Lhd.NameSize)))
printf("\n %s: file header broken\n",ArcFileName);
for (I=0;ArcFileName[I];I++)
if (ArcFileName[I]=='\\' || ArcFileName[I]=='/')
ArcFileName[I]=PATHDIV;
if (Lhd.HostOS==MS_DOS)
strtolwr(ArcFileName);
}
return(Size);
}
int UnpRead(Addr,Count)
UBYTE *Addr;
UWORD Count;
{
int RetCode;
unsigned int ReadSize,TotalRead=0;
UBYTE *ReadAddr;
ReadAddr=Addr;
while (Count > 0)
{
ReadSize=(unsigned int)((Count>UnpPackedSize) ? UnpPackedSize : Count);
if ((RetCode=fread(ReadAddr,1,ReadSize,RdUnpFPtr))!=ReadSize)
break;
TotalRead+=RetCode;
ReadAddr+=RetCode;
Count-=RetCode;
UnpPackedSize-=RetCode;
if (UnpPackedSize == 0 && UnpVolume)
MergeArc(1);
else
break;
}
if (RetCode!=-1)
RetCode=(int)TotalRead;
return(RetCode);
}
int UnpWrite(Addr,Count)
UBYTE *Addr;
UWORD Count;
{
int RetCode;
if (TestMode)
RetCode=(int)Count;
else
if ((RetCode=fwrite(Addr,1,Count,WrUnpFPtr))!=Count)
RetCode = -1;
if (RetCode!=-1)
UnpFileCRC=CRC(UnpFileCRC,Addr,(UWORD)RetCode);
return(RetCode);
}
UDWORD CRC(StartCRC,Addr,Size)
UDWORD StartCRC;
UBYTE *Addr;
UWORD Size;
{
UWORD I;
if (!CRC32_Table[1])
InitCRC();
for (I=0;I<Size;I++)
StartCRC = CRC32_Table[(UBYTE)StartCRC ^ Addr[I]] ^ (StartCRC >> 8);
return(StartCRC);
}
void InitCRC()
{
int I, J;
UDWORD C;
for (I=0;I<256;I++)
{
for (C=I,J=0;J<8;J++)
C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
CRC32_Table[I]=C;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -