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