Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
 (sic: version numbers) (#43)
  • Loading branch information
chlily1 authored Jan 24, 2025
1 parent 7f22bab commit a4ae80f
Show file tree
Hide file tree
Showing 20 changed files with 231 additions and 44 deletions.
2 changes: 2 additions & 0 deletions archive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ Archive::Archive(CommandData *InitCmd)
FailedHeaderDecryption=false;
BrokenHeader=false;
LastReadBlock=0;
CurHeaderType=HEAD_UNKNOWN;

CurBlockPos=0;
NextBlockPos=0;

RecoveryPercent=-1;

MainHead.Reset();
CryptHead={};
Expand Down
2 changes: 2 additions & 0 deletions archive.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class Archive:public File
bool DummyCmd;
CommandData *Cmd;

int RecoveryPercent;

RarTime LatestTime;
int LastReadBlock;
Expand All @@ -65,6 +66,7 @@ class Archive:public File
size_t SearchBlock(HEADER_TYPE HeaderType);
size_t SearchSubBlock(const wchar *Type);
size_t SearchRR();
int GetRecoveryPercent() {return RecoveryPercent;}
size_t ReadHeader();
void CheckArc(bool EnableBroken);
void CheckOpen(const std::wstring &Name);
Expand Down
14 changes: 12 additions & 2 deletions arcread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ void Archive::UnexpEndArcMsg()
if (CurBlockPos!=ArcSize || NextBlockPos!=ArcSize)
{
uiMsg(UIERROR_UNEXPEOF,FileName);
if (CurHeaderType!=HEAD_FILE)
if (CurHeaderType!=HEAD_FILE && CurHeaderType!=HEAD_UNKNOWN)
uiMsg(UIERROR_TRUNCSERVICE,FileName,SubHead.FileName);

ErrHandler.SetErrorCode(RARX_WARNING);
Expand Down Expand Up @@ -904,6 +904,16 @@ size_t Archive::ReadHeader50()
if (!FileBlock && hd->CmpName(SUBHEAD_TYPE_CMT))
MainComment=true;

// For RAR5 format we read the user specified recovery percent here.
if (!FileBlock && hd->CmpName(SUBHEAD_TYPE_RR) && hd->SubData.size()>0)
{
// It is stored as a single byte up to RAR 6.02 and as vint since
// 6.10, where we extended the maximum RR size from 99% to 1000%.
RawRead RawPercent;
RawPercent.Read(hd->SubData.data(),hd->SubData.size());
RecoveryPercent=(int)RawPercent.GetV();

}

if (BadCRC) // Add the file name to broken header message displayed above.
uiMsg(UIERROR_FHEADERBROKEN,Archive::FileName,hd->FileName);
Expand Down Expand Up @@ -1308,7 +1318,7 @@ size_t Archive::ReadHeader14()
std::string FileName(NameSize,0);
Raw.GetB((byte *)&FileName[0],NameSize);
std::string NameA;
IntToExt(FileName,NameA);
OemToExt(FileName,NameA);
CharToWide(NameA,FileHead.FileName);
ConvertNameCase(FileHead.FileName);
ConvertFileHeader(&FileHead);
Expand Down
6 changes: 3 additions & 3 deletions dll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
AnsiArcName=r->ArcName;
#ifdef _WIN_ALL
if (!AreFileApisANSI())
IntToExt(r->ArcName,AnsiArcName);
OemToExt(r->ArcName,AnsiArcName);
#endif
}

Expand Down Expand Up @@ -369,7 +369,7 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
// We must not apply OemToCharBuffA directly to DestPath,
// because we do not know DestPath length and OemToCharBuffA
// does not stop at 0.
IntToExt(ExtrPathA,ExtrPathA);
OemToExt(ExtrPathA,ExtrPathA);
#endif
CharToWide(ExtrPathA,Data->Cmd.ExtrPath);
AddEndSlash(Data->Cmd.ExtrPath);
Expand All @@ -381,7 +381,7 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
// We must not apply OemToCharBuffA directly to DestName,
// because we do not know DestName length and OemToCharBuffA
// does not stop at 0.
IntToExt(DestNameA,DestNameA);
OemToExt(DestNameA,DestNameA);
#endif
CharToWide(DestNameA,Data->Cmd.DllDestName);
}
Expand Down
10 changes: 5 additions & 5 deletions dll.rc
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
#include <commctrl.h>

VS_VERSION_INFO VERSIONINFO
FILEVERSION 7, 10, 2, 1436
PRODUCTVERSION 7, 10, 2, 1436
FILEVERSION 7, 10, 3, 1480
PRODUCTVERSION 7, 10, 3, 1480
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
{
Expand All @@ -14,9 +14,9 @@ FILETYPE VFT_APP
VALUE "CompanyName", "Alexander Roshal\0"
VALUE "ProductName", "RAR decompression library\0"
VALUE "FileDescription", "RAR decompression library\0"
VALUE "FileVersion", "7.10.2\0"
VALUE "ProductVersion", "7.10.2\0"
VALUE "LegalCopyright", "Copyright � Alexander Roshal 1993-2024\0"
VALUE "FileVersion", "7.10.3\0"
VALUE "ProductVersion", "7.10.3\0"
VALUE "LegalCopyright", "Copyright � Alexander Roshal 1993-2025\0"
VALUE "OriginalFilename", "Unrar.dll\0"
}
}
Expand Down
4 changes: 3 additions & 1 deletion extract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1606,8 +1606,10 @@ void CmdExtract::AnalyzeArchive(const std::wstring &ArcName,bool Volume,bool New

if (!Arc.FileHead.SplitBefore)
{
if (!MatchFound && !Arc.FileHead.Solid) // Can start extraction from here.
if (!MatchFound && !Arc.FileHead.Solid && !Arc.FileHead.Dir &&
Arc.FileHead.RedirType==FSREDIR_NONE && Arc.FileHead.Method!=0)
{
// Can start extraction from here.
// We would gain nothing and unnecessarily complicate extraction
// if we set StartName for first volume or StartPos for first
// archived file.
Expand Down
2 changes: 2 additions & 0 deletions filefn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,8 @@ void ResetFileCache(const std::wstring &Name)





// Delete symbolic links in file path, if any, and replace them by directories.
// Prevents extracting files outside of destination folder with symlink chains.
bool LinksToDirs(const std::wstring &SrcName,const std::wstring &SkipPart,std::wstring &LastChecked)
Expand Down
23 changes: 21 additions & 2 deletions list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,21 @@ void ListArchive(CommandData *Cmd)
}
break;
case HEAD_SERVICE:
// For service blocks dependent on previous block, such as ACL
// or NTFS stream, we use "file matched" flag of host file.
// Independent blocks like RR are matched separately,
// so we can list them by their name. Also we match even
// dependent blocks separately if "vta -idn" are set. User may
// want to see service blocks only in this case.
if (!Arc.SubHead.SubBlock || Cmd->DisableNames)
FileMatched=Cmd->IsProcessFile(Arc.SubHead,NULL,MATCH_WILDSUBPATH,0,NULL)!=0;
if (FileMatched && !Bare)
{
// Here we set DisableNames parameter to true regardless of
// Cmd->DisableNames. If "vta -idn" are set together, user
// wants to see service blocks like RR only.
if (Technical && ShowService)
ListFileHeader(Arc,Arc.SubHead,TitleShown,Verbose,true,false,Cmd->DisableNames);
ListFileHeader(Arc,Arc.SubHead,TitleShown,Verbose,true,false,false);
}
break;
}
Expand Down Expand Up @@ -249,7 +260,7 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo
if (hd.SplitAfter)
wcsncpyz(RatioStr,L"-->",ASIZE(RatioStr));
else
swprintf(RatioStr,ASIZE(RatioStr),L"%d%%",ToPercentUnlim(hd.PackSize,hd.UnpSize));
swprintf(RatioStr,ASIZE(RatioStr),L"%u%%",ToPercentUnlim(hd.PackSize,hd.UnpSize));

wchar DateStr[50];
hd.mtime.GetText(DateStr,ASIZE(DateStr),Technical);
Expand Down Expand Up @@ -315,6 +326,14 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo
mprintf(L"\n%12ls: %ls",St(MListSize),UnpSizeText);
mprintf(L"\n%12ls: %ls",St(MListPacked),PackSizeText);
mprintf(L"\n%12ls: %ls",St(MListRatio),RatioStr);

if (!FileBlock && Arc.SubHead.CmpName(SUBHEAD_TYPE_RR))
{
// Display the original -rrN percent if available.
int RecoveryPercent=Arc.GetRecoveryPercent();
if (RecoveryPercent>0) // It can be -1 if failed to detect.
mprintf(L"\n%12ls: %u%%",L"RR%", RecoveryPercent);
}
}
bool WinTitles=false;
#ifdef _WIN_ALL
Expand Down
5 changes: 4 additions & 1 deletion rar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ int main(int argc, char *argv[])
{
case 'T':
case 'V':
Cmd->Command[0]=UpperCmd;
// Also copy 't' and 'a' modifiers for -v[t,a], if present.
Cmd->Command.clear();
for (char *c=Switch+1;*c!=0;c++)
Cmd->Command+=etoupper(*c);
break;
case '?':
Cmd->OutHelp(RARX_SUCCESS);
Expand Down
40 changes: 26 additions & 14 deletions scantree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,23 +212,36 @@ bool ScanTree::GetNextMask()
UnixSlashToDos(CurMask,CurMask);
#endif

// We shall set it before appending the path separator to \\server\share
// UNC mask below, so "rar a -ep1 arc \\server\share" includes paths
// starting from "share\".
SpecPathLength=GetNamePos(CurMask);

// We prefer to scan entire disk if mask like \\server\share\ or c:\
// is specified regardless of recursion mode. Use \\server\share\*.*
// or c:\*.* mask to scan only the root directory.
if (CurMask.size()>2 && CurMask[0]=='\\' && CurMask[1]=='\\')
{
auto Slash=CurMask.find('\\',2);
if (Slash!=std::wstring::npos)
// is specified even without -r, but not with -r-. Use \\server\share\*.*,
// c:\*.* mask or -r- to scan only the root directory. Note that UNC names
// are possible both in Win32 and Unix, just with proper path separators.
if (Recurse!=RECURSE_DISABLE)
if (CurMask.size()>2 && CurMask[0]==CPATHDIVIDER && CurMask[1]==CPATHDIVIDER)
{
Slash=CurMask.find('\\',Slash+1);
// If backslash is found and it is the last string character.
ScanEntireDisk=Slash!=std::wstring::npos && Slash+1==CurMask.size();
auto Slash=CurMask.find(CPATHDIVIDER,2);
if (Slash!=std::wstring::npos)
{
Slash=CurMask.find(CPATHDIVIDER,Slash+1);
// If path separator is mssing or it is the last string character.
ScanEntireDisk=Slash==std::wstring::npos ||
Slash!=std::wstring::npos && Slash+1==CurMask.size();

// Win32 FindFirstFile fails for \\server\share names without
// the trailing backslash. So we add it here.
if (Slash==std::wstring::npos)
CurMask+=CPATHDIVIDER;
}
}
}
else
ScanEntireDisk=IsDriveLetter(CurMask) && IsPathDiv(CurMask[2]) && CurMask[3]==0;

else
ScanEntireDisk=IsDriveLetter(CurMask) && IsPathDiv(CurMask[2]) && CurMask[3]==0;

// Calculate the name position again, because we could modify UNC path above.
auto NamePos=GetNamePos(CurMask);
std::wstring Name=CurMask.substr(NamePos);
if (Name.empty())
Expand All @@ -238,7 +251,6 @@ bool ScanTree::GetNextMask()
AddEndSlash(CurMask);
CurMask+=MASKALL;
}
SpecPathLength=NamePos;
Depth=0;

OrigCurMask=CurMask;
Expand Down
5 changes: 3 additions & 2 deletions strfn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const wchar *NullToEmpty(const wchar *Str)
}


void IntToExt(const std::string &Src,std::string &Dest)
// Convert from OEM encoding.
void OemToExt(const std::string &Src,std::string &Dest)
{
#ifdef _WIN_ALL
if (std::addressof(Src)!=std::addressof(Dest))
Expand Down Expand Up @@ -44,7 +45,7 @@ void ArcCharToWide(const char *Src,std::wstring &Dest,ACTW_ENCODING Encoding)
std::string NameA;
if (Encoding==ACTW_OEM)
{
IntToExt(Src,NameA);
OemToExt(Src,NameA);
Src=NameA.data();
}
CharToWide(Src,Dest);
Expand Down
2 changes: 1 addition & 1 deletion strfn.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

const char* NullToEmpty(const char *Str);
const wchar* NullToEmpty(const wchar *Str);
void IntToExt(const std::string &Src,std::string &Dest);
void OemToExt(const std::string &Src,std::string &Dest);

enum ACTW_ENCODING { ACTW_DEFAULT, ACTW_OEM, ACTW_UTF8};
void ArcCharToWide(const char *Src,std::wstring &Dest,ACTW_ENCODING Encoding);
Expand Down
36 changes: 36 additions & 0 deletions threadmisc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,42 @@ uint GetNumberOfCPU()
return sysctlbyname("hw.ncpu",&Count,&Size,NULL,0)==0 ? Count:1;
#endif
#else // !_UNIX

#ifdef WIN32_CPU_GROUPS
// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getprocessaffinitymask
// "Starting with Windows 11 and Windows Server 2022, on a system with
// more than 64 processors, process and thread affinities span all
// processors in the system, across all processor groups, by default."
// Supposing there are 80 CPUs in 2 processor groups 40 CPUs each.
// Looks like, beginning from Windows 11 an app can use them all by default,
// not resorting to processor groups API. But if we use GetProcessAffinityMask
// to count CPUs, we would be limited to 40 CPUs only. So we call
// GetActiveProcessorCount() if it is available anf if there are multiple
// processor groups. For a single group we prefer the affinity aware
// GetProcessAffinityMask(). Out thread pool code handles the case
// with restricted processor group affinity. So we avoid the complicated
// code to calculate all processor groups affinity here, such as using
// GetLogicalProcessorInformationEx, and resort to GetActiveProcessorCount().
HMODULE hKernel=GetModuleHandle(L"kernel32.dll");
if (hKernel!=nullptr)
{
typedef DWORD (WINAPI *GETACTIVEPROCESSORCOUNT)(WORD GroupNumber);
GETACTIVEPROCESSORCOUNT pGetActiveProcessorCount=(GETACTIVEPROCESSORCOUNT)GetProcAddress(hKernel,"GetActiveProcessorCount");
typedef WORD (WINAPI *GETACTIVEPROCESSORGROUPCOUNT)();
GETACTIVEPROCESSORGROUPCOUNT pGetActiveProcessorGroupCount=(GETACTIVEPROCESSORGROUPCOUNT)GetProcAddress(hKernel,"GetActiveProcessorGroupCount");
if (pGetActiveProcessorCount!=nullptr && pGetActiveProcessorGroupCount!=nullptr &&
pGetActiveProcessorGroupCount()>1)
{
// Once the thread pool called SetThreadGroupAffinity(),
// GetProcessAffinityMask() below will return 0. So we shall always
// use GetActiveProcessorCount() here if there are multiple processor
// groups, which makes SetThreadGroupAffinity() call possible.
DWORD Count=pGetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
return Count;
}
}
#endif

DWORD_PTR ProcessMask;
DWORD_PTR SystemMask;

Expand Down
Loading

0 comments on commit a4ae80f

Please sign in to comment.