As with the previous libclamunrar commit, this update maintains the hack
in dll.cpp:332 that allows skipping of files in solid archives.
... | ... |
@@ -7,7 +7,7 @@ Note: This file refers to the source tarball. Things described here may differ |
7 | 7 |
|
8 | 8 |
ClamAV 0.102.3 is a bug patch release to address the following issues. |
9 | 9 |
|
10 |
-- |
|
10 |
+- Updated libclamunrar to UnRAR 5.9.2. |
|
11 | 11 |
|
12 | 12 |
Special thanks to the following for code contributions and bug reports: |
13 | 13 |
|
14 | 14 |
deleted file mode 100644 |
... | ... |
@@ -1,22 +0,0 @@ |
1 |
-PROJECT_NAME = ClamAV - Libclamunrar |
|
2 |
-OUTPUT_DIRECTORY = ../docs/libclamunrar |
|
3 |
-WARNINGS = YES |
|
4 |
-FILE_PATTERNS = *.c *.h |
|
5 |
-PERL_PATH = /usr/bin/perl |
|
6 |
-SEARCHENGINE = YES |
|
7 |
- |
|
8 |
-GENERATE_LATEX=NO |
|
9 |
-OPTIMIZE_OUTPUT_FOR_C=YES |
|
10 |
-HAVE_DOT=YES |
|
11 |
-CALL_GRAPH=YES |
|
12 |
-CALLER_GRAPH=YES |
|
13 |
-JAVADOC_AUTOBRIEF=YES |
|
14 |
-GENERATE_MAN=NO |
|
15 |
-EXAMPLE_PATH=examples |
|
16 |
- |
|
17 |
-DOT_CLEANUP=NO |
|
18 |
-MAX_DOT_GRAPH_DEPTH=3 |
|
19 |
- |
|
20 |
-EXTRACT_ALL=YES |
|
21 |
-INPUT = . \ |
|
22 |
- ../shared |
... | ... |
@@ -4,8 +4,15 @@ bool Archive::GetComment(Array<wchar> *CmtData) |
4 | 4 |
{ |
5 | 5 |
if (!MainComment) |
6 | 6 |
return false; |
7 |
- SaveFilePos SavePos(*this); |
|
7 |
+ int64 SavePos=Tell(); |
|
8 |
+ bool Success=DoGetComment(CmtData); |
|
9 |
+ Seek(SavePos,SEEK_SET); |
|
10 |
+ return Success; |
|
11 |
+} |
|
12 |
+ |
|
8 | 13 |
|
14 |
+bool Archive::DoGetComment(Array<wchar> *CmtData) |
|
15 |
+{ |
|
9 | 16 |
#ifndef SFX_MODULE |
10 | 17 |
uint CmtLength; |
11 | 18 |
if (Format==RARFMT14) |
... | ... |
@@ -136,7 +143,7 @@ bool Archive::GetComment(Array<wchar> *CmtData) |
136 | 136 |
bool Archive::ReadCommentData(Array<wchar> *CmtData) |
137 | 137 |
{ |
138 | 138 |
Array<byte> CmtRaw; |
139 |
- if (!ReadSubData(&CmtRaw,NULL)) |
|
139 |
+ if (!ReadSubData(&CmtRaw,NULL,false)) |
|
140 | 140 |
return false; |
141 | 141 |
size_t CmtSize=CmtRaw.Size(); |
142 | 142 |
CmtRaw.Push(0); |
... | ... |
@@ -208,8 +208,8 @@ bool Archive::IsArchive(bool EnableBroken) |
208 | 208 |
break; |
209 | 209 |
} |
210 | 210 |
|
211 |
- // This check allows to make RS based recovery even if password is incorrect. |
|
212 |
- // But we should not do it for EnableBroken or we'll get 'not RAR archive' |
|
211 |
+ |
|
212 |
+ // We should not do it for EnableBroken or we'll get 'not RAR archive' |
|
213 | 213 |
// messages when extracting encrypted archives with wrong password. |
214 | 214 |
if (FailedHeaderDecryption && !EnableBroken) |
215 | 215 |
return false; |
... | ... |
@@ -233,7 +233,7 @@ bool Archive::IsArchive(bool EnableBroken) |
233 | 233 |
// immediately after IsArchive call. |
234 | 234 |
if (HeadersLeft && (!SilentOpen || !Encrypted)) |
235 | 235 |
{ |
236 |
- SaveFilePos SavePos(*this); |
|
236 |
+ int64 SavePos=Tell(); |
|
237 | 237 |
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos; |
238 | 238 |
HEADER_TYPE SaveCurHeaderType=CurHeaderType; |
239 | 239 |
|
... | ... |
@@ -262,6 +262,7 @@ bool Archive::IsArchive(bool EnableBroken) |
262 | 262 |
CurBlockPos=SaveCurBlockPos; |
263 | 263 |
NextBlockPos=SaveNextBlockPos; |
264 | 264 |
CurHeaderType=SaveCurHeaderType; |
265 |
+ Seek(SavePos,SEEK_SET); |
|
265 | 266 |
} |
266 | 267 |
if (!Volume || FirstVolume) |
267 | 268 |
wcsncpyz(FirstVolumeName,FileName,ASIZE(FirstVolumeName)); |
... | ... |
@@ -29,7 +29,6 @@ class Archive:public File |
29 | 29 |
void UpdateLatestTime(FileHeader *CurBlock); |
30 | 30 |
void ConvertNameCase(wchar *Name); |
31 | 31 |
void ConvertFileHeader(FileHeader *hd); |
32 |
- void WriteBlock50(HEADER_TYPE HeaderType,BaseBlock *wb,bool OnlySetSize,bool NonFinalWrite); |
|
33 | 32 |
size_t ReadHeader14(); |
34 | 33 |
size_t ReadHeader15(); |
35 | 34 |
size_t ReadHeader50(); |
... | ... |
@@ -38,6 +37,7 @@ class Archive:public File |
38 | 38 |
void UnexpEndArcMsg(); |
39 | 39 |
void BrokenHeaderMsg(); |
40 | 40 |
void UnkEncVerMsg(const wchar *Name,const wchar *Info); |
41 |
+ bool DoGetComment(Array<wchar> *CmtData); |
|
41 | 42 |
bool ReadCommentData(Array<wchar> *CmtData); |
42 | 43 |
|
43 | 44 |
#if !defined(RAR_NOCRYPT) |
... | ... |
@@ -65,8 +65,6 @@ class Archive:public File |
65 | 65 |
size_t SearchBlock(HEADER_TYPE HeaderType); |
66 | 66 |
size_t SearchSubBlock(const wchar *Type); |
67 | 67 |
size_t SearchRR(); |
68 |
- void WriteBlock(HEADER_TYPE HeaderType,BaseBlock *wb=NULL,bool OnlySetSize=false,bool NonFinalWrite=false); |
|
69 |
- void SetBlockSize(HEADER_TYPE HeaderType,BaseBlock *wb=NULL) {WriteBlock(HeaderType,wb,true);} |
|
70 | 68 |
size_t ReadHeader(); |
71 | 69 |
void CheckArc(bool EnableBroken); |
72 | 70 |
void CheckOpen(const wchar *Name); |
... | ... |
@@ -83,7 +81,7 @@ class Archive:public File |
83 | 83 |
int64 GetStartPos(); |
84 | 84 |
void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile, |
85 | 85 |
const wchar *Name,uint Flags); |
86 |
- bool ReadSubData(Array<byte> *UnpData,File *DestFile); |
|
86 |
+ bool ReadSubData(Array<byte> *UnpData,File *DestFile,bool TestMode); |
|
87 | 87 |
HEADER_TYPE GetHeaderType() {return CurHeaderType;} |
88 | 88 |
RAROptions* GetRAROptions() {return Cmd;} |
89 | 89 |
void SetSilentOpen(bool Mode) {SilentOpen=Mode;} |
90 | 90 |
deleted file mode 100644 |
... | ... |
@@ -1,67 +0,0 @@ |
1 |
-ArcMemory::ArcMemory() |
|
2 |
-{ |
|
3 |
- Loaded=false; |
|
4 |
- SeekPos=0; |
|
5 |
-} |
|
6 |
- |
|
7 |
- |
|
8 |
-void ArcMemory::Load(const byte *Data,size_t Size) |
|
9 |
-{ |
|
10 |
- ArcData.Alloc(Size); |
|
11 |
- memcpy(&ArcData[0],Data,Size); |
|
12 |
- Loaded=true; |
|
13 |
- SeekPos=0; |
|
14 |
-} |
|
15 |
- |
|
16 |
- |
|
17 |
-bool ArcMemory::Unload() |
|
18 |
-{ |
|
19 |
- if (!Loaded) |
|
20 |
- return false; |
|
21 |
- Loaded=false; |
|
22 |
- return true; |
|
23 |
-} |
|
24 |
- |
|
25 |
- |
|
26 |
-bool ArcMemory::Read(void *Data,size_t Size,size_t &Result) |
|
27 |
-{ |
|
28 |
- if (!Loaded) |
|
29 |
- return false; |
|
30 |
- Result=(size_t)Min(Size,ArcData.Size()-SeekPos); |
|
31 |
- memcpy(Data,&ArcData[(size_t)SeekPos],Result); |
|
32 |
- SeekPos+=Result; |
|
33 |
- return true; |
|
34 |
-} |
|
35 |
- |
|
36 |
- |
|
37 |
-bool ArcMemory::Seek(int64 Offset,int Method) |
|
38 |
-{ |
|
39 |
- if (!Loaded) |
|
40 |
- return false; |
|
41 |
- if (Method==SEEK_SET) |
|
42 |
- { |
|
43 |
- if (Offset<0) |
|
44 |
- SeekPos=0; |
|
45 |
- else |
|
46 |
- SeekPos=Min((uint64)Offset,ArcData.Size()); |
|
47 |
- } |
|
48 |
- else |
|
49 |
- if (Method==SEEK_CUR || Method==SEEK_END) |
|
50 |
- { |
|
51 |
- if (Method==SEEK_END) |
|
52 |
- SeekPos=ArcData.Size(); |
|
53 |
- SeekPos+=(uint64)Offset; |
|
54 |
- if (SeekPos>ArcData.Size()) |
|
55 |
- SeekPos=Offset<0 ? 0 : ArcData.Size(); |
|
56 |
- } |
|
57 |
- return true; |
|
58 |
-} |
|
59 |
- |
|
60 |
- |
|
61 |
-bool ArcMemory::Tell(int64 *Pos) |
|
62 |
-{ |
|
63 |
- if (!Loaded) |
|
64 |
- return false; |
|
65 |
- *Pos=SeekPos; |
|
66 |
- return true; |
|
67 |
-} |
68 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,22 +0,0 @@ |
1 |
-#ifndef _RAR_ARCMEM_ |
|
2 |
-#define _RAR_ARCMEM_ |
|
3 |
- |
|
4 |
-// Memory interface for software fuzzers. |
|
5 |
- |
|
6 |
-class ArcMemory |
|
7 |
-{ |
|
8 |
- private: |
|
9 |
- bool Loaded; |
|
10 |
- Array<byte> ArcData; |
|
11 |
- uint64 SeekPos; |
|
12 |
- public: |
|
13 |
- ArcMemory(); |
|
14 |
- void Load(const byte *Data,size_t Size); |
|
15 |
- bool Unload(); |
|
16 |
- bool IsLoaded() {return Loaded;} |
|
17 |
- bool Read(void *Data,size_t Size,size_t &Result); |
|
18 |
- bool Seek(int64 Offset,int Method); |
|
19 |
- bool Tell(int64 *Pos); |
|
20 |
-}; |
|
21 |
- |
|
22 |
-#endif |
... | ... |
@@ -268,14 +268,14 @@ size_t Archive::ReadHeader15() |
268 | 268 |
uint FileTime=Raw.Get4(); |
269 | 269 |
hd->UnpVer=Raw.Get1(); |
270 | 270 |
|
271 |
- // RAR15 did not use the special dictionary size to mark dirs. |
|
272 |
- if (hd->UnpVer<20 && (hd->FileAttr & 0x10)!=0) |
|
273 |
- hd->Dir=true; |
|
274 |
- |
|
275 | 271 |
hd->Method=Raw.Get1()-0x30; |
276 | 272 |
size_t NameSize=Raw.Get2(); |
277 | 273 |
hd->FileAttr=Raw.Get4(); |
278 | 274 |
|
275 |
+ // RAR15 did not use the special dictionary size to mark dirs. |
|
276 |
+ if (hd->UnpVer<20 && (hd->FileAttr & 0x10)!=0) |
|
277 |
+ hd->Dir=true; |
|
278 |
+ |
|
279 | 279 |
hd->CryptMethod=CRYPT_NONE; |
280 | 280 |
if (hd->Encrypted) |
281 | 281 |
switch(hd->UnpVer) |
... | ... |
@@ -402,8 +402,8 @@ size_t Archive::ReadHeader15() |
402 | 402 |
if (rmode & 4) |
403 | 403 |
rlt.Second++; |
404 | 404 |
rlt.Reminder=0; |
405 |
- int count=rmode&3; |
|
406 |
- for (int J=0;J<count;J++) |
|
405 |
+ uint count=rmode&3; |
|
406 |
+ for (uint J=0;J<count;J++) |
|
407 | 407 |
{ |
408 | 408 |
byte CurByte=Raw.Get1(); |
409 | 409 |
rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8)); |
... | ... |
@@ -521,7 +521,6 @@ size_t Archive::ReadHeader15() |
521 | 521 |
{ |
522 | 522 |
// Last 7 bytes of recovered volume can contain zeroes, because |
523 | 523 |
// REV files store its own information (volume number, etc.) here. |
524 |
- SaveFilePos SavePos(*this); |
|
525 | 524 |
int64 Length=Tell(); |
526 | 525 |
Seek(Length-7,SEEK_SET); |
527 | 526 |
Recovered=true; |
... | ... |
@@ -584,7 +583,7 @@ size_t Archive::ReadHeader50() |
584 | 584 |
{ |
585 | 585 |
// This message is used by Android GUI to reset cached passwords. |
586 | 586 |
// Update appropriate code if changed. |
587 |
- uiMsg(UIERROR_BADPSW,FileName); |
|
587 |
+ uiMsg(UIERROR_BADPSW,FileName,FileName); |
|
588 | 588 |
FailedHeaderDecryption=true; |
589 | 589 |
ErrHandler.SetErrorCode(RARX_BADPWD); |
590 | 590 |
return 0; |
... | ... |
@@ -593,7 +592,7 @@ size_t Archive::ReadHeader50() |
593 | 593 |
{ |
594 | 594 |
// This message is used by Android GUI and Windows GUI and SFX to |
595 | 595 |
// reset cached passwords. Update appropriate code if changed. |
596 |
- uiMsg(UIWAIT_BADPSW,FileName); |
|
596 |
+ uiMsg(UIWAIT_BADPSW,FileName,FileName); |
|
597 | 597 |
Cmd->Password.Clean(); |
598 | 598 |
} |
599 | 599 |
|
... | ... |
@@ -720,6 +719,7 @@ size_t Archive::ReadHeader50() |
720 | 720 |
UnkEncVerMsg(FileName,Info); |
721 | 721 |
return 0; |
722 | 722 |
} |
723 |
+ |
|
723 | 724 |
Raw.GetB(CryptHead.Salt,SIZE_SALT50); |
724 | 725 |
if (CryptHead.UsePswCheck) |
725 | 726 |
{ |
... | ... |
@@ -1256,8 +1256,9 @@ size_t Archive::ReadHeader14() |
1256 | 1256 |
Raw.Read(NameSize); |
1257 | 1257 |
|
1258 | 1258 |
char FileName[NM]; |
1259 |
- Raw.GetB((byte *)FileName,Min(NameSize,ASIZE(FileName))); |
|
1260 |
- FileName[NameSize]=0; |
|
1259 |
+ size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1); |
|
1260 |
+ Raw.GetB((byte *)FileName,ReadNameSize); |
|
1261 |
+ FileName[ReadNameSize]=0; |
|
1261 | 1262 |
IntToExt(FileName,FileName,ASIZE(FileName)); |
1262 | 1263 |
CharToWide(FileName,FileHead.FileName,ASIZE(FileHead.FileName)); |
1263 | 1264 |
ConvertNameCase(FileHead.FileName); |
... | ... |
@@ -1414,7 +1415,7 @@ int64 Archive::GetStartPos() |
1414 | 1414 |
} |
1415 | 1415 |
|
1416 | 1416 |
|
1417 |
-bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile) |
|
1417 |
+bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile,bool TestMode) |
|
1418 | 1418 |
{ |
1419 | 1419 |
if (BrokenHeader) |
1420 | 1420 |
{ |
... | ... |
@@ -1462,6 +1463,7 @@ bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile) |
1462 | 1462 |
SubDataIO.SetPackedSizeToRead(SubHead.PackSize); |
1463 | 1463 |
SubDataIO.EnableShowProgress(false); |
1464 | 1464 |
SubDataIO.SetFiles(this,DestFile); |
1465 |
+ SubDataIO.SetTestMode(TestMode); |
|
1465 | 1466 |
SubDataIO.UnpVolume=SubHead.SplitAfter; |
1466 | 1467 |
SubDataIO.SetSubHeader(&SubHead,NULL); |
1467 | 1468 |
Unpack.SetDestSize(SubHead.UnpSize); |
... | ... |
@@ -295,10 +295,13 @@ void CommandData::ProcessSwitch(const wchar *Switch) |
295 | 295 |
if (Switch[2]=='-' && Switch[3]==0) |
296 | 296 |
GenerateArcName=0; |
297 | 297 |
else |
298 |
- { |
|
299 |
- GenerateArcName=true; |
|
300 |
- wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask)); |
|
301 |
- } |
|
298 |
+ if (toupperw(Switch[2])=='F') |
|
299 |
+ wcsncpyz(DefGenerateMask,Switch+3,ASIZE(DefGenerateMask)); |
|
300 |
+ else |
|
301 |
+ { |
|
302 |
+ GenerateArcName=true; |
|
303 |
+ wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask)); |
|
304 |
+ } |
|
302 | 305 |
break; |
303 | 306 |
#endif |
304 | 307 |
case 'I': |
... | ... |
@@ -373,11 +376,11 @@ void CommandData::ProcessSwitch(const wchar *Switch) |
373 | 373 |
default: |
374 | 374 |
if (Switch[1]=='+') |
375 | 375 |
{ |
376 |
- InclFileAttr|=GetExclAttr(Switch+2); |
|
376 |
+ InclFileAttr|=GetExclAttr(Switch+2,InclDir); |
|
377 | 377 |
InclAttrSet=true; |
378 | 378 |
} |
379 | 379 |
else |
380 |
- ExclFileAttr|=GetExclAttr(Switch+1); |
|
380 |
+ ExclFileAttr|=GetExclAttr(Switch+1,ExclDir); |
|
381 | 381 |
break; |
382 | 382 |
} |
383 | 383 |
break; |
... | ... |
@@ -825,39 +828,7 @@ void CommandData::ProcessSwitch(const wchar *Switch) |
825 | 825 |
SetTimeFilters(Switch+2,false,false); |
826 | 826 |
break; |
827 | 827 |
case 'S': |
828 |
- { |
|
829 |
- EXTTIME_MODE Mode=EXTTIME_HIGH3; |
|
830 |
- bool CommonMode=Switch[2]>='0' && Switch[2]<='4'; |
|
831 |
- if (CommonMode) |
|
832 |
- Mode=(EXTTIME_MODE)(Switch[2]-'0'); |
|
833 |
- if (Mode==EXTTIME_HIGH1 || Mode==EXTTIME_HIGH2) // '2' and '3' not supported anymore. |
|
834 |
- Mode=EXTTIME_HIGH3; |
|
835 |
- if (Switch[2]=='-') |
|
836 |
- Mode=EXTTIME_NONE; |
|
837 |
- if (CommonMode || Switch[2]=='-' || Switch[2]=='+' || Switch[2]==0) |
|
838 |
- xmtime=xctime=xatime=Mode; |
|
839 |
- else |
|
840 |
- { |
|
841 |
- if (Switch[3]>='0' && Switch[3]<='4') |
|
842 |
- Mode=(EXTTIME_MODE)(Switch[3]-'0'); |
|
843 |
- if (Mode==EXTTIME_HIGH1 || Mode==EXTTIME_HIGH2) // '2' and '3' not supported anymore. |
|
844 |
- Mode=EXTTIME_HIGH3; |
|
845 |
- if (Switch[3]=='-') |
|
846 |
- Mode=EXTTIME_NONE; |
|
847 |
- switch(toupperw(Switch[2])) |
|
848 |
- { |
|
849 |
- case 'M': |
|
850 |
- xmtime=Mode; |
|
851 |
- break; |
|
852 |
- case 'C': |
|
853 |
- xctime=Mode; |
|
854 |
- break; |
|
855 |
- case 'A': |
|
856 |
- xatime=Mode; |
|
857 |
- break; |
|
858 |
- } |
|
859 |
- } |
|
860 |
- } |
|
828 |
+ SetStoreTimeMode(Switch+2); |
|
861 | 829 |
break; |
862 | 830 |
case '-': |
863 | 831 |
Test=false; |
... | ... |
@@ -960,7 +931,10 @@ void CommandData::ProcessCommand() |
960 | 960 |
if (wcschr(L"AFUMD",*Command)==NULL) |
961 | 961 |
{ |
962 | 962 |
if (GenerateArcName) |
963 |
- GenerateArchiveName(ArcName,ASIZE(ArcName),GenerateMask,false); |
|
963 |
+ { |
|
964 |
+ const wchar *Mask=*GenerateMask!=0 ? GenerateMask:DefGenerateMask; |
|
965 |
+ GenerateArchiveName(ArcName,ASIZE(ArcName),Mask,false); |
|
966 |
+ } |
|
964 | 967 |
|
965 | 968 |
StringList ArcMasks; |
966 | 969 |
ArcMasks.AddString(ArcName); |
... | ... |
@@ -979,7 +953,6 @@ void CommandData::ProcessCommand() |
979 | 979 |
case 'X': |
980 | 980 |
case 'E': |
981 | 981 |
case 'T': |
982 |
- case 'I': |
|
983 | 982 |
{ |
984 | 983 |
CmdExtract Extract(this); |
985 | 984 |
Extract.DoExtract(); |
... | ... |
@@ -1022,7 +995,7 @@ bool CommandData::IsSwitch(int Ch) |
1022 | 1022 |
|
1023 | 1023 |
|
1024 | 1024 |
#ifndef SFX_MODULE |
1025 |
-uint CommandData::GetExclAttr(const wchar *Str) |
|
1025 |
+uint CommandData::GetExclAttr(const wchar *Str,bool &Dir) |
|
1026 | 1026 |
{ |
1027 | 1027 |
if (IsDigit(*Str)) |
1028 | 1028 |
return wcstol(Str,NULL,0); |
... | ... |
@@ -1032,10 +1005,10 @@ uint CommandData::GetExclAttr(const wchar *Str) |
1032 | 1032 |
{ |
1033 | 1033 |
switch(toupperw(*Str)) |
1034 | 1034 |
{ |
1035 |
-#ifdef _UNIX |
|
1036 | 1035 |
case 'D': |
1037 |
- Attr|=S_IFDIR; |
|
1036 |
+ Dir=true; |
|
1038 | 1037 |
break; |
1038 |
+#ifdef _UNIX |
|
1039 | 1039 |
case 'V': |
1040 | 1040 |
Attr|=S_IFCHR; |
1041 | 1041 |
break; |
... | ... |
@@ -1049,9 +1022,6 @@ uint CommandData::GetExclAttr(const wchar *Str) |
1049 | 1049 |
case 'S': |
1050 | 1050 |
Attr|=0x4; |
1051 | 1051 |
break; |
1052 |
- case 'D': |
|
1053 |
- Attr|=0x10; |
|
1054 |
- break; |
|
1055 | 1052 |
case 'A': |
1056 | 1053 |
Attr|=0x20; |
1057 | 1054 |
break; |
... | ... |
@@ -14,9 +14,10 @@ class CommandData:public RAROptions |
14 | 14 |
void ProcessSwitchesString(const wchar *Str); |
15 | 15 |
void ProcessSwitch(const wchar *Switch); |
16 | 16 |
void BadSwitch(const wchar *Switch); |
17 |
- uint GetExclAttr(const wchar *Str); |
|
17 |
+ uint GetExclAttr(const wchar *Str,bool &Dir); |
|
18 | 18 |
#if !defined(SFX_MODULE) |
19 | 19 |
void SetTimeFilters(const wchar *Mod,bool Before,bool Age); |
20 |
+ void SetStoreTimeMode(const wchar *S); |
|
20 | 21 |
#endif |
21 | 22 |
|
22 | 23 |
bool FileLists; |
... | ... |
@@ -285,7 +285,10 @@ int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchTy |
285 | 285 |
#ifndef SFX_MODULE |
286 | 286 |
if (TimeCheck(FileHead.mtime,FileHead.ctime,FileHead.atime)) |
287 | 287 |
return 0; |
288 |
- if ((FileHead.FileAttr & ExclFileAttr)!=0 || InclAttrSet && (FileHead.FileAttr & InclFileAttr)==0) |
|
288 |
+ if ((FileHead.FileAttr & ExclFileAttr)!=0 || FileHead.Dir && ExclDir) |
|
289 |
+ return 0; |
|
290 |
+ if (InclAttrSet && (!FileHead.Dir && (FileHead.FileAttr & InclFileAttr)==0 || |
|
291 |
+ FileHead.Dir && !InclDir)) |
|
289 | 292 |
return 0; |
290 | 293 |
if (!Dir && SizeCheck(FileHead.UnpSize)) |
291 | 294 |
return 0; |
... | ... |
@@ -303,3 +306,47 @@ int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchTy |
303 | 303 |
} |
304 | 304 |
return 0; |
305 | 305 |
} |
306 |
+ |
|
307 |
+ |
|
308 |
+#if !defined(SFX_MODULE) |
|
309 |
+void CommandData::SetStoreTimeMode(const wchar *S) |
|
310 |
+{ |
|
311 |
+ if (*S==0 || IsDigit(*S) || *S=='-' || *S=='+') |
|
312 |
+ { |
|
313 |
+ // Apply -ts, -ts1, -ts-, -ts+ to all 3 times. |
|
314 |
+ // Handle obsolete -ts[2,3,4] as ts+. |
|
315 |
+ EXTTIME_MODE Mode=EXTTIME_MAX; |
|
316 |
+ if (*S=='-') |
|
317 |
+ Mode=EXTTIME_NONE; |
|
318 |
+ if (*S=='1') |
|
319 |
+ Mode=EXTTIME_1S; |
|
320 |
+ xmtime=xctime=xatime=Mode; |
|
321 |
+ S++; |
|
322 |
+ } |
|
323 |
+ |
|
324 |
+ while (*S!=0) |
|
325 |
+ { |
|
326 |
+ EXTTIME_MODE Mode=EXTTIME_MAX; |
|
327 |
+ if (S[1]=='-') |
|
328 |
+ Mode=EXTTIME_NONE; |
|
329 |
+ if (S[1]=='1') |
|
330 |
+ Mode=EXTTIME_1S; |
|
331 |
+ switch(toupperw(*S)) |
|
332 |
+ { |
|
333 |
+ case 'M': |
|
334 |
+ xmtime=Mode; |
|
335 |
+ break; |
|
336 |
+ case 'C': |
|
337 |
+ xctime=Mode; |
|
338 |
+ break; |
|
339 |
+ case 'A': |
|
340 |
+ xatime=Mode; |
|
341 |
+ break; |
|
342 |
+ case 'P': |
|
343 |
+ PreserveAtime=true; |
|
344 |
+ break; |
|
345 |
+ } |
|
346 |
+ S++; |
|
347 |
+ } |
|
348 |
+} |
|
349 |
+#endif |
... | ... |
@@ -95,23 +95,23 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r) |
95 | 95 |
r->Flags=0; |
96 | 96 |
|
97 | 97 |
if (Data->Arc.Volume) |
98 |
- r->Flags|=0x01; |
|
98 |
+ r->Flags|=ROADF_VOLUME; |
|
99 | 99 |
if (Data->Arc.MainComment) |
100 |
- r->Flags|=0x02; |
|
100 |
+ r->Flags|=ROADF_COMMENT; |
|
101 | 101 |
if (Data->Arc.Locked) |
102 |
- r->Flags|=0x04; |
|
102 |
+ r->Flags|=ROADF_LOCK; |
|
103 | 103 |
if (Data->Arc.Solid) |
104 |
- r->Flags|=0x08; |
|
104 |
+ r->Flags|=ROADF_SOLID; |
|
105 | 105 |
if (Data->Arc.NewNumbering) |
106 |
- r->Flags|=0x10; |
|
106 |
+ r->Flags|=ROADF_NEWNUMBERING; |
|
107 | 107 |
if (Data->Arc.Signed) |
108 |
- r->Flags|=0x20; |
|
108 |
+ r->Flags|=ROADF_SIGNED; |
|
109 | 109 |
if (Data->Arc.Protected) |
110 |
- r->Flags|=0x40; |
|
110 |
+ r->Flags|=ROADF_RECOVERY; |
|
111 | 111 |
if (Data->Arc.Encrypted) |
112 |
- r->Flags|=0x80; |
|
112 |
+ r->Flags|=ROADF_ENCHEADERS; |
|
113 | 113 |
if (Data->Arc.FirstVolume) |
114 |
- r->Flags|=0x100; |
|
114 |
+ r->Flags|=ROADF_FIRSTVOLUME; |
|
115 | 115 |
|
116 | 116 |
Array<wchar> CmtDataW; |
117 | 117 |
if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW)) |
... | ... |
@@ -2,8 +2,8 @@ |
2 | 2 |
#include <commctrl.h> |
3 | 3 |
|
4 | 4 |
VS_VERSION_INFO VERSIONINFO |
5 |
-FILEVERSION 5, 71, 100, 3045 |
|
6 |
-PRODUCTVERSION 5, 71, 100, 3045 |
|
5 |
+FILEVERSION 5, 90, 100, 3379 |
|
6 |
+PRODUCTVERSION 5, 90, 100, 3379 |
|
7 | 7 |
FILEOS VOS__WINDOWS32 |
8 | 8 |
FILETYPE VFT_APP |
9 | 9 |
{ |
... | ... |
@@ -14,9 +14,9 @@ FILETYPE VFT_APP |
14 | 14 |
VALUE "CompanyName", "Alexander Roshal\0" |
15 | 15 |
VALUE "ProductName", "RAR decompression library\0" |
16 | 16 |
VALUE "FileDescription", "RAR decompression library\0" |
17 |
- VALUE "FileVersion", "5.71.0\0" |
|
18 |
- VALUE "ProductVersion", "5.71.0\0" |
|
19 | ||
17 |
+ VALUE "FileVersion", "5.90.0\0" |
|
18 |
+ VALUE "ProductVersion", "5.90.0\0" |
|
19 | ||
20 | 20 |
VALUE "OriginalFilename", "Unrar.dll\0" |
21 | 21 |
} |
22 | 22 |
} |
... | ... |
@@ -158,6 +158,7 @@ void ErrorHandler::OpenErrorMsg(const wchar *FileName) |
158 | 158 |
|
159 | 159 |
void ErrorHandler::OpenErrorMsg(const wchar *ArcName,const wchar *FileName) |
160 | 160 |
{ |
161 |
+ Wait(); // Keep GUI responsive if many files cannot be opened when archiving. |
|
161 | 162 |
uiMsg(UIERROR_FILEOPEN,ArcName,FileName); |
162 | 163 |
SysErrMsg(); |
163 | 164 |
SetErrorCode(RARX_OPEN); |
... | ... |
@@ -328,7 +329,7 @@ void ErrorHandler::Throw(RAR_EXIT Code) |
328 | 328 |
|
329 | 329 |
bool ErrorHandler::GetSysErrMsg(wchar *Msg,size_t Size) |
330 | 330 |
{ |
331 |
-#if !defined(SFX_MODULE) && !defined(SILENT) |
|
331 |
+#ifndef SILENT |
|
332 | 332 |
#ifdef _WIN_ALL |
333 | 333 |
int ErrType=GetLastError(); |
334 | 334 |
if (ErrType!=0) |
... | ... |
@@ -361,7 +362,7 @@ void ErrorHandler::SysErrMsg() |
361 | 361 |
return; |
362 | 362 |
#ifdef _WIN_ALL |
363 | 363 |
wchar *CurMsg=Msg; |
364 |
- while (CurMsg!=NULL) |
|
364 |
+ while (CurMsg!=NULL) // Print string with \r\n as several strings to multiple lines. |
|
365 | 365 |
{ |
366 | 366 |
while (*CurMsg=='\r' || *CurMsg=='\n') |
367 | 367 |
CurMsg++; |
... | ... |
@@ -40,6 +40,8 @@ void CmdExtract::DoExtract() |
40 | 40 |
{ |
41 | 41 |
if (Cmd->ManualPassword) |
42 | 42 |
Cmd->Password.Clean(); // Clean user entered password before processing next archive. |
43 |
+ |
|
44 |
+ ReconstructDone=false; // Must be reset here, not in ExtractArchiveInit(). |
|
43 | 45 |
while (true) |
44 | 46 |
{ |
45 | 47 |
EXTRACT_ARC_CODE Code=ExtractArchive(); |
... | ... |
@@ -93,7 +95,6 @@ void CmdExtract::ExtractArchiveInit(Archive &Arc) |
93 | 93 |
|
94 | 94 |
PrevProcessed=false; |
95 | 95 |
AllMatchesExact=true; |
96 |
- ReconstructDone=false; |
|
97 | 96 |
AnySolidDataUnpackedWell=false; |
98 | 97 |
|
99 | 98 |
StartTime.SetCurrentTime(); |
... | ... |
@@ -479,13 +480,13 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) |
479 | 479 |
{ |
480 | 480 |
// This message is used by Android GUI to reset cached passwords. |
481 | 481 |
// Update appropriate code if changed. |
482 |
- uiMsg(UIERROR_BADPSW,ArcFileName); |
|
482 |
+ uiMsg(UIERROR_BADPSW,Arc.FileName,ArcFileName); |
|
483 | 483 |
} |
484 | 484 |
else // For passwords entered manually. |
485 | 485 |
{ |
486 | 486 |
// This message is used by Android GUI and Windows GUI and SFX to |
487 | 487 |
// reset cached passwords. Update appropriate code if changed. |
488 |
- uiMsg(UIWAIT_BADPSW,ArcFileName); |
|
488 |
+ uiMsg(UIWAIT_BADPSW,Arc.FileName,ArcFileName); |
|
489 | 489 |
Cmd->Password.Clean(); |
490 | 490 |
|
491 | 491 |
// Avoid new requests for unrar.dll to prevent the infinite loop |
... | ... |
@@ -624,7 +625,6 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) |
624 | 624 |
CurFile.Prealloc(Arc.FileHead.UnpSize); |
625 | 625 |
Preallocated=Arc.FileHead.UnpSize; |
626 | 626 |
} |
627 |
- |
|
628 | 627 |
CurFile.SetAllowDelete(!Cmd->KeepBroken); |
629 | 628 |
|
630 | 629 |
bool FileCreateMode=!TestMode && !SkipSolid && Command!='P'; |
... | ... |
@@ -736,38 +736,52 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) |
736 | 736 |
else |
737 | 737 |
mprintf(L"\b\b\b\b\b "); |
738 | 738 |
|
739 |
+ // If we successfully unpacked a hard link, we wish to set its file |
|
740 |
+ // attributes. Hard link shares file metadata with link target, |
|
741 |
+ // so we do not need to set link time or owner. But when we overwrite |
|
742 |
+ // an existing link, we can call PrepareToDelete(), which affects |
|
743 |
+ // link target attributes as well. So we set link attributes to restore |
|
744 |
+ // both target and link attributes if PrepareToDelete() changed them. |
|
745 |
+ bool SetAttrOnly=LinkEntry && Arc.FileHead.RedirType==FSREDIR_HARDLINK && LinkSuccess; |
|
746 |
+ |
|
739 | 747 |
if (!TestMode && (Command=='X' || Command=='E') && |
740 |
- (!LinkEntry || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) && |
|
748 |
+ (!LinkEntry || SetAttrOnly || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) && |
|
741 | 749 |
(!BrokenFile || Cmd->KeepBroken)) |
742 | 750 |
{ |
743 |
- // We could preallocate more space that really written to broken file |
|
744 |
- // or file with crafted header. |
|
745 |
- if (Preallocated>0 && (BrokenFile || DataIO.CurUnpWrite!=Preallocated)) |
|
746 |
- CurFile.Truncate(); |
|
751 |
+ // Below we use DestFileName instead of CurFile.FileName, |
|
752 |
+ // so we can set file attributes also for hard links, which do not |
|
753 |
+ // have the open CurFile. These strings are the same for other items. |
|
747 | 754 |
|
748 |
-#if defined(_WIN_ALL) || defined(_EMX) |
|
749 |
- if (Cmd->ClearArc) |
|
750 |
- Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE; |
|
751 |
-#endif |
|
755 |
+ if (!SetAttrOnly) |
|
756 |
+ { |
|
757 |
+ // We could preallocate more space that really written to broken file |
|
758 |
+ // or file with crafted header. |
|
759 |
+ if (Preallocated>0 && (BrokenFile || DataIO.CurUnpWrite!=Preallocated)) |
|
760 |
+ CurFile.Truncate(); |
|
752 | 761 |
|
753 | 762 |
|
754 |
- CurFile.SetOpenFileTime( |
|
755 |
- Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime, |
|
756 |
- Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime, |
|
757 |
- Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime); |
|
758 |
- CurFile.Close(); |
|
763 |
+ CurFile.SetOpenFileTime( |
|
764 |
+ Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime, |
|
765 |
+ Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime, |
|
766 |
+ Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime); |
|
767 |
+ CurFile.Close(); |
|
768 |
+ |
|
769 |
+ SetFileHeaderExtra(Cmd,Arc,DestFileName); |
|
770 |
+ |
|
771 |
+ CurFile.SetCloseFileTime( |
|
772 |
+ Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime, |
|
773 |
+ Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime); |
|
774 |
+ } |
|
775 |
+ |
|
759 | 776 |
#if defined(_WIN_ALL) && !defined(SFX_MODULE) |
760 | 777 |
if (Cmd->SetCompressedAttr && |
761 | 778 |
(Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0) |
762 |
- SetFileCompression(CurFile.FileName,true); |
|
779 |
+ SetFileCompression(DestFileName,true); |
|
780 |
+ if (Cmd->ClearArc) |
|
781 |
+ Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE; |
|
763 | 782 |
#endif |
764 |
- SetFileHeaderExtra(Cmd,Arc,CurFile.FileName); |
|
765 |
- |
|
766 |
- CurFile.SetCloseFileTime( |
|
767 |
- Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime, |
|
768 |
- Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime); |
|
769 |
- if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(CurFile.FileName,Arc.FileHead.FileAttr)) |
|
770 |
- uiMsg(UIERROR_FILEATTR,Arc.FileName,CurFile.FileName); |
|
783 |
+ if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(DestFileName,Arc.FileHead.FileAttr)) |
|
784 |
+ uiMsg(UIERROR_FILEATTR,Arc.FileName,DestFileName); |
|
771 | 785 |
|
772 | 786 |
PrevProcessed=true; |
773 | 787 |
} |
... | ... |
@@ -13,6 +13,7 @@ File::File() |
13 | 13 |
OpenShared=false; |
14 | 14 |
AllowDelete=true; |
15 | 15 |
AllowExceptions=true; |
16 |
+ PreserveAtime=false; |
|
16 | 17 |
#ifdef _WIN_ALL |
17 | 18 |
NoSequentialRead=false; |
18 | 19 |
CreateMode=FMF_UNDEFINED; |
... | ... |
@@ -56,6 +57,9 @@ bool File::Open(const wchar *Name,uint Mode) |
56 | 56 |
if (OpenShared) |
57 | 57 |
ShareMode|=FILE_SHARE_WRITE; |
58 | 58 |
uint Flags=NoSequentialRead ? 0:FILE_FLAG_SEQUENTIAL_SCAN; |
59 |
+ FindData FD; |
|
60 |
+ if (PreserveAtime) |
|
61 |
+ Access|=FILE_WRITE_ATTRIBUTES; // Needed to preserve atime. |
|
59 | 62 |
hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL); |
60 | 63 |
|
61 | 64 |
DWORD LastError; |
... | ... |
@@ -86,6 +90,11 @@ bool File::Open(const wchar *Name,uint Mode) |
86 | 86 |
} |
87 | 87 |
if (hNewFile==FILE_BAD_HANDLE && LastError==ERROR_FILE_NOT_FOUND) |
88 | 88 |
ErrorType=FILE_NOTFOUND; |
89 |
+ if (PreserveAtime && hNewFile!=FILE_BAD_HANDLE) |
|
90 |
+ { |
|
91 |
+ FILETIME ft={0xffffffff,0xffffffff}; // This value prevents atime modification. |
|
92 |
+ SetFileTime(hNewFile,NULL,&ft,NULL); |
|
93 |
+ } |
|
89 | 94 |
|
90 | 95 |
#else |
91 | 96 |
int flags=UpdateMode ? O_RDWR:(WriteMode ? O_WRONLY:O_RDONLY); |
... | ... |
@@ -95,6 +104,11 @@ bool File::Open(const wchar *Name,uint Mode) |
95 | 95 |
flags|=O_LARGEFILE; |
96 | 96 |
#endif |
97 | 97 |
#endif |
98 |
+ // NDK r20 has O_NOATIME, but fails to create files with it in Android 7+. |
|
99 |
+#if defined(O_NOATIME) |
|
100 |
+ if (PreserveAtime) |
|
101 |
+ flags|=O_NOATIME; |
|
102 |
+#endif |
|
98 | 103 |
char NameA[NM]; |
99 | 104 |
WideToChar(Name,NameA,ASIZE(NameA)); |
100 | 105 |
|
... | ... |
@@ -230,7 +244,7 @@ bool File::Close() |
230 | 230 |
{ |
231 | 231 |
#ifdef _WIN_ALL |
232 | 232 |
// We use the standard system handle for stdout in Windows |
233 |
- // and it must not be closed here. |
|
233 |
+ // and it must not be closed here. |
|
234 | 234 |
if (HandleType==FILE_HANDLENORMAL) |
235 | 235 |
Success=CloseHandle(hFile)==TRUE; |
236 | 236 |
#else |
... | ... |
@@ -387,7 +401,7 @@ int File::Read(void *Data,size_t Size) |
387 | 387 |
} |
388 | 388 |
break; |
389 | 389 |
} |
390 |
- return ReadSize; |
|
390 |
+ return ReadSize; // It can return -1 only if AllowExceptions is disabled. |
|
391 | 391 |
} |
392 | 392 |
|
393 | 393 |
|
... | ... |
@@ -670,9 +684,11 @@ void File::GetOpenFileTime(RarTime *ft) |
670 | 670 |
|
671 | 671 |
int64 File::FileLength() |
672 | 672 |
{ |
673 |
- SaveFilePos SavePos(*this); |
|
673 |
+ int64 SavePos=Tell(); |
|
674 | 674 |
Seek(0,SEEK_END); |
675 |
- return Tell(); |
|
675 |
+ int64 Length=Tell(); |
|
676 |
+ Seek(SavePos,SEEK_SET); |
|
677 |
+ return Length; |
|
676 | 678 |
} |
677 | 679 |
|
678 | 680 |
|
... | ... |
@@ -62,6 +62,7 @@ class File |
62 | 62 |
bool NoSequentialRead; |
63 | 63 |
uint CreateMode; |
64 | 64 |
#endif |
65 |
+ bool PreserveAtime; |
|
65 | 66 |
protected: |
66 | 67 |
bool OpenShared; // Set by 'Archive' class. |
67 | 68 |
public: |
... | ... |
@@ -114,6 +115,7 @@ class File |
114 | 114 |
#ifdef _WIN_ALL |
115 | 115 |
void RemoveSequentialFlag() {NoSequentialRead=true;} |
116 | 116 |
#endif |
117 |
+ void SetPreserveAtime(bool Preserve) {PreserveAtime=Preserve;} |
|
117 | 118 |
#ifdef _UNIX |
118 | 119 |
int GetFD() |
119 | 120 |
{ |
... | ... |
@@ -360,7 +360,7 @@ wchar *MkTemp(wchar *Name,size_t MaxSize) |
360 | 360 |
#if !defined(SFX_MODULE) |
361 | 361 |
void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags) |
362 | 362 |
{ |
363 |
- SaveFilePos SavePos(*SrcFile); |
|
363 |
+ int64 SavePos=SrcFile->Tell(); |
|
364 | 364 |
#ifndef SILENT |
365 | 365 |
int64 FileLength=Size==INT64NDF ? SrcFile->FileLength() : Size; |
366 | 366 |
#endif |
... | ... |
@@ -415,6 +415,8 @@ void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size, |
415 | 415 |
if (Size!=INT64NDF) |
416 | 416 |
Size-=ReadSize; |
417 | 417 |
} |
418 |
+ SrcFile->Seek(SavePos,SEEK_SET); |
|
419 |
+ |
|
418 | 420 |
if ((Flags & CALCFSUM_SHOWPERCENT)!=0) |
419 | 421 |
uiMsg(UIEVENT_FILESUMEND); |
420 | 422 |
|
... | ... |
@@ -63,12 +63,12 @@ bool FindFile::Next(FindData *fd,bool GetSymLink) |
63 | 63 |
} |
64 | 64 |
while (1) |
65 | 65 |
{ |
66 |
+ wchar Name[NM]; |
|
66 | 67 |
struct dirent *ent=readdir(dirp); |
67 | 68 |
if (ent==NULL) |
68 | 69 |
return false; |
69 | 70 |
if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0) |
70 | 71 |
continue; |
71 |
- wchar Name[NM]; |
|
72 | 72 |
if (!CharToWide(ent->d_name,Name,ASIZE(Name))) |
73 | 73 |
uiMsg(UIERROR_INVALIDNAME,UINULL,Name); |
74 | 74 |
|
... | ... |
@@ -53,7 +53,7 @@ DataHash::DataHash() |
53 | 53 |
DataHash::~DataHash() |
54 | 54 |
{ |
55 | 55 |
#ifdef RAR_SMP |
56 |
- DestroyThreadPool(ThPool); |
|
56 |
+ delete ThPool; |
|
57 | 57 |
#endif |
58 | 58 |
cleandata(&CurCRC32, sizeof(CurCRC32)); |
59 | 59 |
if (blake2ctx!=NULL) |
... | ... |
@@ -94,7 +94,7 @@ void DataHash::Update(const void *Data,size_t DataSize) |
94 | 94 |
{ |
95 | 95 |
#ifdef RAR_SMP |
96 | 96 |
if (MaxThreads>1 && ThPool==NULL) |
97 |
- ThPool=CreateThreadPool(); |
|
97 |
+ ThPool=new ThreadPool(BLAKE2_THREADS_NUMBER); |
|
98 | 98 |
blake2ctx->ThPool=ThPool; |
99 | 99 |
blake2ctx->MaxThreads=MaxThreads; |
100 | 100 |
#endif |
... | ... |
@@ -345,7 +345,7 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo |
345 | 345 |
mprintf(L"\n%12ls: %ls",St(MListHostOS),HostOS); |
346 | 346 |
|
347 | 347 |
mprintf(L"\n%12ls: RAR %ls(v%d) -m%d -md=%d%s",St(MListCompInfo), |
348 |
- Format==RARFMT15 ? L"3.0":L"5.0", |
|
348 |
+ Format==RARFMT15 ? L"1.5":L"5.0", |
|
349 | 349 |
hd.UnpVer==VER_UNKNOWN ? 0 : hd.UnpVer,hd.Method, |
350 | 350 |
hd.WinSize>=0x100000 ? hd.WinSize/0x100000:hd.WinSize/0x400, |
351 | 351 |
hd.WinSize>=0x100000 ? L"M":L"K"); |
... | ... |
@@ -131,7 +131,7 @@ |
131 | 131 |
#define MCHelpSwTO L"\n to[mcao]<t> Process files older than <t> time" |
132 | 132 |
#define MCHelpSwTA L"\n ta[mcao]<d> Process files modified after <d> YYYYMMDDHHMMSS date" |
133 | 133 |
#define MCHelpSwTB L"\n tb[mcao]<d> Process files modified before <d> YYYYMMDDHHMMSS date" |
134 |
-#define MCHelpSwTS L"\n ts[m,c,a] Save or restore file time (modification, creation, access)" |
|
134 |
+#define MCHelpSwTS L"\n ts[m,c,a,p] Save or restore time (modification, creation, access, preserve)" |
|
135 | 135 |
#define MCHelpSwU L"\n u Update files" |
136 | 136 |
#define MCHelpSwV L"\n v Create volumes with size autodetection or list all volumes" |
137 | 137 |
#define MCHelpSwVUnr L"\n v List all volumes" |
... | ... |
@@ -203,7 +203,6 @@ |
203 | 203 |
#define MErrOpenFile L"file" |
204 | 204 |
#define MAddNoFiles L"\nWARNING: No files" |
205 | 205 |
#define MMdfEncrSol L"\n%s: encrypted" |
206 |
-#define MCannotMdfEncrSol L"\nCannot modify solid archive containing encrypted files" |
|
207 | 206 |
#define MAddAnalyze L"\nAnalyzing archived files: " |
208 | 207 |
#define MRepacking L"\nRepacking archived files: " |
209 | 208 |
#define MCRCFailed L"\n%-20s - checksum error" |
... | ... |
@@ -342,7 +341,7 @@ |
342 | 342 |
#define MFAT32Size L"\nWARNING: FAT32 file system does not support 4 GB or larger files" |
343 | 343 |
#define MErrChangeAttr L"\nWARNING: Cannot change attributes of %s" |
344 | 344 |
#define MWrongSFXVer L"\nERROR: default SFX module does not support RAR %d.%d archives" |
345 |
-#define MCannotEncName L"\nCannot encrypt archive already containing encrypted files" |
|
345 |
+#define MHeadEncMismatch L"\nCannot change the header encryption mode in already encrypted archive" |
|
346 | 346 |
#define MCannotEmail L"\nCannot email the file %s" |
347 | 347 |
#define MCopyrightS L"\nRAR SFX archive" |
348 | 348 |
#define MSHelpCmd L"\n\n<Commands>" |
... | ... |
@@ -360,6 +359,7 @@ |
360 | 360 |
#define MNewerRAR L"\nYou may need a newer version of RAR." |
361 | 361 |
#define MUnkEncMethod L"\nUnknown encryption method in %s" |
362 | 362 |
#define MWrongPassword L"\nThe specified password is incorrect." |
363 |
+#define MWrongFilePassword L"\nIncorrect password for %s" |
|
363 | 364 |
#define MAreaDamaged L"\nCorrupt %d bytes at %08x %08x" |
364 | 365 |
#define MBlocksRecovered L"\n%u blocks are recovered, %u blocks are relocated" |
365 | 366 |
#define MRRDamaged L"\nRecovery record is corrupt." |
... | ... |
@@ -379,3 +379,4 @@ |
379 | 379 |
#define MNeedAdmin L"\nYou may need to run RAR as administrator" |
380 | 380 |
#define MDictOutMem L"\nNot enough memory for %d MB compression dictionary, changed to %d MB." |
381 | 381 |
#define MUseSmalllerDict L"\nPlease use a smaller compression dictionary." |
382 |
+#define MOpenErrAtime L"\nYou may need to remove -tsp switch to open this file." |
... | ... |
@@ -21,7 +21,7 @@ enum {SOLID_NONE=0,SOLID_NORMAL=1,SOLID_COUNT=2,SOLID_FILEEXT=4, |
21 | 21 |
enum {ARCTIME_NONE=0,ARCTIME_KEEP,ARCTIME_LATEST}; |
22 | 22 |
|
23 | 23 |
enum EXTTIME_MODE { |
24 |
- EXTTIME_NONE=0,EXTTIME_1S,EXTTIME_HIGH1,EXTTIME_HIGH2,EXTTIME_HIGH3 |
|
24 |
+ EXTTIME_NONE=0,EXTTIME_1S,EXTTIME_MAX |
|
25 | 25 |
}; |
26 | 26 |
|
27 | 27 |
enum {NAMES_ORIGINALCASE=0,NAMES_UPPERCASE,NAMES_LOWERCASE}; |
... | ... |
@@ -92,6 +92,12 @@ class RAROptions |
92 | 92 |
|
93 | 93 |
uint ExclFileAttr; |
94 | 94 |
uint InclFileAttr; |
95 |
+ |
|
96 |
+ // We handle -ed and -e+d with special flags instead of attribute mask, |
|
97 |
+ // so it works with both Windows and Unix archives. |
|
98 |
+ bool ExclDir; |
|
99 |
+ bool InclDir; |
|
100 |
+ |
|
95 | 101 |
bool InclAttrSet; |
96 | 102 |
size_t WinSize; |
97 | 103 |
wchar TempPath[NM]; |
... | ... |
@@ -162,6 +168,7 @@ class RAROptions |
162 | 162 |
#ifndef SFX_MODULE |
163 | 163 |
bool GenerateArcName; |
164 | 164 |
wchar GenerateMask[MAX_GENERATE_MASK]; |
165 |
+ wchar DefGenerateMask[MAX_GENERATE_MASK]; |
|
165 | 166 |
#endif |
166 | 167 |
bool SyncFiles; |
167 | 168 |
bool ProcessEA; |
... | ... |
@@ -185,6 +192,7 @@ class RAROptions |
185 | 185 |
EXTTIME_MODE xmtime; // Extended time modes (time precision to store). |
186 | 186 |
EXTTIME_MODE xctime; |
187 | 187 |
EXTTIME_MODE xatime; |
188 |
+ bool PreserveAtime; |
|
188 | 189 |
wchar CompressStdin[NM]; |
189 | 190 |
|
190 | 191 |
uint Threads; // We use it to init hash even if RAR_SMP is not defined. |
... | ... |
@@ -170,14 +170,17 @@ int GetPathDisk(const wchar *Path) |
170 | 170 |
void AddEndSlash(wchar *Path,size_t MaxLength) |
171 | 171 |
{ |
172 | 172 |
size_t Length=wcslen(Path); |
173 |
- if (Length>0 && Path[Length-1]!=CPATHDIVIDER) |
|
174 |
- wcsncatz(Path,SPATHDIVIDER,MaxLength); |
|
173 |
+ if (Length>0 && Path[Length-1]!=CPATHDIVIDER && Length+1<MaxLength) |
|
174 |
+ { |
|
175 |
+ Path[Length]=CPATHDIVIDER; |
|
176 |
+ Path[Length+1]=0; |
|
177 |
+ } |
|
175 | 178 |
} |
176 | 179 |
|
177 | 180 |
|
178 | 181 |
void MakeName(const wchar *Path,const wchar *Name,wchar *Pathname,size_t MaxSize) |
179 | 182 |
{ |
180 |
- // 'Name' and 'Pathname' can point to same memory area. This is why we use |
|
183 |
+ // 'Path', 'Name' and 'Pathname' can point to same memory area. So we use |
|
181 | 184 |
// the temporary buffer instead of constructing the name in 'Pathname'. |
182 | 185 |
wchar OutName[NM]; |
183 | 186 |
wcsncpyz(OutName,Path,ASIZE(OutName)); |
... | ... |
@@ -67,7 +67,7 @@ void QuickOpen::Load(uint64 BlockPos) |
67 | 67 |
SeekPos=Arc->Tell(); |
68 | 68 |
UnsyncSeekPos=false; |
69 | 69 |
|
70 |
- SaveFilePos SavePos(*Arc); |
|
70 |
+ int64 SavePos=SeekPos; |
|
71 | 71 |
Arc->Seek(BlockPos,SEEK_SET); |
72 | 72 |
|
73 | 73 |
// If BlockPos points to original main header, we'll have the infinite |
... | ... |
@@ -83,10 +83,14 @@ void QuickOpen::Load(uint64 BlockPos) |
83 | 83 |
|
84 | 84 |
if (ReadSize==0 || Arc->GetHeaderType()!=HEAD_SERVICE || |
85 | 85 |
!Arc->SubHead.CmpName(SUBHEAD_TYPE_QOPEN)) |
86 |
+ { |
|
87 |
+ Arc->Seek(SavePos,SEEK_SET); |
|
86 | 88 |
return; |
89 |
+ } |
|
87 | 90 |
QOHeaderPos=Arc->CurBlockPos; |
88 | 91 |
RawDataStart=Arc->Tell(); |
89 | 92 |
RawDataSize=Arc->SubHead.UnpSize; |
93 |
+ Arc->Seek(SavePos,SEEK_SET); |
|
90 | 94 |
|
91 | 95 |
Loaded=true; // Set only after all file processing calls like Tell, Seek, ReadHeader. |
92 | 96 |
} |
... | ... |
@@ -201,22 +205,28 @@ bool QuickOpen::Tell(int64 *Pos) |
201 | 201 |
|
202 | 202 |
uint QuickOpen::ReadBuffer() |
203 | 203 |
{ |
204 |
- SaveFilePos SavePos(*Arc); |
|
204 |
+ int64 SavePos=Arc->Tell(); |
|
205 | 205 |
Arc->File::Seek(RawDataStart+RawDataPos,SEEK_SET); |
206 | 206 |
size_t SizeToRead=(size_t)Min(RawDataSize-RawDataPos,MaxBufSize-ReadBufSize); |
207 | 207 |
if (Arc->SubHead.Encrypted) |
208 | 208 |
SizeToRead &= ~CRYPT_BLOCK_MASK; |
209 |
- if (SizeToRead==0) |
|
210 |
- return 0; |
|
211 |
- int ReadSize=Arc->File::Read(Buf+ReadBufSize,SizeToRead); |
|
212 |
- if (ReadSize<=0) |
|
213 |
- return 0; |
|
209 |
+ int ReadSize=0; |
|
210 |
+ if (SizeToRead!=0) |
|
211 |
+ { |
|
212 |
+ ReadSize=Arc->File::Read(Buf+ReadBufSize,SizeToRead); |
|
213 |
+ if (ReadSize<=0) |
|
214 |
+ ReadSize=0; |
|
215 |
+ else |
|
216 |
+ { |
|
214 | 217 |
#ifndef RAR_NOCRYPT |
215 |
- if (Arc->SubHead.Encrypted) |
|
216 |
- Crypt.DecryptBlock(Buf+ReadBufSize,ReadSize & ~CRYPT_BLOCK_MASK); |
|
218 |
+ if (Arc->SubHead.Encrypted) |
|
219 |
+ Crypt.DecryptBlock(Buf+ReadBufSize,ReadSize & ~CRYPT_BLOCK_MASK); |
|
217 | 220 |
#endif |
218 |
- RawDataPos+=ReadSize; |
|
219 |
- ReadBufSize+=ReadSize; |
|
221 |
+ RawDataPos+=ReadSize; |
|
222 |
+ ReadBufSize+=ReadSize; |
|
223 |
+ } |
|
224 |
+ } |
|
225 |
+ Arc->Seek(SavePos,SEEK_SET); |
|
220 | 226 |
return ReadSize; |
221 | 227 |
} |
222 | 228 |
|
... | ... |
@@ -39,7 +39,6 @@ |
39 | 39 |
#include "filestr.hpp" |
40 | 40 |
#include "find.hpp" |
41 | 41 |
#include "scantree.hpp" |
42 |
-#include "savepos.hpp" |
|
43 | 42 |
#include "getbits.hpp" |
44 | 43 |
#include "rdwrfn.hpp" |
45 | 44 |
#ifdef USE_QOPEN |
... | ... |
@@ -77,6 +76,9 @@ |
77 | 77 |
|
78 | 78 |
#include "rs.hpp" |
79 | 79 |
#include "rs16.hpp" |
80 |
+ |
|
81 |
+ |
|
82 |
+ |
|
80 | 83 |
#include "recvol.hpp" |
81 | 84 |
#include "volume.hpp" |
82 | 85 |
#include "smallfn.hpp" |
... | ... |
@@ -21,15 +21,12 @@ typedef wchar_t wchar; // Unicode character |
21 | 21 |
// Maximum int64 value. |
22 | 22 |
#define MAX_INT64 int64(INT32TO64(0x7fffffff,0xffffffff)) |
23 | 23 |
|
24 |
-// Special int64 value, large enough to never be found in real life. |
|
24 |
+// Special int64 value, large enough to never be found in real life |
|
25 |
+// and small enough to fit to both signed and unsigned 64-bit ints. |
|
25 | 26 |
// We use it in situations, when we need to indicate that parameter |
26 | 27 |
// is not defined and probably should be calculated inside of function. |
27 | 28 |
// Lower part is intentionally 0x7fffffff, not 0xffffffff, to make it |
28 |
-// compatible with 32 bit int64. |
|
29 |
+// compatible with 32 bit int64 if 64 bit type is not supported. |
|
29 | 30 |
#define INT64NDF INT32TO64(0x7fffffff,0x7fffffff) |
30 | 31 |
|
31 |
-// Maximum uint64 value. |
|
32 |
-#define MAX_UINT64 INT32TO64(0xffffffff,0xffffffff) |
|
33 |
-#define UINT64NDF MAX_UINT64 |
|
34 |
- |
|
35 | 32 |
#endif |
... | ... |
@@ -31,12 +31,12 @@ bool RecVolumesRestore(RAROptions *Cmd,const wchar *Name,bool Silent) |
31 | 31 |
// handling exceptions. So it can close and delete files on Cancel. |
32 | 32 |
if (Fmt==RARFMT15) |
33 | 33 |
{ |
34 |
- RecVolumes3 RecVol(false); |
|
34 |
+ RecVolumes3 RecVol(Cmd,false); |
|
35 | 35 |
return RecVol.Restore(Cmd,Name,Silent); |
36 | 36 |
} |
37 | 37 |
else |
38 | 38 |
{ |
39 |
- RecVolumes5 RecVol(false); |
|
39 |
+ RecVolumes5 RecVol(Cmd,false); |
|
40 | 40 |
return RecVol.Restore(Cmd,Name,Silent); |
41 | 41 |
} |
42 | 42 |
} |
... | ... |
@@ -100,12 +100,12 @@ void RecVolumesTest(RAROptions *Cmd,Archive *Arc,const wchar *Name) |
100 | 100 |
RevFile.Close(); |
101 | 101 |
if (Rev5) |
102 | 102 |
{ |
103 |
- RecVolumes5 RecVol(true); |
|
103 |
+ RecVolumes5 RecVol(Cmd,true); |
|
104 | 104 |
RecVol.Test(Cmd,Name); |
105 | 105 |
} |
106 | 106 |
else |
107 | 107 |
{ |
108 |
- RecVolumes3 RecVol(true); |
|
108 |
+ RecVolumes3 RecVol(Cmd,true); |
|
109 | 109 |
RecVol.Test(Cmd,Name); |
110 | 110 |
} |
111 | 111 |
} |
... | ... |
@@ -14,7 +14,7 @@ class RecVolumes3 |
14 | 14 |
ThreadPool *RSThreadPool; |
15 | 15 |
#endif |
16 | 16 |
public: |
17 |
- RecVolumes3(bool TestOnly); |
|
17 |
+ RecVolumes3(RAROptions *Cmd,bool TestOnly); |
|
18 | 18 |
~RecVolumes3(); |
19 | 19 |
void Make(RAROptions *Cmd,wchar *ArcName); |
20 | 20 |
bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent); |
... | ... |
@@ -71,11 +71,12 @@ class RecVolumes5 |
71 | 71 |
#ifdef RAR_SMP |
72 | 72 |
ThreadPool *RecThreadPool; |
73 | 73 |
#endif |
74 |
- RecRSThreadData ThreadData[MaxPoolThreads]; // Store thread parameters. |
|
74 |
+ uint MaxUserThreads; // Maximum number of threads defined by user. |
|
75 |
+ RecRSThreadData *ThreadData; // Array to store thread parameters. |
|
75 | 76 |
public: // 'public' only because called from thread functions. |
76 | 77 |
void ProcessAreaRS(RecRSThreadData *td); |
77 | 78 |
public: |
78 |
- RecVolumes5(bool TestOnly); |
|
79 |
+ RecVolumes5(RAROptions *Cmd,bool TestOnly); |
|
79 | 80 |
~RecVolumes5(); |
80 | 81 |
bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent); |
81 | 82 |
void Test(RAROptions *Cmd,const wchar *Name); |
... | ... |
@@ -36,7 +36,7 @@ THREAD_PROC(RSDecodeThread) |
36 | 36 |
} |
37 | 37 |
#endif |
38 | 38 |
|
39 |
-RecVolumes3::RecVolumes3(bool TestOnly) |
|
39 |
+RecVolumes3::RecVolumes3(RAROptions *Cmd,bool TestOnly) |
|
40 | 40 |
{ |
41 | 41 |
memset(SrcFile,0,sizeof(SrcFile)); |
42 | 42 |
if (TestOnly) |
... | ... |
@@ -50,7 +50,7 @@ RecVolumes3::RecVolumes3(bool TestOnly) |
50 | 50 |
Buf.Alloc(TotalBufferSize); |
51 | 51 |
memset(SrcFile,0,sizeof(SrcFile)); |
52 | 52 |
#ifdef RAR_SMP |
53 |
- RSThreadPool=CreateThreadPool(); |
|
53 |
+ RSThreadPool=new ThreadPool(Cmd->Threads); |
|
54 | 54 |
#endif |
55 | 55 |
} |
56 | 56 |
} |
... | ... |
@@ -61,7 +61,7 @@ RecVolumes3::~RecVolumes3() |
61 | 61 |
for (size_t I=0;I<ASIZE(SrcFile);I++) |
62 | 62 |
delete SrcFile[I]; |
63 | 63 |
#ifdef RAR_SMP |
64 |
- DestroyThreadPool(RSThreadPool); |
|
64 |
+ delete RSThreadPool; |
|
65 | 65 |
#endif |
66 | 66 |
} |
67 | 67 |
|
... | ... |
@@ -363,11 +363,10 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent) |
363 | 363 |
|
364 | 364 |
#ifdef RAR_SMP |
365 | 365 |
uint ThreadNumber=Cmd->Threads; |
366 |
- RSEncode rse[MaxPoolThreads]; |
|
367 | 366 |
#else |
368 | 367 |
uint ThreadNumber=1; |
369 |
- RSEncode rse[1]; |
|
370 | 368 |
#endif |
369 |
+ RSEncode *rse=new RSEncode[ThreadNumber]; |
|
371 | 370 |
for (uint I=0;I<ThreadNumber;I++) |
372 | 371 |
rse[I].Init(RecVolNumber); |
373 | 372 |
|
... | ... |
@@ -438,6 +437,8 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent) |
438 | 438 |
if (WriteFlags[I]) |
439 | 439 |
SrcFile[I]->Write(&Buf[I*RecBufferSize],MaxRead); |
440 | 440 |
} |
441 |
+ delete[] rse; |
|
442 |
+ |
|
441 | 443 |
for (int I=0;I<RecVolNumber+FileNumber;I++) |
442 | 444 |
if (SrcFile[I]!=NULL) |
443 | 445 |
{ |
... | ... |
@@ -1,6 +1,6 @@ |
1 | 1 |
static const uint MaxVolumes=65535; |
2 | 2 |
|
3 |
-RecVolumes5::RecVolumes5(bool TestOnly) |
|
3 |
+RecVolumes5::RecVolumes5(RAROptions *Cmd,bool TestOnly) |
|
4 | 4 |
{ |
5 | 5 |
RealBuf=NULL; |
6 | 6 |
RealReadBuffer=NULL; |
... | ... |
@@ -10,7 +10,14 @@ RecVolumes5::RecVolumes5(bool TestOnly) |
10 | 10 |
TotalCount=0; |
11 | 11 |
RecBufferSize=0; |
12 | 12 |
|
13 |
- for (uint I=0;I<ASIZE(ThreadData);I++) |
|
13 |
+#ifdef RAR_SMP |
|
14 |
+ MaxUserThreads=Cmd->Threads; |
|
15 |
+#else |
|
16 |
+ MaxUserThreads=1; |
|
17 |
+#endif |
|
18 |
+ |
|
19 |
+ ThreadData=new RecRSThreadData[MaxUserThreads]; |
|
20 |
+ for (uint I=0;I<MaxUserThreads;I++) |
|
14 | 21 |
{ |
15 | 22 |
ThreadData[I].RecRSPtr=this; |
16 | 23 |
ThreadData[I].RS=NULL; |
... | ... |
@@ -25,7 +32,7 @@ RecVolumes5::RecVolumes5(bool TestOnly) |
25 | 25 |
else |
26 | 26 |
{ |
27 | 27 |
#ifdef RAR_SMP |
28 |
- RecThreadPool=CreateThreadPool(); |
|
28 |
+ RecThreadPool=new ThreadPool(MaxUserThreads); |
|
29 | 29 |
#endif |
30 | 30 |
RealBuf=new byte[TotalBufferSize+SSE_ALIGNMENT]; |
31 | 31 |
Buf=(byte *)ALIGN_VALUE(RealBuf,SSE_ALIGNMENT); |
... | ... |
@@ -39,10 +46,11 @@ RecVolumes5::~RecVolumes5() |
39 | 39 |
delete[] RealReadBuffer; |
40 | 40 |
for (uint I=0;I<RecItems.Size();I++) |
41 | 41 |
delete RecItems[I].f; |
42 |
- for (uint I=0;I<ASIZE(ThreadData);I++) |
|
42 |
+ for (uint I=0;I<MaxUserThreads;I++) |
|
43 | 43 |
delete ThreadData[I].RS; |
44 |
+ delete[] ThreadData; |
|
44 | 45 |
#ifdef RAR_SMP |
45 |
- DestroyThreadPool(RecThreadPool); |
|
46 |
+ delete RecThreadPool; |
|
46 | 47 |
#endif |
47 | 48 |
} |
48 | 49 |
|
... | ... |
@@ -68,11 +76,7 @@ void RecVolumes5::ProcessRS(RAROptions *Cmd,uint DataNum,const byte *Data,uint M |
68 | 68 |
RS.UpdateECC(DataNum, I, Data, Buf+I*RecBufferSize, MaxRead); |
69 | 69 |
*/ |
70 | 70 |
|
71 |
-#ifdef RAR_SMP |
|
72 |
- uint ThreadNumber=Cmd->Threads; |
|
73 |
-#else |
|
74 |
- uint ThreadNumber=1; |
|
75 |
-#endif |
|
71 |
+ uint ThreadNumber=MaxUserThreads; |
|
76 | 72 |
|
77 | 73 |
const uint MinThreadBlock=0x1000; |
78 | 74 |
ThreadNumber=Min(ThreadNumber,MaxRead/MinThreadBlock); |
... | ... |
@@ -238,7 +242,7 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent) |
238 | 238 |
uiMsg(UIMSG_STRING,Item->Name); |
239 | 239 |
|
240 | 240 |
uint RevCRC; |
241 |
- CalcFileSum(Item->f,&RevCRC,NULL,Cmd->Threads,INT64NDF,CALCFSUM_CURPOS); |
|
241 |
+ CalcFileSum(Item->f,&RevCRC,NULL,MaxUserThreads,INT64NDF,CALCFSUM_CURPOS); |
|
242 | 242 |
Item->Valid=RevCRC==Item->CRC; |
243 | 243 |
if (!Item->Valid) |
244 | 244 |
{ |
... | ... |
@@ -75,8 +75,14 @@ void Rijndael::Init(bool Encrypt,const byte *key,uint keyLen,const byte * initVe |
75 | 75 |
// Check SSE here instead of constructor, so if object is a part of some |
76 | 76 |
// structure memset'ed before use, this variable is not lost. |
77 | 77 |
int CPUInfo[4]; |
78 |
- __cpuid(CPUInfo, 1); |
|
79 |
- AES_NI=(CPUInfo[2] & 0x2000000)!=0; |
|
78 |
+ __cpuid(CPUInfo, 0x80000000); // Get the maximum supported cpuid function. |
|
79 |
+ if ((CPUInfo[0] & 0x7fffffff)>=1) |
|
80 |
+ { |
|
81 |
+ __cpuid(CPUInfo, 1); |
|
82 |
+ AES_NI=(CPUInfo[2] & 0x2000000)!=0; |
|
83 |
+ } |
|
84 |
+ else |
|
85 |
+ AES_NI=0; |
|
80 | 86 |
#endif |
81 | 87 |
|
82 | 88 |
// Other developers asked us to initialize it to suppress "may be used |
... | ... |
@@ -14,13 +14,26 @@ class SaveFilePos |
14 | 14 |
} |
15 | 15 |
~SaveFilePos() |
16 | 16 |
{ |
17 |
- // If file is already closed by current exception processing, |
|
18 |
- // we would get uneeded error messages and an exception inside of |
|
19 |
- // exception and terminate if we try to seek without checking |
|
20 |
- // if file is still opened. We should not also restore the position |
|
21 |
- // if external code closed the file on purpose. |
|
17 |
+ // Unless the file is already closed either by current exception |
|
18 |
+ // processing or intentionally by external code. |
|
22 | 19 |
if (SaveFile->IsOpened()) |
23 |
- SaveFile->Seek(SavePos,SEEK_SET); |
|
20 |
+ { |
|
21 |
+ try |
|
22 |
+ { |
|
23 |
+ SaveFile->Seek(SavePos,SEEK_SET); |
|
24 |
+ } |
|
25 |
+ catch(RAR_EXIT) |
|
26 |
+ { |
|
27 |
+ // Seek() can throw an exception and it terminates process |
|
28 |
+ // if we are already processing another exception. Also in C++ 11 |
|
29 |
+ // an exception in destructor always terminates process unless |
|
30 |
+ // we mark destructor with noexcept(false). So we do not want to |
|
31 |
+ // throw here. To prevent data loss we do not want to continue |
|
32 |
+ // execution after seek error, so we close the file. |
|
33 |
+ // Any next access to this file will return an error. |
|
34 |
+ SaveFile->Close(); |
|
35 |
+ } |
|
36 |
+ } |
|
24 | 37 |
} |
25 | 38 |
}; |
26 | 39 |
|
... | ... |
@@ -241,8 +241,8 @@ uint GetDigits(uint Number) |
241 | 241 |
|
242 | 242 |
bool LowAscii(const char *Str) |
243 | 243 |
{ |
244 |
- for (int I=0;Str[I]!=0;I++) |
|
245 |
- if ((byte)Str[I]<32 || (byte)Str[I]>127) |
|
244 |
+ for (size_t I=0;Str[I]!=0;I++) |
|
245 |
+ if (/*(byte)Str[I]<32 || */(byte)Str[I]>127) |
|
246 | 246 |
return false; |
247 | 247 |
return true; |
248 | 248 |
} |
... | ... |
@@ -250,11 +250,11 @@ bool LowAscii(const char *Str) |
250 | 250 |
|
251 | 251 |
bool LowAscii(const wchar *Str) |
252 | 252 |
{ |
253 |
- for (int I=0;Str[I]!=0;I++) |
|
253 |
+ for (size_t I=0;Str[I]!=0;I++) |
|
254 | 254 |
{ |
255 | 255 |
// We convert wchar_t to uint just in case if some compiler |
256 | 256 |
// uses signed wchar_t. |
257 |
- if ((uint)Str[I]<32 || (uint)Str[I]>127) |
|
257 |
+ if (/*(uint)Str[I]<32 || */(uint)Str[I]>127) |
|
258 | 258 |
return false; |
259 | 259 |
} |
260 | 260 |
return true; |
... | ... |
@@ -187,18 +187,29 @@ SSE_VERSION _SSE_Version=GetSSEVersion(); |
187 | 187 |
SSE_VERSION GetSSEVersion() |
188 | 188 |
{ |
189 | 189 |
int CPUInfo[4]; |
190 |
- __cpuid(CPUInfo, 7); |
|
191 |
- if ((CPUInfo[1] & 0x20)!=0) |
|
192 |
- return SSE_AVX2; |
|
193 |
- __cpuid(CPUInfo, 1); |
|
194 |
- if ((CPUInfo[2] & 0x80000)!=0) |
|
195 |
- return SSE_SSE41; |
|
196 |
- if ((CPUInfo[2] & 0x200)!=0) |
|
197 |
- return SSE_SSSE3; |
|
198 |
- if ((CPUInfo[3] & 0x4000000)!=0) |
|
199 |
- return SSE_SSE2; |
|
200 |
- if ((CPUInfo[3] & 0x2000000)!=0) |
|
201 |
- return SSE_SSE; |
|
190 |
+ __cpuid(CPUInfo, 0x80000000); |
|
191 |
+ |
|
192 |
+ // Maximum supported cpuid function. For example, Pentium M 755 returns 4 here. |
|
193 |
+ uint MaxSupported=CPUInfo[0] & 0x7fffffff; |
|
194 |
+ |
|
195 |
+ if (MaxSupported>=7) |
|
196 |
+ { |
|
197 |
+ __cpuid(CPUInfo, 7); |
|
198 |
+ if ((CPUInfo[1] & 0x20)!=0) |
|
199 |
+ return SSE_AVX2; |
|
200 |
+ } |
|
201 |
+ if (MaxSupported>=1) |
|
202 |
+ { |
|
203 |
+ __cpuid(CPUInfo, 1); |
|
204 |
+ if ((CPUInfo[2] & 0x80000)!=0) |
|
205 |
+ return SSE_SSE41; |
|
206 |
+ if ((CPUInfo[2] & 0x200)!=0) |
|
207 |
+ return SSE_SSSE3; |
|
208 |
+ if ((CPUInfo[3] & 0x4000000)!=0) |
|
209 |
+ return SSE_SSE2; |
|
210 |
+ if ((CPUInfo[3] & 0x2000000)!=0) |
|
211 |
+ return SSE_SSE; |
|
212 |
+ } |
|
202 | 213 |
return SSE_NONE; |
203 | 214 |
} |
204 | 215 |
#endif |
... | ... |
@@ -1,7 +1,3 @@ |
1 |
-// Typically we use the same global thread pool for all RAR modules. |
|
2 |
-static ThreadPool *GlobalPool=NULL; |
|
3 |
-static uint GlobalPoolUseCount=0; |
|
4 |
- |
|
5 | 1 |
static inline bool CriticalSectionCreate(CRITSECT_HANDLE *CritSection) |
6 | 2 |
{ |
7 | 3 |
#ifdef _WIN_ALL |
... | ... |
@@ -43,53 +39,6 @@ static inline void CriticalSectionEnd(CRITSECT_HANDLE *CritSection) |
43 | 43 |
} |
44 | 44 |
|
45 | 45 |
|
46 |
-static struct GlobalPoolCreateSync |
|
47 |
-{ |
|
48 |
- CRITSECT_HANDLE CritSection; |
|
49 |
- GlobalPoolCreateSync() { CriticalSectionCreate(&CritSection); } |
|
50 |
- ~GlobalPoolCreateSync() { CriticalSectionDelete(&CritSection); } |
|
51 |
-} PoolCreateSync; |
|
52 |
- |
|
53 |
- |
|
54 |
-ThreadPool* CreateThreadPool() |
|
55 |
-{ |
|
56 |
-#ifdef RARDLL |
|
57 |
- // We use a simple thread pool, which does not allow to add tasks from |
|
58 |
- // different functions and threads in the same time. It is ok for RAR, |
|
59 |
- // but UnRAR.dll can be used in multithreaded environment. So we return |
|
60 |
- // a new pool for UnRAR.dll every time. |
|
61 |
- return new ThreadPool(MaxPoolThreads); |
|
62 |
-#else |
|
63 |
- // Reuse the existing pool for RAR. |
|
64 |
- CriticalSectionStart(&PoolCreateSync.CritSection); |
|
65 |
- |
|
66 |
- if (GlobalPoolUseCount++ == 0) |
|
67 |
- GlobalPool=new ThreadPool(MaxPoolThreads); |
|
68 |
- |
|
69 |
- CriticalSectionEnd(&PoolCreateSync.CritSection); |
|
70 |
- return GlobalPool; |
|
71 |
-#endif |
|
72 |
-} |
|
73 |
- |
|
74 |
- |
|
75 |
-void DestroyThreadPool(ThreadPool *Pool) |
|
76 |
-{ |
|
77 |
- if (Pool!=NULL) |
|
78 |
- { |
|
79 |
-#ifdef RARDLL |
|
80 |
- delete Pool; |
|
81 |
-#else |
|
82 |
- CriticalSectionStart(&PoolCreateSync.CritSection); |
|
83 |
- |
|
84 |
- if (Pool==GlobalPool && GlobalPoolUseCount > 0 && --GlobalPoolUseCount == 0) |
|
85 |
- delete GlobalPool; |
|
86 |
- |
|
87 |
- CriticalSectionEnd(&PoolCreateSync.CritSection); |
|
88 |
-#endif |
|
89 |
- } |
|
90 |
-} |
|
91 |
- |
|
92 |
- |
|
93 | 46 |
static THREAD_HANDLE ThreadCreate(NATIVE_THREAD_PTR Proc,void *Data) |
94 | 47 |
{ |
95 | 48 |
#ifdef _UNIX |
... | ... |
@@ -170,12 +170,13 @@ void ThreadPool::AddTask(PTHREAD_PROC Proc,void *Data) |
170 | 170 |
CreateThreads(); |
171 | 171 |
|
172 | 172 |
// If queue is full, wait until it is empty. |
173 |
- if ((QueueTop + 1) % ASIZE(TaskQueue) == QueueBottom) |
|
173 |
+ if (ActiveThreads>=ASIZE(TaskQueue)) |
|
174 | 174 |
WaitDone(); |
175 | 175 |
|
176 | 176 |
TaskQueue[QueueTop].Proc = Proc; |
177 | 177 |
TaskQueue[QueueTop].Param = Data; |
178 | 178 |
QueueTop = (QueueTop + 1) % ASIZE(TaskQueue); |
179 |
+ ActiveThreads++; |
|
179 | 180 |
} |
180 | 181 |
|
181 | 182 |
|
... | ... |
@@ -184,9 +185,6 @@ void ThreadPool::AddTask(PTHREAD_PROC Proc,void *Data) |
184 | 184 |
// are sleeping yet. |
185 | 185 |
void ThreadPool::WaitDone() |
186 | 186 |
{ |
187 |
- // We add ASIZE(TaskQueue) for case if TaskQueue array size is not |
|
188 |
- // a power of two. Negative numbers would not suit our purpose here. |
|
189 |
- ActiveThreads=(QueueTop+ASIZE(TaskQueue)-QueueBottom) % ASIZE(TaskQueue); |
|
190 | 187 |
if (ActiveThreads==0) |
191 | 188 |
return; |
192 | 189 |
#ifdef _WIN_ALL |
... | ... |
@@ -4,7 +4,10 @@ |
4 | 4 |
#ifndef RAR_SMP |
5 | 5 |
const uint MaxPoolThreads=1; // For single threaded version. |
6 | 6 |
#else |
7 |
-const uint MaxPoolThreads=32; |
|
7 |
+// We need to use the processor groups API to increase it beyond 64. |
|
8 |
+// Also be sure to check and adjust if needed per thread and total block size |
|
9 |
+// when compressing if going above 64. |
|
10 |
+const uint MaxPoolThreads=64; |
|
8 | 11 |
|
9 | 12 |
|
10 | 13 |
#ifdef _UNIX |
... | ... |
@@ -98,9 +101,6 @@ class ThreadPool |
98 | 98 |
#endif |
99 | 99 |
}; |
100 | 100 |
|
101 |
-ThreadPool* CreateThreadPool(); |
|
102 |
-void DestroyThreadPool(ThreadPool *Pool); |
|
103 |
- |
|
104 | 101 |
#endif // RAR_SMP |
105 | 102 |
|
106 | 103 |
#endif // _RAR_THREADPOOL_ |
... | ... |
@@ -20,7 +20,7 @@ enum UIMESSAGE_CODE { |
20 | 20 |
UIERROR_SUBHEADERDATABROKEN, UIERROR_RRDAMAGED, UIERROR_UNKNOWNMETHOD, |
21 | 21 |
UIERROR_UNKNOWNENCMETHOD, UIERROR_RENAMING, UIERROR_NEWERRAR, |
22 | 22 |
UIERROR_NOTSFX, UIERROR_OLDTOSFX, |
23 |
- UIERROR_WRONGSFXVER, UIERROR_ALREADYENC, UIERROR_DICTOUTMEM, |
|
23 |
+ UIERROR_WRONGSFXVER, UIERROR_HEADENCMISMATCH, UIERROR_DICTOUTMEM, |
|
24 | 24 |
UIERROR_USESMALLERDICT, UIERROR_MODIFYUNKNOWN, UIERROR_MODIFYOLD, |
25 | 25 |
UIERROR_MODIFYLOCKED, UIERROR_MODIFYVOLUME, UIERROR_NOTVOLUME, |
26 | 26 |
UIERROR_NOTFIRSTVOLUME, UIERROR_RECVOLLIMIT, UIERROR_RECVOLDIFFSETS, |
... | ... |
@@ -38,6 +38,7 @@ enum UIMESSAGE_CODE { |
38 | 38 |
UIERROR_PATHTOOLONG, UIERROR_DIRSCAN, UIERROR_UOWNERGET, |
39 | 39 |
UIERROR_UOWNERBROKEN, UIERROR_UOWNERGETOWNERID, UIERROR_UOWNERGETGROUPID, |
40 | 40 |
UIERROR_UOWNERSET, UIERROR_ULINKREAD, UIERROR_ULINKEXIST, |
41 |
+ UIERROR_OPENPRESERVEATIME, |
|
41 | 42 |
|
42 | 43 |
UIMSG_FIRST, |
43 | 44 |
UIMSG_STRING, UIMSG_BUILD, UIMSG_RRSEARCH, UIMSG_ANALYZEFILEDATA, |
... | ... |
@@ -489,6 +489,8 @@ const wchar_t* wcscasestr(const wchar_t *str, const wchar_t *search) |
489 | 489 |
wchar* wcslower(wchar *s) |
490 | 490 |
{ |
491 | 491 |
#ifdef _WIN_ALL |
492 |
+ // _wcslwr requires setlocale and we do not want to depend on setlocale |
|
493 |
+ // in Windows. Also CharLower involves less overhead. |
|
492 | 494 |
CharLower(s); |
493 | 495 |
#else |
494 | 496 |
for (wchar *c=s;*c!=0;c++) |
... | ... |
@@ -503,6 +505,8 @@ wchar* wcslower(wchar *s) |
503 | 503 |
wchar* wcsupper(wchar *s) |
504 | 504 |
{ |
505 | 505 |
#ifdef _WIN_ALL |
506 |
+ // _wcsupr requires setlocale and we do not want to depend on setlocale |
|
507 |
+ // in Windows. Also CharUpper involves less overhead. |
|
506 | 508 |
CharUpper(s); |
507 | 509 |
#else |
508 | 510 |
for (wchar *c=s;*c!=0;c++) |
... | ... |
@@ -520,8 +524,9 @@ int toupperw(int ch) |
520 | 520 |
#if defined(_WIN_ALL) |
521 | 521 |
// CharUpper is more reliable than towupper in Windows, which seems to be |
522 | 522 |
// C locale dependent even in Unicode version. For example, towupper failed |
523 |
- // to convert lowercase Russian characters. |
|
524 |
- return (int)(INT_PTR)CharUpper((wchar *)(INT_PTR)ch); |
|
523 |
+ // to convert lowercase Russian characters. Use 0xffff mask to prevent crash |
|
524 |
+ // if value larger than 0xffff is passed to this function. |
|
525 |
+ return (int)(INT_PTR)CharUpper((wchar *)(INT_PTR)(ch&0xffff)); |
|
525 | 526 |
#else |
526 | 527 |
return towupper(ch); |
527 | 528 |
#endif |
... | ... |
@@ -532,8 +537,9 @@ int tolowerw(int ch) |
532 | 532 |
{ |
533 | 533 |
#if defined(_WIN_ALL) |
534 | 534 |
// CharLower is more reliable than towlower in Windows. |
535 |
- // See comment for towupper above. |
|
536 |
- return (int)(INT_PTR)CharLower((wchar *)(INT_PTR)ch); |
|
535 |
+ // See comment for towupper above. Use 0xffff mask to prevent crash |
|
536 |
+ // if value larger than 0xffff is passed to this function. |
|
537 |
+ return (int)(INT_PTR)CharLower((wchar *)(INT_PTR)(ch&0xffff)); |
|
537 | 538 |
#else |
538 | 539 |
return towlower(ch); |
539 | 540 |
#endif |
... | ... |
@@ -648,3 +654,5 @@ char* SupportDBCS::strrchrd(const char *s, int c) |
648 | 648 |
return((char *)found); |
649 | 649 |
} |
650 | 650 |
#endif |
651 |
+ |
|
652 |
+ |
... | ... |
@@ -26,7 +26,7 @@ Unpack::Unpack(ComprDataIO *DataIO) |
26 | 26 |
UnpSomeRead=false; |
27 | 27 |
#ifdef RAR_SMP |
28 | 28 |
MaxUserThreads=1; |
29 |
- UnpThreadPool=CreateThreadPool(); |
|
29 |
+ UnpThreadPool=NULL; |
|
30 | 30 |
ReadBufMT=NULL; |
31 | 31 |
UnpThreadData=NULL; |
32 | 32 |
#endif |
... | ... |
@@ -52,13 +52,24 @@ Unpack::~Unpack() |
52 | 52 |
if (Window!=NULL) |
53 | 53 |
free(Window); |
54 | 54 |
#ifdef RAR_SMP |
55 |
- DestroyThreadPool(UnpThreadPool); |
|
55 |
+ delete UnpThreadPool; |
|
56 | 56 |
delete[] ReadBufMT; |
57 | 57 |
delete[] UnpThreadData; |
58 | 58 |
#endif |
59 | 59 |
} |
60 | 60 |
|
61 | 61 |
|
62 |
+#ifdef RAR_SMP |
|
63 |
+void Unpack::SetThreads(uint Threads) |
|
64 |
+{ |
|
65 |
+ // More than 8 threads are unlikely to provide noticeable gain |
|
66 |
+ // for unpacking, but would use the additional memory. |
|
67 |
+ MaxUserThreads=Min(Threads,8); |
|
68 |
+ UnpThreadPool=new ThreadPool(MaxUserThreads); |
|
69 |
+} |
|
70 |
+#endif |
|
71 |
+ |
|
72 |
+ |
|
62 | 73 |
void Unpack::Init(size_t WinSize,bool Solid) |
63 | 74 |
{ |
64 | 75 |
// If 32-bit RAR unpacks an archive with 4 GB dictionary, the window size |
... | ... |
@@ -24,7 +24,7 @@ |
24 | 24 |
#define MAX_FILTER_BLOCK_SIZE 0x400000 |
25 | 25 |
|
26 | 26 |
// Write data in 4 MB or smaller blocks. Must not exceed PACK_MAX_WRITE, |
27 |
-// so we keep number of buffered filter in unpacker reasonable. |
|
27 |
+// so we keep a number of buffered filters in unpacker reasonable. |
|
28 | 28 |
#define UNPACK_MAX_WRITE 0x400000 |
29 | 29 |
|
30 | 30 |
// Decode compressed bit fields to alphabet numbers. |
... | ... |
@@ -382,10 +382,7 @@ class Unpack:PackDef |
382 | 382 |
void SetSuspended(bool Suspended) {Unpack::Suspended=Suspended;} |
383 | 383 |
|
384 | 384 |
#ifdef RAR_SMP |
385 |
- // More than 8 threads are unlikely to provide a noticeable gain |
|
386 |
- // for unpacking, but would use the additional memory. |
|
387 |
- void SetThreads(uint Threads) {MaxUserThreads=Min(Threads,8);} |
|
388 |
- |
|
385 |
+ void SetThreads(uint Threads); |
|
389 | 386 |
void UnpackDecode(UnpackThreadData &D); |
390 | 387 |
#endif |
391 | 388 |
|
... | ... |
@@ -436,6 +436,10 @@ byte* Unpack::ApplyFilter(byte *Data,uint DataSize,UnpackFilter *Flt) |
436 | 436 |
} |
437 | 437 |
return SrcData; |
438 | 438 |
case FILTER_ARM: |
439 |
+ // 2019-11-15: we turned off ARM filter by default when compressing, |
|
440 |
+ // mostly because it is inefficient for modern 64 bit ARM binaries. |
|
441 |
+ // It was turned on by default in 5.0 - 5.80b3 , so we still need it |
|
442 |
+ // here for compatibility with some of previously created archives. |
|
439 | 443 |
{ |
440 | 444 |
uint FileOffset=(uint)WrittenFileSize; |
441 | 445 |
// DataSize is unsigned, so we use "CurPos+3" and not "DataSize-3" |
... | ... |
@@ -67,7 +67,7 @@ void ExtractACL20(Archive &Arc,const wchar *FileName) |
67 | 67 |
void ExtractACL(Archive &Arc,const wchar *FileName) |
68 | 68 |
{ |
69 | 69 |
Array<byte> SubData; |
70 |
- if (!Arc.ReadSubData(&SubData,NULL)) |
|
70 |
+ if (!Arc.ReadSubData(&SubData,NULL,false)) |
|
71 | 71 |
return; |
72 | 72 |
|
73 | 73 |
SetACLPrivileges(); |
... | ... |
@@ -104,7 +104,8 @@ void ExtractStreams(Archive &Arc,const wchar *FileName,bool TestMode) |
104 | 104 |
|
105 | 105 |
if (TestMode) |
106 | 106 |
{ |
107 |
- Arc.ReadSubData(NULL,NULL); |
|
107 |
+ File CurFile; |
|
108 |
+ Arc.ReadSubData(NULL,&CurFile,true); |
|
108 | 109 |
return; |
109 | 110 |
} |
110 | 111 |
|
... | ... |
@@ -116,7 +117,7 @@ void ExtractStreams(Archive &Arc,const wchar *FileName,bool TestMode) |
116 | 116 |
if ((fd.FileAttr & FILE_ATTRIBUTE_READONLY)!=0) |
117 | 117 |
SetFileAttr(FileName,fd.FileAttr & ~FILE_ATTRIBUTE_READONLY); |
118 | 118 |
File CurFile; |
119 |
- if (CurFile.WCreate(FullName) && Arc.ReadSubData(NULL,&CurFile)) |
|
119 |
+ if (CurFile.WCreate(FullName) && Arc.ReadSubData(NULL,&CurFile,false)) |
|
120 | 120 |
CurFile.Close(); |
121 | 121 |
File HostFile; |
122 | 122 |
if (Found && HostFile.Open(FileName,FMF_OPENSHARED|FMF_UPDATE)) |