Updated unrar source from 5.9.4 to 6.0.5

This commit is contained in:
Jens Steube
2021-05-15 11:31:42 +02:00
parent ce90f83b65
commit f4ca10b116
32 changed files with 400 additions and 94 deletions
+174 -25
View File
@@ -42,6 +42,7 @@ void CmdExtract::DoExtract()
Cmd->Password.Clean(); // Clean user entered password before processing next archive.
ReconstructDone=false; // Must be reset here, not in ExtractArchiveInit().
UseExactVolName=false; // Must be reset here, not in ExtractArchiveInit().
while (true)
{
EXTRACT_ARC_CODE Code=ExtractArchive();
@@ -140,7 +141,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive()
return EXTRACT_ARC_NEXT;
#ifndef SFX_MODULE
if (Arc.Volume && !Arc.FirstVolume)
if (Arc.Volume && !Arc.FirstVolume && !UseExactVolName)
{
wchar FirstVolName[NM];
VolNameToFirstName(ArcName,FirstVolName,ASIZE(FirstVolName),Arc.NewNumbering);
@@ -158,6 +159,16 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive()
if (Arc.Volume)
{
#ifndef SFX_MODULE
// Try to speed up extraction for independent solid volumes by starting
// extraction from non-first volume if we can.
if (!UseExactVolName && Arc.Solid && DetectStartVolume(Arc.FileName,Arc.NewNumbering))
{
UseExactVolName=true;
return EXTRACT_ARC_REPEAT;
}
#endif
// Calculate the total size of all accessible volumes.
// This size is necessary to display the correct total progress indicator.
@@ -318,11 +329,11 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
Arc.ConvertAttributes();
#if !defined(SFX_MODULE) && !defined(RARDLL)
if (Arc.FileHead.SplitBefore && FirstFile)
if (Arc.FileHead.SplitBefore && FirstFile && !UseExactVolName)
{
wchar CurVolName[NM];
wcsncpyz(CurVolName,ArcName,ASIZE(CurVolName));
VolNameToFirstName(ArcName,ArcName,ASIZE(ArcName),Arc.NewNumbering);
GetFirstVolIfFullSet(ArcName,Arc.NewNumbering,ArcName,ASIZE(ArcName));
if (wcsicomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
{
@@ -575,7 +586,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
TotalFileCount++;
}
FileCount++;
if (Command!='I')
if (Command!='I' && !Cmd->DisableNames)
if (SkipSolid)
mprintf(St(MExtrSkipFile),ArcFileName);
else
@@ -594,8 +605,10 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
mprintf(St(MExtrFile),DestFileName);
break;
}
if (!Cmd->DisablePercentage)
if (!Cmd->DisablePercentage && !Cmd->DisableNames)
mprintf(L" ");
if (Cmd->DisableNames)
uiEolAfterMsg(); // Avoid erasing preceding messages by percentage indicator in -idn mode.
DataIO.CurUnpRead=0;
DataIO.CurUnpWrite=0;
@@ -641,7 +654,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
ExtrPrepareName(Arc,Arc.FileHead.RedirName,NameExisting,ASIZE(NameExisting));
if (FileCreateMode && *NameExisting!=0) // *NameExisting can be 0 in case of excessive -ap switch.
if (Type==FSREDIR_HARDLINK)
LinkSuccess=ExtractHardlink(DestFileName,NameExisting,ASIZE(NameExisting));
LinkSuccess=ExtractHardlink(Cmd,DestFileName,NameExisting,ASIZE(NameExisting));
else
LinkSuccess=ExtractFileCopy(CurFile,Arc.FileName,DestFileName,NameExisting,ASIZE(NameExisting));
}
@@ -653,7 +666,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
}
else
{
uiMsg(UIERROR_UNKNOWNEXTRA, Arc.FileName, DestFileName);
uiMsg(UIERROR_UNKNOWNEXTRA,Arc.FileName,DestFileName);
LinkSuccess=false;
}
@@ -711,7 +724,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
{
if (ValidCRC)
{
if (Command!='P' && Command!='I')
if (Command!='P' && Command!='I' && !Cmd->DisableNames)
mprintf(L"%s%s ",Cmd->DisablePercentage ? L" ":L"\b\b\b\b\b ",
Arc.FileHead.FileHash.Type==HASH_NONE ? L" ?":St(MOk));
}
@@ -734,7 +747,13 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
}
}
else
mprintf(L"\b\b\b\b\b ");
{
// We check SkipSolid to remove percent for skipped solid files only.
// We must not apply these \b to links with ShowChecksum==false
// and their possible error messages.
if (SkipSolid)
mprintf(L"\b\b\b\b\b ");
}
// If we successfully unpacked a hard link, we wish to set its file
// attributes. Hard link shares file metadata with link target,
@@ -781,7 +800,13 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE;
#endif
if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(DestFileName,Arc.FileHead.FileAttr))
{
uiMsg(UIERROR_FILEATTR,Arc.FileName,DestFileName);
// Android cannot set file attributes and while UIERROR_FILEATTR
// above is handled by Android RAR silently, this call would cause
// "Operation not permitted" message for every unpacked file.
ErrHandler.SysErrMsg();
}
PrevProcessed=true;
}
@@ -874,11 +899,21 @@ void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *De
#ifndef SFX_MODULE
if (Cmd->AppendArcNameToPath!=APPENDARCNAME_NONE)
{
if (Cmd->AppendArcNameToPath==APPENDARCNAME_DESTPATH)
wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize);
else
wcsncpyz(DestName,Arc.FirstVolumeName,DestSize); // To archive own dir.
SetExt(DestName,NULL,DestSize);
switch(Cmd->AppendArcNameToPath)
{
case APPENDARCNAME_DESTPATH: // To subdir of destination path.
wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize);
SetExt(DestName,NULL,DestSize);
break;
case APPENDARCNAME_OWNSUBDIR: // To subdir of archive own dir.
wcsncpyz(DestName,Arc.FirstVolumeName,DestSize);
SetExt(DestName,NULL,DestSize);
break;
case APPENDARCNAME_OWNDIR: // To archive own dir.
wcsncpyz(DestName,Arc.FirstVolumeName,DestSize);
RemoveNameFromPath(DestName);
break;
}
AddEndSlash(DestName,DestSize);
}
#endif
@@ -1048,8 +1083,11 @@ void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName)
{
if (Cmd->Test)
{
mprintf(St(MExtrTestFile),ArcFileName);
mprintf(L" %s",St(MOk));
if (!Cmd->DisableNames)
{
mprintf(St(MExtrTestFile),ArcFileName);
mprintf(L" %s",St(MOk));
}
return;
}
@@ -1068,26 +1106,33 @@ void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName)
}
if (!DirExist)
{
CreatePath(DestFileName,true);
CreatePath(DestFileName,true,Cmd->DisableNames);
MDCode=MakeDir(DestFileName,!Cmd->IgnoreGeneralAttr,Arc.FileHead.FileAttr);
if (MDCode!=MKDIR_SUCCESS)
if (MDCode!=MKDIR_SUCCESS && !IsNameUsable(DestFileName))
{
uiMsg(UIMSG_CORRECTINGNAME,Arc.FileName);
wchar OrigName[ASIZE(DestFileName)];
wcsncpyz(OrigName,DestFileName,ASIZE(OrigName));
MakeNameUsable(DestFileName,true);
CreatePath(DestFileName,true);
MDCode=MakeDir(DestFileName,!Cmd->IgnoreGeneralAttr,Arc.FileHead.FileAttr);
#ifndef SFX_MODULE
if (MDCode==MKDIR_SUCCESS)
uiMsg(UIERROR_RENAMING,Arc.FileName,OrigName,DestFileName);
uiMsg(UIERROR_RENAMING,Arc.FileName,OrigName,DestFileName);
#endif
DirExist=FileExist(DestFileName) && IsDir(GetFileAttr(DestFileName));
if (!DirExist)
{
CreatePath(DestFileName,true,Cmd->DisableNames);
MDCode=MakeDir(DestFileName,!Cmd->IgnoreGeneralAttr,Arc.FileHead.FileAttr);
}
}
}
}
if (MDCode==MKDIR_SUCCESS)
{
mprintf(St(MCreatDir),DestFileName);
mprintf(L" %s",St(MOk));
if (!Cmd->DisableNames)
{
mprintf(St(MCreatDir),DestFileName);
mprintf(L" %s",St(MOk));
}
PrevProcessed=true;
}
else
@@ -1141,6 +1186,9 @@ bool CmdExtract::ExtrCreateFile(Archive &Arc,File &CurFile)
if (!UserReject)
{
ErrHandler.CreateErrorMsg(Arc.FileName,DestFileName);
if (FileExist(DestFileName) && IsDir(GetFileAttr(DestFileName)))
uiMsg(UIERROR_DIRNAMEEXISTS);
#ifdef RARDLL
Cmd->DllError=ERAR_ECREATE;
#endif
@@ -1153,7 +1201,7 @@ bool CmdExtract::ExtrCreateFile(Archive &Arc,File &CurFile)
MakeNameUsable(DestFileName,true);
CreatePath(DestFileName,true);
CreatePath(DestFileName,true,Cmd->DisableNames);
if (FileCreate(Cmd,&CurFile,DestFileName,ASIZE(DestFileName),&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime,true))
{
#ifndef SFX_MODULE
@@ -1196,3 +1244,104 @@ bool CmdExtract::CheckUnpVer(Archive &Arc,const wchar *ArcFileName)
}
return !WrongVer;
}
#ifndef SFX_MODULE
// To speed up solid volumes extraction, try to find a non-first start volume,
// which still allows to unpack all files. It is possible for independent
// solid volumes with solid statistics reset in the beginning.
bool CmdExtract::DetectStartVolume(const wchar *VolName,bool NewNumbering)
{
wchar *ArgName=Cmd->FileArgs.GetString();
Cmd->FileArgs.Rewind();
if (ArgName!=NULL && (wcscmp(ArgName,L"*")==0 || wcscmp(ArgName,L"*.*")==0))
return false; // No need to check further for * and *.* masks.
wchar StartName[NM];
*StartName=0;
// Start search from first volume if all volumes preceding current are available.
wchar NextName[NM];
GetFirstVolIfFullSet(VolName,NewNumbering,NextName,ASIZE(NextName));
bool Matched=false;
while (!Matched)
{
Archive Arc(Cmd);
if (!Arc.Open(NextName) || !Arc.IsArchive(false) || !Arc.Volume)
break;
bool OpenNext=false;
while (Arc.ReadHeader()>0)
{
Wait();
HEADER_TYPE HeaderType=Arc.GetHeaderType();
if (HeaderType==HEAD_ENDARC)
{
OpenNext|=Arc.EndArcHead.NextVolume; // Allow open next volume.
break;
}
if (HeaderType==HEAD_FILE)
{
if (!Arc.FileHead.SplitBefore)
{
if (!Arc.FileHead.Solid) // Can start extraction from here.
wcsncpyz(StartName,NextName,ASIZE(StartName));
if (Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL,0)!=0)
{
Matched=true; // First matched file found, must stop further scan.
break;
}
}
if (Arc.FileHead.SplitAfter)
{
OpenNext=true; // Allow open next volume.
break;
}
}
Arc.SeekToNext();
}
Arc.Close();
if (!OpenNext)
break;
NextVolumeName(NextName,ASIZE(NextName),!Arc.NewNumbering);
}
bool NewStartFound=wcscmp(VolName,StartName)!=0;
if (NewStartFound) // Found a new volume to start extraction.
wcsncpyz(ArcName,StartName,ASIZE(ArcName));
return NewStartFound;
}
#endif
#ifndef SFX_MODULE
// Return the first volume name if all volumes preceding the specified
// are available. Otherwise return the specified volume name.
void CmdExtract::GetFirstVolIfFullSet(const wchar *SrcName,bool NewNumbering,wchar *DestName,size_t DestSize)
{
wchar FirstVolName[NM];
VolNameToFirstName(SrcName,FirstVolName,ASIZE(FirstVolName),NewNumbering);
wchar NextName[NM];
wcsncpyz(NextName,FirstVolName,ASIZE(NextName));
wchar ResultName[NM];
wcsncpyz(ResultName,SrcName,ASIZE(ResultName));
while (true)
{
if (wcscmp(SrcName,NextName)==0)
{
wcsncpyz(ResultName,FirstVolName,DestSize);
break;
}
if (!FileExist(NextName))
break;
NextVolumeName(NextName,ASIZE(NextName),!NewNumbering);
}
wcsncpyz(DestName,ResultName,DestSize);
}
#endif