diff options
Diffstat (limited to 'CPP/7zip/Archive/7z/7zUpdate.cpp')
-rw-r--r-- | CPP/7zip/Archive/7z/7zUpdate.cpp | 924 |
1 files changed, 635 insertions, 289 deletions
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index b6fd192..4e9ea5d 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp | |||
@@ -4,6 +4,8 @@ | |||
4 | 4 | ||
5 | #include "../../../../C/CpuArch.h" | 5 | #include "../../../../C/CpuArch.h" |
6 | 6 | ||
7 | #include "../../../Common/MyLinux.h" | ||
8 | #include "../../../Common/StringToInt.h" | ||
7 | #include "../../../Common/Wildcard.h" | 9 | #include "../../../Common/Wildcard.h" |
8 | 10 | ||
9 | #include "../../Common/CreateCoder.h" | 11 | #include "../../Common/CreateCoder.h" |
@@ -24,24 +26,43 @@ | |||
24 | namespace NArchive { | 26 | namespace NArchive { |
25 | namespace N7z { | 27 | namespace N7z { |
26 | 28 | ||
27 | |||
28 | #define k_X86 k_BCJ | 29 | #define k_X86 k_BCJ |
29 | 30 | ||
30 | struct CFilterMode | 31 | struct CFilterMode |
31 | { | 32 | { |
32 | UInt32 Id; | 33 | UInt32 Id; |
33 | UInt32 Delta; | 34 | UInt32 Delta; // required File Size alignment, if Id is not k_Delta. |
34 | 35 | // (Delta == 0) means unknown alignment | |
35 | CFilterMode(): Id(0), Delta(0) {} | 36 | UInt32 Offset; // for k_ARM64 |
37 | // UInt32 AlignSizeOpt; // for k_ARM64 | ||
38 | |||
39 | CFilterMode(): | ||
40 | Id(0), | ||
41 | Delta(0), | ||
42 | Offset(0) | ||
43 | // , AlignSizeOpt(0) | ||
44 | {} | ||
45 | |||
46 | void ClearFilterMode() | ||
47 | { | ||
48 | Id = 0; | ||
49 | Delta = 0; | ||
50 | Offset = 0; | ||
51 | // AlignSizeOpt = 0; | ||
52 | } | ||
36 | 53 | ||
54 | // it sets Delta as Align value, if Id is exe filter | ||
55 | // in another cases it sets Delta = 0, that | ||
37 | void SetDelta() | 56 | void SetDelta() |
38 | { | 57 | { |
39 | if (Id == k_IA64) | 58 | if (Id == k_IA64) |
40 | Delta = 16; | 59 | Delta = 16; |
41 | else if (Id == k_ARM || Id == k_PPC || Id == k_SPARC) | 60 | else if (Id == k_ARM64 || Id == k_ARM || Id == k_PPC || Id == k_SPARC) |
42 | Delta = 4; | 61 | Delta = 4; |
43 | else if (Id == k_ARMT) | 62 | else if (Id == k_ARMT) |
44 | Delta = 2; | 63 | Delta = 2; |
64 | else if (Id == k_BCJ || Id == k_BCJ2) | ||
65 | Delta = 1; // do we need it? | ||
45 | else | 66 | else |
46 | Delta = 0; | 67 | Delta = 0; |
47 | } | 68 | } |
@@ -78,6 +99,7 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) | |||
78 | { | 99 | { |
79 | case 0x014C: | 100 | case 0x014C: |
80 | case 0x8664: filterId = k_X86; break; | 101 | case 0x8664: filterId = k_X86; break; |
102 | case 0xAA64: filterId = k_ARM64; break; | ||
81 | 103 | ||
82 | /* | 104 | /* |
83 | IMAGE_FILE_MACHINE_ARM 0x01C0 // ARM LE | 105 | IMAGE_FILE_MACHINE_ARM 0x01C0 // ARM LE |
@@ -94,6 +116,7 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) | |||
94 | default: return 0; | 116 | default: return 0; |
95 | } | 117 | } |
96 | 118 | ||
119 | // const UInt32 numSections = GetUi16(p + 2); | ||
97 | optHeaderSize = GetUi16(p + 16); | 120 | optHeaderSize = GetUi16(p + 16); |
98 | if (optHeaderSize > (1 << 10)) | 121 | if (optHeaderSize > (1 << 10)) |
99 | return 0; | 122 | return 0; |
@@ -109,6 +132,63 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) | |||
109 | return 0; | 132 | return 0; |
110 | } | 133 | } |
111 | 134 | ||
135 | /* | ||
136 | // Windows exe file sizes are not aligned for 4 KiB. | ||
137 | // So we can't use (CFilterMode::Offset != 0) in solid archives. | ||
138 | // So we just don't set Offset here. | ||
139 | #define NUM_SCAN_SECTIONS_MAX (1 << 6) | ||
140 | #define EXE_SECTION_OFFSET_MAX (1 << 27) | ||
141 | #define EXE_SECTION_SIZE_MIN (1 << 8) | ||
142 | #define EXE_SECTION_SIZE_MAX (1 << 27) | ||
143 | #define PE_SectHeaderSize 40 | ||
144 | #define PE_SECT_EXECUTE 0x20000000 | ||
145 | |||
146 | if (numSections > NUM_SCAN_SECTIONS_MAX) | ||
147 | return 0; | ||
148 | |||
149 | p += optHeaderSize; | ||
150 | // UInt32 numExeSections = 0; | ||
151 | // bool execute_finded = false; | ||
152 | // UInt32 sect_va = 0; | ||
153 | // UInt32 sect_size = 0; | ||
154 | // UInt32 sect_offset = 0; | ||
155 | |||
156 | for (UInt32 i = 0; i < numSections | ||
157 | // && numExeSections < numSectionsMax | ||
158 | ; i++, p += PE_SectHeaderSize) | ||
159 | { | ||
160 | UInt32 characts, rawSize, offset; | ||
161 | if ((UInt32)(p - buf) + PE_SectHeaderSize > size) | ||
162 | return 0; | ||
163 | rawSize = GetUi32(p + 16); | ||
164 | offset = GetUi32(p + 20); | ||
165 | characts = GetUi32(p + 36); | ||
166 | if (rawSize >= EXE_SECTION_SIZE_MIN && | ||
167 | rawSize <= EXE_SECTION_SIZE_MAX && | ||
168 | offset <= EXE_SECTION_OFFSET_MAX && | ||
169 | // offset < limit && | ||
170 | offset > 0) | ||
171 | { | ||
172 | if ((characts & PE_SECT_EXECUTE) != 0) | ||
173 | { | ||
174 | // execute_finded = true; | ||
175 | // sect_va = GetUi32(p + 12); | ||
176 | // sect_size = rawSize; | ||
177 | // sect_offset = offset; | ||
178 | break; | ||
179 | } | ||
180 | } | ||
181 | } | ||
182 | |||
183 | filterMode->Offset = 0; | ||
184 | if (filterId == k_ARM64) | ||
185 | { | ||
186 | // filterMode->AlignSizeOpt = (1 << 12); | ||
187 | // const UInt32 offs = (sect_va - sect_offset) & 0xFFF; | ||
188 | // if (offs != 0) | ||
189 | // filterMode->Offset = offs; // change it | ||
190 | } | ||
191 | */ | ||
112 | filterMode->Id = filterId; | 192 | filterMode->Id = filterId; |
113 | return 1; | 193 | return 1; |
114 | } | 194 | } |
@@ -164,8 +244,9 @@ static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode) | |||
164 | case 20: | 244 | case 20: |
165 | case 21: if (!be) return 0; filterId = k_PPC; break; | 245 | case 21: if (!be) return 0; filterId = k_PPC; break; |
166 | case 40: if ( be) return 0; filterId = k_ARM; break; | 246 | case 40: if ( be) return 0; filterId = k_ARM; break; |
167 | 247 | case 183: if (be) return 0; filterId = k_ARM64; break; | |
168 | /* Some IA-64 ELF exacutable have size that is not aligned for 16 bytes. | 248 | |
249 | /* Some IA-64 ELF executables have size that is not aligned for 16 bytes. | ||
169 | So we don't use IA-64 filter for IA-64 ELF */ | 250 | So we don't use IA-64 filter for IA-64 ELF */ |
170 | // case 50: if ( be) return 0; filterId = k_IA64; break; | 251 | // case 50: if ( be) return 0; filterId = k_IA64; break; |
171 | 252 | ||
@@ -192,6 +273,7 @@ static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode) | |||
192 | #define MACH_MACHINE_PPC 18 | 273 | #define MACH_MACHINE_PPC 18 |
193 | #define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC) | 274 | #define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC) |
194 | #define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386) | 275 | #define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386) |
276 | #define MACH_MACHINE_ARM64 (MACH_ARCH_ABI64 | MACH_MACHINE_ARM) | ||
195 | 277 | ||
196 | static unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode) | 278 | static unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode) |
197 | { | 279 | { |
@@ -218,6 +300,7 @@ static unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode | |||
218 | case MACH_MACHINE_SPARC: if (!be) return 0; filterId = k_SPARC; break; | 300 | case MACH_MACHINE_SPARC: if (!be) return 0; filterId = k_SPARC; break; |
219 | case MACH_MACHINE_PPC: | 301 | case MACH_MACHINE_PPC: |
220 | case MACH_MACHINE_PPC64: if (!be) return 0; filterId = k_PPC; break; | 302 | case MACH_MACHINE_PPC64: if (!be) return 0; filterId = k_PPC; break; |
303 | case MACH_MACHINE_ARM64: if ( be) return 0; filterId = k_ARM64; break; | ||
221 | default: return 0; | 304 | default: return 0; |
222 | } | 305 | } |
223 | 306 | ||
@@ -284,10 +367,15 @@ static BoolInt Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode) | |||
284 | return False; | 367 | return False; |
285 | } | 368 | } |
286 | 369 | ||
370 | |||
371 | /* | ||
372 | filterMode->Delta will be set as: | ||
373 | = delta value : [1, 256] : for k_Delta | ||
374 | = 0 for another filters (branch filters) | ||
375 | */ | ||
287 | static BoolInt ParseFile(const Byte *buf, size_t size, CFilterMode *filterMode) | 376 | static BoolInt ParseFile(const Byte *buf, size_t size, CFilterMode *filterMode) |
288 | { | 377 | { |
289 | filterMode->Id = 0; | 378 | filterMode->ClearFilterMode(); |
290 | filterMode->Delta = 0; | ||
291 | 379 | ||
292 | if (Parse_EXE(buf, size, filterMode)) return True; | 380 | if (Parse_EXE(buf, size, filterMode)) return True; |
293 | if (Parse_ELF(buf, size, filterMode)) return True; | 381 | if (Parse_ELF(buf, size, filterMode)) return True; |
@@ -315,18 +403,44 @@ struct CFilterMode2: public CFilterMode | |||
315 | else if (!m.Encrypted) | 403 | else if (!m.Encrypted) |
316 | return 1; | 404 | return 1; |
317 | 405 | ||
318 | if (Id < m.Id) return -1; | 406 | const UInt32 id1 = Id; |
319 | if (Id > m.Id) return 1; | 407 | const UInt32 id2 = m.Id; |
408 | /* | ||
409 | // we can change the order to place k_ARM64 files close to another exe files | ||
410 | if (id1 <= k_SPARC && | ||
411 | id2 <= k_SPARC) | ||
412 | { | ||
413 | #define k_ARM64_FOR_SORT 0x3030901 | ||
414 | if (id1 == k_ARM64) id1 = k_ARM64_FOR_SORT; | ||
415 | if (id2 == k_ARM64) id2 = k_ARM64_FOR_SORT; | ||
416 | } | ||
417 | */ | ||
418 | if (id1 < id2) return -1; | ||
419 | if (id1 > id2) return 1; | ||
320 | 420 | ||
321 | if (Delta < m.Delta) return -1; | 421 | if (Delta < m.Delta) return -1; |
322 | if (Delta > m.Delta) return 1; | 422 | if (Delta > m.Delta) return 1; |
323 | 423 | ||
424 | if (Offset < m.Offset) return -1; | ||
425 | if (Offset > m.Offset) return 1; | ||
426 | |||
427 | /* we don't go here, because GetGroup() | ||
428 | and operator ==(const CFilterMode2 &m) | ||
429 | add only unique CFilterMode2:: { Id, Delta, Offset, Encrypted } items. | ||
430 | */ | ||
431 | /* | ||
432 | if (GroupIndex < m.GroupIndex) return -1; | ||
433 | if (GroupIndex > m.GroupIndex) return 1; | ||
434 | */ | ||
324 | return 0; | 435 | return 0; |
325 | } | 436 | } |
326 | 437 | ||
327 | bool operator ==(const CFilterMode2 &m) const | 438 | bool operator ==(const CFilterMode2 &m) const |
328 | { | 439 | { |
329 | return Id == m.Id && Delta == m.Delta && Encrypted == m.Encrypted; | 440 | return Id == m.Id |
441 | && Delta == m.Delta | ||
442 | && Offset == m.Offset | ||
443 | && Encrypted == m.Encrypted; | ||
330 | } | 444 | } |
331 | }; | 445 | }; |
332 | 446 | ||
@@ -367,6 +481,7 @@ static inline bool IsExeFilter(CMethodId m) | |||
367 | { | 481 | { |
368 | switch (m) | 482 | switch (m) |
369 | { | 483 | { |
484 | case k_ARM64: | ||
370 | case k_BCJ: | 485 | case k_BCJ: |
371 | case k_BCJ2: | 486 | case k_BCJ2: |
372 | case k_ARM: | 487 | case k_ARM: |
@@ -383,8 +498,9 @@ static unsigned Get_FilterGroup_for_Folder( | |||
383 | CRecordVector<CFilterMode2> &filters, const CFolderEx &f, bool extractFilter) | 498 | CRecordVector<CFilterMode2> &filters, const CFolderEx &f, bool extractFilter) |
384 | { | 499 | { |
385 | CFilterMode2 m; | 500 | CFilterMode2 m; |
386 | m.Id = 0; | 501 | // m.Id = 0; |
387 | m.Delta = 0; | 502 | // m.Delta = 0; |
503 | // m.Offset = 0; | ||
388 | m.Encrypted = f.IsEncrypted(); | 504 | m.Encrypted = f.IsEncrypted(); |
389 | 505 | ||
390 | if (extractFilter) | 506 | if (extractFilter) |
@@ -405,6 +521,9 @@ static unsigned Get_FilterGroup_for_Folder( | |||
405 | if (m.Id == k_BCJ2) | 521 | if (m.Id == k_BCJ2) |
406 | m.Id = k_BCJ; | 522 | m.Id = k_BCJ; |
407 | m.SetDelta(); | 523 | m.SetDelta(); |
524 | if (m.Id == k_ARM64) | ||
525 | if (coder.Props.Size() == 4) | ||
526 | m.Offset = GetUi32(coder.Props); | ||
408 | } | 527 | } |
409 | } | 528 | } |
410 | 529 | ||
@@ -417,15 +536,15 @@ static unsigned Get_FilterGroup_for_Folder( | |||
417 | static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, | 536 | static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, |
418 | UInt64 position, UInt64 size, ICompressProgressInfo *progress) | 537 | UInt64 position, UInt64 size, ICompressProgressInfo *progress) |
419 | { | 538 | { |
420 | RINOK(inStream->Seek((Int64)position, STREAM_SEEK_SET, 0)); | 539 | RINOK(InStream_SeekSet(inStream, position)) |
421 | CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; | 540 | CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; |
422 | CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec); | 541 | CMyComPtr<ISequentialInStream> inStreamLimited(streamSpec); |
423 | streamSpec->SetStream(inStream); | 542 | streamSpec->SetStream(inStream); |
424 | streamSpec->Init(size); | 543 | streamSpec->Init(size); |
425 | 544 | ||
426 | NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; | 545 | NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; |
427 | CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; | 546 | CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; |
428 | RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); | 547 | RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)) |
429 | return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL); | 548 | return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL); |
430 | } | 549 | } |
431 | 550 | ||
@@ -445,7 +564,7 @@ UString CUpdateItem::GetExtension() const | |||
445 | } | 564 | } |
446 | */ | 565 | */ |
447 | 566 | ||
448 | #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } | 567 | #define RINOZ(x) { const int _t_ = (x); if (_t_ != 0) return _t_; } |
449 | 568 | ||
450 | #define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b)) | 569 | #define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b)) |
451 | 570 | ||
@@ -630,7 +749,7 @@ struct CRefItem | |||
630 | unsigned NamePos; | 749 | unsigned NamePos; |
631 | unsigned ExtensionIndex; | 750 | unsigned ExtensionIndex; |
632 | 751 | ||
633 | CRefItem() {}; | 752 | CRefItem() {} |
634 | CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType): | 753 | CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType): |
635 | UpdateItem(&ui), | 754 | UpdateItem(&ui), |
636 | Index(index), | 755 | Index(index), |
@@ -710,16 +829,16 @@ static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *para | |||
710 | 829 | ||
711 | // bool sortByType = *(bool *)param; | 830 | // bool sortByType = *(bool *)param; |
712 | const CSortParam *sortParam = (const CSortParam *)param; | 831 | const CSortParam *sortParam = (const CSortParam *)param; |
713 | bool sortByType = sortParam->SortByType; | 832 | const bool sortByType = sortParam->SortByType; |
714 | if (sortByType) | 833 | if (sortByType) |
715 | { | 834 | { |
716 | RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex); | 835 | RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex) |
717 | RINOZ(CompareFileNames(u1.Name.Ptr(a1.ExtensionPos), u2.Name.Ptr(a2.ExtensionPos))); | 836 | RINOZ(CompareFileNames(u1.Name.Ptr(a1.ExtensionPos), u2.Name.Ptr(a2.ExtensionPos))) |
718 | RINOZ(CompareFileNames(u1.Name.Ptr(a1.NamePos), u2.Name.Ptr(a2.NamePos))); | 837 | RINOZ(CompareFileNames(u1.Name.Ptr(a1.NamePos), u2.Name.Ptr(a2.NamePos))) |
719 | if (!u1.MTimeDefined && u2.MTimeDefined) return 1; | 838 | if (!u1.MTimeDefined && u2.MTimeDefined) return 1; |
720 | if (u1.MTimeDefined && !u2.MTimeDefined) return -1; | 839 | if (u1.MTimeDefined && !u2.MTimeDefined) return -1; |
721 | if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime); | 840 | if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime) |
722 | RINOZ_COMP(u1.Size, u2.Size); | 841 | RINOZ_COMP(u1.Size, u2.Size) |
723 | } | 842 | } |
724 | /* | 843 | /* |
725 | int par1 = a1.UpdateItem->ParentFolderIndex; | 844 | int par1 = a1.UpdateItem->ParentFolderIndex; |
@@ -765,9 +884,9 @@ static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *para | |||
765 | } | 884 | } |
766 | */ | 885 | */ |
767 | // RINOZ_COMP(a1.UpdateItem->ParentSortIndex, a2.UpdateItem->ParentSortIndex); | 886 | // RINOZ_COMP(a1.UpdateItem->ParentSortIndex, a2.UpdateItem->ParentSortIndex); |
768 | RINOK(CompareFileNames(u1.Name, u2.Name)); | 887 | RINOK(CompareFileNames(u1.Name, u2.Name)) |
769 | RINOZ_COMP(a1.UpdateItem->IndexInClient, a2.UpdateItem->IndexInClient); | 888 | RINOZ_COMP(a1.UpdateItem->IndexInClient, a2.UpdateItem->IndexInClient) |
770 | RINOZ_COMP(a1.UpdateItem->IndexInArchive, a2.UpdateItem->IndexInArchive); | 889 | RINOZ_COMP(a1.UpdateItem->IndexInArchive, a2.UpdateItem->IndexInArchive) |
771 | return 0; | 890 | return 0; |
772 | } | 891 | } |
773 | 892 | ||
@@ -778,7 +897,7 @@ struct CSolidGroup | |||
778 | CRecordVector<CFolderRepack> folderRefs; | 897 | CRecordVector<CFolderRepack> folderRefs; |
779 | }; | 898 | }; |
780 | 899 | ||
781 | static const char * const g_ExeExts[] = | 900 | static const char * const g_Exe_Exts[] = |
782 | { | 901 | { |
783 | "dll" | 902 | "dll" |
784 | , "exe" | 903 | , "exe" |
@@ -787,14 +906,65 @@ static const char * const g_ExeExts[] = | |||
787 | , "sys" | 906 | , "sys" |
788 | }; | 907 | }; |
789 | 908 | ||
790 | static bool IsExeExt(const wchar_t *ext) | 909 | static const char * const g_ExeUnix_Exts[] = |
910 | { | ||
911 | "so" | ||
912 | , "dylib" | ||
913 | }; | ||
914 | |||
915 | static bool IsExt_Exe(const wchar_t *ext) | ||
791 | { | 916 | { |
792 | for (unsigned i = 0; i < ARRAY_SIZE(g_ExeExts); i++) | 917 | for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_Exe_Exts); i++) |
793 | if (StringsAreEqualNoCase_Ascii(ext, g_ExeExts[i])) | 918 | if (StringsAreEqualNoCase_Ascii(ext, g_Exe_Exts[i])) |
794 | return true; | 919 | return true; |
795 | return false; | 920 | return false; |
796 | } | 921 | } |
797 | 922 | ||
923 | /* | ||
924 | static bool IsExt_ExeUnix(const wchar_t *ext) | ||
925 | { | ||
926 | for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ExeUnix_Exts); i++) | ||
927 | if (StringsAreEqualNoCase_Ascii(ext, g_ExeUnix_Exts[i])) | ||
928 | return true; | ||
929 | return false; | ||
930 | } | ||
931 | */ | ||
932 | |||
933 | // we try to find "so" extension in such name: libstdc++.so.6.0.29 | ||
934 | static bool IsExt_ExeUnix_NumericAllowed(const UString &path) | ||
935 | { | ||
936 | unsigned pos = path.Len(); | ||
937 | unsigned dotPos = pos; | ||
938 | for (;;) | ||
939 | { | ||
940 | if (pos == 0) | ||
941 | return false; | ||
942 | const wchar_t c = path[--pos]; | ||
943 | if (IS_PATH_SEPAR(c)) | ||
944 | return false; | ||
945 | if (c == '.') | ||
946 | { | ||
947 | const unsigned num = (dotPos - pos) - 1; | ||
948 | if (num < 1) | ||
949 | return false; | ||
950 | const wchar_t *cur = path.Ptr(pos + 1); | ||
951 | for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ExeUnix_Exts); i++) | ||
952 | { | ||
953 | const char *ext = g_ExeUnix_Exts[i]; | ||
954 | if (num == MyStringLen(ext)) | ||
955 | if (IsString1PrefixedByString2_NoCase_Ascii(cur, ext)) | ||
956 | return true; | ||
957 | } | ||
958 | const wchar_t *end; | ||
959 | ConvertStringToUInt32(cur, &end); | ||
960 | if ((size_t)(end - cur) != num) | ||
961 | return false; | ||
962 | dotPos = pos; | ||
963 | } | ||
964 | } | ||
965 | } | ||
966 | |||
967 | |||
798 | struct CAnalysis | 968 | struct CAnalysis |
799 | { | 969 | { |
800 | CMyComPtr<IArchiveUpdateCallbackFile> Callback; | 970 | CMyComPtr<IArchiveUpdateCallbackFile> Callback; |
@@ -802,6 +972,8 @@ struct CAnalysis | |||
802 | 972 | ||
803 | bool ParseWav; | 973 | bool ParseWav; |
804 | bool ParseExe; | 974 | bool ParseExe; |
975 | bool ParseExeUnix; | ||
976 | bool ParseNoExt; | ||
805 | bool ParseAll; | 977 | bool ParseAll; |
806 | 978 | ||
807 | /* | 979 | /* |
@@ -811,8 +983,10 @@ struct CAnalysis | |||
811 | */ | 983 | */ |
812 | 984 | ||
813 | CAnalysis(): | 985 | CAnalysis(): |
814 | ParseWav(true), | 986 | ParseWav(false), |
815 | ParseExe(false), | 987 | ParseExe(false), |
988 | ParseExeUnix(false), | ||
989 | ParseNoExt(false), | ||
816 | ParseAll(false) | 990 | ParseAll(false) |
817 | /* | 991 | /* |
818 | , Need_ATime(false) | 992 | , Need_ATime(false) |
@@ -829,32 +1003,46 @@ HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMo | |||
829 | { | 1003 | { |
830 | filterMode.Id = 0; | 1004 | filterMode.Id = 0; |
831 | filterMode.Delta = 0; | 1005 | filterMode.Delta = 0; |
1006 | filterMode.Offset = 0; | ||
832 | 1007 | ||
833 | CFilterMode filterModeTemp = filterMode; | 1008 | CFilterMode filterModeTemp = filterMode; |
834 | 1009 | ||
835 | int slashPos = ui.Name.ReverseFind_PathSepar(); | 1010 | const int slashPos = ui.Name.ReverseFind_PathSepar(); |
836 | int dotPos = ui.Name.ReverseFind_Dot(); | 1011 | const int dotPos = ui.Name.ReverseFind_Dot(); |
837 | 1012 | ||
838 | // if (dotPos > slashPos) | 1013 | // if (dotPos > slashPos) |
839 | { | 1014 | { |
840 | bool needReadFile = ParseAll; | 1015 | bool needReadFile = ParseAll; |
841 | 1016 | /* if (Callback) is not supported by client, | |
1017 | we still try to use file name extension to detect executable file */ | ||
842 | bool probablyIsSameIsa = false; | 1018 | bool probablyIsSameIsa = false; |
843 | 1019 | ||
844 | if (!needReadFile || !Callback) | 1020 | if (!needReadFile || !Callback) |
845 | { | 1021 | { |
846 | const wchar_t *ext; | 1022 | const wchar_t *ext = NULL; |
847 | if (dotPos > slashPos) | 1023 | if (dotPos > slashPos) |
848 | ext = ui.Name.Ptr((unsigned)(dotPos + 1)); | 1024 | ext = ui.Name.Ptr((unsigned)(dotPos + 1)); |
849 | else | 1025 | // 7-zip stores posix attributes in high 16 bits and sets (0x8000) flag |
850 | ext = ui.Name.RightPtr(0); | ||
851 | |||
852 | // p7zip uses the trick to store posix attributes in high 16 bits | ||
853 | if (ui.Attrib & 0x8000) | 1026 | if (ui.Attrib & 0x8000) |
854 | { | 1027 | { |
855 | unsigned st_mode = ui.Attrib >> 16; | 1028 | const unsigned st_mode = ui.Attrib >> 16; |
856 | // st_mode = 00111; | 1029 | /* note: executable ".so" can be without execute permission, |
857 | if ((st_mode & 00111) && (ui.Size >= 2048)) | 1030 | and symbolic link to such ".so" file is possible */ |
1031 | // st_mode = 00111; // for debug | ||
1032 | /* in Linux we expect such permissions: | ||
1033 | 0755 : for most executables | ||
1034 | 0644 : for some ".so" files | ||
1035 | 0777 : in WSL for all files. | ||
1036 | We can try to exclude some such 0777 cases from analysis, | ||
1037 | if there is non-executable extension. | ||
1038 | */ | ||
1039 | |||
1040 | if ((st_mode & ( | ||
1041 | MY_LIN_S_IXUSR | | ||
1042 | MY_LIN_S_IXGRP | | ||
1043 | MY_LIN_S_IXOTH)) != 0 | ||
1044 | && MY_LIN_S_ISREG(st_mode) | ||
1045 | && (ui.Size >= (1u << 11))) | ||
858 | { | 1046 | { |
859 | #ifndef _WIN32 | 1047 | #ifndef _WIN32 |
860 | probablyIsSameIsa = true; | 1048 | probablyIsSameIsa = true; |
@@ -863,36 +1051,45 @@ HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMo | |||
863 | } | 1051 | } |
864 | } | 1052 | } |
865 | 1053 | ||
866 | if (IsExeExt(ext)) | 1054 | if (!needReadFile) |
867 | { | ||
868 | needReadFile = true; | ||
869 | #ifdef _WIN32 | ||
870 | probablyIsSameIsa = true; | ||
871 | needReadFile = ParseExe; | ||
872 | #endif | ||
873 | } | ||
874 | else if (StringsAreEqualNoCase_Ascii(ext, "wav")) | ||
875 | { | ||
876 | needReadFile = ParseWav; | ||
877 | } | ||
878 | /* | ||
879 | else if (!needReadFile && ParseUnixExt) | ||
880 | { | 1055 | { |
881 | if (StringsAreEqualNoCase_Ascii(ext, "so") | 1056 | if (!ext) |
882 | || StringsAreEqualNoCase_Ascii(ext, "")) | 1057 | needReadFile = ParseNoExt; |
883 | 1058 | else | |
884 | needReadFile = true; | 1059 | { |
1060 | bool isUnixExt = false; | ||
1061 | if (ParseExeUnix) | ||
1062 | isUnixExt = IsExt_ExeUnix_NumericAllowed(ui.Name); | ||
1063 | if (isUnixExt) | ||
1064 | { | ||
1065 | needReadFile = true; | ||
1066 | #ifndef _WIN32 | ||
1067 | probablyIsSameIsa = true; | ||
1068 | #endif | ||
1069 | } | ||
1070 | else if (IsExt_Exe(ext)) | ||
1071 | { | ||
1072 | needReadFile = ParseExe; | ||
1073 | #ifdef _WIN32 | ||
1074 | probablyIsSameIsa = true; | ||
1075 | #endif | ||
1076 | } | ||
1077 | else if (StringsAreEqualNoCase_Ascii(ext, "wav")) | ||
1078 | { | ||
1079 | if (!needReadFile) | ||
1080 | needReadFile = ParseWav; | ||
1081 | } | ||
1082 | } | ||
885 | } | 1083 | } |
886 | */ | ||
887 | } | 1084 | } |
888 | 1085 | ||
889 | if (needReadFile && Callback) | 1086 | if (needReadFile) |
890 | { | 1087 | { |
891 | if (Buffer.Size() != kAnalysisBufSize) | 1088 | BoolInt parseRes = false; |
892 | { | 1089 | if (Callback) |
893 | Buffer.Alloc(kAnalysisBufSize); | ||
894 | } | ||
895 | { | 1090 | { |
1091 | if (Buffer.Size() != kAnalysisBufSize) | ||
1092 | Buffer.Alloc(kAnalysisBufSize); | ||
896 | CMyComPtr<ISequentialInStream> stream; | 1093 | CMyComPtr<ISequentialInStream> stream; |
897 | HRESULT result = Callback->GetStream2(index, &stream, NUpdateNotifyOp::kAnalyze); | 1094 | HRESULT result = Callback->GetStream2(index, &stream, NUpdateNotifyOp::kAnalyze); |
898 | if (result == S_OK && stream) | 1095 | if (result == S_OK && stream) |
@@ -908,40 +1105,60 @@ HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMo | |||
908 | ATime_Defined = true; | 1105 | ATime_Defined = true; |
909 | } | 1106 | } |
910 | */ | 1107 | */ |
911 | |||
912 | size_t size = kAnalysisBufSize; | 1108 | size_t size = kAnalysisBufSize; |
913 | result = ReadStream(stream, Buffer, &size); | 1109 | result = ReadStream(stream, Buffer, &size); |
914 | stream.Release(); | 1110 | stream.Release(); |
915 | // RINOK(Callback->SetOperationResult2(index, NUpdate::NOperationResult::kOK)); | 1111 | // RINOK(Callback->SetOperationResult2(index, NUpdate::NOperationResult::kOK)); |
916 | if (result == S_OK) | 1112 | if (result == S_OK) |
917 | { | 1113 | { |
918 | BoolInt parseRes = ParseFile(Buffer, size, &filterModeTemp); | 1114 | parseRes = ParseFile(Buffer, size, &filterModeTemp); |
919 | if (parseRes && filterModeTemp.Delta == 0) | 1115 | } |
920 | { | 1116 | } |
921 | filterModeTemp.SetDelta(); | 1117 | } // Callback |
922 | if (filterModeTemp.Delta != 0 && filterModeTemp.Id != k_Delta) | 1118 | else if (probablyIsSameIsa) |
923 | { | 1119 | { |
924 | if (ui.Size % filterModeTemp.Delta != 0) | 1120 | #ifdef MY_CPU_X86_OR_AMD64 |
925 | { | 1121 | filterModeTemp.Id = k_X86; |
926 | parseRes = false; | 1122 | #endif |
927 | } | 1123 | #ifdef MY_CPU_ARM64 |
928 | } | 1124 | filterModeTemp.Id = k_ARM64; |
929 | } | 1125 | #endif |
930 | if (!parseRes) | 1126 | parseRes = true; |
1127 | } | ||
1128 | |||
1129 | if (parseRes | ||
1130 | && filterModeTemp.Id != k_Delta | ||
1131 | && filterModeTemp.Delta == 0) | ||
1132 | { | ||
1133 | /* ParseFile() sets (filterModeTemp.Delta == 0) for all | ||
1134 | methods except of k_Delta. */ | ||
1135 | // it's not k_Delta | ||
1136 | // So we call SetDelta() to set Delta | ||
1137 | filterModeTemp.SetDelta(); | ||
1138 | if (filterModeTemp.Delta > 1) | ||
1139 | { | ||
1140 | /* If file Size is not aligned, then branch filter | ||
1141 | will not work for next file in solid block. | ||
1142 | Maybe we should allow filter for non-aligned-size file in non-solid archives ? | ||
1143 | */ | ||
1144 | if (ui.Size % filterModeTemp.Delta != 0) | ||
1145 | parseRes = false; | ||
1146 | // windows exe files are not aligned for 4 KiB. | ||
1147 | /* | ||
1148 | else if (filterModeTemp.Id == k_ARM64 && filterModeTemp.Offset != 0) | ||
1149 | { | ||
1150 | if (ui.Size % (1 << 12) != 0) | ||
931 | { | 1151 | { |
932 | filterModeTemp.Id = 0; | 1152 | // If Size is not aligned for 4 KiB, then Offset will not work for next file in solid block. |
933 | filterModeTemp.Delta = 0; | 1153 | // so we place such file in group with (Offset==0). |
1154 | filterModeTemp.Offset = 0; | ||
934 | } | 1155 | } |
935 | } | 1156 | } |
1157 | */ | ||
936 | } | 1158 | } |
937 | } | 1159 | } |
938 | } | 1160 | if (!parseRes) |
939 | else if ((needReadFile && !Callback) || probablyIsSameIsa) | 1161 | filterModeTemp.ClearFilterMode(); |
940 | { | ||
941 | #ifdef MY_CPU_X86_OR_AMD64 | ||
942 | if (probablyIsSameIsa) | ||
943 | filterModeTemp.Id = k_X86; | ||
944 | #endif | ||
945 | } | 1162 | } |
946 | } | 1163 | } |
947 | 1164 | ||
@@ -1010,7 +1227,7 @@ static HRESULT AddBcj2Methods(CCompressionMethodMode &mode) | |||
1010 | mode.Methods.Add(m); | 1227 | mode.Methods.Add(m); |
1011 | mode.Methods.Add(m); | 1228 | mode.Methods.Add(m); |
1012 | 1229 | ||
1013 | RINOK(AddBondForFilter(mode)); | 1230 | RINOK(AddBondForFilter(mode)) |
1014 | CBond2 bond; | 1231 | CBond2 bond; |
1015 | bond.OutCoder = 0; | 1232 | bond.OutCoder = 0; |
1016 | bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond); | 1233 | bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond); |
@@ -1024,7 +1241,7 @@ static HRESULT MakeExeMethod(CCompressionMethodMode &mode, | |||
1024 | if (mode.Filter_was_Inserted) | 1241 | if (mode.Filter_was_Inserted) |
1025 | { | 1242 | { |
1026 | const CMethodFull &m = mode.Methods[0]; | 1243 | const CMethodFull &m = mode.Methods[0]; |
1027 | CMethodId id = m.Id; | 1244 | const CMethodId id = m.Id; |
1028 | if (id == k_BCJ2) | 1245 | if (id == k_BCJ2) |
1029 | return AddBcj2Methods(mode); | 1246 | return AddBcj2Methods(mode); |
1030 | if (!m.IsSimpleCoder()) | 1247 | if (!m.IsSimpleCoder()) |
@@ -1039,7 +1256,7 @@ static HRESULT MakeExeMethod(CCompressionMethodMode &mode, | |||
1039 | CMethodFull &m = mode.Methods.InsertNew(0); | 1256 | CMethodFull &m = mode.Methods.InsertNew(0); |
1040 | 1257 | ||
1041 | { | 1258 | { |
1042 | FOR_VECTOR(k, mode.Bonds) | 1259 | FOR_VECTOR (k, mode.Bonds) |
1043 | { | 1260 | { |
1044 | CBond2 &bond = mode.Bonds[k]; | 1261 | CBond2 &bond = mode.Bonds[k]; |
1045 | bond.InCoder++; | 1262 | bond.InCoder++; |
@@ -1059,23 +1276,32 @@ static HRESULT MakeExeMethod(CCompressionMethodMode &mode, | |||
1059 | GetMethodFull(filterMode.Id, 1, m); | 1276 | GetMethodFull(filterMode.Id, 1, m); |
1060 | if (filterMode.Id == k_Delta) | 1277 | if (filterMode.Id == k_Delta) |
1061 | m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta); | 1278 | m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta); |
1279 | else if (filterMode.Id == k_ARM64) | ||
1280 | { | ||
1281 | // if (filterMode.Offset != 0) | ||
1282 | m.AddProp32( | ||
1283 | NCoderPropID::kDefaultProp, | ||
1284 | // NCoderPropID::kBranchOffset, | ||
1285 | filterMode.Offset); | ||
1286 | } | ||
1062 | res = AddFilterBond(mode); | 1287 | res = AddFilterBond(mode); |
1063 | 1288 | ||
1064 | int alignBits = -1; | 1289 | int alignBits = -1; |
1065 | if (filterMode.Id == k_Delta || filterMode.Delta != 0) | ||
1066 | { | ||
1067 | if (filterMode.Delta == 1) alignBits = 0; | ||
1068 | else if (filterMode.Delta == 2) alignBits = 1; | ||
1069 | else if (filterMode.Delta == 4) alignBits = 2; | ||
1070 | else if (filterMode.Delta == 8) alignBits = 3; | ||
1071 | else if (filterMode.Delta == 16) alignBits = 4; | ||
1072 | } | ||
1073 | else | ||
1074 | { | 1290 | { |
1075 | // alignBits = GetAlignForFilterMethod(filterMode.Id); | 1291 | const UInt32 delta = filterMode.Delta; |
1292 | if (delta == 0 || delta > 16) | ||
1293 | { | ||
1294 | // if (delta == 0) alignBits = GetAlignForFilterMethod(filterMode.Id); | ||
1295 | } | ||
1296 | else if ((delta & ((1 << 4) - 1)) == 0) alignBits = 4; | ||
1297 | else if ((delta & ((1 << 3) - 1)) == 0) alignBits = 3; | ||
1298 | else if ((delta & ((1 << 2) - 1)) == 0) alignBits = 2; | ||
1299 | else if ((delta & ((1 << 1) - 1)) == 0) alignBits = 1; | ||
1300 | // else alignBits = 0; | ||
1301 | /* alignBits=0 is default mode for lzma/lzma2. | ||
1302 | So we don't set alignBits=0 here. */ | ||
1076 | } | 1303 | } |
1077 | 1304 | if (res == S_OK && alignBits > 0) | |
1078 | if (res == S_OK && alignBits >= 0) | ||
1079 | { | 1305 | { |
1080 | unsigned nextCoder = 1; | 1306 | unsigned nextCoder = 1; |
1081 | if (!mode.Bonds.IsEmpty()) | 1307 | if (!mode.Bonds.IsEmpty()) |
@@ -1135,13 +1361,13 @@ static void UpdateItem_To_FileItem(const CUpdateItem &ui, | |||
1135 | 1361 | ||
1136 | 1362 | ||
1137 | 1363 | ||
1138 | class CRepackInStreamWithSizes: | 1364 | Z7_CLASS_IMP_COM_2( |
1139 | public ISequentialInStream, | 1365 | CRepackInStreamWithSizes |
1140 | public ICompressGetSubStreamSize, | 1366 | , ISequentialInStream |
1141 | public CMyUnknownImp | 1367 | , ICompressGetSubStreamSize |
1142 | { | 1368 | ) |
1143 | CMyComPtr<ISequentialInStream> _stream; | 1369 | CMyComPtr<ISequentialInStream> _stream; |
1144 | // UInt64 _size; | 1370 | UInt64 _size; |
1145 | const CBoolVector *_extractStatuses; | 1371 | const CBoolVector *_extractStatuses; |
1146 | UInt32 _startIndex; | 1372 | UInt32 _startIndex; |
1147 | public: | 1373 | public: |
@@ -1151,37 +1377,28 @@ public: | |||
1151 | { | 1377 | { |
1152 | _startIndex = startIndex; | 1378 | _startIndex = startIndex; |
1153 | _extractStatuses = extractStatuses; | 1379 | _extractStatuses = extractStatuses; |
1154 | // _size = 0; | 1380 | _size = 0; |
1155 | _stream = stream; | 1381 | _stream = stream; |
1156 | } | 1382 | } |
1157 | // UInt64 GetSize() const { return _size; } | 1383 | UInt64 GetSize() const { return _size; } |
1158 | |||
1159 | MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize) | ||
1160 | |||
1161 | STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); | ||
1162 | |||
1163 | STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); | ||
1164 | }; | 1384 | }; |
1165 | 1385 | ||
1166 | STDMETHODIMP CRepackInStreamWithSizes::Read(void *data, UInt32 size, UInt32 *processedSize) | 1386 | Z7_COM7F_IMF(CRepackInStreamWithSizes::Read(void *data, UInt32 size, UInt32 *processedSize)) |
1167 | { | 1387 | { |
1168 | return _stream->Read(data, size, processedSize); | ||
1169 | /* | ||
1170 | UInt32 realProcessedSize; | 1388 | UInt32 realProcessedSize; |
1171 | HRESULT result = _stream->Read(data, size, &realProcessedSize); | 1389 | const HRESULT result = _stream->Read(data, size, &realProcessedSize); |
1172 | _size += realProcessedSize; | 1390 | _size += realProcessedSize; |
1173 | if (processedSize) | 1391 | if (processedSize) |
1174 | *processedSize = realProcessedSize; | 1392 | *processedSize = realProcessedSize; |
1175 | return result; | 1393 | return result; |
1176 | */ | ||
1177 | } | 1394 | } |
1178 | 1395 | ||
1179 | STDMETHODIMP CRepackInStreamWithSizes::GetSubStreamSize(UInt64 subStream, UInt64 *value) | 1396 | Z7_COM7F_IMF(CRepackInStreamWithSizes::GetSubStreamSize(UInt64 subStream, UInt64 *value)) |
1180 | { | 1397 | { |
1181 | *value = 0; | 1398 | *value = 0; |
1182 | if (subStream >= _extractStatuses->Size()) | 1399 | if (subStream >= _extractStatuses->Size()) |
1183 | return S_FALSE; // E_FAIL; | 1400 | return S_FALSE; // E_FAIL; |
1184 | unsigned index = (unsigned)subStream; | 1401 | const unsigned index = (unsigned)subStream; |
1185 | if ((*_extractStatuses)[index]) | 1402 | if ((*_extractStatuses)[index]) |
1186 | { | 1403 | { |
1187 | const CFileItem &fi = _db->Files[_startIndex + index]; | 1404 | const CFileItem &fi = _db->Files[_startIndex + index]; |
@@ -1212,7 +1429,7 @@ protected: | |||
1212 | public: | 1429 | public: |
1213 | const CDbEx *_db; | 1430 | const CDbEx *_db; |
1214 | CMyComPtr<IArchiveUpdateCallbackFile> _opCallback; | 1431 | CMyComPtr<IArchiveUpdateCallbackFile> _opCallback; |
1215 | CMyComPtr<IArchiveExtractCallbackMessage> _extractCallback; | 1432 | CMyComPtr<IArchiveExtractCallbackMessage2> _extractCallback; |
1216 | 1433 | ||
1217 | HRESULT Init(UInt32 startIndex, const CBoolVector *extractStatuses); | 1434 | HRESULT Init(UInt32 startIndex, const CBoolVector *extractStatuses); |
1218 | HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; } | 1435 | HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; } |
@@ -1241,7 +1458,7 @@ HRESULT CRepackStreamBase::OpenFile() | |||
1241 | NEventIndexType::kInArcIndex, arcIndex, | 1458 | NEventIndexType::kInArcIndex, arcIndex, |
1242 | _needWrite ? | 1459 | _needWrite ? |
1243 | NUpdateNotifyOp::kRepack : | 1460 | NUpdateNotifyOp::kRepack : |
1244 | NUpdateNotifyOp::kSkip)); | 1461 | NUpdateNotifyOp::kSkip)) |
1245 | } | 1462 | } |
1246 | 1463 | ||
1247 | _crc = CRC_INIT_VAL; | 1464 | _crc = CRC_INIT_VAL; |
@@ -1267,7 +1484,7 @@ HRESULT CRepackStreamBase::CloseFile() | |||
1267 | { | 1484 | { |
1268 | RINOK(_extractCallback->ReportExtractResult( | 1485 | RINOK(_extractCallback->ReportExtractResult( |
1269 | NEventIndexType::kInArcIndex, arcIndex, | 1486 | NEventIndexType::kInArcIndex, arcIndex, |
1270 | NExtract::NOperationResult::kCRCError)); | 1487 | NExtract::NOperationResult::kCRCError)) |
1271 | } | 1488 | } |
1272 | // return S_FALSE; | 1489 | // return S_FALSE; |
1273 | return k_My_HRESULT_CRC_ERROR; | 1490 | return k_My_HRESULT_CRC_ERROR; |
@@ -1277,30 +1494,28 @@ HRESULT CRepackStreamBase::ProcessEmptyFiles() | |||
1277 | { | 1494 | { |
1278 | while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0) | 1495 | while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0) |
1279 | { | 1496 | { |
1280 | RINOK(OpenFile()); | 1497 | RINOK(OpenFile()) |
1281 | RINOK(CloseFile()); | 1498 | RINOK(CloseFile()) |
1282 | } | 1499 | } |
1283 | return S_OK; | 1500 | return S_OK; |
1284 | } | 1501 | } |
1285 | 1502 | ||
1286 | 1503 | ||
1287 | 1504 | ||
1288 | #ifndef _7ZIP_ST | 1505 | #ifndef Z7_ST |
1289 | 1506 | ||
1290 | class CFolderOutStream2: | 1507 | class CFolderOutStream2 Z7_final: |
1291 | public CRepackStreamBase, | 1508 | public CRepackStreamBase, |
1292 | public ISequentialOutStream, | 1509 | public ISequentialOutStream, |
1293 | public CMyUnknownImp | 1510 | public CMyUnknownImp |
1294 | { | 1511 | { |
1512 | Z7_COM_UNKNOWN_IMP_0 | ||
1513 | Z7_IFACE_COM7_IMP(ISequentialOutStream) | ||
1295 | public: | 1514 | public: |
1296 | CMyComPtr<ISequentialOutStream> _stream; | 1515 | CMyComPtr<ISequentialOutStream> _stream; |
1297 | |||
1298 | MY_UNKNOWN_IMP | ||
1299 | |||
1300 | STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); | ||
1301 | }; | 1516 | }; |
1302 | 1517 | ||
1303 | STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize) | 1518 | Z7_COM7F_IMF(CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize)) |
1304 | { | 1519 | { |
1305 | if (processedSize) | 1520 | if (processedSize) |
1306 | *processedSize = 0; | 1521 | *processedSize = 0; |
@@ -1322,22 +1537,22 @@ STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *pro | |||
1322 | _rem -= cur; | 1537 | _rem -= cur; |
1323 | if (_rem == 0) | 1538 | if (_rem == 0) |
1324 | { | 1539 | { |
1325 | RINOK(CloseFile()); | 1540 | RINOK(CloseFile()) |
1326 | RINOK(ProcessEmptyFiles()); | 1541 | RINOK(ProcessEmptyFiles()) |
1327 | } | 1542 | } |
1328 | RINOK(result); | 1543 | RINOK(result) |
1329 | if (cur == 0) | 1544 | if (cur == 0) |
1330 | break; | 1545 | break; |
1331 | continue; | 1546 | continue; |
1332 | } | 1547 | } |
1333 | 1548 | ||
1334 | RINOK(ProcessEmptyFiles()); | 1549 | RINOK(ProcessEmptyFiles()) |
1335 | if (_currentIndex == _extractStatuses->Size()) | 1550 | if (_currentIndex == _extractStatuses->Size()) |
1336 | { | 1551 | { |
1337 | // we don't support write cut here | 1552 | // we don't support write cut here |
1338 | return E_FAIL; | 1553 | return E_FAIL; |
1339 | } | 1554 | } |
1340 | RINOK(OpenFile()); | 1555 | RINOK(OpenFile()) |
1341 | } | 1556 | } |
1342 | 1557 | ||
1343 | return S_OK; | 1558 | return S_OK; |
@@ -1349,18 +1564,19 @@ STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *pro | |||
1349 | 1564 | ||
1350 | static const UInt32 kTempBufSize = 1 << 16; | 1565 | static const UInt32 kTempBufSize = 1 << 16; |
1351 | 1566 | ||
1352 | class CFolderInStream2: | 1567 | class CFolderInStream2 Z7_final: |
1353 | public CRepackStreamBase, | 1568 | public CRepackStreamBase, |
1354 | public ISequentialInStream, | 1569 | public ISequentialInStream, |
1355 | public CMyUnknownImp | 1570 | public CMyUnknownImp |
1356 | { | 1571 | { |
1572 | Z7_COM_UNKNOWN_IMP_0 | ||
1573 | Z7_IFACE_COM7_IMP(ISequentialInStream) | ||
1574 | |||
1357 | Byte *_buf; | 1575 | Byte *_buf; |
1358 | public: | 1576 | public: |
1359 | CMyComPtr<ISequentialInStream> _inStream; | 1577 | CMyComPtr<ISequentialInStream> _inStream; |
1360 | HRESULT Result; | 1578 | HRESULT Result; |
1361 | 1579 | ||
1362 | MY_UNKNOWN_IMP | ||
1363 | |||
1364 | CFolderInStream2(): | 1580 | CFolderInStream2(): |
1365 | Result(S_OK) | 1581 | Result(S_OK) |
1366 | { | 1582 | { |
@@ -1373,10 +1589,9 @@ public: | |||
1373 | } | 1589 | } |
1374 | 1590 | ||
1375 | void Init() { Result = S_OK; } | 1591 | void Init() { Result = S_OK; } |
1376 | STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); | ||
1377 | }; | 1592 | }; |
1378 | 1593 | ||
1379 | STDMETHODIMP CFolderInStream2::Read(void *data, UInt32 size, UInt32 *processedSize) | 1594 | Z7_COM7F_IMF(CFolderInStream2::Read(void *data, UInt32 size, UInt32 *processedSize)) |
1380 | { | 1595 | { |
1381 | if (processedSize) | 1596 | if (processedSize) |
1382 | *processedSize = 0; | 1597 | *processedSize = 0; |
@@ -1397,7 +1612,7 @@ STDMETHODIMP CFolderInStream2::Read(void *data, UInt32 size, UInt32 *processedSi | |||
1397 | cur = kTempBufSize; | 1612 | cur = kTempBufSize; |
1398 | } | 1613 | } |
1399 | 1614 | ||
1400 | HRESULT result = _inStream->Read(buf, cur, &cur); | 1615 | const HRESULT result = _inStream->Read(buf, cur, &cur); |
1401 | _crc = CrcUpdate(_crc, buf, cur); | 1616 | _crc = CrcUpdate(_crc, buf, cur); |
1402 | _rem -= cur; | 1617 | _rem -= cur; |
1403 | 1618 | ||
@@ -1414,11 +1629,11 @@ STDMETHODIMP CFolderInStream2::Read(void *data, UInt32 size, UInt32 *processedSi | |||
1414 | 1629 | ||
1415 | if (_rem == 0) | 1630 | if (_rem == 0) |
1416 | { | 1631 | { |
1417 | RINOK(CloseFile()); | 1632 | RINOK(CloseFile()) |
1418 | RINOK(ProcessEmptyFiles()); | 1633 | RINOK(ProcessEmptyFiles()) |
1419 | } | 1634 | } |
1420 | 1635 | ||
1421 | RINOK(result); | 1636 | RINOK(result) |
1422 | 1637 | ||
1423 | if (cur == 0) | 1638 | if (cur == 0) |
1424 | return E_FAIL; | 1639 | return E_FAIL; |
@@ -1426,20 +1641,20 @@ STDMETHODIMP CFolderInStream2::Read(void *data, UInt32 size, UInt32 *processedSi | |||
1426 | continue; | 1641 | continue; |
1427 | } | 1642 | } |
1428 | 1643 | ||
1429 | RINOK(ProcessEmptyFiles()); | 1644 | RINOK(ProcessEmptyFiles()) |
1430 | if (_currentIndex == _extractStatuses->Size()) | 1645 | if (_currentIndex == _extractStatuses->Size()) |
1431 | { | 1646 | { |
1432 | return S_OK; | 1647 | return S_OK; |
1433 | } | 1648 | } |
1434 | RINOK(OpenFile()); | 1649 | RINOK(OpenFile()) |
1435 | } | 1650 | } |
1436 | 1651 | ||
1437 | return S_OK; | 1652 | return S_OK; |
1438 | } | 1653 | } |
1439 | 1654 | ||
1440 | 1655 | ||
1441 | class CThreadDecoder | 1656 | class CThreadDecoder Z7_final |
1442 | #ifndef _7ZIP_ST | 1657 | #ifndef Z7_ST |
1443 | : public CVirtThread | 1658 | : public CVirtThread |
1444 | #endif | 1659 | #endif |
1445 | { | 1660 | { |
@@ -1449,7 +1664,7 @@ public: | |||
1449 | CThreadDecoder(bool multiThreadMixer): | 1664 | CThreadDecoder(bool multiThreadMixer): |
1450 | Decoder(multiThreadMixer) | 1665 | Decoder(multiThreadMixer) |
1451 | { | 1666 | { |
1452 | #ifndef _7ZIP_ST | 1667 | #ifndef Z7_ST |
1453 | if (multiThreadMixer) | 1668 | if (multiThreadMixer) |
1454 | { | 1669 | { |
1455 | MtMode = false; | 1670 | MtMode = false; |
@@ -1463,7 +1678,7 @@ public: | |||
1463 | // send_UnpackSize = false; | 1678 | // send_UnpackSize = false; |
1464 | } | 1679 | } |
1465 | 1680 | ||
1466 | #ifndef _7ZIP_ST | 1681 | #ifndef Z7_ST |
1467 | 1682 | ||
1468 | bool dataAfterEnd_Error; | 1683 | bool dataAfterEnd_Error; |
1469 | HRESULT Result; | 1684 | HRESULT Result; |
@@ -1479,31 +1694,39 @@ public: | |||
1479 | // bool send_UnpackSize; | 1694 | // bool send_UnpackSize; |
1480 | // UInt64 UnpackSize; | 1695 | // UInt64 UnpackSize; |
1481 | 1696 | ||
1482 | #ifndef _NO_CRYPTO | 1697 | #ifndef Z7_NO_CRYPTO |
1483 | CMyComPtr<ICryptoGetTextPassword> getTextPassword; | 1698 | CMyComPtr<ICryptoGetTextPassword> getTextPassword; |
1484 | #endif | 1699 | #endif |
1485 | 1700 | ||
1486 | DECL_EXTERNAL_CODECS_LOC_VARS2; | 1701 | DECL_EXTERNAL_CODECS_LOC_VARS_DECL |
1487 | 1702 | ||
1488 | #ifndef _7ZIP_ST | 1703 | #ifndef Z7_ST |
1489 | bool MtMode; | 1704 | bool MtMode; |
1490 | UInt32 NumThreads; | 1705 | UInt32 NumThreads; |
1491 | #endif | 1706 | #endif |
1492 | 1707 | ||
1493 | 1708 | ||
1494 | ~CThreadDecoder() { CVirtThread::WaitThreadFinish(); } | 1709 | ~CThreadDecoder() Z7_DESTRUCTOR_override |
1495 | virtual void Execute(); | 1710 | { |
1711 | /* WaitThreadFinish() will be called in ~CVirtThread(). | ||
1712 | But we need WaitThreadFinish() call before | ||
1713 | destructors of this class members. | ||
1714 | */ | ||
1715 | CVirtThread::WaitThreadFinish(); | ||
1716 | } | ||
1717 | private: | ||
1718 | virtual void Execute() Z7_override; | ||
1496 | 1719 | ||
1497 | #endif | 1720 | #endif |
1498 | }; | 1721 | }; |
1499 | 1722 | ||
1500 | #ifndef _7ZIP_ST | 1723 | #ifndef Z7_ST |
1501 | 1724 | ||
1502 | void CThreadDecoder::Execute() | 1725 | void CThreadDecoder::Execute() |
1503 | { | 1726 | { |
1504 | try | 1727 | try |
1505 | { | 1728 | { |
1506 | #ifndef _NO_CRYPTO | 1729 | #ifndef Z7_NO_CRYPTO |
1507 | bool isEncrypted = false; | 1730 | bool isEncrypted = false; |
1508 | bool passwordIsDefined = false; | 1731 | bool passwordIsDefined = false; |
1509 | UString password; | 1732 | UString password; |
@@ -1526,8 +1749,8 @@ void CThreadDecoder::Execute() | |||
1526 | NULL // *inStreamMainRes | 1749 | NULL // *inStreamMainRes |
1527 | , dataAfterEnd_Error | 1750 | , dataAfterEnd_Error |
1528 | 1751 | ||
1529 | _7Z_DECODER_CRYPRO_VARS | 1752 | Z7_7Z_DECODER_CRYPRO_VARS |
1530 | #ifndef _7ZIP_ST | 1753 | #ifndef Z7_ST |
1531 | , MtMode, NumThreads, | 1754 | , MtMode, NumThreads, |
1532 | 0 // MemUsage | 1755 | 0 // MemUsage |
1533 | #endif | 1756 | #endif |
@@ -1548,20 +1771,17 @@ void CThreadDecoder::Execute() | |||
1548 | 1771 | ||
1549 | #endif | 1772 | #endif |
1550 | 1773 | ||
1551 | #ifndef _NO_CRYPTO | 1774 | #ifndef Z7_NO_CRYPTO |
1552 | 1775 | ||
1553 | class CCryptoGetTextPassword: | 1776 | Z7_CLASS_IMP_NOQIB_1( |
1554 | public ICryptoGetTextPassword, | 1777 | CCryptoGetTextPassword |
1555 | public CMyUnknownImp | 1778 | , ICryptoGetTextPassword |
1556 | { | 1779 | ) |
1557 | public: | 1780 | public: |
1558 | UString Password; | 1781 | UString Password; |
1559 | |||
1560 | MY_UNKNOWN_IMP | ||
1561 | STDMETHOD(CryptoGetTextPassword)(BSTR *password); | ||
1562 | }; | 1782 | }; |
1563 | 1783 | ||
1564 | STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password) | 1784 | Z7_COM7F_IMF(CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password)) |
1565 | { | 1785 | { |
1566 | return StringToBstr(Password, password); | 1786 | return StringToBstr(Password, password); |
1567 | } | 1787 | } |
@@ -1585,58 +1805,70 @@ HRESULT Update( | |||
1585 | DECL_EXTERNAL_CODECS_LOC_VARS | 1805 | DECL_EXTERNAL_CODECS_LOC_VARS |
1586 | IInStream *inStream, | 1806 | IInStream *inStream, |
1587 | const CDbEx *db, | 1807 | const CDbEx *db, |
1588 | const CObjectVector<CUpdateItem> &updateItems, | 1808 | CObjectVector<CUpdateItem> &updateItems, |
1589 | // const CObjectVector<CTreeFolder> &treeFolders, | 1809 | // const CObjectVector<CTreeFolder> &treeFolders, |
1590 | // const CUniqBlocks &secureBlocks, | 1810 | // const CUniqBlocks &secureBlocks, |
1591 | COutArchive &archive, | ||
1592 | CArchiveDatabaseOut &newDatabase, | ||
1593 | ISequentialOutStream *seqOutStream, | 1811 | ISequentialOutStream *seqOutStream, |
1594 | IArchiveUpdateCallback *updateCallback, | 1812 | IArchiveUpdateCallback *updateCallback, |
1595 | const CUpdateOptions &options | 1813 | const CUpdateOptions &options) |
1596 | #ifndef _NO_CRYPTO | ||
1597 | , ICryptoGetTextPassword *getDecoderPassword | ||
1598 | #endif | ||
1599 | ) | ||
1600 | { | 1814 | { |
1601 | UInt64 numSolidFiles = options.NumSolidFiles; | 1815 | UInt64 numSolidFiles = options.NumSolidFiles; |
1602 | if (numSolidFiles == 0) | 1816 | if (numSolidFiles == 0) |
1603 | numSolidFiles = 1; | 1817 | numSolidFiles = 1; |
1604 | 1818 | ||
1605 | CMyComPtr<IArchiveUpdateCallbackFile> opCallback; | 1819 | Z7_DECL_CMyComPtr_QI_FROM( |
1606 | updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); | 1820 | IArchiveUpdateCallbackFile, |
1821 | opCallback, updateCallback) | ||
1607 | 1822 | ||
1608 | CMyComPtr<IArchiveExtractCallbackMessage> extractCallback; | 1823 | Z7_DECL_CMyComPtr_QI_FROM( |
1609 | updateCallback->QueryInterface(IID_IArchiveExtractCallbackMessage, (void **)&extractCallback); | 1824 | IArchiveExtractCallbackMessage2, |
1825 | extractCallback, updateCallback) | ||
1610 | 1826 | ||
1611 | /* | 1827 | /* |
1612 | CMyComPtr<IArchiveUpdateCallbackArcProp> reportArcProp; | 1828 | Z7_DECL_CMyComPtr_QI_FROM( |
1613 | updateCallback->QueryInterface(IID_IArchiveUpdateCallbackArcProp, (void **)&reportArcProp); | 1829 | IArchiveUpdateCallbackArcProp, |
1830 | reportArcProp, updateCallback) | ||
1614 | */ | 1831 | */ |
1615 | 1832 | ||
1616 | // size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes(); | 1833 | // size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes(); |
1617 | 1834 | ||
1618 | /* | 1835 | CMyComPtr<IStreamSetRestriction> v_StreamSetRestriction; |
1619 | CMyComPtr<IOutStream> outStream; | ||
1620 | RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream)); | ||
1621 | if (!outStream) | ||
1622 | return E_NOTIMPL; | ||
1623 | */ | ||
1624 | |||
1625 | UInt64 startBlockSize = db ? db->ArcInfo.StartPosition: 0; | ||
1626 | if (startBlockSize > 0 && !options.RemoveSfxBlock) | ||
1627 | { | 1836 | { |
1628 | RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL)); | 1837 | Z7_DECL_CMyComPtr_QI_FROM( |
1838 | IOutStream, | ||
1839 | outStream, seqOutStream) | ||
1840 | if (!outStream) | ||
1841 | return E_NOTIMPL; | ||
1842 | const UInt64 sfxBlockSize = (db && !options.RemoveSfxBlock) ? | ||
1843 | db->ArcInfo.StartPosition: 0; | ||
1844 | seqOutStream->QueryInterface(IID_IStreamSetRestriction, (void **)&v_StreamSetRestriction); | ||
1845 | if (v_StreamSetRestriction) | ||
1846 | { | ||
1847 | UInt64 offset = 0; | ||
1848 | RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &offset)) | ||
1849 | RINOK(v_StreamSetRestriction->SetRestriction( | ||
1850 | outStream ? offset + sfxBlockSize : 0, | ||
1851 | outStream ? offset + sfxBlockSize + k_StartHeadersRewriteSize : 0)) | ||
1852 | } | ||
1853 | outStream.Release(); | ||
1854 | if (sfxBlockSize != 0) | ||
1855 | { | ||
1856 | RINOK(WriteRange(inStream, seqOutStream, 0, sfxBlockSize, NULL)) | ||
1857 | } | ||
1629 | } | 1858 | } |
1630 | 1859 | ||
1631 | CIntArr fileIndexToUpdateIndexMap; | 1860 | CIntArr fileIndexToUpdateIndexMap; |
1632 | UInt64 complexity = 0; | 1861 | UInt64 complexity = 0; |
1633 | UInt64 inSizeForReduce2 = 0; | 1862 | UInt64 inSizeForReduce2 = 0; |
1863 | |||
1864 | #ifndef Z7_NO_CRYPTO | ||
1634 | bool needEncryptedRepack = false; | 1865 | bool needEncryptedRepack = false; |
1866 | #endif | ||
1635 | 1867 | ||
1636 | CRecordVector<CFilterMode2> filters; | 1868 | CRecordVector<CFilterMode2> filters; |
1637 | CObjectVector<CSolidGroup> groups; | 1869 | CObjectVector<CSolidGroup> groups; |
1638 | 1870 | ||
1639 | #ifndef _7ZIP_ST | 1871 | #ifndef Z7_ST |
1640 | bool thereAreRepacks = false; | 1872 | bool thereAreRepacks = false; |
1641 | #endif | 1873 | #endif |
1642 | 1874 | ||
@@ -1646,11 +1878,15 @@ HRESULT Update( | |||
1646 | const CCompressionMethodMode &method = *options.Method; | 1878 | const CCompressionMethodMode &method = *options.Method; |
1647 | 1879 | ||
1648 | FOR_VECTOR (i, method.Methods) | 1880 | FOR_VECTOR (i, method.Methods) |
1881 | { | ||
1882 | /* IsFilterMethod() knows only built-in codecs | ||
1883 | FIXME: we should check IsFilter status for external filters too */ | ||
1649 | if (IsFilterMethod(method.Methods[i].Id)) | 1884 | if (IsFilterMethod(method.Methods[i].Id)) |
1650 | { | 1885 | { |
1651 | useFilters = false; | 1886 | useFilters = false; |
1652 | break; | 1887 | break; |
1653 | } | 1888 | } |
1889 | } | ||
1654 | } | 1890 | } |
1655 | 1891 | ||
1656 | if (db) | 1892 | if (db) |
@@ -1672,7 +1908,7 @@ HRESULT Update( | |||
1672 | { | 1908 | { |
1673 | CNum indexInFolder = 0; | 1909 | CNum indexInFolder = 0; |
1674 | CNum numCopyItems = 0; | 1910 | CNum numCopyItems = 0; |
1675 | CNum numUnpackStreams = db->NumUnpackStreamsVector[i]; | 1911 | const CNum numUnpackStreams = db->NumUnpackStreamsVector[i]; |
1676 | UInt64 repackSize = 0; | 1912 | UInt64 repackSize = 0; |
1677 | 1913 | ||
1678 | for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++) | 1914 | for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++) |
@@ -1684,7 +1920,7 @@ HRESULT Update( | |||
1684 | if (file.HasStream) | 1920 | if (file.HasStream) |
1685 | { | 1921 | { |
1686 | indexInFolder++; | 1922 | indexInFolder++; |
1687 | int updateIndex = fileIndexToUpdateIndexMap[fi]; | 1923 | const int updateIndex = fileIndexToUpdateIndexMap[fi]; |
1688 | if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData) | 1924 | if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData) |
1689 | { | 1925 | { |
1690 | numCopyItems++; | 1926 | numCopyItems++; |
@@ -1702,11 +1938,13 @@ HRESULT Update( | |||
1702 | CFolderEx f; | 1938 | CFolderEx f; |
1703 | db->ParseFolderEx(i, f); | 1939 | db->ParseFolderEx(i, f); |
1704 | 1940 | ||
1941 | #ifndef Z7_NO_CRYPTO | ||
1705 | const bool isEncrypted = f.IsEncrypted(); | 1942 | const bool isEncrypted = f.IsEncrypted(); |
1943 | #endif | ||
1706 | const bool needCopy = (numCopyItems == numUnpackStreams); | 1944 | const bool needCopy = (numCopyItems == numUnpackStreams); |
1707 | const bool extractFilter = (useFilters || needCopy); | 1945 | const bool extractFilter = (useFilters || needCopy); |
1708 | 1946 | ||
1709 | unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f, extractFilter); | 1947 | const unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f, extractFilter); |
1710 | 1948 | ||
1711 | while (groupIndex >= groups.Size()) | 1949 | while (groupIndex >= groups.Size()) |
1712 | groups.AddNew(); | 1950 | groups.AddNew(); |
@@ -1717,14 +1955,16 @@ HRESULT Update( | |||
1717 | complexity += db->GetFolderFullPackSize(i); | 1955 | complexity += db->GetFolderFullPackSize(i); |
1718 | else | 1956 | else |
1719 | { | 1957 | { |
1720 | #ifndef _7ZIP_ST | 1958 | #ifndef Z7_ST |
1721 | thereAreRepacks = true; | 1959 | thereAreRepacks = true; |
1722 | #endif | 1960 | #endif |
1723 | complexity += repackSize; | 1961 | complexity += repackSize; |
1724 | if (inSizeForReduce2 < repackSize) | 1962 | if (inSizeForReduce2 < repackSize) |
1725 | inSizeForReduce2 = repackSize; | 1963 | inSizeForReduce2 = repackSize; |
1964 | #ifndef Z7_NO_CRYPTO | ||
1726 | if (isEncrypted) | 1965 | if (isEncrypted) |
1727 | needEncryptedRepack = true; | 1966 | needEncryptedRepack = true; |
1967 | #endif | ||
1728 | } | 1968 | } |
1729 | } | 1969 | } |
1730 | } | 1970 | } |
@@ -1749,13 +1989,13 @@ HRESULT Update( | |||
1749 | if (inSizeForReduce < inSizeForReduce2) | 1989 | if (inSizeForReduce < inSizeForReduce2) |
1750 | inSizeForReduce = inSizeForReduce2; | 1990 | inSizeForReduce = inSizeForReduce2; |
1751 | 1991 | ||
1752 | RINOK(updateCallback->SetTotal(complexity)); | 1992 | RINOK(updateCallback->SetTotal(complexity)) |
1753 | 1993 | ||
1754 | CLocalProgress *lps = new CLocalProgress; | 1994 | CLocalProgress *lps = new CLocalProgress; |
1755 | CMyComPtr<ICompressProgressInfo> progress = lps; | 1995 | CMyComPtr<ICompressProgressInfo> progress = lps; |
1756 | lps->Init(updateCallback, true); | 1996 | lps->Init(updateCallback, true); |
1757 | 1997 | ||
1758 | #ifndef _7ZIP_ST | 1998 | #ifndef Z7_ST |
1759 | 1999 | ||
1760 | CStreamBinder sb; | 2000 | CStreamBinder sb; |
1761 | /* | 2001 | /* |
@@ -1769,13 +2009,13 @@ HRESULT Update( | |||
1769 | 2009 | ||
1770 | CThreadDecoder threadDecoder(options.MultiThreadMixer); | 2010 | CThreadDecoder threadDecoder(options.MultiThreadMixer); |
1771 | 2011 | ||
1772 | #ifndef _7ZIP_ST | 2012 | #ifndef Z7_ST |
1773 | if (options.MultiThreadMixer && thereAreRepacks) | 2013 | if (options.MultiThreadMixer && thereAreRepacks) |
1774 | { | 2014 | { |
1775 | #ifdef EXTERNAL_CODECS | 2015 | #ifdef Z7_EXTERNAL_CODECS |
1776 | threadDecoder.__externalCodecs = __externalCodecs; | 2016 | threadDecoder._externalCodecs = _externalCodecs; |
1777 | #endif | 2017 | #endif |
1778 | WRes wres = threadDecoder.Create(); | 2018 | const WRes wres = threadDecoder.Create(); |
1779 | if (wres != 0) | 2019 | if (wres != 0) |
1780 | return HRESULT_FROM_WIN32(wres); | 2020 | return HRESULT_FROM_WIN32(wres); |
1781 | } | 2021 | } |
@@ -1784,22 +2024,23 @@ HRESULT Update( | |||
1784 | { | 2024 | { |
1785 | CAnalysis analysis; | 2025 | CAnalysis analysis; |
1786 | // analysis.Need_ATime = options.Need_ATime; | 2026 | // analysis.Need_ATime = options.Need_ATime; |
1787 | if (options.AnalysisLevel == 0) | 2027 | int analysisLevel = options.AnalysisLevel; |
1788 | { | 2028 | // (analysisLevel < 0) means default level (5) |
1789 | analysis.ParseWav = false; | 2029 | if (analysisLevel < 0) |
1790 | analysis.ParseExe = false; | 2030 | analysisLevel = 5; |
1791 | analysis.ParseAll = false; | 2031 | if (analysisLevel != 0) |
1792 | } | ||
1793 | else | ||
1794 | { | 2032 | { |
1795 | analysis.Callback = opCallback; | 2033 | analysis.Callback = opCallback; |
1796 | if (options.AnalysisLevel > 0) | 2034 | analysis.ParseWav = true; |
2035 | if (analysisLevel >= 5) | ||
1797 | { | 2036 | { |
1798 | analysis.ParseWav = true; | 2037 | analysis.ParseExe = true; |
1799 | if (options.AnalysisLevel >= 7) | 2038 | analysis.ParseExeUnix = true; |
2039 | // analysis.ParseNoExt = true; | ||
2040 | if (analysisLevel >= 7) | ||
1800 | { | 2041 | { |
1801 | analysis.ParseExe = true; | 2042 | analysis.ParseNoExt = true; |
1802 | if (options.AnalysisLevel >= 9) | 2043 | if (analysisLevel >= 9) |
1803 | analysis.ParseAll = true; | 2044 | analysis.ParseAll = true; |
1804 | } | 2045 | } |
1805 | } | 2046 | } |
@@ -1819,7 +2060,7 @@ HRESULT Update( | |||
1819 | if (useFilters) | 2060 | if (useFilters) |
1820 | { | 2061 | { |
1821 | // analysis.ATime_Defined = false; | 2062 | // analysis.ATime_Defined = false; |
1822 | RINOK(analysis.GetFilterGroup(i, ui, fm)); | 2063 | RINOK(analysis.GetFilterGroup(i, ui, fm)) |
1823 | /* | 2064 | /* |
1824 | if (analysis.ATime_Defined) | 2065 | if (analysis.ATime_Defined) |
1825 | { | 2066 | { |
@@ -1830,7 +2071,7 @@ HRESULT Update( | |||
1830 | } | 2071 | } |
1831 | fm.Encrypted = method.PasswordIsDefined; | 2072 | fm.Encrypted = method.PasswordIsDefined; |
1832 | 2073 | ||
1833 | unsigned groupIndex = GetGroup(filters, fm); | 2074 | const unsigned groupIndex = GetGroup(filters, fm); |
1834 | while (groupIndex >= groups.Size()) | 2075 | while (groupIndex >= groups.Size()) |
1835 | groups.AddNew(); | 2076 | groups.AddNew(); |
1836 | groups[groupIndex].Indices.Add(i); | 2077 | groups[groupIndex].Indices.Add(i); |
@@ -1838,7 +2079,7 @@ HRESULT Update( | |||
1838 | } | 2079 | } |
1839 | 2080 | ||
1840 | 2081 | ||
1841 | #ifndef _NO_CRYPTO | 2082 | #ifndef Z7_NO_CRYPTO |
1842 | 2083 | ||
1843 | CCryptoGetTextPassword *getPasswordSpec = NULL; | 2084 | CCryptoGetTextPassword *getPasswordSpec = NULL; |
1844 | CMyComPtr<ICryptoGetTextPassword> getTextPassword; | 2085 | CMyComPtr<ICryptoGetTextPassword> getTextPassword; |
@@ -1847,7 +2088,7 @@ HRESULT Update( | |||
1847 | getPasswordSpec = new CCryptoGetTextPassword; | 2088 | getPasswordSpec = new CCryptoGetTextPassword; |
1848 | getTextPassword = getPasswordSpec; | 2089 | getTextPassword = getPasswordSpec; |
1849 | 2090 | ||
1850 | #ifndef _7ZIP_ST | 2091 | #ifndef Z7_ST |
1851 | threadDecoder.getTextPassword = getPasswordSpec; | 2092 | threadDecoder.getTextPassword = getPasswordSpec; |
1852 | #endif | 2093 | #endif |
1853 | 2094 | ||
@@ -1855,10 +2096,13 @@ HRESULT Update( | |||
1855 | getPasswordSpec->Password = options.Method->Password; | 2096 | getPasswordSpec->Password = options.Method->Password; |
1856 | else | 2097 | else |
1857 | { | 2098 | { |
2099 | Z7_DECL_CMyComPtr_QI_FROM( | ||
2100 | ICryptoGetTextPassword, | ||
2101 | getDecoderPassword, updateCallback) | ||
1858 | if (!getDecoderPassword) | 2102 | if (!getDecoderPassword) |
1859 | return E_NOTIMPL; | 2103 | return E_NOTIMPL; |
1860 | CMyComBSTR password; | 2104 | CMyComBSTR password; |
1861 | RINOK(getDecoderPassword->CryptoGetTextPassword(&password)); | 2105 | RINOK(getDecoderPassword->CryptoGetTextPassword(&password)) |
1862 | if (password) | 2106 | if (password) |
1863 | getPasswordSpec->Password = password; | 2107 | getPasswordSpec->Password = password; |
1864 | } | 2108 | } |
@@ -1866,11 +2110,12 @@ HRESULT Update( | |||
1866 | 2110 | ||
1867 | #endif | 2111 | #endif |
1868 | 2112 | ||
1869 | |||
1870 | // ---------- Compress ---------- | 2113 | // ---------- Compress ---------- |
1871 | 2114 | ||
1872 | RINOK(archive.Create(seqOutStream, false)); | 2115 | COutArchive archive; |
1873 | RINOK(archive.SkipPrefixArchiveHeader()); | 2116 | CArchiveDatabaseOut newDatabase; |
2117 | |||
2118 | RINOK(archive.Create_and_WriteStartPrefix(seqOutStream)) | ||
1874 | 2119 | ||
1875 | /* | 2120 | /* |
1876 | CIntVector treeFolderToArcIndex; | 2121 | CIntVector treeFolderToArcIndex; |
@@ -1973,7 +2218,6 @@ HRESULT Update( | |||
1973 | 2218 | ||
1974 | { | 2219 | { |
1975 | // ---------- Sort Filters ---------- | 2220 | // ---------- Sort Filters ---------- |
1976 | |||
1977 | FOR_VECTOR (i, filters) | 2221 | FOR_VECTOR (i, filters) |
1978 | { | 2222 | { |
1979 | filters[i].GroupIndex = i; | 2223 | filters[i].GroupIndex = i; |
@@ -1987,22 +2231,22 @@ HRESULT Update( | |||
1987 | 2231 | ||
1988 | CCompressionMethodMode method = *options.Method; | 2232 | CCompressionMethodMode method = *options.Method; |
1989 | { | 2233 | { |
1990 | HRESULT res = MakeExeMethod(method, filterMode, | 2234 | const HRESULT res = MakeExeMethod(method, filterMode, |
1991 | #ifdef _7ZIP_ST | 2235 | #ifdef Z7_ST |
1992 | false | 2236 | false |
1993 | #else | 2237 | #else |
1994 | options.MaxFilter && options.MultiThreadMixer | 2238 | options.MaxFilter && options.MultiThreadMixer |
1995 | #endif | 2239 | #endif |
1996 | ); | 2240 | ); |
1997 | 2241 | ||
1998 | RINOK(res); | 2242 | RINOK(res) |
1999 | } | 2243 | } |
2000 | 2244 | ||
2001 | if (filterMode.Encrypted) | 2245 | if (filterMode.Encrypted) |
2002 | { | 2246 | { |
2003 | if (!method.PasswordIsDefined) | 2247 | if (!method.PasswordIsDefined) |
2004 | { | 2248 | { |
2005 | #ifndef _NO_CRYPTO | 2249 | #ifndef Z7_NO_CRYPTO |
2006 | if (getPasswordSpec) | 2250 | if (getPasswordSpec) |
2007 | method.Password = getPasswordSpec->Password; | 2251 | method.Password = getPasswordSpec->Password; |
2008 | #endif | 2252 | #endif |
@@ -2021,13 +2265,13 @@ HRESULT Update( | |||
2021 | 2265 | ||
2022 | const CSolidGroup &group = groups[filterMode.GroupIndex]; | 2266 | const CSolidGroup &group = groups[filterMode.GroupIndex]; |
2023 | 2267 | ||
2024 | FOR_VECTOR(folderRefIndex, group.folderRefs) | 2268 | FOR_VECTOR (folderRefIndex, group.folderRefs) |
2025 | { | 2269 | { |
2026 | const CFolderRepack &rep = group.folderRefs[folderRefIndex]; | 2270 | const CFolderRepack &rep = group.folderRefs[folderRefIndex]; |
2027 | 2271 | ||
2028 | unsigned folderIndex = rep.FolderIndex; | 2272 | const unsigned folderIndex = rep.FolderIndex; |
2029 | 2273 | ||
2030 | CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; | 2274 | const CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; |
2031 | 2275 | ||
2032 | if (rep.NumCopyFiles == numUnpackStreams) | 2276 | if (rep.NumCopyFiles == numUnpackStreams) |
2033 | { | 2277 | { |
@@ -2035,7 +2279,7 @@ HRESULT Update( | |||
2035 | { | 2279 | { |
2036 | RINOK(opCallback->ReportOperation( | 2280 | RINOK(opCallback->ReportOperation( |
2037 | NEventIndexType::kBlockIndex, (UInt32)folderIndex, | 2281 | NEventIndexType::kBlockIndex, (UInt32)folderIndex, |
2038 | NUpdateNotifyOp::kReplicate)); | 2282 | NUpdateNotifyOp::kReplicate)) |
2039 | 2283 | ||
2040 | // ---------- Copy old solid block ---------- | 2284 | // ---------- Copy old solid block ---------- |
2041 | { | 2285 | { |
@@ -2047,21 +2291,27 @@ HRESULT Update( | |||
2047 | indexInFolder++; | 2291 | indexInFolder++; |
2048 | RINOK(opCallback->ReportOperation( | 2292 | RINOK(opCallback->ReportOperation( |
2049 | NEventIndexType::kInArcIndex, (UInt32)fi, | 2293 | NEventIndexType::kInArcIndex, (UInt32)fi, |
2050 | NUpdateNotifyOp::kReplicate)); | 2294 | NUpdateNotifyOp::kReplicate)) |
2051 | } | 2295 | } |
2052 | } | 2296 | } |
2053 | } | 2297 | } |
2054 | } | 2298 | } |
2055 | 2299 | ||
2056 | UInt64 packSize = db->GetFolderFullPackSize(folderIndex); | 2300 | const UInt64 packSize = db->GetFolderFullPackSize(folderIndex); |
2057 | RINOK(WriteRange(inStream, archive.SeqStream, | 2301 | RINOK(WriteRange(inStream, archive.SeqStream, |
2058 | db->GetFolderStreamPos(folderIndex, 0), packSize, progress)); | 2302 | db->GetFolderStreamPos(folderIndex, 0), packSize, progress)) |
2059 | lps->ProgressOffset += packSize; | 2303 | lps->ProgressOffset += packSize; |
2060 | 2304 | ||
2305 | const unsigned folderIndex_New = newDatabase.Folders.Size(); | ||
2061 | CFolder &folder = newDatabase.Folders.AddNew(); | 2306 | CFolder &folder = newDatabase.Folders.AddNew(); |
2307 | // v23.01: we copy FolderCrc, if FolderCrc was used | ||
2308 | if (db->FolderCRCs.ValidAndDefined(folderIndex)) | ||
2309 | newDatabase.FolderUnpackCRCs.SetItem(folderIndex_New, | ||
2310 | true, db->FolderCRCs.Vals[folderIndex]); | ||
2311 | |||
2062 | db->ParseFolderInfo(folderIndex, folder); | 2312 | db->ParseFolderInfo(folderIndex, folder); |
2063 | CNum startIndex = db->FoStartPackStreamIndex[folderIndex]; | 2313 | const CNum startIndex = db->FoStartPackStreamIndex[folderIndex]; |
2064 | FOR_VECTOR(j, folder.PackStreams) | 2314 | FOR_VECTOR (j, folder.PackStreams) |
2065 | { | 2315 | { |
2066 | newDatabase.PackSizes.Add(db->GetStreamPackSize(startIndex + j)); | 2316 | newDatabase.PackSizes.Add(db->GetStreamPackSize(startIndex + j)); |
2067 | // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); | 2317 | // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); |
@@ -2069,7 +2319,7 @@ HRESULT Update( | |||
2069 | } | 2319 | } |
2070 | 2320 | ||
2071 | size_t indexStart = db->FoToCoderUnpackSizes[folderIndex]; | 2321 | size_t indexStart = db->FoToCoderUnpackSizes[folderIndex]; |
2072 | size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1]; | 2322 | const size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1]; |
2073 | for (; indexStart < indexEnd; indexStart++) | 2323 | for (; indexStart < indexEnd; indexStart++) |
2074 | newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]); | 2324 | newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]); |
2075 | } | 2325 | } |
@@ -2108,7 +2358,7 @@ HRESULT Update( | |||
2108 | if (file.HasStream) | 2358 | if (file.HasStream) |
2109 | { | 2359 | { |
2110 | indexInFolder++; | 2360 | indexInFolder++; |
2111 | int updateIndex = fileIndexToUpdateIndexMap[fi]; | 2361 | const int updateIndex = fileIndexToUpdateIndexMap[fi]; |
2112 | if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData) | 2362 | if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData) |
2113 | needExtract = true; | 2363 | needExtract = true; |
2114 | // decodeSize += file.Size; | 2364 | // decodeSize += file.Size; |
@@ -2130,7 +2380,6 @@ HRESULT Update( | |||
2130 | unsigned startPackIndex = newDatabase.PackSizes.Size(); | 2380 | unsigned startPackIndex = newDatabase.PackSizes.Size(); |
2131 | UInt64 curUnpackSize; | 2381 | UInt64 curUnpackSize; |
2132 | { | 2382 | { |
2133 | |||
2134 | CMyComPtr<ISequentialInStream> sbInStream; | 2383 | CMyComPtr<ISequentialInStream> sbInStream; |
2135 | CRepackStreamBase *repackBase; | 2384 | CRepackStreamBase *repackBase; |
2136 | CFolderInStream2 *FosSpec2 = NULL; | 2385 | CFolderInStream2 *FosSpec2 = NULL; |
@@ -2138,13 +2387,13 @@ HRESULT Update( | |||
2138 | CRepackInStreamWithSizes *inStreamSizeCountSpec = new CRepackInStreamWithSizes; | 2387 | CRepackInStreamWithSizes *inStreamSizeCountSpec = new CRepackInStreamWithSizes; |
2139 | CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; | 2388 | CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; |
2140 | { | 2389 | { |
2141 | #ifndef _7ZIP_ST | 2390 | #ifndef Z7_ST |
2142 | if (options.MultiThreadMixer) | 2391 | if (options.MultiThreadMixer) |
2143 | { | 2392 | { |
2144 | repackBase = threadDecoder.FosSpec; | 2393 | repackBase = threadDecoder.FosSpec; |
2145 | CMyComPtr<ISequentialOutStream> sbOutStream; | 2394 | CMyComPtr<ISequentialOutStream> sbOutStream; |
2146 | sb.CreateStreams2(sbInStream, sbOutStream); | 2395 | sb.CreateStreams2(sbInStream, sbOutStream); |
2147 | RINOK(sb.Create_ReInit()); | 2396 | RINOK(sb.Create_ReInit()) |
2148 | 2397 | ||
2149 | threadDecoder.FosSpec->_stream = sbOutStream; | 2398 | threadDecoder.FosSpec->_stream = sbOutStream; |
2150 | 2399 | ||
@@ -2164,7 +2413,7 @@ HRESULT Update( | |||
2164 | sbInStream = FosSpec2; | 2413 | sbInStream = FosSpec2; |
2165 | repackBase = FosSpec2; | 2414 | repackBase = FosSpec2; |
2166 | 2415 | ||
2167 | #ifndef _NO_CRYPTO | 2416 | #ifndef Z7_NO_CRYPTO |
2168 | bool isEncrypted = false; | 2417 | bool isEncrypted = false; |
2169 | bool passwordIsDefined = false; | 2418 | bool passwordIsDefined = false; |
2170 | UString password; | 2419 | UString password; |
@@ -2173,7 +2422,7 @@ HRESULT Update( | |||
2173 | CMyComPtr<ISequentialInStream> decodedStream; | 2422 | CMyComPtr<ISequentialInStream> decodedStream; |
2174 | bool dataAfterEnd_Error = false; | 2423 | bool dataAfterEnd_Error = false; |
2175 | 2424 | ||
2176 | HRESULT res = threadDecoder.Decoder.Decode( | 2425 | const HRESULT res = threadDecoder.Decoder.Decode( |
2177 | EXTERNAL_CODECS_LOC_VARS | 2426 | EXTERNAL_CODECS_LOC_VARS |
2178 | inStream, | 2427 | inStream, |
2179 | db->ArcInfo.DataStartPosition, // db->GetFolderStreamPos(folderIndex, 0);, | 2428 | db->ArcInfo.DataStartPosition, // db->GetFolderStreamPos(folderIndex, 0);, |
@@ -2187,15 +2436,15 @@ HRESULT Update( | |||
2187 | &decodedStream | 2436 | &decodedStream |
2188 | , dataAfterEnd_Error | 2437 | , dataAfterEnd_Error |
2189 | 2438 | ||
2190 | _7Z_DECODER_CRYPRO_VARS | 2439 | Z7_7Z_DECODER_CRYPRO_VARS |
2191 | #ifndef _7ZIP_ST | 2440 | #ifndef Z7_ST |
2192 | , false // mtMode | 2441 | , false // mtMode |
2193 | , 1 // numThreads | 2442 | , 1 // numThreads |
2194 | , 0 // memUsage | 2443 | , 0 // memUsage |
2195 | #endif | 2444 | #endif |
2196 | ); | 2445 | ); |
2197 | 2446 | ||
2198 | RINOK(res); | 2447 | RINOK(res) |
2199 | if (!decodedStream) | 2448 | if (!decodedStream) |
2200 | return E_FAIL; | 2449 | return E_FAIL; |
2201 | 2450 | ||
@@ -2207,12 +2456,12 @@ HRESULT Update( | |||
2207 | repackBase->_extractCallback = extractCallback; | 2456 | repackBase->_extractCallback = extractCallback; |
2208 | 2457 | ||
2209 | UInt32 startIndex = db->FolderStartFileIndex[folderIndex]; | 2458 | UInt32 startIndex = db->FolderStartFileIndex[folderIndex]; |
2210 | RINOK(repackBase->Init(startIndex, &extractStatuses)); | 2459 | RINOK(repackBase->Init(startIndex, &extractStatuses)) |
2211 | 2460 | ||
2212 | inStreamSizeCountSpec->_db = db; | 2461 | inStreamSizeCountSpec->_db = db; |
2213 | inStreamSizeCountSpec->Init(sbInStream, startIndex, &extractStatuses); | 2462 | inStreamSizeCountSpec->Init(sbInStream, startIndex, &extractStatuses); |
2214 | 2463 | ||
2215 | #ifndef _7ZIP_ST | 2464 | #ifndef Z7_ST |
2216 | if (options.MultiThreadMixer) | 2465 | if (options.MultiThreadMixer) |
2217 | { | 2466 | { |
2218 | WRes wres = threadDecoder.Start(); | 2467 | WRes wres = threadDecoder.Start(); |
@@ -2222,20 +2471,29 @@ HRESULT Update( | |||
2222 | #endif | 2471 | #endif |
2223 | } | 2472 | } |
2224 | 2473 | ||
2225 | curUnpackSize = sizeToEncode; | 2474 | // curUnpackSize = sizeToEncode; |
2226 | 2475 | ||
2227 | HRESULT encodeRes = encoder.Encode( | 2476 | HRESULT encodeRes = encoder.Encode1( |
2228 | EXTERNAL_CODECS_LOC_VARS | 2477 | EXTERNAL_CODECS_LOC_VARS |
2229 | inStreamSizeCount, | 2478 | inStreamSizeCount, |
2230 | // NULL, | 2479 | // NULL, |
2231 | &inSizeForReduce, | 2480 | &inSizeForReduce, |
2232 | newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curUnpackSize, | 2481 | sizeToEncode, // expectedDataSize |
2482 | newDatabase.Folders.AddNew(), | ||
2483 | // newDatabase.CoderUnpackSizes, curUnpackSize, | ||
2233 | archive.SeqStream, newDatabase.PackSizes, progress); | 2484 | archive.SeqStream, newDatabase.PackSizes, progress); |
2234 | 2485 | ||
2235 | if (encodeRes == k_My_HRESULT_CRC_ERROR) | 2486 | if (encodeRes == k_My_HRESULT_CRC_ERROR) |
2236 | return E_FAIL; | 2487 | return E_FAIL; |
2237 | 2488 | ||
2238 | #ifndef _7ZIP_ST | 2489 | curUnpackSize = inStreamSizeCountSpec->GetSize(); |
2490 | |||
2491 | if (encodeRes == S_OK) | ||
2492 | { | ||
2493 | encoder.Encode_Post(curUnpackSize, newDatabase.CoderUnpackSizes); | ||
2494 | } | ||
2495 | |||
2496 | #ifndef Z7_ST | ||
2239 | if (options.MultiThreadMixer) | 2497 | if (options.MultiThreadMixer) |
2240 | { | 2498 | { |
2241 | // 16.00: hang was fixed : for case if decoding was not finished. | 2499 | // 16.00: hang was fixed : for case if decoding was not finished. |
@@ -2244,12 +2502,12 @@ HRESULT Update( | |||
2244 | sbInStream.Release(); | 2502 | sbInStream.Release(); |
2245 | 2503 | ||
2246 | { | 2504 | { |
2247 | WRes wres = threadDecoder.WaitExecuteFinish(); | 2505 | const WRes wres = threadDecoder.WaitExecuteFinish(); |
2248 | if (wres != 0) | 2506 | if (wres != 0) |
2249 | return HRESULT_FROM_WIN32(wres); | 2507 | return HRESULT_FROM_WIN32(wres); |
2250 | } | 2508 | } |
2251 | 2509 | ||
2252 | HRESULT decodeRes = threadDecoder.Result; | 2510 | const HRESULT decodeRes = threadDecoder.Result; |
2253 | // if (res == k_My_HRESULT_CRC_ERROR) | 2511 | // if (res == k_My_HRESULT_CRC_ERROR) |
2254 | if (decodeRes == S_FALSE || threadDecoder.dataAfterEnd_Error) | 2512 | if (decodeRes == S_FALSE || threadDecoder.dataAfterEnd_Error) |
2255 | { | 2513 | { |
@@ -2260,12 +2518,12 @@ HRESULT Update( | |||
2260 | // NEventIndexType::kBlockIndex, (UInt32)folderIndex, | 2518 | // NEventIndexType::kBlockIndex, (UInt32)folderIndex, |
2261 | (decodeRes != S_OK ? | 2519 | (decodeRes != S_OK ? |
2262 | NExtract::NOperationResult::kDataError : | 2520 | NExtract::NOperationResult::kDataError : |
2263 | NExtract::NOperationResult::kDataAfterEnd))); | 2521 | NExtract::NOperationResult::kDataAfterEnd))) |
2264 | } | 2522 | } |
2265 | if (decodeRes != S_OK) | 2523 | if (decodeRes != S_OK) |
2266 | return E_FAIL; | 2524 | return E_FAIL; |
2267 | } | 2525 | } |
2268 | RINOK(decodeRes); | 2526 | RINOK(decodeRes) |
2269 | if (encodeRes == S_OK) | 2527 | if (encodeRes == S_OK) |
2270 | if (sb.ProcessedSize != sizeToEncode) | 2528 | if (sb.ProcessedSize != sizeToEncode) |
2271 | encodeRes = E_FAIL; | 2529 | encodeRes = E_FAIL; |
@@ -2279,15 +2537,15 @@ HRESULT Update( | |||
2279 | { | 2537 | { |
2280 | RINOK(extractCallback->ReportExtractResult( | 2538 | RINOK(extractCallback->ReportExtractResult( |
2281 | NEventIndexType::kBlockIndex, (UInt32)folderIndex, | 2539 | NEventIndexType::kBlockIndex, (UInt32)folderIndex, |
2282 | NExtract::NOperationResult::kDataError)); | 2540 | NExtract::NOperationResult::kDataError)) |
2283 | } | 2541 | } |
2284 | return E_FAIL; | 2542 | return E_FAIL; |
2285 | } | 2543 | } |
2286 | RINOK(FosSpec2->Result); | 2544 | RINOK(FosSpec2->Result) |
2287 | } | 2545 | } |
2288 | 2546 | ||
2289 | RINOK(encodeRes); | 2547 | RINOK(encodeRes) |
2290 | RINOK(repackBase->CheckFinishedState()); | 2548 | RINOK(repackBase->CheckFinishedState()) |
2291 | 2549 | ||
2292 | if (curUnpackSize != sizeToEncode) | 2550 | if (curUnpackSize != sizeToEncode) |
2293 | return E_FAIL; | 2551 | return E_FAIL; |
@@ -2306,7 +2564,7 @@ HRESULT Update( | |||
2306 | if (db->Files[fi].HasStream) | 2564 | if (db->Files[fi].HasStream) |
2307 | { | 2565 | { |
2308 | indexInFolder++; | 2566 | indexInFolder++; |
2309 | int updateIndex = fileIndexToUpdateIndexMap[fi]; | 2567 | const int updateIndex = fileIndexToUpdateIndexMap[fi]; |
2310 | if (updateIndex >= 0) | 2568 | if (updateIndex >= 0) |
2311 | { | 2569 | { |
2312 | const CUpdateItem &ui = updateItems[(unsigned)updateIndex]; | 2570 | const CUpdateItem &ui = updateItems[(unsigned)updateIndex]; |
@@ -2343,13 +2601,13 @@ HRESULT Update( | |||
2343 | 2601 | ||
2344 | // ---------- Compress files to new solid blocks ---------- | 2602 | // ---------- Compress files to new solid blocks ---------- |
2345 | 2603 | ||
2346 | unsigned numFiles = group.Indices.Size(); | 2604 | const unsigned numFiles = group.Indices.Size(); |
2347 | if (numFiles == 0) | 2605 | if (numFiles == 0) |
2348 | continue; | 2606 | continue; |
2349 | CRecordVector<CRefItem> refItems; | 2607 | CRecordVector<CRefItem> refItems; |
2350 | refItems.ClearAndSetSize(numFiles); | 2608 | refItems.ClearAndSetSize(numFiles); |
2351 | // bool sortByType = (options.UseTypeSorting && isSoid); // numSolidFiles > 1 | 2609 | // bool sortByType = (options.UseTypeSorting && isSoid); // numSolidFiles > 1 |
2352 | bool sortByType = options.UseTypeSorting; | 2610 | const bool sortByType = options.UseTypeSorting; |
2353 | 2611 | ||
2354 | unsigned i; | 2612 | unsigned i; |
2355 | 2613 | ||
@@ -2365,7 +2623,7 @@ HRESULT Update( | |||
2365 | 2623 | ||
2366 | for (i = 0; i < numFiles; i++) | 2624 | for (i = 0; i < numFiles; i++) |
2367 | { | 2625 | { |
2368 | UInt32 index = refItems[i].Index; | 2626 | const UInt32 index = refItems[i].Index; |
2369 | indices[i] = index; | 2627 | indices[i] = index; |
2370 | /* | 2628 | /* |
2371 | const CUpdateItem &ui = updateItems[index]; | 2629 | const CUpdateItem &ui = updateItems[index]; |
@@ -2395,8 +2653,8 @@ HRESULT Update( | |||
2395 | break; | 2653 | break; |
2396 | if (options.SolidExtension) | 2654 | if (options.SolidExtension) |
2397 | { | 2655 | { |
2398 | int slashPos = ui.Name.ReverseFind_PathSepar(); | 2656 | const int slashPos = ui.Name.ReverseFind_PathSepar(); |
2399 | int dotPos = ui.Name.ReverseFind_Dot(); | 2657 | const int dotPos = ui.Name.ReverseFind_Dot(); |
2400 | const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : (unsigned)(dotPos + 1)); | 2658 | const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : (unsigned)(dotPos + 1)); |
2401 | if (numSubFiles == 0) | 2659 | if (numSubFiles == 0) |
2402 | prevExtension = ext; | 2660 | prevExtension = ext; |
@@ -2408,7 +2666,7 @@ HRESULT Update( | |||
2408 | if (numSubFiles < 1) | 2666 | if (numSubFiles < 1) |
2409 | numSubFiles = 1; | 2667 | numSubFiles = 1; |
2410 | 2668 | ||
2411 | RINOK(lps->SetCur()); | 2669 | RINOK(lps->SetCur()) |
2412 | 2670 | ||
2413 | /* | 2671 | /* |
2414 | const unsigned folderIndex = newDatabase.NumUnpackStreamsVector.Size(); | 2672 | const unsigned folderIndex = newDatabase.NumUnpackStreamsVector.Size(); |
@@ -2431,31 +2689,45 @@ HRESULT Update( | |||
2431 | inStreamSpec->Need_ATime = options.Need_ATime; | 2689 | inStreamSpec->Need_ATime = options.Need_ATime; |
2432 | inStreamSpec->Need_MTime = options.Need_MTime; | 2690 | inStreamSpec->Need_MTime = options.Need_MTime; |
2433 | inStreamSpec->Need_Attrib = options.Need_Attrib; | 2691 | inStreamSpec->Need_Attrib = options.Need_Attrib; |
2692 | // inStreamSpec->Need_Crc = options.Need_Crc; | ||
2434 | 2693 | ||
2435 | inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); | 2694 | inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); |
2436 | 2695 | ||
2437 | unsigned startPackIndex = newDatabase.PackSizes.Size(); | 2696 | unsigned startPackIndex = newDatabase.PackSizes.Size(); |
2438 | UInt64 curFolderUnpackSize = totalSize; | 2697 | // UInt64 curFolderUnpackSize = totalSize; |
2439 | // curFolderUnpackSize = (UInt64)(Int64)-1; // for debug | 2698 | // curFolderUnpackSize = (UInt64)(Int64)-1; // for debug |
2699 | const UInt64 expectedDataSize = totalSize; | ||
2700 | |||
2701 | // const unsigned folderIndex_New = newDatabase.Folders.Size(); | ||
2440 | 2702 | ||
2441 | RINOK(encoder.Encode( | 2703 | RINOK(encoder.Encode1( |
2442 | EXTERNAL_CODECS_LOC_VARS | 2704 | EXTERNAL_CODECS_LOC_VARS |
2443 | solidInStream, | 2705 | solidInStream, |
2444 | // NULL, | 2706 | // NULL, |
2445 | &inSizeForReduce, | 2707 | &inSizeForReduce, |
2446 | newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curFolderUnpackSize, | 2708 | expectedDataSize, // expected size |
2447 | archive.SeqStream, newDatabase.PackSizes, progress)); | 2709 | newDatabase.Folders.AddNew(), |
2710 | // newDatabase.CoderUnpackSizes, curFolderUnpackSize, | ||
2711 | archive.SeqStream, newDatabase.PackSizes, progress)) | ||
2448 | 2712 | ||
2449 | if (!inStreamSpec->WasFinished()) | 2713 | if (!inStreamSpec->WasFinished()) |
2450 | return E_FAIL; | 2714 | return E_FAIL; |
2451 | 2715 | ||
2716 | /* | ||
2717 | if (inStreamSpec->Need_FolderCrc) | ||
2718 | newDatabase.FolderUnpackCRCs.SetItem(folderIndex_New, | ||
2719 | true, inStreamSpec->GetFolderCrc()); | ||
2720 | */ | ||
2721 | |||
2722 | const UInt64 curFolderUnpackSize = inStreamSpec->Get_TotalSize_for_Coder(); | ||
2723 | encoder.Encode_Post(curFolderUnpackSize, newDatabase.CoderUnpackSizes); | ||
2724 | |||
2452 | UInt64 packSize = 0; | 2725 | UInt64 packSize = 0; |
2453 | // const UInt32 numStreams = newDatabase.PackSizes.Size() - startPackIndex; | 2726 | // const UInt32 numStreams = newDatabase.PackSizes.Size() - startPackIndex; |
2454 | for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) | 2727 | for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) |
2455 | packSize += newDatabase.PackSizes[startPackIndex]; | 2728 | packSize += newDatabase.PackSizes[startPackIndex]; |
2456 | lps->OutSize += packSize; | 2729 | lps->OutSize += packSize; |
2457 | 2730 | ||
2458 | lps->InSize += curFolderUnpackSize; | ||
2459 | // for () | 2731 | // for () |
2460 | // newDatabase.PackCRCsDefined.Add(false); | 2732 | // newDatabase.PackCRCsDefined.Add(false); |
2461 | // newDatabase.PackCRCs.Add(0); | 2733 | // newDatabase.PackCRCs.Add(0); |
@@ -2496,14 +2768,15 @@ HRESULT Update( | |||
2496 | // name += ".locked"; // for debug | 2768 | // name += ".locked"; // for debug |
2497 | } | 2769 | } |
2498 | 2770 | ||
2771 | // if (inStreamSpec->Need_Crc) | ||
2499 | file.Crc = inStreamSpec->CRCs[subIndex]; | 2772 | file.Crc = inStreamSpec->CRCs[subIndex]; |
2500 | file.Size = inStreamSpec->Sizes[subIndex]; | 2773 | file.Size = inStreamSpec->Sizes[subIndex]; |
2501 | 2774 | ||
2502 | procSize += file.Size; | 2775 | procSize += file.Size; |
2503 | // if (file.Size >= 0) // test purposes | 2776 | // if (file.Size >= 0) // for debug: test purposes |
2504 | if (file.Size != 0) | 2777 | if (file.Size != 0) |
2505 | { | 2778 | { |
2506 | file.CrcDefined = true; | 2779 | file.CrcDefined = true; // inStreamSpec->Need_Crc; |
2507 | file.HasStream = true; | 2780 | file.HasStream = true; |
2508 | numUnpackStreams++; | 2781 | numUnpackStreams++; |
2509 | } | 2782 | } |
@@ -2549,9 +2822,66 @@ HRESULT Update( | |||
2549 | newDatabase.AddFile(file, file2, name); | 2822 | newDatabase.AddFile(file, file2, name); |
2550 | } | 2823 | } |
2551 | 2824 | ||
2825 | /* | ||
2826 | // for debug: | ||
2827 | // we can write crc to folders area, if folder contains only one file | ||
2828 | if (numUnpackStreams == 1 && numSubFiles == 1) | ||
2829 | { | ||
2830 | const CFileItem &file = newDatabase.Files.Back(); | ||
2831 | if (file.CrcDefined) | ||
2832 | newDatabase.FolderUnpackCRCs.SetItem(folderIndex_New, true, file.Crc); | ||
2833 | } | ||
2834 | */ | ||
2835 | |||
2836 | /* | ||
2552 | // it's optional check to ensure that sizes are correct | 2837 | // it's optional check to ensure that sizes are correct |
2553 | if (procSize != curFolderUnpackSize) | 2838 | if (inStreamSpec->TotalSize_for_Coder != curFolderUnpackSize) |
2554 | return E_FAIL; | 2839 | return E_FAIL; |
2840 | */ | ||
2841 | // if (inStreamSpec->AlignLog == 0) | ||
2842 | { | ||
2843 | if (procSize != curFolderUnpackSize) | ||
2844 | return E_FAIL; | ||
2845 | } | ||
2846 | // else | ||
2847 | { | ||
2848 | /* | ||
2849 | { | ||
2850 | const CFolder &old = newDatabase.Folders.Back(); | ||
2851 | CFolder &folder = newDatabase.Folders.AddNew(); | ||
2852 | { | ||
2853 | const unsigned numBonds = old.Bonds.Size(); | ||
2854 | folder.Bonds.SetSize(numBonds + 1); | ||
2855 | for (unsigned k = 0; k < numBonds; k++) | ||
2856 | folder.Bonds[k] = old.Bonds[k]; | ||
2857 | CBond &bond = folder.Bonds[numBonds]; | ||
2858 | bond.PackIndex = 0; | ||
2859 | bond.UnpackIndex = 0; | ||
2860 | } | ||
2861 | { | ||
2862 | const unsigned numCoders = old.Coders.Size(); | ||
2863 | folder.Coders.SetSize(numCoders + 1); | ||
2864 | for (unsigned k = 0; k < numCoders; k++) | ||
2865 | folder.Coders[k] = old.Coders[k]; | ||
2866 | CCoderInfo &cod = folder.Coders[numCoders]; | ||
2867 | cod.Props.Alloc(1); | ||
2868 | cod.Props[0] = (Byte)inStreamSpec->AlignLog; | ||
2869 | cod.NumStreams = 1; | ||
2870 | } | ||
2871 | { | ||
2872 | const unsigned numPackStreams = old.Coders.Size(); | ||
2873 | folder.Coders.SetSize(numPackStreams); | ||
2874 | for (unsigned k = 0; k < numPackStreams; k++) | ||
2875 | folder.PackStreams[k] = old.PackStreams[k]; | ||
2876 | } | ||
2877 | } | ||
2878 | newDatabase.Folders.Delete(newDatabase.Folders.Size() - 2); | ||
2879 | */ | ||
2880 | } | ||
2881 | |||
2882 | |||
2883 | lps->InSize += procSize; | ||
2884 | // lps->InSize += curFolderUnpackSize; | ||
2555 | 2885 | ||
2556 | // numUnpackStreams = 0 is very bad case for locked files | 2886 | // numUnpackStreams = 0 is very bad case for locked files |
2557 | // v3.13 doesn't understand it. | 2887 | // v3.13 doesn't understand it. |
@@ -2561,7 +2891,7 @@ HRESULT Update( | |||
2561 | if (skippedSize != 0 && complexity >= skippedSize) | 2891 | if (skippedSize != 0 && complexity >= skippedSize) |
2562 | { | 2892 | { |
2563 | complexity -= skippedSize; | 2893 | complexity -= skippedSize; |
2564 | RINOK(updateCallback->SetTotal(complexity)); | 2894 | RINOK(updateCallback->SetTotal(complexity)) |
2565 | } | 2895 | } |
2566 | 2896 | ||
2567 | /* | 2897 | /* |
@@ -2604,7 +2934,7 @@ HRESULT Update( | |||
2604 | } | 2934 | } |
2605 | } | 2935 | } |
2606 | 2936 | ||
2607 | RINOK(lps->SetCur()); | 2937 | RINOK(lps->SetCur()) |
2608 | 2938 | ||
2609 | /* | 2939 | /* |
2610 | fileIndexToUpdateIndexMap.ClearAndFree(); | 2940 | fileIndexToUpdateIndexMap.ClearAndFree(); |
@@ -2634,10 +2964,26 @@ HRESULT Update( | |||
2634 | } | 2964 | } |
2635 | } | 2965 | } |
2636 | */ | 2966 | */ |
2967 | |||
2968 | { | ||
2969 | const unsigned numFolders = newDatabase.Folders.Size(); | ||
2970 | if (newDatabase.NumUnpackStreamsVector.Size() != numFolders | ||
2971 | || newDatabase.FolderUnpackCRCs.Defs.Size() > numFolders) | ||
2972 | return E_FAIL; | ||
2973 | newDatabase.FolderUnpackCRCs.if_NonEmpty_FillResedue_with_false(numFolders); | ||
2974 | } | ||
2975 | |||
2976 | updateItems.ClearAndFree(); | ||
2637 | newDatabase.ReserveDown(); | 2977 | newDatabase.ReserveDown(); |
2638 | 2978 | ||
2639 | if (opCallback) | 2979 | if (opCallback) |
2640 | RINOK(opCallback->ReportOperation(NEventIndexType::kNoIndex, (UInt32)(Int32)-1, NUpdateNotifyOp::kHeader)); | 2980 | RINOK(opCallback->ReportOperation(NEventIndexType::kNoIndex, (UInt32)(Int32)-1, NUpdateNotifyOp::kHeader)) |
2981 | |||
2982 | RINOK(archive.WriteDatabase(EXTERNAL_CODECS_LOC_VARS | ||
2983 | newDatabase, options.HeaderMethod, options.HeaderOptions)) | ||
2984 | |||
2985 | if (v_StreamSetRestriction) | ||
2986 | RINOK(v_StreamSetRestriction->SetRestriction(0, 0)) | ||
2641 | 2987 | ||
2642 | return S_OK; | 2988 | return S_OK; |
2643 | } | 2989 | } |