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