aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/Archive/7z/7zUpdate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive/7z/7zUpdate.cpp')
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.cpp924
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 @@
24namespace NArchive { 26namespace NArchive {
25namespace N7z { 27namespace N7z {
26 28
27
28#define k_X86 k_BCJ 29#define k_X86 k_BCJ
29 30
30struct CFilterMode 31struct 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
196static unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode) 278static 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*/
287static BoolInt ParseFile(const Byte *buf, size_t size, CFilterMode *filterMode) 376static 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(
417static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, 536static 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
781static const char * const g_ExeExts[] = 900static 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
790static bool IsExeExt(const wchar_t *ext) 909static const char * const g_ExeUnix_Exts[] =
910{
911 "so"
912 , "dylib"
913};
914
915static 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/*
924static 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
934static 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
798struct CAnalysis 968struct 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
1138class CRepackInStreamWithSizes: 1364Z7_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;
1147public: 1373public:
@@ -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
1166STDMETHODIMP CRepackInStreamWithSizes::Read(void *data, UInt32 size, UInt32 *processedSize) 1386Z7_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
1179STDMETHODIMP CRepackInStreamWithSizes::GetSubStreamSize(UInt64 subStream, UInt64 *value) 1396Z7_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:
1212public: 1429public:
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
1290class CFolderOutStream2: 1507class 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)
1295public: 1514public:
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
1303STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize) 1518Z7_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
1350static const UInt32 kTempBufSize = 1 << 16; 1565static const UInt32 kTempBufSize = 1 << 16;
1351 1566
1352class CFolderInStream2: 1567class 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;
1358public: 1576public:
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
1379STDMETHODIMP CFolderInStream2::Read(void *data, UInt32 size, UInt32 *processedSize) 1594Z7_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
1441class CThreadDecoder 1656class 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 }
1717private:
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
1502void CThreadDecoder::Execute() 1725void 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
1553class CCryptoGetTextPassword: 1776Z7_CLASS_IMP_NOQIB_1(
1554 public ICryptoGetTextPassword, 1777 CCryptoGetTextPassword
1555 public CMyUnknownImp 1778 , ICryptoGetTextPassword
1556{ 1779)
1557public: 1780public:
1558 UString Password; 1781 UString Password;
1559
1560 MY_UNKNOWN_IMP
1561 STDMETHOD(CryptoGetTextPassword)(BSTR *password);
1562}; 1782};
1563 1783
1564STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password) 1784Z7_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}