xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/7z/7zUpdate.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // 7zUpdate.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/CpuArch.h"
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/MyLinux.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringToInt.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/Wildcard.h"
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/CreateCoder.h"
12*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/LimitedStreams.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ProgressUtils.h"
14*f6dc9357SAndroid Build Coastguard Worker 
15*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/CopyCoder.h"
16*f6dc9357SAndroid Build Coastguard Worker 
17*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ItemNameUtils.h"
18*f6dc9357SAndroid Build Coastguard Worker 
19*f6dc9357SAndroid Build Coastguard Worker #include "7zDecode.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "7zEncode.h"
21*f6dc9357SAndroid Build Coastguard Worker #include "7zFolderInStream.h"
22*f6dc9357SAndroid Build Coastguard Worker #include "7zHandler.h"
23*f6dc9357SAndroid Build Coastguard Worker #include "7zOut.h"
24*f6dc9357SAndroid Build Coastguard Worker #include "7zUpdate.h"
25*f6dc9357SAndroid Build Coastguard Worker 
26*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
27*f6dc9357SAndroid Build Coastguard Worker namespace N7z {
28*f6dc9357SAndroid Build Coastguard Worker 
29*f6dc9357SAndroid Build Coastguard Worker #define k_X86 k_BCJ
30*f6dc9357SAndroid Build Coastguard Worker 
31*f6dc9357SAndroid Build Coastguard Worker struct CFilterMode
32*f6dc9357SAndroid Build Coastguard Worker {
33*f6dc9357SAndroid Build Coastguard Worker   UInt32 Id;
34*f6dc9357SAndroid Build Coastguard Worker   UInt32 Delta;  // required File Size alignment, if Id is not k_Delta.
35*f6dc9357SAndroid Build Coastguard Worker                  // (Delta == 0) means unknown alignment
36*f6dc9357SAndroid Build Coastguard Worker   UInt32 Offset; // for k_ARM64 / k_RISCV
37*f6dc9357SAndroid Build Coastguard Worker   // UInt32 AlignSizeOpt; // for k_ARM64
38*f6dc9357SAndroid Build Coastguard Worker 
CFilterModeNArchive::N7z::CFilterMode39*f6dc9357SAndroid Build Coastguard Worker   CFilterMode():
40*f6dc9357SAndroid Build Coastguard Worker     Id(0),
41*f6dc9357SAndroid Build Coastguard Worker     Delta(0),
42*f6dc9357SAndroid Build Coastguard Worker     Offset(0)
43*f6dc9357SAndroid Build Coastguard Worker     // , AlignSizeOpt(0)
44*f6dc9357SAndroid Build Coastguard Worker     {}
45*f6dc9357SAndroid Build Coastguard Worker 
ClearFilterModeNArchive::N7z::CFilterMode46*f6dc9357SAndroid Build Coastguard Worker   void ClearFilterMode()
47*f6dc9357SAndroid Build Coastguard Worker   {
48*f6dc9357SAndroid Build Coastguard Worker     Id = 0;
49*f6dc9357SAndroid Build Coastguard Worker     Delta = 0;
50*f6dc9357SAndroid Build Coastguard Worker     Offset = 0;
51*f6dc9357SAndroid Build Coastguard Worker     // AlignSizeOpt = 0;
52*f6dc9357SAndroid Build Coastguard Worker   }
53*f6dc9357SAndroid Build Coastguard Worker 
54*f6dc9357SAndroid Build Coastguard Worker   // it sets Delta as Align value, if Id is exe filter
55*f6dc9357SAndroid Build Coastguard Worker   // in another cases it sets Delta = 0, that
SetDeltaNArchive::N7z::CFilterMode56*f6dc9357SAndroid Build Coastguard Worker   void SetDelta()
57*f6dc9357SAndroid Build Coastguard Worker   {
58*f6dc9357SAndroid Build Coastguard Worker     if (Id == k_IA64)
59*f6dc9357SAndroid Build Coastguard Worker       Delta = 16;
60*f6dc9357SAndroid Build Coastguard Worker     else if (Id == k_ARM64 || Id == k_ARM || Id == k_PPC || Id == k_SPARC)
61*f6dc9357SAndroid Build Coastguard Worker       Delta = 4;
62*f6dc9357SAndroid Build Coastguard Worker     else if (Id == k_ARMT || Id == k_RISCV)
63*f6dc9357SAndroid Build Coastguard Worker       Delta = 2;
64*f6dc9357SAndroid Build Coastguard Worker     else if (Id == k_BCJ || Id == k_BCJ2)
65*f6dc9357SAndroid Build Coastguard Worker       Delta = 1; // do we need it?
66*f6dc9357SAndroid Build Coastguard Worker     else
67*f6dc9357SAndroid Build Coastguard Worker       Delta = 0;
68*f6dc9357SAndroid Build Coastguard Worker   }
69*f6dc9357SAndroid Build Coastguard Worker };
70*f6dc9357SAndroid Build Coastguard Worker 
71*f6dc9357SAndroid Build Coastguard Worker 
72*f6dc9357SAndroid Build Coastguard Worker /* ---------- PE ---------- */
73*f6dc9357SAndroid Build Coastguard Worker 
74*f6dc9357SAndroid Build Coastguard Worker #define MZ_SIG 0x5A4D
75*f6dc9357SAndroid Build Coastguard Worker 
76*f6dc9357SAndroid Build Coastguard Worker #define PE_SIG 0x00004550
77*f6dc9357SAndroid Build Coastguard Worker #define PE_OptHeader_Magic_32 0x10B
78*f6dc9357SAndroid Build Coastguard Worker #define PE_OptHeader_Magic_64 0x20B
79*f6dc9357SAndroid Build Coastguard Worker // #define PE_SectHeaderSize 40
80*f6dc9357SAndroid Build Coastguard Worker // #define PE_SECT_EXECUTE 0x20000000
81*f6dc9357SAndroid Build Coastguard Worker 
Parse_EXE(const Byte * buf,size_t size,CFilterMode * filterMode)82*f6dc9357SAndroid Build Coastguard Worker static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
83*f6dc9357SAndroid Build Coastguard Worker {
84*f6dc9357SAndroid Build Coastguard Worker   if (size < 512 || GetUi16(buf) != MZ_SIG)
85*f6dc9357SAndroid Build Coastguard Worker     return 0;
86*f6dc9357SAndroid Build Coastguard Worker 
87*f6dc9357SAndroid Build Coastguard Worker   const Byte *p;
88*f6dc9357SAndroid Build Coastguard Worker   UInt32 peOffset, optHeaderSize, filterId;
89*f6dc9357SAndroid Build Coastguard Worker 
90*f6dc9357SAndroid Build Coastguard Worker   peOffset = GetUi32(buf + 0x3C);
91*f6dc9357SAndroid Build Coastguard Worker   if (peOffset >= 0x1000 || peOffset + 512 > size || (peOffset & 7) != 0)
92*f6dc9357SAndroid Build Coastguard Worker     return 0;
93*f6dc9357SAndroid Build Coastguard Worker   p = buf + peOffset;
94*f6dc9357SAndroid Build Coastguard Worker   if (GetUi32(p) != PE_SIG)
95*f6dc9357SAndroid Build Coastguard Worker     return 0;
96*f6dc9357SAndroid Build Coastguard Worker   p += 4;
97*f6dc9357SAndroid Build Coastguard Worker 
98*f6dc9357SAndroid Build Coastguard Worker   const unsigned machine = GetUi16(p);
99*f6dc9357SAndroid Build Coastguard Worker 
100*f6dc9357SAndroid Build Coastguard Worker   switch (machine)
101*f6dc9357SAndroid Build Coastguard Worker   {
102*f6dc9357SAndroid Build Coastguard Worker     case 0x014C:
103*f6dc9357SAndroid Build Coastguard Worker     case 0x8664:  filterId = k_X86; break;
104*f6dc9357SAndroid Build Coastguard Worker     case 0xAA64:  filterId = k_ARM64; break;
105*f6dc9357SAndroid Build Coastguard Worker 
106*f6dc9357SAndroid Build Coastguard Worker     /*
107*f6dc9357SAndroid Build Coastguard Worker     IMAGE_FILE_MACHINE_ARM   0x01C0  // ARM LE
108*f6dc9357SAndroid Build Coastguard Worker     IMAGE_FILE_MACHINE_THUMB 0x01C2  // ARM Thumb / Thumb-2 LE
109*f6dc9357SAndroid Build Coastguard Worker     IMAGE_FILE_MACHINE_ARMNT 0x01C4  // ARM Thumb-2, LE
110*f6dc9357SAndroid Build Coastguard Worker     Note: We use ARM filter for 0x01C2. (WinCE 5 - 0x01C2) files mostly contain ARM code (not Thumb/Thumb-2).
111*f6dc9357SAndroid Build Coastguard Worker     */
112*f6dc9357SAndroid Build Coastguard Worker 
113*f6dc9357SAndroid Build Coastguard Worker     case 0x01C0:                            // WinCE old
114*f6dc9357SAndroid Build Coastguard Worker     case 0x01C2:  filterId = k_ARM; break;  // WinCE new
115*f6dc9357SAndroid Build Coastguard Worker     case 0x01C4:  filterId = k_ARMT; break; // WinRT
116*f6dc9357SAndroid Build Coastguard Worker 
117*f6dc9357SAndroid Build Coastguard Worker     case 0x5032:  // RISCV32
118*f6dc9357SAndroid Build Coastguard Worker     case 0x5064:  // RISCV64
119*f6dc9357SAndroid Build Coastguard Worker     // case 0x5128:  // RISCV128
120*f6dc9357SAndroid Build Coastguard Worker                   filterId = k_RISCV; break;
121*f6dc9357SAndroid Build Coastguard Worker 
122*f6dc9357SAndroid Build Coastguard Worker     case 0x0200:  filterId = k_IA64; break;
123*f6dc9357SAndroid Build Coastguard Worker     default:  return 0;
124*f6dc9357SAndroid Build Coastguard Worker   }
125*f6dc9357SAndroid Build Coastguard Worker 
126*f6dc9357SAndroid Build Coastguard Worker   const UInt32 numSections = GetUi16(p + 2);
127*f6dc9357SAndroid Build Coastguard Worker   optHeaderSize = GetUi16(p + 16);
128*f6dc9357SAndroid Build Coastguard Worker   if (optHeaderSize > (1 << 10))
129*f6dc9357SAndroid Build Coastguard Worker     return 0;
130*f6dc9357SAndroid Build Coastguard Worker 
131*f6dc9357SAndroid Build Coastguard Worker   p += 20; /* headerSize */
132*f6dc9357SAndroid Build Coastguard Worker 
133*f6dc9357SAndroid Build Coastguard Worker   switch (GetUi16(p))
134*f6dc9357SAndroid Build Coastguard Worker   {
135*f6dc9357SAndroid Build Coastguard Worker     case PE_OptHeader_Magic_32:
136*f6dc9357SAndroid Build Coastguard Worker     case PE_OptHeader_Magic_64:
137*f6dc9357SAndroid Build Coastguard Worker       break;
138*f6dc9357SAndroid Build Coastguard Worker     default:
139*f6dc9357SAndroid Build Coastguard Worker       return 0;
140*f6dc9357SAndroid Build Coastguard Worker   }
141*f6dc9357SAndroid Build Coastguard Worker 
142*f6dc9357SAndroid Build Coastguard Worker     // Windows exe file sizes are not aligned for 4 KiB.
143*f6dc9357SAndroid Build Coastguard Worker     // So we can't use (CFilterMode::Offset != 0) in solid archives.
144*f6dc9357SAndroid Build Coastguard Worker     // So we just don't set Offset here.
145*f6dc9357SAndroid Build Coastguard Worker #define NUM_SCAN_SECTIONS_MAX (1 << 6)
146*f6dc9357SAndroid Build Coastguard Worker // #define EXE_SECTION_OFFSET_MAX (1 << 27)
147*f6dc9357SAndroid Build Coastguard Worker // #define EXE_SECTION_SIZE_MIN (1 << 8)
148*f6dc9357SAndroid Build Coastguard Worker // #define EXE_SECTION_SIZE_MAX (1 << 27)
149*f6dc9357SAndroid Build Coastguard Worker #define PE_SectHeaderSize 40
150*f6dc9357SAndroid Build Coastguard Worker // #define PE_SECT_EXECUTE 0x20000000
151*f6dc9357SAndroid Build Coastguard Worker 
152*f6dc9357SAndroid Build Coastguard Worker /*
153*f6dc9357SAndroid Build Coastguard Worker   if (numSections > NUM_SCAN_SECTIONS_MAX)
154*f6dc9357SAndroid Build Coastguard Worker     return 0;
155*f6dc9357SAndroid Build Coastguard Worker */
156*f6dc9357SAndroid Build Coastguard Worker 
157*f6dc9357SAndroid Build Coastguard Worker   if ((size_t)(p - buf) + optHeaderSize <= size)
158*f6dc9357SAndroid Build Coastguard Worker   {
159*f6dc9357SAndroid Build Coastguard Worker   p += optHeaderSize;
160*f6dc9357SAndroid Build Coastguard Worker /*
161*f6dc9357SAndroid Build Coastguard Worker   // UInt32 numExeSections = 0;
162*f6dc9357SAndroid Build Coastguard Worker   // bool execute_finded = false;
163*f6dc9357SAndroid Build Coastguard Worker   // UInt32 sect_va = 0;
164*f6dc9357SAndroid Build Coastguard Worker   // UInt32 sect_size = 0;
165*f6dc9357SAndroid Build Coastguard Worker   // UInt32 sect_offset = 0;
166*f6dc9357SAndroid Build Coastguard Worker */
167*f6dc9357SAndroid Build Coastguard Worker   if (numSections <= NUM_SCAN_SECTIONS_MAX)
168*f6dc9357SAndroid Build Coastguard Worker   if (machine == 0x8664)
169*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < numSections
170*f6dc9357SAndroid Build Coastguard Worker         ; i++, p += PE_SectHeaderSize)
171*f6dc9357SAndroid Build Coastguard Worker   {
172*f6dc9357SAndroid Build Coastguard Worker     // UInt32 characts, rawSize, offset;
173*f6dc9357SAndroid Build Coastguard Worker     if ((UInt32)(p - buf) + PE_SectHeaderSize > size)
174*f6dc9357SAndroid Build Coastguard Worker     {
175*f6dc9357SAndroid Build Coastguard Worker       // return 0;
176*f6dc9357SAndroid Build Coastguard Worker       break;
177*f6dc9357SAndroid Build Coastguard Worker     }
178*f6dc9357SAndroid Build Coastguard Worker     if (memcmp(p, ".a64xrm", 8) == 0)
179*f6dc9357SAndroid Build Coastguard Worker     {
180*f6dc9357SAndroid Build Coastguard Worker       // ARM64EC
181*f6dc9357SAndroid Build Coastguard Worker       filterId = k_ARM64;
182*f6dc9357SAndroid Build Coastguard Worker       break;
183*f6dc9357SAndroid Build Coastguard Worker     }
184*f6dc9357SAndroid Build Coastguard Worker /*
185*f6dc9357SAndroid Build Coastguard Worker     rawSize = GetUi32(p + 16);
186*f6dc9357SAndroid Build Coastguard Worker     offset = GetUi32(p + 20);
187*f6dc9357SAndroid Build Coastguard Worker     characts = GetUi32(p + 36);
188*f6dc9357SAndroid Build Coastguard Worker     if (rawSize >= EXE_SECTION_SIZE_MIN &&
189*f6dc9357SAndroid Build Coastguard Worker         rawSize <= EXE_SECTION_SIZE_MAX &&
190*f6dc9357SAndroid Build Coastguard Worker         offset <= EXE_SECTION_OFFSET_MAX &&
191*f6dc9357SAndroid Build Coastguard Worker         // offset < limit &&
192*f6dc9357SAndroid Build Coastguard Worker         offset > 0)
193*f6dc9357SAndroid Build Coastguard Worker     {
194*f6dc9357SAndroid Build Coastguard Worker       if ((characts & PE_SECT_EXECUTE) != 0)
195*f6dc9357SAndroid Build Coastguard Worker       {
196*f6dc9357SAndroid Build Coastguard Worker         // execute_finded = true;
197*f6dc9357SAndroid Build Coastguard Worker         // sect_va = GetUi32(p + 12);
198*f6dc9357SAndroid Build Coastguard Worker         // sect_size = rawSize;
199*f6dc9357SAndroid Build Coastguard Worker         // sect_offset = offset;
200*f6dc9357SAndroid Build Coastguard Worker         break;
201*f6dc9357SAndroid Build Coastguard Worker       }
202*f6dc9357SAndroid Build Coastguard Worker     }
203*f6dc9357SAndroid Build Coastguard Worker */
204*f6dc9357SAndroid Build Coastguard Worker   }
205*f6dc9357SAndroid Build Coastguard Worker   }
206*f6dc9357SAndroid Build Coastguard Worker 
207*f6dc9357SAndroid Build Coastguard Worker   /*
208*f6dc9357SAndroid Build Coastguard Worker   filterMode->Offset = 0;
209*f6dc9357SAndroid Build Coastguard Worker   if (filterId == k_ARM64)
210*f6dc9357SAndroid Build Coastguard Worker   {
211*f6dc9357SAndroid Build Coastguard Worker     // filterMode->AlignSizeOpt = (1 << 12);
212*f6dc9357SAndroid Build Coastguard Worker     // const UInt32 offs = (sect_va - sect_offset) & 0xFFF;
213*f6dc9357SAndroid Build Coastguard Worker     // if (offs != 0)
214*f6dc9357SAndroid Build Coastguard Worker     // filterMode->Offset = offs; // change it
215*f6dc9357SAndroid Build Coastguard Worker   }
216*f6dc9357SAndroid Build Coastguard Worker   */
217*f6dc9357SAndroid Build Coastguard Worker   filterMode->Id = filterId;
218*f6dc9357SAndroid Build Coastguard Worker   return 1;
219*f6dc9357SAndroid Build Coastguard Worker }
220*f6dc9357SAndroid Build Coastguard Worker 
221*f6dc9357SAndroid Build Coastguard Worker 
222*f6dc9357SAndroid Build Coastguard Worker /*
223*f6dc9357SAndroid Build Coastguard Worker   Filters don't improve the compression ratio for relocatable object files (".o").
224*f6dc9357SAndroid Build Coastguard Worker   But we can get compression ratio gain, if we compress object
225*f6dc9357SAndroid Build Coastguard Worker   files and executables in same solid block.
226*f6dc9357SAndroid Build Coastguard Worker   So we use filters for relocatable object files (".o"):
227*f6dc9357SAndroid Build Coastguard Worker */
228*f6dc9357SAndroid Build Coastguard Worker // #define Z7_7Z_CREATE_ARC_DISABLE_FILTER_FOR_OBJ
229*f6dc9357SAndroid Build Coastguard Worker 
230*f6dc9357SAndroid Build Coastguard Worker /* ---------- ELF ---------- */
231*f6dc9357SAndroid Build Coastguard Worker 
232*f6dc9357SAndroid Build Coastguard Worker #define ELF_SIG 0x464C457F
233*f6dc9357SAndroid Build Coastguard Worker 
234*f6dc9357SAndroid Build Coastguard Worker #define ELF_CLASS_32  1
235*f6dc9357SAndroid Build Coastguard Worker #define ELF_CLASS_64  2
236*f6dc9357SAndroid Build Coastguard Worker 
237*f6dc9357SAndroid Build Coastguard Worker #define ELF_DATA_2LSB 1
238*f6dc9357SAndroid Build Coastguard Worker #define ELF_DATA_2MSB 2
239*f6dc9357SAndroid Build Coastguard Worker 
Get16(const Byte * p,BoolInt be)240*f6dc9357SAndroid Build Coastguard Worker static UInt16 Get16(const Byte *p, BoolInt be) { if (be) return (UInt16)GetBe16(p); return (UInt16)GetUi16(p); }
Get32(const Byte * p,BoolInt be)241*f6dc9357SAndroid Build Coastguard Worker static UInt32 Get32(const Byte *p, BoolInt be) { if (be) return GetBe32(p); return GetUi32(p); }
242*f6dc9357SAndroid Build Coastguard Worker // static UInt64 Get64(const Byte *p, BoolInt be) { if (be) return GetBe64(p); return GetUi64(p); }
243*f6dc9357SAndroid Build Coastguard Worker 
Parse_ELF(const Byte * buf,size_t size,CFilterMode * filterMode)244*f6dc9357SAndroid Build Coastguard Worker static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode)
245*f6dc9357SAndroid Build Coastguard Worker {
246*f6dc9357SAndroid Build Coastguard Worker   BoolInt /* is32, */ be;
247*f6dc9357SAndroid Build Coastguard Worker   UInt32 filterId;
248*f6dc9357SAndroid Build Coastguard Worker 
249*f6dc9357SAndroid Build Coastguard Worker   if (size < 512 || buf[6] != 1) /* ver */
250*f6dc9357SAndroid Build Coastguard Worker     return 0;
251*f6dc9357SAndroid Build Coastguard Worker 
252*f6dc9357SAndroid Build Coastguard Worker   if (GetUi32(buf) != ELF_SIG)
253*f6dc9357SAndroid Build Coastguard Worker     return 0;
254*f6dc9357SAndroid Build Coastguard Worker 
255*f6dc9357SAndroid Build Coastguard Worker   switch (buf[4])
256*f6dc9357SAndroid Build Coastguard Worker   {
257*f6dc9357SAndroid Build Coastguard Worker     case ELF_CLASS_32: /* is32 = True; */ break;
258*f6dc9357SAndroid Build Coastguard Worker     case ELF_CLASS_64: /* is32 = False; */ break;
259*f6dc9357SAndroid Build Coastguard Worker     default: return 0;
260*f6dc9357SAndroid Build Coastguard Worker   }
261*f6dc9357SAndroid Build Coastguard Worker 
262*f6dc9357SAndroid Build Coastguard Worker   switch (buf[5])
263*f6dc9357SAndroid Build Coastguard Worker   {
264*f6dc9357SAndroid Build Coastguard Worker     case ELF_DATA_2LSB: be = False; break;
265*f6dc9357SAndroid Build Coastguard Worker     case ELF_DATA_2MSB: be = True; break;
266*f6dc9357SAndroid Build Coastguard Worker     default: return 0;
267*f6dc9357SAndroid Build Coastguard Worker   }
268*f6dc9357SAndroid Build Coastguard Worker 
269*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_7Z_CREATE_ARC_DISABLE_FILTER_FOR_OBJ
270*f6dc9357SAndroid Build Coastguard Worker #define ELF_ET_REL  1
271*f6dc9357SAndroid Build Coastguard Worker   if (Get16(buf + 0x10, be) == ELF_ET_REL)
272*f6dc9357SAndroid Build Coastguard Worker     return 0;
273*f6dc9357SAndroid Build Coastguard Worker #endif
274*f6dc9357SAndroid Build Coastguard Worker 
275*f6dc9357SAndroid Build Coastguard Worker   switch (Get16(buf + 0x12, be))
276*f6dc9357SAndroid Build Coastguard Worker   {
277*f6dc9357SAndroid Build Coastguard Worker     case 3:
278*f6dc9357SAndroid Build Coastguard Worker     case 6:
279*f6dc9357SAndroid Build Coastguard Worker     case 62: filterId = k_X86; break;
280*f6dc9357SAndroid Build Coastguard Worker     case 2:
281*f6dc9357SAndroid Build Coastguard Worker     case 18:
282*f6dc9357SAndroid Build Coastguard Worker     case 43: filterId = k_SPARC; break;
283*f6dc9357SAndroid Build Coastguard Worker     case 20:
284*f6dc9357SAndroid Build Coastguard Worker     case 21: if (!be) return 0; filterId = k_PPC; break;
285*f6dc9357SAndroid Build Coastguard Worker     case 40:  if (be) return 0; filterId = k_ARM; break;
286*f6dc9357SAndroid Build Coastguard Worker     case 183: if (be) return 0; filterId = k_ARM64; break;
287*f6dc9357SAndroid Build Coastguard Worker     case 243: if (be) return 0; filterId = k_RISCV; break;
288*f6dc9357SAndroid Build Coastguard Worker 
289*f6dc9357SAndroid Build Coastguard Worker     /* Some IA-64 ELF executables have size that is not aligned for 16 bytes.
290*f6dc9357SAndroid Build Coastguard Worker        So we don't use IA-64 filter for IA-64 ELF */
291*f6dc9357SAndroid Build Coastguard Worker     // case 50: if ( be) return 0; filterId = k_IA64; break;
292*f6dc9357SAndroid Build Coastguard Worker 
293*f6dc9357SAndroid Build Coastguard Worker     default: return 0;
294*f6dc9357SAndroid Build Coastguard Worker   }
295*f6dc9357SAndroid Build Coastguard Worker 
296*f6dc9357SAndroid Build Coastguard Worker   filterMode->Id = filterId;
297*f6dc9357SAndroid Build Coastguard Worker   return 1;
298*f6dc9357SAndroid Build Coastguard Worker }
299*f6dc9357SAndroid Build Coastguard Worker 
300*f6dc9357SAndroid Build Coastguard Worker 
301*f6dc9357SAndroid Build Coastguard Worker 
302*f6dc9357SAndroid Build Coastguard Worker /* ---------- Mach-O ---------- */
303*f6dc9357SAndroid Build Coastguard Worker 
304*f6dc9357SAndroid Build Coastguard Worker #define MACH_SIG_BE_32 0xCEFAEDFE
305*f6dc9357SAndroid Build Coastguard Worker #define MACH_SIG_BE_64 0xCFFAEDFE
306*f6dc9357SAndroid Build Coastguard Worker #define MACH_SIG_LE_32 0xFEEDFACE
307*f6dc9357SAndroid Build Coastguard Worker #define MACH_SIG_LE_64 0xFEEDFACF
308*f6dc9357SAndroid Build Coastguard Worker 
309*f6dc9357SAndroid Build Coastguard Worker #define MACH_ARCH_ABI64 (1 << 24)
310*f6dc9357SAndroid Build Coastguard Worker #define MACH_MACHINE_386 7
311*f6dc9357SAndroid Build Coastguard Worker #define MACH_MACHINE_ARM 12
312*f6dc9357SAndroid Build Coastguard Worker #define MACH_MACHINE_SPARC 14
313*f6dc9357SAndroid Build Coastguard Worker #define MACH_MACHINE_PPC 18
314*f6dc9357SAndroid Build Coastguard Worker #define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC)
315*f6dc9357SAndroid Build Coastguard Worker #define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386)
316*f6dc9357SAndroid Build Coastguard Worker #define MACH_MACHINE_ARM64 (MACH_ARCH_ABI64 | MACH_MACHINE_ARM)
317*f6dc9357SAndroid Build Coastguard Worker 
Parse_MACH(const Byte * buf,size_t size,CFilterMode * filterMode)318*f6dc9357SAndroid Build Coastguard Worker static unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode)
319*f6dc9357SAndroid Build Coastguard Worker {
320*f6dc9357SAndroid Build Coastguard Worker   UInt32 filterId, numCommands, commandsSize;
321*f6dc9357SAndroid Build Coastguard Worker 
322*f6dc9357SAndroid Build Coastguard Worker   if (size < 512)
323*f6dc9357SAndroid Build Coastguard Worker     return 0;
324*f6dc9357SAndroid Build Coastguard Worker 
325*f6dc9357SAndroid Build Coastguard Worker   BoolInt /* mode64, */ be;
326*f6dc9357SAndroid Build Coastguard Worker   switch (GetUi32(buf))
327*f6dc9357SAndroid Build Coastguard Worker   {
328*f6dc9357SAndroid Build Coastguard Worker     case MACH_SIG_BE_32: /* mode64 = False; */ be = True; break;
329*f6dc9357SAndroid Build Coastguard Worker     case MACH_SIG_BE_64: /* mode64 = True;  */ be = True; break;
330*f6dc9357SAndroid Build Coastguard Worker     case MACH_SIG_LE_32: /* mode64 = False; */ be = False; break;
331*f6dc9357SAndroid Build Coastguard Worker     case MACH_SIG_LE_64: /* mode64 = True;  */ be = False; break;
332*f6dc9357SAndroid Build Coastguard Worker     default: return 0;
333*f6dc9357SAndroid Build Coastguard Worker   }
334*f6dc9357SAndroid Build Coastguard Worker 
335*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_7Z_CREATE_ARC_DISABLE_FILTER_FOR_OBJ
336*f6dc9357SAndroid Build Coastguard Worker #define MACH_TYPE_OBJECT 1
337*f6dc9357SAndroid Build Coastguard Worker   if (Get32(buf + 0xC, be) == MACH_TYPE_OBJECT)
338*f6dc9357SAndroid Build Coastguard Worker       return 0;
339*f6dc9357SAndroid Build Coastguard Worker #endif
340*f6dc9357SAndroid Build Coastguard Worker 
341*f6dc9357SAndroid Build Coastguard Worker   switch (Get32(buf + 4, be))
342*f6dc9357SAndroid Build Coastguard Worker   {
343*f6dc9357SAndroid Build Coastguard Worker     case MACH_MACHINE_386:
344*f6dc9357SAndroid Build Coastguard Worker     case MACH_MACHINE_AMD64: filterId = k_X86; break;
345*f6dc9357SAndroid Build Coastguard Worker     case MACH_MACHINE_ARM:   if ( be) return 0; filterId = k_ARM; break;
346*f6dc9357SAndroid Build Coastguard Worker     case MACH_MACHINE_SPARC: if (!be) return 0; filterId = k_SPARC; break;
347*f6dc9357SAndroid Build Coastguard Worker     case MACH_MACHINE_PPC:
348*f6dc9357SAndroid Build Coastguard Worker     case MACH_MACHINE_PPC64: if (!be) return 0; filterId = k_PPC; break;
349*f6dc9357SAndroid Build Coastguard Worker     case MACH_MACHINE_ARM64: if ( be) return 0; filterId = k_ARM64; break;
350*f6dc9357SAndroid Build Coastguard Worker     default: return 0;
351*f6dc9357SAndroid Build Coastguard Worker   }
352*f6dc9357SAndroid Build Coastguard Worker 
353*f6dc9357SAndroid Build Coastguard Worker   numCommands = Get32(buf + 0x10, be);
354*f6dc9357SAndroid Build Coastguard Worker   commandsSize = Get32(buf + 0x14, be);
355*f6dc9357SAndroid Build Coastguard Worker 
356*f6dc9357SAndroid Build Coastguard Worker   if (commandsSize > (1 << 24) || numCommands > (1 << 18))
357*f6dc9357SAndroid Build Coastguard Worker     return 0;
358*f6dc9357SAndroid Build Coastguard Worker 
359*f6dc9357SAndroid Build Coastguard Worker   filterMode->Id = filterId;
360*f6dc9357SAndroid Build Coastguard Worker   return 1;
361*f6dc9357SAndroid Build Coastguard Worker }
362*f6dc9357SAndroid Build Coastguard Worker 
363*f6dc9357SAndroid Build Coastguard Worker 
364*f6dc9357SAndroid Build Coastguard Worker /* ---------- WAV ---------- */
365*f6dc9357SAndroid Build Coastguard Worker 
366*f6dc9357SAndroid Build Coastguard Worker #define WAV_SUBCHUNK_fmt  0x20746D66
367*f6dc9357SAndroid Build Coastguard Worker #define WAV_SUBCHUNK_data 0x61746164
368*f6dc9357SAndroid Build Coastguard Worker 
369*f6dc9357SAndroid Build Coastguard Worker #define RIFF_SIG 0x46464952
370*f6dc9357SAndroid Build Coastguard Worker 
Parse_WAV(const Byte * buf,size_t size,CFilterMode * filterMode)371*f6dc9357SAndroid Build Coastguard Worker static BoolInt Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode)
372*f6dc9357SAndroid Build Coastguard Worker {
373*f6dc9357SAndroid Build Coastguard Worker   UInt32 subChunkSize, pos;
374*f6dc9357SAndroid Build Coastguard Worker   if (size < 0x2C)
375*f6dc9357SAndroid Build Coastguard Worker     return False;
376*f6dc9357SAndroid Build Coastguard Worker 
377*f6dc9357SAndroid Build Coastguard Worker   if (GetUi32(buf + 0) != RIFF_SIG ||
378*f6dc9357SAndroid Build Coastguard Worker       GetUi32(buf + 8) != 0x45564157 || // WAVE
379*f6dc9357SAndroid Build Coastguard Worker       GetUi32(buf + 0xC) != WAV_SUBCHUNK_fmt)
380*f6dc9357SAndroid Build Coastguard Worker     return False;
381*f6dc9357SAndroid Build Coastguard Worker   subChunkSize = GetUi32(buf + 0x10);
382*f6dc9357SAndroid Build Coastguard Worker   /* [0x14 = format] = 1 (PCM) */
383*f6dc9357SAndroid Build Coastguard Worker   if (subChunkSize < 0x10 || subChunkSize > 0x12 || GetUi16(buf + 0x14) != 1)
384*f6dc9357SAndroid Build Coastguard Worker     return False;
385*f6dc9357SAndroid Build Coastguard Worker 
386*f6dc9357SAndroid Build Coastguard Worker   const unsigned numChannels = GetUi16(buf + 0x16);
387*f6dc9357SAndroid Build Coastguard Worker   const unsigned bitsPerSample = GetUi16(buf + 0x22);
388*f6dc9357SAndroid Build Coastguard Worker   if ((bitsPerSample & 0x7) != 0)
389*f6dc9357SAndroid Build Coastguard Worker     return False;
390*f6dc9357SAndroid Build Coastguard Worker   const UInt32 delta = (UInt32)numChannels * (bitsPerSample >> 3);
391*f6dc9357SAndroid Build Coastguard Worker   if (delta == 0 || delta > 256)
392*f6dc9357SAndroid Build Coastguard Worker     return False;
393*f6dc9357SAndroid Build Coastguard Worker 
394*f6dc9357SAndroid Build Coastguard Worker   pos = 0x14 + subChunkSize;
395*f6dc9357SAndroid Build Coastguard Worker 
396*f6dc9357SAndroid Build Coastguard Worker   const int kNumSubChunksTests = 10;
397*f6dc9357SAndroid Build Coastguard Worker   // Do we need to scan more than 3 sub-chunks?
398*f6dc9357SAndroid Build Coastguard Worker   for (int i = 0; i < kNumSubChunksTests; i++)
399*f6dc9357SAndroid Build Coastguard Worker   {
400*f6dc9357SAndroid Build Coastguard Worker     if (pos + 8 > size)
401*f6dc9357SAndroid Build Coastguard Worker       return False;
402*f6dc9357SAndroid Build Coastguard Worker     subChunkSize = GetUi32(buf + pos + 4);
403*f6dc9357SAndroid Build Coastguard Worker     if (GetUi32(buf + pos) == WAV_SUBCHUNK_data)
404*f6dc9357SAndroid Build Coastguard Worker     {
405*f6dc9357SAndroid Build Coastguard Worker       filterMode->Id = k_Delta;
406*f6dc9357SAndroid Build Coastguard Worker       filterMode->Delta = delta;
407*f6dc9357SAndroid Build Coastguard Worker       return True;
408*f6dc9357SAndroid Build Coastguard Worker     }
409*f6dc9357SAndroid Build Coastguard Worker     if (subChunkSize > (1 << 16))
410*f6dc9357SAndroid Build Coastguard Worker       return False;
411*f6dc9357SAndroid Build Coastguard Worker     pos += subChunkSize + 8;
412*f6dc9357SAndroid Build Coastguard Worker   }
413*f6dc9357SAndroid Build Coastguard Worker   return False;
414*f6dc9357SAndroid Build Coastguard Worker }
415*f6dc9357SAndroid Build Coastguard Worker 
416*f6dc9357SAndroid Build Coastguard Worker 
417*f6dc9357SAndroid Build Coastguard Worker /*
418*f6dc9357SAndroid Build Coastguard Worker   filterMode->Delta will be set as:
419*f6dc9357SAndroid Build Coastguard Worker     = delta value : [1, 256] : for k_Delta
420*f6dc9357SAndroid Build Coastguard Worker     = 0 for another filters (branch filters)
421*f6dc9357SAndroid Build Coastguard Worker */
ParseFile(const Byte * buf,size_t size,CFilterMode * filterMode)422*f6dc9357SAndroid Build Coastguard Worker static BoolInt ParseFile(const Byte *buf, size_t size, CFilterMode *filterMode)
423*f6dc9357SAndroid Build Coastguard Worker {
424*f6dc9357SAndroid Build Coastguard Worker   filterMode->ClearFilterMode();
425*f6dc9357SAndroid Build Coastguard Worker 
426*f6dc9357SAndroid Build Coastguard Worker   if (Parse_EXE(buf, size, filterMode)) return True;
427*f6dc9357SAndroid Build Coastguard Worker   if (Parse_ELF(buf, size, filterMode)) return True;
428*f6dc9357SAndroid Build Coastguard Worker   if (Parse_MACH(buf, size, filterMode)) return True;
429*f6dc9357SAndroid Build Coastguard Worker   return Parse_WAV(buf, size, filterMode);
430*f6dc9357SAndroid Build Coastguard Worker }
431*f6dc9357SAndroid Build Coastguard Worker 
432*f6dc9357SAndroid Build Coastguard Worker 
433*f6dc9357SAndroid Build Coastguard Worker 
434*f6dc9357SAndroid Build Coastguard Worker 
435*f6dc9357SAndroid Build Coastguard Worker struct CFilterMode2: public CFilterMode
436*f6dc9357SAndroid Build Coastguard Worker {
437*f6dc9357SAndroid Build Coastguard Worker   bool Encrypted;
438*f6dc9357SAndroid Build Coastguard Worker   unsigned GroupIndex;
439*f6dc9357SAndroid Build Coastguard Worker 
CFilterMode2NArchive::N7z::CFilterMode2440*f6dc9357SAndroid Build Coastguard Worker   CFilterMode2(): Encrypted(false) {}
441*f6dc9357SAndroid Build Coastguard Worker 
CompareNArchive::N7z::CFilterMode2442*f6dc9357SAndroid Build Coastguard Worker   int Compare(const CFilterMode2 &m) const
443*f6dc9357SAndroid Build Coastguard Worker   {
444*f6dc9357SAndroid Build Coastguard Worker     if (!Encrypted)
445*f6dc9357SAndroid Build Coastguard Worker     {
446*f6dc9357SAndroid Build Coastguard Worker       if (m.Encrypted)
447*f6dc9357SAndroid Build Coastguard Worker         return -1;
448*f6dc9357SAndroid Build Coastguard Worker     }
449*f6dc9357SAndroid Build Coastguard Worker     else if (!m.Encrypted)
450*f6dc9357SAndroid Build Coastguard Worker       return 1;
451*f6dc9357SAndroid Build Coastguard Worker 
452*f6dc9357SAndroid Build Coastguard Worker     const UInt32 id1 = Id;
453*f6dc9357SAndroid Build Coastguard Worker     const UInt32 id2 = m.Id;
454*f6dc9357SAndroid Build Coastguard Worker     /*
455*f6dc9357SAndroid Build Coastguard Worker     // we can change the order to place k_ARM64 files close to another exe files
456*f6dc9357SAndroid Build Coastguard Worker     if (id1 <= k_SPARC &&
457*f6dc9357SAndroid Build Coastguard Worker         id2 <= k_SPARC)
458*f6dc9357SAndroid Build Coastguard Worker     {
459*f6dc9357SAndroid Build Coastguard Worker       #define k_ARM64_FOR_SORT 0x3030901
460*f6dc9357SAndroid Build Coastguard Worker       if (id1 == k_ARM64) id1 = k_ARM64_FOR_SORT;
461*f6dc9357SAndroid Build Coastguard Worker       if (id2 == k_ARM64) id2 = k_ARM64_FOR_SORT;
462*f6dc9357SAndroid Build Coastguard Worker     }
463*f6dc9357SAndroid Build Coastguard Worker     */
464*f6dc9357SAndroid Build Coastguard Worker     if (id1 < id2) return -1;
465*f6dc9357SAndroid Build Coastguard Worker     if (id1 > id2) return 1;
466*f6dc9357SAndroid Build Coastguard Worker 
467*f6dc9357SAndroid Build Coastguard Worker     if (Delta < m.Delta) return -1;
468*f6dc9357SAndroid Build Coastguard Worker     if (Delta > m.Delta) return 1;
469*f6dc9357SAndroid Build Coastguard Worker 
470*f6dc9357SAndroid Build Coastguard Worker     if (Offset < m.Offset) return -1;
471*f6dc9357SAndroid Build Coastguard Worker     if (Offset > m.Offset) return 1;
472*f6dc9357SAndroid Build Coastguard Worker 
473*f6dc9357SAndroid Build Coastguard Worker     /* we don't go here, because GetGroup()
474*f6dc9357SAndroid Build Coastguard Worker        and operator ==(const CFilterMode2 &m)
475*f6dc9357SAndroid Build Coastguard Worker        add only unique CFilterMode2:: { Id, Delta, Offset, Encrypted } items.
476*f6dc9357SAndroid Build Coastguard Worker     */
477*f6dc9357SAndroid Build Coastguard Worker     /*
478*f6dc9357SAndroid Build Coastguard Worker     if (GroupIndex < m.GroupIndex) return -1;
479*f6dc9357SAndroid Build Coastguard Worker     if (GroupIndex > m.GroupIndex) return 1;
480*f6dc9357SAndroid Build Coastguard Worker     */
481*f6dc9357SAndroid Build Coastguard Worker     return 0;
482*f6dc9357SAndroid Build Coastguard Worker   }
483*f6dc9357SAndroid Build Coastguard Worker 
operator ==NArchive::N7z::CFilterMode2484*f6dc9357SAndroid Build Coastguard Worker   bool operator ==(const CFilterMode2 &m) const
485*f6dc9357SAndroid Build Coastguard Worker   {
486*f6dc9357SAndroid Build Coastguard Worker     return Id == m.Id
487*f6dc9357SAndroid Build Coastguard Worker         && Delta == m.Delta
488*f6dc9357SAndroid Build Coastguard Worker         && Offset == m.Offset
489*f6dc9357SAndroid Build Coastguard Worker         && Encrypted == m.Encrypted;
490*f6dc9357SAndroid Build Coastguard Worker   }
491*f6dc9357SAndroid Build Coastguard Worker };
492*f6dc9357SAndroid Build Coastguard Worker 
GetGroup(CRecordVector<CFilterMode2> & filters,const CFilterMode2 & m)493*f6dc9357SAndroid Build Coastguard Worker static unsigned GetGroup(CRecordVector<CFilterMode2> &filters, const CFilterMode2 &m)
494*f6dc9357SAndroid Build Coastguard Worker {
495*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
496*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < filters.Size(); i++)
497*f6dc9357SAndroid Build Coastguard Worker   {
498*f6dc9357SAndroid Build Coastguard Worker     const CFilterMode2 &m2 = filters[i];
499*f6dc9357SAndroid Build Coastguard Worker     if (m == m2)
500*f6dc9357SAndroid Build Coastguard Worker       return i;
501*f6dc9357SAndroid Build Coastguard Worker     /*
502*f6dc9357SAndroid Build Coastguard Worker     if (m.Encrypted != m2.Encrypted)
503*f6dc9357SAndroid Build Coastguard Worker     {
504*f6dc9357SAndroid Build Coastguard Worker       if (!m.Encrypted)
505*f6dc9357SAndroid Build Coastguard Worker         break;
506*f6dc9357SAndroid Build Coastguard Worker       continue;
507*f6dc9357SAndroid Build Coastguard Worker     }
508*f6dc9357SAndroid Build Coastguard Worker 
509*f6dc9357SAndroid Build Coastguard Worker     if (m.Id < m2.Id)  break;
510*f6dc9357SAndroid Build Coastguard Worker     if (m.Id != m2.Id) continue;
511*f6dc9357SAndroid Build Coastguard Worker 
512*f6dc9357SAndroid Build Coastguard Worker     if (m.Delta < m2.Delta) break;
513*f6dc9357SAndroid Build Coastguard Worker     if (m.Delta != m2.Delta) continue;
514*f6dc9357SAndroid Build Coastguard Worker     */
515*f6dc9357SAndroid Build Coastguard Worker   }
516*f6dc9357SAndroid Build Coastguard Worker   // filters.Insert(i, m);
517*f6dc9357SAndroid Build Coastguard Worker   // return i;
518*f6dc9357SAndroid Build Coastguard Worker   return filters.Add(m);
519*f6dc9357SAndroid Build Coastguard Worker }
520*f6dc9357SAndroid Build Coastguard Worker 
Is86Filter(CMethodId m)521*f6dc9357SAndroid Build Coastguard Worker static inline bool Is86Filter(CMethodId m)
522*f6dc9357SAndroid Build Coastguard Worker {
523*f6dc9357SAndroid Build Coastguard Worker   return (m == k_BCJ || m == k_BCJ2);
524*f6dc9357SAndroid Build Coastguard Worker }
525*f6dc9357SAndroid Build Coastguard Worker 
IsExeFilter(CMethodId m)526*f6dc9357SAndroid Build Coastguard Worker static inline bool IsExeFilter(CMethodId m)
527*f6dc9357SAndroid Build Coastguard Worker {
528*f6dc9357SAndroid Build Coastguard Worker   switch (m)
529*f6dc9357SAndroid Build Coastguard Worker   {
530*f6dc9357SAndroid Build Coastguard Worker     case k_ARM64:
531*f6dc9357SAndroid Build Coastguard Worker     case k_RISCV:
532*f6dc9357SAndroid Build Coastguard Worker     case k_BCJ:
533*f6dc9357SAndroid Build Coastguard Worker     case k_BCJ2:
534*f6dc9357SAndroid Build Coastguard Worker     case k_ARM:
535*f6dc9357SAndroid Build Coastguard Worker     case k_ARMT:
536*f6dc9357SAndroid Build Coastguard Worker     case k_PPC:
537*f6dc9357SAndroid Build Coastguard Worker     case k_SPARC:
538*f6dc9357SAndroid Build Coastguard Worker     case k_IA64:
539*f6dc9357SAndroid Build Coastguard Worker       return true;
540*f6dc9357SAndroid Build Coastguard Worker     default: break;
541*f6dc9357SAndroid Build Coastguard Worker   }
542*f6dc9357SAndroid Build Coastguard Worker   return false;
543*f6dc9357SAndroid Build Coastguard Worker }
544*f6dc9357SAndroid Build Coastguard Worker 
Get_FilterGroup_for_Folder(CRecordVector<CFilterMode2> & filters,const CFolderEx & f,bool extractFilter)545*f6dc9357SAndroid Build Coastguard Worker static unsigned Get_FilterGroup_for_Folder(
546*f6dc9357SAndroid Build Coastguard Worker     CRecordVector<CFilterMode2> &filters, const CFolderEx &f, bool extractFilter)
547*f6dc9357SAndroid Build Coastguard Worker {
548*f6dc9357SAndroid Build Coastguard Worker   CFilterMode2 m;
549*f6dc9357SAndroid Build Coastguard Worker   // m.Id = 0;
550*f6dc9357SAndroid Build Coastguard Worker   // m.Delta = 0;
551*f6dc9357SAndroid Build Coastguard Worker   // m.Offset = 0;
552*f6dc9357SAndroid Build Coastguard Worker   m.Encrypted = f.IsEncrypted();
553*f6dc9357SAndroid Build Coastguard Worker 
554*f6dc9357SAndroid Build Coastguard Worker   if (extractFilter)
555*f6dc9357SAndroid Build Coastguard Worker   {
556*f6dc9357SAndroid Build Coastguard Worker     const CCoderInfo &coder = f.Coders[f.UnpackCoder];
557*f6dc9357SAndroid Build Coastguard Worker 
558*f6dc9357SAndroid Build Coastguard Worker     if (coder.MethodID == k_Delta)
559*f6dc9357SAndroid Build Coastguard Worker     {
560*f6dc9357SAndroid Build Coastguard Worker       if (coder.Props.Size() == 1)
561*f6dc9357SAndroid Build Coastguard Worker       {
562*f6dc9357SAndroid Build Coastguard Worker         m.Delta = (unsigned)coder.Props[0] + 1;
563*f6dc9357SAndroid Build Coastguard Worker         m.Id = k_Delta;
564*f6dc9357SAndroid Build Coastguard Worker       }
565*f6dc9357SAndroid Build Coastguard Worker     }
566*f6dc9357SAndroid Build Coastguard Worker     else if (IsExeFilter(coder.MethodID))
567*f6dc9357SAndroid Build Coastguard Worker     {
568*f6dc9357SAndroid Build Coastguard Worker       m.Id = (UInt32)coder.MethodID;
569*f6dc9357SAndroid Build Coastguard Worker       if (m.Id == k_BCJ2)
570*f6dc9357SAndroid Build Coastguard Worker         m.Id = k_BCJ;
571*f6dc9357SAndroid Build Coastguard Worker       m.SetDelta();
572*f6dc9357SAndroid Build Coastguard Worker       if (m.Id == k_ARM64 ||
573*f6dc9357SAndroid Build Coastguard Worker           m.Id == k_RISCV)
574*f6dc9357SAndroid Build Coastguard Worker         if (coder.Props.Size() == 4)
575*f6dc9357SAndroid Build Coastguard Worker           m.Offset = GetUi32(coder.Props);
576*f6dc9357SAndroid Build Coastguard Worker     }
577*f6dc9357SAndroid Build Coastguard Worker   }
578*f6dc9357SAndroid Build Coastguard Worker 
579*f6dc9357SAndroid Build Coastguard Worker   return GetGroup(filters, m);
580*f6dc9357SAndroid Build Coastguard Worker }
581*f6dc9357SAndroid Build Coastguard Worker 
582*f6dc9357SAndroid Build Coastguard Worker 
583*f6dc9357SAndroid Build Coastguard Worker 
584*f6dc9357SAndroid Build Coastguard Worker 
WriteRange(IInStream * inStream,ISequentialOutStream * outStream,UInt64 position,UInt64 size,ICompressProgressInfo * progress)585*f6dc9357SAndroid Build Coastguard Worker static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,
586*f6dc9357SAndroid Build Coastguard Worker     UInt64 position, UInt64 size, ICompressProgressInfo *progress)
587*f6dc9357SAndroid Build Coastguard Worker {
588*f6dc9357SAndroid Build Coastguard Worker   RINOK(InStream_SeekSet(inStream, position))
589*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> streamSpec;
590*f6dc9357SAndroid Build Coastguard Worker   streamSpec->SetStream(inStream);
591*f6dc9357SAndroid Build Coastguard Worker   streamSpec->Init(size);
592*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
593*f6dc9357SAndroid Build Coastguard Worker   RINOK(copyCoder.Interface()->Code(streamSpec, outStream, NULL, NULL, progress))
594*f6dc9357SAndroid Build Coastguard Worker   return (copyCoder->TotalSize == size ? S_OK : E_FAIL);
595*f6dc9357SAndroid Build Coastguard Worker }
596*f6dc9357SAndroid Build Coastguard Worker 
597*f6dc9357SAndroid Build Coastguard Worker /*
598*f6dc9357SAndroid Build Coastguard Worker unsigned CUpdateItem::GetExtensionPos() const
599*f6dc9357SAndroid Build Coastguard Worker {
600*f6dc9357SAndroid Build Coastguard Worker   int slashPos = Name.ReverseFind_PathSepar();
601*f6dc9357SAndroid Build Coastguard Worker   int dotPos = Name.ReverseFind_Dot();
602*f6dc9357SAndroid Build Coastguard Worker   if (dotPos <= slashPos)
603*f6dc9357SAndroid Build Coastguard Worker     return Name.Len();
604*f6dc9357SAndroid Build Coastguard Worker   return dotPos + 1;
605*f6dc9357SAndroid Build Coastguard Worker }
606*f6dc9357SAndroid Build Coastguard Worker 
607*f6dc9357SAndroid Build Coastguard Worker UString CUpdateItem::GetExtension() const
608*f6dc9357SAndroid Build Coastguard Worker {
609*f6dc9357SAndroid Build Coastguard Worker   return Name.Ptr(GetExtensionPos());
610*f6dc9357SAndroid Build Coastguard Worker }
611*f6dc9357SAndroid Build Coastguard Worker */
612*f6dc9357SAndroid Build Coastguard Worker 
613*f6dc9357SAndroid Build Coastguard Worker #define RINOZ(x) { const int _t_ = (x); if (_t_ != 0) return _t_; }
614*f6dc9357SAndroid Build Coastguard Worker 
615*f6dc9357SAndroid Build Coastguard Worker #define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b))
616*f6dc9357SAndroid Build Coastguard Worker 
617*f6dc9357SAndroid Build Coastguard Worker /*
618*f6dc9357SAndroid Build Coastguard Worker static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2)
619*f6dc9357SAndroid Build Coastguard Worker {
620*f6dc9357SAndroid Build Coastguard Worker   size_t c1 = a1.GetCapacity();
621*f6dc9357SAndroid Build Coastguard Worker   size_t c2 = a2.GetCapacity();
622*f6dc9357SAndroid Build Coastguard Worker   RINOZ_COMP(c1, c2);
623*f6dc9357SAndroid Build Coastguard Worker   for (size_t i = 0; i < c1; i++)
624*f6dc9357SAndroid Build Coastguard Worker     RINOZ_COMP(a1[i], a2[i]);
625*f6dc9357SAndroid Build Coastguard Worker   return 0;
626*f6dc9357SAndroid Build Coastguard Worker }
627*f6dc9357SAndroid Build Coastguard Worker 
628*f6dc9357SAndroid Build Coastguard Worker static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2)
629*f6dc9357SAndroid Build Coastguard Worker {
630*f6dc9357SAndroid Build Coastguard Worker   RINOZ_COMP(c1.NumInStreams, c2.NumInStreams);
631*f6dc9357SAndroid Build Coastguard Worker   RINOZ_COMP(c1.NumOutStreams, c2.NumOutStreams);
632*f6dc9357SAndroid Build Coastguard Worker   RINOZ_COMP(c1.MethodID, c2.MethodID);
633*f6dc9357SAndroid Build Coastguard Worker   return CompareBuffers(c1.Props, c2.Props);
634*f6dc9357SAndroid Build Coastguard Worker }
635*f6dc9357SAndroid Build Coastguard Worker 
636*f6dc9357SAndroid Build Coastguard Worker static int CompareBonds(const CBond &b1, const CBond &b2)
637*f6dc9357SAndroid Build Coastguard Worker {
638*f6dc9357SAndroid Build Coastguard Worker   RINOZ_COMP(b1.InIndex, b2.InIndex);
639*f6dc9357SAndroid Build Coastguard Worker   return MyCompare(b1.OutIndex, b2.OutIndex);
640*f6dc9357SAndroid Build Coastguard Worker }
641*f6dc9357SAndroid Build Coastguard Worker 
642*f6dc9357SAndroid Build Coastguard Worker static int CompareFolders(const CFolder &f1, const CFolder &f2)
643*f6dc9357SAndroid Build Coastguard Worker {
644*f6dc9357SAndroid Build Coastguard Worker   int s1 = f1.Coders.Size();
645*f6dc9357SAndroid Build Coastguard Worker   int s2 = f2.Coders.Size();
646*f6dc9357SAndroid Build Coastguard Worker   RINOZ_COMP(s1, s2);
647*f6dc9357SAndroid Build Coastguard Worker   int i;
648*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < s1; i++)
649*f6dc9357SAndroid Build Coastguard Worker     RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i]));
650*f6dc9357SAndroid Build Coastguard Worker   s1 = f1.Bonds.Size();
651*f6dc9357SAndroid Build Coastguard Worker   s2 = f2.Bonds.Size();
652*f6dc9357SAndroid Build Coastguard Worker   RINOZ_COMP(s1, s2);
653*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < s1; i++)
654*f6dc9357SAndroid Build Coastguard Worker     RINOZ(CompareBonds(f1.Bonds[i], f2.Bonds[i]));
655*f6dc9357SAndroid Build Coastguard Worker   return 0;
656*f6dc9357SAndroid Build Coastguard Worker }
657*f6dc9357SAndroid Build Coastguard Worker */
658*f6dc9357SAndroid Build Coastguard Worker 
659*f6dc9357SAndroid Build Coastguard Worker /*
660*f6dc9357SAndroid Build Coastguard Worker static int CompareFiles(const CFileItem &f1, const CFileItem &f2)
661*f6dc9357SAndroid Build Coastguard Worker {
662*f6dc9357SAndroid Build Coastguard Worker   return CompareFileNames(f1.Name, f2.Name);
663*f6dc9357SAndroid Build Coastguard Worker }
664*f6dc9357SAndroid Build Coastguard Worker */
665*f6dc9357SAndroid Build Coastguard Worker 
666*f6dc9357SAndroid Build Coastguard Worker struct CFolderRepack
667*f6dc9357SAndroid Build Coastguard Worker {
668*f6dc9357SAndroid Build Coastguard Worker   unsigned FolderIndex;
669*f6dc9357SAndroid Build Coastguard Worker   CNum NumCopyFiles;
670*f6dc9357SAndroid Build Coastguard Worker };
671*f6dc9357SAndroid Build Coastguard Worker 
672*f6dc9357SAndroid Build Coastguard Worker /*
673*f6dc9357SAndroid Build Coastguard Worker static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *)
674*f6dc9357SAndroid Build Coastguard Worker {
675*f6dc9357SAndroid Build Coastguard Worker   int i1 = p1->FolderIndex;
676*f6dc9357SAndroid Build Coastguard Worker   int i2 = p2->FolderIndex;
677*f6dc9357SAndroid Build Coastguard Worker   // In that version we don't want to parse folders here, so we don't compare folders
678*f6dc9357SAndroid Build Coastguard Worker   // probably it must be improved in future
679*f6dc9357SAndroid Build Coastguard Worker   // const CDbEx &db = *(const CDbEx *)param;
680*f6dc9357SAndroid Build Coastguard Worker   // RINOZ(CompareFolders(
681*f6dc9357SAndroid Build Coastguard Worker   //     db.Folders[i1],
682*f6dc9357SAndroid Build Coastguard Worker   //     db.Folders[i2]));
683*f6dc9357SAndroid Build Coastguard Worker 
684*f6dc9357SAndroid Build Coastguard Worker   return MyCompare(i1, i2);
685*f6dc9357SAndroid Build Coastguard Worker 
686*f6dc9357SAndroid Build Coastguard Worker   // RINOZ_COMP(
687*f6dc9357SAndroid Build Coastguard Worker   //     db.NumUnpackStreamsVector[i1],
688*f6dc9357SAndroid Build Coastguard Worker   //     db.NumUnpackStreamsVector[i2]);
689*f6dc9357SAndroid Build Coastguard Worker   // if (db.NumUnpackStreamsVector[i1] == 0)
690*f6dc9357SAndroid Build Coastguard Worker   //   return 0;
691*f6dc9357SAndroid Build Coastguard Worker   // return CompareFiles(
692*f6dc9357SAndroid Build Coastguard Worker   //     db.Files[db.FolderStartFileIndex[i1]],
693*f6dc9357SAndroid Build Coastguard Worker   //     db.Files[db.FolderStartFileIndex[i2]]);
694*f6dc9357SAndroid Build Coastguard Worker }
695*f6dc9357SAndroid Build Coastguard Worker */
696*f6dc9357SAndroid Build Coastguard Worker 
697*f6dc9357SAndroid Build Coastguard Worker /*
698*f6dc9357SAndroid Build Coastguard Worker   we sort empty files and dirs in such order:
699*f6dc9357SAndroid Build Coastguard Worker   - Dir.NonAnti   (name sorted)
700*f6dc9357SAndroid Build Coastguard Worker   - File.NonAnti  (name sorted)
701*f6dc9357SAndroid Build Coastguard Worker   - File.Anti     (name sorted)
702*f6dc9357SAndroid Build Coastguard Worker   - Dir.Anti (reverse name sorted)
703*f6dc9357SAndroid Build Coastguard Worker */
704*f6dc9357SAndroid Build Coastguard Worker 
CompareEmptyItems(const unsigned * p1,const unsigned * p2,void * param)705*f6dc9357SAndroid Build Coastguard Worker static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param)
706*f6dc9357SAndroid Build Coastguard Worker {
707*f6dc9357SAndroid Build Coastguard Worker   const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param;
708*f6dc9357SAndroid Build Coastguard Worker   const CUpdateItem &u1 = updateItems[*p1];
709*f6dc9357SAndroid Build Coastguard Worker   const CUpdateItem &u2 = updateItems[*p2];
710*f6dc9357SAndroid Build Coastguard Worker   // NonAnti < Anti
711*f6dc9357SAndroid Build Coastguard Worker   if (u1.IsAnti != u2.IsAnti)
712*f6dc9357SAndroid Build Coastguard Worker     return (u1.IsAnti ? 1 : -1);
713*f6dc9357SAndroid Build Coastguard Worker   if (u1.IsDir != u2.IsDir)
714*f6dc9357SAndroid Build Coastguard Worker   {
715*f6dc9357SAndroid Build Coastguard Worker     // Dir.NonAnti < File < Dir.Anti
716*f6dc9357SAndroid Build Coastguard Worker     if (u1.IsDir)
717*f6dc9357SAndroid Build Coastguard Worker       return (u1.IsAnti ? 1 : -1);
718*f6dc9357SAndroid Build Coastguard Worker     return (u2.IsAnti ? -1 : 1);
719*f6dc9357SAndroid Build Coastguard Worker   }
720*f6dc9357SAndroid Build Coastguard Worker   int n = CompareFileNames(u1.Name, u2.Name);
721*f6dc9357SAndroid Build Coastguard Worker   return (u1.IsDir && u1.IsAnti) ? -n : n;
722*f6dc9357SAndroid Build Coastguard Worker }
723*f6dc9357SAndroid Build Coastguard Worker 
724*f6dc9357SAndroid Build Coastguard Worker static const char *g_Exts =
725*f6dc9357SAndroid Build Coastguard Worker   " 7z xz lzma ace arc arj bz tbz bz2 tbz2 cab deb gz tgz ha lha lzh lzo lzx pak rar rpm sit zoo"
726*f6dc9357SAndroid Build Coastguard Worker   " zip jar ear war msi"
727*f6dc9357SAndroid Build Coastguard Worker   " 3gp avi mov mpeg mpg mpe wmv"
728*f6dc9357SAndroid Build Coastguard Worker   " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav"
729*f6dc9357SAndroid Build Coastguard Worker   " swf"
730*f6dc9357SAndroid Build Coastguard Worker   " chm hxi hxs"
731*f6dc9357SAndroid Build Coastguard Worker   " gif jpeg jpg jp2 png tiff  bmp ico psd psp"
732*f6dc9357SAndroid Build Coastguard Worker   " awg ps eps cgm dxf svg vrml wmf emf ai md"
733*f6dc9357SAndroid Build Coastguard Worker   " cad dwg pps key sxi"
734*f6dc9357SAndroid Build Coastguard Worker   " max 3ds"
735*f6dc9357SAndroid Build Coastguard Worker   " iso bin nrg mdf img pdi tar cpio xpi"
736*f6dc9357SAndroid Build Coastguard Worker   " vfd vhd vud vmc vsv"
737*f6dc9357SAndroid Build Coastguard Worker   " vmdk dsk nvram vmem vmsd vmsn vmss vmtm"
738*f6dc9357SAndroid Build Coastguard Worker   " inl inc idl acf asa"
739*f6dc9357SAndroid Build Coastguard Worker   " h hpp hxx c cpp cxx m mm go swift"
740*f6dc9357SAndroid Build Coastguard Worker   " rc java cs rs pas bas vb cls ctl frm dlg def"
741*f6dc9357SAndroid Build Coastguard Worker   " f77 f f90 f95"
742*f6dc9357SAndroid Build Coastguard Worker   " asm s"
743*f6dc9357SAndroid Build Coastguard Worker   " sql manifest dep"
744*f6dc9357SAndroid Build Coastguard Worker   " mak clw csproj vcproj sln dsp dsw"
745*f6dc9357SAndroid Build Coastguard Worker   " class"
746*f6dc9357SAndroid Build Coastguard Worker   " bat cmd bash sh"
747*f6dc9357SAndroid Build Coastguard Worker   " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml"
748*f6dc9357SAndroid Build Coastguard Worker   " awk sed hta js json php php3 php4 php5 phptml pl pm py pyo rb tcl ts vbs"
749*f6dc9357SAndroid Build Coastguard Worker   " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf"
750*f6dc9357SAndroid Build Coastguard Worker   " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf"
751*f6dc9357SAndroid Build Coastguard Worker   " abw afp cwk lwp wpd wps wpt wrf wri"
752*f6dc9357SAndroid Build Coastguard Worker   " abf afm bdf fon mgf otf pcf pfa snf ttf"
753*f6dc9357SAndroid Build Coastguard Worker   " dbf mdb nsf ntf wdb db fdb gdb"
754*f6dc9357SAndroid Build Coastguard Worker   " exe dll ocx vbx sfx sys tlb awx com obj lib out o so"
755*f6dc9357SAndroid Build Coastguard Worker   " pdb pch idb ncb opt";
756*f6dc9357SAndroid Build Coastguard Worker 
GetExtIndex(const char * ext)757*f6dc9357SAndroid Build Coastguard Worker static unsigned GetExtIndex(const char *ext)
758*f6dc9357SAndroid Build Coastguard Worker {
759*f6dc9357SAndroid Build Coastguard Worker   unsigned extIndex = 1;
760*f6dc9357SAndroid Build Coastguard Worker   const char *p = g_Exts;
761*f6dc9357SAndroid Build Coastguard Worker   for (;;)
762*f6dc9357SAndroid Build Coastguard Worker   {
763*f6dc9357SAndroid Build Coastguard Worker     char c = *p++;
764*f6dc9357SAndroid Build Coastguard Worker     if (c == 0)
765*f6dc9357SAndroid Build Coastguard Worker       return extIndex;
766*f6dc9357SAndroid Build Coastguard Worker     if (c == ' ')
767*f6dc9357SAndroid Build Coastguard Worker       continue;
768*f6dc9357SAndroid Build Coastguard Worker     unsigned pos = 0;
769*f6dc9357SAndroid Build Coastguard Worker     for (;;)
770*f6dc9357SAndroid Build Coastguard Worker     {
771*f6dc9357SAndroid Build Coastguard Worker       char c2 = ext[pos++];
772*f6dc9357SAndroid Build Coastguard Worker       if (c2 == 0 && (c == 0 || c == ' '))
773*f6dc9357SAndroid Build Coastguard Worker         return extIndex;
774*f6dc9357SAndroid Build Coastguard Worker       if (c != c2)
775*f6dc9357SAndroid Build Coastguard Worker         break;
776*f6dc9357SAndroid Build Coastguard Worker       c = *p++;
777*f6dc9357SAndroid Build Coastguard Worker     }
778*f6dc9357SAndroid Build Coastguard Worker     extIndex++;
779*f6dc9357SAndroid Build Coastguard Worker     for (;;)
780*f6dc9357SAndroid Build Coastguard Worker     {
781*f6dc9357SAndroid Build Coastguard Worker       if (c == 0)
782*f6dc9357SAndroid Build Coastguard Worker         return extIndex;
783*f6dc9357SAndroid Build Coastguard Worker       if (c == ' ')
784*f6dc9357SAndroid Build Coastguard Worker         break;
785*f6dc9357SAndroid Build Coastguard Worker       c = *p++;
786*f6dc9357SAndroid Build Coastguard Worker     }
787*f6dc9357SAndroid Build Coastguard Worker   }
788*f6dc9357SAndroid Build Coastguard Worker }
789*f6dc9357SAndroid Build Coastguard Worker 
790*f6dc9357SAndroid Build Coastguard Worker struct CRefItem
791*f6dc9357SAndroid Build Coastguard Worker {
792*f6dc9357SAndroid Build Coastguard Worker   const CUpdateItem *UpdateItem;
793*f6dc9357SAndroid Build Coastguard Worker   UInt32 Index;
794*f6dc9357SAndroid Build Coastguard Worker   unsigned ExtensionPos;
795*f6dc9357SAndroid Build Coastguard Worker   unsigned NamePos;
796*f6dc9357SAndroid Build Coastguard Worker   unsigned ExtensionIndex;
797*f6dc9357SAndroid Build Coastguard Worker 
CRefItemNArchive::N7z::CRefItem798*f6dc9357SAndroid Build Coastguard Worker   CRefItem() {}
CRefItemNArchive::N7z::CRefItem799*f6dc9357SAndroid Build Coastguard Worker   CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType):
800*f6dc9357SAndroid Build Coastguard Worker     UpdateItem(&ui),
801*f6dc9357SAndroid Build Coastguard Worker     Index(index),
802*f6dc9357SAndroid Build Coastguard Worker     ExtensionPos(0),
803*f6dc9357SAndroid Build Coastguard Worker     NamePos(0),
804*f6dc9357SAndroid Build Coastguard Worker     ExtensionIndex(0)
805*f6dc9357SAndroid Build Coastguard Worker   {
806*f6dc9357SAndroid Build Coastguard Worker     if (sortByType)
807*f6dc9357SAndroid Build Coastguard Worker     {
808*f6dc9357SAndroid Build Coastguard Worker       const int slashPos = ui.Name.ReverseFind_PathSepar();
809*f6dc9357SAndroid Build Coastguard Worker       NamePos = (unsigned)(slashPos + 1);
810*f6dc9357SAndroid Build Coastguard Worker       const int dotPos = ui.Name.ReverseFind_Dot();
811*f6dc9357SAndroid Build Coastguard Worker       if (dotPos <= slashPos)
812*f6dc9357SAndroid Build Coastguard Worker         ExtensionPos = ui.Name.Len();
813*f6dc9357SAndroid Build Coastguard Worker       else
814*f6dc9357SAndroid Build Coastguard Worker       {
815*f6dc9357SAndroid Build Coastguard Worker         ExtensionPos = (unsigned)(dotPos + 1);
816*f6dc9357SAndroid Build Coastguard Worker         if (ExtensionPos != ui.Name.Len())
817*f6dc9357SAndroid Build Coastguard Worker         {
818*f6dc9357SAndroid Build Coastguard Worker           AString s;
819*f6dc9357SAndroid Build Coastguard Worker           for (unsigned pos = ExtensionPos;; pos++)
820*f6dc9357SAndroid Build Coastguard Worker           {
821*f6dc9357SAndroid Build Coastguard Worker             const wchar_t c = ui.Name[pos];
822*f6dc9357SAndroid Build Coastguard Worker             if (c >= 0x80)
823*f6dc9357SAndroid Build Coastguard Worker               break;
824*f6dc9357SAndroid Build Coastguard Worker             if (c == 0)
825*f6dc9357SAndroid Build Coastguard Worker             {
826*f6dc9357SAndroid Build Coastguard Worker               ExtensionIndex = GetExtIndex(s);
827*f6dc9357SAndroid Build Coastguard Worker               break;
828*f6dc9357SAndroid Build Coastguard Worker             }
829*f6dc9357SAndroid Build Coastguard Worker             s.Add_Char((char)MyCharLower_Ascii((char)c));
830*f6dc9357SAndroid Build Coastguard Worker           }
831*f6dc9357SAndroid Build Coastguard Worker         }
832*f6dc9357SAndroid Build Coastguard Worker       }
833*f6dc9357SAndroid Build Coastguard Worker     }
834*f6dc9357SAndroid Build Coastguard Worker   }
835*f6dc9357SAndroid Build Coastguard Worker };
836*f6dc9357SAndroid Build Coastguard Worker 
837*f6dc9357SAndroid Build Coastguard Worker struct CSortParam
838*f6dc9357SAndroid Build Coastguard Worker {
839*f6dc9357SAndroid Build Coastguard Worker   // const CObjectVector<CTreeFolder> *TreeFolders;
840*f6dc9357SAndroid Build Coastguard Worker   bool SortByType;
841*f6dc9357SAndroid Build Coastguard Worker };
842*f6dc9357SAndroid Build Coastguard Worker 
843*f6dc9357SAndroid Build Coastguard Worker /*
844*f6dc9357SAndroid Build Coastguard Worker   we sort files in such order:
845*f6dc9357SAndroid Build Coastguard Worker   - Dir.NonAnti   (name sorted)
846*f6dc9357SAndroid Build Coastguard Worker   - alt streams
847*f6dc9357SAndroid Build Coastguard Worker   - Dirs
848*f6dc9357SAndroid Build Coastguard Worker   - Dir.Anti (reverse name sorted)
849*f6dc9357SAndroid Build Coastguard Worker */
850*f6dc9357SAndroid Build Coastguard Worker 
851*f6dc9357SAndroid Build Coastguard Worker 
CompareUpdateItems(const CRefItem * p1,const CRefItem * p2,void * param)852*f6dc9357SAndroid Build Coastguard Worker static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param)
853*f6dc9357SAndroid Build Coastguard Worker {
854*f6dc9357SAndroid Build Coastguard Worker   const CRefItem &a1 = *p1;
855*f6dc9357SAndroid Build Coastguard Worker   const CRefItem &a2 = *p2;
856*f6dc9357SAndroid Build Coastguard Worker   const CUpdateItem &u1 = *a1.UpdateItem;
857*f6dc9357SAndroid Build Coastguard Worker   const CUpdateItem &u2 = *a2.UpdateItem;
858*f6dc9357SAndroid Build Coastguard Worker 
859*f6dc9357SAndroid Build Coastguard Worker   /*
860*f6dc9357SAndroid Build Coastguard Worker   if (u1.IsAltStream != u2.IsAltStream)
861*f6dc9357SAndroid Build Coastguard Worker     return u1.IsAltStream ? 1 : -1;
862*f6dc9357SAndroid Build Coastguard Worker   */
863*f6dc9357SAndroid Build Coastguard Worker 
864*f6dc9357SAndroid Build Coastguard Worker   // Actually there are no dirs that time. They were stored in other steps
865*f6dc9357SAndroid Build Coastguard Worker   // So that code is unused?
866*f6dc9357SAndroid Build Coastguard Worker   if (u1.IsDir != u2.IsDir)
867*f6dc9357SAndroid Build Coastguard Worker     return u1.IsDir ? 1 : -1;
868*f6dc9357SAndroid Build Coastguard Worker   if (u1.IsDir)
869*f6dc9357SAndroid Build Coastguard Worker   {
870*f6dc9357SAndroid Build Coastguard Worker     if (u1.IsAnti != u2.IsAnti)
871*f6dc9357SAndroid Build Coastguard Worker       return (u1.IsAnti ? 1 : -1);
872*f6dc9357SAndroid Build Coastguard Worker     int n = CompareFileNames(u1.Name, u2.Name);
873*f6dc9357SAndroid Build Coastguard Worker     return -n;
874*f6dc9357SAndroid Build Coastguard Worker   }
875*f6dc9357SAndroid Build Coastguard Worker 
876*f6dc9357SAndroid Build Coastguard Worker   // bool sortByType = *(bool *)param;
877*f6dc9357SAndroid Build Coastguard Worker   const CSortParam *sortParam = (const CSortParam *)param;
878*f6dc9357SAndroid Build Coastguard Worker   const bool sortByType = sortParam->SortByType;
879*f6dc9357SAndroid Build Coastguard Worker   if (sortByType)
880*f6dc9357SAndroid Build Coastguard Worker   {
881*f6dc9357SAndroid Build Coastguard Worker     RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex)
882*f6dc9357SAndroid Build Coastguard Worker     RINOZ(CompareFileNames(u1.Name.Ptr(a1.ExtensionPos), u2.Name.Ptr(a2.ExtensionPos)))
883*f6dc9357SAndroid Build Coastguard Worker     RINOZ(CompareFileNames(u1.Name.Ptr(a1.NamePos), u2.Name.Ptr(a2.NamePos)))
884*f6dc9357SAndroid Build Coastguard Worker     if (!u1.MTimeDefined && u2.MTimeDefined) return 1;
885*f6dc9357SAndroid Build Coastguard Worker     if (u1.MTimeDefined && !u2.MTimeDefined) return -1;
886*f6dc9357SAndroid Build Coastguard Worker     if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime)
887*f6dc9357SAndroid Build Coastguard Worker     RINOZ_COMP(u1.Size, u2.Size)
888*f6dc9357SAndroid Build Coastguard Worker   }
889*f6dc9357SAndroid Build Coastguard Worker   /*
890*f6dc9357SAndroid Build Coastguard Worker   int par1 = a1.UpdateItem->ParentFolderIndex;
891*f6dc9357SAndroid Build Coastguard Worker   int par2 = a2.UpdateItem->ParentFolderIndex;
892*f6dc9357SAndroid Build Coastguard Worker   const CTreeFolder &tf1 = (*sortParam->TreeFolders)[par1];
893*f6dc9357SAndroid Build Coastguard Worker   const CTreeFolder &tf2 = (*sortParam->TreeFolders)[par2];
894*f6dc9357SAndroid Build Coastguard Worker 
895*f6dc9357SAndroid Build Coastguard Worker   int b1 = tf1.SortIndex, e1 = tf1.SortIndexEnd;
896*f6dc9357SAndroid Build Coastguard Worker   int b2 = tf2.SortIndex, e2 = tf2.SortIndexEnd;
897*f6dc9357SAndroid Build Coastguard Worker   if (b1 < b2)
898*f6dc9357SAndroid Build Coastguard Worker   {
899*f6dc9357SAndroid Build Coastguard Worker     if (e1 <= b2)
900*f6dc9357SAndroid Build Coastguard Worker       return -1;
901*f6dc9357SAndroid Build Coastguard Worker     // p2 in p1
902*f6dc9357SAndroid Build Coastguard Worker     int par = par2;
903*f6dc9357SAndroid Build Coastguard Worker     for (;;)
904*f6dc9357SAndroid Build Coastguard Worker     {
905*f6dc9357SAndroid Build Coastguard Worker       const CTreeFolder &tf = (*sortParam->TreeFolders)[par];
906*f6dc9357SAndroid Build Coastguard Worker       par = tf.Parent;
907*f6dc9357SAndroid Build Coastguard Worker       if (par == par1)
908*f6dc9357SAndroid Build Coastguard Worker       {
909*f6dc9357SAndroid Build Coastguard Worker         RINOZ(CompareFileNames(u1.Name, tf.Name));
910*f6dc9357SAndroid Build Coastguard Worker         break;
911*f6dc9357SAndroid Build Coastguard Worker       }
912*f6dc9357SAndroid Build Coastguard Worker     }
913*f6dc9357SAndroid Build Coastguard Worker   }
914*f6dc9357SAndroid Build Coastguard Worker   else if (b2 < b1)
915*f6dc9357SAndroid Build Coastguard Worker   {
916*f6dc9357SAndroid Build Coastguard Worker     if (e2 <= b1)
917*f6dc9357SAndroid Build Coastguard Worker       return 1;
918*f6dc9357SAndroid Build Coastguard Worker     // p1 in p2
919*f6dc9357SAndroid Build Coastguard Worker     int par = par1;
920*f6dc9357SAndroid Build Coastguard Worker     for (;;)
921*f6dc9357SAndroid Build Coastguard Worker     {
922*f6dc9357SAndroid Build Coastguard Worker       const CTreeFolder &tf = (*sortParam->TreeFolders)[par];
923*f6dc9357SAndroid Build Coastguard Worker       par = tf.Parent;
924*f6dc9357SAndroid Build Coastguard Worker       if (par == par2)
925*f6dc9357SAndroid Build Coastguard Worker       {
926*f6dc9357SAndroid Build Coastguard Worker         RINOZ(CompareFileNames(tf.Name, u2.Name));
927*f6dc9357SAndroid Build Coastguard Worker         break;
928*f6dc9357SAndroid Build Coastguard Worker       }
929*f6dc9357SAndroid Build Coastguard Worker     }
930*f6dc9357SAndroid Build Coastguard Worker   }
931*f6dc9357SAndroid Build Coastguard Worker   */
932*f6dc9357SAndroid Build Coastguard Worker   // RINOZ_COMP(a1.UpdateItem->ParentSortIndex, a2.UpdateItem->ParentSortIndex);
933*f6dc9357SAndroid Build Coastguard Worker   RINOK(CompareFileNames(u1.Name, u2.Name))
934*f6dc9357SAndroid Build Coastguard Worker   RINOZ_COMP(a1.UpdateItem->IndexInClient, a2.UpdateItem->IndexInClient)
935*f6dc9357SAndroid Build Coastguard Worker   RINOZ_COMP(a1.UpdateItem->IndexInArchive, a2.UpdateItem->IndexInArchive)
936*f6dc9357SAndroid Build Coastguard Worker   return 0;
937*f6dc9357SAndroid Build Coastguard Worker }
938*f6dc9357SAndroid Build Coastguard Worker 
939*f6dc9357SAndroid Build Coastguard Worker struct CSolidGroup
940*f6dc9357SAndroid Build Coastguard Worker {
941*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<UInt32> Indices;
942*f6dc9357SAndroid Build Coastguard Worker 
943*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<CFolderRepack> folderRefs;
944*f6dc9357SAndroid Build Coastguard Worker };
945*f6dc9357SAndroid Build Coastguard Worker 
946*f6dc9357SAndroid Build Coastguard Worker static const char * const g_Exe_Exts[] =
947*f6dc9357SAndroid Build Coastguard Worker {
948*f6dc9357SAndroid Build Coastguard Worker     "dll"
949*f6dc9357SAndroid Build Coastguard Worker   , "exe"
950*f6dc9357SAndroid Build Coastguard Worker   , "ocx"
951*f6dc9357SAndroid Build Coastguard Worker   , "sfx"
952*f6dc9357SAndroid Build Coastguard Worker   , "sys"
953*f6dc9357SAndroid Build Coastguard Worker };
954*f6dc9357SAndroid Build Coastguard Worker 
955*f6dc9357SAndroid Build Coastguard Worker static const char * const g_ExeUnix_Exts[] =
956*f6dc9357SAndroid Build Coastguard Worker {
957*f6dc9357SAndroid Build Coastguard Worker     "so"
958*f6dc9357SAndroid Build Coastguard Worker   , "dylib"
959*f6dc9357SAndroid Build Coastguard Worker };
960*f6dc9357SAndroid Build Coastguard Worker 
IsExt_Exe(const wchar_t * ext)961*f6dc9357SAndroid Build Coastguard Worker static bool IsExt_Exe(const wchar_t *ext)
962*f6dc9357SAndroid Build Coastguard Worker {
963*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_Exe_Exts); i++)
964*f6dc9357SAndroid Build Coastguard Worker     if (StringsAreEqualNoCase_Ascii(ext, g_Exe_Exts[i]))
965*f6dc9357SAndroid Build Coastguard Worker       return true;
966*f6dc9357SAndroid Build Coastguard Worker   return false;
967*f6dc9357SAndroid Build Coastguard Worker }
968*f6dc9357SAndroid Build Coastguard Worker 
969*f6dc9357SAndroid Build Coastguard Worker /*
970*f6dc9357SAndroid Build Coastguard Worker static bool IsExt_ExeUnix(const wchar_t *ext)
971*f6dc9357SAndroid Build Coastguard Worker {
972*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ExeUnix_Exts); i++)
973*f6dc9357SAndroid Build Coastguard Worker     if (StringsAreEqualNoCase_Ascii(ext, g_ExeUnix_Exts[i]))
974*f6dc9357SAndroid Build Coastguard Worker       return true;
975*f6dc9357SAndroid Build Coastguard Worker   return false;
976*f6dc9357SAndroid Build Coastguard Worker }
977*f6dc9357SAndroid Build Coastguard Worker */
978*f6dc9357SAndroid Build Coastguard Worker 
979*f6dc9357SAndroid Build Coastguard Worker // we try to find "so" extension in such name: libstdc++.so.6.0.29
IsExt_ExeUnix_NumericAllowed(const UString & path)980*f6dc9357SAndroid Build Coastguard Worker static bool IsExt_ExeUnix_NumericAllowed(const UString &path)
981*f6dc9357SAndroid Build Coastguard Worker {
982*f6dc9357SAndroid Build Coastguard Worker   unsigned pos = path.Len();
983*f6dc9357SAndroid Build Coastguard Worker   unsigned dotPos = pos;
984*f6dc9357SAndroid Build Coastguard Worker   for (;;)
985*f6dc9357SAndroid Build Coastguard Worker   {
986*f6dc9357SAndroid Build Coastguard Worker     if (pos == 0)
987*f6dc9357SAndroid Build Coastguard Worker       return false;
988*f6dc9357SAndroid Build Coastguard Worker     const wchar_t c = path[--pos];
989*f6dc9357SAndroid Build Coastguard Worker     if (IS_PATH_SEPAR(c))
990*f6dc9357SAndroid Build Coastguard Worker       return false;
991*f6dc9357SAndroid Build Coastguard Worker     if (c == '.')
992*f6dc9357SAndroid Build Coastguard Worker     {
993*f6dc9357SAndroid Build Coastguard Worker       const unsigned num = (dotPos - pos) - 1;
994*f6dc9357SAndroid Build Coastguard Worker       if (num < 1)
995*f6dc9357SAndroid Build Coastguard Worker         return false;
996*f6dc9357SAndroid Build Coastguard Worker       const wchar_t *cur = path.Ptr(pos + 1);
997*f6dc9357SAndroid Build Coastguard Worker       for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ExeUnix_Exts); i++)
998*f6dc9357SAndroid Build Coastguard Worker       {
999*f6dc9357SAndroid Build Coastguard Worker         const char *ext = g_ExeUnix_Exts[i];
1000*f6dc9357SAndroid Build Coastguard Worker         if (num == MyStringLen(ext))
1001*f6dc9357SAndroid Build Coastguard Worker           if (IsString1PrefixedByString2_NoCase_Ascii(cur, ext))
1002*f6dc9357SAndroid Build Coastguard Worker             return true;
1003*f6dc9357SAndroid Build Coastguard Worker       }
1004*f6dc9357SAndroid Build Coastguard Worker       const wchar_t *end;
1005*f6dc9357SAndroid Build Coastguard Worker       ConvertStringToUInt32(cur, &end);
1006*f6dc9357SAndroid Build Coastguard Worker       if ((size_t)(end - cur) != num)
1007*f6dc9357SAndroid Build Coastguard Worker         return false;
1008*f6dc9357SAndroid Build Coastguard Worker       dotPos = pos;
1009*f6dc9357SAndroid Build Coastguard Worker     }
1010*f6dc9357SAndroid Build Coastguard Worker   }
1011*f6dc9357SAndroid Build Coastguard Worker }
1012*f6dc9357SAndroid Build Coastguard Worker 
1013*f6dc9357SAndroid Build Coastguard Worker 
1014*f6dc9357SAndroid Build Coastguard Worker struct CAnalysis
1015*f6dc9357SAndroid Build Coastguard Worker {
1016*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IArchiveUpdateCallbackFile> Callback;
1017*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer Buffer;
1018*f6dc9357SAndroid Build Coastguard Worker 
1019*f6dc9357SAndroid Build Coastguard Worker   bool ParseWav;
1020*f6dc9357SAndroid Build Coastguard Worker   bool ParseExe;
1021*f6dc9357SAndroid Build Coastguard Worker   bool ParseExeUnix;
1022*f6dc9357SAndroid Build Coastguard Worker   bool ParseNoExt;
1023*f6dc9357SAndroid Build Coastguard Worker   bool ParseAll;
1024*f6dc9357SAndroid Build Coastguard Worker 
1025*f6dc9357SAndroid Build Coastguard Worker   /*
1026*f6dc9357SAndroid Build Coastguard Worker   bool Need_ATime;
1027*f6dc9357SAndroid Build Coastguard Worker   bool ATime_Defined;
1028*f6dc9357SAndroid Build Coastguard Worker   FILETIME ATime;
1029*f6dc9357SAndroid Build Coastguard Worker   */
1030*f6dc9357SAndroid Build Coastguard Worker 
CAnalysisNArchive::N7z::CAnalysis1031*f6dc9357SAndroid Build Coastguard Worker   CAnalysis():
1032*f6dc9357SAndroid Build Coastguard Worker       ParseWav(false),
1033*f6dc9357SAndroid Build Coastguard Worker       ParseExe(false),
1034*f6dc9357SAndroid Build Coastguard Worker       ParseExeUnix(false),
1035*f6dc9357SAndroid Build Coastguard Worker       ParseNoExt(false),
1036*f6dc9357SAndroid Build Coastguard Worker       ParseAll(false)
1037*f6dc9357SAndroid Build Coastguard Worker       /*
1038*f6dc9357SAndroid Build Coastguard Worker       , Need_ATime(false)
1039*f6dc9357SAndroid Build Coastguard Worker       , ATime_Defined(false)
1040*f6dc9357SAndroid Build Coastguard Worker       */
1041*f6dc9357SAndroid Build Coastguard Worker   {}
1042*f6dc9357SAndroid Build Coastguard Worker 
1043*f6dc9357SAndroid Build Coastguard Worker   HRESULT GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode);
1044*f6dc9357SAndroid Build Coastguard Worker };
1045*f6dc9357SAndroid Build Coastguard Worker 
1046*f6dc9357SAndroid Build Coastguard Worker static const size_t kAnalysisBufSize = 1 << 14;
1047*f6dc9357SAndroid Build Coastguard Worker 
GetFilterGroup(UInt32 index,const CUpdateItem & ui,CFilterMode & filterMode)1048*f6dc9357SAndroid Build Coastguard Worker HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode)
1049*f6dc9357SAndroid Build Coastguard Worker {
1050*f6dc9357SAndroid Build Coastguard Worker   filterMode.Id = 0;
1051*f6dc9357SAndroid Build Coastguard Worker   filterMode.Delta = 0;
1052*f6dc9357SAndroid Build Coastguard Worker   filterMode.Offset = 0;
1053*f6dc9357SAndroid Build Coastguard Worker 
1054*f6dc9357SAndroid Build Coastguard Worker   CFilterMode filterModeTemp = filterMode;
1055*f6dc9357SAndroid Build Coastguard Worker 
1056*f6dc9357SAndroid Build Coastguard Worker   const int slashPos = ui.Name.ReverseFind_PathSepar();
1057*f6dc9357SAndroid Build Coastguard Worker   const int dotPos = ui.Name.ReverseFind_Dot();
1058*f6dc9357SAndroid Build Coastguard Worker 
1059*f6dc9357SAndroid Build Coastguard Worker   // if (dotPos > slashPos)
1060*f6dc9357SAndroid Build Coastguard Worker   {
1061*f6dc9357SAndroid Build Coastguard Worker     bool needReadFile = ParseAll;
1062*f6dc9357SAndroid Build Coastguard Worker     /* if (Callback) is not supported by client,
1063*f6dc9357SAndroid Build Coastguard Worker        we still try to use file name extension to detect executable file */
1064*f6dc9357SAndroid Build Coastguard Worker     bool probablyIsSameIsa = false;
1065*f6dc9357SAndroid Build Coastguard Worker 
1066*f6dc9357SAndroid Build Coastguard Worker     if (!needReadFile || !Callback)
1067*f6dc9357SAndroid Build Coastguard Worker     {
1068*f6dc9357SAndroid Build Coastguard Worker       const wchar_t *ext = NULL;
1069*f6dc9357SAndroid Build Coastguard Worker       if (dotPos > slashPos)
1070*f6dc9357SAndroid Build Coastguard Worker         ext = ui.Name.Ptr((unsigned)(dotPos + 1));
1071*f6dc9357SAndroid Build Coastguard Worker       // 7-zip stores posix attributes in high 16 bits and sets (0x8000) flag
1072*f6dc9357SAndroid Build Coastguard Worker       if (ui.Attrib & 0x8000)
1073*f6dc9357SAndroid Build Coastguard Worker       {
1074*f6dc9357SAndroid Build Coastguard Worker         const unsigned st_mode = ui.Attrib >> 16;
1075*f6dc9357SAndroid Build Coastguard Worker         /* note: executable ".so" can be without execute permission,
1076*f6dc9357SAndroid Build Coastguard Worker            and symbolic link to such ".so" file is possible */
1077*f6dc9357SAndroid Build Coastguard Worker         // st_mode = 00111; // for debug
1078*f6dc9357SAndroid Build Coastguard Worker         /* in Linux we expect such permissions:
1079*f6dc9357SAndroid Build Coastguard Worker              0755 : for most executables
1080*f6dc9357SAndroid Build Coastguard Worker              0644 : for some ".so" files
1081*f6dc9357SAndroid Build Coastguard Worker              0777 : in WSL for all files.
1082*f6dc9357SAndroid Build Coastguard Worker                     We can try to exclude some such 0777 cases from analysis,
1083*f6dc9357SAndroid Build Coastguard Worker                     if there is non-executable extension.
1084*f6dc9357SAndroid Build Coastguard Worker         */
1085*f6dc9357SAndroid Build Coastguard Worker 
1086*f6dc9357SAndroid Build Coastguard Worker         if ((st_mode & (
1087*f6dc9357SAndroid Build Coastguard Worker               MY_LIN_S_IXUSR |
1088*f6dc9357SAndroid Build Coastguard Worker               MY_LIN_S_IXGRP |
1089*f6dc9357SAndroid Build Coastguard Worker               MY_LIN_S_IXOTH)) != 0
1090*f6dc9357SAndroid Build Coastguard Worker             && MY_LIN_S_ISREG(st_mode)
1091*f6dc9357SAndroid Build Coastguard Worker             && (ui.Size >= (1u << 11)))
1092*f6dc9357SAndroid Build Coastguard Worker         {
1093*f6dc9357SAndroid Build Coastguard Worker           #ifndef _WIN32
1094*f6dc9357SAndroid Build Coastguard Worker           probablyIsSameIsa = true;
1095*f6dc9357SAndroid Build Coastguard Worker           #endif
1096*f6dc9357SAndroid Build Coastguard Worker           needReadFile = true;
1097*f6dc9357SAndroid Build Coastguard Worker         }
1098*f6dc9357SAndroid Build Coastguard Worker       }
1099*f6dc9357SAndroid Build Coastguard Worker 
1100*f6dc9357SAndroid Build Coastguard Worker       if (!needReadFile)
1101*f6dc9357SAndroid Build Coastguard Worker       {
1102*f6dc9357SAndroid Build Coastguard Worker         if (!ext)
1103*f6dc9357SAndroid Build Coastguard Worker           needReadFile = ParseNoExt;
1104*f6dc9357SAndroid Build Coastguard Worker         else
1105*f6dc9357SAndroid Build Coastguard Worker         {
1106*f6dc9357SAndroid Build Coastguard Worker           bool isUnixExt = false;
1107*f6dc9357SAndroid Build Coastguard Worker           if (ParseExeUnix)
1108*f6dc9357SAndroid Build Coastguard Worker             isUnixExt = IsExt_ExeUnix_NumericAllowed(ui.Name);
1109*f6dc9357SAndroid Build Coastguard Worker           if (isUnixExt)
1110*f6dc9357SAndroid Build Coastguard Worker           {
1111*f6dc9357SAndroid Build Coastguard Worker             needReadFile = true;
1112*f6dc9357SAndroid Build Coastguard Worker             #ifndef _WIN32
1113*f6dc9357SAndroid Build Coastguard Worker               probablyIsSameIsa = true;
1114*f6dc9357SAndroid Build Coastguard Worker             #endif
1115*f6dc9357SAndroid Build Coastguard Worker           }
1116*f6dc9357SAndroid Build Coastguard Worker           else if (IsExt_Exe(ext))
1117*f6dc9357SAndroid Build Coastguard Worker           {
1118*f6dc9357SAndroid Build Coastguard Worker             needReadFile = ParseExe;
1119*f6dc9357SAndroid Build Coastguard Worker             #ifdef _WIN32
1120*f6dc9357SAndroid Build Coastguard Worker               probablyIsSameIsa = true;
1121*f6dc9357SAndroid Build Coastguard Worker             #endif
1122*f6dc9357SAndroid Build Coastguard Worker           }
1123*f6dc9357SAndroid Build Coastguard Worker           else if (StringsAreEqualNoCase_Ascii(ext, "wav"))
1124*f6dc9357SAndroid Build Coastguard Worker           {
1125*f6dc9357SAndroid Build Coastguard Worker             if (!needReadFile)
1126*f6dc9357SAndroid Build Coastguard Worker               needReadFile = ParseWav;
1127*f6dc9357SAndroid Build Coastguard Worker           }
1128*f6dc9357SAndroid Build Coastguard Worker         }
1129*f6dc9357SAndroid Build Coastguard Worker       }
1130*f6dc9357SAndroid Build Coastguard Worker     }
1131*f6dc9357SAndroid Build Coastguard Worker 
1132*f6dc9357SAndroid Build Coastguard Worker     if (needReadFile)
1133*f6dc9357SAndroid Build Coastguard Worker     {
1134*f6dc9357SAndroid Build Coastguard Worker       BoolInt parseRes = false;
1135*f6dc9357SAndroid Build Coastguard Worker       if (Callback)
1136*f6dc9357SAndroid Build Coastguard Worker       {
1137*f6dc9357SAndroid Build Coastguard Worker         if (Buffer.Size() != kAnalysisBufSize)
1138*f6dc9357SAndroid Build Coastguard Worker           Buffer.Alloc(kAnalysisBufSize);
1139*f6dc9357SAndroid Build Coastguard Worker         CMyComPtr<ISequentialInStream> stream;
1140*f6dc9357SAndroid Build Coastguard Worker         HRESULT result = Callback->GetStream2(index, &stream, NUpdateNotifyOp::kAnalyze);
1141*f6dc9357SAndroid Build Coastguard Worker         if (result == S_OK && stream)
1142*f6dc9357SAndroid Build Coastguard Worker         {
1143*f6dc9357SAndroid Build Coastguard Worker           /*
1144*f6dc9357SAndroid Build Coastguard Worker           if (Need_ATime)
1145*f6dc9357SAndroid Build Coastguard Worker           {
1146*f6dc9357SAndroid Build Coastguard Worker             // access time could be changed in analysis pass
1147*f6dc9357SAndroid Build Coastguard Worker             CMyComPtr<IStreamGetProps> getProps;
1148*f6dc9357SAndroid Build Coastguard Worker             stream.QueryInterface(IID_IStreamGetProps, (void **)&getProps);
1149*f6dc9357SAndroid Build Coastguard Worker             if (getProps)
1150*f6dc9357SAndroid Build Coastguard Worker               if (getProps->GetProps(NULL, NULL, &ATime, NULL, NULL) == S_OK)
1151*f6dc9357SAndroid Build Coastguard Worker                 ATime_Defined = true;
1152*f6dc9357SAndroid Build Coastguard Worker           }
1153*f6dc9357SAndroid Build Coastguard Worker           */
1154*f6dc9357SAndroid Build Coastguard Worker           size_t size = kAnalysisBufSize;
1155*f6dc9357SAndroid Build Coastguard Worker           result = ReadStream(stream, Buffer, &size);
1156*f6dc9357SAndroid Build Coastguard Worker           stream.Release();
1157*f6dc9357SAndroid Build Coastguard Worker           // RINOK(Callback->SetOperationResult2(index, NUpdate::NOperationResult::kOK));
1158*f6dc9357SAndroid Build Coastguard Worker           if (result == S_OK)
1159*f6dc9357SAndroid Build Coastguard Worker           {
1160*f6dc9357SAndroid Build Coastguard Worker             parseRes = ParseFile(Buffer, size, &filterModeTemp);
1161*f6dc9357SAndroid Build Coastguard Worker           }
1162*f6dc9357SAndroid Build Coastguard Worker         }
1163*f6dc9357SAndroid Build Coastguard Worker       } // Callback
1164*f6dc9357SAndroid Build Coastguard Worker       else if (probablyIsSameIsa)
1165*f6dc9357SAndroid Build Coastguard Worker       {
1166*f6dc9357SAndroid Build Coastguard Worker         #ifdef MY_CPU_X86_OR_AMD64
1167*f6dc9357SAndroid Build Coastguard Worker           filterModeTemp.Id = k_X86;
1168*f6dc9357SAndroid Build Coastguard Worker         #endif
1169*f6dc9357SAndroid Build Coastguard Worker         #ifdef MY_CPU_ARM64
1170*f6dc9357SAndroid Build Coastguard Worker           filterModeTemp.Id = k_ARM64;
1171*f6dc9357SAndroid Build Coastguard Worker         #endif
1172*f6dc9357SAndroid Build Coastguard Worker         #ifdef MY_CPU_RISCV
1173*f6dc9357SAndroid Build Coastguard Worker           filterModeTemp.Id = k_RISCV;
1174*f6dc9357SAndroid Build Coastguard Worker         #endif
1175*f6dc9357SAndroid Build Coastguard Worker         #ifdef MY_CPU_SPARC
1176*f6dc9357SAndroid Build Coastguard Worker           filterModeTemp.Id = k_SPARC;
1177*f6dc9357SAndroid Build Coastguard Worker         #endif
1178*f6dc9357SAndroid Build Coastguard Worker         parseRes = true;
1179*f6dc9357SAndroid Build Coastguard Worker       }
1180*f6dc9357SAndroid Build Coastguard Worker 
1181*f6dc9357SAndroid Build Coastguard Worker       if (parseRes
1182*f6dc9357SAndroid Build Coastguard Worker           && filterModeTemp.Id != k_Delta
1183*f6dc9357SAndroid Build Coastguard Worker           && filterModeTemp.Delta == 0)
1184*f6dc9357SAndroid Build Coastguard Worker       {
1185*f6dc9357SAndroid Build Coastguard Worker         /* ParseFile() sets (filterModeTemp.Delta == 0) for all
1186*f6dc9357SAndroid Build Coastguard Worker            methods except of k_Delta. */
1187*f6dc9357SAndroid Build Coastguard Worker         // it's not k_Delta
1188*f6dc9357SAndroid Build Coastguard Worker         // So we call SetDelta() to set Delta
1189*f6dc9357SAndroid Build Coastguard Worker         filterModeTemp.SetDelta();
1190*f6dc9357SAndroid Build Coastguard Worker         if (filterModeTemp.Delta > 1)
1191*f6dc9357SAndroid Build Coastguard Worker         {
1192*f6dc9357SAndroid Build Coastguard Worker           /* If file Size is not aligned, then branch filter
1193*f6dc9357SAndroid Build Coastguard Worker              will not work for next file in solid block.
1194*f6dc9357SAndroid Build Coastguard Worker              Maybe we should allow filter for non-aligned-size file in non-solid archives ?
1195*f6dc9357SAndroid Build Coastguard Worker           */
1196*f6dc9357SAndroid Build Coastguard Worker           if (ui.Size % filterModeTemp.Delta != 0)
1197*f6dc9357SAndroid Build Coastguard Worker             parseRes = false;
1198*f6dc9357SAndroid Build Coastguard Worker           // windows exe files are not aligned for 4 KiB.
1199*f6dc9357SAndroid Build Coastguard Worker           /*
1200*f6dc9357SAndroid Build Coastguard Worker           else if (filterModeTemp.Id == k_ARM64 && filterModeTemp.Offset != 0)
1201*f6dc9357SAndroid Build Coastguard Worker           {
1202*f6dc9357SAndroid Build Coastguard Worker             if (ui.Size % (1 << 12) != 0)
1203*f6dc9357SAndroid Build Coastguard Worker             {
1204*f6dc9357SAndroid Build Coastguard Worker               // If Size is not aligned for 4 KiB, then Offset will not work for next file in solid block.
1205*f6dc9357SAndroid Build Coastguard Worker               // so we place such file in group with (Offset==0).
1206*f6dc9357SAndroid Build Coastguard Worker               filterModeTemp.Offset = 0;
1207*f6dc9357SAndroid Build Coastguard Worker             }
1208*f6dc9357SAndroid Build Coastguard Worker           }
1209*f6dc9357SAndroid Build Coastguard Worker           */
1210*f6dc9357SAndroid Build Coastguard Worker         }
1211*f6dc9357SAndroid Build Coastguard Worker       }
1212*f6dc9357SAndroid Build Coastguard Worker       if (!parseRes)
1213*f6dc9357SAndroid Build Coastguard Worker         filterModeTemp.ClearFilterMode();
1214*f6dc9357SAndroid Build Coastguard Worker     }
1215*f6dc9357SAndroid Build Coastguard Worker   }
1216*f6dc9357SAndroid Build Coastguard Worker 
1217*f6dc9357SAndroid Build Coastguard Worker   filterMode = filterModeTemp;
1218*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1219*f6dc9357SAndroid Build Coastguard Worker }
1220*f6dc9357SAndroid Build Coastguard Worker 
GetMethodFull(UInt64 methodID,UInt32 numStreams,CMethodFull & m)1221*f6dc9357SAndroid Build Coastguard Worker static inline void GetMethodFull(UInt64 methodID, UInt32 numStreams, CMethodFull &m)
1222*f6dc9357SAndroid Build Coastguard Worker {
1223*f6dc9357SAndroid Build Coastguard Worker   m.Id = methodID;
1224*f6dc9357SAndroid Build Coastguard Worker   m.NumStreams = numStreams;
1225*f6dc9357SAndroid Build Coastguard Worker }
1226*f6dc9357SAndroid Build Coastguard Worker 
1227*f6dc9357SAndroid Build Coastguard Worker 
1228*f6dc9357SAndroid Build Coastguard Worker // we add bond for mode.Methods[0] that is filter
AddBondForFilter(CCompressionMethodMode & mode)1229*f6dc9357SAndroid Build Coastguard Worker static HRESULT AddBondForFilter(CCompressionMethodMode &mode)
1230*f6dc9357SAndroid Build Coastguard Worker {
1231*f6dc9357SAndroid Build Coastguard Worker   for (unsigned c = 1; c < mode.Methods.Size(); c++)
1232*f6dc9357SAndroid Build Coastguard Worker   {
1233*f6dc9357SAndroid Build Coastguard Worker     if (!mode.IsThereBond_to_Coder(c))
1234*f6dc9357SAndroid Build Coastguard Worker     {
1235*f6dc9357SAndroid Build Coastguard Worker       CBond2 bond;
1236*f6dc9357SAndroid Build Coastguard Worker       bond.OutCoder = 0;
1237*f6dc9357SAndroid Build Coastguard Worker       bond.OutStream = 0;
1238*f6dc9357SAndroid Build Coastguard Worker       bond.InCoder = c;
1239*f6dc9357SAndroid Build Coastguard Worker       mode.Bonds.Add(bond);
1240*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1241*f6dc9357SAndroid Build Coastguard Worker     }
1242*f6dc9357SAndroid Build Coastguard Worker   }
1243*f6dc9357SAndroid Build Coastguard Worker   return E_INVALIDARG;
1244*f6dc9357SAndroid Build Coastguard Worker }
1245*f6dc9357SAndroid Build Coastguard Worker 
1246*f6dc9357SAndroid Build Coastguard Worker /*
1247*f6dc9357SAndroid Build Coastguard Worker static HRESULT AddBondForFilter_if_ThereAreBonds(CCompressionMethodMode &mode)
1248*f6dc9357SAndroid Build Coastguard Worker {
1249*f6dc9357SAndroid Build Coastguard Worker   if (!mode.Bonds.IsEmpty())
1250*f6dc9357SAndroid Build Coastguard Worker     return AddBondForFilter(mode);
1251*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1252*f6dc9357SAndroid Build Coastguard Worker }
1253*f6dc9357SAndroid Build Coastguard Worker */
1254*f6dc9357SAndroid Build Coastguard Worker 
AddBcj2Methods(CCompressionMethodMode & mode)1255*f6dc9357SAndroid Build Coastguard Worker static HRESULT AddBcj2Methods(CCompressionMethodMode &mode)
1256*f6dc9357SAndroid Build Coastguard Worker {
1257*f6dc9357SAndroid Build Coastguard Worker   // mode.Methods[0] must be k_BCJ2 method !
1258*f6dc9357SAndroid Build Coastguard Worker   // mode.Methods[1] : we expect that there is at least one method after BCJ2
1259*f6dc9357SAndroid Build Coastguard Worker 
1260*f6dc9357SAndroid Build Coastguard Worker   CMethodFull m;
1261*f6dc9357SAndroid Build Coastguard Worker   GetMethodFull(k_LZMA, 1, m);
1262*f6dc9357SAndroid Build Coastguard Worker 
1263*f6dc9357SAndroid Build Coastguard Worker   m.AddProp32(NCoderPropID::kDictionarySize, 1 << 20);
1264*f6dc9357SAndroid Build Coastguard Worker   m.AddProp32(NCoderPropID::kNumFastBytes, 128);
1265*f6dc9357SAndroid Build Coastguard Worker   m.AddProp32(NCoderPropID::kNumThreads, 1);
1266*f6dc9357SAndroid Build Coastguard Worker   m.AddProp32(NCoderPropID::kLitPosBits, 2);
1267*f6dc9357SAndroid Build Coastguard Worker   m.AddProp32(NCoderPropID::kLitContextBits, 0);
1268*f6dc9357SAndroid Build Coastguard Worker   // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2");
1269*f6dc9357SAndroid Build Coastguard Worker 
1270*f6dc9357SAndroid Build Coastguard Worker   const unsigned methodIndex = mode.Methods.Size();
1271*f6dc9357SAndroid Build Coastguard Worker 
1272*f6dc9357SAndroid Build Coastguard Worker   if (mode.Bonds.IsEmpty())
1273*f6dc9357SAndroid Build Coastguard Worker   {
1274*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 1; i + 1 < mode.Methods.Size(); i++)
1275*f6dc9357SAndroid Build Coastguard Worker     {
1276*f6dc9357SAndroid Build Coastguard Worker       CBond2 bond;
1277*f6dc9357SAndroid Build Coastguard Worker       bond.OutCoder = i;
1278*f6dc9357SAndroid Build Coastguard Worker       bond.OutStream = 0;
1279*f6dc9357SAndroid Build Coastguard Worker       bond.InCoder = i + 1;
1280*f6dc9357SAndroid Build Coastguard Worker       mode.Bonds.Add(bond);
1281*f6dc9357SAndroid Build Coastguard Worker     }
1282*f6dc9357SAndroid Build Coastguard Worker   }
1283*f6dc9357SAndroid Build Coastguard Worker 
1284*f6dc9357SAndroid Build Coastguard Worker   mode.Methods.Add(m);
1285*f6dc9357SAndroid Build Coastguard Worker   mode.Methods.Add(m);
1286*f6dc9357SAndroid Build Coastguard Worker 
1287*f6dc9357SAndroid Build Coastguard Worker   RINOK(AddBondForFilter(mode))
1288*f6dc9357SAndroid Build Coastguard Worker   CBond2 bond;
1289*f6dc9357SAndroid Build Coastguard Worker   bond.OutCoder = 0; // index of BCJ2 coder
1290*f6dc9357SAndroid Build Coastguard Worker   bond.InCoder = methodIndex;      bond.OutStream = 1;  mode.Bonds.Add(bond);
1291*f6dc9357SAndroid Build Coastguard Worker   bond.InCoder = methodIndex + 1;  bond.OutStream = 2;  mode.Bonds.Add(bond);
1292*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1293*f6dc9357SAndroid Build Coastguard Worker }
1294*f6dc9357SAndroid Build Coastguard Worker 
1295*f6dc9357SAndroid Build Coastguard Worker 
MakeExeMethod(CCompressionMethodMode & mode,const CFilterMode & filterMode,const bool bcj2_IsAllowed,const CUIntVector & disabledFilterIDs)1296*f6dc9357SAndroid Build Coastguard Worker static HRESULT MakeExeMethod(CCompressionMethodMode &mode,
1297*f6dc9357SAndroid Build Coastguard Worker     const CFilterMode &filterMode,
1298*f6dc9357SAndroid Build Coastguard Worker     const bool bcj2_IsAllowed,
1299*f6dc9357SAndroid Build Coastguard Worker     const CUIntVector &disabledFilterIDs)
1300*f6dc9357SAndroid Build Coastguard Worker {
1301*f6dc9357SAndroid Build Coastguard Worker   if (mode.Filter_was_Inserted)
1302*f6dc9357SAndroid Build Coastguard Worker   {
1303*f6dc9357SAndroid Build Coastguard Worker     // filter was inserted, but bond for that filter was not added still.
1304*f6dc9357SAndroid Build Coastguard Worker     const CMethodFull &m = mode.Methods[0];
1305*f6dc9357SAndroid Build Coastguard Worker     if (m.Id == k_BCJ2)
1306*f6dc9357SAndroid Build Coastguard Worker       return AddBcj2Methods(mode);
1307*f6dc9357SAndroid Build Coastguard Worker     if (!m.IsSimpleCoder())
1308*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
1309*f6dc9357SAndroid Build Coastguard Worker     if (mode.Bonds.IsEmpty())
1310*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1311*f6dc9357SAndroid Build Coastguard Worker     return AddBondForFilter(mode);
1312*f6dc9357SAndroid Build Coastguard Worker   }
1313*f6dc9357SAndroid Build Coastguard Worker 
1314*f6dc9357SAndroid Build Coastguard Worker   if (filterMode.Id == 0)
1315*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1316*f6dc9357SAndroid Build Coastguard Worker 
1317*f6dc9357SAndroid Build Coastguard Worker   unsigned nextCoder;
1318*f6dc9357SAndroid Build Coastguard Worker 
1319*f6dc9357SAndroid Build Coastguard Worker   const bool useBcj2 = bcj2_IsAllowed
1320*f6dc9357SAndroid Build Coastguard Worker       && Is86Filter(filterMode.Id)
1321*f6dc9357SAndroid Build Coastguard Worker       && disabledFilterIDs.FindInSorted(k_BCJ2) < 0;
1322*f6dc9357SAndroid Build Coastguard Worker 
1323*f6dc9357SAndroid Build Coastguard Worker   if (!useBcj2 && disabledFilterIDs.FindInSorted(filterMode.Id) >= 0)
1324*f6dc9357SAndroid Build Coastguard Worker   {
1325*f6dc9357SAndroid Build Coastguard Worker     // required filter is disabled,
1326*f6dc9357SAndroid Build Coastguard Worker     // but we still can use information about data alignment.
1327*f6dc9357SAndroid Build Coastguard Worker #if 0 // 1 for debug
1328*f6dc9357SAndroid Build Coastguard Worker     // we can return here, if we want default lzma properties
1329*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1330*f6dc9357SAndroid Build Coastguard Worker #else
1331*f6dc9357SAndroid Build Coastguard Worker     // we will try to change lzma/lzma2 properties
1332*f6dc9357SAndroid Build Coastguard Worker     nextCoder = 0;
1333*f6dc9357SAndroid Build Coastguard Worker     if (!mode.Bonds.IsEmpty())
1334*f6dc9357SAndroid Build Coastguard Worker       for (unsigned c = 0;; c++)
1335*f6dc9357SAndroid Build Coastguard Worker       {
1336*f6dc9357SAndroid Build Coastguard Worker         if (c == mode.Methods.Size())
1337*f6dc9357SAndroid Build Coastguard Worker           return S_OK;
1338*f6dc9357SAndroid Build Coastguard Worker         if (!mode.IsThereBond_to_Coder(c))
1339*f6dc9357SAndroid Build Coastguard Worker         {
1340*f6dc9357SAndroid Build Coastguard Worker           nextCoder = c;
1341*f6dc9357SAndroid Build Coastguard Worker           break;
1342*f6dc9357SAndroid Build Coastguard Worker         }
1343*f6dc9357SAndroid Build Coastguard Worker       }
1344*f6dc9357SAndroid Build Coastguard Worker #endif
1345*f6dc9357SAndroid Build Coastguard Worker   }
1346*f6dc9357SAndroid Build Coastguard Worker   else
1347*f6dc9357SAndroid Build Coastguard Worker   {
1348*f6dc9357SAndroid Build Coastguard Worker     // we insert new filter method:
1349*f6dc9357SAndroid Build Coastguard Worker     CMethodFull &m = mode.Methods.InsertNew(0); // 0 == index of new inserted item
1350*f6dc9357SAndroid Build Coastguard Worker     {
1351*f6dc9357SAndroid Build Coastguard Worker       // we move all coder indexes in bonds up for 1 position:
1352*f6dc9357SAndroid Build Coastguard Worker       FOR_VECTOR (k, mode.Bonds)
1353*f6dc9357SAndroid Build Coastguard Worker       {
1354*f6dc9357SAndroid Build Coastguard Worker         CBond2 &bond = mode.Bonds[k];
1355*f6dc9357SAndroid Build Coastguard Worker         bond.InCoder++;
1356*f6dc9357SAndroid Build Coastguard Worker         bond.OutCoder++;
1357*f6dc9357SAndroid Build Coastguard Worker       }
1358*f6dc9357SAndroid Build Coastguard Worker     }
1359*f6dc9357SAndroid Build Coastguard Worker     if (useBcj2)
1360*f6dc9357SAndroid Build Coastguard Worker     {
1361*f6dc9357SAndroid Build Coastguard Worker       GetMethodFull(k_BCJ2, 4, m);
1362*f6dc9357SAndroid Build Coastguard Worker       return AddBcj2Methods(mode);
1363*f6dc9357SAndroid Build Coastguard Worker     }
1364*f6dc9357SAndroid Build Coastguard Worker 
1365*f6dc9357SAndroid Build Coastguard Worker     GetMethodFull(filterMode.Id, 1, m);
1366*f6dc9357SAndroid Build Coastguard Worker 
1367*f6dc9357SAndroid Build Coastguard Worker     if (filterMode.Id == k_Delta)
1368*f6dc9357SAndroid Build Coastguard Worker       m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta);
1369*f6dc9357SAndroid Build Coastguard Worker     else if (filterMode.Id == k_ARM64
1370*f6dc9357SAndroid Build Coastguard Worker           || filterMode.Id == k_RISCV)
1371*f6dc9357SAndroid Build Coastguard Worker     {
1372*f6dc9357SAndroid Build Coastguard Worker       // if (filterMode.Offset != 0)
1373*f6dc9357SAndroid Build Coastguard Worker       m.AddProp32(
1374*f6dc9357SAndroid Build Coastguard Worker         NCoderPropID::kDefaultProp,
1375*f6dc9357SAndroid Build Coastguard Worker         // NCoderPropID::kBranchOffset,
1376*f6dc9357SAndroid Build Coastguard Worker         filterMode.Offset);
1377*f6dc9357SAndroid Build Coastguard Worker     }
1378*f6dc9357SAndroid Build Coastguard Worker 
1379*f6dc9357SAndroid Build Coastguard Worker     nextCoder = 1;
1380*f6dc9357SAndroid Build Coastguard Worker     if (!mode.Bonds.IsEmpty())
1381*f6dc9357SAndroid Build Coastguard Worker     {
1382*f6dc9357SAndroid Build Coastguard Worker       RINOK(AddBondForFilter(mode))
1383*f6dc9357SAndroid Build Coastguard Worker       nextCoder = mode.Bonds.Back().InCoder;
1384*f6dc9357SAndroid Build Coastguard Worker     }
1385*f6dc9357SAndroid Build Coastguard Worker   }
1386*f6dc9357SAndroid Build Coastguard Worker 
1387*f6dc9357SAndroid Build Coastguard Worker   if (nextCoder >= mode.Methods.Size())
1388*f6dc9357SAndroid Build Coastguard Worker   {
1389*f6dc9357SAndroid Build Coastguard Worker     // we don't expect that case, if there was non-filter method.
1390*f6dc9357SAndroid Build Coastguard Worker     // but we return S_OK to support filter-only case.
1391*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1392*f6dc9357SAndroid Build Coastguard Worker   }
1393*f6dc9357SAndroid Build Coastguard Worker 
1394*f6dc9357SAndroid Build Coastguard Worker   int alignBits = -1;
1395*f6dc9357SAndroid Build Coastguard Worker   {
1396*f6dc9357SAndroid Build Coastguard Worker     const UInt32 delta = filterMode.Delta;
1397*f6dc9357SAndroid Build Coastguard Worker     if (delta == 0 || delta > 16)
1398*f6dc9357SAndroid Build Coastguard Worker     {
1399*f6dc9357SAndroid Build Coastguard Worker       // if (delta == 0) alignBits = GetAlignForFilterMethod(filterMode.Id);
1400*f6dc9357SAndroid Build Coastguard Worker     }
1401*f6dc9357SAndroid Build Coastguard Worker     else if ((delta & ((1 << 4) - 1)) == 0) alignBits = 4;
1402*f6dc9357SAndroid Build Coastguard Worker     else if ((delta & ((1 << 3) - 1)) == 0) alignBits = 3;
1403*f6dc9357SAndroid Build Coastguard Worker     else if ((delta & ((1 << 2) - 1)) == 0) alignBits = 2;
1404*f6dc9357SAndroid Build Coastguard Worker     else if ((delta & ((1 << 1) - 1)) == 0) alignBits = 1;
1405*f6dc9357SAndroid Build Coastguard Worker     // else alignBits = 0;
1406*f6dc9357SAndroid Build Coastguard Worker     /* alignBits=0 is default mode for lzma/lzma2.
1407*f6dc9357SAndroid Build Coastguard Worker     So we don't set alignBits=0 here. */
1408*f6dc9357SAndroid Build Coastguard Worker   }
1409*f6dc9357SAndroid Build Coastguard Worker   if (alignBits <= 0)
1410*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1411*f6dc9357SAndroid Build Coastguard Worker   // (alignBits > 0)
1412*f6dc9357SAndroid Build Coastguard Worker   CMethodFull &nextMethod = mode.Methods[nextCoder];
1413*f6dc9357SAndroid Build Coastguard Worker   if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2)
1414*f6dc9357SAndroid Build Coastguard Worker   if (!nextMethod.Are_Lzma_Model_Props_Defined())
1415*f6dc9357SAndroid Build Coastguard Worker   {
1416*f6dc9357SAndroid Build Coastguard Worker     if (alignBits > 2 || filterMode.Id == k_Delta)
1417*f6dc9357SAndroid Build Coastguard Worker       nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits);
1418*f6dc9357SAndroid Build Coastguard Worker     const unsigned lc = (alignBits < 3) ? (unsigned)(3 - alignBits) : 0u;
1419*f6dc9357SAndroid Build Coastguard Worker     nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc);
1420*f6dc9357SAndroid Build Coastguard Worker     nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits);
1421*f6dc9357SAndroid Build Coastguard Worker   }
1422*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1423*f6dc9357SAndroid Build Coastguard Worker }
1424*f6dc9357SAndroid Build Coastguard Worker 
1425*f6dc9357SAndroid Build Coastguard Worker 
UpdateItem_To_FileItem2(const CUpdateItem & ui,CFileItem2 & file2)1426*f6dc9357SAndroid Build Coastguard Worker static void UpdateItem_To_FileItem2(const CUpdateItem &ui, CFileItem2 &file2)
1427*f6dc9357SAndroid Build Coastguard Worker {
1428*f6dc9357SAndroid Build Coastguard Worker   file2.Attrib = ui.Attrib;  file2.AttribDefined = ui.AttribDefined;
1429*f6dc9357SAndroid Build Coastguard Worker   file2.CTime = ui.CTime;  file2.CTimeDefined = ui.CTimeDefined;
1430*f6dc9357SAndroid Build Coastguard Worker   file2.ATime = ui.ATime;  file2.ATimeDefined = ui.ATimeDefined;
1431*f6dc9357SAndroid Build Coastguard Worker   file2.MTime = ui.MTime;  file2.MTimeDefined = ui.MTimeDefined;
1432*f6dc9357SAndroid Build Coastguard Worker   file2.IsAnti = ui.IsAnti;
1433*f6dc9357SAndroid Build Coastguard Worker   // file2.IsAux = false;
1434*f6dc9357SAndroid Build Coastguard Worker   file2.StartPosDefined = false;
1435*f6dc9357SAndroid Build Coastguard Worker   // file2.StartPos = 0;
1436*f6dc9357SAndroid Build Coastguard Worker }
1437*f6dc9357SAndroid Build Coastguard Worker 
1438*f6dc9357SAndroid Build Coastguard Worker 
UpdateItem_To_FileItem(const CUpdateItem & ui,CFileItem & file,CFileItem2 & file2)1439*f6dc9357SAndroid Build Coastguard Worker static void UpdateItem_To_FileItem(const CUpdateItem &ui,
1440*f6dc9357SAndroid Build Coastguard Worker     CFileItem &file, CFileItem2 &file2)
1441*f6dc9357SAndroid Build Coastguard Worker {
1442*f6dc9357SAndroid Build Coastguard Worker   UpdateItem_To_FileItem2(ui, file2);
1443*f6dc9357SAndroid Build Coastguard Worker 
1444*f6dc9357SAndroid Build Coastguard Worker   file.Size = ui.Size;
1445*f6dc9357SAndroid Build Coastguard Worker   file.IsDir = ui.IsDir;
1446*f6dc9357SAndroid Build Coastguard Worker   file.HasStream = ui.HasStream();
1447*f6dc9357SAndroid Build Coastguard Worker   // file.IsAltStream = ui.IsAltStream;
1448*f6dc9357SAndroid Build Coastguard Worker }
1449*f6dc9357SAndroid Build Coastguard Worker 
1450*f6dc9357SAndroid Build Coastguard Worker 
1451*f6dc9357SAndroid Build Coastguard Worker 
1452*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_2(
1453*f6dc9357SAndroid Build Coastguard Worker   CRepackInStreamWithSizes
1454*f6dc9357SAndroid Build Coastguard Worker   , ISequentialInStream
1455*f6dc9357SAndroid Build Coastguard Worker   , ICompressGetSubStreamSize
1456*f6dc9357SAndroid Build Coastguard Worker )
1457*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialInStream> _stream;
1458*f6dc9357SAndroid Build Coastguard Worker   UInt64 _size;
1459*f6dc9357SAndroid Build Coastguard Worker   const CBoolVector *_extractStatuses;
1460*f6dc9357SAndroid Build Coastguard Worker   UInt32 _startIndex;
1461*f6dc9357SAndroid Build Coastguard Worker public:
1462*f6dc9357SAndroid Build Coastguard Worker   const CDbEx *_db;
1463*f6dc9357SAndroid Build Coastguard Worker 
1464*f6dc9357SAndroid Build Coastguard Worker   void Init(ISequentialInStream *stream, UInt32 startIndex, const CBoolVector *extractStatuses)
1465*f6dc9357SAndroid Build Coastguard Worker   {
1466*f6dc9357SAndroid Build Coastguard Worker     _startIndex = startIndex;
1467*f6dc9357SAndroid Build Coastguard Worker     _extractStatuses = extractStatuses;
1468*f6dc9357SAndroid Build Coastguard Worker     _size = 0;
1469*f6dc9357SAndroid Build Coastguard Worker     _stream = stream;
1470*f6dc9357SAndroid Build Coastguard Worker   }
1471*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetSize() const { return _size; }
1472*f6dc9357SAndroid Build Coastguard Worker };
1473*f6dc9357SAndroid Build Coastguard Worker 
1474*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CRepackInStreamWithSizes::Read(void *data, UInt32 size, UInt32 *processedSize))
1475*f6dc9357SAndroid Build Coastguard Worker {
1476*f6dc9357SAndroid Build Coastguard Worker   UInt32 realProcessedSize;
1477*f6dc9357SAndroid Build Coastguard Worker   const HRESULT result = _stream->Read(data, size, &realProcessedSize);
1478*f6dc9357SAndroid Build Coastguard Worker   _size += realProcessedSize;
1479*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
1480*f6dc9357SAndroid Build Coastguard Worker     *processedSize = realProcessedSize;
1481*f6dc9357SAndroid Build Coastguard Worker   return result;
1482*f6dc9357SAndroid Build Coastguard Worker }
1483*f6dc9357SAndroid Build Coastguard Worker 
1484*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CRepackInStreamWithSizes::GetSubStreamSize(UInt64 subStream, UInt64 *value))
1485*f6dc9357SAndroid Build Coastguard Worker {
1486*f6dc9357SAndroid Build Coastguard Worker   *value = 0;
1487*f6dc9357SAndroid Build Coastguard Worker   if (subStream >= _extractStatuses->Size())
1488*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE; // E_FAIL;
1489*f6dc9357SAndroid Build Coastguard Worker   const unsigned index = (unsigned)subStream;
1490*f6dc9357SAndroid Build Coastguard Worker   if ((*_extractStatuses)[index])
1491*f6dc9357SAndroid Build Coastguard Worker   {
1492*f6dc9357SAndroid Build Coastguard Worker     const CFileItem &fi = _db->Files[_startIndex + index];
1493*f6dc9357SAndroid Build Coastguard Worker     if (fi.HasStream)
1494*f6dc9357SAndroid Build Coastguard Worker       *value = fi.Size;
1495*f6dc9357SAndroid Build Coastguard Worker   }
1496*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1497*f6dc9357SAndroid Build Coastguard Worker }
1498*f6dc9357SAndroid Build Coastguard Worker 
1499*f6dc9357SAndroid Build Coastguard Worker 
1500*f6dc9357SAndroid Build Coastguard Worker class CRepackStreamBase
1501*f6dc9357SAndroid Build Coastguard Worker {
1502*f6dc9357SAndroid Build Coastguard Worker protected:
1503*f6dc9357SAndroid Build Coastguard Worker   bool _needWrite;
1504*f6dc9357SAndroid Build Coastguard Worker   bool _fileIsOpen;
1505*f6dc9357SAndroid Build Coastguard Worker   bool _calcCrc;
1506*f6dc9357SAndroid Build Coastguard Worker   UInt32 _crc;
1507*f6dc9357SAndroid Build Coastguard Worker   UInt64 _rem;
1508*f6dc9357SAndroid Build Coastguard Worker 
1509*f6dc9357SAndroid Build Coastguard Worker   const CBoolVector *_extractStatuses;
1510*f6dc9357SAndroid Build Coastguard Worker   UInt32 _startIndex;
1511*f6dc9357SAndroid Build Coastguard Worker   unsigned _currentIndex;
1512*f6dc9357SAndroid Build Coastguard Worker 
1513*f6dc9357SAndroid Build Coastguard Worker   HRESULT OpenFile();
1514*f6dc9357SAndroid Build Coastguard Worker   HRESULT CloseFile();
1515*f6dc9357SAndroid Build Coastguard Worker   HRESULT ProcessEmptyFiles();
1516*f6dc9357SAndroid Build Coastguard Worker 
1517*f6dc9357SAndroid Build Coastguard Worker public:
1518*f6dc9357SAndroid Build Coastguard Worker   const CDbEx *_db;
1519*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IArchiveUpdateCallbackFile> _opCallback;
1520*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IArchiveExtractCallbackMessage2> _extractCallback;
1521*f6dc9357SAndroid Build Coastguard Worker 
1522*f6dc9357SAndroid Build Coastguard Worker   HRESULT Init(UInt32 startIndex, const CBoolVector *extractStatuses);
1523*f6dc9357SAndroid Build Coastguard Worker   HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }
1524*f6dc9357SAndroid Build Coastguard Worker };
1525*f6dc9357SAndroid Build Coastguard Worker 
1526*f6dc9357SAndroid Build Coastguard Worker HRESULT CRepackStreamBase::Init(UInt32 startIndex, const CBoolVector *extractStatuses)
1527*f6dc9357SAndroid Build Coastguard Worker {
1528*f6dc9357SAndroid Build Coastguard Worker   _startIndex = startIndex;
1529*f6dc9357SAndroid Build Coastguard Worker   _extractStatuses = extractStatuses;
1530*f6dc9357SAndroid Build Coastguard Worker 
1531*f6dc9357SAndroid Build Coastguard Worker   _currentIndex = 0;
1532*f6dc9357SAndroid Build Coastguard Worker   _fileIsOpen = false;
1533*f6dc9357SAndroid Build Coastguard Worker 
1534*f6dc9357SAndroid Build Coastguard Worker   return ProcessEmptyFiles();
1535*f6dc9357SAndroid Build Coastguard Worker }
1536*f6dc9357SAndroid Build Coastguard Worker 
1537*f6dc9357SAndroid Build Coastguard Worker HRESULT CRepackStreamBase::OpenFile()
1538*f6dc9357SAndroid Build Coastguard Worker {
1539*f6dc9357SAndroid Build Coastguard Worker   UInt32 arcIndex = _startIndex + _currentIndex;
1540*f6dc9357SAndroid Build Coastguard Worker   const CFileItem &fi = _db->Files[arcIndex];
1541*f6dc9357SAndroid Build Coastguard Worker 
1542*f6dc9357SAndroid Build Coastguard Worker   _needWrite = (*_extractStatuses)[_currentIndex];
1543*f6dc9357SAndroid Build Coastguard Worker   if (_opCallback)
1544*f6dc9357SAndroid Build Coastguard Worker   {
1545*f6dc9357SAndroid Build Coastguard Worker     RINOK(_opCallback->ReportOperation(
1546*f6dc9357SAndroid Build Coastguard Worker         NEventIndexType::kInArcIndex, arcIndex,
1547*f6dc9357SAndroid Build Coastguard Worker         _needWrite ?
1548*f6dc9357SAndroid Build Coastguard Worker             NUpdateNotifyOp::kRepack :
1549*f6dc9357SAndroid Build Coastguard Worker             NUpdateNotifyOp::kSkip))
1550*f6dc9357SAndroid Build Coastguard Worker   }
1551*f6dc9357SAndroid Build Coastguard Worker 
1552*f6dc9357SAndroid Build Coastguard Worker   _crc = CRC_INIT_VAL;
1553*f6dc9357SAndroid Build Coastguard Worker   _calcCrc = (fi.CrcDefined && !fi.IsDir);
1554*f6dc9357SAndroid Build Coastguard Worker 
1555*f6dc9357SAndroid Build Coastguard Worker   _fileIsOpen = true;
1556*f6dc9357SAndroid Build Coastguard Worker   _rem = fi.Size;
1557*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1558*f6dc9357SAndroid Build Coastguard Worker }
1559*f6dc9357SAndroid Build Coastguard Worker 
1560*f6dc9357SAndroid Build Coastguard Worker const HRESULT k_My_HRESULT_CRC_ERROR = 0x20000002;
1561*f6dc9357SAndroid Build Coastguard Worker 
1562*f6dc9357SAndroid Build Coastguard Worker HRESULT CRepackStreamBase::CloseFile()
1563*f6dc9357SAndroid Build Coastguard Worker {
1564*f6dc9357SAndroid Build Coastguard Worker   UInt32 arcIndex = _startIndex + _currentIndex;
1565*f6dc9357SAndroid Build Coastguard Worker   const CFileItem &fi = _db->Files[arcIndex];
1566*f6dc9357SAndroid Build Coastguard Worker   _fileIsOpen = false;
1567*f6dc9357SAndroid Build Coastguard Worker   _currentIndex++;
1568*f6dc9357SAndroid Build Coastguard Worker   if (!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc))
1569*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1570*f6dc9357SAndroid Build Coastguard Worker 
1571*f6dc9357SAndroid Build Coastguard Worker   if (_extractCallback)
1572*f6dc9357SAndroid Build Coastguard Worker   {
1573*f6dc9357SAndroid Build Coastguard Worker     RINOK(_extractCallback->ReportExtractResult(
1574*f6dc9357SAndroid Build Coastguard Worker         NEventIndexType::kInArcIndex, arcIndex,
1575*f6dc9357SAndroid Build Coastguard Worker         NExtract::NOperationResult::kCRCError))
1576*f6dc9357SAndroid Build Coastguard Worker   }
1577*f6dc9357SAndroid Build Coastguard Worker   // return S_FALSE;
1578*f6dc9357SAndroid Build Coastguard Worker   return k_My_HRESULT_CRC_ERROR;
1579*f6dc9357SAndroid Build Coastguard Worker }
1580*f6dc9357SAndroid Build Coastguard Worker 
1581*f6dc9357SAndroid Build Coastguard Worker HRESULT CRepackStreamBase::ProcessEmptyFiles()
1582*f6dc9357SAndroid Build Coastguard Worker {
1583*f6dc9357SAndroid Build Coastguard Worker   while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)
1584*f6dc9357SAndroid Build Coastguard Worker   {
1585*f6dc9357SAndroid Build Coastguard Worker     RINOK(OpenFile())
1586*f6dc9357SAndroid Build Coastguard Worker     RINOK(CloseFile())
1587*f6dc9357SAndroid Build Coastguard Worker   }
1588*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1589*f6dc9357SAndroid Build Coastguard Worker }
1590*f6dc9357SAndroid Build Coastguard Worker 
1591*f6dc9357SAndroid Build Coastguard Worker 
1592*f6dc9357SAndroid Build Coastguard Worker 
1593*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST
1594*f6dc9357SAndroid Build Coastguard Worker 
1595*f6dc9357SAndroid Build Coastguard Worker class CFolderOutStream2 Z7_final:
1596*f6dc9357SAndroid Build Coastguard Worker   public CRepackStreamBase,
1597*f6dc9357SAndroid Build Coastguard Worker   public ISequentialOutStream,
1598*f6dc9357SAndroid Build Coastguard Worker   public CMyUnknownImp
1599*f6dc9357SAndroid Build Coastguard Worker {
1600*f6dc9357SAndroid Build Coastguard Worker   Z7_COM_UNKNOWN_IMP_0
1601*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(ISequentialOutStream)
1602*f6dc9357SAndroid Build Coastguard Worker public:
1603*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialOutStream> _stream;
1604*f6dc9357SAndroid Build Coastguard Worker };
1605*f6dc9357SAndroid Build Coastguard Worker 
1606*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize))
1607*f6dc9357SAndroid Build Coastguard Worker {
1608*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
1609*f6dc9357SAndroid Build Coastguard Worker     *processedSize = 0;
1610*f6dc9357SAndroid Build Coastguard Worker 
1611*f6dc9357SAndroid Build Coastguard Worker   while (size != 0)
1612*f6dc9357SAndroid Build Coastguard Worker   {
1613*f6dc9357SAndroid Build Coastguard Worker     if (_fileIsOpen)
1614*f6dc9357SAndroid Build Coastguard Worker     {
1615*f6dc9357SAndroid Build Coastguard Worker       UInt32 cur = (size < _rem ? size : (UInt32)_rem);
1616*f6dc9357SAndroid Build Coastguard Worker       HRESULT result = S_OK;
1617*f6dc9357SAndroid Build Coastguard Worker       if (_needWrite)
1618*f6dc9357SAndroid Build Coastguard Worker         result = _stream->Write(data, cur, &cur);
1619*f6dc9357SAndroid Build Coastguard Worker       if (_calcCrc)
1620*f6dc9357SAndroid Build Coastguard Worker         _crc = CrcUpdate(_crc, data, cur);
1621*f6dc9357SAndroid Build Coastguard Worker       if (processedSize)
1622*f6dc9357SAndroid Build Coastguard Worker         *processedSize += cur;
1623*f6dc9357SAndroid Build Coastguard Worker       data = (const Byte *)data + cur;
1624*f6dc9357SAndroid Build Coastguard Worker       size -= cur;
1625*f6dc9357SAndroid Build Coastguard Worker       _rem -= cur;
1626*f6dc9357SAndroid Build Coastguard Worker       if (_rem == 0)
1627*f6dc9357SAndroid Build Coastguard Worker       {
1628*f6dc9357SAndroid Build Coastguard Worker         RINOK(CloseFile())
1629*f6dc9357SAndroid Build Coastguard Worker         RINOK(ProcessEmptyFiles())
1630*f6dc9357SAndroid Build Coastguard Worker       }
1631*f6dc9357SAndroid Build Coastguard Worker       RINOK(result)
1632*f6dc9357SAndroid Build Coastguard Worker       if (cur == 0)
1633*f6dc9357SAndroid Build Coastguard Worker         break;
1634*f6dc9357SAndroid Build Coastguard Worker       continue;
1635*f6dc9357SAndroid Build Coastguard Worker     }
1636*f6dc9357SAndroid Build Coastguard Worker 
1637*f6dc9357SAndroid Build Coastguard Worker     RINOK(ProcessEmptyFiles())
1638*f6dc9357SAndroid Build Coastguard Worker     if (_currentIndex == _extractStatuses->Size())
1639*f6dc9357SAndroid Build Coastguard Worker     {
1640*f6dc9357SAndroid Build Coastguard Worker       // we don't support write cut here
1641*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
1642*f6dc9357SAndroid Build Coastguard Worker     }
1643*f6dc9357SAndroid Build Coastguard Worker     RINOK(OpenFile())
1644*f6dc9357SAndroid Build Coastguard Worker   }
1645*f6dc9357SAndroid Build Coastguard Worker 
1646*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1647*f6dc9357SAndroid Build Coastguard Worker }
1648*f6dc9357SAndroid Build Coastguard Worker 
1649*f6dc9357SAndroid Build Coastguard Worker #endif
1650*f6dc9357SAndroid Build Coastguard Worker 
1651*f6dc9357SAndroid Build Coastguard Worker 
1652*f6dc9357SAndroid Build Coastguard Worker 
1653*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kTempBufSize = 1 << 16;
1654*f6dc9357SAndroid Build Coastguard Worker 
1655*f6dc9357SAndroid Build Coastguard Worker class CFolderInStream2 Z7_final:
1656*f6dc9357SAndroid Build Coastguard Worker   public CRepackStreamBase,
1657*f6dc9357SAndroid Build Coastguard Worker   public ISequentialInStream,
1658*f6dc9357SAndroid Build Coastguard Worker   public CMyUnknownImp
1659*f6dc9357SAndroid Build Coastguard Worker {
1660*f6dc9357SAndroid Build Coastguard Worker   Z7_COM_UNKNOWN_IMP_0
1661*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(ISequentialInStream)
1662*f6dc9357SAndroid Build Coastguard Worker 
1663*f6dc9357SAndroid Build Coastguard Worker   Byte *_buf;
1664*f6dc9357SAndroid Build Coastguard Worker public:
1665*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialInStream> _inStream;
1666*f6dc9357SAndroid Build Coastguard Worker   HRESULT Result;
1667*f6dc9357SAndroid Build Coastguard Worker 
1668*f6dc9357SAndroid Build Coastguard Worker   CFolderInStream2():
1669*f6dc9357SAndroid Build Coastguard Worker       Result(S_OK)
1670*f6dc9357SAndroid Build Coastguard Worker   {
1671*f6dc9357SAndroid Build Coastguard Worker     _buf = new Byte[kTempBufSize];
1672*f6dc9357SAndroid Build Coastguard Worker   }
1673*f6dc9357SAndroid Build Coastguard Worker 
1674*f6dc9357SAndroid Build Coastguard Worker   ~CFolderInStream2()
1675*f6dc9357SAndroid Build Coastguard Worker   {
1676*f6dc9357SAndroid Build Coastguard Worker     delete []_buf;
1677*f6dc9357SAndroid Build Coastguard Worker   }
1678*f6dc9357SAndroid Build Coastguard Worker 
1679*f6dc9357SAndroid Build Coastguard Worker   void Init() { Result = S_OK; }
1680*f6dc9357SAndroid Build Coastguard Worker };
1681*f6dc9357SAndroid Build Coastguard Worker 
1682*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CFolderInStream2::Read(void *data, UInt32 size, UInt32 *processedSize))
1683*f6dc9357SAndroid Build Coastguard Worker {
1684*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
1685*f6dc9357SAndroid Build Coastguard Worker     *processedSize = 0;
1686*f6dc9357SAndroid Build Coastguard Worker 
1687*f6dc9357SAndroid Build Coastguard Worker   while (size != 0)
1688*f6dc9357SAndroid Build Coastguard Worker   {
1689*f6dc9357SAndroid Build Coastguard Worker     if (_fileIsOpen)
1690*f6dc9357SAndroid Build Coastguard Worker     {
1691*f6dc9357SAndroid Build Coastguard Worker       UInt32 cur = (size < _rem ? size : (UInt32)_rem);
1692*f6dc9357SAndroid Build Coastguard Worker 
1693*f6dc9357SAndroid Build Coastguard Worker       void *buf;
1694*f6dc9357SAndroid Build Coastguard Worker       if (_needWrite)
1695*f6dc9357SAndroid Build Coastguard Worker         buf = data;
1696*f6dc9357SAndroid Build Coastguard Worker       else
1697*f6dc9357SAndroid Build Coastguard Worker       {
1698*f6dc9357SAndroid Build Coastguard Worker         buf = _buf;
1699*f6dc9357SAndroid Build Coastguard Worker         if (cur > kTempBufSize)
1700*f6dc9357SAndroid Build Coastguard Worker           cur = kTempBufSize;
1701*f6dc9357SAndroid Build Coastguard Worker       }
1702*f6dc9357SAndroid Build Coastguard Worker 
1703*f6dc9357SAndroid Build Coastguard Worker       const HRESULT result = _inStream->Read(buf, cur, &cur);
1704*f6dc9357SAndroid Build Coastguard Worker       _crc = CrcUpdate(_crc, buf, cur);
1705*f6dc9357SAndroid Build Coastguard Worker       _rem -= cur;
1706*f6dc9357SAndroid Build Coastguard Worker 
1707*f6dc9357SAndroid Build Coastguard Worker       if (_needWrite)
1708*f6dc9357SAndroid Build Coastguard Worker       {
1709*f6dc9357SAndroid Build Coastguard Worker         data = (Byte *)data + cur;
1710*f6dc9357SAndroid Build Coastguard Worker         size -= cur;
1711*f6dc9357SAndroid Build Coastguard Worker         if (processedSize)
1712*f6dc9357SAndroid Build Coastguard Worker           *processedSize += cur;
1713*f6dc9357SAndroid Build Coastguard Worker       }
1714*f6dc9357SAndroid Build Coastguard Worker 
1715*f6dc9357SAndroid Build Coastguard Worker       if (result != S_OK)
1716*f6dc9357SAndroid Build Coastguard Worker         Result = result;
1717*f6dc9357SAndroid Build Coastguard Worker 
1718*f6dc9357SAndroid Build Coastguard Worker       if (_rem == 0)
1719*f6dc9357SAndroid Build Coastguard Worker       {
1720*f6dc9357SAndroid Build Coastguard Worker         RINOK(CloseFile())
1721*f6dc9357SAndroid Build Coastguard Worker         RINOK(ProcessEmptyFiles())
1722*f6dc9357SAndroid Build Coastguard Worker       }
1723*f6dc9357SAndroid Build Coastguard Worker 
1724*f6dc9357SAndroid Build Coastguard Worker       RINOK(result)
1725*f6dc9357SAndroid Build Coastguard Worker 
1726*f6dc9357SAndroid Build Coastguard Worker       if (cur == 0)
1727*f6dc9357SAndroid Build Coastguard Worker         return E_FAIL;
1728*f6dc9357SAndroid Build Coastguard Worker 
1729*f6dc9357SAndroid Build Coastguard Worker       continue;
1730*f6dc9357SAndroid Build Coastguard Worker     }
1731*f6dc9357SAndroid Build Coastguard Worker 
1732*f6dc9357SAndroid Build Coastguard Worker     RINOK(ProcessEmptyFiles())
1733*f6dc9357SAndroid Build Coastguard Worker     if (_currentIndex == _extractStatuses->Size())
1734*f6dc9357SAndroid Build Coastguard Worker     {
1735*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1736*f6dc9357SAndroid Build Coastguard Worker     }
1737*f6dc9357SAndroid Build Coastguard Worker     RINOK(OpenFile())
1738*f6dc9357SAndroid Build Coastguard Worker   }
1739*f6dc9357SAndroid Build Coastguard Worker 
1740*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1741*f6dc9357SAndroid Build Coastguard Worker }
1742*f6dc9357SAndroid Build Coastguard Worker 
1743*f6dc9357SAndroid Build Coastguard Worker 
1744*f6dc9357SAndroid Build Coastguard Worker class CThreadDecoder Z7_final
1745*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ST
1746*f6dc9357SAndroid Build Coastguard Worker     : public CVirtThread
1747*f6dc9357SAndroid Build Coastguard Worker   #endif
1748*f6dc9357SAndroid Build Coastguard Worker {
1749*f6dc9357SAndroid Build Coastguard Worker public:
1750*f6dc9357SAndroid Build Coastguard Worker   CDecoder Decoder;
1751*f6dc9357SAndroid Build Coastguard Worker 
1752*f6dc9357SAndroid Build Coastguard Worker   CThreadDecoder(bool multiThreadMixer):
1753*f6dc9357SAndroid Build Coastguard Worker       Decoder(multiThreadMixer)
1754*f6dc9357SAndroid Build Coastguard Worker   {
1755*f6dc9357SAndroid Build Coastguard Worker     #ifndef Z7_ST
1756*f6dc9357SAndroid Build Coastguard Worker     if (multiThreadMixer)
1757*f6dc9357SAndroid Build Coastguard Worker     {
1758*f6dc9357SAndroid Build Coastguard Worker       MtMode = false;
1759*f6dc9357SAndroid Build Coastguard Worker       NumThreads = 1;
1760*f6dc9357SAndroid Build Coastguard Worker       FosSpec = new CFolderOutStream2;
1761*f6dc9357SAndroid Build Coastguard Worker       Fos = FosSpec;
1762*f6dc9357SAndroid Build Coastguard Worker       Result = E_FAIL;
1763*f6dc9357SAndroid Build Coastguard Worker     }
1764*f6dc9357SAndroid Build Coastguard Worker     #endif
1765*f6dc9357SAndroid Build Coastguard Worker     // UnpackSize = 0;
1766*f6dc9357SAndroid Build Coastguard Worker     // send_UnpackSize = false;
1767*f6dc9357SAndroid Build Coastguard Worker   }
1768*f6dc9357SAndroid Build Coastguard Worker 
1769*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ST
1770*f6dc9357SAndroid Build Coastguard Worker 
1771*f6dc9357SAndroid Build Coastguard Worker   bool dataAfterEnd_Error;
1772*f6dc9357SAndroid Build Coastguard Worker   HRESULT Result;
1773*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IInStream> InStream;
1774*f6dc9357SAndroid Build Coastguard Worker 
1775*f6dc9357SAndroid Build Coastguard Worker   CFolderOutStream2 *FosSpec;
1776*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialOutStream> Fos;
1777*f6dc9357SAndroid Build Coastguard Worker 
1778*f6dc9357SAndroid Build Coastguard Worker   UInt64 StartPos;
1779*f6dc9357SAndroid Build Coastguard Worker   const CFolders *Folders;
1780*f6dc9357SAndroid Build Coastguard Worker   unsigned FolderIndex;
1781*f6dc9357SAndroid Build Coastguard Worker 
1782*f6dc9357SAndroid Build Coastguard Worker   // bool send_UnpackSize;
1783*f6dc9357SAndroid Build Coastguard Worker   // UInt64 UnpackSize;
1784*f6dc9357SAndroid Build Coastguard Worker 
1785*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_NO_CRYPTO
1786*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ICryptoGetTextPassword> getTextPassword;
1787*f6dc9357SAndroid Build Coastguard Worker   #endif
1788*f6dc9357SAndroid Build Coastguard Worker 
1789*f6dc9357SAndroid Build Coastguard Worker   DECL_EXTERNAL_CODECS_LOC_VARS_DECL
1790*f6dc9357SAndroid Build Coastguard Worker 
1791*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ST
1792*f6dc9357SAndroid Build Coastguard Worker   bool MtMode;
1793*f6dc9357SAndroid Build Coastguard Worker   UInt32 NumThreads;
1794*f6dc9357SAndroid Build Coastguard Worker   #endif
1795*f6dc9357SAndroid Build Coastguard Worker 
1796*f6dc9357SAndroid Build Coastguard Worker 
1797*f6dc9357SAndroid Build Coastguard Worker   ~CThreadDecoder() Z7_DESTRUCTOR_override
1798*f6dc9357SAndroid Build Coastguard Worker   {
1799*f6dc9357SAndroid Build Coastguard Worker     /* WaitThreadFinish() will be called in ~CVirtThread().
1800*f6dc9357SAndroid Build Coastguard Worker        But we need WaitThreadFinish() call before
1801*f6dc9357SAndroid Build Coastguard Worker        destructors of this class members.
1802*f6dc9357SAndroid Build Coastguard Worker     */
1803*f6dc9357SAndroid Build Coastguard Worker     CVirtThread::WaitThreadFinish();
1804*f6dc9357SAndroid Build Coastguard Worker   }
1805*f6dc9357SAndroid Build Coastguard Worker private:
1806*f6dc9357SAndroid Build Coastguard Worker   virtual void Execute() Z7_override;
1807*f6dc9357SAndroid Build Coastguard Worker 
1808*f6dc9357SAndroid Build Coastguard Worker   #endif
1809*f6dc9357SAndroid Build Coastguard Worker };
1810*f6dc9357SAndroid Build Coastguard Worker 
1811*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST
1812*f6dc9357SAndroid Build Coastguard Worker 
1813*f6dc9357SAndroid Build Coastguard Worker void CThreadDecoder::Execute()
1814*f6dc9357SAndroid Build Coastguard Worker {
1815*f6dc9357SAndroid Build Coastguard Worker   try
1816*f6dc9357SAndroid Build Coastguard Worker   {
1817*f6dc9357SAndroid Build Coastguard Worker     #ifndef Z7_NO_CRYPTO
1818*f6dc9357SAndroid Build Coastguard Worker       bool isEncrypted = false;
1819*f6dc9357SAndroid Build Coastguard Worker       bool passwordIsDefined = false;
1820*f6dc9357SAndroid Build Coastguard Worker       UString password;
1821*f6dc9357SAndroid Build Coastguard Worker     #endif
1822*f6dc9357SAndroid Build Coastguard Worker 
1823*f6dc9357SAndroid Build Coastguard Worker     dataAfterEnd_Error = false;
1824*f6dc9357SAndroid Build Coastguard Worker 
1825*f6dc9357SAndroid Build Coastguard Worker     Result = Decoder.Decode(
1826*f6dc9357SAndroid Build Coastguard Worker       EXTERNAL_CODECS_LOC_VARS
1827*f6dc9357SAndroid Build Coastguard Worker       InStream,
1828*f6dc9357SAndroid Build Coastguard Worker       StartPos,
1829*f6dc9357SAndroid Build Coastguard Worker       *Folders, FolderIndex,
1830*f6dc9357SAndroid Build Coastguard Worker 
1831*f6dc9357SAndroid Build Coastguard Worker       // send_UnpackSize ? &UnpackSize : NULL,
1832*f6dc9357SAndroid Build Coastguard Worker       NULL, // unpackSize : FULL unpack
1833*f6dc9357SAndroid Build Coastguard Worker 
1834*f6dc9357SAndroid Build Coastguard Worker       Fos,
1835*f6dc9357SAndroid Build Coastguard Worker       NULL, // compressProgress
1836*f6dc9357SAndroid Build Coastguard Worker 
1837*f6dc9357SAndroid Build Coastguard Worker       NULL  // *inStreamMainRes
1838*f6dc9357SAndroid Build Coastguard Worker       , dataAfterEnd_Error
1839*f6dc9357SAndroid Build Coastguard Worker 
1840*f6dc9357SAndroid Build Coastguard Worker       Z7_7Z_DECODER_CRYPRO_VARS
1841*f6dc9357SAndroid Build Coastguard Worker       #ifndef Z7_ST
1842*f6dc9357SAndroid Build Coastguard Worker         , MtMode, NumThreads,
1843*f6dc9357SAndroid Build Coastguard Worker         0 // MemUsage
1844*f6dc9357SAndroid Build Coastguard Worker       #endif
1845*f6dc9357SAndroid Build Coastguard Worker 
1846*f6dc9357SAndroid Build Coastguard Worker       );
1847*f6dc9357SAndroid Build Coastguard Worker   }
1848*f6dc9357SAndroid Build Coastguard Worker   catch(...)
1849*f6dc9357SAndroid Build Coastguard Worker   {
1850*f6dc9357SAndroid Build Coastguard Worker     Result = E_FAIL;
1851*f6dc9357SAndroid Build Coastguard Worker   }
1852*f6dc9357SAndroid Build Coastguard Worker 
1853*f6dc9357SAndroid Build Coastguard Worker   /*
1854*f6dc9357SAndroid Build Coastguard Worker   if (Result == S_OK)
1855*f6dc9357SAndroid Build Coastguard Worker     Result = FosSpec->CheckFinishedState();
1856*f6dc9357SAndroid Build Coastguard Worker   */
1857*f6dc9357SAndroid Build Coastguard Worker   FosSpec->_stream.Release();
1858*f6dc9357SAndroid Build Coastguard Worker }
1859*f6dc9357SAndroid Build Coastguard Worker 
1860*f6dc9357SAndroid Build Coastguard Worker #endif
1861*f6dc9357SAndroid Build Coastguard Worker 
1862*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_NO_CRYPTO
1863*f6dc9357SAndroid Build Coastguard Worker 
1864*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_NOQIB_1(
1865*f6dc9357SAndroid Build Coastguard Worker   CCryptoGetTextPassword
1866*f6dc9357SAndroid Build Coastguard Worker   , ICryptoGetTextPassword
1867*f6dc9357SAndroid Build Coastguard Worker )
1868*f6dc9357SAndroid Build Coastguard Worker public:
1869*f6dc9357SAndroid Build Coastguard Worker   UString Password;
1870*f6dc9357SAndroid Build Coastguard Worker };
1871*f6dc9357SAndroid Build Coastguard Worker 
1872*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password))
1873*f6dc9357SAndroid Build Coastguard Worker {
1874*f6dc9357SAndroid Build Coastguard Worker   return StringToBstr(Password, password);
1875*f6dc9357SAndroid Build Coastguard Worker }
1876*f6dc9357SAndroid Build Coastguard Worker 
1877*f6dc9357SAndroid Build Coastguard Worker #endif
1878*f6dc9357SAndroid Build Coastguard Worker 
1879*f6dc9357SAndroid Build Coastguard Worker 
1880*f6dc9357SAndroid Build Coastguard Worker static void GetFile(const CDatabase &inDb, unsigned index, CFileItem &file, CFileItem2 &file2)
1881*f6dc9357SAndroid Build Coastguard Worker {
1882*f6dc9357SAndroid Build Coastguard Worker   file = inDb.Files[index];
1883*f6dc9357SAndroid Build Coastguard Worker   file2.CTimeDefined = inDb.CTime.GetItem(index, file2.CTime);
1884*f6dc9357SAndroid Build Coastguard Worker   file2.ATimeDefined = inDb.ATime.GetItem(index, file2.ATime);
1885*f6dc9357SAndroid Build Coastguard Worker   file2.MTimeDefined = inDb.MTime.GetItem(index, file2.MTime);
1886*f6dc9357SAndroid Build Coastguard Worker   file2.StartPosDefined = inDb.StartPos.GetItem(index, file2.StartPos);
1887*f6dc9357SAndroid Build Coastguard Worker   file2.AttribDefined = inDb.Attrib.GetItem(index, file2.Attrib);
1888*f6dc9357SAndroid Build Coastguard Worker   file2.IsAnti = inDb.IsItemAnti(index);
1889*f6dc9357SAndroid Build Coastguard Worker   // file2.IsAux = inDb.IsItemAux(index);
1890*f6dc9357SAndroid Build Coastguard Worker }
1891*f6dc9357SAndroid Build Coastguard Worker 
1892*f6dc9357SAndroid Build Coastguard Worker HRESULT Update(
1893*f6dc9357SAndroid Build Coastguard Worker     DECL_EXTERNAL_CODECS_LOC_VARS
1894*f6dc9357SAndroid Build Coastguard Worker     IInStream *inStream,
1895*f6dc9357SAndroid Build Coastguard Worker     const CDbEx *db,
1896*f6dc9357SAndroid Build Coastguard Worker     CObjectVector<CUpdateItem> &updateItems,
1897*f6dc9357SAndroid Build Coastguard Worker     // const CObjectVector<CTreeFolder> &treeFolders,
1898*f6dc9357SAndroid Build Coastguard Worker     // const CUniqBlocks &secureBlocks,
1899*f6dc9357SAndroid Build Coastguard Worker     ISequentialOutStream *seqOutStream,
1900*f6dc9357SAndroid Build Coastguard Worker     IArchiveUpdateCallback *updateCallback,
1901*f6dc9357SAndroid Build Coastguard Worker     const CUpdateOptions &options)
1902*f6dc9357SAndroid Build Coastguard Worker {
1903*f6dc9357SAndroid Build Coastguard Worker   UInt64 numSolidFiles = options.NumSolidFiles;
1904*f6dc9357SAndroid Build Coastguard Worker   if (numSolidFiles == 0)
1905*f6dc9357SAndroid Build Coastguard Worker     numSolidFiles = 1;
1906*f6dc9357SAndroid Build Coastguard Worker 
1907*f6dc9357SAndroid Build Coastguard Worker   Z7_DECL_CMyComPtr_QI_FROM(
1908*f6dc9357SAndroid Build Coastguard Worker       IArchiveUpdateCallbackFile,
1909*f6dc9357SAndroid Build Coastguard Worker       opCallback, updateCallback)
1910*f6dc9357SAndroid Build Coastguard Worker 
1911*f6dc9357SAndroid Build Coastguard Worker   Z7_DECL_CMyComPtr_QI_FROM(
1912*f6dc9357SAndroid Build Coastguard Worker       IArchiveExtractCallbackMessage2,
1913*f6dc9357SAndroid Build Coastguard Worker       extractCallback, updateCallback)
1914*f6dc9357SAndroid Build Coastguard Worker 
1915*f6dc9357SAndroid Build Coastguard Worker   /*
1916*f6dc9357SAndroid Build Coastguard Worker   Z7_DECL_CMyComPtr_QI_FROM(
1917*f6dc9357SAndroid Build Coastguard Worker       IArchiveUpdateCallbackArcProp,
1918*f6dc9357SAndroid Build Coastguard Worker       reportArcProp, updateCallback)
1919*f6dc9357SAndroid Build Coastguard Worker   */
1920*f6dc9357SAndroid Build Coastguard Worker 
1921*f6dc9357SAndroid Build Coastguard Worker   // size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes();
1922*f6dc9357SAndroid Build Coastguard Worker 
1923*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IStreamSetRestriction> v_StreamSetRestriction;
1924*f6dc9357SAndroid Build Coastguard Worker   {
1925*f6dc9357SAndroid Build Coastguard Worker     Z7_DECL_CMyComPtr_QI_FROM(
1926*f6dc9357SAndroid Build Coastguard Worker         IOutStream,
1927*f6dc9357SAndroid Build Coastguard Worker         outStream, seqOutStream)
1928*f6dc9357SAndroid Build Coastguard Worker     if (!outStream)
1929*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
1930*f6dc9357SAndroid Build Coastguard Worker     const UInt64 sfxBlockSize = (db && !options.RemoveSfxBlock) ?
1931*f6dc9357SAndroid Build Coastguard Worker         db->ArcInfo.StartPosition: 0;
1932*f6dc9357SAndroid Build Coastguard Worker     seqOutStream->QueryInterface(IID_IStreamSetRestriction, (void **)&v_StreamSetRestriction);
1933*f6dc9357SAndroid Build Coastguard Worker     if (v_StreamSetRestriction)
1934*f6dc9357SAndroid Build Coastguard Worker     {
1935*f6dc9357SAndroid Build Coastguard Worker       UInt64 offset = 0;
1936*f6dc9357SAndroid Build Coastguard Worker       RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &offset))
1937*f6dc9357SAndroid Build Coastguard Worker       RINOK(v_StreamSetRestriction->SetRestriction(
1938*f6dc9357SAndroid Build Coastguard Worker           outStream ? offset + sfxBlockSize : 0,
1939*f6dc9357SAndroid Build Coastguard Worker           outStream ? offset + sfxBlockSize + k_StartHeadersRewriteSize : 0))
1940*f6dc9357SAndroid Build Coastguard Worker     }
1941*f6dc9357SAndroid Build Coastguard Worker     outStream.Release();
1942*f6dc9357SAndroid Build Coastguard Worker     if (sfxBlockSize != 0)
1943*f6dc9357SAndroid Build Coastguard Worker     {
1944*f6dc9357SAndroid Build Coastguard Worker       RINOK(WriteRange(inStream, seqOutStream, 0, sfxBlockSize, NULL))
1945*f6dc9357SAndroid Build Coastguard Worker     }
1946*f6dc9357SAndroid Build Coastguard Worker   }
1947*f6dc9357SAndroid Build Coastguard Worker 
1948*f6dc9357SAndroid Build Coastguard Worker   CIntArr fileIndexToUpdateIndexMap;
1949*f6dc9357SAndroid Build Coastguard Worker   UInt64 complexity = 0;
1950*f6dc9357SAndroid Build Coastguard Worker   bool isThere_UnknownSize = false;
1951*f6dc9357SAndroid Build Coastguard Worker   UInt64 inSizeForReduce2 = 0;
1952*f6dc9357SAndroid Build Coastguard Worker 
1953*f6dc9357SAndroid Build Coastguard Worker  #ifndef Z7_NO_CRYPTO
1954*f6dc9357SAndroid Build Coastguard Worker   bool needEncryptedRepack = false;
1955*f6dc9357SAndroid Build Coastguard Worker  #endif
1956*f6dc9357SAndroid Build Coastguard Worker 
1957*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<CFilterMode2> filters;
1958*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CSolidGroup> groups;
1959*f6dc9357SAndroid Build Coastguard Worker 
1960*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ST
1961*f6dc9357SAndroid Build Coastguard Worker   bool thereAreRepacks = false;
1962*f6dc9357SAndroid Build Coastguard Worker   #endif
1963*f6dc9357SAndroid Build Coastguard Worker 
1964*f6dc9357SAndroid Build Coastguard Worker   bool useFilters = options.UseFilters;
1965*f6dc9357SAndroid Build Coastguard Worker   if (useFilters)
1966*f6dc9357SAndroid Build Coastguard Worker   {
1967*f6dc9357SAndroid Build Coastguard Worker     const CCompressionMethodMode &method = *options.Method;
1968*f6dc9357SAndroid Build Coastguard Worker 
1969*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, method.Methods)
1970*f6dc9357SAndroid Build Coastguard Worker     {
1971*f6dc9357SAndroid Build Coastguard Worker       /* IsFilterMethod() knows only built-in codecs
1972*f6dc9357SAndroid Build Coastguard Worker          FIXME: we should check IsFilter status for external filters too */
1973*f6dc9357SAndroid Build Coastguard Worker       if (IsFilterMethod(method.Methods[i].Id))
1974*f6dc9357SAndroid Build Coastguard Worker       {
1975*f6dc9357SAndroid Build Coastguard Worker         useFilters = false;
1976*f6dc9357SAndroid Build Coastguard Worker         break;
1977*f6dc9357SAndroid Build Coastguard Worker       }
1978*f6dc9357SAndroid Build Coastguard Worker     }
1979*f6dc9357SAndroid Build Coastguard Worker   }
1980*f6dc9357SAndroid Build Coastguard Worker 
1981*f6dc9357SAndroid Build Coastguard Worker   if (db)
1982*f6dc9357SAndroid Build Coastguard Worker   {
1983*f6dc9357SAndroid Build Coastguard Worker     fileIndexToUpdateIndexMap.Alloc(db->Files.Size());
1984*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
1985*f6dc9357SAndroid Build Coastguard Worker 
1986*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < db->Files.Size(); i++)
1987*f6dc9357SAndroid Build Coastguard Worker       fileIndexToUpdateIndexMap[i] = -1;
1988*f6dc9357SAndroid Build Coastguard Worker 
1989*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < updateItems.Size(); i++)
1990*f6dc9357SAndroid Build Coastguard Worker     {
1991*f6dc9357SAndroid Build Coastguard Worker       int index = updateItems[i].IndexInArchive;
1992*f6dc9357SAndroid Build Coastguard Worker       if (index != -1)
1993*f6dc9357SAndroid Build Coastguard Worker         fileIndexToUpdateIndexMap[(unsigned)index] = (int)i;
1994*f6dc9357SAndroid Build Coastguard Worker     }
1995*f6dc9357SAndroid Build Coastguard Worker 
1996*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < db->NumFolders; i++)
1997*f6dc9357SAndroid Build Coastguard Worker     {
1998*f6dc9357SAndroid Build Coastguard Worker       CNum indexInFolder = 0;
1999*f6dc9357SAndroid Build Coastguard Worker       CNum numCopyItems = 0;
2000*f6dc9357SAndroid Build Coastguard Worker       const CNum numUnpackStreams = db->NumUnpackStreamsVector[i];
2001*f6dc9357SAndroid Build Coastguard Worker       UInt64 repackSize = 0;
2002*f6dc9357SAndroid Build Coastguard Worker 
2003*f6dc9357SAndroid Build Coastguard Worker       for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++)
2004*f6dc9357SAndroid Build Coastguard Worker       {
2005*f6dc9357SAndroid Build Coastguard Worker         if (fi >= db->Files.Size())
2006*f6dc9357SAndroid Build Coastguard Worker           return E_FAIL;
2007*f6dc9357SAndroid Build Coastguard Worker 
2008*f6dc9357SAndroid Build Coastguard Worker         const CFileItem &file = db->Files[fi];
2009*f6dc9357SAndroid Build Coastguard Worker         if (file.HasStream)
2010*f6dc9357SAndroid Build Coastguard Worker         {
2011*f6dc9357SAndroid Build Coastguard Worker           indexInFolder++;
2012*f6dc9357SAndroid Build Coastguard Worker           const int updateIndex = fileIndexToUpdateIndexMap[fi];
2013*f6dc9357SAndroid Build Coastguard Worker           if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData)
2014*f6dc9357SAndroid Build Coastguard Worker           {
2015*f6dc9357SAndroid Build Coastguard Worker             numCopyItems++;
2016*f6dc9357SAndroid Build Coastguard Worker             repackSize += file.Size;
2017*f6dc9357SAndroid Build Coastguard Worker           }
2018*f6dc9357SAndroid Build Coastguard Worker         }
2019*f6dc9357SAndroid Build Coastguard Worker       }
2020*f6dc9357SAndroid Build Coastguard Worker 
2021*f6dc9357SAndroid Build Coastguard Worker       if (numCopyItems == 0)
2022*f6dc9357SAndroid Build Coastguard Worker         continue;
2023*f6dc9357SAndroid Build Coastguard Worker 
2024*f6dc9357SAndroid Build Coastguard Worker       CFolderRepack rep;
2025*f6dc9357SAndroid Build Coastguard Worker       rep.FolderIndex = i;
2026*f6dc9357SAndroid Build Coastguard Worker       rep.NumCopyFiles = numCopyItems;
2027*f6dc9357SAndroid Build Coastguard Worker       CFolderEx f;
2028*f6dc9357SAndroid Build Coastguard Worker       db->ParseFolderEx(i, f);
2029*f6dc9357SAndroid Build Coastguard Worker 
2030*f6dc9357SAndroid Build Coastguard Worker      #ifndef Z7_NO_CRYPTO
2031*f6dc9357SAndroid Build Coastguard Worker       const bool isEncrypted = f.IsEncrypted();
2032*f6dc9357SAndroid Build Coastguard Worker      #endif
2033*f6dc9357SAndroid Build Coastguard Worker       const bool needCopy = (numCopyItems == numUnpackStreams);
2034*f6dc9357SAndroid Build Coastguard Worker       const bool extractFilter = (useFilters || needCopy);
2035*f6dc9357SAndroid Build Coastguard Worker 
2036*f6dc9357SAndroid Build Coastguard Worker       const unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f, extractFilter);
2037*f6dc9357SAndroid Build Coastguard Worker 
2038*f6dc9357SAndroid Build Coastguard Worker       while (groupIndex >= groups.Size())
2039*f6dc9357SAndroid Build Coastguard Worker         groups.AddNew();
2040*f6dc9357SAndroid Build Coastguard Worker 
2041*f6dc9357SAndroid Build Coastguard Worker       groups[groupIndex].folderRefs.Add(rep);
2042*f6dc9357SAndroid Build Coastguard Worker 
2043*f6dc9357SAndroid Build Coastguard Worker       if (needCopy)
2044*f6dc9357SAndroid Build Coastguard Worker         complexity += db->GetFolderFullPackSize(i);
2045*f6dc9357SAndroid Build Coastguard Worker       else
2046*f6dc9357SAndroid Build Coastguard Worker       {
2047*f6dc9357SAndroid Build Coastguard Worker         #ifndef Z7_ST
2048*f6dc9357SAndroid Build Coastguard Worker         thereAreRepacks = true;
2049*f6dc9357SAndroid Build Coastguard Worker         #endif
2050*f6dc9357SAndroid Build Coastguard Worker         complexity += repackSize;
2051*f6dc9357SAndroid Build Coastguard Worker         if (inSizeForReduce2 < repackSize)
2052*f6dc9357SAndroid Build Coastguard Worker           inSizeForReduce2 = repackSize;
2053*f6dc9357SAndroid Build Coastguard Worker        #ifndef Z7_NO_CRYPTO
2054*f6dc9357SAndroid Build Coastguard Worker         if (isEncrypted)
2055*f6dc9357SAndroid Build Coastguard Worker           needEncryptedRepack = true;
2056*f6dc9357SAndroid Build Coastguard Worker        #endif
2057*f6dc9357SAndroid Build Coastguard Worker       }
2058*f6dc9357SAndroid Build Coastguard Worker     }
2059*f6dc9357SAndroid Build Coastguard Worker   }
2060*f6dc9357SAndroid Build Coastguard Worker 
2061*f6dc9357SAndroid Build Coastguard Worker   UInt64 inSizeForReduce = 0;
2062*f6dc9357SAndroid Build Coastguard Worker   {
2063*f6dc9357SAndroid Build Coastguard Worker     const bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0);
2064*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, updateItems)
2065*f6dc9357SAndroid Build Coastguard Worker     {
2066*f6dc9357SAndroid Build Coastguard Worker       const CUpdateItem &ui = updateItems[i];
2067*f6dc9357SAndroid Build Coastguard Worker       if (ui.NewData)
2068*f6dc9357SAndroid Build Coastguard Worker       {
2069*f6dc9357SAndroid Build Coastguard Worker         if (ui.Size == (UInt64)(Int64)-1)
2070*f6dc9357SAndroid Build Coastguard Worker           isThere_UnknownSize = true;
2071*f6dc9357SAndroid Build Coastguard Worker         else
2072*f6dc9357SAndroid Build Coastguard Worker         {
2073*f6dc9357SAndroid Build Coastguard Worker           complexity += ui.Size;
2074*f6dc9357SAndroid Build Coastguard Worker           if (isSolid)
2075*f6dc9357SAndroid Build Coastguard Worker             inSizeForReduce += ui.Size;
2076*f6dc9357SAndroid Build Coastguard Worker           else if (inSizeForReduce < ui.Size)
2077*f6dc9357SAndroid Build Coastguard Worker             inSizeForReduce = ui.Size;
2078*f6dc9357SAndroid Build Coastguard Worker         }
2079*f6dc9357SAndroid Build Coastguard Worker       }
2080*f6dc9357SAndroid Build Coastguard Worker     }
2081*f6dc9357SAndroid Build Coastguard Worker   }
2082*f6dc9357SAndroid Build Coastguard Worker 
2083*f6dc9357SAndroid Build Coastguard Worker   if (isThere_UnknownSize)
2084*f6dc9357SAndroid Build Coastguard Worker     inSizeForReduce = (UInt64)(Int64)-1;
2085*f6dc9357SAndroid Build Coastguard Worker   else
2086*f6dc9357SAndroid Build Coastguard Worker     RINOK(updateCallback->SetTotal(complexity))
2087*f6dc9357SAndroid Build Coastguard Worker 
2088*f6dc9357SAndroid Build Coastguard Worker   if (inSizeForReduce < inSizeForReduce2)
2089*f6dc9357SAndroid Build Coastguard Worker       inSizeForReduce = inSizeForReduce2;
2090*f6dc9357SAndroid Build Coastguard Worker 
2091*f6dc9357SAndroid Build Coastguard Worker 
2092*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
2093*f6dc9357SAndroid Build Coastguard Worker   lps->Init(updateCallback, true);
2094*f6dc9357SAndroid Build Coastguard Worker 
2095*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ST
2096*f6dc9357SAndroid Build Coastguard Worker 
2097*f6dc9357SAndroid Build Coastguard Worker   CStreamBinder sb;
2098*f6dc9357SAndroid Build Coastguard Worker   /*
2099*f6dc9357SAndroid Build Coastguard Worker   if (options.MultiThreadMixer)
2100*f6dc9357SAndroid Build Coastguard Worker   {
2101*f6dc9357SAndroid Build Coastguard Worker     RINOK(sb.CreateEvents());
2102*f6dc9357SAndroid Build Coastguard Worker   }
2103*f6dc9357SAndroid Build Coastguard Worker   */
2104*f6dc9357SAndroid Build Coastguard Worker 
2105*f6dc9357SAndroid Build Coastguard Worker   #endif
2106*f6dc9357SAndroid Build Coastguard Worker 
2107*f6dc9357SAndroid Build Coastguard Worker   CThreadDecoder threadDecoder(options.MultiThreadMixer);
2108*f6dc9357SAndroid Build Coastguard Worker 
2109*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ST
2110*f6dc9357SAndroid Build Coastguard Worker   if (options.MultiThreadMixer && thereAreRepacks)
2111*f6dc9357SAndroid Build Coastguard Worker   {
2112*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_EXTERNAL_CODECS
2113*f6dc9357SAndroid Build Coastguard Worker     threadDecoder._externalCodecs = _externalCodecs;
2114*f6dc9357SAndroid Build Coastguard Worker     #endif
2115*f6dc9357SAndroid Build Coastguard Worker     const WRes wres = threadDecoder.Create();
2116*f6dc9357SAndroid Build Coastguard Worker     if (wres != 0)
2117*f6dc9357SAndroid Build Coastguard Worker       return HRESULT_FROM_WIN32(wres);
2118*f6dc9357SAndroid Build Coastguard Worker   }
2119*f6dc9357SAndroid Build Coastguard Worker   #endif
2120*f6dc9357SAndroid Build Coastguard Worker 
2121*f6dc9357SAndroid Build Coastguard Worker   {
2122*f6dc9357SAndroid Build Coastguard Worker     CAnalysis analysis;
2123*f6dc9357SAndroid Build Coastguard Worker     // analysis.Need_ATime = options.Need_ATime;
2124*f6dc9357SAndroid Build Coastguard Worker     int analysisLevel = options.AnalysisLevel;
2125*f6dc9357SAndroid Build Coastguard Worker     // (analysisLevel < 0) means default level (5)
2126*f6dc9357SAndroid Build Coastguard Worker     if (analysisLevel < 0)
2127*f6dc9357SAndroid Build Coastguard Worker       analysisLevel = 5;
2128*f6dc9357SAndroid Build Coastguard Worker     if (analysisLevel != 0)
2129*f6dc9357SAndroid Build Coastguard Worker     {
2130*f6dc9357SAndroid Build Coastguard Worker       analysis.Callback = opCallback;
2131*f6dc9357SAndroid Build Coastguard Worker       analysis.ParseWav = true;
2132*f6dc9357SAndroid Build Coastguard Worker       if (analysisLevel >= 5)
2133*f6dc9357SAndroid Build Coastguard Worker       {
2134*f6dc9357SAndroid Build Coastguard Worker         analysis.ParseExe = true;
2135*f6dc9357SAndroid Build Coastguard Worker         analysis.ParseExeUnix = true;
2136*f6dc9357SAndroid Build Coastguard Worker         // analysis.ParseNoExt = true;
2137*f6dc9357SAndroid Build Coastguard Worker         if (analysisLevel >= 7)
2138*f6dc9357SAndroid Build Coastguard Worker         {
2139*f6dc9357SAndroid Build Coastguard Worker           analysis.ParseNoExt = true;
2140*f6dc9357SAndroid Build Coastguard Worker           if (analysisLevel >= 9)
2141*f6dc9357SAndroid Build Coastguard Worker             analysis.ParseAll = true;
2142*f6dc9357SAndroid Build Coastguard Worker         }
2143*f6dc9357SAndroid Build Coastguard Worker       }
2144*f6dc9357SAndroid Build Coastguard Worker     }
2145*f6dc9357SAndroid Build Coastguard Worker 
2146*f6dc9357SAndroid Build Coastguard Worker     // ---------- Split files to groups ----------
2147*f6dc9357SAndroid Build Coastguard Worker 
2148*f6dc9357SAndroid Build Coastguard Worker     const CCompressionMethodMode &method = *options.Method;
2149*f6dc9357SAndroid Build Coastguard Worker 
2150*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, updateItems)
2151*f6dc9357SAndroid Build Coastguard Worker     {
2152*f6dc9357SAndroid Build Coastguard Worker       const CUpdateItem &ui = updateItems[i];
2153*f6dc9357SAndroid Build Coastguard Worker       if (!ui.NewData || !ui.HasStream())
2154*f6dc9357SAndroid Build Coastguard Worker         continue;
2155*f6dc9357SAndroid Build Coastguard Worker 
2156*f6dc9357SAndroid Build Coastguard Worker       CFilterMode2 fm;
2157*f6dc9357SAndroid Build Coastguard Worker       if (useFilters)
2158*f6dc9357SAndroid Build Coastguard Worker       {
2159*f6dc9357SAndroid Build Coastguard Worker         // analysis.ATime_Defined = false;
2160*f6dc9357SAndroid Build Coastguard Worker         RINOK(analysis.GetFilterGroup(i, ui, fm))
2161*f6dc9357SAndroid Build Coastguard Worker         /*
2162*f6dc9357SAndroid Build Coastguard Worker         if (analysis.ATime_Defined)
2163*f6dc9357SAndroid Build Coastguard Worker         {
2164*f6dc9357SAndroid Build Coastguard Worker           ui.ATime = FILETIME_To_UInt64(analysis.ATime);
2165*f6dc9357SAndroid Build Coastguard Worker           ui.ATime_WasReadByAnalysis = true;
2166*f6dc9357SAndroid Build Coastguard Worker         }
2167*f6dc9357SAndroid Build Coastguard Worker         */
2168*f6dc9357SAndroid Build Coastguard Worker       }
2169*f6dc9357SAndroid Build Coastguard Worker       fm.Encrypted = method.PasswordIsDefined;
2170*f6dc9357SAndroid Build Coastguard Worker 
2171*f6dc9357SAndroid Build Coastguard Worker       const unsigned groupIndex = GetGroup(filters, fm);
2172*f6dc9357SAndroid Build Coastguard Worker       while (groupIndex >= groups.Size())
2173*f6dc9357SAndroid Build Coastguard Worker         groups.AddNew();
2174*f6dc9357SAndroid Build Coastguard Worker       groups[groupIndex].Indices.Add(i);
2175*f6dc9357SAndroid Build Coastguard Worker     }
2176*f6dc9357SAndroid Build Coastguard Worker   }
2177*f6dc9357SAndroid Build Coastguard Worker 
2178*f6dc9357SAndroid Build Coastguard Worker 
2179*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_NO_CRYPTO
2180*f6dc9357SAndroid Build Coastguard Worker 
2181*f6dc9357SAndroid Build Coastguard Worker   CCryptoGetTextPassword *getPasswordSpec = NULL;
2182*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ICryptoGetTextPassword> getTextPassword;
2183*f6dc9357SAndroid Build Coastguard Worker   if (needEncryptedRepack)
2184*f6dc9357SAndroid Build Coastguard Worker   {
2185*f6dc9357SAndroid Build Coastguard Worker     getPasswordSpec = new CCryptoGetTextPassword;
2186*f6dc9357SAndroid Build Coastguard Worker     getTextPassword = getPasswordSpec;
2187*f6dc9357SAndroid Build Coastguard Worker 
2188*f6dc9357SAndroid Build Coastguard Worker     #ifndef Z7_ST
2189*f6dc9357SAndroid Build Coastguard Worker     threadDecoder.getTextPassword = getPasswordSpec;
2190*f6dc9357SAndroid Build Coastguard Worker     #endif
2191*f6dc9357SAndroid Build Coastguard Worker 
2192*f6dc9357SAndroid Build Coastguard Worker     if (options.Method->PasswordIsDefined)
2193*f6dc9357SAndroid Build Coastguard Worker       getPasswordSpec->Password = options.Method->Password;
2194*f6dc9357SAndroid Build Coastguard Worker     else
2195*f6dc9357SAndroid Build Coastguard Worker     {
2196*f6dc9357SAndroid Build Coastguard Worker       Z7_DECL_CMyComPtr_QI_FROM(
2197*f6dc9357SAndroid Build Coastguard Worker           ICryptoGetTextPassword,
2198*f6dc9357SAndroid Build Coastguard Worker           getDecoderPassword, updateCallback)
2199*f6dc9357SAndroid Build Coastguard Worker       if (!getDecoderPassword)
2200*f6dc9357SAndroid Build Coastguard Worker         return E_NOTIMPL;
2201*f6dc9357SAndroid Build Coastguard Worker       CMyComBSTR password;
2202*f6dc9357SAndroid Build Coastguard Worker       RINOK(getDecoderPassword->CryptoGetTextPassword(&password))
2203*f6dc9357SAndroid Build Coastguard Worker       if (password)
2204*f6dc9357SAndroid Build Coastguard Worker         getPasswordSpec->Password = password;
2205*f6dc9357SAndroid Build Coastguard Worker     }
2206*f6dc9357SAndroid Build Coastguard Worker   }
2207*f6dc9357SAndroid Build Coastguard Worker 
2208*f6dc9357SAndroid Build Coastguard Worker   #endif
2209*f6dc9357SAndroid Build Coastguard Worker 
2210*f6dc9357SAndroid Build Coastguard Worker   // ---------- Compress ----------
2211*f6dc9357SAndroid Build Coastguard Worker 
2212*f6dc9357SAndroid Build Coastguard Worker   COutArchive archive;
2213*f6dc9357SAndroid Build Coastguard Worker   CArchiveDatabaseOut newDatabase;
2214*f6dc9357SAndroid Build Coastguard Worker 
2215*f6dc9357SAndroid Build Coastguard Worker   RINOK(archive.Create_and_WriteStartPrefix(seqOutStream))
2216*f6dc9357SAndroid Build Coastguard Worker 
2217*f6dc9357SAndroid Build Coastguard Worker   /*
2218*f6dc9357SAndroid Build Coastguard Worker   CIntVector treeFolderToArcIndex;
2219*f6dc9357SAndroid Build Coastguard Worker   treeFolderToArcIndex.Reserve(treeFolders.Size());
2220*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < treeFolders.Size(); i++)
2221*f6dc9357SAndroid Build Coastguard Worker     treeFolderToArcIndex.Add(-1);
2222*f6dc9357SAndroid Build Coastguard Worker   // ---------- Write Tree (only AUX dirs) ----------
2223*f6dc9357SAndroid Build Coastguard Worker   for (i = 1; i < treeFolders.Size(); i++)
2224*f6dc9357SAndroid Build Coastguard Worker   {
2225*f6dc9357SAndroid Build Coastguard Worker     const CTreeFolder &treeFolder = treeFolders[i];
2226*f6dc9357SAndroid Build Coastguard Worker     CFileItem file;
2227*f6dc9357SAndroid Build Coastguard Worker     CFileItem2 file2;
2228*f6dc9357SAndroid Build Coastguard Worker     file2.Init();
2229*f6dc9357SAndroid Build Coastguard Worker     int secureID = 0;
2230*f6dc9357SAndroid Build Coastguard Worker     if (treeFolder.UpdateItemIndex < 0)
2231*f6dc9357SAndroid Build Coastguard Worker     {
2232*f6dc9357SAndroid Build Coastguard Worker       // we can store virtual dir item wuthout attrib, but we want all items have attrib.
2233*f6dc9357SAndroid Build Coastguard Worker       file.SetAttrib(FILE_ATTRIBUTE_DIRECTORY);
2234*f6dc9357SAndroid Build Coastguard Worker       file2.IsAux = true;
2235*f6dc9357SAndroid Build Coastguard Worker     }
2236*f6dc9357SAndroid Build Coastguard Worker     else
2237*f6dc9357SAndroid Build Coastguard Worker     {
2238*f6dc9357SAndroid Build Coastguard Worker       const CUpdateItem &ui = updateItems[treeFolder.UpdateItemIndex];
2239*f6dc9357SAndroid Build Coastguard Worker       // if item is not dir, then it's parent for alt streams.
2240*f6dc9357SAndroid Build Coastguard Worker       // we will write such items later
2241*f6dc9357SAndroid Build Coastguard Worker       if (!ui.IsDir)
2242*f6dc9357SAndroid Build Coastguard Worker         continue;
2243*f6dc9357SAndroid Build Coastguard Worker       secureID = ui.SecureIndex;
2244*f6dc9357SAndroid Build Coastguard Worker       if (ui.NewProps)
2245*f6dc9357SAndroid Build Coastguard Worker         UpdateItem_To_FileItem(ui, file, file2);
2246*f6dc9357SAndroid Build Coastguard Worker       else
2247*f6dc9357SAndroid Build Coastguard Worker         GetFile(*db, ui.IndexInArchive, file, file2);
2248*f6dc9357SAndroid Build Coastguard Worker     }
2249*f6dc9357SAndroid Build Coastguard Worker     file.Size = 0;
2250*f6dc9357SAndroid Build Coastguard Worker     file.HasStream = false;
2251*f6dc9357SAndroid Build Coastguard Worker     file.IsDir = true;
2252*f6dc9357SAndroid Build Coastguard Worker     file.Parent = treeFolder.Parent;
2253*f6dc9357SAndroid Build Coastguard Worker 
2254*f6dc9357SAndroid Build Coastguard Worker     treeFolderToArcIndex[i] = newDatabase.Files.Size();
2255*f6dc9357SAndroid Build Coastguard Worker     newDatabase.AddFile(file, file2, treeFolder.Name);
2256*f6dc9357SAndroid Build Coastguard Worker 
2257*f6dc9357SAndroid Build Coastguard Worker     if (totalSecureDataSize != 0)
2258*f6dc9357SAndroid Build Coastguard Worker       newDatabase.SecureIDs.Add(secureID);
2259*f6dc9357SAndroid Build Coastguard Worker   }
2260*f6dc9357SAndroid Build Coastguard Worker   */
2261*f6dc9357SAndroid Build Coastguard Worker 
2262*f6dc9357SAndroid Build Coastguard Worker   {
2263*f6dc9357SAndroid Build Coastguard Worker     /* ---------- Write non-AUX dirs and Empty files ---------- */
2264*f6dc9357SAndroid Build Coastguard Worker     CUIntVector emptyRefs;
2265*f6dc9357SAndroid Build Coastguard Worker 
2266*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
2267*f6dc9357SAndroid Build Coastguard Worker 
2268*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < updateItems.Size(); i++)
2269*f6dc9357SAndroid Build Coastguard Worker     {
2270*f6dc9357SAndroid Build Coastguard Worker       const CUpdateItem &ui = updateItems[i];
2271*f6dc9357SAndroid Build Coastguard Worker       if (ui.NewData)
2272*f6dc9357SAndroid Build Coastguard Worker       {
2273*f6dc9357SAndroid Build Coastguard Worker         if (ui.HasStream())
2274*f6dc9357SAndroid Build Coastguard Worker           continue;
2275*f6dc9357SAndroid Build Coastguard Worker       }
2276*f6dc9357SAndroid Build Coastguard Worker       else if (ui.IndexInArchive != -1 && db->Files[(unsigned)ui.IndexInArchive].HasStream)
2277*f6dc9357SAndroid Build Coastguard Worker         continue;
2278*f6dc9357SAndroid Build Coastguard Worker       /*
2279*f6dc9357SAndroid Build Coastguard Worker       if (ui.TreeFolderIndex >= 0)
2280*f6dc9357SAndroid Build Coastguard Worker         continue;
2281*f6dc9357SAndroid Build Coastguard Worker       */
2282*f6dc9357SAndroid Build Coastguard Worker       emptyRefs.Add(i);
2283*f6dc9357SAndroid Build Coastguard Worker     }
2284*f6dc9357SAndroid Build Coastguard Worker 
2285*f6dc9357SAndroid Build Coastguard Worker     emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);
2286*f6dc9357SAndroid Build Coastguard Worker 
2287*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < emptyRefs.Size(); i++)
2288*f6dc9357SAndroid Build Coastguard Worker     {
2289*f6dc9357SAndroid Build Coastguard Worker       const CUpdateItem &ui = updateItems[emptyRefs[i]];
2290*f6dc9357SAndroid Build Coastguard Worker       CFileItem file;
2291*f6dc9357SAndroid Build Coastguard Worker       CFileItem2 file2;
2292*f6dc9357SAndroid Build Coastguard Worker       UString name;
2293*f6dc9357SAndroid Build Coastguard Worker       if (ui.NewProps)
2294*f6dc9357SAndroid Build Coastguard Worker       {
2295*f6dc9357SAndroid Build Coastguard Worker         UpdateItem_To_FileItem(ui, file, file2);
2296*f6dc9357SAndroid Build Coastguard Worker         file.CrcDefined = false;
2297*f6dc9357SAndroid Build Coastguard Worker         name = ui.Name;
2298*f6dc9357SAndroid Build Coastguard Worker       }
2299*f6dc9357SAndroid Build Coastguard Worker       else
2300*f6dc9357SAndroid Build Coastguard Worker       {
2301*f6dc9357SAndroid Build Coastguard Worker         GetFile(*db, (unsigned)ui.IndexInArchive, file, file2);
2302*f6dc9357SAndroid Build Coastguard Worker         db->GetPath((unsigned)ui.IndexInArchive, name);
2303*f6dc9357SAndroid Build Coastguard Worker       }
2304*f6dc9357SAndroid Build Coastguard Worker 
2305*f6dc9357SAndroid Build Coastguard Worker       /*
2306*f6dc9357SAndroid Build Coastguard Worker       if (totalSecureDataSize != 0)
2307*f6dc9357SAndroid Build Coastguard Worker         newDatabase.SecureIDs.Add(ui.SecureIndex);
2308*f6dc9357SAndroid Build Coastguard Worker       file.Parent = ui.ParentFolderIndex;
2309*f6dc9357SAndroid Build Coastguard Worker       */
2310*f6dc9357SAndroid Build Coastguard Worker       newDatabase.AddFile(file, file2, name);
2311*f6dc9357SAndroid Build Coastguard Worker     }
2312*f6dc9357SAndroid Build Coastguard Worker   }
2313*f6dc9357SAndroid Build Coastguard Worker 
2314*f6dc9357SAndroid Build Coastguard Worker   lps->ProgressOffset = 0;
2315*f6dc9357SAndroid Build Coastguard Worker 
2316*f6dc9357SAndroid Build Coastguard Worker   {
2317*f6dc9357SAndroid Build Coastguard Worker     // ---------- Sort Filters ----------
2318*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, filters)
2319*f6dc9357SAndroid Build Coastguard Worker     {
2320*f6dc9357SAndroid Build Coastguard Worker       filters[i].GroupIndex = i;
2321*f6dc9357SAndroid Build Coastguard Worker     }
2322*f6dc9357SAndroid Build Coastguard Worker     filters.Sort2();
2323*f6dc9357SAndroid Build Coastguard Worker   }
2324*f6dc9357SAndroid Build Coastguard Worker 
2325*f6dc9357SAndroid Build Coastguard Worker   for (unsigned groupIndex = 0; groupIndex < filters.Size(); groupIndex++)
2326*f6dc9357SAndroid Build Coastguard Worker   {
2327*f6dc9357SAndroid Build Coastguard Worker     const CFilterMode2 &filterMode = filters[groupIndex];
2328*f6dc9357SAndroid Build Coastguard Worker 
2329*f6dc9357SAndroid Build Coastguard Worker     CCompressionMethodMode method = *options.Method;
2330*f6dc9357SAndroid Build Coastguard Worker     {
2331*f6dc9357SAndroid Build Coastguard Worker       const HRESULT res = MakeExeMethod(method, filterMode,
2332*f6dc9357SAndroid Build Coastguard Worker         // bcj2_IsAllowed:
2333*f6dc9357SAndroid Build Coastguard Worker         #ifdef Z7_ST
2334*f6dc9357SAndroid Build Coastguard Worker           false
2335*f6dc9357SAndroid Build Coastguard Worker         #else
2336*f6dc9357SAndroid Build Coastguard Worker           options.MaxFilter && options.MultiThreadMixer
2337*f6dc9357SAndroid Build Coastguard Worker         #endif
2338*f6dc9357SAndroid Build Coastguard Worker         , options.DisabledFilterIDs);
2339*f6dc9357SAndroid Build Coastguard Worker 
2340*f6dc9357SAndroid Build Coastguard Worker       RINOK(res)
2341*f6dc9357SAndroid Build Coastguard Worker     }
2342*f6dc9357SAndroid Build Coastguard Worker 
2343*f6dc9357SAndroid Build Coastguard Worker     if (filterMode.Encrypted)
2344*f6dc9357SAndroid Build Coastguard Worker     {
2345*f6dc9357SAndroid Build Coastguard Worker       if (!method.PasswordIsDefined)
2346*f6dc9357SAndroid Build Coastguard Worker       {
2347*f6dc9357SAndroid Build Coastguard Worker         #ifndef Z7_NO_CRYPTO
2348*f6dc9357SAndroid Build Coastguard Worker         if (getPasswordSpec)
2349*f6dc9357SAndroid Build Coastguard Worker           method.Password = getPasswordSpec->Password;
2350*f6dc9357SAndroid Build Coastguard Worker         #endif
2351*f6dc9357SAndroid Build Coastguard Worker         method.PasswordIsDefined = true;
2352*f6dc9357SAndroid Build Coastguard Worker       }
2353*f6dc9357SAndroid Build Coastguard Worker     }
2354*f6dc9357SAndroid Build Coastguard Worker     else
2355*f6dc9357SAndroid Build Coastguard Worker     {
2356*f6dc9357SAndroid Build Coastguard Worker       method.PasswordIsDefined = false;
2357*f6dc9357SAndroid Build Coastguard Worker       method.Password.Empty();
2358*f6dc9357SAndroid Build Coastguard Worker     }
2359*f6dc9357SAndroid Build Coastguard Worker 
2360*f6dc9357SAndroid Build Coastguard Worker     CEncoder encoder(method);
2361*f6dc9357SAndroid Build Coastguard Worker 
2362*f6dc9357SAndroid Build Coastguard Worker     // ---------- Repack and copy old solid blocks ----------
2363*f6dc9357SAndroid Build Coastguard Worker 
2364*f6dc9357SAndroid Build Coastguard Worker     const CSolidGroup &group = groups[filterMode.GroupIndex];
2365*f6dc9357SAndroid Build Coastguard Worker 
2366*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (folderRefIndex, group.folderRefs)
2367*f6dc9357SAndroid Build Coastguard Worker     {
2368*f6dc9357SAndroid Build Coastguard Worker       const CFolderRepack &rep = group.folderRefs[folderRefIndex];
2369*f6dc9357SAndroid Build Coastguard Worker 
2370*f6dc9357SAndroid Build Coastguard Worker       const unsigned folderIndex = rep.FolderIndex;
2371*f6dc9357SAndroid Build Coastguard Worker 
2372*f6dc9357SAndroid Build Coastguard Worker       const CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
2373*f6dc9357SAndroid Build Coastguard Worker 
2374*f6dc9357SAndroid Build Coastguard Worker       if (rep.NumCopyFiles == numUnpackStreams)
2375*f6dc9357SAndroid Build Coastguard Worker       {
2376*f6dc9357SAndroid Build Coastguard Worker         if (opCallback)
2377*f6dc9357SAndroid Build Coastguard Worker         {
2378*f6dc9357SAndroid Build Coastguard Worker           RINOK(opCallback->ReportOperation(
2379*f6dc9357SAndroid Build Coastguard Worker               NEventIndexType::kBlockIndex, (UInt32)folderIndex,
2380*f6dc9357SAndroid Build Coastguard Worker               NUpdateNotifyOp::kReplicate))
2381*f6dc9357SAndroid Build Coastguard Worker 
2382*f6dc9357SAndroid Build Coastguard Worker           // ---------- Copy old solid block ----------
2383*f6dc9357SAndroid Build Coastguard Worker           {
2384*f6dc9357SAndroid Build Coastguard Worker             CNum indexInFolder = 0;
2385*f6dc9357SAndroid Build Coastguard Worker             for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
2386*f6dc9357SAndroid Build Coastguard Worker             {
2387*f6dc9357SAndroid Build Coastguard Worker               if (db->Files[fi].HasStream)
2388*f6dc9357SAndroid Build Coastguard Worker               {
2389*f6dc9357SAndroid Build Coastguard Worker                 indexInFolder++;
2390*f6dc9357SAndroid Build Coastguard Worker                 RINOK(opCallback->ReportOperation(
2391*f6dc9357SAndroid Build Coastguard Worker                     NEventIndexType::kInArcIndex, (UInt32)fi,
2392*f6dc9357SAndroid Build Coastguard Worker                     NUpdateNotifyOp::kReplicate))
2393*f6dc9357SAndroid Build Coastguard Worker               }
2394*f6dc9357SAndroid Build Coastguard Worker             }
2395*f6dc9357SAndroid Build Coastguard Worker           }
2396*f6dc9357SAndroid Build Coastguard Worker         }
2397*f6dc9357SAndroid Build Coastguard Worker 
2398*f6dc9357SAndroid Build Coastguard Worker         const UInt64 packSize = db->GetFolderFullPackSize(folderIndex);
2399*f6dc9357SAndroid Build Coastguard Worker         RINOK(WriteRange(inStream, archive.SeqStream,
2400*f6dc9357SAndroid Build Coastguard Worker             db->GetFolderStreamPos(folderIndex, 0), packSize, lps))
2401*f6dc9357SAndroid Build Coastguard Worker         lps->ProgressOffset += packSize;
2402*f6dc9357SAndroid Build Coastguard Worker 
2403*f6dc9357SAndroid Build Coastguard Worker         const unsigned folderIndex_New = newDatabase.Folders.Size();
2404*f6dc9357SAndroid Build Coastguard Worker         CFolder &folder = newDatabase.Folders.AddNew();
2405*f6dc9357SAndroid Build Coastguard Worker         // v23.01: we copy FolderCrc, if FolderCrc was used
2406*f6dc9357SAndroid Build Coastguard Worker         if (db->FolderCRCs.ValidAndDefined(folderIndex))
2407*f6dc9357SAndroid Build Coastguard Worker           newDatabase.FolderUnpackCRCs.SetItem(folderIndex_New,
2408*f6dc9357SAndroid Build Coastguard Worker               true, db->FolderCRCs.Vals[folderIndex]);
2409*f6dc9357SAndroid Build Coastguard Worker 
2410*f6dc9357SAndroid Build Coastguard Worker         db->ParseFolderInfo(folderIndex, folder);
2411*f6dc9357SAndroid Build Coastguard Worker         const CNum startIndex = db->FoStartPackStreamIndex[folderIndex];
2412*f6dc9357SAndroid Build Coastguard Worker         FOR_VECTOR (j, folder.PackStreams)
2413*f6dc9357SAndroid Build Coastguard Worker         {
2414*f6dc9357SAndroid Build Coastguard Worker           newDatabase.PackSizes.Add(db->GetStreamPackSize(startIndex + j));
2415*f6dc9357SAndroid Build Coastguard Worker           // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]);
2416*f6dc9357SAndroid Build Coastguard Worker           // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]);
2417*f6dc9357SAndroid Build Coastguard Worker         }
2418*f6dc9357SAndroid Build Coastguard Worker 
2419*f6dc9357SAndroid Build Coastguard Worker         size_t indexStart = db->FoToCoderUnpackSizes[folderIndex];
2420*f6dc9357SAndroid Build Coastguard Worker         const size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1];
2421*f6dc9357SAndroid Build Coastguard Worker         for (; indexStart < indexEnd; indexStart++)
2422*f6dc9357SAndroid Build Coastguard Worker           newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes.ConstData()[indexStart]);
2423*f6dc9357SAndroid Build Coastguard Worker       }
2424*f6dc9357SAndroid Build Coastguard Worker       else
2425*f6dc9357SAndroid Build Coastguard Worker       {
2426*f6dc9357SAndroid Build Coastguard Worker         // ---------- Repack old solid block ----------
2427*f6dc9357SAndroid Build Coastguard Worker 
2428*f6dc9357SAndroid Build Coastguard Worker         CBoolVector extractStatuses;
2429*f6dc9357SAndroid Build Coastguard Worker 
2430*f6dc9357SAndroid Build Coastguard Worker         CNum indexInFolder = 0;
2431*f6dc9357SAndroid Build Coastguard Worker 
2432*f6dc9357SAndroid Build Coastguard Worker         if (opCallback)
2433*f6dc9357SAndroid Build Coastguard Worker         {
2434*f6dc9357SAndroid Build Coastguard Worker           RINOK(opCallback->ReportOperation(
2435*f6dc9357SAndroid Build Coastguard Worker               NEventIndexType::kBlockIndex, (UInt32)folderIndex,
2436*f6dc9357SAndroid Build Coastguard Worker               NUpdateNotifyOp::kRepack))
2437*f6dc9357SAndroid Build Coastguard Worker         }
2438*f6dc9357SAndroid Build Coastguard Worker 
2439*f6dc9357SAndroid Build Coastguard Worker         /* We could reduce data size of decoded folder, if we don't need to repack
2440*f6dc9357SAndroid Build Coastguard Worker            last files in folder. But the gain in speed is small in most cases.
2441*f6dc9357SAndroid Build Coastguard Worker            So we unpack full folder. */
2442*f6dc9357SAndroid Build Coastguard Worker 
2443*f6dc9357SAndroid Build Coastguard Worker         UInt64 sizeToEncode = 0;
2444*f6dc9357SAndroid Build Coastguard Worker 
2445*f6dc9357SAndroid Build Coastguard Worker         /*
2446*f6dc9357SAndroid Build Coastguard Worker         UInt64 importantUnpackSize = 0;
2447*f6dc9357SAndroid Build Coastguard Worker         unsigned numImportantFiles = 0;
2448*f6dc9357SAndroid Build Coastguard Worker         UInt64 decodeSize = 0;
2449*f6dc9357SAndroid Build Coastguard Worker         */
2450*f6dc9357SAndroid Build Coastguard Worker 
2451*f6dc9357SAndroid Build Coastguard Worker         for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
2452*f6dc9357SAndroid Build Coastguard Worker         {
2453*f6dc9357SAndroid Build Coastguard Worker           bool needExtract = false;
2454*f6dc9357SAndroid Build Coastguard Worker           const CFileItem &file = db->Files[fi];
2455*f6dc9357SAndroid Build Coastguard Worker 
2456*f6dc9357SAndroid Build Coastguard Worker           if (file.HasStream)
2457*f6dc9357SAndroid Build Coastguard Worker           {
2458*f6dc9357SAndroid Build Coastguard Worker             indexInFolder++;
2459*f6dc9357SAndroid Build Coastguard Worker             const int updateIndex = fileIndexToUpdateIndexMap[fi];
2460*f6dc9357SAndroid Build Coastguard Worker             if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData)
2461*f6dc9357SAndroid Build Coastguard Worker               needExtract = true;
2462*f6dc9357SAndroid Build Coastguard Worker             // decodeSize += file.Size;
2463*f6dc9357SAndroid Build Coastguard Worker           }
2464*f6dc9357SAndroid Build Coastguard Worker 
2465*f6dc9357SAndroid Build Coastguard Worker           extractStatuses.Add(needExtract);
2466*f6dc9357SAndroid Build Coastguard Worker           if (needExtract)
2467*f6dc9357SAndroid Build Coastguard Worker           {
2468*f6dc9357SAndroid Build Coastguard Worker             sizeToEncode += file.Size;
2469*f6dc9357SAndroid Build Coastguard Worker             /*
2470*f6dc9357SAndroid Build Coastguard Worker             numImportantFiles = extractStatuses.Size();
2471*f6dc9357SAndroid Build Coastguard Worker             importantUnpackSize = decodeSize;
2472*f6dc9357SAndroid Build Coastguard Worker             */
2473*f6dc9357SAndroid Build Coastguard Worker           }
2474*f6dc9357SAndroid Build Coastguard Worker         }
2475*f6dc9357SAndroid Build Coastguard Worker 
2476*f6dc9357SAndroid Build Coastguard Worker         // extractStatuses.DeleteFrom(numImportantFiles);
2477*f6dc9357SAndroid Build Coastguard Worker 
2478*f6dc9357SAndroid Build Coastguard Worker         unsigned startPackIndex = newDatabase.PackSizes.Size();
2479*f6dc9357SAndroid Build Coastguard Worker         UInt64 curUnpackSize;
2480*f6dc9357SAndroid Build Coastguard Worker         {
2481*f6dc9357SAndroid Build Coastguard Worker           CMyComPtr<ISequentialInStream> sbInStream;
2482*f6dc9357SAndroid Build Coastguard Worker           CRepackStreamBase *repackBase;
2483*f6dc9357SAndroid Build Coastguard Worker           CFolderInStream2 *FosSpec2 = NULL;
2484*f6dc9357SAndroid Build Coastguard Worker 
2485*f6dc9357SAndroid Build Coastguard Worker           CRepackInStreamWithSizes *inStreamSizeCountSpec = new CRepackInStreamWithSizes;
2486*f6dc9357SAndroid Build Coastguard Worker           CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
2487*f6dc9357SAndroid Build Coastguard Worker           {
2488*f6dc9357SAndroid Build Coastguard Worker             #ifndef Z7_ST
2489*f6dc9357SAndroid Build Coastguard Worker             if (options.MultiThreadMixer)
2490*f6dc9357SAndroid Build Coastguard Worker             {
2491*f6dc9357SAndroid Build Coastguard Worker               repackBase = threadDecoder.FosSpec;
2492*f6dc9357SAndroid Build Coastguard Worker               CMyComPtr<ISequentialOutStream> sbOutStream;
2493*f6dc9357SAndroid Build Coastguard Worker               sb.CreateStreams2(sbInStream, sbOutStream);
2494*f6dc9357SAndroid Build Coastguard Worker               RINOK(sb.Create_ReInit())
2495*f6dc9357SAndroid Build Coastguard Worker 
2496*f6dc9357SAndroid Build Coastguard Worker               threadDecoder.FosSpec->_stream = sbOutStream;
2497*f6dc9357SAndroid Build Coastguard Worker 
2498*f6dc9357SAndroid Build Coastguard Worker               threadDecoder.InStream = inStream;
2499*f6dc9357SAndroid Build Coastguard Worker               threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0);
2500*f6dc9357SAndroid Build Coastguard Worker               threadDecoder.Folders = (const CFolders *)db;
2501*f6dc9357SAndroid Build Coastguard Worker               threadDecoder.FolderIndex = folderIndex;
2502*f6dc9357SAndroid Build Coastguard Worker 
2503*f6dc9357SAndroid Build Coastguard Worker               // threadDecoder.UnpackSize = importantUnpackSize;
2504*f6dc9357SAndroid Build Coastguard Worker               // threadDecoder.send_UnpackSize = true;
2505*f6dc9357SAndroid Build Coastguard Worker             }
2506*f6dc9357SAndroid Build Coastguard Worker             else
2507*f6dc9357SAndroid Build Coastguard Worker             #endif
2508*f6dc9357SAndroid Build Coastguard Worker             {
2509*f6dc9357SAndroid Build Coastguard Worker               FosSpec2 = new CFolderInStream2;
2510*f6dc9357SAndroid Build Coastguard Worker               FosSpec2->Init();
2511*f6dc9357SAndroid Build Coastguard Worker               sbInStream = FosSpec2;
2512*f6dc9357SAndroid Build Coastguard Worker               repackBase = FosSpec2;
2513*f6dc9357SAndroid Build Coastguard Worker 
2514*f6dc9357SAndroid Build Coastguard Worker               #ifndef Z7_NO_CRYPTO
2515*f6dc9357SAndroid Build Coastguard Worker               bool isEncrypted = false;
2516*f6dc9357SAndroid Build Coastguard Worker               bool passwordIsDefined = false;
2517*f6dc9357SAndroid Build Coastguard Worker               UString password;
2518*f6dc9357SAndroid Build Coastguard Worker               #endif
2519*f6dc9357SAndroid Build Coastguard Worker 
2520*f6dc9357SAndroid Build Coastguard Worker               CMyComPtr<ISequentialInStream> decodedStream;
2521*f6dc9357SAndroid Build Coastguard Worker               bool dataAfterEnd_Error = false;
2522*f6dc9357SAndroid Build Coastguard Worker 
2523*f6dc9357SAndroid Build Coastguard Worker               const HRESULT res = threadDecoder.Decoder.Decode(
2524*f6dc9357SAndroid Build Coastguard Worker                   EXTERNAL_CODECS_LOC_VARS
2525*f6dc9357SAndroid Build Coastguard Worker                   inStream,
2526*f6dc9357SAndroid Build Coastguard Worker                   db->ArcInfo.DataStartPosition, // db->GetFolderStreamPos(folderIndex, 0);,
2527*f6dc9357SAndroid Build Coastguard Worker                   *db, folderIndex,
2528*f6dc9357SAndroid Build Coastguard Worker                   // &importantUnpackSize, // *unpackSize
2529*f6dc9357SAndroid Build Coastguard Worker                   NULL, // *unpackSize : FULL unpack
2530*f6dc9357SAndroid Build Coastguard Worker 
2531*f6dc9357SAndroid Build Coastguard Worker                   NULL, // *outStream
2532*f6dc9357SAndroid Build Coastguard Worker                   NULL, // *compressProgress
2533*f6dc9357SAndroid Build Coastguard Worker 
2534*f6dc9357SAndroid Build Coastguard Worker                   &decodedStream
2535*f6dc9357SAndroid Build Coastguard Worker                   , dataAfterEnd_Error
2536*f6dc9357SAndroid Build Coastguard Worker 
2537*f6dc9357SAndroid Build Coastguard Worker                   Z7_7Z_DECODER_CRYPRO_VARS
2538*f6dc9357SAndroid Build Coastguard Worker                   #ifndef Z7_ST
2539*f6dc9357SAndroid Build Coastguard Worker                     , false // mtMode
2540*f6dc9357SAndroid Build Coastguard Worker                     , 1 // numThreads
2541*f6dc9357SAndroid Build Coastguard Worker                     , 0 // memUsage
2542*f6dc9357SAndroid Build Coastguard Worker                   #endif
2543*f6dc9357SAndroid Build Coastguard Worker                 );
2544*f6dc9357SAndroid Build Coastguard Worker 
2545*f6dc9357SAndroid Build Coastguard Worker               RINOK(res)
2546*f6dc9357SAndroid Build Coastguard Worker               if (!decodedStream)
2547*f6dc9357SAndroid Build Coastguard Worker                 return E_FAIL;
2548*f6dc9357SAndroid Build Coastguard Worker 
2549*f6dc9357SAndroid Build Coastguard Worker               FosSpec2->_inStream = decodedStream;
2550*f6dc9357SAndroid Build Coastguard Worker             }
2551*f6dc9357SAndroid Build Coastguard Worker 
2552*f6dc9357SAndroid Build Coastguard Worker             repackBase->_db = db;
2553*f6dc9357SAndroid Build Coastguard Worker             repackBase->_opCallback = opCallback;
2554*f6dc9357SAndroid Build Coastguard Worker             repackBase->_extractCallback = extractCallback;
2555*f6dc9357SAndroid Build Coastguard Worker 
2556*f6dc9357SAndroid Build Coastguard Worker             UInt32 startIndex = db->FolderStartFileIndex[folderIndex];
2557*f6dc9357SAndroid Build Coastguard Worker             RINOK(repackBase->Init(startIndex, &extractStatuses))
2558*f6dc9357SAndroid Build Coastguard Worker 
2559*f6dc9357SAndroid Build Coastguard Worker             inStreamSizeCountSpec->_db = db;
2560*f6dc9357SAndroid Build Coastguard Worker             inStreamSizeCountSpec->Init(sbInStream, startIndex, &extractStatuses);
2561*f6dc9357SAndroid Build Coastguard Worker 
2562*f6dc9357SAndroid Build Coastguard Worker             #ifndef Z7_ST
2563*f6dc9357SAndroid Build Coastguard Worker             if (options.MultiThreadMixer)
2564*f6dc9357SAndroid Build Coastguard Worker             {
2565*f6dc9357SAndroid Build Coastguard Worker               WRes wres = threadDecoder.Start();
2566*f6dc9357SAndroid Build Coastguard Worker               if (wres != 0)
2567*f6dc9357SAndroid Build Coastguard Worker                 return HRESULT_FROM_WIN32(wres);
2568*f6dc9357SAndroid Build Coastguard Worker             }
2569*f6dc9357SAndroid Build Coastguard Worker             #endif
2570*f6dc9357SAndroid Build Coastguard Worker           }
2571*f6dc9357SAndroid Build Coastguard Worker 
2572*f6dc9357SAndroid Build Coastguard Worker           // curUnpackSize = sizeToEncode;
2573*f6dc9357SAndroid Build Coastguard Worker 
2574*f6dc9357SAndroid Build Coastguard Worker           HRESULT encodeRes = encoder.Encode1(
2575*f6dc9357SAndroid Build Coastguard Worker               EXTERNAL_CODECS_LOC_VARS
2576*f6dc9357SAndroid Build Coastguard Worker               inStreamSizeCount,
2577*f6dc9357SAndroid Build Coastguard Worker               // NULL,
2578*f6dc9357SAndroid Build Coastguard Worker               &inSizeForReduce,
2579*f6dc9357SAndroid Build Coastguard Worker               sizeToEncode, // expectedDataSize
2580*f6dc9357SAndroid Build Coastguard Worker               newDatabase.Folders.AddNew(),
2581*f6dc9357SAndroid Build Coastguard Worker               // newDatabase.CoderUnpackSizes, curUnpackSize,
2582*f6dc9357SAndroid Build Coastguard Worker               archive.SeqStream, newDatabase.PackSizes, lps);
2583*f6dc9357SAndroid Build Coastguard Worker 
2584*f6dc9357SAndroid Build Coastguard Worker           if (encodeRes == k_My_HRESULT_CRC_ERROR)
2585*f6dc9357SAndroid Build Coastguard Worker             return E_FAIL;
2586*f6dc9357SAndroid Build Coastguard Worker 
2587*f6dc9357SAndroid Build Coastguard Worker           curUnpackSize = inStreamSizeCountSpec->GetSize();
2588*f6dc9357SAndroid Build Coastguard Worker 
2589*f6dc9357SAndroid Build Coastguard Worker           if (encodeRes == S_OK)
2590*f6dc9357SAndroid Build Coastguard Worker           {
2591*f6dc9357SAndroid Build Coastguard Worker             encoder.Encode_Post(curUnpackSize, newDatabase.CoderUnpackSizes);
2592*f6dc9357SAndroid Build Coastguard Worker           }
2593*f6dc9357SAndroid Build Coastguard Worker 
2594*f6dc9357SAndroid Build Coastguard Worker           #ifndef Z7_ST
2595*f6dc9357SAndroid Build Coastguard Worker           if (options.MultiThreadMixer)
2596*f6dc9357SAndroid Build Coastguard Worker           {
2597*f6dc9357SAndroid Build Coastguard Worker             // 16.00: hang was fixed : for case if decoding was not finished.
2598*f6dc9357SAndroid Build Coastguard Worker             // We close CBinderInStream and it calls CStreamBinder::CloseRead()
2599*f6dc9357SAndroid Build Coastguard Worker             inStreamSizeCount.Release();
2600*f6dc9357SAndroid Build Coastguard Worker             sbInStream.Release();
2601*f6dc9357SAndroid Build Coastguard Worker 
2602*f6dc9357SAndroid Build Coastguard Worker             {
2603*f6dc9357SAndroid Build Coastguard Worker               const WRes wres = threadDecoder.WaitExecuteFinish();
2604*f6dc9357SAndroid Build Coastguard Worker               if (wres != 0)
2605*f6dc9357SAndroid Build Coastguard Worker                 return HRESULT_FROM_WIN32(wres);
2606*f6dc9357SAndroid Build Coastguard Worker             }
2607*f6dc9357SAndroid Build Coastguard Worker 
2608*f6dc9357SAndroid Build Coastguard Worker             const HRESULT decodeRes = threadDecoder.Result;
2609*f6dc9357SAndroid Build Coastguard Worker             // if (res == k_My_HRESULT_CRC_ERROR)
2610*f6dc9357SAndroid Build Coastguard Worker             if (decodeRes == S_FALSE || threadDecoder.dataAfterEnd_Error)
2611*f6dc9357SAndroid Build Coastguard Worker             {
2612*f6dc9357SAndroid Build Coastguard Worker               if (extractCallback)
2613*f6dc9357SAndroid Build Coastguard Worker               {
2614*f6dc9357SAndroid Build Coastguard Worker                 RINOK(extractCallback->ReportExtractResult(
2615*f6dc9357SAndroid Build Coastguard Worker                     NEventIndexType::kInArcIndex, db->FolderStartFileIndex[folderIndex],
2616*f6dc9357SAndroid Build Coastguard Worker                     // NEventIndexType::kBlockIndex, (UInt32)folderIndex,
2617*f6dc9357SAndroid Build Coastguard Worker                     (decodeRes != S_OK ?
2618*f6dc9357SAndroid Build Coastguard Worker                       NExtract::NOperationResult::kDataError :
2619*f6dc9357SAndroid Build Coastguard Worker                       NExtract::NOperationResult::kDataAfterEnd)))
2620*f6dc9357SAndroid Build Coastguard Worker               }
2621*f6dc9357SAndroid Build Coastguard Worker               if (decodeRes != S_OK)
2622*f6dc9357SAndroid Build Coastguard Worker                 return E_FAIL;
2623*f6dc9357SAndroid Build Coastguard Worker             }
2624*f6dc9357SAndroid Build Coastguard Worker             RINOK(decodeRes)
2625*f6dc9357SAndroid Build Coastguard Worker             if (encodeRes == S_OK)
2626*f6dc9357SAndroid Build Coastguard Worker               if (sb.ProcessedSize != sizeToEncode)
2627*f6dc9357SAndroid Build Coastguard Worker                 encodeRes = E_FAIL;
2628*f6dc9357SAndroid Build Coastguard Worker           }
2629*f6dc9357SAndroid Build Coastguard Worker           else
2630*f6dc9357SAndroid Build Coastguard Worker           #endif
2631*f6dc9357SAndroid Build Coastguard Worker           {
2632*f6dc9357SAndroid Build Coastguard Worker             if (FosSpec2->Result == S_FALSE)
2633*f6dc9357SAndroid Build Coastguard Worker             {
2634*f6dc9357SAndroid Build Coastguard Worker               if (extractCallback)
2635*f6dc9357SAndroid Build Coastguard Worker               {
2636*f6dc9357SAndroid Build Coastguard Worker                 RINOK(extractCallback->ReportExtractResult(
2637*f6dc9357SAndroid Build Coastguard Worker                     NEventIndexType::kBlockIndex, (UInt32)folderIndex,
2638*f6dc9357SAndroid Build Coastguard Worker                     NExtract::NOperationResult::kDataError))
2639*f6dc9357SAndroid Build Coastguard Worker               }
2640*f6dc9357SAndroid Build Coastguard Worker               return E_FAIL;
2641*f6dc9357SAndroid Build Coastguard Worker             }
2642*f6dc9357SAndroid Build Coastguard Worker             RINOK(FosSpec2->Result)
2643*f6dc9357SAndroid Build Coastguard Worker           }
2644*f6dc9357SAndroid Build Coastguard Worker 
2645*f6dc9357SAndroid Build Coastguard Worker           RINOK(encodeRes)
2646*f6dc9357SAndroid Build Coastguard Worker           RINOK(repackBase->CheckFinishedState())
2647*f6dc9357SAndroid Build Coastguard Worker 
2648*f6dc9357SAndroid Build Coastguard Worker           if (curUnpackSize != sizeToEncode)
2649*f6dc9357SAndroid Build Coastguard Worker             return E_FAIL;
2650*f6dc9357SAndroid Build Coastguard Worker         }
2651*f6dc9357SAndroid Build Coastguard Worker 
2652*f6dc9357SAndroid Build Coastguard Worker         for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)
2653*f6dc9357SAndroid Build Coastguard Worker           lps->OutSize += newDatabase.PackSizes[startPackIndex];
2654*f6dc9357SAndroid Build Coastguard Worker         lps->InSize += curUnpackSize;
2655*f6dc9357SAndroid Build Coastguard Worker       }
2656*f6dc9357SAndroid Build Coastguard Worker 
2657*f6dc9357SAndroid Build Coastguard Worker       newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles);
2658*f6dc9357SAndroid Build Coastguard Worker 
2659*f6dc9357SAndroid Build Coastguard Worker       CNum indexInFolder = 0;
2660*f6dc9357SAndroid Build Coastguard Worker       for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
2661*f6dc9357SAndroid Build Coastguard Worker       {
2662*f6dc9357SAndroid Build Coastguard Worker         if (db->Files[fi].HasStream)
2663*f6dc9357SAndroid Build Coastguard Worker         {
2664*f6dc9357SAndroid Build Coastguard Worker           indexInFolder++;
2665*f6dc9357SAndroid Build Coastguard Worker           const int updateIndex = fileIndexToUpdateIndexMap[fi];
2666*f6dc9357SAndroid Build Coastguard Worker           if (updateIndex >= 0)
2667*f6dc9357SAndroid Build Coastguard Worker           {
2668*f6dc9357SAndroid Build Coastguard Worker             const CUpdateItem &ui = updateItems[(unsigned)updateIndex];
2669*f6dc9357SAndroid Build Coastguard Worker             if (ui.NewData)
2670*f6dc9357SAndroid Build Coastguard Worker               continue;
2671*f6dc9357SAndroid Build Coastguard Worker 
2672*f6dc9357SAndroid Build Coastguard Worker             UString name;
2673*f6dc9357SAndroid Build Coastguard Worker             CFileItem file;
2674*f6dc9357SAndroid Build Coastguard Worker             CFileItem2 file2;
2675*f6dc9357SAndroid Build Coastguard Worker             GetFile(*db, fi, file, file2);
2676*f6dc9357SAndroid Build Coastguard Worker 
2677*f6dc9357SAndroid Build Coastguard Worker             if (ui.NewProps)
2678*f6dc9357SAndroid Build Coastguard Worker             {
2679*f6dc9357SAndroid Build Coastguard Worker               UpdateItem_To_FileItem2(ui, file2);
2680*f6dc9357SAndroid Build Coastguard Worker               file.IsDir = ui.IsDir;
2681*f6dc9357SAndroid Build Coastguard Worker               name = ui.Name;
2682*f6dc9357SAndroid Build Coastguard Worker             }
2683*f6dc9357SAndroid Build Coastguard Worker             else
2684*f6dc9357SAndroid Build Coastguard Worker               db->GetPath(fi, name);
2685*f6dc9357SAndroid Build Coastguard Worker 
2686*f6dc9357SAndroid Build Coastguard Worker             /*
2687*f6dc9357SAndroid Build Coastguard Worker             file.Parent = ui.ParentFolderIndex;
2688*f6dc9357SAndroid Build Coastguard Worker             if (ui.TreeFolderIndex >= 0)
2689*f6dc9357SAndroid Build Coastguard Worker               treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size();
2690*f6dc9357SAndroid Build Coastguard Worker             if (totalSecureDataSize != 0)
2691*f6dc9357SAndroid Build Coastguard Worker               newDatabase.SecureIDs.Add(ui.SecureIndex);
2692*f6dc9357SAndroid Build Coastguard Worker             */
2693*f6dc9357SAndroid Build Coastguard Worker             newDatabase.AddFile(file, file2, name);
2694*f6dc9357SAndroid Build Coastguard Worker           }
2695*f6dc9357SAndroid Build Coastguard Worker         }
2696*f6dc9357SAndroid Build Coastguard Worker       }
2697*f6dc9357SAndroid Build Coastguard Worker     }
2698*f6dc9357SAndroid Build Coastguard Worker 
2699*f6dc9357SAndroid Build Coastguard Worker 
2700*f6dc9357SAndroid Build Coastguard Worker     // ---------- Compress files to new solid blocks ----------
2701*f6dc9357SAndroid Build Coastguard Worker 
2702*f6dc9357SAndroid Build Coastguard Worker     const unsigned numFiles = group.Indices.Size();
2703*f6dc9357SAndroid Build Coastguard Worker     if (numFiles == 0)
2704*f6dc9357SAndroid Build Coastguard Worker       continue;
2705*f6dc9357SAndroid Build Coastguard Worker     CRecordVector<CRefItem> refItems;
2706*f6dc9357SAndroid Build Coastguard Worker     refItems.ClearAndSetSize(numFiles);
2707*f6dc9357SAndroid Build Coastguard Worker     // bool sortByType = (options.UseTypeSorting && isSoid); // numSolidFiles > 1
2708*f6dc9357SAndroid Build Coastguard Worker     const bool sortByType = options.UseTypeSorting;
2709*f6dc9357SAndroid Build Coastguard Worker 
2710*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
2711*f6dc9357SAndroid Build Coastguard Worker 
2712*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < numFiles; i++)
2713*f6dc9357SAndroid Build Coastguard Worker       refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType);
2714*f6dc9357SAndroid Build Coastguard Worker 
2715*f6dc9357SAndroid Build Coastguard Worker     CSortParam sortParam;
2716*f6dc9357SAndroid Build Coastguard Worker     // sortParam.TreeFolders = &treeFolders;
2717*f6dc9357SAndroid Build Coastguard Worker     sortParam.SortByType = sortByType;
2718*f6dc9357SAndroid Build Coastguard Worker     refItems.Sort(CompareUpdateItems, (void *)&sortParam);
2719*f6dc9357SAndroid Build Coastguard Worker 
2720*f6dc9357SAndroid Build Coastguard Worker     CObjArray<UInt32> indices(numFiles);
2721*f6dc9357SAndroid Build Coastguard Worker 
2722*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < numFiles; i++)
2723*f6dc9357SAndroid Build Coastguard Worker     {
2724*f6dc9357SAndroid Build Coastguard Worker       const UInt32 index = refItems[i].Index;
2725*f6dc9357SAndroid Build Coastguard Worker       indices[i] = index;
2726*f6dc9357SAndroid Build Coastguard Worker       /*
2727*f6dc9357SAndroid Build Coastguard Worker       const CUpdateItem &ui = updateItems[index];
2728*f6dc9357SAndroid Build Coastguard Worker       CFileItem file;
2729*f6dc9357SAndroid Build Coastguard Worker       if (ui.NewProps)
2730*f6dc9357SAndroid Build Coastguard Worker         UpdateItem_To_FileItem(ui, file);
2731*f6dc9357SAndroid Build Coastguard Worker       else
2732*f6dc9357SAndroid Build Coastguard Worker         file = db.Files[ui.IndexInArchive];
2733*f6dc9357SAndroid Build Coastguard Worker       if (file.IsAnti || file.IsDir)
2734*f6dc9357SAndroid Build Coastguard Worker         return E_FAIL;
2735*f6dc9357SAndroid Build Coastguard Worker       newDatabase.Files.Add(file);
2736*f6dc9357SAndroid Build Coastguard Worker       */
2737*f6dc9357SAndroid Build Coastguard Worker     }
2738*f6dc9357SAndroid Build Coastguard Worker 
2739*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < numFiles;)
2740*f6dc9357SAndroid Build Coastguard Worker     {
2741*f6dc9357SAndroid Build Coastguard Worker       UInt64 totalSize = 0;
2742*f6dc9357SAndroid Build Coastguard Worker       unsigned numSubFiles;
2743*f6dc9357SAndroid Build Coastguard Worker 
2744*f6dc9357SAndroid Build Coastguard Worker       const wchar_t *prevExtension = NULL;
2745*f6dc9357SAndroid Build Coastguard Worker 
2746*f6dc9357SAndroid Build Coastguard Worker       for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++)
2747*f6dc9357SAndroid Build Coastguard Worker       {
2748*f6dc9357SAndroid Build Coastguard Worker         const CUpdateItem &ui = updateItems[indices[i + numSubFiles]];
2749*f6dc9357SAndroid Build Coastguard Worker         totalSize += ui.Size;
2750*f6dc9357SAndroid Build Coastguard Worker         if (totalSize > options.NumSolidBytes)
2751*f6dc9357SAndroid Build Coastguard Worker           break;
2752*f6dc9357SAndroid Build Coastguard Worker         if (options.SolidExtension)
2753*f6dc9357SAndroid Build Coastguard Worker         {
2754*f6dc9357SAndroid Build Coastguard Worker           const int slashPos = ui.Name.ReverseFind_PathSepar();
2755*f6dc9357SAndroid Build Coastguard Worker           const int dotPos = ui.Name.ReverseFind_Dot();
2756*f6dc9357SAndroid Build Coastguard Worker           const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : (unsigned)(dotPos + 1));
2757*f6dc9357SAndroid Build Coastguard Worker           if (numSubFiles == 0)
2758*f6dc9357SAndroid Build Coastguard Worker             prevExtension = ext;
2759*f6dc9357SAndroid Build Coastguard Worker           else if (!StringsAreEqualNoCase(ext, prevExtension))
2760*f6dc9357SAndroid Build Coastguard Worker             break;
2761*f6dc9357SAndroid Build Coastguard Worker         }
2762*f6dc9357SAndroid Build Coastguard Worker       }
2763*f6dc9357SAndroid Build Coastguard Worker 
2764*f6dc9357SAndroid Build Coastguard Worker       if (numSubFiles < 1)
2765*f6dc9357SAndroid Build Coastguard Worker         numSubFiles = 1;
2766*f6dc9357SAndroid Build Coastguard Worker 
2767*f6dc9357SAndroid Build Coastguard Worker       RINOK(lps->SetCur())
2768*f6dc9357SAndroid Build Coastguard Worker 
2769*f6dc9357SAndroid Build Coastguard Worker       /*
2770*f6dc9357SAndroid Build Coastguard Worker       const unsigned folderIndex = newDatabase.NumUnpackStreamsVector.Size();
2771*f6dc9357SAndroid Build Coastguard Worker 
2772*f6dc9357SAndroid Build Coastguard Worker       if (opCallback)
2773*f6dc9357SAndroid Build Coastguard Worker       {
2774*f6dc9357SAndroid Build Coastguard Worker         RINOK(opCallback->ReportOperation(
2775*f6dc9357SAndroid Build Coastguard Worker             NEventIndexType::kBlockIndex, (UInt32)folderIndex,
2776*f6dc9357SAndroid Build Coastguard Worker             NUpdateNotifyOp::kAdd));
2777*f6dc9357SAndroid Build Coastguard Worker       }
2778*f6dc9357SAndroid Build Coastguard Worker       */
2779*f6dc9357SAndroid Build Coastguard Worker 
2780*f6dc9357SAndroid Build Coastguard Worker 
2781*f6dc9357SAndroid Build Coastguard Worker       CMyComPtr2_Create<ISequentialInStream, CFolderInStream> inStreamSpec; // solidInStream;
2782*f6dc9357SAndroid Build Coastguard Worker 
2783*f6dc9357SAndroid Build Coastguard Worker       // inStreamSpec->_reportArcProp = reportArcProp;
2784*f6dc9357SAndroid Build Coastguard Worker 
2785*f6dc9357SAndroid Build Coastguard Worker       inStreamSpec->Need_CTime = options.Need_CTime;
2786*f6dc9357SAndroid Build Coastguard Worker       inStreamSpec->Need_ATime = options.Need_ATime;
2787*f6dc9357SAndroid Build Coastguard Worker       inStreamSpec->Need_MTime = options.Need_MTime;
2788*f6dc9357SAndroid Build Coastguard Worker       inStreamSpec->Need_Attrib = options.Need_Attrib;
2789*f6dc9357SAndroid Build Coastguard Worker       // inStreamSpec->Need_Crc = options.Need_Crc;
2790*f6dc9357SAndroid Build Coastguard Worker 
2791*f6dc9357SAndroid Build Coastguard Worker       inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);
2792*f6dc9357SAndroid Build Coastguard Worker 
2793*f6dc9357SAndroid Build Coastguard Worker       unsigned startPackIndex = newDatabase.PackSizes.Size();
2794*f6dc9357SAndroid Build Coastguard Worker       // UInt64 curFolderUnpackSize = totalSize;
2795*f6dc9357SAndroid Build Coastguard Worker       // curFolderUnpackSize = (UInt64)(Int64)-1; // for debug
2796*f6dc9357SAndroid Build Coastguard Worker       const UInt64 expectedDataSize = totalSize;
2797*f6dc9357SAndroid Build Coastguard Worker 
2798*f6dc9357SAndroid Build Coastguard Worker       // const unsigned folderIndex_New = newDatabase.Folders.Size();
2799*f6dc9357SAndroid Build Coastguard Worker 
2800*f6dc9357SAndroid Build Coastguard Worker       RINOK(encoder.Encode1(
2801*f6dc9357SAndroid Build Coastguard Worker           EXTERNAL_CODECS_LOC_VARS
2802*f6dc9357SAndroid Build Coastguard Worker           inStreamSpec,
2803*f6dc9357SAndroid Build Coastguard Worker           // NULL,
2804*f6dc9357SAndroid Build Coastguard Worker           &inSizeForReduce,
2805*f6dc9357SAndroid Build Coastguard Worker           expectedDataSize, // expected size
2806*f6dc9357SAndroid Build Coastguard Worker           newDatabase.Folders.AddNew(),
2807*f6dc9357SAndroid Build Coastguard Worker           // newDatabase.CoderUnpackSizes, curFolderUnpackSize,
2808*f6dc9357SAndroid Build Coastguard Worker           archive.SeqStream, newDatabase.PackSizes, lps))
2809*f6dc9357SAndroid Build Coastguard Worker 
2810*f6dc9357SAndroid Build Coastguard Worker       if (!inStreamSpec->WasFinished())
2811*f6dc9357SAndroid Build Coastguard Worker         return E_FAIL;
2812*f6dc9357SAndroid Build Coastguard Worker 
2813*f6dc9357SAndroid Build Coastguard Worker       /*
2814*f6dc9357SAndroid Build Coastguard Worker       if (inStreamSpec->Need_FolderCrc)
2815*f6dc9357SAndroid Build Coastguard Worker         newDatabase.FolderUnpackCRCs.SetItem(folderIndex_New,
2816*f6dc9357SAndroid Build Coastguard Worker             true, inStreamSpec->GetFolderCrc());
2817*f6dc9357SAndroid Build Coastguard Worker       */
2818*f6dc9357SAndroid Build Coastguard Worker 
2819*f6dc9357SAndroid Build Coastguard Worker       const UInt64 curFolderUnpackSize = inStreamSpec->Get_TotalSize_for_Coder();
2820*f6dc9357SAndroid Build Coastguard Worker       encoder.Encode_Post(curFolderUnpackSize, newDatabase.CoderUnpackSizes);
2821*f6dc9357SAndroid Build Coastguard Worker 
2822*f6dc9357SAndroid Build Coastguard Worker       UInt64 packSize = 0;
2823*f6dc9357SAndroid Build Coastguard Worker       // const UInt32 numStreams = newDatabase.PackSizes.Size() - startPackIndex;
2824*f6dc9357SAndroid Build Coastguard Worker       for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)
2825*f6dc9357SAndroid Build Coastguard Worker         packSize += newDatabase.PackSizes[startPackIndex];
2826*f6dc9357SAndroid Build Coastguard Worker       lps->OutSize += packSize;
2827*f6dc9357SAndroid Build Coastguard Worker 
2828*f6dc9357SAndroid Build Coastguard Worker       // for ()
2829*f6dc9357SAndroid Build Coastguard Worker       // newDatabase.PackCRCsDefined.Add(false);
2830*f6dc9357SAndroid Build Coastguard Worker       // newDatabase.PackCRCs.Add(0);
2831*f6dc9357SAndroid Build Coastguard Worker 
2832*f6dc9357SAndroid Build Coastguard Worker       CNum numUnpackStreams = 0;
2833*f6dc9357SAndroid Build Coastguard Worker       UInt64 skippedSize = 0;
2834*f6dc9357SAndroid Build Coastguard Worker       UInt64 procSize = 0;
2835*f6dc9357SAndroid Build Coastguard Worker       // unsigned numProcessedFiles = 0;
2836*f6dc9357SAndroid Build Coastguard Worker 
2837*f6dc9357SAndroid Build Coastguard Worker       for (unsigned subIndex = 0; subIndex < numSubFiles; subIndex++)
2838*f6dc9357SAndroid Build Coastguard Worker       {
2839*f6dc9357SAndroid Build Coastguard Worker         const CUpdateItem &ui = updateItems[indices[i + subIndex]];
2840*f6dc9357SAndroid Build Coastguard Worker         CFileItem file;
2841*f6dc9357SAndroid Build Coastguard Worker         CFileItem2 file2;
2842*f6dc9357SAndroid Build Coastguard Worker         UString name;
2843*f6dc9357SAndroid Build Coastguard Worker         if (ui.NewProps)
2844*f6dc9357SAndroid Build Coastguard Worker         {
2845*f6dc9357SAndroid Build Coastguard Worker           UpdateItem_To_FileItem(ui, file, file2);
2846*f6dc9357SAndroid Build Coastguard Worker           name = ui.Name;
2847*f6dc9357SAndroid Build Coastguard Worker         }
2848*f6dc9357SAndroid Build Coastguard Worker         else
2849*f6dc9357SAndroid Build Coastguard Worker         {
2850*f6dc9357SAndroid Build Coastguard Worker           GetFile(*db, (unsigned)ui.IndexInArchive, file, file2);
2851*f6dc9357SAndroid Build Coastguard Worker           db->GetPath((unsigned)ui.IndexInArchive, name);
2852*f6dc9357SAndroid Build Coastguard Worker         }
2853*f6dc9357SAndroid Build Coastguard Worker         if (file2.IsAnti || file.IsDir)
2854*f6dc9357SAndroid Build Coastguard Worker           return E_FAIL;
2855*f6dc9357SAndroid Build Coastguard Worker 
2856*f6dc9357SAndroid Build Coastguard Worker         /*
2857*f6dc9357SAndroid Build Coastguard Worker         CFileItem &file = newDatabase.Files[
2858*f6dc9357SAndroid Build Coastguard Worker               startFileIndexInDatabase + i + subIndex];
2859*f6dc9357SAndroid Build Coastguard Worker         */
2860*f6dc9357SAndroid Build Coastguard Worker         if (!inStreamSpec->Processed[subIndex])
2861*f6dc9357SAndroid Build Coastguard Worker         {
2862*f6dc9357SAndroid Build Coastguard Worker           // we don't add file here
2863*f6dc9357SAndroid Build Coastguard Worker           skippedSize += ui.Size;
2864*f6dc9357SAndroid Build Coastguard Worker           continue; // comment it for debug
2865*f6dc9357SAndroid Build Coastguard Worker           // name += ".locked"; // for debug
2866*f6dc9357SAndroid Build Coastguard Worker         }
2867*f6dc9357SAndroid Build Coastguard Worker 
2868*f6dc9357SAndroid Build Coastguard Worker         // if (inStreamSpec->Need_Crc)
2869*f6dc9357SAndroid Build Coastguard Worker         file.Crc = inStreamSpec->CRCs[subIndex];
2870*f6dc9357SAndroid Build Coastguard Worker         file.Size = inStreamSpec->Sizes[subIndex];
2871*f6dc9357SAndroid Build Coastguard Worker 
2872*f6dc9357SAndroid Build Coastguard Worker         procSize += file.Size;
2873*f6dc9357SAndroid Build Coastguard Worker         // if (file.Size >= 0) // for debug: test purposes
2874*f6dc9357SAndroid Build Coastguard Worker         if (file.Size != 0)
2875*f6dc9357SAndroid Build Coastguard Worker         {
2876*f6dc9357SAndroid Build Coastguard Worker           file.CrcDefined = true; // inStreamSpec->Need_Crc;
2877*f6dc9357SAndroid Build Coastguard Worker           file.HasStream = true;
2878*f6dc9357SAndroid Build Coastguard Worker           numUnpackStreams++;
2879*f6dc9357SAndroid Build Coastguard Worker         }
2880*f6dc9357SAndroid Build Coastguard Worker         else
2881*f6dc9357SAndroid Build Coastguard Worker         {
2882*f6dc9357SAndroid Build Coastguard Worker           file.CrcDefined = false;
2883*f6dc9357SAndroid Build Coastguard Worker           file.HasStream = false;
2884*f6dc9357SAndroid Build Coastguard Worker         }
2885*f6dc9357SAndroid Build Coastguard Worker 
2886*f6dc9357SAndroid Build Coastguard Worker         if (inStreamSpec->TimesDefined[subIndex])
2887*f6dc9357SAndroid Build Coastguard Worker         {
2888*f6dc9357SAndroid Build Coastguard Worker           if (inStreamSpec->Need_CTime)
2889*f6dc9357SAndroid Build Coastguard Worker             { file2.CTimeDefined = true;  file2.CTime = inStreamSpec->CTimes[subIndex]; }
2890*f6dc9357SAndroid Build Coastguard Worker           if (inStreamSpec->Need_ATime
2891*f6dc9357SAndroid Build Coastguard Worker               // && !ui.ATime_WasReadByAnalysis
2892*f6dc9357SAndroid Build Coastguard Worker               )
2893*f6dc9357SAndroid Build Coastguard Worker             { file2.ATimeDefined = true;  file2.ATime = inStreamSpec->ATimes[subIndex]; }
2894*f6dc9357SAndroid Build Coastguard Worker           if (inStreamSpec->Need_MTime)
2895*f6dc9357SAndroid Build Coastguard Worker             { file2.MTimeDefined = true;  file2.MTime = inStreamSpec->MTimes[subIndex]; }
2896*f6dc9357SAndroid Build Coastguard Worker           if (inStreamSpec->Need_Attrib)
2897*f6dc9357SAndroid Build Coastguard Worker           {
2898*f6dc9357SAndroid Build Coastguard Worker             file2.AttribDefined = true;
2899*f6dc9357SAndroid Build Coastguard Worker             file2.Attrib = inStreamSpec->Attribs[subIndex];
2900*f6dc9357SAndroid Build Coastguard Worker           }
2901*f6dc9357SAndroid Build Coastguard Worker         }
2902*f6dc9357SAndroid Build Coastguard Worker 
2903*f6dc9357SAndroid Build Coastguard Worker         /*
2904*f6dc9357SAndroid Build Coastguard Worker         file.Parent = ui.ParentFolderIndex;
2905*f6dc9357SAndroid Build Coastguard Worker         if (ui.TreeFolderIndex >= 0)
2906*f6dc9357SAndroid Build Coastguard Worker           treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size();
2907*f6dc9357SAndroid Build Coastguard Worker         if (totalSecureDataSize != 0)
2908*f6dc9357SAndroid Build Coastguard Worker           newDatabase.SecureIDs.Add(ui.SecureIndex);
2909*f6dc9357SAndroid Build Coastguard Worker         */
2910*f6dc9357SAndroid Build Coastguard Worker         /*
2911*f6dc9357SAndroid Build Coastguard Worker         if (reportArcProp)
2912*f6dc9357SAndroid Build Coastguard Worker         {
2913*f6dc9357SAndroid Build Coastguard Worker           RINOK(ReportItemProps(reportArcProp, ui.IndexInClient, file.Size,
2914*f6dc9357SAndroid Build Coastguard Worker               file.CrcDefined ? &file.Crc : NULL))
2915*f6dc9357SAndroid Build Coastguard Worker         }
2916*f6dc9357SAndroid Build Coastguard Worker         */
2917*f6dc9357SAndroid Build Coastguard Worker 
2918*f6dc9357SAndroid Build Coastguard Worker         // numProcessedFiles++;
2919*f6dc9357SAndroid Build Coastguard Worker         newDatabase.AddFile(file, file2, name);
2920*f6dc9357SAndroid Build Coastguard Worker       }
2921*f6dc9357SAndroid Build Coastguard Worker 
2922*f6dc9357SAndroid Build Coastguard Worker       /*
2923*f6dc9357SAndroid Build Coastguard Worker       // for debug:
2924*f6dc9357SAndroid Build Coastguard Worker       // we can write crc to folders area, if folder contains only one file
2925*f6dc9357SAndroid Build Coastguard Worker       if (numUnpackStreams == 1 && numSubFiles == 1)
2926*f6dc9357SAndroid Build Coastguard Worker       {
2927*f6dc9357SAndroid Build Coastguard Worker         const CFileItem &file = newDatabase.Files.Back();
2928*f6dc9357SAndroid Build Coastguard Worker         if (file.CrcDefined)
2929*f6dc9357SAndroid Build Coastguard Worker           newDatabase.FolderUnpackCRCs.SetItem(folderIndex_New, true, file.Crc);
2930*f6dc9357SAndroid Build Coastguard Worker       }
2931*f6dc9357SAndroid Build Coastguard Worker       */
2932*f6dc9357SAndroid Build Coastguard Worker 
2933*f6dc9357SAndroid Build Coastguard Worker       /*
2934*f6dc9357SAndroid Build Coastguard Worker       // it's optional check to ensure that sizes are correct
2935*f6dc9357SAndroid Build Coastguard Worker       if (inStreamSpec->TotalSize_for_Coder != curFolderUnpackSize)
2936*f6dc9357SAndroid Build Coastguard Worker         return E_FAIL;
2937*f6dc9357SAndroid Build Coastguard Worker       */
2938*f6dc9357SAndroid Build Coastguard Worker       // if (inStreamSpec->AlignLog == 0)
2939*f6dc9357SAndroid Build Coastguard Worker       {
2940*f6dc9357SAndroid Build Coastguard Worker         if (procSize != curFolderUnpackSize)
2941*f6dc9357SAndroid Build Coastguard Worker           return E_FAIL;
2942*f6dc9357SAndroid Build Coastguard Worker       }
2943*f6dc9357SAndroid Build Coastguard Worker       // else
2944*f6dc9357SAndroid Build Coastguard Worker       {
2945*f6dc9357SAndroid Build Coastguard Worker         /*
2946*f6dc9357SAndroid Build Coastguard Worker         {
2947*f6dc9357SAndroid Build Coastguard Worker           const CFolder &old = newDatabase.Folders.Back();
2948*f6dc9357SAndroid Build Coastguard Worker           CFolder &folder = newDatabase.Folders.AddNew();
2949*f6dc9357SAndroid Build Coastguard Worker           {
2950*f6dc9357SAndroid Build Coastguard Worker             const unsigned numBonds = old.Bonds.Size();
2951*f6dc9357SAndroid Build Coastguard Worker             folder.Bonds.SetSize(numBonds + 1);
2952*f6dc9357SAndroid Build Coastguard Worker             for (unsigned k = 0; k < numBonds; k++)
2953*f6dc9357SAndroid Build Coastguard Worker               folder.Bonds[k] = old.Bonds[k];
2954*f6dc9357SAndroid Build Coastguard Worker             CBond &bond = folder.Bonds[numBonds];
2955*f6dc9357SAndroid Build Coastguard Worker             bond.PackIndex = 0;
2956*f6dc9357SAndroid Build Coastguard Worker             bond.UnpackIndex = 0;
2957*f6dc9357SAndroid Build Coastguard Worker           }
2958*f6dc9357SAndroid Build Coastguard Worker           {
2959*f6dc9357SAndroid Build Coastguard Worker             const unsigned numCoders = old.Coders.Size();
2960*f6dc9357SAndroid Build Coastguard Worker             folder.Coders.SetSize(numCoders + 1);
2961*f6dc9357SAndroid Build Coastguard Worker             for (unsigned k = 0; k < numCoders; k++)
2962*f6dc9357SAndroid Build Coastguard Worker               folder.Coders[k] = old.Coders[k];
2963*f6dc9357SAndroid Build Coastguard Worker             CCoderInfo &cod = folder.Coders[numCoders];
2964*f6dc9357SAndroid Build Coastguard Worker             cod.Props.Alloc(1);
2965*f6dc9357SAndroid Build Coastguard Worker             cod.Props[0] = (Byte)inStreamSpec->AlignLog;
2966*f6dc9357SAndroid Build Coastguard Worker             cod.NumStreams = 1;
2967*f6dc9357SAndroid Build Coastguard Worker           }
2968*f6dc9357SAndroid Build Coastguard Worker           {
2969*f6dc9357SAndroid Build Coastguard Worker             const unsigned numPackStreams = old.Coders.Size();
2970*f6dc9357SAndroid Build Coastguard Worker             folder.Coders.SetSize(numPackStreams);
2971*f6dc9357SAndroid Build Coastguard Worker             for (unsigned k = 0; k < numPackStreams; k++)
2972*f6dc9357SAndroid Build Coastguard Worker               folder.PackStreams[k] = old.PackStreams[k];
2973*f6dc9357SAndroid Build Coastguard Worker           }
2974*f6dc9357SAndroid Build Coastguard Worker         }
2975*f6dc9357SAndroid Build Coastguard Worker         newDatabase.Folders.Delete(newDatabase.Folders.Size() - 2);
2976*f6dc9357SAndroid Build Coastguard Worker         */
2977*f6dc9357SAndroid Build Coastguard Worker       }
2978*f6dc9357SAndroid Build Coastguard Worker 
2979*f6dc9357SAndroid Build Coastguard Worker 
2980*f6dc9357SAndroid Build Coastguard Worker       lps->InSize += procSize;
2981*f6dc9357SAndroid Build Coastguard Worker       // lps->InSize += curFolderUnpackSize;
2982*f6dc9357SAndroid Build Coastguard Worker 
2983*f6dc9357SAndroid Build Coastguard Worker       // numUnpackStreams = 0 is very bad case for locked files
2984*f6dc9357SAndroid Build Coastguard Worker       // v3.13 doesn't understand it.
2985*f6dc9357SAndroid Build Coastguard Worker       newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams);
2986*f6dc9357SAndroid Build Coastguard Worker       i += numSubFiles;
2987*f6dc9357SAndroid Build Coastguard Worker 
2988*f6dc9357SAndroid Build Coastguard Worker       if (skippedSize != 0 && complexity >= skippedSize)
2989*f6dc9357SAndroid Build Coastguard Worker       {
2990*f6dc9357SAndroid Build Coastguard Worker         complexity -= skippedSize;
2991*f6dc9357SAndroid Build Coastguard Worker         RINOK(updateCallback->SetTotal(complexity))
2992*f6dc9357SAndroid Build Coastguard Worker       }
2993*f6dc9357SAndroid Build Coastguard Worker 
2994*f6dc9357SAndroid Build Coastguard Worker       /*
2995*f6dc9357SAndroid Build Coastguard Worker       if (reportArcProp)
2996*f6dc9357SAndroid Build Coastguard Worker       {
2997*f6dc9357SAndroid Build Coastguard Worker         PROPVARIANT prop;
2998*f6dc9357SAndroid Build Coastguard Worker         prop.vt = VT_EMPTY;
2999*f6dc9357SAndroid Build Coastguard Worker         prop.wReserved1 = 0;
3000*f6dc9357SAndroid Build Coastguard Worker         {
3001*f6dc9357SAndroid Build Coastguard Worker           NWindows::NCOM::PropVarEm_Set_UInt32(&prop, numProcessedFiles);
3002*f6dc9357SAndroid Build Coastguard Worker           RINOK(reportArcProp->ReportProp(
3003*f6dc9357SAndroid Build Coastguard Worker               NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidNumSubFiles, &prop));
3004*f6dc9357SAndroid Build Coastguard Worker         }
3005*f6dc9357SAndroid Build Coastguard Worker         {
3006*f6dc9357SAndroid Build Coastguard Worker           NWindows::NCOM::PropVarEm_Set_UInt64(&prop, curFolderUnpackSize);
3007*f6dc9357SAndroid Build Coastguard Worker           RINOK(reportArcProp->ReportProp(
3008*f6dc9357SAndroid Build Coastguard Worker               NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidSize, &prop));
3009*f6dc9357SAndroid Build Coastguard Worker         }
3010*f6dc9357SAndroid Build Coastguard Worker         {
3011*f6dc9357SAndroid Build Coastguard Worker           NWindows::NCOM::PropVarEm_Set_UInt64(&prop, packSize);
3012*f6dc9357SAndroid Build Coastguard Worker           RINOK(reportArcProp->ReportProp(
3013*f6dc9357SAndroid Build Coastguard Worker               NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidPackSize, &prop));
3014*f6dc9357SAndroid Build Coastguard Worker         }
3015*f6dc9357SAndroid Build Coastguard Worker         {
3016*f6dc9357SAndroid Build Coastguard Worker           NWindows::NCOM::PropVarEm_Set_UInt32(&prop, numStreams);
3017*f6dc9357SAndroid Build Coastguard Worker           RINOK(reportArcProp->ReportProp(
3018*f6dc9357SAndroid Build Coastguard Worker               NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidNumStreams, &prop));
3019*f6dc9357SAndroid Build Coastguard Worker         }
3020*f6dc9357SAndroid Build Coastguard Worker         RINOK(reportArcProp->ReportFinished(NEventIndexType::kBlockIndex, (UInt32)folderIndex, NUpdate::NOperationResult::kOK));
3021*f6dc9357SAndroid Build Coastguard Worker       }
3022*f6dc9357SAndroid Build Coastguard Worker       */
3023*f6dc9357SAndroid Build Coastguard Worker       /*
3024*f6dc9357SAndroid Build Coastguard Worker       if (opCallback)
3025*f6dc9357SAndroid Build Coastguard Worker       {
3026*f6dc9357SAndroid Build Coastguard Worker         RINOK(opCallback->ReportOperation(
3027*f6dc9357SAndroid Build Coastguard Worker             NEventIndexType::kBlockIndex, (UInt32)folderIndex,
3028*f6dc9357SAndroid Build Coastguard Worker             NUpdateNotifyOp::kOpFinished));
3029*f6dc9357SAndroid Build Coastguard Worker       }
3030*f6dc9357SAndroid Build Coastguard Worker       */
3031*f6dc9357SAndroid Build Coastguard Worker     }
3032*f6dc9357SAndroid Build Coastguard Worker   }
3033*f6dc9357SAndroid Build Coastguard Worker 
3034*f6dc9357SAndroid Build Coastguard Worker   RINOK(lps->SetCur())
3035*f6dc9357SAndroid Build Coastguard Worker 
3036*f6dc9357SAndroid Build Coastguard Worker   /*
3037*f6dc9357SAndroid Build Coastguard Worker   fileIndexToUpdateIndexMap.ClearAndFree();
3038*f6dc9357SAndroid Build Coastguard Worker   groups.ClearAndFree();
3039*f6dc9357SAndroid Build Coastguard Worker   */
3040*f6dc9357SAndroid Build Coastguard Worker 
3041*f6dc9357SAndroid Build Coastguard Worker   /*
3042*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < newDatabase.Files.Size(); i++)
3043*f6dc9357SAndroid Build Coastguard Worker   {
3044*f6dc9357SAndroid Build Coastguard Worker     CFileItem &file = newDatabase.Files[i];
3045*f6dc9357SAndroid Build Coastguard Worker     file.Parent = treeFolderToArcIndex[file.Parent];
3046*f6dc9357SAndroid Build Coastguard Worker   }
3047*f6dc9357SAndroid Build Coastguard Worker 
3048*f6dc9357SAndroid Build Coastguard Worker   if (totalSecureDataSize != 0)
3049*f6dc9357SAndroid Build Coastguard Worker   {
3050*f6dc9357SAndroid Build Coastguard Worker     newDatabase.SecureBuf.SetCapacity(totalSecureDataSize);
3051*f6dc9357SAndroid Build Coastguard Worker     size_t pos = 0;
3052*f6dc9357SAndroid Build Coastguard Worker     newDatabase.SecureSizes.Reserve(secureBlocks.Sorted.Size());
3053*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < secureBlocks.Sorted.Size(); i++)
3054*f6dc9357SAndroid Build Coastguard Worker     {
3055*f6dc9357SAndroid Build Coastguard Worker       const CByteBuffer &buf = secureBlocks.Bufs[secureBlocks.Sorted[i]];
3056*f6dc9357SAndroid Build Coastguard Worker       size_t size = buf.GetCapacity();
3057*f6dc9357SAndroid Build Coastguard Worker       if (size != 0)
3058*f6dc9357SAndroid Build Coastguard Worker         memcpy(newDatabase.SecureBuf + pos, buf, size);
3059*f6dc9357SAndroid Build Coastguard Worker       newDatabase.SecureSizes.Add((UInt32)size);
3060*f6dc9357SAndroid Build Coastguard Worker       pos += size;
3061*f6dc9357SAndroid Build Coastguard Worker     }
3062*f6dc9357SAndroid Build Coastguard Worker   }
3063*f6dc9357SAndroid Build Coastguard Worker   */
3064*f6dc9357SAndroid Build Coastguard Worker 
3065*f6dc9357SAndroid Build Coastguard Worker   {
3066*f6dc9357SAndroid Build Coastguard Worker     const unsigned numFolders = newDatabase.Folders.Size();
3067*f6dc9357SAndroid Build Coastguard Worker     if (newDatabase.NumUnpackStreamsVector.Size() != numFolders
3068*f6dc9357SAndroid Build Coastguard Worker         || newDatabase.FolderUnpackCRCs.Defs.Size() > numFolders)
3069*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
3070*f6dc9357SAndroid Build Coastguard Worker     newDatabase.FolderUnpackCRCs.if_NonEmpty_FillResidue_with_false(numFolders);
3071*f6dc9357SAndroid Build Coastguard Worker   }
3072*f6dc9357SAndroid Build Coastguard Worker 
3073*f6dc9357SAndroid Build Coastguard Worker   updateItems.ClearAndFree();
3074*f6dc9357SAndroid Build Coastguard Worker   newDatabase.ReserveDown();
3075*f6dc9357SAndroid Build Coastguard Worker 
3076*f6dc9357SAndroid Build Coastguard Worker   if (opCallback)
3077*f6dc9357SAndroid Build Coastguard Worker     RINOK(opCallback->ReportOperation(NEventIndexType::kNoIndex, (UInt32)(Int32)-1, NUpdateNotifyOp::kHeader))
3078*f6dc9357SAndroid Build Coastguard Worker 
3079*f6dc9357SAndroid Build Coastguard Worker   RINOK(archive.WriteDatabase(EXTERNAL_CODECS_LOC_VARS
3080*f6dc9357SAndroid Build Coastguard Worker       newDatabase, options.HeaderMethod, options.HeaderOptions))
3081*f6dc9357SAndroid Build Coastguard Worker 
3082*f6dc9357SAndroid Build Coastguard Worker   if (v_StreamSetRestriction)
3083*f6dc9357SAndroid Build Coastguard Worker     RINOK(v_StreamSetRestriction->SetRestriction(0, 0))
3084*f6dc9357SAndroid Build Coastguard Worker 
3085*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
3086*f6dc9357SAndroid Build Coastguard Worker }
3087*f6dc9357SAndroid Build Coastguard Worker 
3088*f6dc9357SAndroid Build Coastguard Worker }}
3089