1 /* 7zArcIn.c -- 7z Input functions
2 2017-04-03 : Igor Pavlov : Public domain */
13 #define MY_ALLOC(T, p, size, alloc) { \
14 if ((p = (T *)ISzAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; }
16 #define MY_ALLOC_ZE(T, p, size, alloc) { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) }
18 #define MY_ALLOC_AND_CPY(to, size, from, alloc) \
19 { MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); }
21 #define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \
22 { if ((size) == 0) p = NULL; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } }
24 #define k7zMajorVersion 0
30 k7zIdArchiveProperties
,
31 k7zIdAdditionalStreamsInfo
,
40 k7zIdCodersUnpackSize
,
59 const Byte k7zSignature
[k7zSignatureSize
] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
61 #define SzBitUi32s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
63 static SRes
SzBitUi32s_Alloc(CSzBitUi32s
*p
, size_t num
, ISzAllocPtr alloc
)
72 MY_ALLOC(Byte
, p
->Defs
, (num
+ 7) >> 3, alloc
);
73 MY_ALLOC(UInt32
, p
->Vals
, num
, alloc
);
78 void SzBitUi32s_Free(CSzBitUi32s
*p
, ISzAllocPtr alloc
)
80 ISzAlloc_Free(alloc
, p
->Defs
); p
->Defs
= NULL
;
81 ISzAlloc_Free(alloc
, p
->Vals
); p
->Vals
= NULL
;
84 #define SzBitUi64s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
86 void SzBitUi64s_Free(CSzBitUi64s
*p
, ISzAllocPtr alloc
)
88 ISzAlloc_Free(alloc
, p
->Defs
); p
->Defs
= NULL
;
89 ISzAlloc_Free(alloc
, p
->Vals
); p
->Vals
= NULL
;
93 static void SzAr_Init(CSzAr
*p
)
95 p
->NumPackStreams
= 0;
98 p
->PackPositions
= NULL
;
99 SzBitUi32s_Init(&p
->FolderCRCs
);
101 p
->FoCodersOffsets
= NULL
;
102 p
->FoStartPackStreamIndex
= NULL
;
103 p
->FoToCoderUnpackSizes
= NULL
;
104 p
->FoToMainUnpackSizeIndex
= NULL
;
105 p
->CoderUnpackSizes
= NULL
;
107 p
->CodersData
= NULL
;
110 static void SzAr_Free(CSzAr
*p
, ISzAllocPtr alloc
)
112 ISzAlloc_Free(alloc
, p
->PackPositions
);
113 SzBitUi32s_Free(&p
->FolderCRCs
, alloc
);
115 ISzAlloc_Free(alloc
, p
->FoCodersOffsets
);
116 ISzAlloc_Free(alloc
, p
->FoStartPackStreamIndex
);
117 ISzAlloc_Free(alloc
, p
->FoToCoderUnpackSizes
);
118 ISzAlloc_Free(alloc
, p
->FoToMainUnpackSizeIndex
);
119 ISzAlloc_Free(alloc
, p
->CoderUnpackSizes
);
121 ISzAlloc_Free(alloc
, p
->CodersData
);
127 void SzArEx_Init(CSzArEx
*p
)
134 p
->UnpackPositions
= NULL
;
137 p
->FolderToFile
= NULL
;
138 p
->FileToFolder
= NULL
;
140 p
->FileNameOffsets
= NULL
;
143 SzBitUi32s_Init(&p
->CRCs
);
144 SzBitUi32s_Init(&p
->Attribs
);
145 // SzBitUi32s_Init(&p->Parents);
146 SzBitUi64s_Init(&p
->MTime
);
147 SzBitUi64s_Init(&p
->CTime
);
150 void SzArEx_Free(CSzArEx
*p
, ISzAllocPtr alloc
)
152 ISzAlloc_Free(alloc
, p
->UnpackPositions
);
153 ISzAlloc_Free(alloc
, p
->IsDirs
);
155 ISzAlloc_Free(alloc
, p
->FolderToFile
);
156 ISzAlloc_Free(alloc
, p
->FileToFolder
);
158 ISzAlloc_Free(alloc
, p
->FileNameOffsets
);
159 ISzAlloc_Free(alloc
, p
->FileNames
);
161 SzBitUi32s_Free(&p
->CRCs
, alloc
);
162 SzBitUi32s_Free(&p
->Attribs
, alloc
);
163 // SzBitUi32s_Free(&p->Parents, alloc);
164 SzBitUi64s_Free(&p
->MTime
, alloc
);
165 SzBitUi64s_Free(&p
->CTime
, alloc
);
167 SzAr_Free(&p
->db
, alloc
);
172 static int TestSignatureCandidate(const Byte
*testBytes
)
175 for (i
= 0; i
< k7zSignatureSize
; i
++)
176 if (testBytes
[i
] != k7zSignature
[i
])
181 #define SzData_Clear(p) { (p)->Data = NULL; (p)->Size = 0; }
183 #define SZ_READ_BYTE_SD(_sd_, dest) if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; (_sd_)->Size--; dest = *(_sd_)->Data++;
184 #define SZ_READ_BYTE(dest) SZ_READ_BYTE_SD(sd, dest)
185 #define SZ_READ_BYTE_2(dest) if (sd.Size == 0) return SZ_ERROR_ARCHIVE; sd.Size--; dest = *sd.Data++;
187 #define SKIP_DATA(sd, size) { sd->Size -= (size_t)(size); sd->Data += (size_t)(size); }
188 #define SKIP_DATA2(sd, size) { sd.Size -= (size_t)(size); sd.Data += (size_t)(size); }
190 #define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \
191 dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4);
193 static MY_NO_INLINE SRes
ReadNumber(CSzData
*sd
, UInt64
*value
)
195 Byte firstByte
, mask
;
199 SZ_READ_BYTE(firstByte
);
200 if ((firstByte
& 0x80) == 0)
206 if ((firstByte
& 0x40) == 0)
208 *value
= (((UInt32
)firstByte
& 0x3F) << 8) | v
;
212 *value
= v
| ((UInt32
)mask
<< 8);
214 for (i
= 2; i
< 8; i
++)
217 if ((firstByte
& mask
) == 0)
219 UInt64 highPart
= (unsigned)firstByte
& (unsigned)(mask
- 1);
220 *value
|= (highPart
<< (8 * i
));
224 *value
|= ((UInt64
)b
<< (8 * i
));
231 static MY_NO_INLINE SRes
SzReadNumber32(CSzData
*sd
, UInt32
*value
)
236 return SZ_ERROR_ARCHIVE
;
237 firstByte
= *sd
->Data
;
238 if ((firstByte
& 0x80) == 0)
245 RINOK(ReadNumber(sd
, &value64
));
246 if (value64
>= (UInt32
)0x80000000 - 1)
247 return SZ_ERROR_UNSUPPORTED
;
248 if (value64
>= ((UInt64
)(1) << ((sizeof(size_t) - 1) * 8 + 4)))
249 return SZ_ERROR_UNSUPPORTED
;
250 *value
= (UInt32
)value64
;
254 #define ReadID(sd, value) ReadNumber(sd, value)
256 static SRes
SkipData(CSzData
*sd
)
259 RINOK(ReadNumber(sd
, &size
));
261 return SZ_ERROR_ARCHIVE
;
266 static SRes
WaitId(CSzData
*sd
, UInt32 id
)
271 RINOK(ReadID(sd
, &type
));
274 if (type
== k7zIdEnd
)
275 return SZ_ERROR_ARCHIVE
;
280 static SRes
RememberBitVector(CSzData
*sd
, UInt32 numItems
, const Byte
**v
)
282 UInt32 numBytes
= (numItems
+ 7) >> 3;
283 if (numBytes
> sd
->Size
)
284 return SZ_ERROR_ARCHIVE
;
286 SKIP_DATA(sd
, numBytes
);
290 static UInt32
CountDefinedBits(const Byte
*bits
, UInt32 numItems
)
295 for (; numItems
!= 0; numItems
--)
303 sum
+= ((b
>> m
) & 1);
308 static MY_NO_INLINE SRes
ReadBitVector(CSzData
*sd
, UInt32 numItems
, Byte
**v
, ISzAllocPtr alloc
)
312 UInt32 numBytes
= (numItems
+ 7) >> 3;
314 SZ_READ_BYTE(allAreDefined
);
317 if (allAreDefined
== 0)
319 if (numBytes
> sd
->Size
)
320 return SZ_ERROR_ARCHIVE
;
321 MY_ALLOC_AND_CPY(*v
, numBytes
, sd
->Data
, alloc
);
322 SKIP_DATA(sd
, numBytes
);
325 MY_ALLOC(Byte
, *v
, numBytes
, alloc
);
327 memset(v2
, 0xFF, (size_t)numBytes
);
329 unsigned numBits
= (unsigned)numItems
& 7;
331 v2
[(size_t)numBytes
- 1] = (Byte
)((((UInt32
)1 << numBits
) - 1) << (8 - numBits
));
336 static MY_NO_INLINE SRes
ReadUi32s(CSzData
*sd2
, UInt32 numItems
, CSzBitUi32s
*crcs
, ISzAllocPtr alloc
)
342 MY_ALLOC_ZE(UInt32
, crcs
->Vals
, numItems
, alloc
);
346 for (i
= 0; i
< numItems
; i
++)
347 if (SzBitArray_Check(defs
, i
))
357 static SRes
ReadBitUi32s(CSzData
*sd
, UInt32 numItems
, CSzBitUi32s
*crcs
, ISzAllocPtr alloc
)
359 SzBitUi32s_Free(crcs
, alloc
);
360 RINOK(ReadBitVector(sd
, numItems
, &crcs
->Defs
, alloc
));
361 return ReadUi32s(sd
, numItems
, crcs
, alloc
);
364 static SRes
SkipBitUi32s(CSzData
*sd
, UInt32 numItems
)
367 UInt32 numDefined
= numItems
;
368 SZ_READ_BYTE(allAreDefined
);
371 size_t numBytes
= (numItems
+ 7) >> 3;
372 if (numBytes
> sd
->Size
)
373 return SZ_ERROR_ARCHIVE
;
374 numDefined
= CountDefinedBits(sd
->Data
, numItems
);
375 SKIP_DATA(sd
, numBytes
);
377 if (numDefined
> (sd
->Size
>> 2))
378 return SZ_ERROR_ARCHIVE
;
379 SKIP_DATA(sd
, (size_t)numDefined
* 4);
383 static SRes
ReadPackInfo(CSzAr
*p
, CSzData
*sd
, ISzAllocPtr alloc
)
385 RINOK(SzReadNumber32(sd
, &p
->NumPackStreams
));
387 RINOK(WaitId(sd
, k7zIdSize
));
388 MY_ALLOC(UInt64
, p
->PackPositions
, (size_t)p
->NumPackStreams
+ 1, alloc
);
392 UInt32 numPackStreams
= p
->NumPackStreams
;
393 for (i
= 0; i
< numPackStreams
; i
++)
396 p
->PackPositions
[i
] = sum
;
397 RINOK(ReadNumber(sd
, &packSize
));
400 return SZ_ERROR_ARCHIVE
;
402 p
->PackPositions
[i
] = sum
;
408 RINOK(ReadID(sd
, &type
));
409 if (type
== k7zIdEnd
)
411 if (type
== k7zIdCRC
)
413 /* CRC of packed streams is unused now */
414 RINOK(SkipBitUi32s(sd
, p
->NumPackStreams
));
422 static SRes SzReadSwitch(CSzData *sd)
425 RINOK(SzReadByte(sd, &external));
426 return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED;
430 #define k_NumCodersStreams_in_Folder_MAX (SZ_NUM_BONDS_IN_FOLDER_MAX + SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)
432 SRes
SzGetNextFolderItem(CSzFolder
*f
, CSzData
*sd
)
435 UInt32 numInStreams
= 0;
436 const Byte
*dataStart
= sd
->Data
;
440 f
->NumPackStreams
= 0;
443 RINOK(SzReadNumber32(sd
, &numCoders
));
444 if (numCoders
== 0 || numCoders
> SZ_NUM_CODERS_IN_FOLDER_MAX
)
445 return SZ_ERROR_UNSUPPORTED
;
447 for (i
= 0; i
< numCoders
; i
++)
450 CSzCoderInfo
*coder
= f
->Coders
+ i
;
454 SZ_READ_BYTE(mainByte
);
455 if ((mainByte
& 0xC0) != 0)
456 return SZ_ERROR_UNSUPPORTED
;
458 idSize
= (unsigned)(mainByte
& 0xF);
459 if (idSize
> sizeof(id
))
460 return SZ_ERROR_UNSUPPORTED
;
461 if (idSize
> sd
->Size
)
462 return SZ_ERROR_ARCHIVE
;
464 for (j
= 0; j
< idSize
; j
++)
466 id
= ((id
<< 8) | *sd
->Data
);
470 if (id
> (UInt32
)0xFFFFFFFF)
471 return SZ_ERROR_UNSUPPORTED
;
472 coder
->MethodID
= (UInt32
)id
;
474 coder
->NumStreams
= 1;
475 coder
->PropsOffset
= 0;
476 coder
->PropsSize
= 0;
478 if ((mainByte
& 0x10) != 0)
482 RINOK(SzReadNumber32(sd
, &numStreams
));
483 if (numStreams
> k_NumCodersStreams_in_Folder_MAX
)
484 return SZ_ERROR_UNSUPPORTED
;
485 coder
->NumStreams
= (Byte
)numStreams
;
487 RINOK(SzReadNumber32(sd
, &numStreams
));
489 return SZ_ERROR_UNSUPPORTED
;
492 numInStreams
+= coder
->NumStreams
;
494 if (numInStreams
> k_NumCodersStreams_in_Folder_MAX
)
495 return SZ_ERROR_UNSUPPORTED
;
497 if ((mainByte
& 0x20) != 0)
499 UInt32 propsSize
= 0;
500 RINOK(SzReadNumber32(sd
, &propsSize
));
501 if (propsSize
> sd
->Size
)
502 return SZ_ERROR_ARCHIVE
;
503 if (propsSize
>= 0x80)
504 return SZ_ERROR_UNSUPPORTED
;
505 coder
->PropsOffset
= sd
->Data
- dataStart
;
506 coder
->PropsSize
= (Byte
)propsSize
;
507 sd
->Data
+= (size_t)propsSize
;
508 sd
->Size
-= (size_t)propsSize
;
513 if (numInStreams == 1 && numCoders == 1)
515 f->NumPackStreams = 1;
516 f->PackStreams[0] = 0;
521 Byte streamUsed
[k_NumCodersStreams_in_Folder_MAX
];
522 UInt32 numBonds
, numPackStreams
;
524 numBonds
= numCoders
- 1;
525 if (numInStreams
< numBonds
)
526 return SZ_ERROR_ARCHIVE
;
527 if (numBonds
> SZ_NUM_BONDS_IN_FOLDER_MAX
)
528 return SZ_ERROR_UNSUPPORTED
;
529 f
->NumBonds
= numBonds
;
531 numPackStreams
= numInStreams
- numBonds
;
532 if (numPackStreams
> SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX
)
533 return SZ_ERROR_UNSUPPORTED
;
534 f
->NumPackStreams
= numPackStreams
;
536 for (i
= 0; i
< numInStreams
; i
++)
537 streamUsed
[i
] = False
;
541 Byte coderUsed
[SZ_NUM_CODERS_IN_FOLDER_MAX
];
543 for (i
= 0; i
< numCoders
; i
++)
544 coderUsed
[i
] = False
;
546 for (i
= 0; i
< numBonds
; i
++)
548 CSzBond
*bp
= f
->Bonds
+ i
;
550 RINOK(SzReadNumber32(sd
, &bp
->InIndex
));
551 if (bp
->InIndex
>= numInStreams
|| streamUsed
[bp
->InIndex
])
552 return SZ_ERROR_ARCHIVE
;
553 streamUsed
[bp
->InIndex
] = True
;
555 RINOK(SzReadNumber32(sd
, &bp
->OutIndex
));
556 if (bp
->OutIndex
>= numCoders
|| coderUsed
[bp
->OutIndex
])
557 return SZ_ERROR_ARCHIVE
;
558 coderUsed
[bp
->OutIndex
] = True
;
561 for (i
= 0; i
< numCoders
; i
++)
569 return SZ_ERROR_ARCHIVE
;
572 if (numPackStreams
== 1)
574 for (i
= 0; i
< numInStreams
; i
++)
577 if (i
== numInStreams
)
578 return SZ_ERROR_ARCHIVE
;
579 f
->PackStreams
[0] = i
;
582 for (i
= 0; i
< numPackStreams
; i
++)
585 RINOK(SzReadNumber32(sd
, &index
));
586 if (index
>= numInStreams
|| streamUsed
[index
])
587 return SZ_ERROR_ARCHIVE
;
588 streamUsed
[index
] = True
;
589 f
->PackStreams
[i
] = index
;
593 f
->NumCoders
= numCoders
;
599 static MY_NO_INLINE SRes
SkipNumbers(CSzData
*sd2
, UInt32 num
)
603 for (; num
!= 0; num
--)
605 Byte firstByte
, mask
;
607 SZ_READ_BYTE_2(firstByte
);
608 if ((firstByte
& 0x80) == 0)
610 if ((firstByte
& 0x40) == 0)
613 return SZ_ERROR_ARCHIVE
;
619 for (i
= 2; i
< 8 && (firstByte
& mask
) != 0; i
++)
622 return SZ_ERROR_ARCHIVE
;
630 #define k_Scan_NumCoders_MAX 64
631 #define k_Scan_NumCodersStreams_in_Folder_MAX 64
634 static SRes
ReadUnpackInfo(CSzAr
*p
,
636 UInt32 numFoldersMax
,
637 const CBuf
*tempBufs
, UInt32 numTempBufs
,
642 UInt32 fo
, numFolders
, numCodersOutStreams
, packStreamIndex
;
643 const Byte
*startBufPtr
;
646 RINOK(WaitId(sd2
, k7zIdFolder
));
648 RINOK(SzReadNumber32(sd2
, &numFolders
));
649 if (numFolders
> numFoldersMax
)
650 return SZ_ERROR_UNSUPPORTED
;
651 p
->NumFolders
= numFolders
;
653 SZ_READ_BYTE_SD(sd2
, external
);
659 RINOK(SzReadNumber32(sd2
, &index
));
660 if (index
>= numTempBufs
)
661 return SZ_ERROR_ARCHIVE
;
662 sd
.Data
= tempBufs
[index
].data
;
663 sd
.Size
= tempBufs
[index
].size
;
666 MY_ALLOC(size_t, p
->FoCodersOffsets
, (size_t)numFolders
+ 1, alloc
);
667 MY_ALLOC(UInt32
, p
->FoStartPackStreamIndex
, (size_t)numFolders
+ 1, alloc
);
668 MY_ALLOC(UInt32
, p
->FoToCoderUnpackSizes
, (size_t)numFolders
+ 1, alloc
);
669 MY_ALLOC(Byte
, p
->FoToMainUnpackSizeIndex
, (size_t)numFolders
, alloc
);
671 startBufPtr
= sd
.Data
;
674 numCodersOutStreams
= 0;
676 for (fo
= 0; fo
< numFolders
; fo
++)
678 UInt32 numCoders
, ci
, numInStreams
= 0;
680 p
->FoCodersOffsets
[fo
] = sd
.Data
- startBufPtr
;
682 RINOK(SzReadNumber32(&sd
, &numCoders
));
683 if (numCoders
== 0 || numCoders
> k_Scan_NumCoders_MAX
)
684 return SZ_ERROR_UNSUPPORTED
;
686 for (ci
= 0; ci
< numCoders
; ci
++)
690 UInt32 coderInStreams
;
692 SZ_READ_BYTE_2(mainByte
);
693 if ((mainByte
& 0xC0) != 0)
694 return SZ_ERROR_UNSUPPORTED
;
695 idSize
= (mainByte
& 0xF);
697 return SZ_ERROR_UNSUPPORTED
;
698 if (idSize
> sd
.Size
)
699 return SZ_ERROR_ARCHIVE
;
700 SKIP_DATA2(sd
, idSize
);
704 if ((mainByte
& 0x10) != 0)
706 UInt32 coderOutStreams
;
707 RINOK(SzReadNumber32(&sd
, &coderInStreams
));
708 RINOK(SzReadNumber32(&sd
, &coderOutStreams
));
709 if (coderInStreams
> k_Scan_NumCodersStreams_in_Folder_MAX
|| coderOutStreams
!= 1)
710 return SZ_ERROR_UNSUPPORTED
;
713 numInStreams
+= coderInStreams
;
715 if ((mainByte
& 0x20) != 0)
718 RINOK(SzReadNumber32(&sd
, &propsSize
));
719 if (propsSize
> sd
.Size
)
720 return SZ_ERROR_ARCHIVE
;
721 SKIP_DATA2(sd
, propsSize
);
726 UInt32 indexOfMainStream
= 0;
727 UInt32 numPackStreams
= 1;
729 if (numCoders
!= 1 || numInStreams
!= 1)
731 Byte streamUsed
[k_Scan_NumCodersStreams_in_Folder_MAX
];
732 Byte coderUsed
[k_Scan_NumCoders_MAX
];
735 UInt32 numBonds
= numCoders
- 1;
736 if (numInStreams
< numBonds
)
737 return SZ_ERROR_ARCHIVE
;
739 if (numInStreams
> k_Scan_NumCodersStreams_in_Folder_MAX
)
740 return SZ_ERROR_UNSUPPORTED
;
742 for (i
= 0; i
< numInStreams
; i
++)
743 streamUsed
[i
] = False
;
744 for (i
= 0; i
< numCoders
; i
++)
745 coderUsed
[i
] = False
;
747 for (i
= 0; i
< numBonds
; i
++)
751 RINOK(SzReadNumber32(&sd
, &index
));
752 if (index
>= numInStreams
|| streamUsed
[index
])
753 return SZ_ERROR_ARCHIVE
;
754 streamUsed
[index
] = True
;
756 RINOK(SzReadNumber32(&sd
, &index
));
757 if (index
>= numCoders
|| coderUsed
[index
])
758 return SZ_ERROR_ARCHIVE
;
759 coderUsed
[index
] = True
;
762 numPackStreams
= numInStreams
- numBonds
;
764 if (numPackStreams
!= 1)
765 for (i
= 0; i
< numPackStreams
; i
++)
768 RINOK(SzReadNumber32(&sd
, &index
));
769 if (index
>= numInStreams
|| streamUsed
[index
])
770 return SZ_ERROR_ARCHIVE
;
771 streamUsed
[index
] = True
;
774 for (i
= 0; i
< numCoders
; i
++)
777 indexOfMainStream
= i
;
782 return SZ_ERROR_ARCHIVE
;
785 p
->FoStartPackStreamIndex
[fo
] = packStreamIndex
;
786 p
->FoToCoderUnpackSizes
[fo
] = numCodersOutStreams
;
787 p
->FoToMainUnpackSizeIndex
[fo
] = (Byte
)indexOfMainStream
;
788 numCodersOutStreams
+= numCoders
;
789 if (numCodersOutStreams
< numCoders
)
790 return SZ_ERROR_UNSUPPORTED
;
791 if (numPackStreams
> p
->NumPackStreams
- packStreamIndex
)
792 return SZ_ERROR_ARCHIVE
;
793 packStreamIndex
+= numPackStreams
;
797 p
->FoToCoderUnpackSizes
[fo
] = numCodersOutStreams
;
800 size_t dataSize
= sd
.Data
- startBufPtr
;
801 p
->FoStartPackStreamIndex
[fo
] = packStreamIndex
;
802 p
->FoCodersOffsets
[fo
] = dataSize
;
803 MY_ALLOC_ZE_AND_CPY(p
->CodersData
, dataSize
, startBufPtr
, alloc
);
809 return SZ_ERROR_ARCHIVE
;
813 RINOK(WaitId(&sd
, k7zIdCodersUnpackSize
));
815 MY_ALLOC_ZE(UInt64
, p
->CoderUnpackSizes
, (size_t)numCodersOutStreams
, alloc
);
818 for (i
= 0; i
< numCodersOutStreams
; i
++)
820 RINOK(ReadNumber(&sd
, p
->CoderUnpackSizes
+ i
));
827 RINOK(ReadID(&sd
, &type
));
828 if (type
== k7zIdEnd
)
833 if (type
== k7zIdCRC
)
835 RINOK(ReadBitUi32s(&sd
, numFolders
, &p
->FolderCRCs
, alloc
));
838 RINOK(SkipData(&sd
));
843 UInt64
SzAr_GetFolderUnpackSize(const CSzAr
*p
, UInt32 folderIndex
)
845 return p
->CoderUnpackSizes
[p
->FoToCoderUnpackSizes
[folderIndex
] + p
->FoToMainUnpackSizeIndex
[folderIndex
]];
851 UInt32 NumTotalSubStreams
;
852 UInt32 NumSubDigests
;
853 CSzData sdNumSubStreams
;
859 static SRes
ReadSubStreamsInfo(CSzAr
*p
, CSzData
*sd
, CSubStreamInfo
*ssi
)
862 UInt32 numSubDigests
= 0;
863 UInt32 numFolders
= p
->NumFolders
;
864 UInt32 numUnpackStreams
= numFolders
;
865 UInt32 numUnpackSizesInData
= 0;
869 RINOK(ReadID(sd
, &type
));
870 if (type
== k7zIdNumUnpackStream
)
873 ssi
->sdNumSubStreams
.Data
= sd
->Data
;
874 numUnpackStreams
= 0;
876 for (i
= 0; i
< numFolders
; i
++)
879 RINOK(SzReadNumber32(sd
, &numStreams
));
880 if (numUnpackStreams
> numUnpackStreams
+ numStreams
)
881 return SZ_ERROR_UNSUPPORTED
;
882 numUnpackStreams
+= numStreams
;
884 numUnpackSizesInData
+= (numStreams
- 1);
885 if (numStreams
!= 1 || !SzBitWithVals_Check(&p
->FolderCRCs
, i
))
886 numSubDigests
+= numStreams
;
888 ssi
->sdNumSubStreams
.Size
= sd
->Data
- ssi
->sdNumSubStreams
.Data
;
891 if (type
== k7zIdCRC
|| type
== k7zIdSize
|| type
== k7zIdEnd
)
896 if (!ssi
->sdNumSubStreams
.Data
)
898 numSubDigests
= numFolders
;
899 if (p
->FolderCRCs
.Defs
)
900 numSubDigests
= numFolders
- CountDefinedBits(p
->FolderCRCs
.Defs
, numFolders
);
903 ssi
->NumTotalSubStreams
= numUnpackStreams
;
904 ssi
->NumSubDigests
= numSubDigests
;
906 if (type
== k7zIdSize
)
908 ssi
->sdSizes
.Data
= sd
->Data
;
909 RINOK(SkipNumbers(sd
, numUnpackSizesInData
));
910 ssi
->sdSizes
.Size
= sd
->Data
- ssi
->sdSizes
.Data
;
911 RINOK(ReadID(sd
, &type
));
916 if (type
== k7zIdEnd
)
918 if (type
== k7zIdCRC
)
920 ssi
->sdCRCs
.Data
= sd
->Data
;
921 RINOK(SkipBitUi32s(sd
, numSubDigests
));
922 ssi
->sdCRCs
.Size
= sd
->Data
- ssi
->sdCRCs
.Data
;
928 RINOK(ReadID(sd
, &type
));
932 static SRes
SzReadStreamsInfo(CSzAr
*p
,
934 UInt32 numFoldersMax
, const CBuf
*tempBufs
, UInt32 numTempBufs
,
941 SzData_Clear(&ssi
->sdSizes
);
942 SzData_Clear(&ssi
->sdCRCs
);
943 SzData_Clear(&ssi
->sdNumSubStreams
);
946 RINOK(ReadID(sd
, &type
));
947 if (type
== k7zIdPackInfo
)
949 RINOK(ReadNumber(sd
, dataOffset
));
950 RINOK(ReadPackInfo(p
, sd
, alloc
));
951 RINOK(ReadID(sd
, &type
));
953 if (type
== k7zIdUnpackInfo
)
955 RINOK(ReadUnpackInfo(p
, sd
, numFoldersMax
, tempBufs
, numTempBufs
, alloc
));
956 RINOK(ReadID(sd
, &type
));
958 if (type
== k7zIdSubStreamsInfo
)
960 RINOK(ReadSubStreamsInfo(p
, sd
, ssi
));
961 RINOK(ReadID(sd
, &type
));
965 ssi
->NumTotalSubStreams
= p
->NumFolders
;
966 // ssi->NumSubDigests = 0;
969 return (type
== k7zIdEnd
? SZ_OK
: SZ_ERROR_UNSUPPORTED
);
972 static SRes
SzReadAndDecodePackedStreams(
973 ILookInStream
*inStream
,
976 UInt32 numFoldersMax
,
979 ISzAllocPtr allocTemp
)
985 RINOK(SzReadStreamsInfo(p
, sd
, numFoldersMax
, NULL
, 0, &dataStartPos
, &ssi
, allocTemp
));
987 dataStartPos
+= baseOffset
;
988 if (p
->NumFolders
== 0)
989 return SZ_ERROR_ARCHIVE
;
991 for (fo
= 0; fo
< p
->NumFolders
; fo
++)
992 Buf_Init(tempBufs
+ fo
);
994 for (fo
= 0; fo
< p
->NumFolders
; fo
++)
996 CBuf
*tempBuf
= tempBufs
+ fo
;
997 UInt64 unpackSize
= SzAr_GetFolderUnpackSize(p
, fo
);
998 if ((size_t)unpackSize
!= unpackSize
)
1000 if (!Buf_Create(tempBuf
, (size_t)unpackSize
, allocTemp
))
1001 return SZ_ERROR_MEM
;
1004 for (fo
= 0; fo
< p
->NumFolders
; fo
++)
1006 const CBuf
*tempBuf
= tempBufs
+ fo
;
1007 RINOK(LookInStream_SeekTo(inStream
, dataStartPos
));
1008 RINOK(SzAr_DecodeFolder(p
, fo
, inStream
, dataStartPos
, tempBuf
->data
, tempBuf
->size
, allocTemp
));
1014 static SRes
SzReadFileNames(const Byte
*data
, size_t size
, UInt32 numFiles
, size_t *offsets
)
1019 return (size
== 0) ? SZ_OK
: SZ_ERROR_ARCHIVE
;
1021 return SZ_ERROR_ARCHIVE
;
1022 if (data
[size
- 2] != 0 || data
[size
- 1] != 0)
1023 return SZ_ERROR_ARCHIVE
;
1028 return SZ_ERROR_ARCHIVE
;
1029 for (p
= data
+ pos
;
1031 *(const UInt16
*)p
!= 0
1033 p
[0] != 0 || p
[1] != 0
1037 *offsets
++ = (pos
>> 1);
1040 return (pos
== size
) ? SZ_OK
: SZ_ERROR_ARCHIVE
;
1043 static MY_NO_INLINE SRes
ReadTime(CSzBitUi64s
*p
, UInt32 num
,
1045 const CBuf
*tempBufs
, UInt32 numTempBufs
,
1050 CNtfsFileTime
*vals
;
1054 RINOK(ReadBitVector(sd2
, num
, &p
->Defs
, alloc
));
1056 SZ_READ_BYTE_SD(sd2
, external
);
1062 RINOK(SzReadNumber32(sd2
, &index
));
1063 if (index
>= numTempBufs
)
1064 return SZ_ERROR_ARCHIVE
;
1065 sd
.Data
= tempBufs
[index
].data
;
1066 sd
.Size
= tempBufs
[index
].size
;
1069 MY_ALLOC_ZE(CNtfsFileTime
, p
->Vals
, num
, alloc
);
1072 for (i
= 0; i
< num
; i
++)
1073 if (SzBitArray_Check(defs
, i
))
1076 return SZ_ERROR_ARCHIVE
;
1077 vals
[i
].Low
= GetUi32(sd
.Data
);
1078 vals
[i
].High
= GetUi32(sd
.Data
+ 4);
1082 vals
[i
].High
= vals
[i
].Low
= 0;
1091 #define NUM_ADDITIONAL_STREAMS_MAX 8
1094 static SRes
SzReadHeader2(
1095 CSzArEx
*p
, /* allocMain */
1097 ILookInStream
*inStream
,
1098 CBuf
*tempBufs
, UInt32
*numTempBufs
,
1099 ISzAllocPtr allocMain
,
1100 ISzAllocPtr allocTemp
1108 SzData_Clear(&ssi
.sdSizes
);
1109 SzData_Clear(&ssi
.sdCRCs
);
1110 SzData_Clear(&ssi
.sdNumSubStreams
);
1112 ssi
.NumSubDigests
= 0;
1113 ssi
.NumTotalSubStreams
= 0;
1115 RINOK(ReadID(sd
, &type
));
1117 if (type
== k7zIdArchiveProperties
)
1122 RINOK(ReadID(sd
, &type2
));
1123 if (type2
== k7zIdEnd
)
1125 RINOK(SkipData(sd
));
1127 RINOK(ReadID(sd
, &type
));
1130 if (type
== k7zIdAdditionalStreamsInfo
)
1136 res
= SzReadAndDecodePackedStreams(inStream
, sd
, tempBufs
, NUM_ADDITIONAL_STREAMS_MAX
,
1137 p
->startPosAfterHeader
, &tempAr
, allocTemp
);
1138 *numTempBufs
= tempAr
.NumFolders
;
1139 SzAr_Free(&tempAr
, allocTemp
);
1143 RINOK(ReadID(sd
, &type
));
1146 if (type
== k7zIdMainStreamsInfo
)
1148 RINOK(SzReadStreamsInfo(&p
->db
, sd
, (UInt32
)1 << 30, tempBufs
, *numTempBufs
,
1149 &p
->dataPos
, &ssi
, allocMain
));
1150 p
->dataPos
+= p
->startPosAfterHeader
;
1151 RINOK(ReadID(sd
, &type
));
1154 if (type
== k7zIdEnd
)
1159 if (type
!= k7zIdFilesInfo
)
1160 return SZ_ERROR_ARCHIVE
;
1164 UInt32 numFiles
= 0;
1165 UInt32 numEmptyStreams
= 0;
1166 const Byte
*emptyStreams
= NULL
;
1167 const Byte
*emptyFiles
= NULL
;
1169 RINOK(SzReadNumber32(sd
, &numFiles
));
1170 p
->NumFiles
= numFiles
;
1176 RINOK(ReadID(sd
, &type
));
1177 if (type
== k7zIdEnd
)
1179 RINOK(ReadNumber(sd
, &size
));
1180 if (size
> sd
->Size
)
1181 return SZ_ERROR_ARCHIVE
;
1183 if (type
>= ((UInt32
)1 << 8))
1185 SKIP_DATA(sd
, size
);
1187 else switch ((unsigned)type
)
1192 const Byte
*namesData
;
1195 SZ_READ_BYTE(external
);
1198 namesSize
= (size_t)size
- 1;
1199 namesData
= sd
->Data
;
1204 RINOK(SzReadNumber32(sd
, &index
));
1205 if (index
>= *numTempBufs
)
1206 return SZ_ERROR_ARCHIVE
;
1207 namesData
= (tempBufs
)[index
].data
;
1208 namesSize
= (tempBufs
)[index
].size
;
1211 if ((namesSize
& 1) != 0)
1212 return SZ_ERROR_ARCHIVE
;
1213 MY_ALLOC(size_t, p
->FileNameOffsets
, numFiles
+ 1, allocMain
);
1214 MY_ALLOC_ZE_AND_CPY(p
->FileNames
, namesSize
, namesData
, allocMain
);
1215 RINOK(SzReadFileNames(p
->FileNames
, namesSize
, numFiles
, p
->FileNameOffsets
))
1218 SKIP_DATA(sd
, namesSize
);
1222 case k7zIdEmptyStream
:
1224 RINOK(RememberBitVector(sd
, numFiles
, &emptyStreams
));
1225 numEmptyStreams
= CountDefinedBits(emptyStreams
, numFiles
);
1229 case k7zIdEmptyFile
:
1231 RINOK(RememberBitVector(sd
, numEmptyStreams
, &emptyFiles
));
1234 case k7zIdWinAttrib
:
1239 SzBitUi32s_Free(&p
->Attribs
, allocMain
);
1240 RINOK(ReadBitVector(sd
, numFiles
, &p
->Attribs
.Defs
, allocMain
));
1242 SZ_READ_BYTE(external
);
1248 RINOK(SzReadNumber32(sd
, &index
));
1249 if (index
>= *numTempBufs
)
1250 return SZ_ERROR_ARCHIVE
;
1251 sdSwitch
.Data
= (tempBufs
)[index
].data
;
1252 sdSwitch
.Size
= (tempBufs
)[index
].size
;
1255 RINOK(ReadUi32s(sdPtr
, numFiles
, &p
->Attribs
, allocMain
));
1261 SzBitUi32s_Free(&p->Parents, allocMain);
1262 RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain));
1263 RINOK(SzReadSwitch(sd));
1264 RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain));
1268 case k7zIdMTime
: RINOK(ReadTime(&p
->MTime
, numFiles
, sd
, tempBufs
, *numTempBufs
, allocMain
)); break;
1269 case k7zIdCTime
: RINOK(ReadTime(&p
->CTime
, numFiles
, sd
, tempBufs
, *numTempBufs
, allocMain
)); break;
1272 SKIP_DATA(sd
, size
);
1277 if (numFiles
- numEmptyStreams
!= ssi
.NumTotalSubStreams
)
1278 return SZ_ERROR_ARCHIVE
;
1283 RINOK(ReadID(sd
, &type
));
1284 if (type
== k7zIdEnd
)
1286 RINOK(SkipData(sd
));
1291 UInt32 emptyFileIndex
= 0;
1292 UInt32 folderIndex
= 0;
1293 UInt32 remSubStreams
= 0;
1294 UInt32 numSubStreams
= 0;
1295 UInt64 unpackPos
= 0;
1296 const Byte
*digestsDefs
= NULL
;
1297 const Byte
*digestsVals
= NULL
;
1298 UInt32 digestsValsIndex
= 0;
1300 Byte allDigestsDefined
= 0;
1305 MY_ALLOC(UInt32
, p
->FolderToFile
, p
->db
.NumFolders
+ 1, allocMain
);
1306 MY_ALLOC_ZE(UInt32
, p
->FileToFolder
, p
->NumFiles
, allocMain
);
1307 MY_ALLOC(UInt64
, p
->UnpackPositions
, p
->NumFiles
+ 1, allocMain
);
1308 MY_ALLOC_ZE(Byte
, p
->IsDirs
, (p
->NumFiles
+ 7) >> 3, allocMain
);
1310 RINOK(SzBitUi32s_Alloc(&p
->CRCs
, p
->NumFiles
, allocMain
));
1312 if (ssi
.sdCRCs
.Size
!= 0)
1314 SZ_READ_BYTE_SD(&ssi
.sdCRCs
, allDigestsDefined
);
1315 if (allDigestsDefined
)
1316 digestsVals
= ssi
.sdCRCs
.Data
;
1319 size_t numBytes
= (ssi
.NumSubDigests
+ 7) >> 3;
1320 digestsDefs
= ssi
.sdCRCs
.Data
;
1321 digestsVals
= digestsDefs
+ numBytes
;
1327 for (i
= 0; i
< numFiles
; i
++, mask
>>= 1)
1331 UInt32 byteIndex
= (i
- 1) >> 3;
1332 p
->IsDirs
[byteIndex
] = isDirMask
;
1333 p
->CRCs
.Defs
[byteIndex
] = crcMask
;
1339 p
->UnpackPositions
[i
] = unpackPos
;
1340 p
->CRCs
.Vals
[i
] = 0;
1342 if (emptyStreams
&& SzBitArray_Check(emptyStreams
, i
))
1346 if (!SzBitArray_Check(emptyFiles
, emptyFileIndex
))
1352 if (remSubStreams
== 0)
1354 p
->FileToFolder
[i
] = (UInt32
)-1;
1359 if (remSubStreams
== 0)
1363 if (folderIndex
>= p
->db
.NumFolders
)
1364 return SZ_ERROR_ARCHIVE
;
1365 p
->FolderToFile
[folderIndex
] = i
;
1367 if (ssi
.sdNumSubStreams
.Data
)
1369 RINOK(SzReadNumber32(&ssi
.sdNumSubStreams
, &numSubStreams
));
1371 remSubStreams
= numSubStreams
;
1372 if (numSubStreams
!= 0)
1375 UInt64 folderUnpackSize
= SzAr_GetFolderUnpackSize(&p
->db
, folderIndex
);
1376 unpackPos
+= folderUnpackSize
;
1377 if (unpackPos
< folderUnpackSize
)
1378 return SZ_ERROR_ARCHIVE
;
1385 p
->FileToFolder
[i
] = folderIndex
;
1387 if (emptyStreams
&& SzBitArray_Check(emptyStreams
, i
))
1390 if (--remSubStreams
== 0)
1392 UInt64 folderUnpackSize
= SzAr_GetFolderUnpackSize(&p
->db
, folderIndex
);
1393 UInt64 startFolderUnpackPos
= p
->UnpackPositions
[p
->FolderToFile
[folderIndex
]];
1394 if (folderUnpackSize
< unpackPos
- startFolderUnpackPos
)
1395 return SZ_ERROR_ARCHIVE
;
1396 unpackPos
= startFolderUnpackPos
+ folderUnpackSize
;
1397 if (unpackPos
< folderUnpackSize
)
1398 return SZ_ERROR_ARCHIVE
;
1400 if (numSubStreams
== 1 && SzBitWithVals_Check(&p
->db
.FolderCRCs
, i
))
1402 p
->CRCs
.Vals
[i
] = p
->db
.FolderCRCs
.Vals
[folderIndex
];
1405 else if (allDigestsDefined
|| (digestsDefs
&& SzBitArray_Check(digestsDefs
, digestIndex
)))
1407 p
->CRCs
.Vals
[i
] = GetUi32(digestsVals
+ (size_t)digestsValsIndex
* 4);
1417 RINOK(ReadNumber(&ssi
.sdSizes
, &v
));
1420 return SZ_ERROR_ARCHIVE
;
1421 if (allDigestsDefined
|| (digestsDefs
&& SzBitArray_Check(digestsDefs
, digestIndex
)))
1423 p
->CRCs
.Vals
[i
] = GetUi32(digestsVals
+ (size_t)digestsValsIndex
* 4);
1432 UInt32 byteIndex
= (i
- 1) >> 3;
1433 p
->IsDirs
[byteIndex
] = isDirMask
;
1434 p
->CRCs
.Defs
[byteIndex
] = crcMask
;
1437 p
->UnpackPositions
[i
] = unpackPos
;
1439 if (remSubStreams
!= 0)
1440 return SZ_ERROR_ARCHIVE
;
1444 p
->FolderToFile
[folderIndex
] = i
;
1445 if (folderIndex
>= p
->db
.NumFolders
)
1447 if (!ssi
.sdNumSubStreams
.Data
)
1448 return SZ_ERROR_ARCHIVE
;
1449 RINOK(SzReadNumber32(&ssi
.sdNumSubStreams
, &numSubStreams
));
1450 if (numSubStreams
!= 0)
1451 return SZ_ERROR_ARCHIVE
;
1454 UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1455 unpackPos += folderUnpackSize;
1456 if (unpackPos < folderUnpackSize)
1457 return SZ_ERROR_ARCHIVE;
1463 if (ssi
.sdNumSubStreams
.Data
&& ssi
.sdNumSubStreams
.Size
!= 0)
1464 return SZ_ERROR_ARCHIVE
;
1471 static SRes
SzReadHeader(
1474 ILookInStream
*inStream
,
1475 ISzAllocPtr allocMain
,
1476 ISzAllocPtr allocTemp
)
1479 UInt32 numTempBufs
= 0;
1481 CBuf tempBufs
[NUM_ADDITIONAL_STREAMS_MAX
];
1483 for (i
= 0; i
< NUM_ADDITIONAL_STREAMS_MAX
; i
++)
1484 Buf_Init(tempBufs
+ i
);
1486 res
= SzReadHeader2(p
, sd
, inStream
,
1487 tempBufs
, &numTempBufs
,
1488 allocMain
, allocTemp
);
1490 for (i
= 0; i
< NUM_ADDITIONAL_STREAMS_MAX
; i
++)
1491 Buf_Free(tempBufs
+ i
, allocTemp
);
1496 return SZ_ERROR_FAIL
;
1501 static SRes
SzArEx_Open2(
1503 ILookInStream
*inStream
,
1504 ISzAllocPtr allocMain
,
1505 ISzAllocPtr allocTemp
)
1507 Byte header
[k7zStartHeaderSize
];
1509 UInt64 nextHeaderOffset
, nextHeaderSize
;
1510 size_t nextHeaderSizeT
;
1511 UInt32 nextHeaderCRC
;
1516 RINOK(ILookInStream_Seek(inStream
, &startArcPos
, SZ_SEEK_CUR
));
1518 RINOK(LookInStream_Read2(inStream
, header
, k7zStartHeaderSize
, SZ_ERROR_NO_ARCHIVE
));
1520 if (!TestSignatureCandidate(header
))
1521 return SZ_ERROR_NO_ARCHIVE
;
1522 if (header
[6] != k7zMajorVersion
)
1523 return SZ_ERROR_UNSUPPORTED
;
1525 nextHeaderOffset
= GetUi64(header
+ 12);
1526 nextHeaderSize
= GetUi64(header
+ 20);
1527 nextHeaderCRC
= GetUi32(header
+ 28);
1529 p
->startPosAfterHeader
= startArcPos
+ k7zStartHeaderSize
;
1531 if (CrcCalc(header
+ 12, 20) != GetUi32(header
+ 8))
1532 return SZ_ERROR_CRC
;
1534 nextHeaderSizeT
= (size_t)nextHeaderSize
;
1535 if (nextHeaderSizeT
!= nextHeaderSize
)
1536 return SZ_ERROR_MEM
;
1537 if (nextHeaderSizeT
== 0)
1539 if (nextHeaderOffset
> nextHeaderOffset
+ nextHeaderSize
||
1540 nextHeaderOffset
> nextHeaderOffset
+ nextHeaderSize
+ k7zStartHeaderSize
)
1541 return SZ_ERROR_NO_ARCHIVE
;
1545 RINOK(ILookInStream_Seek(inStream
, &pos
, SZ_SEEK_END
));
1546 if ((UInt64
)pos
< startArcPos
+ nextHeaderOffset
||
1547 (UInt64
)pos
< startArcPos
+ k7zStartHeaderSize
+ nextHeaderOffset
||
1548 (UInt64
)pos
< startArcPos
+ k7zStartHeaderSize
+ nextHeaderOffset
+ nextHeaderSize
)
1549 return SZ_ERROR_INPUT_EOF
;
1552 RINOK(LookInStream_SeekTo(inStream
, startArcPos
+ k7zStartHeaderSize
+ nextHeaderOffset
));
1554 if (!Buf_Create(&buf
, nextHeaderSizeT
, allocTemp
))
1555 return SZ_ERROR_MEM
;
1557 res
= LookInStream_Read(inStream
, buf
.data
, nextHeaderSizeT
);
1561 res
= SZ_ERROR_ARCHIVE
;
1562 if (CrcCalc(buf
.data
, nextHeaderSizeT
) == nextHeaderCRC
)
1569 res
= ReadID(&sd
, &type
);
1571 if (res
== SZ_OK
&& type
== k7zIdEncodedHeader
)
1578 res
= SzReadAndDecodePackedStreams(inStream
, &sd
, &tempBuf
, 1, p
->startPosAfterHeader
, &tempAr
, allocTemp
);
1579 SzAr_Free(&tempAr
, allocTemp
);
1583 Buf_Free(&tempBuf
, allocTemp
);
1587 Buf_Free(&buf
, allocTemp
);
1588 buf
.data
= tempBuf
.data
;
1589 buf
.size
= tempBuf
.size
;
1592 res
= ReadID(&sd
, &type
);
1598 if (type
== k7zIdHeader
)
1603 for (ttt = 0; ttt < 40000; ttt++)
1605 SzArEx_Free(p, allocMain);
1607 res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp);
1612 res
= SzReadHeader(p
, &sd
, inStream
, allocMain
, allocTemp
);
1615 res
= SZ_ERROR_UNSUPPORTED
;
1620 Buf_Free(&buf
, allocTemp
);
1625 SRes
SzArEx_Open(CSzArEx
*p
, ILookInStream
*inStream
,
1626 ISzAllocPtr allocMain
, ISzAllocPtr allocTemp
)
1628 SRes res
= SzArEx_Open2(p
, inStream
, allocMain
, allocTemp
);
1630 SzArEx_Free(p
, allocMain
);
1635 SRes
SzArEx_Extract(
1637 ILookInStream
*inStream
,
1641 size_t *outBufferSize
,
1643 size_t *outSizeProcessed
,
1644 ISzAllocPtr allocMain
,
1645 ISzAllocPtr allocTemp
)
1647 UInt32 folderIndex
= p
->FileToFolder
[fileIndex
];
1651 *outSizeProcessed
= 0;
1653 if (folderIndex
== (UInt32
)-1)
1655 ISzAlloc_Free(allocMain
, *tempBuf
);
1656 *blockIndex
= folderIndex
;
1662 if (*tempBuf
== NULL
|| *blockIndex
!= folderIndex
)
1664 UInt64 unpackSizeSpec
= SzAr_GetFolderUnpackSize(&p
->db
, folderIndex
);
1666 UInt64 unpackSizeSpec =
1667 p->UnpackPositions[p->FolderToFile[(size_t)folderIndex + 1]] -
1668 p->UnpackPositions[p->FolderToFile[folderIndex]];
1670 size_t unpackSize
= (size_t)unpackSizeSpec
;
1672 if (unpackSize
!= unpackSizeSpec
)
1673 return SZ_ERROR_MEM
;
1674 *blockIndex
= folderIndex
;
1675 ISzAlloc_Free(allocMain
, *tempBuf
);
1680 *outBufferSize
= unpackSize
;
1681 if (unpackSize
!= 0)
1683 *tempBuf
= (Byte
*)ISzAlloc_Alloc(allocMain
, unpackSize
);
1684 if (*tempBuf
== NULL
)
1690 res
= SzAr_DecodeFolder(&p
->db
, folderIndex
,
1691 inStream
, p
->dataPos
, *tempBuf
, unpackSize
, allocTemp
);
1698 UInt64 unpackPos
= p
->UnpackPositions
[fileIndex
];
1699 *offset
= (size_t)(unpackPos
- p
->UnpackPositions
[p
->FolderToFile
[folderIndex
]]);
1700 *outSizeProcessed
= (size_t)(p
->UnpackPositions
[(size_t)fileIndex
+ 1] - unpackPos
);
1701 if (*offset
+ *outSizeProcessed
> *outBufferSize
)
1702 return SZ_ERROR_FAIL
;
1703 if (SzBitWithVals_Check(&p
->CRCs
, fileIndex
))
1704 if (CrcCalc(*tempBuf
+ *offset
, *outSizeProcessed
) != p
->CRCs
.Vals
[fileIndex
])
1712 size_t SzArEx_GetFileNameUtf16(const CSzArEx
*p
, size_t fileIndex
, UInt16
*dest
)
1714 size_t offs
= p
->FileNameOffsets
[fileIndex
];
1715 size_t len
= p
->FileNameOffsets
[fileIndex
+ 1] - offs
;
1719 const Byte
*src
= p
->FileNames
+ offs
* 2;
1720 for (i
= 0; i
< len
; i
++)
1721 dest
[i
] = GetUi16(src
+ i
* 2);
1727 size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex)
1730 if (!p->FileNameOffsets)
1735 UInt32 parent = (UInt32)(Int32)-1;
1736 len += p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
1737 if SzBitWithVals_Check(&p->Parents, fileIndex)
1738 parent = p->Parents.Vals[fileIndex];
1739 if (parent == (UInt32)(Int32)-1)
1745 UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
1748 if (!p->FileNameOffsets)
1756 UInt32 parent = (UInt32)(Int32)-1;
1757 size_t curLen = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
1758 SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen);
1764 if SzBitWithVals_Check(&p->Parents, fileIndex)
1765 parent = p->Parents.Vals[fileIndex];
1766 if (parent == (UInt32)(Int32)-1)