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