xref: /aosp_15_r20/external/lzma/C/7zArcIn.c (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker /* 7zArcIn.c -- 7z Input functions
2*f6dc9357SAndroid Build Coastguard Worker 2023-09-07 : Igor Pavlov : Public domain */
3*f6dc9357SAndroid Build Coastguard Worker 
4*f6dc9357SAndroid Build Coastguard Worker #include "Precomp.h"
5*f6dc9357SAndroid Build Coastguard Worker 
6*f6dc9357SAndroid Build Coastguard Worker #include <string.h>
7*f6dc9357SAndroid Build Coastguard Worker 
8*f6dc9357SAndroid Build Coastguard Worker #include "7z.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "7zBuf.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "7zCrc.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "CpuArch.h"
12*f6dc9357SAndroid Build Coastguard Worker 
13*f6dc9357SAndroid Build Coastguard Worker #define MY_ALLOC(T, p, size, alloc) \
14*f6dc9357SAndroid Build Coastguard Worker   { if ((p = (T *)ISzAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; }
15*f6dc9357SAndroid Build Coastguard Worker 
16*f6dc9357SAndroid Build Coastguard Worker #define MY_ALLOC_ZE(T, p, size, alloc) \
17*f6dc9357SAndroid Build Coastguard Worker   { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) }
18*f6dc9357SAndroid Build Coastguard Worker 
19*f6dc9357SAndroid Build Coastguard Worker #define MY_ALLOC_AND_CPY(to, size, from, alloc) \
20*f6dc9357SAndroid Build Coastguard Worker   { MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); }
21*f6dc9357SAndroid Build Coastguard Worker 
22*f6dc9357SAndroid Build Coastguard Worker #define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \
23*f6dc9357SAndroid Build Coastguard Worker   { if ((size) == 0) to = NULL; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } }
24*f6dc9357SAndroid Build Coastguard Worker 
25*f6dc9357SAndroid Build Coastguard Worker #define k7zMajorVersion 0
26*f6dc9357SAndroid Build Coastguard Worker 
27*f6dc9357SAndroid Build Coastguard Worker enum EIdEnum
28*f6dc9357SAndroid Build Coastguard Worker {
29*f6dc9357SAndroid Build Coastguard Worker   k7zIdEnd,
30*f6dc9357SAndroid Build Coastguard Worker   k7zIdHeader,
31*f6dc9357SAndroid Build Coastguard Worker   k7zIdArchiveProperties,
32*f6dc9357SAndroid Build Coastguard Worker   k7zIdAdditionalStreamsInfo,
33*f6dc9357SAndroid Build Coastguard Worker   k7zIdMainStreamsInfo,
34*f6dc9357SAndroid Build Coastguard Worker   k7zIdFilesInfo,
35*f6dc9357SAndroid Build Coastguard Worker   k7zIdPackInfo,
36*f6dc9357SAndroid Build Coastguard Worker   k7zIdUnpackInfo,
37*f6dc9357SAndroid Build Coastguard Worker   k7zIdSubStreamsInfo,
38*f6dc9357SAndroid Build Coastguard Worker   k7zIdSize,
39*f6dc9357SAndroid Build Coastguard Worker   k7zIdCRC,
40*f6dc9357SAndroid Build Coastguard Worker   k7zIdFolder,
41*f6dc9357SAndroid Build Coastguard Worker   k7zIdCodersUnpackSize,
42*f6dc9357SAndroid Build Coastguard Worker   k7zIdNumUnpackStream,
43*f6dc9357SAndroid Build Coastguard Worker   k7zIdEmptyStream,
44*f6dc9357SAndroid Build Coastguard Worker   k7zIdEmptyFile,
45*f6dc9357SAndroid Build Coastguard Worker   k7zIdAnti,
46*f6dc9357SAndroid Build Coastguard Worker   k7zIdName,
47*f6dc9357SAndroid Build Coastguard Worker   k7zIdCTime,
48*f6dc9357SAndroid Build Coastguard Worker   k7zIdATime,
49*f6dc9357SAndroid Build Coastguard Worker   k7zIdMTime,
50*f6dc9357SAndroid Build Coastguard Worker   k7zIdWinAttrib,
51*f6dc9357SAndroid Build Coastguard Worker   k7zIdComment,
52*f6dc9357SAndroid Build Coastguard Worker   k7zIdEncodedHeader,
53*f6dc9357SAndroid Build Coastguard Worker   k7zIdStartPos,
54*f6dc9357SAndroid Build Coastguard Worker   k7zIdDummy
55*f6dc9357SAndroid Build Coastguard Worker   // k7zNtSecure,
56*f6dc9357SAndroid Build Coastguard Worker   // k7zParent,
57*f6dc9357SAndroid Build Coastguard Worker   // k7zIsReal
58*f6dc9357SAndroid Build Coastguard Worker };
59*f6dc9357SAndroid Build Coastguard Worker 
60*f6dc9357SAndroid Build Coastguard Worker const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
61*f6dc9357SAndroid Build Coastguard Worker 
62*f6dc9357SAndroid Build Coastguard Worker #define SzBitUi32s_INIT(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
63*f6dc9357SAndroid Build Coastguard Worker 
SzBitUi32s_Alloc(CSzBitUi32s * p,size_t num,ISzAllocPtr alloc)64*f6dc9357SAndroid Build Coastguard Worker static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc)
65*f6dc9357SAndroid Build Coastguard Worker {
66*f6dc9357SAndroid Build Coastguard Worker   if (num == 0)
67*f6dc9357SAndroid Build Coastguard Worker   {
68*f6dc9357SAndroid Build Coastguard Worker     p->Defs = NULL;
69*f6dc9357SAndroid Build Coastguard Worker     p->Vals = NULL;
70*f6dc9357SAndroid Build Coastguard Worker   }
71*f6dc9357SAndroid Build Coastguard Worker   else
72*f6dc9357SAndroid Build Coastguard Worker   {
73*f6dc9357SAndroid Build Coastguard Worker     MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc)
74*f6dc9357SAndroid Build Coastguard Worker     MY_ALLOC(UInt32, p->Vals, num, alloc)
75*f6dc9357SAndroid Build Coastguard Worker   }
76*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
77*f6dc9357SAndroid Build Coastguard Worker }
78*f6dc9357SAndroid Build Coastguard Worker 
SzBitUi32s_Free(CSzBitUi32s * p,ISzAllocPtr alloc)79*f6dc9357SAndroid Build Coastguard Worker static void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc)
80*f6dc9357SAndroid Build Coastguard Worker {
81*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL;
82*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL;
83*f6dc9357SAndroid Build Coastguard Worker }
84*f6dc9357SAndroid Build Coastguard Worker 
85*f6dc9357SAndroid Build Coastguard Worker #define SzBitUi64s_INIT(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
86*f6dc9357SAndroid Build Coastguard Worker 
SzBitUi64s_Free(CSzBitUi64s * p,ISzAllocPtr alloc)87*f6dc9357SAndroid Build Coastguard Worker static void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc)
88*f6dc9357SAndroid Build Coastguard Worker {
89*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL;
90*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL;
91*f6dc9357SAndroid Build Coastguard Worker }
92*f6dc9357SAndroid Build Coastguard Worker 
93*f6dc9357SAndroid Build Coastguard Worker 
SzAr_Init(CSzAr * p)94*f6dc9357SAndroid Build Coastguard Worker static void SzAr_Init(CSzAr *p)
95*f6dc9357SAndroid Build Coastguard Worker {
96*f6dc9357SAndroid Build Coastguard Worker   p->NumPackStreams = 0;
97*f6dc9357SAndroid Build Coastguard Worker   p->NumFolders = 0;
98*f6dc9357SAndroid Build Coastguard Worker 
99*f6dc9357SAndroid Build Coastguard Worker   p->PackPositions = NULL;
100*f6dc9357SAndroid Build Coastguard Worker   SzBitUi32s_INIT(&p->FolderCRCs)
101*f6dc9357SAndroid Build Coastguard Worker 
102*f6dc9357SAndroid Build Coastguard Worker   p->FoCodersOffsets = NULL;
103*f6dc9357SAndroid Build Coastguard Worker   p->FoStartPackStreamIndex = NULL;
104*f6dc9357SAndroid Build Coastguard Worker   p->FoToCoderUnpackSizes = NULL;
105*f6dc9357SAndroid Build Coastguard Worker   p->FoToMainUnpackSizeIndex = NULL;
106*f6dc9357SAndroid Build Coastguard Worker   p->CoderUnpackSizes = NULL;
107*f6dc9357SAndroid Build Coastguard Worker 
108*f6dc9357SAndroid Build Coastguard Worker   p->CodersData = NULL;
109*f6dc9357SAndroid Build Coastguard Worker 
110*f6dc9357SAndroid Build Coastguard Worker   p->RangeLimit = 0;
111*f6dc9357SAndroid Build Coastguard Worker }
112*f6dc9357SAndroid Build Coastguard Worker 
SzAr_Free(CSzAr * p,ISzAllocPtr alloc)113*f6dc9357SAndroid Build Coastguard Worker static void SzAr_Free(CSzAr *p, ISzAllocPtr alloc)
114*f6dc9357SAndroid Build Coastguard Worker {
115*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->PackPositions);
116*f6dc9357SAndroid Build Coastguard Worker   SzBitUi32s_Free(&p->FolderCRCs, alloc);
117*f6dc9357SAndroid Build Coastguard Worker 
118*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->FoCodersOffsets);
119*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->FoStartPackStreamIndex);
120*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->FoToCoderUnpackSizes);
121*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->FoToMainUnpackSizeIndex);
122*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->CoderUnpackSizes);
123*f6dc9357SAndroid Build Coastguard Worker 
124*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->CodersData);
125*f6dc9357SAndroid Build Coastguard Worker 
126*f6dc9357SAndroid Build Coastguard Worker   SzAr_Init(p);
127*f6dc9357SAndroid Build Coastguard Worker }
128*f6dc9357SAndroid Build Coastguard Worker 
129*f6dc9357SAndroid Build Coastguard Worker 
SzArEx_Init(CSzArEx * p)130*f6dc9357SAndroid Build Coastguard Worker void SzArEx_Init(CSzArEx *p)
131*f6dc9357SAndroid Build Coastguard Worker {
132*f6dc9357SAndroid Build Coastguard Worker   SzAr_Init(&p->db);
133*f6dc9357SAndroid Build Coastguard Worker 
134*f6dc9357SAndroid Build Coastguard Worker   p->NumFiles = 0;
135*f6dc9357SAndroid Build Coastguard Worker   p->dataPos = 0;
136*f6dc9357SAndroid Build Coastguard Worker 
137*f6dc9357SAndroid Build Coastguard Worker   p->UnpackPositions = NULL;
138*f6dc9357SAndroid Build Coastguard Worker   p->IsDirs = NULL;
139*f6dc9357SAndroid Build Coastguard Worker 
140*f6dc9357SAndroid Build Coastguard Worker   p->FolderToFile = NULL;
141*f6dc9357SAndroid Build Coastguard Worker   p->FileToFolder = NULL;
142*f6dc9357SAndroid Build Coastguard Worker 
143*f6dc9357SAndroid Build Coastguard Worker   p->FileNameOffsets = NULL;
144*f6dc9357SAndroid Build Coastguard Worker   p->FileNames = NULL;
145*f6dc9357SAndroid Build Coastguard Worker 
146*f6dc9357SAndroid Build Coastguard Worker   SzBitUi32s_INIT(&p->CRCs)
147*f6dc9357SAndroid Build Coastguard Worker   SzBitUi32s_INIT(&p->Attribs)
148*f6dc9357SAndroid Build Coastguard Worker   // SzBitUi32s_INIT(&p->Parents)
149*f6dc9357SAndroid Build Coastguard Worker   SzBitUi64s_INIT(&p->MTime)
150*f6dc9357SAndroid Build Coastguard Worker   SzBitUi64s_INIT(&p->CTime)
151*f6dc9357SAndroid Build Coastguard Worker }
152*f6dc9357SAndroid Build Coastguard Worker 
SzArEx_Free(CSzArEx * p,ISzAllocPtr alloc)153*f6dc9357SAndroid Build Coastguard Worker void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc)
154*f6dc9357SAndroid Build Coastguard Worker {
155*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->UnpackPositions);
156*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->IsDirs);
157*f6dc9357SAndroid Build Coastguard Worker 
158*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->FolderToFile);
159*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->FileToFolder);
160*f6dc9357SAndroid Build Coastguard Worker 
161*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->FileNameOffsets);
162*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->FileNames);
163*f6dc9357SAndroid Build Coastguard Worker 
164*f6dc9357SAndroid Build Coastguard Worker   SzBitUi32s_Free(&p->CRCs, alloc);
165*f6dc9357SAndroid Build Coastguard Worker   SzBitUi32s_Free(&p->Attribs, alloc);
166*f6dc9357SAndroid Build Coastguard Worker   // SzBitUi32s_Free(&p->Parents, alloc);
167*f6dc9357SAndroid Build Coastguard Worker   SzBitUi64s_Free(&p->MTime, alloc);
168*f6dc9357SAndroid Build Coastguard Worker   SzBitUi64s_Free(&p->CTime, alloc);
169*f6dc9357SAndroid Build Coastguard Worker 
170*f6dc9357SAndroid Build Coastguard Worker   SzAr_Free(&p->db, alloc);
171*f6dc9357SAndroid Build Coastguard Worker   SzArEx_Init(p);
172*f6dc9357SAndroid Build Coastguard Worker }
173*f6dc9357SAndroid Build Coastguard Worker 
174*f6dc9357SAndroid Build Coastguard Worker 
TestSignatureCandidate(const Byte * testBytes)175*f6dc9357SAndroid Build Coastguard Worker static int TestSignatureCandidate(const Byte *testBytes)
176*f6dc9357SAndroid Build Coastguard Worker {
177*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
178*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < k7zSignatureSize; i++)
179*f6dc9357SAndroid Build Coastguard Worker     if (testBytes[i] != k7zSignature[i])
180*f6dc9357SAndroid Build Coastguard Worker       return 0;
181*f6dc9357SAndroid Build Coastguard Worker   return 1;
182*f6dc9357SAndroid Build Coastguard Worker }
183*f6dc9357SAndroid Build Coastguard Worker 
184*f6dc9357SAndroid Build Coastguard Worker #define SzData_CLEAR(p) { (p)->Data = NULL; (p)->Size = 0; }
185*f6dc9357SAndroid Build Coastguard Worker 
186*f6dc9357SAndroid Build Coastguard Worker #define SZ_READ_BYTE_SD_NOCHECK(_sd_, dest) \
187*f6dc9357SAndroid Build Coastguard Worker     (_sd_)->Size--; dest = *(_sd_)->Data++;
188*f6dc9357SAndroid Build Coastguard Worker 
189*f6dc9357SAndroid Build Coastguard Worker #define SZ_READ_BYTE_SD(_sd_, dest) \
190*f6dc9357SAndroid Build Coastguard Worker     if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; \
191*f6dc9357SAndroid Build Coastguard Worker     SZ_READ_BYTE_SD_NOCHECK(_sd_, dest)
192*f6dc9357SAndroid Build Coastguard Worker 
193*f6dc9357SAndroid Build Coastguard Worker #define SZ_READ_BYTE(dest) SZ_READ_BYTE_SD(sd, dest)
194*f6dc9357SAndroid Build Coastguard Worker 
195*f6dc9357SAndroid Build Coastguard Worker #define SZ_READ_BYTE_2(dest) \
196*f6dc9357SAndroid Build Coastguard Worker     if (sd.Size == 0) return SZ_ERROR_ARCHIVE; \
197*f6dc9357SAndroid Build Coastguard Worker     sd.Size--; dest = *sd.Data++;
198*f6dc9357SAndroid Build Coastguard Worker 
199*f6dc9357SAndroid Build Coastguard Worker #define SKIP_DATA(sd, size) { sd->Size -= (size_t)(size); sd->Data += (size_t)(size); }
200*f6dc9357SAndroid Build Coastguard Worker #define SKIP_DATA2(sd, size) { sd.Size -= (size_t)(size); sd.Data += (size_t)(size); }
201*f6dc9357SAndroid Build Coastguard Worker 
202*f6dc9357SAndroid Build Coastguard Worker #define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \
203*f6dc9357SAndroid Build Coastguard Worker    dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4);
204*f6dc9357SAndroid Build Coastguard Worker 
ReadNumber(CSzData * sd,UInt64 * value)205*f6dc9357SAndroid Build Coastguard Worker static Z7_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value)
206*f6dc9357SAndroid Build Coastguard Worker {
207*f6dc9357SAndroid Build Coastguard Worker   Byte firstByte, mask;
208*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
209*f6dc9357SAndroid Build Coastguard Worker   UInt32 v;
210*f6dc9357SAndroid Build Coastguard Worker 
211*f6dc9357SAndroid Build Coastguard Worker   SZ_READ_BYTE(firstByte)
212*f6dc9357SAndroid Build Coastguard Worker   if ((firstByte & 0x80) == 0)
213*f6dc9357SAndroid Build Coastguard Worker   {
214*f6dc9357SAndroid Build Coastguard Worker     *value = firstByte;
215*f6dc9357SAndroid Build Coastguard Worker     return SZ_OK;
216*f6dc9357SAndroid Build Coastguard Worker   }
217*f6dc9357SAndroid Build Coastguard Worker   SZ_READ_BYTE(v)
218*f6dc9357SAndroid Build Coastguard Worker   if ((firstByte & 0x40) == 0)
219*f6dc9357SAndroid Build Coastguard Worker   {
220*f6dc9357SAndroid Build Coastguard Worker     *value = (((UInt32)firstByte & 0x3F) << 8) | v;
221*f6dc9357SAndroid Build Coastguard Worker     return SZ_OK;
222*f6dc9357SAndroid Build Coastguard Worker   }
223*f6dc9357SAndroid Build Coastguard Worker   SZ_READ_BYTE(mask)
224*f6dc9357SAndroid Build Coastguard Worker   *value = v | ((UInt32)mask << 8);
225*f6dc9357SAndroid Build Coastguard Worker   mask = 0x20;
226*f6dc9357SAndroid Build Coastguard Worker   for (i = 2; i < 8; i++)
227*f6dc9357SAndroid Build Coastguard Worker   {
228*f6dc9357SAndroid Build Coastguard Worker     Byte b;
229*f6dc9357SAndroid Build Coastguard Worker     if ((firstByte & mask) == 0)
230*f6dc9357SAndroid Build Coastguard Worker     {
231*f6dc9357SAndroid Build Coastguard Worker       const UInt64 highPart = (unsigned)firstByte & (unsigned)(mask - 1);
232*f6dc9357SAndroid Build Coastguard Worker       *value |= (highPart << (8 * i));
233*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
234*f6dc9357SAndroid Build Coastguard Worker     }
235*f6dc9357SAndroid Build Coastguard Worker     SZ_READ_BYTE(b)
236*f6dc9357SAndroid Build Coastguard Worker     *value |= ((UInt64)b << (8 * i));
237*f6dc9357SAndroid Build Coastguard Worker     mask >>= 1;
238*f6dc9357SAndroid Build Coastguard Worker   }
239*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
240*f6dc9357SAndroid Build Coastguard Worker }
241*f6dc9357SAndroid Build Coastguard Worker 
242*f6dc9357SAndroid Build Coastguard Worker 
SzReadNumber32(CSzData * sd,UInt32 * value)243*f6dc9357SAndroid Build Coastguard Worker static Z7_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value)
244*f6dc9357SAndroid Build Coastguard Worker {
245*f6dc9357SAndroid Build Coastguard Worker   Byte firstByte;
246*f6dc9357SAndroid Build Coastguard Worker   UInt64 value64;
247*f6dc9357SAndroid Build Coastguard Worker   if (sd->Size == 0)
248*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_ARCHIVE;
249*f6dc9357SAndroid Build Coastguard Worker   firstByte = *sd->Data;
250*f6dc9357SAndroid Build Coastguard Worker   if ((firstByte & 0x80) == 0)
251*f6dc9357SAndroid Build Coastguard Worker   {
252*f6dc9357SAndroid Build Coastguard Worker     *value = firstByte;
253*f6dc9357SAndroid Build Coastguard Worker     sd->Data++;
254*f6dc9357SAndroid Build Coastguard Worker     sd->Size--;
255*f6dc9357SAndroid Build Coastguard Worker     return SZ_OK;
256*f6dc9357SAndroid Build Coastguard Worker   }
257*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadNumber(sd, &value64))
258*f6dc9357SAndroid Build Coastguard Worker   if (value64 >= (UInt32)0x80000000 - 1)
259*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_UNSUPPORTED;
260*f6dc9357SAndroid Build Coastguard Worker   if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 4)))
261*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_UNSUPPORTED;
262*f6dc9357SAndroid Build Coastguard Worker   *value = (UInt32)value64;
263*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
264*f6dc9357SAndroid Build Coastguard Worker }
265*f6dc9357SAndroid Build Coastguard Worker 
266*f6dc9357SAndroid Build Coastguard Worker #define ReadID(sd, value) ReadNumber(sd, value)
267*f6dc9357SAndroid Build Coastguard Worker 
SkipData(CSzData * sd)268*f6dc9357SAndroid Build Coastguard Worker static SRes SkipData(CSzData *sd)
269*f6dc9357SAndroid Build Coastguard Worker {
270*f6dc9357SAndroid Build Coastguard Worker   UInt64 size;
271*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadNumber(sd, &size))
272*f6dc9357SAndroid Build Coastguard Worker   if (size > sd->Size)
273*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_ARCHIVE;
274*f6dc9357SAndroid Build Coastguard Worker   SKIP_DATA(sd, size)
275*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
276*f6dc9357SAndroid Build Coastguard Worker }
277*f6dc9357SAndroid Build Coastguard Worker 
WaitId(CSzData * sd,UInt32 id)278*f6dc9357SAndroid Build Coastguard Worker static SRes WaitId(CSzData *sd, UInt32 id)
279*f6dc9357SAndroid Build Coastguard Worker {
280*f6dc9357SAndroid Build Coastguard Worker   for (;;)
281*f6dc9357SAndroid Build Coastguard Worker   {
282*f6dc9357SAndroid Build Coastguard Worker     UInt64 type;
283*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadID(sd, &type))
284*f6dc9357SAndroid Build Coastguard Worker     if (type == id)
285*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
286*f6dc9357SAndroid Build Coastguard Worker     if (type == k7zIdEnd)
287*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_ARCHIVE;
288*f6dc9357SAndroid Build Coastguard Worker     RINOK(SkipData(sd))
289*f6dc9357SAndroid Build Coastguard Worker   }
290*f6dc9357SAndroid Build Coastguard Worker }
291*f6dc9357SAndroid Build Coastguard Worker 
RememberBitVector(CSzData * sd,UInt32 numItems,const Byte ** v)292*f6dc9357SAndroid Build Coastguard Worker static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v)
293*f6dc9357SAndroid Build Coastguard Worker {
294*f6dc9357SAndroid Build Coastguard Worker   const UInt32 numBytes = (numItems + 7) >> 3;
295*f6dc9357SAndroid Build Coastguard Worker   if (numBytes > sd->Size)
296*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_ARCHIVE;
297*f6dc9357SAndroid Build Coastguard Worker   *v = sd->Data;
298*f6dc9357SAndroid Build Coastguard Worker   SKIP_DATA(sd, numBytes)
299*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
300*f6dc9357SAndroid Build Coastguard Worker }
301*f6dc9357SAndroid Build Coastguard Worker 
CountDefinedBits(const Byte * bits,UInt32 numItems)302*f6dc9357SAndroid Build Coastguard Worker static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems)
303*f6dc9357SAndroid Build Coastguard Worker {
304*f6dc9357SAndroid Build Coastguard Worker   unsigned b = 0;
305*f6dc9357SAndroid Build Coastguard Worker   unsigned m = 0;
306*f6dc9357SAndroid Build Coastguard Worker   UInt32 sum = 0;
307*f6dc9357SAndroid Build Coastguard Worker   for (; numItems != 0; numItems--)
308*f6dc9357SAndroid Build Coastguard Worker   {
309*f6dc9357SAndroid Build Coastguard Worker     if (m == 0)
310*f6dc9357SAndroid Build Coastguard Worker     {
311*f6dc9357SAndroid Build Coastguard Worker       b = *bits++;
312*f6dc9357SAndroid Build Coastguard Worker       m = 8;
313*f6dc9357SAndroid Build Coastguard Worker     }
314*f6dc9357SAndroid Build Coastguard Worker     m--;
315*f6dc9357SAndroid Build Coastguard Worker     sum += (UInt32)((b >> m) & 1);
316*f6dc9357SAndroid Build Coastguard Worker   }
317*f6dc9357SAndroid Build Coastguard Worker   return sum;
318*f6dc9357SAndroid Build Coastguard Worker }
319*f6dc9357SAndroid Build Coastguard Worker 
ReadBitVector(CSzData * sd,UInt32 numItems,Byte ** v,ISzAllocPtr alloc)320*f6dc9357SAndroid Build Coastguard Worker static Z7_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAllocPtr alloc)
321*f6dc9357SAndroid Build Coastguard Worker {
322*f6dc9357SAndroid Build Coastguard Worker   Byte allAreDefined;
323*f6dc9357SAndroid Build Coastguard Worker   Byte *v2;
324*f6dc9357SAndroid Build Coastguard Worker   const UInt32 numBytes = (numItems + 7) >> 3;
325*f6dc9357SAndroid Build Coastguard Worker   *v = NULL;
326*f6dc9357SAndroid Build Coastguard Worker   SZ_READ_BYTE(allAreDefined)
327*f6dc9357SAndroid Build Coastguard Worker   if (numBytes == 0)
328*f6dc9357SAndroid Build Coastguard Worker     return SZ_OK;
329*f6dc9357SAndroid Build Coastguard Worker   if (allAreDefined == 0)
330*f6dc9357SAndroid Build Coastguard Worker   {
331*f6dc9357SAndroid Build Coastguard Worker     if (numBytes > sd->Size)
332*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_ARCHIVE;
333*f6dc9357SAndroid Build Coastguard Worker     MY_ALLOC_AND_CPY(*v, numBytes, sd->Data, alloc)
334*f6dc9357SAndroid Build Coastguard Worker     SKIP_DATA(sd, numBytes)
335*f6dc9357SAndroid Build Coastguard Worker     return SZ_OK;
336*f6dc9357SAndroid Build Coastguard Worker   }
337*f6dc9357SAndroid Build Coastguard Worker   MY_ALLOC(Byte, *v, numBytes, alloc)
338*f6dc9357SAndroid Build Coastguard Worker   v2 = *v;
339*f6dc9357SAndroid Build Coastguard Worker   memset(v2, 0xFF, (size_t)numBytes);
340*f6dc9357SAndroid Build Coastguard Worker   {
341*f6dc9357SAndroid Build Coastguard Worker     const unsigned numBits = (unsigned)numItems & 7;
342*f6dc9357SAndroid Build Coastguard Worker     if (numBits != 0)
343*f6dc9357SAndroid Build Coastguard Worker       v2[(size_t)numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits));
344*f6dc9357SAndroid Build Coastguard Worker   }
345*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
346*f6dc9357SAndroid Build Coastguard Worker }
347*f6dc9357SAndroid Build Coastguard Worker 
ReadUi32s(CSzData * sd2,UInt32 numItems,CSzBitUi32s * crcs,ISzAllocPtr alloc)348*f6dc9357SAndroid Build Coastguard Worker static Z7_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
349*f6dc9357SAndroid Build Coastguard Worker {
350*f6dc9357SAndroid Build Coastguard Worker   UInt32 i;
351*f6dc9357SAndroid Build Coastguard Worker   CSzData sd;
352*f6dc9357SAndroid Build Coastguard Worker   UInt32 *vals;
353*f6dc9357SAndroid Build Coastguard Worker   const Byte *defs;
354*f6dc9357SAndroid Build Coastguard Worker   MY_ALLOC_ZE(UInt32, crcs->Vals, numItems, alloc)
355*f6dc9357SAndroid Build Coastguard Worker   sd = *sd2;
356*f6dc9357SAndroid Build Coastguard Worker   defs = crcs->Defs;
357*f6dc9357SAndroid Build Coastguard Worker   vals = crcs->Vals;
358*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < numItems; i++)
359*f6dc9357SAndroid Build Coastguard Worker     if (SzBitArray_Check(defs, i))
360*f6dc9357SAndroid Build Coastguard Worker     {
361*f6dc9357SAndroid Build Coastguard Worker       SZ_READ_32(vals[i])
362*f6dc9357SAndroid Build Coastguard Worker     }
363*f6dc9357SAndroid Build Coastguard Worker     else
364*f6dc9357SAndroid Build Coastguard Worker       vals[i] = 0;
365*f6dc9357SAndroid Build Coastguard Worker   *sd2 = sd;
366*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
367*f6dc9357SAndroid Build Coastguard Worker }
368*f6dc9357SAndroid Build Coastguard Worker 
ReadBitUi32s(CSzData * sd,UInt32 numItems,CSzBitUi32s * crcs,ISzAllocPtr alloc)369*f6dc9357SAndroid Build Coastguard Worker static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
370*f6dc9357SAndroid Build Coastguard Worker {
371*f6dc9357SAndroid Build Coastguard Worker   SzBitUi32s_Free(crcs, alloc);
372*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc))
373*f6dc9357SAndroid Build Coastguard Worker   return ReadUi32s(sd, numItems, crcs, alloc);
374*f6dc9357SAndroid Build Coastguard Worker }
375*f6dc9357SAndroid Build Coastguard Worker 
SkipBitUi32s(CSzData * sd,UInt32 numItems)376*f6dc9357SAndroid Build Coastguard Worker static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems)
377*f6dc9357SAndroid Build Coastguard Worker {
378*f6dc9357SAndroid Build Coastguard Worker   Byte allAreDefined;
379*f6dc9357SAndroid Build Coastguard Worker   UInt32 numDefined = numItems;
380*f6dc9357SAndroid Build Coastguard Worker   SZ_READ_BYTE(allAreDefined)
381*f6dc9357SAndroid Build Coastguard Worker   if (!allAreDefined)
382*f6dc9357SAndroid Build Coastguard Worker   {
383*f6dc9357SAndroid Build Coastguard Worker     const size_t numBytes = (numItems + 7) >> 3;
384*f6dc9357SAndroid Build Coastguard Worker     if (numBytes > sd->Size)
385*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_ARCHIVE;
386*f6dc9357SAndroid Build Coastguard Worker     numDefined = CountDefinedBits(sd->Data, numItems);
387*f6dc9357SAndroid Build Coastguard Worker     SKIP_DATA(sd, numBytes)
388*f6dc9357SAndroid Build Coastguard Worker   }
389*f6dc9357SAndroid Build Coastguard Worker   if (numDefined > (sd->Size >> 2))
390*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_ARCHIVE;
391*f6dc9357SAndroid Build Coastguard Worker   SKIP_DATA(sd, (size_t)numDefined * 4)
392*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
393*f6dc9357SAndroid Build Coastguard Worker }
394*f6dc9357SAndroid Build Coastguard Worker 
ReadPackInfo(CSzAr * p,CSzData * sd,ISzAllocPtr alloc)395*f6dc9357SAndroid Build Coastguard Worker static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAllocPtr alloc)
396*f6dc9357SAndroid Build Coastguard Worker {
397*f6dc9357SAndroid Build Coastguard Worker   RINOK(SzReadNumber32(sd, &p->NumPackStreams))
398*f6dc9357SAndroid Build Coastguard Worker 
399*f6dc9357SAndroid Build Coastguard Worker   RINOK(WaitId(sd, k7zIdSize))
400*f6dc9357SAndroid Build Coastguard Worker   MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc)
401*f6dc9357SAndroid Build Coastguard Worker   {
402*f6dc9357SAndroid Build Coastguard Worker     UInt64 sum = 0;
403*f6dc9357SAndroid Build Coastguard Worker     UInt32 i;
404*f6dc9357SAndroid Build Coastguard Worker     const UInt32 numPackStreams = p->NumPackStreams;
405*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < numPackStreams; i++)
406*f6dc9357SAndroid Build Coastguard Worker     {
407*f6dc9357SAndroid Build Coastguard Worker       UInt64 packSize;
408*f6dc9357SAndroid Build Coastguard Worker       p->PackPositions[i] = sum;
409*f6dc9357SAndroid Build Coastguard Worker       RINOK(ReadNumber(sd, &packSize))
410*f6dc9357SAndroid Build Coastguard Worker       sum += packSize;
411*f6dc9357SAndroid Build Coastguard Worker       if (sum < packSize)
412*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_ARCHIVE;
413*f6dc9357SAndroid Build Coastguard Worker     }
414*f6dc9357SAndroid Build Coastguard Worker     p->PackPositions[i] = sum;
415*f6dc9357SAndroid Build Coastguard Worker   }
416*f6dc9357SAndroid Build Coastguard Worker 
417*f6dc9357SAndroid Build Coastguard Worker   for (;;)
418*f6dc9357SAndroid Build Coastguard Worker   {
419*f6dc9357SAndroid Build Coastguard Worker     UInt64 type;
420*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadID(sd, &type))
421*f6dc9357SAndroid Build Coastguard Worker     if (type == k7zIdEnd)
422*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
423*f6dc9357SAndroid Build Coastguard Worker     if (type == k7zIdCRC)
424*f6dc9357SAndroid Build Coastguard Worker     {
425*f6dc9357SAndroid Build Coastguard Worker       /* CRC of packed streams is unused now */
426*f6dc9357SAndroid Build Coastguard Worker       RINOK(SkipBitUi32s(sd, p->NumPackStreams))
427*f6dc9357SAndroid Build Coastguard Worker       continue;
428*f6dc9357SAndroid Build Coastguard Worker     }
429*f6dc9357SAndroid Build Coastguard Worker     RINOK(SkipData(sd))
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 static SRes SzReadSwitch(CSzData *sd)
435*f6dc9357SAndroid Build Coastguard Worker {
436*f6dc9357SAndroid Build Coastguard Worker   Byte external;
437*f6dc9357SAndroid Build Coastguard Worker   RINOK(SzReadByte(sd, &external));
438*f6dc9357SAndroid Build Coastguard Worker   return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED;
439*f6dc9357SAndroid Build Coastguard Worker }
440*f6dc9357SAndroid Build Coastguard Worker */
441*f6dc9357SAndroid Build Coastguard Worker 
442*f6dc9357SAndroid Build Coastguard Worker #define k_NumCodersStreams_in_Folder_MAX (SZ_NUM_BONDS_IN_FOLDER_MAX + SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)
443*f6dc9357SAndroid Build Coastguard Worker 
SzGetNextFolderItem(CSzFolder * f,CSzData * sd)444*f6dc9357SAndroid Build Coastguard Worker SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd)
445*f6dc9357SAndroid Build Coastguard Worker {
446*f6dc9357SAndroid Build Coastguard Worker   UInt32 numCoders, i;
447*f6dc9357SAndroid Build Coastguard Worker   UInt32 numInStreams = 0;
448*f6dc9357SAndroid Build Coastguard Worker   const Byte *dataStart = sd->Data;
449*f6dc9357SAndroid Build Coastguard Worker 
450*f6dc9357SAndroid Build Coastguard Worker   f->NumCoders = 0;
451*f6dc9357SAndroid Build Coastguard Worker   f->NumBonds = 0;
452*f6dc9357SAndroid Build Coastguard Worker   f->NumPackStreams = 0;
453*f6dc9357SAndroid Build Coastguard Worker   f->UnpackStream = 0;
454*f6dc9357SAndroid Build Coastguard Worker 
455*f6dc9357SAndroid Build Coastguard Worker   RINOK(SzReadNumber32(sd, &numCoders))
456*f6dc9357SAndroid Build Coastguard Worker   if (numCoders == 0 || numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX)
457*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_UNSUPPORTED;
458*f6dc9357SAndroid Build Coastguard Worker 
459*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < numCoders; i++)
460*f6dc9357SAndroid Build Coastguard Worker   {
461*f6dc9357SAndroid Build Coastguard Worker     Byte mainByte;
462*f6dc9357SAndroid Build Coastguard Worker     CSzCoderInfo *coder = f->Coders + i;
463*f6dc9357SAndroid Build Coastguard Worker     unsigned idSize, j;
464*f6dc9357SAndroid Build Coastguard Worker     UInt64 id;
465*f6dc9357SAndroid Build Coastguard Worker 
466*f6dc9357SAndroid Build Coastguard Worker     SZ_READ_BYTE(mainByte)
467*f6dc9357SAndroid Build Coastguard Worker     if ((mainByte & 0xC0) != 0)
468*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_UNSUPPORTED;
469*f6dc9357SAndroid Build Coastguard Worker 
470*f6dc9357SAndroid Build Coastguard Worker     idSize = (unsigned)(mainByte & 0xF);
471*f6dc9357SAndroid Build Coastguard Worker     if (idSize > sizeof(id))
472*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_UNSUPPORTED;
473*f6dc9357SAndroid Build Coastguard Worker     if (idSize > sd->Size)
474*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_ARCHIVE;
475*f6dc9357SAndroid Build Coastguard Worker     id = 0;
476*f6dc9357SAndroid Build Coastguard Worker     for (j = 0; j < idSize; j++)
477*f6dc9357SAndroid Build Coastguard Worker     {
478*f6dc9357SAndroid Build Coastguard Worker       id = ((id << 8) | *sd->Data);
479*f6dc9357SAndroid Build Coastguard Worker       sd->Data++;
480*f6dc9357SAndroid Build Coastguard Worker       sd->Size--;
481*f6dc9357SAndroid Build Coastguard Worker     }
482*f6dc9357SAndroid Build Coastguard Worker     if (id > (UInt32)0xFFFFFFFF)
483*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_UNSUPPORTED;
484*f6dc9357SAndroid Build Coastguard Worker     coder->MethodID = (UInt32)id;
485*f6dc9357SAndroid Build Coastguard Worker 
486*f6dc9357SAndroid Build Coastguard Worker     coder->NumStreams = 1;
487*f6dc9357SAndroid Build Coastguard Worker     coder->PropsOffset = 0;
488*f6dc9357SAndroid Build Coastguard Worker     coder->PropsSize = 0;
489*f6dc9357SAndroid Build Coastguard Worker 
490*f6dc9357SAndroid Build Coastguard Worker     if ((mainByte & 0x10) != 0)
491*f6dc9357SAndroid Build Coastguard Worker     {
492*f6dc9357SAndroid Build Coastguard Worker       UInt32 numStreams;
493*f6dc9357SAndroid Build Coastguard Worker 
494*f6dc9357SAndroid Build Coastguard Worker       RINOK(SzReadNumber32(sd, &numStreams))
495*f6dc9357SAndroid Build Coastguard Worker       if (numStreams > k_NumCodersStreams_in_Folder_MAX)
496*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_UNSUPPORTED;
497*f6dc9357SAndroid Build Coastguard Worker       coder->NumStreams = (Byte)numStreams;
498*f6dc9357SAndroid Build Coastguard Worker 
499*f6dc9357SAndroid Build Coastguard Worker       RINOK(SzReadNumber32(sd, &numStreams))
500*f6dc9357SAndroid Build Coastguard Worker       if (numStreams != 1)
501*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_UNSUPPORTED;
502*f6dc9357SAndroid Build Coastguard Worker     }
503*f6dc9357SAndroid Build Coastguard Worker 
504*f6dc9357SAndroid Build Coastguard Worker     numInStreams += coder->NumStreams;
505*f6dc9357SAndroid Build Coastguard Worker 
506*f6dc9357SAndroid Build Coastguard Worker     if (numInStreams > k_NumCodersStreams_in_Folder_MAX)
507*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_UNSUPPORTED;
508*f6dc9357SAndroid Build Coastguard Worker 
509*f6dc9357SAndroid Build Coastguard Worker     if ((mainByte & 0x20) != 0)
510*f6dc9357SAndroid Build Coastguard Worker     {
511*f6dc9357SAndroid Build Coastguard Worker       UInt32 propsSize = 0;
512*f6dc9357SAndroid Build Coastguard Worker       RINOK(SzReadNumber32(sd, &propsSize))
513*f6dc9357SAndroid Build Coastguard Worker       if (propsSize > sd->Size)
514*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_ARCHIVE;
515*f6dc9357SAndroid Build Coastguard Worker       if (propsSize >= 0x80)
516*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_UNSUPPORTED;
517*f6dc9357SAndroid Build Coastguard Worker       coder->PropsOffset = (size_t)(sd->Data - dataStart);
518*f6dc9357SAndroid Build Coastguard Worker       coder->PropsSize = (Byte)propsSize;
519*f6dc9357SAndroid Build Coastguard Worker       sd->Data += (size_t)propsSize;
520*f6dc9357SAndroid Build Coastguard Worker       sd->Size -= (size_t)propsSize;
521*f6dc9357SAndroid Build Coastguard Worker     }
522*f6dc9357SAndroid Build Coastguard Worker   }
523*f6dc9357SAndroid Build Coastguard Worker 
524*f6dc9357SAndroid Build Coastguard Worker   /*
525*f6dc9357SAndroid Build Coastguard Worker   if (numInStreams == 1 && numCoders == 1)
526*f6dc9357SAndroid Build Coastguard Worker   {
527*f6dc9357SAndroid Build Coastguard Worker     f->NumPackStreams = 1;
528*f6dc9357SAndroid Build Coastguard Worker     f->PackStreams[0] = 0;
529*f6dc9357SAndroid Build Coastguard Worker   }
530*f6dc9357SAndroid Build Coastguard Worker   else
531*f6dc9357SAndroid Build Coastguard Worker   */
532*f6dc9357SAndroid Build Coastguard Worker   {
533*f6dc9357SAndroid Build Coastguard Worker     Byte streamUsed[k_NumCodersStreams_in_Folder_MAX];
534*f6dc9357SAndroid Build Coastguard Worker     UInt32 numBonds, numPackStreams;
535*f6dc9357SAndroid Build Coastguard Worker 
536*f6dc9357SAndroid Build Coastguard Worker     numBonds = numCoders - 1;
537*f6dc9357SAndroid Build Coastguard Worker     if (numInStreams < numBonds)
538*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_ARCHIVE;
539*f6dc9357SAndroid Build Coastguard Worker     if (numBonds > SZ_NUM_BONDS_IN_FOLDER_MAX)
540*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_UNSUPPORTED;
541*f6dc9357SAndroid Build Coastguard Worker     f->NumBonds = numBonds;
542*f6dc9357SAndroid Build Coastguard Worker 
543*f6dc9357SAndroid Build Coastguard Worker     numPackStreams = numInStreams - numBonds;
544*f6dc9357SAndroid Build Coastguard Worker     if (numPackStreams > SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)
545*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_UNSUPPORTED;
546*f6dc9357SAndroid Build Coastguard Worker     f->NumPackStreams = numPackStreams;
547*f6dc9357SAndroid Build Coastguard Worker 
548*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < numInStreams; i++)
549*f6dc9357SAndroid Build Coastguard Worker       streamUsed[i] = False;
550*f6dc9357SAndroid Build Coastguard Worker 
551*f6dc9357SAndroid Build Coastguard Worker     if (numBonds != 0)
552*f6dc9357SAndroid Build Coastguard Worker     {
553*f6dc9357SAndroid Build Coastguard Worker       Byte coderUsed[SZ_NUM_CODERS_IN_FOLDER_MAX];
554*f6dc9357SAndroid Build Coastguard Worker 
555*f6dc9357SAndroid Build Coastguard Worker       for (i = 0; i < numCoders; i++)
556*f6dc9357SAndroid Build Coastguard Worker         coderUsed[i] = False;
557*f6dc9357SAndroid Build Coastguard Worker 
558*f6dc9357SAndroid Build Coastguard Worker       for (i = 0; i < numBonds; i++)
559*f6dc9357SAndroid Build Coastguard Worker       {
560*f6dc9357SAndroid Build Coastguard Worker         CSzBond *bp = f->Bonds + i;
561*f6dc9357SAndroid Build Coastguard Worker 
562*f6dc9357SAndroid Build Coastguard Worker         RINOK(SzReadNumber32(sd, &bp->InIndex))
563*f6dc9357SAndroid Build Coastguard Worker         if (bp->InIndex >= numInStreams || streamUsed[bp->InIndex])
564*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_ARCHIVE;
565*f6dc9357SAndroid Build Coastguard Worker         streamUsed[bp->InIndex] = True;
566*f6dc9357SAndroid Build Coastguard Worker 
567*f6dc9357SAndroid Build Coastguard Worker         RINOK(SzReadNumber32(sd, &bp->OutIndex))
568*f6dc9357SAndroid Build Coastguard Worker         if (bp->OutIndex >= numCoders || coderUsed[bp->OutIndex])
569*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_ARCHIVE;
570*f6dc9357SAndroid Build Coastguard Worker         coderUsed[bp->OutIndex] = True;
571*f6dc9357SAndroid Build Coastguard Worker       }
572*f6dc9357SAndroid Build Coastguard Worker 
573*f6dc9357SAndroid Build Coastguard Worker       for (i = 0; i < numCoders; i++)
574*f6dc9357SAndroid Build Coastguard Worker         if (!coderUsed[i])
575*f6dc9357SAndroid Build Coastguard Worker         {
576*f6dc9357SAndroid Build Coastguard Worker           f->UnpackStream = i;
577*f6dc9357SAndroid Build Coastguard Worker           break;
578*f6dc9357SAndroid Build Coastguard Worker         }
579*f6dc9357SAndroid Build Coastguard Worker 
580*f6dc9357SAndroid Build Coastguard Worker       if (i == numCoders)
581*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_ARCHIVE;
582*f6dc9357SAndroid Build Coastguard Worker     }
583*f6dc9357SAndroid Build Coastguard Worker 
584*f6dc9357SAndroid Build Coastguard Worker     if (numPackStreams == 1)
585*f6dc9357SAndroid Build Coastguard Worker     {
586*f6dc9357SAndroid Build Coastguard Worker       for (i = 0; i < numInStreams; i++)
587*f6dc9357SAndroid Build Coastguard Worker         if (!streamUsed[i])
588*f6dc9357SAndroid Build Coastguard Worker           break;
589*f6dc9357SAndroid Build Coastguard Worker       if (i == numInStreams)
590*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_ARCHIVE;
591*f6dc9357SAndroid Build Coastguard Worker       f->PackStreams[0] = i;
592*f6dc9357SAndroid Build Coastguard Worker     }
593*f6dc9357SAndroid Build Coastguard Worker     else
594*f6dc9357SAndroid Build Coastguard Worker       for (i = 0; i < numPackStreams; i++)
595*f6dc9357SAndroid Build Coastguard Worker       {
596*f6dc9357SAndroid Build Coastguard Worker         UInt32 index;
597*f6dc9357SAndroid Build Coastguard Worker         RINOK(SzReadNumber32(sd, &index))
598*f6dc9357SAndroid Build Coastguard Worker         if (index >= numInStreams || streamUsed[index])
599*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_ARCHIVE;
600*f6dc9357SAndroid Build Coastguard Worker         streamUsed[index] = True;
601*f6dc9357SAndroid Build Coastguard Worker         f->PackStreams[i] = index;
602*f6dc9357SAndroid Build Coastguard Worker       }
603*f6dc9357SAndroid Build Coastguard Worker   }
604*f6dc9357SAndroid Build Coastguard Worker 
605*f6dc9357SAndroid Build Coastguard Worker   f->NumCoders = numCoders;
606*f6dc9357SAndroid Build Coastguard Worker 
607*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
608*f6dc9357SAndroid Build Coastguard Worker }
609*f6dc9357SAndroid Build Coastguard Worker 
610*f6dc9357SAndroid Build Coastguard Worker 
SkipNumbers(CSzData * sd2,UInt32 num)611*f6dc9357SAndroid Build Coastguard Worker static Z7_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num)
612*f6dc9357SAndroid Build Coastguard Worker {
613*f6dc9357SAndroid Build Coastguard Worker   CSzData sd;
614*f6dc9357SAndroid Build Coastguard Worker   sd = *sd2;
615*f6dc9357SAndroid Build Coastguard Worker   for (; num != 0; num--)
616*f6dc9357SAndroid Build Coastguard Worker   {
617*f6dc9357SAndroid Build Coastguard Worker     Byte firstByte, mask;
618*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
619*f6dc9357SAndroid Build Coastguard Worker     SZ_READ_BYTE_2(firstByte)
620*f6dc9357SAndroid Build Coastguard Worker     if ((firstByte & 0x80) == 0)
621*f6dc9357SAndroid Build Coastguard Worker       continue;
622*f6dc9357SAndroid Build Coastguard Worker     if ((firstByte & 0x40) == 0)
623*f6dc9357SAndroid Build Coastguard Worker     {
624*f6dc9357SAndroid Build Coastguard Worker       if (sd.Size == 0)
625*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_ARCHIVE;
626*f6dc9357SAndroid Build Coastguard Worker       sd.Size--;
627*f6dc9357SAndroid Build Coastguard Worker       sd.Data++;
628*f6dc9357SAndroid Build Coastguard Worker       continue;
629*f6dc9357SAndroid Build Coastguard Worker     }
630*f6dc9357SAndroid Build Coastguard Worker     mask = 0x20;
631*f6dc9357SAndroid Build Coastguard Worker     for (i = 2; i < 8 && (firstByte & mask) != 0; i++)
632*f6dc9357SAndroid Build Coastguard Worker       mask >>= 1;
633*f6dc9357SAndroid Build Coastguard Worker     if (i > sd.Size)
634*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_ARCHIVE;
635*f6dc9357SAndroid Build Coastguard Worker     SKIP_DATA2(sd, i)
636*f6dc9357SAndroid Build Coastguard Worker   }
637*f6dc9357SAndroid Build Coastguard Worker   *sd2 = sd;
638*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
639*f6dc9357SAndroid Build Coastguard Worker }
640*f6dc9357SAndroid Build Coastguard Worker 
641*f6dc9357SAndroid Build Coastguard Worker 
642*f6dc9357SAndroid Build Coastguard Worker #define k_Scan_NumCoders_MAX 64
643*f6dc9357SAndroid Build Coastguard Worker #define k_Scan_NumCodersStreams_in_Folder_MAX 64
644*f6dc9357SAndroid Build Coastguard Worker 
645*f6dc9357SAndroid Build Coastguard Worker 
ReadUnpackInfo(CSzAr * p,CSzData * sd2,UInt32 numFoldersMax,const CBuf * tempBufs,UInt32 numTempBufs,ISzAllocPtr alloc)646*f6dc9357SAndroid Build Coastguard Worker static SRes ReadUnpackInfo(CSzAr *p,
647*f6dc9357SAndroid Build Coastguard Worker     CSzData *sd2,
648*f6dc9357SAndroid Build Coastguard Worker     UInt32 numFoldersMax,
649*f6dc9357SAndroid Build Coastguard Worker     const CBuf *tempBufs, UInt32 numTempBufs,
650*f6dc9357SAndroid Build Coastguard Worker     ISzAllocPtr alloc)
651*f6dc9357SAndroid Build Coastguard Worker {
652*f6dc9357SAndroid Build Coastguard Worker   CSzData sd;
653*f6dc9357SAndroid Build Coastguard Worker 
654*f6dc9357SAndroid Build Coastguard Worker   UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex;
655*f6dc9357SAndroid Build Coastguard Worker   const Byte *startBufPtr;
656*f6dc9357SAndroid Build Coastguard Worker   Byte external;
657*f6dc9357SAndroid Build Coastguard Worker 
658*f6dc9357SAndroid Build Coastguard Worker   RINOK(WaitId(sd2, k7zIdFolder))
659*f6dc9357SAndroid Build Coastguard Worker 
660*f6dc9357SAndroid Build Coastguard Worker   RINOK(SzReadNumber32(sd2, &numFolders))
661*f6dc9357SAndroid Build Coastguard Worker   if (numFolders > numFoldersMax)
662*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_UNSUPPORTED;
663*f6dc9357SAndroid Build Coastguard Worker   p->NumFolders = numFolders;
664*f6dc9357SAndroid Build Coastguard Worker 
665*f6dc9357SAndroid Build Coastguard Worker   SZ_READ_BYTE_SD(sd2, external)
666*f6dc9357SAndroid Build Coastguard Worker   if (external == 0)
667*f6dc9357SAndroid Build Coastguard Worker     sd = *sd2;
668*f6dc9357SAndroid Build Coastguard Worker   else
669*f6dc9357SAndroid Build Coastguard Worker   {
670*f6dc9357SAndroid Build Coastguard Worker     UInt32 index;
671*f6dc9357SAndroid Build Coastguard Worker     RINOK(SzReadNumber32(sd2, &index))
672*f6dc9357SAndroid Build Coastguard Worker     if (index >= numTempBufs)
673*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_ARCHIVE;
674*f6dc9357SAndroid Build Coastguard Worker     sd.Data = tempBufs[index].data;
675*f6dc9357SAndroid Build Coastguard Worker     sd.Size = tempBufs[index].size;
676*f6dc9357SAndroid Build Coastguard Worker   }
677*f6dc9357SAndroid Build Coastguard Worker 
678*f6dc9357SAndroid Build Coastguard Worker   MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc)
679*f6dc9357SAndroid Build Coastguard Worker   MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc)
680*f6dc9357SAndroid Build Coastguard Worker   MY_ALLOC(UInt32, p->FoToCoderUnpackSizes, (size_t)numFolders + 1, alloc)
681*f6dc9357SAndroid Build Coastguard Worker   MY_ALLOC_ZE(Byte, p->FoToMainUnpackSizeIndex, (size_t)numFolders, alloc)
682*f6dc9357SAndroid Build Coastguard Worker 
683*f6dc9357SAndroid Build Coastguard Worker   startBufPtr = sd.Data;
684*f6dc9357SAndroid Build Coastguard Worker 
685*f6dc9357SAndroid Build Coastguard Worker   packStreamIndex = 0;
686*f6dc9357SAndroid Build Coastguard Worker   numCodersOutStreams = 0;
687*f6dc9357SAndroid Build Coastguard Worker 
688*f6dc9357SAndroid Build Coastguard Worker   for (fo = 0; fo < numFolders; fo++)
689*f6dc9357SAndroid Build Coastguard Worker   {
690*f6dc9357SAndroid Build Coastguard Worker     UInt32 numCoders, ci, numInStreams = 0;
691*f6dc9357SAndroid Build Coastguard Worker 
692*f6dc9357SAndroid Build Coastguard Worker     p->FoCodersOffsets[fo] = (size_t)(sd.Data - startBufPtr);
693*f6dc9357SAndroid Build Coastguard Worker 
694*f6dc9357SAndroid Build Coastguard Worker     RINOK(SzReadNumber32(&sd, &numCoders))
695*f6dc9357SAndroid Build Coastguard Worker     if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
696*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_UNSUPPORTED;
697*f6dc9357SAndroid Build Coastguard Worker 
698*f6dc9357SAndroid Build Coastguard Worker     for (ci = 0; ci < numCoders; ci++)
699*f6dc9357SAndroid Build Coastguard Worker     {
700*f6dc9357SAndroid Build Coastguard Worker       Byte mainByte;
701*f6dc9357SAndroid Build Coastguard Worker       unsigned idSize;
702*f6dc9357SAndroid Build Coastguard Worker       UInt32 coderInStreams;
703*f6dc9357SAndroid Build Coastguard Worker 
704*f6dc9357SAndroid Build Coastguard Worker       SZ_READ_BYTE_2(mainByte)
705*f6dc9357SAndroid Build Coastguard Worker       if ((mainByte & 0xC0) != 0)
706*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_UNSUPPORTED;
707*f6dc9357SAndroid Build Coastguard Worker       idSize = (mainByte & 0xF);
708*f6dc9357SAndroid Build Coastguard Worker       if (idSize > 8)
709*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_UNSUPPORTED;
710*f6dc9357SAndroid Build Coastguard Worker       if (idSize > sd.Size)
711*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_ARCHIVE;
712*f6dc9357SAndroid Build Coastguard Worker       SKIP_DATA2(sd, idSize)
713*f6dc9357SAndroid Build Coastguard Worker 
714*f6dc9357SAndroid Build Coastguard Worker       coderInStreams = 1;
715*f6dc9357SAndroid Build Coastguard Worker 
716*f6dc9357SAndroid Build Coastguard Worker       if ((mainByte & 0x10) != 0)
717*f6dc9357SAndroid Build Coastguard Worker       {
718*f6dc9357SAndroid Build Coastguard Worker         UInt32 coderOutStreams;
719*f6dc9357SAndroid Build Coastguard Worker         RINOK(SzReadNumber32(&sd, &coderInStreams))
720*f6dc9357SAndroid Build Coastguard Worker         RINOK(SzReadNumber32(&sd, &coderOutStreams))
721*f6dc9357SAndroid Build Coastguard Worker         if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX || coderOutStreams != 1)
722*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_UNSUPPORTED;
723*f6dc9357SAndroid Build Coastguard Worker       }
724*f6dc9357SAndroid Build Coastguard Worker 
725*f6dc9357SAndroid Build Coastguard Worker       numInStreams += coderInStreams;
726*f6dc9357SAndroid Build Coastguard Worker 
727*f6dc9357SAndroid Build Coastguard Worker       if ((mainByte & 0x20) != 0)
728*f6dc9357SAndroid Build Coastguard Worker       {
729*f6dc9357SAndroid Build Coastguard Worker         UInt32 propsSize;
730*f6dc9357SAndroid Build Coastguard Worker         RINOK(SzReadNumber32(&sd, &propsSize))
731*f6dc9357SAndroid Build Coastguard Worker         if (propsSize > sd.Size)
732*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_ARCHIVE;
733*f6dc9357SAndroid Build Coastguard Worker         SKIP_DATA2(sd, propsSize)
734*f6dc9357SAndroid Build Coastguard Worker       }
735*f6dc9357SAndroid Build Coastguard Worker     }
736*f6dc9357SAndroid Build Coastguard Worker 
737*f6dc9357SAndroid Build Coastguard Worker     {
738*f6dc9357SAndroid Build Coastguard Worker       UInt32 indexOfMainStream = 0;
739*f6dc9357SAndroid Build Coastguard Worker       UInt32 numPackStreams = 1;
740*f6dc9357SAndroid Build Coastguard Worker 
741*f6dc9357SAndroid Build Coastguard Worker       if (numCoders != 1 || numInStreams != 1)
742*f6dc9357SAndroid Build Coastguard Worker       {
743*f6dc9357SAndroid Build Coastguard Worker         Byte streamUsed[k_Scan_NumCodersStreams_in_Folder_MAX];
744*f6dc9357SAndroid Build Coastguard Worker         Byte coderUsed[k_Scan_NumCoders_MAX];
745*f6dc9357SAndroid Build Coastguard Worker 
746*f6dc9357SAndroid Build Coastguard Worker         UInt32 i;
747*f6dc9357SAndroid Build Coastguard Worker         const UInt32 numBonds = numCoders - 1;
748*f6dc9357SAndroid Build Coastguard Worker         if (numInStreams < numBonds)
749*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_ARCHIVE;
750*f6dc9357SAndroid Build Coastguard Worker 
751*f6dc9357SAndroid Build Coastguard Worker         if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
752*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_UNSUPPORTED;
753*f6dc9357SAndroid Build Coastguard Worker 
754*f6dc9357SAndroid Build Coastguard Worker         for (i = 0; i < numInStreams; i++)
755*f6dc9357SAndroid Build Coastguard Worker           streamUsed[i] = False;
756*f6dc9357SAndroid Build Coastguard Worker         for (i = 0; i < numCoders; i++)
757*f6dc9357SAndroid Build Coastguard Worker           coderUsed[i] = False;
758*f6dc9357SAndroid Build Coastguard Worker 
759*f6dc9357SAndroid Build Coastguard Worker         for (i = 0; i < numBonds; i++)
760*f6dc9357SAndroid Build Coastguard Worker         {
761*f6dc9357SAndroid Build Coastguard Worker           UInt32 index;
762*f6dc9357SAndroid Build Coastguard Worker 
763*f6dc9357SAndroid Build Coastguard Worker           RINOK(SzReadNumber32(&sd, &index))
764*f6dc9357SAndroid Build Coastguard Worker           if (index >= numInStreams || streamUsed[index])
765*f6dc9357SAndroid Build Coastguard Worker             return SZ_ERROR_ARCHIVE;
766*f6dc9357SAndroid Build Coastguard Worker           streamUsed[index] = True;
767*f6dc9357SAndroid Build Coastguard Worker 
768*f6dc9357SAndroid Build Coastguard Worker           RINOK(SzReadNumber32(&sd, &index))
769*f6dc9357SAndroid Build Coastguard Worker           if (index >= numCoders || coderUsed[index])
770*f6dc9357SAndroid Build Coastguard Worker             return SZ_ERROR_ARCHIVE;
771*f6dc9357SAndroid Build Coastguard Worker           coderUsed[index] = True;
772*f6dc9357SAndroid Build Coastguard Worker         }
773*f6dc9357SAndroid Build Coastguard Worker 
774*f6dc9357SAndroid Build Coastguard Worker         numPackStreams = numInStreams - numBonds;
775*f6dc9357SAndroid Build Coastguard Worker 
776*f6dc9357SAndroid Build Coastguard Worker         if (numPackStreams != 1)
777*f6dc9357SAndroid Build Coastguard Worker           for (i = 0; i < numPackStreams; i++)
778*f6dc9357SAndroid Build Coastguard Worker           {
779*f6dc9357SAndroid Build Coastguard Worker             UInt32 index;
780*f6dc9357SAndroid Build Coastguard Worker             RINOK(SzReadNumber32(&sd, &index))
781*f6dc9357SAndroid Build Coastguard Worker             if (index >= numInStreams || streamUsed[index])
782*f6dc9357SAndroid Build Coastguard Worker               return SZ_ERROR_ARCHIVE;
783*f6dc9357SAndroid Build Coastguard Worker             streamUsed[index] = True;
784*f6dc9357SAndroid Build Coastguard Worker           }
785*f6dc9357SAndroid Build Coastguard Worker 
786*f6dc9357SAndroid Build Coastguard Worker         for (i = 0; i < numCoders; i++)
787*f6dc9357SAndroid Build Coastguard Worker           if (!coderUsed[i])
788*f6dc9357SAndroid Build Coastguard Worker           {
789*f6dc9357SAndroid Build Coastguard Worker             indexOfMainStream = i;
790*f6dc9357SAndroid Build Coastguard Worker             break;
791*f6dc9357SAndroid Build Coastguard Worker           }
792*f6dc9357SAndroid Build Coastguard Worker 
793*f6dc9357SAndroid Build Coastguard Worker         if (i == numCoders)
794*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_ARCHIVE;
795*f6dc9357SAndroid Build Coastguard Worker       }
796*f6dc9357SAndroid Build Coastguard Worker 
797*f6dc9357SAndroid Build Coastguard Worker       p->FoStartPackStreamIndex[fo] = packStreamIndex;
798*f6dc9357SAndroid Build Coastguard Worker       p->FoToCoderUnpackSizes[fo] = numCodersOutStreams;
799*f6dc9357SAndroid Build Coastguard Worker       p->FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
800*f6dc9357SAndroid Build Coastguard Worker       numCodersOutStreams += numCoders;
801*f6dc9357SAndroid Build Coastguard Worker       if (numCodersOutStreams < numCoders)
802*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_UNSUPPORTED;
803*f6dc9357SAndroid Build Coastguard Worker       if (numPackStreams > p->NumPackStreams - packStreamIndex)
804*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_ARCHIVE;
805*f6dc9357SAndroid Build Coastguard Worker       packStreamIndex += numPackStreams;
806*f6dc9357SAndroid Build Coastguard Worker     }
807*f6dc9357SAndroid Build Coastguard Worker   }
808*f6dc9357SAndroid Build Coastguard Worker 
809*f6dc9357SAndroid Build Coastguard Worker   p->FoToCoderUnpackSizes[fo] = numCodersOutStreams;
810*f6dc9357SAndroid Build Coastguard Worker 
811*f6dc9357SAndroid Build Coastguard Worker   {
812*f6dc9357SAndroid Build Coastguard Worker     const size_t dataSize = (size_t)(sd.Data - startBufPtr);
813*f6dc9357SAndroid Build Coastguard Worker     p->FoStartPackStreamIndex[fo] = packStreamIndex;
814*f6dc9357SAndroid Build Coastguard Worker     p->FoCodersOffsets[fo] = dataSize;
815*f6dc9357SAndroid Build Coastguard Worker     MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc)
816*f6dc9357SAndroid Build Coastguard Worker   }
817*f6dc9357SAndroid Build Coastguard Worker 
818*f6dc9357SAndroid Build Coastguard Worker   if (external != 0)
819*f6dc9357SAndroid Build Coastguard Worker   {
820*f6dc9357SAndroid Build Coastguard Worker     if (sd.Size != 0)
821*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_ARCHIVE;
822*f6dc9357SAndroid Build Coastguard Worker     sd = *sd2;
823*f6dc9357SAndroid Build Coastguard Worker   }
824*f6dc9357SAndroid Build Coastguard Worker 
825*f6dc9357SAndroid Build Coastguard Worker   RINOK(WaitId(&sd, k7zIdCodersUnpackSize))
826*f6dc9357SAndroid Build Coastguard Worker 
827*f6dc9357SAndroid Build Coastguard Worker   MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc)
828*f6dc9357SAndroid Build Coastguard Worker   {
829*f6dc9357SAndroid Build Coastguard Worker     UInt32 i;
830*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < numCodersOutStreams; i++)
831*f6dc9357SAndroid Build Coastguard Worker     {
832*f6dc9357SAndroid Build Coastguard Worker       RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i))
833*f6dc9357SAndroid Build Coastguard Worker     }
834*f6dc9357SAndroid Build Coastguard Worker   }
835*f6dc9357SAndroid Build Coastguard Worker 
836*f6dc9357SAndroid Build Coastguard Worker   for (;;)
837*f6dc9357SAndroid Build Coastguard Worker   {
838*f6dc9357SAndroid Build Coastguard Worker     UInt64 type;
839*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadID(&sd, &type))
840*f6dc9357SAndroid Build Coastguard Worker     if (type == k7zIdEnd)
841*f6dc9357SAndroid Build Coastguard Worker     {
842*f6dc9357SAndroid Build Coastguard Worker       *sd2 = sd;
843*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
844*f6dc9357SAndroid Build Coastguard Worker     }
845*f6dc9357SAndroid Build Coastguard Worker     if (type == k7zIdCRC)
846*f6dc9357SAndroid Build Coastguard Worker     {
847*f6dc9357SAndroid Build Coastguard Worker       RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc))
848*f6dc9357SAndroid Build Coastguard Worker       continue;
849*f6dc9357SAndroid Build Coastguard Worker     }
850*f6dc9357SAndroid Build Coastguard Worker     RINOK(SkipData(&sd))
851*f6dc9357SAndroid Build Coastguard Worker   }
852*f6dc9357SAndroid Build Coastguard Worker }
853*f6dc9357SAndroid Build Coastguard Worker 
854*f6dc9357SAndroid Build Coastguard Worker 
SzAr_GetFolderUnpackSize(const CSzAr * p,UInt32 folderIndex)855*f6dc9357SAndroid Build Coastguard Worker UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex)
856*f6dc9357SAndroid Build Coastguard Worker {
857*f6dc9357SAndroid Build Coastguard Worker   return p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex] + p->FoToMainUnpackSizeIndex[folderIndex]];
858*f6dc9357SAndroid Build Coastguard Worker }
859*f6dc9357SAndroid Build Coastguard Worker 
860*f6dc9357SAndroid Build Coastguard Worker 
861*f6dc9357SAndroid Build Coastguard Worker typedef struct
862*f6dc9357SAndroid Build Coastguard Worker {
863*f6dc9357SAndroid Build Coastguard Worker   UInt32 NumTotalSubStreams;
864*f6dc9357SAndroid Build Coastguard Worker   UInt32 NumSubDigests;
865*f6dc9357SAndroid Build Coastguard Worker   CSzData sdNumSubStreams;
866*f6dc9357SAndroid Build Coastguard Worker   CSzData sdSizes;
867*f6dc9357SAndroid Build Coastguard Worker   CSzData sdCRCs;
868*f6dc9357SAndroid Build Coastguard Worker } CSubStreamInfo;
869*f6dc9357SAndroid Build Coastguard Worker 
870*f6dc9357SAndroid Build Coastguard Worker 
ReadSubStreamsInfo(CSzAr * p,CSzData * sd,CSubStreamInfo * ssi)871*f6dc9357SAndroid Build Coastguard Worker static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi)
872*f6dc9357SAndroid Build Coastguard Worker {
873*f6dc9357SAndroid Build Coastguard Worker   UInt64 type = 0;
874*f6dc9357SAndroid Build Coastguard Worker   UInt32 numSubDigests = 0;
875*f6dc9357SAndroid Build Coastguard Worker   const UInt32 numFolders = p->NumFolders;
876*f6dc9357SAndroid Build Coastguard Worker   UInt32 numUnpackStreams = numFolders;
877*f6dc9357SAndroid Build Coastguard Worker   UInt32 numUnpackSizesInData = 0;
878*f6dc9357SAndroid Build Coastguard Worker 
879*f6dc9357SAndroid Build Coastguard Worker   for (;;)
880*f6dc9357SAndroid Build Coastguard Worker   {
881*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadID(sd, &type))
882*f6dc9357SAndroid Build Coastguard Worker     if (type == k7zIdNumUnpackStream)
883*f6dc9357SAndroid Build Coastguard Worker     {
884*f6dc9357SAndroid Build Coastguard Worker       UInt32 i;
885*f6dc9357SAndroid Build Coastguard Worker       ssi->sdNumSubStreams.Data = sd->Data;
886*f6dc9357SAndroid Build Coastguard Worker       numUnpackStreams = 0;
887*f6dc9357SAndroid Build Coastguard Worker       numSubDigests = 0;
888*f6dc9357SAndroid Build Coastguard Worker       for (i = 0; i < numFolders; i++)
889*f6dc9357SAndroid Build Coastguard Worker       {
890*f6dc9357SAndroid Build Coastguard Worker         UInt32 numStreams;
891*f6dc9357SAndroid Build Coastguard Worker         RINOK(SzReadNumber32(sd, &numStreams))
892*f6dc9357SAndroid Build Coastguard Worker         if (numUnpackStreams > numUnpackStreams + numStreams)
893*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_UNSUPPORTED;
894*f6dc9357SAndroid Build Coastguard Worker         numUnpackStreams += numStreams;
895*f6dc9357SAndroid Build Coastguard Worker         if (numStreams != 0)
896*f6dc9357SAndroid Build Coastguard Worker           numUnpackSizesInData += (numStreams - 1);
897*f6dc9357SAndroid Build Coastguard Worker         if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i))
898*f6dc9357SAndroid Build Coastguard Worker           numSubDigests += numStreams;
899*f6dc9357SAndroid Build Coastguard Worker       }
900*f6dc9357SAndroid Build Coastguard Worker       ssi->sdNumSubStreams.Size = (size_t)(sd->Data - ssi->sdNumSubStreams.Data);
901*f6dc9357SAndroid Build Coastguard Worker       continue;
902*f6dc9357SAndroid Build Coastguard Worker     }
903*f6dc9357SAndroid Build Coastguard Worker     if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd)
904*f6dc9357SAndroid Build Coastguard Worker       break;
905*f6dc9357SAndroid Build Coastguard Worker     RINOK(SkipData(sd))
906*f6dc9357SAndroid Build Coastguard Worker   }
907*f6dc9357SAndroid Build Coastguard Worker 
908*f6dc9357SAndroid Build Coastguard Worker   if (!ssi->sdNumSubStreams.Data)
909*f6dc9357SAndroid Build Coastguard Worker   {
910*f6dc9357SAndroid Build Coastguard Worker     numSubDigests = numFolders;
911*f6dc9357SAndroid Build Coastguard Worker     if (p->FolderCRCs.Defs)
912*f6dc9357SAndroid Build Coastguard Worker       numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders);
913*f6dc9357SAndroid Build Coastguard Worker   }
914*f6dc9357SAndroid Build Coastguard Worker 
915*f6dc9357SAndroid Build Coastguard Worker   ssi->NumTotalSubStreams = numUnpackStreams;
916*f6dc9357SAndroid Build Coastguard Worker   ssi->NumSubDigests = numSubDigests;
917*f6dc9357SAndroid Build Coastguard Worker 
918*f6dc9357SAndroid Build Coastguard Worker   if (type == k7zIdSize)
919*f6dc9357SAndroid Build Coastguard Worker   {
920*f6dc9357SAndroid Build Coastguard Worker     ssi->sdSizes.Data = sd->Data;
921*f6dc9357SAndroid Build Coastguard Worker     RINOK(SkipNumbers(sd, numUnpackSizesInData))
922*f6dc9357SAndroid Build Coastguard Worker     ssi->sdSizes.Size = (size_t)(sd->Data - ssi->sdSizes.Data);
923*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadID(sd, &type))
924*f6dc9357SAndroid Build Coastguard Worker   }
925*f6dc9357SAndroid Build Coastguard Worker 
926*f6dc9357SAndroid Build Coastguard Worker   for (;;)
927*f6dc9357SAndroid Build Coastguard Worker   {
928*f6dc9357SAndroid Build Coastguard Worker     if (type == k7zIdEnd)
929*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
930*f6dc9357SAndroid Build Coastguard Worker     if (type == k7zIdCRC)
931*f6dc9357SAndroid Build Coastguard Worker     {
932*f6dc9357SAndroid Build Coastguard Worker       ssi->sdCRCs.Data = sd->Data;
933*f6dc9357SAndroid Build Coastguard Worker       RINOK(SkipBitUi32s(sd, numSubDigests))
934*f6dc9357SAndroid Build Coastguard Worker       ssi->sdCRCs.Size = (size_t)(sd->Data - ssi->sdCRCs.Data);
935*f6dc9357SAndroid Build Coastguard Worker     }
936*f6dc9357SAndroid Build Coastguard Worker     else
937*f6dc9357SAndroid Build Coastguard Worker     {
938*f6dc9357SAndroid Build Coastguard Worker       RINOK(SkipData(sd))
939*f6dc9357SAndroid Build Coastguard Worker     }
940*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadID(sd, &type))
941*f6dc9357SAndroid Build Coastguard Worker   }
942*f6dc9357SAndroid Build Coastguard Worker }
943*f6dc9357SAndroid Build Coastguard Worker 
SzReadStreamsInfo(CSzAr * p,CSzData * sd,UInt32 numFoldersMax,const CBuf * tempBufs,UInt32 numTempBufs,UInt64 * dataOffset,CSubStreamInfo * ssi,ISzAllocPtr alloc)944*f6dc9357SAndroid Build Coastguard Worker static SRes SzReadStreamsInfo(CSzAr *p,
945*f6dc9357SAndroid Build Coastguard Worker     CSzData *sd,
946*f6dc9357SAndroid Build Coastguard Worker     UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs,
947*f6dc9357SAndroid Build Coastguard Worker     UInt64 *dataOffset,
948*f6dc9357SAndroid Build Coastguard Worker     CSubStreamInfo *ssi,
949*f6dc9357SAndroid Build Coastguard Worker     ISzAllocPtr alloc)
950*f6dc9357SAndroid Build Coastguard Worker {
951*f6dc9357SAndroid Build Coastguard Worker   UInt64 type;
952*f6dc9357SAndroid Build Coastguard Worker 
953*f6dc9357SAndroid Build Coastguard Worker   SzData_CLEAR(&ssi->sdSizes)
954*f6dc9357SAndroid Build Coastguard Worker   SzData_CLEAR(&ssi->sdCRCs)
955*f6dc9357SAndroid Build Coastguard Worker   SzData_CLEAR(&ssi->sdNumSubStreams)
956*f6dc9357SAndroid Build Coastguard Worker 
957*f6dc9357SAndroid Build Coastguard Worker   *dataOffset = 0;
958*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadID(sd, &type))
959*f6dc9357SAndroid Build Coastguard Worker   if (type == k7zIdPackInfo)
960*f6dc9357SAndroid Build Coastguard Worker   {
961*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadNumber(sd, dataOffset))
962*f6dc9357SAndroid Build Coastguard Worker     if (*dataOffset > p->RangeLimit)
963*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_ARCHIVE;
964*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadPackInfo(p, sd, alloc))
965*f6dc9357SAndroid Build Coastguard Worker     if (p->PackPositions[p->NumPackStreams] > p->RangeLimit - *dataOffset)
966*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_ARCHIVE;
967*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadID(sd, &type))
968*f6dc9357SAndroid Build Coastguard Worker   }
969*f6dc9357SAndroid Build Coastguard Worker   if (type == k7zIdUnpackInfo)
970*f6dc9357SAndroid Build Coastguard Worker   {
971*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc))
972*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadID(sd, &type))
973*f6dc9357SAndroid Build Coastguard Worker   }
974*f6dc9357SAndroid Build Coastguard Worker   if (type == k7zIdSubStreamsInfo)
975*f6dc9357SAndroid Build Coastguard Worker   {
976*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadSubStreamsInfo(p, sd, ssi))
977*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadID(sd, &type))
978*f6dc9357SAndroid Build Coastguard Worker   }
979*f6dc9357SAndroid Build Coastguard Worker   else
980*f6dc9357SAndroid Build Coastguard Worker   {
981*f6dc9357SAndroid Build Coastguard Worker     ssi->NumTotalSubStreams = p->NumFolders;
982*f6dc9357SAndroid Build Coastguard Worker     // ssi->NumSubDigests = 0;
983*f6dc9357SAndroid Build Coastguard Worker   }
984*f6dc9357SAndroid Build Coastguard Worker 
985*f6dc9357SAndroid Build Coastguard Worker   return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED);
986*f6dc9357SAndroid Build Coastguard Worker }
987*f6dc9357SAndroid Build Coastguard Worker 
SzReadAndDecodePackedStreams(ILookInStreamPtr inStream,CSzData * sd,CBuf * tempBufs,UInt32 numFoldersMax,UInt64 baseOffset,CSzAr * p,ISzAllocPtr allocTemp)988*f6dc9357SAndroid Build Coastguard Worker static SRes SzReadAndDecodePackedStreams(
989*f6dc9357SAndroid Build Coastguard Worker     ILookInStreamPtr inStream,
990*f6dc9357SAndroid Build Coastguard Worker     CSzData *sd,
991*f6dc9357SAndroid Build Coastguard Worker     CBuf *tempBufs,
992*f6dc9357SAndroid Build Coastguard Worker     UInt32 numFoldersMax,
993*f6dc9357SAndroid Build Coastguard Worker     UInt64 baseOffset,
994*f6dc9357SAndroid Build Coastguard Worker     CSzAr *p,
995*f6dc9357SAndroid Build Coastguard Worker     ISzAllocPtr allocTemp)
996*f6dc9357SAndroid Build Coastguard Worker {
997*f6dc9357SAndroid Build Coastguard Worker   UInt64 dataStartPos;
998*f6dc9357SAndroid Build Coastguard Worker   UInt32 fo;
999*f6dc9357SAndroid Build Coastguard Worker   CSubStreamInfo ssi;
1000*f6dc9357SAndroid Build Coastguard Worker 
1001*f6dc9357SAndroid Build Coastguard Worker   RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp))
1002*f6dc9357SAndroid Build Coastguard Worker 
1003*f6dc9357SAndroid Build Coastguard Worker   dataStartPos += baseOffset;
1004*f6dc9357SAndroid Build Coastguard Worker   if (p->NumFolders == 0)
1005*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_ARCHIVE;
1006*f6dc9357SAndroid Build Coastguard Worker 
1007*f6dc9357SAndroid Build Coastguard Worker   for (fo = 0; fo < p->NumFolders; fo++)
1008*f6dc9357SAndroid Build Coastguard Worker     Buf_Init(tempBufs + fo);
1009*f6dc9357SAndroid Build Coastguard Worker 
1010*f6dc9357SAndroid Build Coastguard Worker   for (fo = 0; fo < p->NumFolders; fo++)
1011*f6dc9357SAndroid Build Coastguard Worker   {
1012*f6dc9357SAndroid Build Coastguard Worker     CBuf *tempBuf = tempBufs + fo;
1013*f6dc9357SAndroid Build Coastguard Worker     const UInt64 unpackSize = SzAr_GetFolderUnpackSize(p, fo);
1014*f6dc9357SAndroid Build Coastguard Worker     if ((size_t)unpackSize != unpackSize)
1015*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_MEM;
1016*f6dc9357SAndroid Build Coastguard Worker     if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp))
1017*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_MEM;
1018*f6dc9357SAndroid Build Coastguard Worker   }
1019*f6dc9357SAndroid Build Coastguard Worker 
1020*f6dc9357SAndroid Build Coastguard Worker   for (fo = 0; fo < p->NumFolders; fo++)
1021*f6dc9357SAndroid Build Coastguard Worker   {
1022*f6dc9357SAndroid Build Coastguard Worker     const CBuf *tempBuf = tempBufs + fo;
1023*f6dc9357SAndroid Build Coastguard Worker     RINOK(LookInStream_SeekTo(inStream, dataStartPos))
1024*f6dc9357SAndroid Build Coastguard Worker     RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp))
1025*f6dc9357SAndroid Build Coastguard Worker   }
1026*f6dc9357SAndroid Build Coastguard Worker 
1027*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
1028*f6dc9357SAndroid Build Coastguard Worker }
1029*f6dc9357SAndroid Build Coastguard Worker 
SzReadFileNames(const Byte * data,size_t size,UInt32 numFiles,size_t * offsets)1030*f6dc9357SAndroid Build Coastguard Worker static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets)
1031*f6dc9357SAndroid Build Coastguard Worker {
1032*f6dc9357SAndroid Build Coastguard Worker   size_t pos = 0;
1033*f6dc9357SAndroid Build Coastguard Worker   *offsets++ = 0;
1034*f6dc9357SAndroid Build Coastguard Worker   if (numFiles == 0)
1035*f6dc9357SAndroid Build Coastguard Worker     return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE;
1036*f6dc9357SAndroid Build Coastguard Worker   if (size < 2)
1037*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_ARCHIVE;
1038*f6dc9357SAndroid Build Coastguard Worker   if (data[size - 2] != 0 || data[size - 1] != 0)
1039*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_ARCHIVE;
1040*f6dc9357SAndroid Build Coastguard Worker   do
1041*f6dc9357SAndroid Build Coastguard Worker   {
1042*f6dc9357SAndroid Build Coastguard Worker     const Byte *p;
1043*f6dc9357SAndroid Build Coastguard Worker     if (pos == size)
1044*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_ARCHIVE;
1045*f6dc9357SAndroid Build Coastguard Worker     for (p = data + pos;
1046*f6dc9357SAndroid Build Coastguard Worker       #ifdef _WIN32
1047*f6dc9357SAndroid Build Coastguard Worker       *(const UInt16 *)(const void *)p != 0
1048*f6dc9357SAndroid Build Coastguard Worker       #else
1049*f6dc9357SAndroid Build Coastguard Worker       p[0] != 0 || p[1] != 0
1050*f6dc9357SAndroid Build Coastguard Worker       #endif
1051*f6dc9357SAndroid Build Coastguard Worker       ; p += 2);
1052*f6dc9357SAndroid Build Coastguard Worker     pos = (size_t)(p - data) + 2;
1053*f6dc9357SAndroid Build Coastguard Worker     *offsets++ = (pos >> 1);
1054*f6dc9357SAndroid Build Coastguard Worker   }
1055*f6dc9357SAndroid Build Coastguard Worker   while (--numFiles);
1056*f6dc9357SAndroid Build Coastguard Worker   return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
1057*f6dc9357SAndroid Build Coastguard Worker }
1058*f6dc9357SAndroid Build Coastguard Worker 
ReadTime(CSzBitUi64s * p,UInt32 num,CSzData * sd2,const CBuf * tempBufs,UInt32 numTempBufs,ISzAllocPtr alloc)1059*f6dc9357SAndroid Build Coastguard Worker static Z7_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,
1060*f6dc9357SAndroid Build Coastguard Worker     CSzData *sd2,
1061*f6dc9357SAndroid Build Coastguard Worker     const CBuf *tempBufs, UInt32 numTempBufs,
1062*f6dc9357SAndroid Build Coastguard Worker     ISzAllocPtr alloc)
1063*f6dc9357SAndroid Build Coastguard Worker {
1064*f6dc9357SAndroid Build Coastguard Worker   CSzData sd;
1065*f6dc9357SAndroid Build Coastguard Worker   UInt32 i;
1066*f6dc9357SAndroid Build Coastguard Worker   CNtfsFileTime *vals;
1067*f6dc9357SAndroid Build Coastguard Worker   Byte *defs;
1068*f6dc9357SAndroid Build Coastguard Worker   Byte external;
1069*f6dc9357SAndroid Build Coastguard Worker 
1070*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadBitVector(sd2, num, &p->Defs, alloc))
1071*f6dc9357SAndroid Build Coastguard Worker 
1072*f6dc9357SAndroid Build Coastguard Worker   SZ_READ_BYTE_SD(sd2, external)
1073*f6dc9357SAndroid Build Coastguard Worker   if (external == 0)
1074*f6dc9357SAndroid Build Coastguard Worker     sd = *sd2;
1075*f6dc9357SAndroid Build Coastguard Worker   else
1076*f6dc9357SAndroid Build Coastguard Worker   {
1077*f6dc9357SAndroid Build Coastguard Worker     UInt32 index;
1078*f6dc9357SAndroid Build Coastguard Worker     RINOK(SzReadNumber32(sd2, &index))
1079*f6dc9357SAndroid Build Coastguard Worker     if (index >= numTempBufs)
1080*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_ARCHIVE;
1081*f6dc9357SAndroid Build Coastguard Worker     sd.Data = tempBufs[index].data;
1082*f6dc9357SAndroid Build Coastguard Worker     sd.Size = tempBufs[index].size;
1083*f6dc9357SAndroid Build Coastguard Worker   }
1084*f6dc9357SAndroid Build Coastguard Worker 
1085*f6dc9357SAndroid Build Coastguard Worker   MY_ALLOC_ZE(CNtfsFileTime, p->Vals, num, alloc)
1086*f6dc9357SAndroid Build Coastguard Worker   vals = p->Vals;
1087*f6dc9357SAndroid Build Coastguard Worker   defs = p->Defs;
1088*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < num; i++)
1089*f6dc9357SAndroid Build Coastguard Worker     if (SzBitArray_Check(defs, i))
1090*f6dc9357SAndroid Build Coastguard Worker     {
1091*f6dc9357SAndroid Build Coastguard Worker       if (sd.Size < 8)
1092*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_ARCHIVE;
1093*f6dc9357SAndroid Build Coastguard Worker       vals[i].Low = GetUi32(sd.Data);
1094*f6dc9357SAndroid Build Coastguard Worker       vals[i].High = GetUi32(sd.Data + 4);
1095*f6dc9357SAndroid Build Coastguard Worker       SKIP_DATA2(sd, 8)
1096*f6dc9357SAndroid Build Coastguard Worker     }
1097*f6dc9357SAndroid Build Coastguard Worker     else
1098*f6dc9357SAndroid Build Coastguard Worker       vals[i].High = vals[i].Low = 0;
1099*f6dc9357SAndroid Build Coastguard Worker 
1100*f6dc9357SAndroid Build Coastguard Worker   if (external == 0)
1101*f6dc9357SAndroid Build Coastguard Worker     *sd2 = sd;
1102*f6dc9357SAndroid Build Coastguard Worker 
1103*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
1104*f6dc9357SAndroid Build Coastguard Worker }
1105*f6dc9357SAndroid Build Coastguard Worker 
1106*f6dc9357SAndroid Build Coastguard Worker 
1107*f6dc9357SAndroid Build Coastguard Worker #define NUM_ADDITIONAL_STREAMS_MAX 8
1108*f6dc9357SAndroid Build Coastguard Worker 
1109*f6dc9357SAndroid Build Coastguard Worker 
SzReadHeader2(CSzArEx * p,CSzData * sd,ILookInStreamPtr inStream,CBuf * tempBufs,UInt32 * numTempBufs,ISzAllocPtr allocMain,ISzAllocPtr allocTemp)1110*f6dc9357SAndroid Build Coastguard Worker static SRes SzReadHeader2(
1111*f6dc9357SAndroid Build Coastguard Worker     CSzArEx *p,   /* allocMain */
1112*f6dc9357SAndroid Build Coastguard Worker     CSzData *sd,
1113*f6dc9357SAndroid Build Coastguard Worker     ILookInStreamPtr inStream,
1114*f6dc9357SAndroid Build Coastguard Worker     CBuf *tempBufs, UInt32 *numTempBufs,
1115*f6dc9357SAndroid Build Coastguard Worker     ISzAllocPtr allocMain,
1116*f6dc9357SAndroid Build Coastguard Worker     ISzAllocPtr allocTemp
1117*f6dc9357SAndroid Build Coastguard Worker     )
1118*f6dc9357SAndroid Build Coastguard Worker {
1119*f6dc9357SAndroid Build Coastguard Worker   CSubStreamInfo ssi;
1120*f6dc9357SAndroid Build Coastguard Worker 
1121*f6dc9357SAndroid Build Coastguard Worker {
1122*f6dc9357SAndroid Build Coastguard Worker   UInt64 type;
1123*f6dc9357SAndroid Build Coastguard Worker 
1124*f6dc9357SAndroid Build Coastguard Worker   SzData_CLEAR(&ssi.sdSizes)
1125*f6dc9357SAndroid Build Coastguard Worker   SzData_CLEAR(&ssi.sdCRCs)
1126*f6dc9357SAndroid Build Coastguard Worker   SzData_CLEAR(&ssi.sdNumSubStreams)
1127*f6dc9357SAndroid Build Coastguard Worker 
1128*f6dc9357SAndroid Build Coastguard Worker   ssi.NumSubDigests = 0;
1129*f6dc9357SAndroid Build Coastguard Worker   ssi.NumTotalSubStreams = 0;
1130*f6dc9357SAndroid Build Coastguard Worker 
1131*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadID(sd, &type))
1132*f6dc9357SAndroid Build Coastguard Worker 
1133*f6dc9357SAndroid Build Coastguard Worker   if (type == k7zIdArchiveProperties)
1134*f6dc9357SAndroid Build Coastguard Worker   {
1135*f6dc9357SAndroid Build Coastguard Worker     for (;;)
1136*f6dc9357SAndroid Build Coastguard Worker     {
1137*f6dc9357SAndroid Build Coastguard Worker       UInt64 type2;
1138*f6dc9357SAndroid Build Coastguard Worker       RINOK(ReadID(sd, &type2))
1139*f6dc9357SAndroid Build Coastguard Worker       if (type2 == k7zIdEnd)
1140*f6dc9357SAndroid Build Coastguard Worker         break;
1141*f6dc9357SAndroid Build Coastguard Worker       RINOK(SkipData(sd))
1142*f6dc9357SAndroid Build Coastguard Worker     }
1143*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadID(sd, &type))
1144*f6dc9357SAndroid Build Coastguard Worker   }
1145*f6dc9357SAndroid Build Coastguard Worker 
1146*f6dc9357SAndroid Build Coastguard Worker   if (type == k7zIdAdditionalStreamsInfo)
1147*f6dc9357SAndroid Build Coastguard Worker   {
1148*f6dc9357SAndroid Build Coastguard Worker     CSzAr tempAr;
1149*f6dc9357SAndroid Build Coastguard Worker     SRes res;
1150*f6dc9357SAndroid Build Coastguard Worker 
1151*f6dc9357SAndroid Build Coastguard Worker     SzAr_Init(&tempAr);
1152*f6dc9357SAndroid Build Coastguard Worker     tempAr.RangeLimit = p->db.RangeLimit;
1153*f6dc9357SAndroid Build Coastguard Worker 
1154*f6dc9357SAndroid Build Coastguard Worker     res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX,
1155*f6dc9357SAndroid Build Coastguard Worker         p->startPosAfterHeader, &tempAr, allocTemp);
1156*f6dc9357SAndroid Build Coastguard Worker     *numTempBufs = tempAr.NumFolders;
1157*f6dc9357SAndroid Build Coastguard Worker     SzAr_Free(&tempAr, allocTemp);
1158*f6dc9357SAndroid Build Coastguard Worker 
1159*f6dc9357SAndroid Build Coastguard Worker     if (res != SZ_OK)
1160*f6dc9357SAndroid Build Coastguard Worker       return res;
1161*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadID(sd, &type))
1162*f6dc9357SAndroid Build Coastguard Worker   }
1163*f6dc9357SAndroid Build Coastguard Worker 
1164*f6dc9357SAndroid Build Coastguard Worker   if (type == k7zIdMainStreamsInfo)
1165*f6dc9357SAndroid Build Coastguard Worker   {
1166*f6dc9357SAndroid Build Coastguard Worker     RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs,
1167*f6dc9357SAndroid Build Coastguard Worker         &p->dataPos, &ssi, allocMain))
1168*f6dc9357SAndroid Build Coastguard Worker     p->dataPos += p->startPosAfterHeader;
1169*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadID(sd, &type))
1170*f6dc9357SAndroid Build Coastguard Worker   }
1171*f6dc9357SAndroid Build Coastguard Worker 
1172*f6dc9357SAndroid Build Coastguard Worker   if (type == k7zIdEnd)
1173*f6dc9357SAndroid Build Coastguard Worker   {
1174*f6dc9357SAndroid Build Coastguard Worker     return SZ_OK;
1175*f6dc9357SAndroid Build Coastguard Worker   }
1176*f6dc9357SAndroid Build Coastguard Worker 
1177*f6dc9357SAndroid Build Coastguard Worker   if (type != k7zIdFilesInfo)
1178*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_ARCHIVE;
1179*f6dc9357SAndroid Build Coastguard Worker }
1180*f6dc9357SAndroid Build Coastguard Worker 
1181*f6dc9357SAndroid Build Coastguard Worker {
1182*f6dc9357SAndroid Build Coastguard Worker   UInt32 numFiles = 0;
1183*f6dc9357SAndroid Build Coastguard Worker   UInt32 numEmptyStreams = 0;
1184*f6dc9357SAndroid Build Coastguard Worker   const Byte *emptyStreams = NULL;
1185*f6dc9357SAndroid Build Coastguard Worker   const Byte *emptyFiles = NULL;
1186*f6dc9357SAndroid Build Coastguard Worker 
1187*f6dc9357SAndroid Build Coastguard Worker   RINOK(SzReadNumber32(sd, &numFiles))
1188*f6dc9357SAndroid Build Coastguard Worker   p->NumFiles = numFiles;
1189*f6dc9357SAndroid Build Coastguard Worker 
1190*f6dc9357SAndroid Build Coastguard Worker   for (;;)
1191*f6dc9357SAndroid Build Coastguard Worker   {
1192*f6dc9357SAndroid Build Coastguard Worker     UInt64 type;
1193*f6dc9357SAndroid Build Coastguard Worker     UInt64 size;
1194*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadID(sd, &type))
1195*f6dc9357SAndroid Build Coastguard Worker     if (type == k7zIdEnd)
1196*f6dc9357SAndroid Build Coastguard Worker       break;
1197*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadNumber(sd, &size))
1198*f6dc9357SAndroid Build Coastguard Worker     if (size > sd->Size)
1199*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_ARCHIVE;
1200*f6dc9357SAndroid Build Coastguard Worker 
1201*f6dc9357SAndroid Build Coastguard Worker     if (type >= ((UInt32)1 << 8))
1202*f6dc9357SAndroid Build Coastguard Worker     {
1203*f6dc9357SAndroid Build Coastguard Worker       SKIP_DATA(sd, size)
1204*f6dc9357SAndroid Build Coastguard Worker     }
1205*f6dc9357SAndroid Build Coastguard Worker     else switch ((unsigned)type)
1206*f6dc9357SAndroid Build Coastguard Worker     {
1207*f6dc9357SAndroid Build Coastguard Worker       case k7zIdName:
1208*f6dc9357SAndroid Build Coastguard Worker       {
1209*f6dc9357SAndroid Build Coastguard Worker         size_t namesSize;
1210*f6dc9357SAndroid Build Coastguard Worker         const Byte *namesData;
1211*f6dc9357SAndroid Build Coastguard Worker         Byte external;
1212*f6dc9357SAndroid Build Coastguard Worker 
1213*f6dc9357SAndroid Build Coastguard Worker         SZ_READ_BYTE(external)
1214*f6dc9357SAndroid Build Coastguard Worker         if (external == 0)
1215*f6dc9357SAndroid Build Coastguard Worker         {
1216*f6dc9357SAndroid Build Coastguard Worker           namesSize = (size_t)size - 1;
1217*f6dc9357SAndroid Build Coastguard Worker           namesData = sd->Data;
1218*f6dc9357SAndroid Build Coastguard Worker         }
1219*f6dc9357SAndroid Build Coastguard Worker         else
1220*f6dc9357SAndroid Build Coastguard Worker         {
1221*f6dc9357SAndroid Build Coastguard Worker           UInt32 index;
1222*f6dc9357SAndroid Build Coastguard Worker           RINOK(SzReadNumber32(sd, &index))
1223*f6dc9357SAndroid Build Coastguard Worker           if (index >= *numTempBufs)
1224*f6dc9357SAndroid Build Coastguard Worker             return SZ_ERROR_ARCHIVE;
1225*f6dc9357SAndroid Build Coastguard Worker           namesData = (tempBufs)[index].data;
1226*f6dc9357SAndroid Build Coastguard Worker           namesSize = (tempBufs)[index].size;
1227*f6dc9357SAndroid Build Coastguard Worker         }
1228*f6dc9357SAndroid Build Coastguard Worker 
1229*f6dc9357SAndroid Build Coastguard Worker         if ((namesSize & 1) != 0)
1230*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_ARCHIVE;
1231*f6dc9357SAndroid Build Coastguard Worker         MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain)
1232*f6dc9357SAndroid Build Coastguard Worker         MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain)
1233*f6dc9357SAndroid Build Coastguard Worker         RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets))
1234*f6dc9357SAndroid Build Coastguard Worker         if (external == 0)
1235*f6dc9357SAndroid Build Coastguard Worker         {
1236*f6dc9357SAndroid Build Coastguard Worker           SKIP_DATA(sd, namesSize)
1237*f6dc9357SAndroid Build Coastguard Worker         }
1238*f6dc9357SAndroid Build Coastguard Worker         break;
1239*f6dc9357SAndroid Build Coastguard Worker       }
1240*f6dc9357SAndroid Build Coastguard Worker       case k7zIdEmptyStream:
1241*f6dc9357SAndroid Build Coastguard Worker       {
1242*f6dc9357SAndroid Build Coastguard Worker         RINOK(RememberBitVector(sd, numFiles, &emptyStreams))
1243*f6dc9357SAndroid Build Coastguard Worker         numEmptyStreams = CountDefinedBits(emptyStreams, numFiles);
1244*f6dc9357SAndroid Build Coastguard Worker         emptyFiles = NULL;
1245*f6dc9357SAndroid Build Coastguard Worker         break;
1246*f6dc9357SAndroid Build Coastguard Worker       }
1247*f6dc9357SAndroid Build Coastguard Worker       case k7zIdEmptyFile:
1248*f6dc9357SAndroid Build Coastguard Worker       {
1249*f6dc9357SAndroid Build Coastguard Worker         RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles))
1250*f6dc9357SAndroid Build Coastguard Worker         break;
1251*f6dc9357SAndroid Build Coastguard Worker       }
1252*f6dc9357SAndroid Build Coastguard Worker       case k7zIdWinAttrib:
1253*f6dc9357SAndroid Build Coastguard Worker       {
1254*f6dc9357SAndroid Build Coastguard Worker         Byte external;
1255*f6dc9357SAndroid Build Coastguard Worker         CSzData sdSwitch;
1256*f6dc9357SAndroid Build Coastguard Worker         CSzData *sdPtr;
1257*f6dc9357SAndroid Build Coastguard Worker         SzBitUi32s_Free(&p->Attribs, allocMain);
1258*f6dc9357SAndroid Build Coastguard Worker         RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain))
1259*f6dc9357SAndroid Build Coastguard Worker 
1260*f6dc9357SAndroid Build Coastguard Worker         SZ_READ_BYTE(external)
1261*f6dc9357SAndroid Build Coastguard Worker         if (external == 0)
1262*f6dc9357SAndroid Build Coastguard Worker           sdPtr = sd;
1263*f6dc9357SAndroid Build Coastguard Worker         else
1264*f6dc9357SAndroid Build Coastguard Worker         {
1265*f6dc9357SAndroid Build Coastguard Worker           UInt32 index;
1266*f6dc9357SAndroid Build Coastguard Worker           RINOK(SzReadNumber32(sd, &index))
1267*f6dc9357SAndroid Build Coastguard Worker           if (index >= *numTempBufs)
1268*f6dc9357SAndroid Build Coastguard Worker             return SZ_ERROR_ARCHIVE;
1269*f6dc9357SAndroid Build Coastguard Worker           sdSwitch.Data = (tempBufs)[index].data;
1270*f6dc9357SAndroid Build Coastguard Worker           sdSwitch.Size = (tempBufs)[index].size;
1271*f6dc9357SAndroid Build Coastguard Worker           sdPtr = &sdSwitch;
1272*f6dc9357SAndroid Build Coastguard Worker         }
1273*f6dc9357SAndroid Build Coastguard Worker         RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain))
1274*f6dc9357SAndroid Build Coastguard Worker         break;
1275*f6dc9357SAndroid Build Coastguard Worker       }
1276*f6dc9357SAndroid Build Coastguard Worker       /*
1277*f6dc9357SAndroid Build Coastguard Worker       case k7zParent:
1278*f6dc9357SAndroid Build Coastguard Worker       {
1279*f6dc9357SAndroid Build Coastguard Worker         SzBitUi32s_Free(&p->Parents, allocMain);
1280*f6dc9357SAndroid Build Coastguard Worker         RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain));
1281*f6dc9357SAndroid Build Coastguard Worker         RINOK(SzReadSwitch(sd));
1282*f6dc9357SAndroid Build Coastguard Worker         RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain));
1283*f6dc9357SAndroid Build Coastguard Worker         break;
1284*f6dc9357SAndroid Build Coastguard Worker       }
1285*f6dc9357SAndroid Build Coastguard Worker       */
1286*f6dc9357SAndroid Build Coastguard Worker       case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)) break;
1287*f6dc9357SAndroid Build Coastguard Worker       case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)) break;
1288*f6dc9357SAndroid Build Coastguard Worker       default:
1289*f6dc9357SAndroid Build Coastguard Worker       {
1290*f6dc9357SAndroid Build Coastguard Worker         SKIP_DATA(sd, size)
1291*f6dc9357SAndroid Build Coastguard Worker       }
1292*f6dc9357SAndroid Build Coastguard Worker     }
1293*f6dc9357SAndroid Build Coastguard Worker   }
1294*f6dc9357SAndroid Build Coastguard Worker 
1295*f6dc9357SAndroid Build Coastguard Worker   if (numFiles - numEmptyStreams != ssi.NumTotalSubStreams)
1296*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_ARCHIVE;
1297*f6dc9357SAndroid Build Coastguard Worker 
1298*f6dc9357SAndroid Build Coastguard Worker   for (;;)
1299*f6dc9357SAndroid Build Coastguard Worker   {
1300*f6dc9357SAndroid Build Coastguard Worker     UInt64 type;
1301*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadID(sd, &type))
1302*f6dc9357SAndroid Build Coastguard Worker     if (type == k7zIdEnd)
1303*f6dc9357SAndroid Build Coastguard Worker       break;
1304*f6dc9357SAndroid Build Coastguard Worker     RINOK(SkipData(sd))
1305*f6dc9357SAndroid Build Coastguard Worker   }
1306*f6dc9357SAndroid Build Coastguard Worker 
1307*f6dc9357SAndroid Build Coastguard Worker   {
1308*f6dc9357SAndroid Build Coastguard Worker     UInt32 i;
1309*f6dc9357SAndroid Build Coastguard Worker     UInt32 emptyFileIndex = 0;
1310*f6dc9357SAndroid Build Coastguard Worker     UInt32 folderIndex = 0;
1311*f6dc9357SAndroid Build Coastguard Worker     UInt32 remSubStreams = 0;
1312*f6dc9357SAndroid Build Coastguard Worker     UInt32 numSubStreams = 0;
1313*f6dc9357SAndroid Build Coastguard Worker     UInt64 unpackPos = 0;
1314*f6dc9357SAndroid Build Coastguard Worker     const Byte *digestsDefs = NULL;
1315*f6dc9357SAndroid Build Coastguard Worker     const Byte *digestsVals = NULL;
1316*f6dc9357SAndroid Build Coastguard Worker     UInt32 digestIndex = 0;
1317*f6dc9357SAndroid Build Coastguard Worker     Byte isDirMask = 0;
1318*f6dc9357SAndroid Build Coastguard Worker     Byte crcMask = 0;
1319*f6dc9357SAndroid Build Coastguard Worker     Byte mask = 0x80;
1320*f6dc9357SAndroid Build Coastguard Worker 
1321*f6dc9357SAndroid Build Coastguard Worker     MY_ALLOC(UInt32, p->FolderToFile, p->db.NumFolders + 1, allocMain)
1322*f6dc9357SAndroid Build Coastguard Worker     MY_ALLOC_ZE(UInt32, p->FileToFolder, p->NumFiles, allocMain)
1323*f6dc9357SAndroid Build Coastguard Worker     MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain)
1324*f6dc9357SAndroid Build Coastguard Worker     MY_ALLOC_ZE(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain)
1325*f6dc9357SAndroid Build Coastguard Worker 
1326*f6dc9357SAndroid Build Coastguard Worker     RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain))
1327*f6dc9357SAndroid Build Coastguard Worker 
1328*f6dc9357SAndroid Build Coastguard Worker     if (ssi.sdCRCs.Size != 0)
1329*f6dc9357SAndroid Build Coastguard Worker     {
1330*f6dc9357SAndroid Build Coastguard Worker       Byte allDigestsDefined = 0;
1331*f6dc9357SAndroid Build Coastguard Worker       SZ_READ_BYTE_SD_NOCHECK(&ssi.sdCRCs, allDigestsDefined)
1332*f6dc9357SAndroid Build Coastguard Worker       if (allDigestsDefined)
1333*f6dc9357SAndroid Build Coastguard Worker         digestsVals = ssi.sdCRCs.Data;
1334*f6dc9357SAndroid Build Coastguard Worker       else
1335*f6dc9357SAndroid Build Coastguard Worker       {
1336*f6dc9357SAndroid Build Coastguard Worker         const size_t numBytes = (ssi.NumSubDigests + 7) >> 3;
1337*f6dc9357SAndroid Build Coastguard Worker         digestsDefs = ssi.sdCRCs.Data;
1338*f6dc9357SAndroid Build Coastguard Worker         digestsVals = digestsDefs + numBytes;
1339*f6dc9357SAndroid Build Coastguard Worker       }
1340*f6dc9357SAndroid Build Coastguard Worker     }
1341*f6dc9357SAndroid Build Coastguard Worker 
1342*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < numFiles; i++, mask >>= 1)
1343*f6dc9357SAndroid Build Coastguard Worker     {
1344*f6dc9357SAndroid Build Coastguard Worker       if (mask == 0)
1345*f6dc9357SAndroid Build Coastguard Worker       {
1346*f6dc9357SAndroid Build Coastguard Worker         const UInt32 byteIndex = (i - 1) >> 3;
1347*f6dc9357SAndroid Build Coastguard Worker         p->IsDirs[byteIndex] = isDirMask;
1348*f6dc9357SAndroid Build Coastguard Worker         p->CRCs.Defs[byteIndex] = crcMask;
1349*f6dc9357SAndroid Build Coastguard Worker         isDirMask = 0;
1350*f6dc9357SAndroid Build Coastguard Worker         crcMask = 0;
1351*f6dc9357SAndroid Build Coastguard Worker         mask = 0x80;
1352*f6dc9357SAndroid Build Coastguard Worker       }
1353*f6dc9357SAndroid Build Coastguard Worker 
1354*f6dc9357SAndroid Build Coastguard Worker       p->UnpackPositions[i] = unpackPos;
1355*f6dc9357SAndroid Build Coastguard Worker       p->CRCs.Vals[i] = 0;
1356*f6dc9357SAndroid Build Coastguard Worker 
1357*f6dc9357SAndroid Build Coastguard Worker       if (emptyStreams && SzBitArray_Check(emptyStreams, i))
1358*f6dc9357SAndroid Build Coastguard Worker       {
1359*f6dc9357SAndroid Build Coastguard Worker         if (emptyFiles)
1360*f6dc9357SAndroid Build Coastguard Worker         {
1361*f6dc9357SAndroid Build Coastguard Worker           if (!SzBitArray_Check(emptyFiles, emptyFileIndex))
1362*f6dc9357SAndroid Build Coastguard Worker             isDirMask |= mask;
1363*f6dc9357SAndroid Build Coastguard Worker           emptyFileIndex++;
1364*f6dc9357SAndroid Build Coastguard Worker         }
1365*f6dc9357SAndroid Build Coastguard Worker         else
1366*f6dc9357SAndroid Build Coastguard Worker           isDirMask |= mask;
1367*f6dc9357SAndroid Build Coastguard Worker         if (remSubStreams == 0)
1368*f6dc9357SAndroid Build Coastguard Worker         {
1369*f6dc9357SAndroid Build Coastguard Worker           p->FileToFolder[i] = (UInt32)-1;
1370*f6dc9357SAndroid Build Coastguard Worker           continue;
1371*f6dc9357SAndroid Build Coastguard Worker         }
1372*f6dc9357SAndroid Build Coastguard Worker       }
1373*f6dc9357SAndroid Build Coastguard Worker 
1374*f6dc9357SAndroid Build Coastguard Worker       if (remSubStreams == 0)
1375*f6dc9357SAndroid Build Coastguard Worker       {
1376*f6dc9357SAndroid Build Coastguard Worker         for (;;)
1377*f6dc9357SAndroid Build Coastguard Worker         {
1378*f6dc9357SAndroid Build Coastguard Worker           if (folderIndex >= p->db.NumFolders)
1379*f6dc9357SAndroid Build Coastguard Worker             return SZ_ERROR_ARCHIVE;
1380*f6dc9357SAndroid Build Coastguard Worker           p->FolderToFile[folderIndex] = i;
1381*f6dc9357SAndroid Build Coastguard Worker           numSubStreams = 1;
1382*f6dc9357SAndroid Build Coastguard Worker           if (ssi.sdNumSubStreams.Data)
1383*f6dc9357SAndroid Build Coastguard Worker           {
1384*f6dc9357SAndroid Build Coastguard Worker             RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams))
1385*f6dc9357SAndroid Build Coastguard Worker           }
1386*f6dc9357SAndroid Build Coastguard Worker           remSubStreams = numSubStreams;
1387*f6dc9357SAndroid Build Coastguard Worker           if (numSubStreams != 0)
1388*f6dc9357SAndroid Build Coastguard Worker             break;
1389*f6dc9357SAndroid Build Coastguard Worker           {
1390*f6dc9357SAndroid Build Coastguard Worker             const UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1391*f6dc9357SAndroid Build Coastguard Worker             unpackPos += folderUnpackSize;
1392*f6dc9357SAndroid Build Coastguard Worker             if (unpackPos < folderUnpackSize)
1393*f6dc9357SAndroid Build Coastguard Worker               return SZ_ERROR_ARCHIVE;
1394*f6dc9357SAndroid Build Coastguard Worker           }
1395*f6dc9357SAndroid Build Coastguard Worker           folderIndex++;
1396*f6dc9357SAndroid Build Coastguard Worker         }
1397*f6dc9357SAndroid Build Coastguard Worker       }
1398*f6dc9357SAndroid Build Coastguard Worker 
1399*f6dc9357SAndroid Build Coastguard Worker       p->FileToFolder[i] = folderIndex;
1400*f6dc9357SAndroid Build Coastguard Worker 
1401*f6dc9357SAndroid Build Coastguard Worker       if (emptyStreams && SzBitArray_Check(emptyStreams, i))
1402*f6dc9357SAndroid Build Coastguard Worker         continue;
1403*f6dc9357SAndroid Build Coastguard Worker 
1404*f6dc9357SAndroid Build Coastguard Worker       if (--remSubStreams == 0)
1405*f6dc9357SAndroid Build Coastguard Worker       {
1406*f6dc9357SAndroid Build Coastguard Worker         const UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1407*f6dc9357SAndroid Build Coastguard Worker         const UInt64 startFolderUnpackPos = p->UnpackPositions[p->FolderToFile[folderIndex]];
1408*f6dc9357SAndroid Build Coastguard Worker         if (folderUnpackSize < unpackPos - startFolderUnpackPos)
1409*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_ARCHIVE;
1410*f6dc9357SAndroid Build Coastguard Worker         unpackPos = startFolderUnpackPos + folderUnpackSize;
1411*f6dc9357SAndroid Build Coastguard Worker         if (unpackPos < folderUnpackSize)
1412*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_ARCHIVE;
1413*f6dc9357SAndroid Build Coastguard Worker 
1414*f6dc9357SAndroid Build Coastguard Worker         if (numSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, folderIndex))
1415*f6dc9357SAndroid Build Coastguard Worker         {
1416*f6dc9357SAndroid Build Coastguard Worker           p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex];
1417*f6dc9357SAndroid Build Coastguard Worker           crcMask |= mask;
1418*f6dc9357SAndroid Build Coastguard Worker         }
1419*f6dc9357SAndroid Build Coastguard Worker         folderIndex++;
1420*f6dc9357SAndroid Build Coastguard Worker       }
1421*f6dc9357SAndroid Build Coastguard Worker       else
1422*f6dc9357SAndroid Build Coastguard Worker       {
1423*f6dc9357SAndroid Build Coastguard Worker         UInt64 v;
1424*f6dc9357SAndroid Build Coastguard Worker         RINOK(ReadNumber(&ssi.sdSizes, &v))
1425*f6dc9357SAndroid Build Coastguard Worker         unpackPos += v;
1426*f6dc9357SAndroid Build Coastguard Worker         if (unpackPos < v)
1427*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_ARCHIVE;
1428*f6dc9357SAndroid Build Coastguard Worker       }
1429*f6dc9357SAndroid Build Coastguard Worker       if ((crcMask & mask) == 0 && digestsVals)
1430*f6dc9357SAndroid Build Coastguard Worker       {
1431*f6dc9357SAndroid Build Coastguard Worker         if (!digestsDefs || SzBitArray_Check(digestsDefs, digestIndex))
1432*f6dc9357SAndroid Build Coastguard Worker         {
1433*f6dc9357SAndroid Build Coastguard Worker           p->CRCs.Vals[i] = GetUi32(digestsVals);
1434*f6dc9357SAndroid Build Coastguard Worker           digestsVals += 4;
1435*f6dc9357SAndroid Build Coastguard Worker           crcMask |= mask;
1436*f6dc9357SAndroid Build Coastguard Worker         }
1437*f6dc9357SAndroid Build Coastguard Worker         digestIndex++;
1438*f6dc9357SAndroid Build Coastguard Worker       }
1439*f6dc9357SAndroid Build Coastguard Worker     }
1440*f6dc9357SAndroid Build Coastguard Worker 
1441*f6dc9357SAndroid Build Coastguard Worker     if (mask != 0x80)
1442*f6dc9357SAndroid Build Coastguard Worker     {
1443*f6dc9357SAndroid Build Coastguard Worker       const UInt32 byteIndex = (i - 1) >> 3;
1444*f6dc9357SAndroid Build Coastguard Worker       p->IsDirs[byteIndex] = isDirMask;
1445*f6dc9357SAndroid Build Coastguard Worker       p->CRCs.Defs[byteIndex] = crcMask;
1446*f6dc9357SAndroid Build Coastguard Worker     }
1447*f6dc9357SAndroid Build Coastguard Worker 
1448*f6dc9357SAndroid Build Coastguard Worker     p->UnpackPositions[i] = unpackPos;
1449*f6dc9357SAndroid Build Coastguard Worker 
1450*f6dc9357SAndroid Build Coastguard Worker     if (remSubStreams != 0)
1451*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_ARCHIVE;
1452*f6dc9357SAndroid Build Coastguard Worker 
1453*f6dc9357SAndroid Build Coastguard Worker     for (;;)
1454*f6dc9357SAndroid Build Coastguard Worker     {
1455*f6dc9357SAndroid Build Coastguard Worker       p->FolderToFile[folderIndex] = i;
1456*f6dc9357SAndroid Build Coastguard Worker       if (folderIndex >= p->db.NumFolders)
1457*f6dc9357SAndroid Build Coastguard Worker         break;
1458*f6dc9357SAndroid Build Coastguard Worker       if (!ssi.sdNumSubStreams.Data)
1459*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_ARCHIVE;
1460*f6dc9357SAndroid Build Coastguard Worker       RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams))
1461*f6dc9357SAndroid Build Coastguard Worker       if (numSubStreams != 0)
1462*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_ARCHIVE;
1463*f6dc9357SAndroid Build Coastguard Worker       /*
1464*f6dc9357SAndroid Build Coastguard Worker       {
1465*f6dc9357SAndroid Build Coastguard Worker         UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1466*f6dc9357SAndroid Build Coastguard Worker         unpackPos += folderUnpackSize;
1467*f6dc9357SAndroid Build Coastguard Worker         if (unpackPos < folderUnpackSize)
1468*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_ARCHIVE;
1469*f6dc9357SAndroid Build Coastguard Worker       }
1470*f6dc9357SAndroid Build Coastguard Worker       */
1471*f6dc9357SAndroid Build Coastguard Worker       folderIndex++;
1472*f6dc9357SAndroid Build Coastguard Worker     }
1473*f6dc9357SAndroid Build Coastguard Worker 
1474*f6dc9357SAndroid Build Coastguard Worker     if (ssi.sdNumSubStreams.Data && ssi.sdNumSubStreams.Size != 0)
1475*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_ARCHIVE;
1476*f6dc9357SAndroid Build Coastguard Worker   }
1477*f6dc9357SAndroid Build Coastguard Worker }
1478*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
1479*f6dc9357SAndroid Build Coastguard Worker }
1480*f6dc9357SAndroid Build Coastguard Worker 
1481*f6dc9357SAndroid Build Coastguard Worker 
SzReadHeader(CSzArEx * p,CSzData * sd,ILookInStreamPtr inStream,ISzAllocPtr allocMain,ISzAllocPtr allocTemp)1482*f6dc9357SAndroid Build Coastguard Worker static SRes SzReadHeader(
1483*f6dc9357SAndroid Build Coastguard Worker     CSzArEx *p,
1484*f6dc9357SAndroid Build Coastguard Worker     CSzData *sd,
1485*f6dc9357SAndroid Build Coastguard Worker     ILookInStreamPtr inStream,
1486*f6dc9357SAndroid Build Coastguard Worker     ISzAllocPtr allocMain,
1487*f6dc9357SAndroid Build Coastguard Worker     ISzAllocPtr allocTemp)
1488*f6dc9357SAndroid Build Coastguard Worker {
1489*f6dc9357SAndroid Build Coastguard Worker   UInt32 i;
1490*f6dc9357SAndroid Build Coastguard Worker   UInt32 numTempBufs = 0;
1491*f6dc9357SAndroid Build Coastguard Worker   SRes res;
1492*f6dc9357SAndroid Build Coastguard Worker   CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX];
1493*f6dc9357SAndroid Build Coastguard Worker 
1494*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++)
1495*f6dc9357SAndroid Build Coastguard Worker     Buf_Init(tempBufs + i);
1496*f6dc9357SAndroid Build Coastguard Worker 
1497*f6dc9357SAndroid Build Coastguard Worker   res = SzReadHeader2(p, sd, inStream,
1498*f6dc9357SAndroid Build Coastguard Worker       tempBufs, &numTempBufs,
1499*f6dc9357SAndroid Build Coastguard Worker       allocMain, allocTemp);
1500*f6dc9357SAndroid Build Coastguard Worker 
1501*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++)
1502*f6dc9357SAndroid Build Coastguard Worker     Buf_Free(tempBufs + i, allocTemp);
1503*f6dc9357SAndroid Build Coastguard Worker 
1504*f6dc9357SAndroid Build Coastguard Worker   RINOK(res)
1505*f6dc9357SAndroid Build Coastguard Worker 
1506*f6dc9357SAndroid Build Coastguard Worker   if (sd->Size != 0)
1507*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_FAIL;
1508*f6dc9357SAndroid Build Coastguard Worker 
1509*f6dc9357SAndroid Build Coastguard Worker   return res;
1510*f6dc9357SAndroid Build Coastguard Worker }
1511*f6dc9357SAndroid Build Coastguard Worker 
SzArEx_Open2(CSzArEx * p,ILookInStreamPtr inStream,ISzAllocPtr allocMain,ISzAllocPtr allocTemp)1512*f6dc9357SAndroid Build Coastguard Worker static SRes SzArEx_Open2(
1513*f6dc9357SAndroid Build Coastguard Worker     CSzArEx *p,
1514*f6dc9357SAndroid Build Coastguard Worker     ILookInStreamPtr inStream,
1515*f6dc9357SAndroid Build Coastguard Worker     ISzAllocPtr allocMain,
1516*f6dc9357SAndroid Build Coastguard Worker     ISzAllocPtr allocTemp)
1517*f6dc9357SAndroid Build Coastguard Worker {
1518*f6dc9357SAndroid Build Coastguard Worker   Byte header[k7zStartHeaderSize];
1519*f6dc9357SAndroid Build Coastguard Worker   Int64 startArcPos;
1520*f6dc9357SAndroid Build Coastguard Worker   UInt64 nextHeaderOffset, nextHeaderSize;
1521*f6dc9357SAndroid Build Coastguard Worker   size_t nextHeaderSizeT;
1522*f6dc9357SAndroid Build Coastguard Worker   UInt32 nextHeaderCRC;
1523*f6dc9357SAndroid Build Coastguard Worker   CBuf buf;
1524*f6dc9357SAndroid Build Coastguard Worker   SRes res;
1525*f6dc9357SAndroid Build Coastguard Worker 
1526*f6dc9357SAndroid Build Coastguard Worker   startArcPos = 0;
1527*f6dc9357SAndroid Build Coastguard Worker   RINOK(ILookInStream_Seek(inStream, &startArcPos, SZ_SEEK_CUR))
1528*f6dc9357SAndroid Build Coastguard Worker 
1529*f6dc9357SAndroid Build Coastguard Worker   RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE))
1530*f6dc9357SAndroid Build Coastguard Worker 
1531*f6dc9357SAndroid Build Coastguard Worker   if (!TestSignatureCandidate(header))
1532*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_NO_ARCHIVE;
1533*f6dc9357SAndroid Build Coastguard Worker   if (header[6] != k7zMajorVersion)
1534*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_UNSUPPORTED;
1535*f6dc9357SAndroid Build Coastguard Worker 
1536*f6dc9357SAndroid Build Coastguard Worker   nextHeaderOffset = GetUi64(header + 12);
1537*f6dc9357SAndroid Build Coastguard Worker   nextHeaderSize = GetUi64(header + 20);
1538*f6dc9357SAndroid Build Coastguard Worker   nextHeaderCRC = GetUi32(header + 28);
1539*f6dc9357SAndroid Build Coastguard Worker 
1540*f6dc9357SAndroid Build Coastguard Worker   p->startPosAfterHeader = (UInt64)startArcPos + k7zStartHeaderSize;
1541*f6dc9357SAndroid Build Coastguard Worker 
1542*f6dc9357SAndroid Build Coastguard Worker   if (CrcCalc(header + 12, 20) != GetUi32(header + 8))
1543*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_CRC;
1544*f6dc9357SAndroid Build Coastguard Worker 
1545*f6dc9357SAndroid Build Coastguard Worker   p->db.RangeLimit = nextHeaderOffset;
1546*f6dc9357SAndroid Build Coastguard Worker 
1547*f6dc9357SAndroid Build Coastguard Worker   nextHeaderSizeT = (size_t)nextHeaderSize;
1548*f6dc9357SAndroid Build Coastguard Worker   if (nextHeaderSizeT != nextHeaderSize)
1549*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_MEM;
1550*f6dc9357SAndroid Build Coastguard Worker   if (nextHeaderSizeT == 0)
1551*f6dc9357SAndroid Build Coastguard Worker     return SZ_OK;
1552*f6dc9357SAndroid Build Coastguard Worker   if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||
1553*f6dc9357SAndroid Build Coastguard Worker       nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)
1554*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_NO_ARCHIVE;
1555*f6dc9357SAndroid Build Coastguard Worker 
1556*f6dc9357SAndroid Build Coastguard Worker   {
1557*f6dc9357SAndroid Build Coastguard Worker     Int64 pos = 0;
1558*f6dc9357SAndroid Build Coastguard Worker     RINOK(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END))
1559*f6dc9357SAndroid Build Coastguard Worker     if ((UInt64)pos < (UInt64)startArcPos + nextHeaderOffset ||
1560*f6dc9357SAndroid Build Coastguard Worker         (UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
1561*f6dc9357SAndroid Build Coastguard Worker         (UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
1562*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_INPUT_EOF;
1563*f6dc9357SAndroid Build Coastguard Worker   }
1564*f6dc9357SAndroid Build Coastguard Worker 
1565*f6dc9357SAndroid Build Coastguard Worker   RINOK(LookInStream_SeekTo(inStream, (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset))
1566*f6dc9357SAndroid Build Coastguard Worker 
1567*f6dc9357SAndroid Build Coastguard Worker   if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp))
1568*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_MEM;
1569*f6dc9357SAndroid Build Coastguard Worker 
1570*f6dc9357SAndroid Build Coastguard Worker   res = LookInStream_Read(inStream, buf.data, nextHeaderSizeT);
1571*f6dc9357SAndroid Build Coastguard Worker 
1572*f6dc9357SAndroid Build Coastguard Worker   if (res == SZ_OK)
1573*f6dc9357SAndroid Build Coastguard Worker   {
1574*f6dc9357SAndroid Build Coastguard Worker     res = SZ_ERROR_ARCHIVE;
1575*f6dc9357SAndroid Build Coastguard Worker     if (CrcCalc(buf.data, nextHeaderSizeT) == nextHeaderCRC)
1576*f6dc9357SAndroid Build Coastguard Worker     {
1577*f6dc9357SAndroid Build Coastguard Worker       CSzData sd;
1578*f6dc9357SAndroid Build Coastguard Worker       UInt64 type;
1579*f6dc9357SAndroid Build Coastguard Worker       sd.Data = buf.data;
1580*f6dc9357SAndroid Build Coastguard Worker       sd.Size = buf.size;
1581*f6dc9357SAndroid Build Coastguard Worker 
1582*f6dc9357SAndroid Build Coastguard Worker       res = ReadID(&sd, &type);
1583*f6dc9357SAndroid Build Coastguard Worker 
1584*f6dc9357SAndroid Build Coastguard Worker       if (res == SZ_OK && type == k7zIdEncodedHeader)
1585*f6dc9357SAndroid Build Coastguard Worker       {
1586*f6dc9357SAndroid Build Coastguard Worker         CSzAr tempAr;
1587*f6dc9357SAndroid Build Coastguard Worker         CBuf tempBuf;
1588*f6dc9357SAndroid Build Coastguard Worker         Buf_Init(&tempBuf);
1589*f6dc9357SAndroid Build Coastguard Worker 
1590*f6dc9357SAndroid Build Coastguard Worker         SzAr_Init(&tempAr);
1591*f6dc9357SAndroid Build Coastguard Worker         tempAr.RangeLimit = p->db.RangeLimit;
1592*f6dc9357SAndroid Build Coastguard Worker 
1593*f6dc9357SAndroid Build Coastguard Worker         res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp);
1594*f6dc9357SAndroid Build Coastguard Worker         SzAr_Free(&tempAr, allocTemp);
1595*f6dc9357SAndroid Build Coastguard Worker 
1596*f6dc9357SAndroid Build Coastguard Worker         if (res != SZ_OK)
1597*f6dc9357SAndroid Build Coastguard Worker         {
1598*f6dc9357SAndroid Build Coastguard Worker           Buf_Free(&tempBuf, allocTemp);
1599*f6dc9357SAndroid Build Coastguard Worker         }
1600*f6dc9357SAndroid Build Coastguard Worker         else
1601*f6dc9357SAndroid Build Coastguard Worker         {
1602*f6dc9357SAndroid Build Coastguard Worker           Buf_Free(&buf, allocTemp);
1603*f6dc9357SAndroid Build Coastguard Worker           buf.data = tempBuf.data;
1604*f6dc9357SAndroid Build Coastguard Worker           buf.size = tempBuf.size;
1605*f6dc9357SAndroid Build Coastguard Worker           sd.Data = buf.data;
1606*f6dc9357SAndroid Build Coastguard Worker           sd.Size = buf.size;
1607*f6dc9357SAndroid Build Coastguard Worker           res = ReadID(&sd, &type);
1608*f6dc9357SAndroid Build Coastguard Worker         }
1609*f6dc9357SAndroid Build Coastguard Worker       }
1610*f6dc9357SAndroid Build Coastguard Worker 
1611*f6dc9357SAndroid Build Coastguard Worker       if (res == SZ_OK)
1612*f6dc9357SAndroid Build Coastguard Worker       {
1613*f6dc9357SAndroid Build Coastguard Worker         if (type == k7zIdHeader)
1614*f6dc9357SAndroid Build Coastguard Worker         {
1615*f6dc9357SAndroid Build Coastguard Worker           /*
1616*f6dc9357SAndroid Build Coastguard Worker           CSzData sd2;
1617*f6dc9357SAndroid Build Coastguard Worker           unsigned ttt;
1618*f6dc9357SAndroid Build Coastguard Worker           for (ttt = 0; ttt < 40000; ttt++)
1619*f6dc9357SAndroid Build Coastguard Worker           {
1620*f6dc9357SAndroid Build Coastguard Worker             SzArEx_Free(p, allocMain);
1621*f6dc9357SAndroid Build Coastguard Worker             sd2 = sd;
1622*f6dc9357SAndroid Build Coastguard Worker             res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp);
1623*f6dc9357SAndroid Build Coastguard Worker             if (res != SZ_OK)
1624*f6dc9357SAndroid Build Coastguard Worker               break;
1625*f6dc9357SAndroid Build Coastguard Worker           }
1626*f6dc9357SAndroid Build Coastguard Worker           */
1627*f6dc9357SAndroid Build Coastguard Worker           res = SzReadHeader(p, &sd, inStream, allocMain, allocTemp);
1628*f6dc9357SAndroid Build Coastguard Worker         }
1629*f6dc9357SAndroid Build Coastguard Worker         else
1630*f6dc9357SAndroid Build Coastguard Worker           res = SZ_ERROR_UNSUPPORTED;
1631*f6dc9357SAndroid Build Coastguard Worker       }
1632*f6dc9357SAndroid Build Coastguard Worker     }
1633*f6dc9357SAndroid Build Coastguard Worker   }
1634*f6dc9357SAndroid Build Coastguard Worker 
1635*f6dc9357SAndroid Build Coastguard Worker   Buf_Free(&buf, allocTemp);
1636*f6dc9357SAndroid Build Coastguard Worker   return res;
1637*f6dc9357SAndroid Build Coastguard Worker }
1638*f6dc9357SAndroid Build Coastguard Worker 
1639*f6dc9357SAndroid Build Coastguard Worker 
SzArEx_Open(CSzArEx * p,ILookInStreamPtr inStream,ISzAllocPtr allocMain,ISzAllocPtr allocTemp)1640*f6dc9357SAndroid Build Coastguard Worker SRes SzArEx_Open(CSzArEx *p, ILookInStreamPtr inStream,
1641*f6dc9357SAndroid Build Coastguard Worker     ISzAllocPtr allocMain, ISzAllocPtr allocTemp)
1642*f6dc9357SAndroid Build Coastguard Worker {
1643*f6dc9357SAndroid Build Coastguard Worker   const SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);
1644*f6dc9357SAndroid Build Coastguard Worker   if (res != SZ_OK)
1645*f6dc9357SAndroid Build Coastguard Worker     SzArEx_Free(p, allocMain);
1646*f6dc9357SAndroid Build Coastguard Worker   return res;
1647*f6dc9357SAndroid Build Coastguard Worker }
1648*f6dc9357SAndroid Build Coastguard Worker 
1649*f6dc9357SAndroid Build Coastguard Worker 
SzArEx_Extract(const CSzArEx * p,ILookInStreamPtr inStream,UInt32 fileIndex,UInt32 * blockIndex,Byte ** tempBuf,size_t * outBufferSize,size_t * offset,size_t * outSizeProcessed,ISzAllocPtr allocMain,ISzAllocPtr allocTemp)1650*f6dc9357SAndroid Build Coastguard Worker SRes SzArEx_Extract(
1651*f6dc9357SAndroid Build Coastguard Worker     const CSzArEx *p,
1652*f6dc9357SAndroid Build Coastguard Worker     ILookInStreamPtr inStream,
1653*f6dc9357SAndroid Build Coastguard Worker     UInt32 fileIndex,
1654*f6dc9357SAndroid Build Coastguard Worker     UInt32 *blockIndex,
1655*f6dc9357SAndroid Build Coastguard Worker     Byte **tempBuf,
1656*f6dc9357SAndroid Build Coastguard Worker     size_t *outBufferSize,
1657*f6dc9357SAndroid Build Coastguard Worker     size_t *offset,
1658*f6dc9357SAndroid Build Coastguard Worker     size_t *outSizeProcessed,
1659*f6dc9357SAndroid Build Coastguard Worker     ISzAllocPtr allocMain,
1660*f6dc9357SAndroid Build Coastguard Worker     ISzAllocPtr allocTemp)
1661*f6dc9357SAndroid Build Coastguard Worker {
1662*f6dc9357SAndroid Build Coastguard Worker   const UInt32 folderIndex = p->FileToFolder[fileIndex];
1663*f6dc9357SAndroid Build Coastguard Worker   SRes res = SZ_OK;
1664*f6dc9357SAndroid Build Coastguard Worker 
1665*f6dc9357SAndroid Build Coastguard Worker   *offset = 0;
1666*f6dc9357SAndroid Build Coastguard Worker   *outSizeProcessed = 0;
1667*f6dc9357SAndroid Build Coastguard Worker 
1668*f6dc9357SAndroid Build Coastguard Worker   if (folderIndex == (UInt32)-1)
1669*f6dc9357SAndroid Build Coastguard Worker   {
1670*f6dc9357SAndroid Build Coastguard Worker     ISzAlloc_Free(allocMain, *tempBuf);
1671*f6dc9357SAndroid Build Coastguard Worker     *blockIndex = folderIndex;
1672*f6dc9357SAndroid Build Coastguard Worker     *tempBuf = NULL;
1673*f6dc9357SAndroid Build Coastguard Worker     *outBufferSize = 0;
1674*f6dc9357SAndroid Build Coastguard Worker     return SZ_OK;
1675*f6dc9357SAndroid Build Coastguard Worker   }
1676*f6dc9357SAndroid Build Coastguard Worker 
1677*f6dc9357SAndroid Build Coastguard Worker   if (*tempBuf == NULL || *blockIndex != folderIndex)
1678*f6dc9357SAndroid Build Coastguard Worker   {
1679*f6dc9357SAndroid Build Coastguard Worker     const UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1680*f6dc9357SAndroid Build Coastguard Worker     /*
1681*f6dc9357SAndroid Build Coastguard Worker     UInt64 unpackSizeSpec =
1682*f6dc9357SAndroid Build Coastguard Worker         p->UnpackPositions[p->FolderToFile[(size_t)folderIndex + 1]] -
1683*f6dc9357SAndroid Build Coastguard Worker         p->UnpackPositions[p->FolderToFile[folderIndex]];
1684*f6dc9357SAndroid Build Coastguard Worker     */
1685*f6dc9357SAndroid Build Coastguard Worker     const size_t unpackSize = (size_t)unpackSizeSpec;
1686*f6dc9357SAndroid Build Coastguard Worker 
1687*f6dc9357SAndroid Build Coastguard Worker     if (unpackSize != unpackSizeSpec)
1688*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_MEM;
1689*f6dc9357SAndroid Build Coastguard Worker     *blockIndex = folderIndex;
1690*f6dc9357SAndroid Build Coastguard Worker     ISzAlloc_Free(allocMain, *tempBuf);
1691*f6dc9357SAndroid Build Coastguard Worker     *tempBuf = NULL;
1692*f6dc9357SAndroid Build Coastguard Worker 
1693*f6dc9357SAndroid Build Coastguard Worker     if (res == SZ_OK)
1694*f6dc9357SAndroid Build Coastguard Worker     {
1695*f6dc9357SAndroid Build Coastguard Worker       *outBufferSize = unpackSize;
1696*f6dc9357SAndroid Build Coastguard Worker       if (unpackSize != 0)
1697*f6dc9357SAndroid Build Coastguard Worker       {
1698*f6dc9357SAndroid Build Coastguard Worker         *tempBuf = (Byte *)ISzAlloc_Alloc(allocMain, unpackSize);
1699*f6dc9357SAndroid Build Coastguard Worker         if (*tempBuf == NULL)
1700*f6dc9357SAndroid Build Coastguard Worker           res = SZ_ERROR_MEM;
1701*f6dc9357SAndroid Build Coastguard Worker       }
1702*f6dc9357SAndroid Build Coastguard Worker 
1703*f6dc9357SAndroid Build Coastguard Worker       if (res == SZ_OK)
1704*f6dc9357SAndroid Build Coastguard Worker       {
1705*f6dc9357SAndroid Build Coastguard Worker         res = SzAr_DecodeFolder(&p->db, folderIndex,
1706*f6dc9357SAndroid Build Coastguard Worker             inStream, p->dataPos, *tempBuf, unpackSize, allocTemp);
1707*f6dc9357SAndroid Build Coastguard Worker       }
1708*f6dc9357SAndroid Build Coastguard Worker     }
1709*f6dc9357SAndroid Build Coastguard Worker   }
1710*f6dc9357SAndroid Build Coastguard Worker 
1711*f6dc9357SAndroid Build Coastguard Worker   if (res == SZ_OK)
1712*f6dc9357SAndroid Build Coastguard Worker   {
1713*f6dc9357SAndroid Build Coastguard Worker     const UInt64 unpackPos = p->UnpackPositions[fileIndex];
1714*f6dc9357SAndroid Build Coastguard Worker     *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderToFile[folderIndex]]);
1715*f6dc9357SAndroid Build Coastguard Worker     *outSizeProcessed = (size_t)(p->UnpackPositions[(size_t)fileIndex + 1] - unpackPos);
1716*f6dc9357SAndroid Build Coastguard Worker     if (*offset + *outSizeProcessed > *outBufferSize)
1717*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_FAIL;
1718*f6dc9357SAndroid Build Coastguard Worker     if (SzBitWithVals_Check(&p->CRCs, fileIndex))
1719*f6dc9357SAndroid Build Coastguard Worker       if (CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex])
1720*f6dc9357SAndroid Build Coastguard Worker         res = SZ_ERROR_CRC;
1721*f6dc9357SAndroid Build Coastguard Worker   }
1722*f6dc9357SAndroid Build Coastguard Worker 
1723*f6dc9357SAndroid Build Coastguard Worker   return res;
1724*f6dc9357SAndroid Build Coastguard Worker }
1725*f6dc9357SAndroid Build Coastguard Worker 
1726*f6dc9357SAndroid Build Coastguard Worker 
SzArEx_GetFileNameUtf16(const CSzArEx * p,size_t fileIndex,UInt16 * dest)1727*f6dc9357SAndroid Build Coastguard Worker size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
1728*f6dc9357SAndroid Build Coastguard Worker {
1729*f6dc9357SAndroid Build Coastguard Worker   const size_t offs = p->FileNameOffsets[fileIndex];
1730*f6dc9357SAndroid Build Coastguard Worker   const size_t len = p->FileNameOffsets[fileIndex + 1] - offs;
1731*f6dc9357SAndroid Build Coastguard Worker   if (dest != 0)
1732*f6dc9357SAndroid Build Coastguard Worker   {
1733*f6dc9357SAndroid Build Coastguard Worker     size_t i;
1734*f6dc9357SAndroid Build Coastguard Worker     const Byte *src = p->FileNames + offs * 2;
1735*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < len; i++)
1736*f6dc9357SAndroid Build Coastguard Worker       dest[i] = GetUi16(src + i * 2);
1737*f6dc9357SAndroid Build Coastguard Worker   }
1738*f6dc9357SAndroid Build Coastguard Worker   return len;
1739*f6dc9357SAndroid Build Coastguard Worker }
1740*f6dc9357SAndroid Build Coastguard Worker 
1741*f6dc9357SAndroid Build Coastguard Worker /*
1742*f6dc9357SAndroid Build Coastguard Worker size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex)
1743*f6dc9357SAndroid Build Coastguard Worker {
1744*f6dc9357SAndroid Build Coastguard Worker   size_t len;
1745*f6dc9357SAndroid Build Coastguard Worker   if (!p->FileNameOffsets)
1746*f6dc9357SAndroid Build Coastguard Worker     return 1;
1747*f6dc9357SAndroid Build Coastguard Worker   len = 0;
1748*f6dc9357SAndroid Build Coastguard Worker   for (;;)
1749*f6dc9357SAndroid Build Coastguard Worker   {
1750*f6dc9357SAndroid Build Coastguard Worker     UInt32 parent = (UInt32)(Int32)-1;
1751*f6dc9357SAndroid Build Coastguard Worker     len += p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
1752*f6dc9357SAndroid Build Coastguard Worker     if SzBitWithVals_Check(&p->Parents, fileIndex)
1753*f6dc9357SAndroid Build Coastguard Worker       parent = p->Parents.Vals[fileIndex];
1754*f6dc9357SAndroid Build Coastguard Worker     if (parent == (UInt32)(Int32)-1)
1755*f6dc9357SAndroid Build Coastguard Worker       return len;
1756*f6dc9357SAndroid Build Coastguard Worker     fileIndex = parent;
1757*f6dc9357SAndroid Build Coastguard Worker   }
1758*f6dc9357SAndroid Build Coastguard Worker }
1759*f6dc9357SAndroid Build Coastguard Worker 
1760*f6dc9357SAndroid Build Coastguard Worker UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
1761*f6dc9357SAndroid Build Coastguard Worker {
1762*f6dc9357SAndroid Build Coastguard Worker   BoolInt needSlash;
1763*f6dc9357SAndroid Build Coastguard Worker   if (!p->FileNameOffsets)
1764*f6dc9357SAndroid Build Coastguard Worker   {
1765*f6dc9357SAndroid Build Coastguard Worker     *(--dest) = 0;
1766*f6dc9357SAndroid Build Coastguard Worker     return dest;
1767*f6dc9357SAndroid Build Coastguard Worker   }
1768*f6dc9357SAndroid Build Coastguard Worker   needSlash = False;
1769*f6dc9357SAndroid Build Coastguard Worker   for (;;)
1770*f6dc9357SAndroid Build Coastguard Worker   {
1771*f6dc9357SAndroid Build Coastguard Worker     UInt32 parent = (UInt32)(Int32)-1;
1772*f6dc9357SAndroid Build Coastguard Worker     size_t curLen = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
1773*f6dc9357SAndroid Build Coastguard Worker     SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen);
1774*f6dc9357SAndroid Build Coastguard Worker     if (needSlash)
1775*f6dc9357SAndroid Build Coastguard Worker       *(dest - 1) = '/';
1776*f6dc9357SAndroid Build Coastguard Worker     needSlash = True;
1777*f6dc9357SAndroid Build Coastguard Worker     dest -= curLen;
1778*f6dc9357SAndroid Build Coastguard Worker 
1779*f6dc9357SAndroid Build Coastguard Worker     if SzBitWithVals_Check(&p->Parents, fileIndex)
1780*f6dc9357SAndroid Build Coastguard Worker       parent = p->Parents.Vals[fileIndex];
1781*f6dc9357SAndroid Build Coastguard Worker     if (parent == (UInt32)(Int32)-1)
1782*f6dc9357SAndroid Build Coastguard Worker       return dest;
1783*f6dc9357SAndroid Build Coastguard Worker     fileIndex = parent;
1784*f6dc9357SAndroid Build Coastguard Worker   }
1785*f6dc9357SAndroid Build Coastguard Worker }
1786*f6dc9357SAndroid Build Coastguard Worker */
1787