15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 7zIn.c -- 7z Input functions
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)2010-10-29 : Igor Pavlov : Public domain */
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "7z.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "7zCrc.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "CpuArch.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; }
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NUM_FOLDER_CODERS_MAX 32
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NUM_CODER_STREAMS_MAX 32
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SzCoderInfo_Init(CSzCoderInfo *p)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Buf_Init(&p->Props);
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Buf_Free(&p->Props, alloc);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SzCoderInfo_Init(p);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SzFolder_Init(CSzFolder *p)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->Coders = 0;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->BindPairs = 0;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->PackStreams = 0;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->UnpackSizes = 0;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->NumCoders = 0;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->NumBindPairs = 0;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->NumPackStreams = 0;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->UnpackCRCDefined = 0;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->UnpackCRC = 0;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->NumUnpackStreams = 0;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 i;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (p->Coders)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < p->NumCoders; i++)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SzCoderInfo_Free(&p->Coders[i], alloc);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(alloc, p->Coders);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(alloc, p->BindPairs);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(alloc, p->PackStreams);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(alloc, p->UnpackSizes);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SzFolder_Init(p);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 result = 0;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 i;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < p->NumCoders; i++)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result += p->Coders[i].NumOutStreams;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 i;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < p->NumBindPairs; i++)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (p->BindPairs[i].InIndex == inStreamIndex)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return i;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return -1;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 i;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < p->NumBindPairs; i++)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (p->BindPairs[i].OutIndex == outStreamIndex)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return i;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return -1;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UInt64 SzFolder_GetUnpackSize(CSzFolder *p)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i = (int)SzFolder_GetNumOutStreams(p);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == 0)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i--; i >= 0; i--)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SzFolder_FindBindPairForOutStream(p, i) < 0)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return p->UnpackSizes[i];
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* throw 1; */
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SzFile_Init(CSzFileItem *p)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->HasStream = 1;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->IsDir = 0;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->IsAnti = 0;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->CrcDefined = 0;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->MTimeDefined = 0;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SzAr_Init(CSzAr *p)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->PackSizes = 0;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->PackCRCsDefined = 0;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->PackCRCs = 0;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->Folders = 0;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->Files = 0;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->NumPackStreams = 0;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->NumFolders = 0;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->NumFiles = 0;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 i;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (p->Folders)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < p->NumFolders; i++)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SzFolder_Free(&p->Folders[i], alloc);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(alloc, p->PackSizes);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(alloc, p->PackCRCsDefined);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(alloc, p->PackCRCs);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(alloc, p->Folders);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(alloc, p->Files);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SzAr_Init(p);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SzArEx_Init(CSzArEx *p)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SzAr_Init(&p->db);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->FolderStartPackStreamIndex = 0;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->PackStreamStartPositions = 0;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->FolderStartFileIndex = 0;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->FileIndexToFolderIndexMap = 0;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->FileNameOffsets = 0;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Buf_Init(&p->FileNames);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(alloc, p->FolderStartPackStreamIndex);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(alloc, p->PackStreamStartPositions);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(alloc, p->FolderStartFileIndex);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(alloc, p->FileIndexToFolderIndexMap);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(alloc, p->FileNameOffsets);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Buf_Free(&p->FileNames, alloc);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SzAr_Free(&p->db, alloc);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SzArEx_Init(p);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UInt64 GetFilePackSize(int fileIndex) const
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int folderIndex = FileIndexToFolderIndexMap[fileIndex];
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (folderIndex >= 0)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CSzFolder &folderInfo = Folders[folderIndex];
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FolderStartFileIndex[folderIndex] == fileIndex)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetFolderFullPackSize(folderIndex);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 startPos = 0;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt64 startPosSize = 0;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 i;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 folderIndex = 0;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 indexInFolder = 0;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < p->db.NumFolders; i++)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->FolderStartPackStreamIndex[i] = startPos;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    startPos += p->db.Folders[i].NumPackStreams;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < p->db.NumPackStreams; i++)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->PackStreamStartPositions[i] = startPosSize;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    startPosSize += p->db.PackSizes[i];
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < p->db.NumFiles; i++)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzFileItem *file = p->db.Files + i;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int emptyStream = !file->HasStream;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (emptyStream && indexInFolder == 0)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->FileIndexToFolderIndexMap[i] = (UInt32)-1;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (indexInFolder == 0)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /*
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      v3.13 incorrectly worked with empty folders
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      v4.07: Loop for skipping empty folders
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (;;)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (folderIndex >= p->db.NumFolders)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return SZ_ERROR_ARCHIVE;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        p->FolderStartFileIndex[folderIndex] = i;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (p->db.Folders[folderIndex].NumUnpackStreams != 0)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        folderIndex++;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->FileIndexToFolderIndexMap[i] = folderIndex;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (emptyStream)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    indexInFolder++;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      folderIndex++;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      indexInFolder = 0;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return p->dataPos +
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder];
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex];
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CSzFolder *folder = p->db.Folders + folderIndex;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt64 size = 0;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 i;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < folder->NumPackStreams; i++)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 t = size + p->db.PackSizes[packStreamIndex + i];
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (t < size) /* check it */
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SZ_ERROR_FAIL;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size = t;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *resSize = size;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SRes SzReadTime(const CObjectVector<CBuf> &dataVector,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CObjectVector<CSzFileItem> &files, UInt64 type)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CBoolVector boolVector;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(ReadBoolVector2(files.Size(), boolVector))
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CStreamSwitch streamSwitch;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(streamSwitch.Set(this, &dataVector));
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < files.Size(); i++)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzFileItem &file = files[i];
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CArchiveFileTime fileTime;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool defined = boolVector[i];
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (defined)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UInt32 low, high;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(SzReadUInt32(low));
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(SzReadUInt32(high));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fileTime.dwLowDateTime = low;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fileTime.dwHighDateTime = high;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch(type)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int TestSignatureCandidate(Byte *testBytes)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t i;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < k7zSignatureSize; i++)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (testBytes[i] != k7zSignature[i])
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct _CSzState
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Byte *Data;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t Size;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}CSzData;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadByte(CSzData *sd, Byte *b)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sd->Size == 0)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_ARCHIVE;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sd->Size--;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *b = *sd->Data++;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadBytes(CSzData *sd, Byte *data, size_t size)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t i;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < size; i++)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadByte(sd, data + i));
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadUInt32(CSzData *sd, UInt32 *value)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *value = 0;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < 4; i++)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Byte b;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadByte(sd, &b));
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *value |= ((UInt32)(b) << (8 * i));
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadNumber(CSzData *sd, UInt64 *value)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Byte firstByte;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Byte mask = 0x80;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzReadByte(sd, &firstByte));
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *value = 0;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < 8; i++)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Byte b;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((firstByte & mask) == 0)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UInt64 highPart = firstByte & (mask - 1);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *value += (highPart << (8 * i));
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SZ_OK;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadByte(sd, &b));
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *value |= ((UInt64)b << (8 * i));
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mask >>= 1;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadNumber32(CSzData *sd, UInt32 *value)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt64 value64;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzReadNumber(sd, &value64));
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (value64 >= 0x80000000)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_UNSUPPORTED;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2)))
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_UNSUPPORTED;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *value = (UInt32)value64;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadID(CSzData *sd, UInt64 *value)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SzReadNumber(sd, value);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzSkeepDataSize(CSzData *sd, UInt64 size)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size > sd->Size)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_ARCHIVE;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sd->Size -= (size_t)size;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sd->Data += (size_t)size;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzSkeepData(CSzData *sd)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt64 size;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzReadNumber(sd, &size));
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SzSkeepDataSize(sd, size);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadArchiveProperties(CSzData *sd)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (;;)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 type;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadID(sd, &type));
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == k7zIdEnd)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SzSkeepData(sd);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (;;)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 type;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadID(sd, &type));
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == attribute)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SZ_OK;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == k7zIdEnd)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SZ_ERROR_ARCHIVE;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzSkeepData(sd));
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Byte b = 0;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Byte mask = 0;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t i;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MY_ALLOC(Byte, *v, numItems, alloc);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < numItems; i++)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mask == 0)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(SzReadByte(sd, &b));
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mask = 0x80;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mask >>= 1;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Byte allAreDefined;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t i;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzReadByte(sd, &allAreDefined));
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (allAreDefined == 0)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SzReadBoolVector(sd, numItems, v, alloc);
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MY_ALLOC(Byte, *v, numItems, alloc);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < numItems; i++)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*v)[i] = 1;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadHashDigests(
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzData *sd,
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t numItems,
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Byte **digestsDefined,
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 **digests,
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *alloc)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t i;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc));
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MY_ALLOC(UInt32, *digests, numItems, alloc);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < numItems; i++)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*digestsDefined)[i])
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(SzReadUInt32(sd, (*digests) + i));
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadPackInfo(
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzData *sd,
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 *dataOffset,
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 *numPackStreams,
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 **packSizes,
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Byte **packCRCsDefined,
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 **packCRCs,
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *alloc)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 i;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzReadNumber(sd, dataOffset));
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzReadNumber32(sd, numPackStreams));
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzWaitAttribute(sd, k7zIdSize));
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < *numPackStreams; i++)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadNumber(sd, (*packSizes) + i));
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (;;)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 type;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadID(sd, &type));
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == k7zIdEnd)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == k7zIdCRC)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, alloc));
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzSkeepData(sd));
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*packCRCsDefined == 0)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc);
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < *numPackStreams; i++)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*packCRCsDefined)[i] = 0;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*packCRCs)[i] = 0;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadSwitch(CSzData *sd)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Byte external;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzReadByte(sd, &external));
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 numCoders, numBindPairs, numPackStreams, i;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 numInStreams = 0, numOutStreams = 0;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzReadNumber32(sd, &numCoders));
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (numCoders > NUM_FOLDER_CODERS_MAX)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_UNSUPPORTED;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  folder->NumCoders = numCoders;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < numCoders; i++)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SzCoderInfo_Init(folder->Coders + i);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < numCoders; i++)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Byte mainByte;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzCoderInfo *coder = folder->Coders + i;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned idSize, j;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Byte longID[15];
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(SzReadByte(sd, &mainByte));
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      idSize = (unsigned)(mainByte & 0xF);
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(SzReadBytes(sd, longID, idSize));
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (idSize > sizeof(coder->MethodID))
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SZ_ERROR_UNSUPPORTED;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coder->MethodID = 0;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (j = 0; j < idSize; j++)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((mainByte & 0x10) != 0)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadNumber32(sd, &coder->NumInStreams));
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadNumber32(sd, &coder->NumOutStreams));
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (coder->NumInStreams > NUM_CODER_STREAMS_MAX ||
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            coder->NumOutStreams > NUM_CODER_STREAMS_MAX)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return SZ_ERROR_UNSUPPORTED;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        coder->NumInStreams = 1;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        coder->NumOutStreams = 1;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((mainByte & 0x20) != 0)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UInt64 propertiesSize = 0;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadNumber(sd, &propertiesSize));
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc))
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return SZ_ERROR_MEM;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize));
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while ((mainByte & 0x80) != 0)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(SzReadByte(sd, &mainByte));
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(SzSkeepDataSize(sd, (mainByte & 0xF)));
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((mainByte & 0x10) != 0)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UInt32 n;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadNumber32(sd, &n));
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadNumber32(sd, &n));
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((mainByte & 0x20) != 0)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UInt64 propertiesSize = 0;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadNumber(sd, &propertiesSize));
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzSkeepDataSize(sd, propertiesSize));
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    numInStreams += coder->NumInStreams;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    numOutStreams += coder->NumOutStreams;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (numOutStreams == 0)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_UNSUPPORTED;
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  folder->NumBindPairs = numBindPairs = numOutStreams - 1;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MY_ALLOC(CSzBindPair, folder->BindPairs, (size_t)numBindPairs, alloc);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < numBindPairs; i++)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzBindPair *bp = folder->BindPairs + i;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadNumber32(sd, &bp->InIndex));
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadNumber32(sd, &bp->OutIndex));
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (numInStreams < numBindPairs)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_UNSUPPORTED;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc);
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (numPackStreams == 1)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < numInStreams ; i++)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (SzFolder_FindBindPairForInStream(folder, i) < 0)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i == numInStreams)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SZ_ERROR_UNSUPPORTED;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    folder->PackStreams[0] = i;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < numPackStreams; i++)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(SzReadNumber32(sd, folder->PackStreams + i));
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadUnpackInfo(
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzData *sd,
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 *numFolders,
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzFolder **folders,  /* for alloc */
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *alloc,
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *allocTemp)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 i;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzWaitAttribute(sd, k7zIdFolder));
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzReadNumber32(sd, numFolders));
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadSwitch(sd));
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc);
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < *numFolders; i++)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SzFolder_Init((*folders) + i);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < *numFolders; i++)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc));
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize));
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < *numFolders; i++)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 j;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzFolder *folder = (*folders) + i;
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder);
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc);
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (j = 0; j < numOutStreams; j++)
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(SzReadNumber(sd, folder->UnpackSizes + j));
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (;;)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 type;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadID(sd, &type));
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == k7zIdEnd)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SZ_OK;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == k7zIdCRC)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SRes res;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Byte *crcsDefined = 0;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UInt32 *crcs = 0;
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (res == SZ_OK)
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = 0; i < *numFolders; i++)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CSzFolder *folder = (*folders) + i;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          folder->UnpackCRCDefined = crcsDefined[i];
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          folder->UnpackCRC = crcs[i];
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IAlloc_Free(allocTemp, crcs);
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IAlloc_Free(allocTemp, crcsDefined);
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(res);
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzSkeepData(sd));
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadSubStreamsInfo(
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzData *sd,
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 numFolders,
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzFolder *folders,
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 *numUnpackStreams,
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 **unpackSizes,
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Byte **digestsDefined,
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 **digests,
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *allocTemp)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt64 type = 0;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 i;
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 si = 0;
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 numDigests = 0;
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < numFolders; i++)
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    folders[i].NumUnpackStreams = 1;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *numUnpackStreams = numFolders;
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (;;)
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadID(sd, &type));
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == k7zIdNumUnpackStream)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *numUnpackStreams = 0;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (i = 0; i < numFolders; i++)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UInt32 numStreams;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadNumber32(sd, &numStreams));
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        folders[i].NumUnpackStreams = numStreams;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *numUnpackStreams += numStreams;
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == k7zIdCRC || type == k7zIdSize)
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == k7zIdEnd)
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzSkeepData(sd));
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*numUnpackStreams == 0)
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *unpackSizes = 0;
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *digestsDefined = 0;
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *digests = 0;
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64));
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOM(*unpackSizes);
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte));
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOM(*digestsDefined);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32));
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOM(*digests);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < numFolders; i++)
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v3.13 incorrectly worked with empty folders
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v4.07: we check that folder is empty
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 sum = 0;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 j;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 numSubstreams = folders[i].NumUnpackStreams;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (numSubstreams == 0)
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == k7zIdSize)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (j = 1; j < numSubstreams; j++)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UInt64 size;
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(SzReadNumber(sd, &size));
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*unpackSizes)[si++] = size;
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sum += size;
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum;
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == k7zIdSize)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadID(sd, &type));
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < *numUnpackStreams; i++)
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*digestsDefined)[i] = 0;
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*digests)[i] = 0;
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < numFolders; i++)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 numSubstreams = folders[i].NumUnpackStreams;
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (numSubstreams != 1 || !folders[i].UnpackCRCDefined)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      numDigests += numSubstreams;
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  si = 0;
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (;;)
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == k7zIdCRC)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int digestIndex = 0;
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Byte *digestsDefined2 = 0;
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UInt32 *digests2 = 0;
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (res == SZ_OK)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = 0; i < numFolders; i++)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CSzFolder *folder = folders + i;
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          UInt32 numSubstreams = folder->NumUnpackStreams;
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (numSubstreams == 1 && folder->UnpackCRCDefined)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          {
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (*digestsDefined)[si] = 1;
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (*digests)[si] = folder->UnpackCRC;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            si++;
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          else
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          {
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            UInt32 j;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (j = 0; j < numSubstreams; j++, digestIndex++)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (*digestsDefined)[si] = digestsDefined2[digestIndex];
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (*digests)[si] = digests2[digestIndex];
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              si++;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IAlloc_Free(allocTemp, digestsDefined2);
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IAlloc_Free(allocTemp, digests2);
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(res);
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (type == k7zIdEnd)
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SZ_OK;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(SzSkeepData(sd));
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadID(sd, &type));
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadStreamsInfo(
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzData *sd,
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 *dataOffset,
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzAr *p,
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 *numUnpackStreams,
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 **unpackSizes, /* allocTemp */
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Byte **digestsDefined,   /* allocTemp */
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 **digests,        /* allocTemp */
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *alloc,
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *allocTemp)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (;;)
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 type;
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadID(sd, &type));
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((UInt64)(int)type != type)
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SZ_ERROR_UNSUPPORTED;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch((int)type)
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case k7zIdEnd:
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SZ_OK;
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case k7zIdPackInfo:
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams,
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc));
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case k7zIdUnpackInfo:
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp));
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case k7zIdSubStreamsInfo:
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders,
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp));
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SZ_ERROR_UNSUPPORTED;
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t len = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dest != 0)
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t i;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Byte *src = p->FileNames.data + (p->FileNameOffsets[fileIndex] * 2);
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < len; i++)
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dest[i] = GetUi16(src + i * 2);
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return len;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadFileNames(const Byte *p, size_t size, UInt32 numFiles, size_t *sizes)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 i;
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t pos = 0;
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < numFiles; i++)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sizes[i] = pos;
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (;;)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (pos >= size)
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SZ_ERROR_ARCHIVE;
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (p[pos * 2] == 0 && p[pos * 2 + 1] == 0)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pos++;
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos++;
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sizes[i] = pos;
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadHeader2(
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzArEx *p,   /* allocMain */
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzData *sd,
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 **unpackSizes,  /* allocTemp */
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Byte **digestsDefined,    /* allocTemp */
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 **digests,         /* allocTemp */
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Byte **emptyStreamVector, /* allocTemp */
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Byte **emptyFileVector,   /* allocTemp */
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Byte **lwtVector,         /* allocTemp */
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *allocMain,
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *allocTemp)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt64 type;
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 numUnpackStreams = 0;
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 numFiles = 0;
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CSzFileItem *files = 0;
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 numEmptyStreams = 0;
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 i;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzReadID(sd, &type));
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == k7zIdArchiveProperties)
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadArchiveProperties(sd));
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadID(sd, &type));
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == k7zIdMainStreamsInfo)
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadStreamsInfo(sd,
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &p->dataPos,
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &p->db,
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &numUnpackStreams,
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unpackSizes,
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        digestsDefined,
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        digests, allocMain, allocTemp));
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->dataPos += p->startPosAfterHeader;
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadID(sd, &type));
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == k7zIdEnd)
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_OK;
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type != k7zIdFilesInfo)
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_ARCHIVE;
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzReadNumber32(sd, &numFiles));
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->db.NumFiles = numFiles;
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain);
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->db.Files = files;
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < numFiles; i++)
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SzFile_Init(files + i);
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (;;)
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 type;
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 size;
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadID(sd, &type));
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == k7zIdEnd)
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(SzReadNumber(sd, &size));
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size > sd->Size)
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SZ_ERROR_ARCHIVE;
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((UInt64)(int)type != type)
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RINOK(SzSkeepDataSize(sd, size));
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch((int)type)
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case k7zIdName:
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t namesSize;
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadSwitch(sd));
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        namesSize = (size_t)size - 1;
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((namesSize & 1) != 0)
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return SZ_ERROR_ARCHIVE;
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!Buf_Create(&p->FileNames, namesSize, allocMain))
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return SZ_ERROR_MEM;
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain);
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(p->FileNames.data, sd->Data, namesSize);
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets))
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzSkeepDataSize(sd, namesSize));
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case k7zIdEmptyStream:
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp));
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        numEmptyStreams = 0;
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = 0; i < numFiles; i++)
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if ((*emptyStreamVector)[i])
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            numEmptyStreams++;
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case k7zIdEmptyFile:
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp));
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case k7zIdWinAttributes:
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadSwitch(sd));
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = 0; i < numFiles; i++)
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CSzFileItem *f = &files[i];
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          Byte defined = (*lwtVector)[i];
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          f->AttribDefined = defined;
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          f->Attrib = 0;
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (defined)
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          {
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            RINOK(SzReadUInt32(sd, &f->Attrib));
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IAlloc_Free(allocTemp, *lwtVector);
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *lwtVector = NULL;
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case k7zIdMTime:
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzReadSwitch(sd));
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = 0; i < numFiles; i++)
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CSzFileItem *f = &files[i];
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          Byte defined = (*lwtVector)[i];
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          f->MTimeDefined = defined;
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          f->MTime.Low = f->MTime.High = 0;
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (defined)
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          {
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            RINOK(SzReadUInt32(sd, &f->MTime.Low));
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            RINOK(SzReadUInt32(sd, &f->MTime.High));
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IAlloc_Free(allocTemp, *lwtVector);
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *lwtVector = NULL;
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RINOK(SzSkeepDataSize(sd, size));
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 emptyFileIndex = 0;
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 sizeIndex = 0;
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < numFiles; i++)
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CSzFileItem *file = files + i;
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      file->IsAnti = 0;
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (*emptyStreamVector == 0)
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file->HasStream = 1;
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1);
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (file->HasStream)
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file->IsDir = 0;
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file->Size = (*unpackSizes)[sizeIndex];
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file->Crc = (*digests)[sizeIndex];
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file->CrcDefined = (Byte)(*digestsDefined)[sizeIndex];
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sizeIndex++;
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (*emptyFileVector == 0)
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          file->IsDir = 1;
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        emptyFileIndex++;
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file->Size = 0;
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file->Crc = 0;
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file->CrcDefined = 0;
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SzArEx_Fill(p, allocMain);
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadHeader(
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzArEx *p,
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzData *sd,
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *allocMain,
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *allocTemp)
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt64 *unpackSizes = 0;
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Byte *digestsDefined = 0;
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 *digests = 0;
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Byte *emptyStreamVector = 0;
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Byte *emptyFileVector = 0;
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Byte *lwtVector = 0;
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SRes res = SzReadHeader2(p, sd,
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &unpackSizes, &digestsDefined, &digests,
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &emptyStreamVector, &emptyFileVector, &lwtVector,
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allocMain, allocTemp);
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(allocTemp, unpackSizes);
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(allocTemp, digestsDefined);
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(allocTemp, digests);
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(allocTemp, emptyStreamVector);
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(allocTemp, emptyFileVector);
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(allocTemp, lwtVector);
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return res;
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadAndDecodePackedStreams2(
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ILookInStream *inStream,
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzData *sd,
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CBuf *outBuffer,
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 baseOffset,
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzAr *p,
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 **unpackSizes,
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Byte **digestsDefined,
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 **digests,
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *allocTemp)
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 numUnpackStreams = 0;
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt64 dataStartPos;
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CSzFolder *folder;
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt64 unpackSize;
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SRes res;
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(SzReadStreamsInfo(sd, &dataStartPos, p,
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &numUnpackStreams,  unpackSizes, digestsDefined, digests,
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allocTemp, allocTemp));
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dataStartPos += baseOffset;
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (p->NumFolders != 1)
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_ARCHIVE;
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  folder = p->Folders;
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unpackSize = SzFolder_GetUnpackSize(folder);
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(LookInStream_SeekTo(inStream, dataStartPos));
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp))
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_MEM;
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = SzFolder_Decode(folder, p->PackSizes,
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          inStream, dataStartPos,
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          outBuffer->data, (size_t)unpackSize, allocTemp);
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(res);
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (folder->UnpackCRCDefined)
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC)
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SZ_ERROR_CRC;
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SZ_OK;
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzReadAndDecodePackedStreams(
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ILookInStream *inStream,
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzData *sd,
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CBuf *outBuffer,
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 baseOffset,
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *allocTemp)
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CSzAr p;
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt64 *unpackSizes = 0;
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Byte *digestsDefined = 0;
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 *digests = 0;
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SRes res;
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SzAr_Init(&p);
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset,
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    &p, &unpackSizes, &digestsDefined, &digests,
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allocTemp);
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SzAr_Free(&p, allocTemp);
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(allocTemp, unpackSizes);
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(allocTemp, digestsDefined);
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IAlloc_Free(allocTemp, digests);
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return res;
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SRes SzArEx_Open2(
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzArEx *p,
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ILookInStream *inStream,
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *allocMain,
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *allocTemp)
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Byte header[k7zStartHeaderSize];
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Int64 startArcPos;
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt64 nextHeaderOffset, nextHeaderSize;
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t nextHeaderSizeT;
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 nextHeaderCRC;
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CBuf buffer;
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SRes res;
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  startArcPos = 0;
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR));
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!TestSignatureCandidate(header))
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_NO_ARCHIVE;
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header[6] != k7zMajorVersion)
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_UNSUPPORTED;
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nextHeaderOffset = GetUi64(header + 12);
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nextHeaderSize = GetUi64(header + 20);
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nextHeaderCRC = GetUi32(header + 28);
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->startPosAfterHeader = startArcPos + k7zStartHeaderSize;
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CrcCalc(header + 12, 20) != GetUi32(header + 8))
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_CRC;
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nextHeaderSizeT = (size_t)nextHeaderSize;
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nextHeaderSizeT != nextHeaderSize)
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_MEM;
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nextHeaderSizeT == 0)
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_OK;
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_NO_ARCHIVE;
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Int64 pos = 0;
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END));
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((UInt64)pos < startArcPos + nextHeaderOffset ||
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SZ_ERROR_INPUT_EOF;
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset));
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp))
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_ERROR_MEM;
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT);
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (res == SZ_OK)
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    res = SZ_ERROR_ARCHIVE;
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC)
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CSzData sd;
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UInt64 type;
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sd.Data = buffer.data;
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sd.Size = buffer.size;
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      res = SzReadID(&sd, &type);
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (res == SZ_OK)
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (type == k7zIdEncodedHeader)
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CBuf outBuffer;
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          Buf_Init(&outBuffer);
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp);
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (res != SZ_OK)
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            Buf_Free(&outBuffer, allocTemp);
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          else
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          {
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            Buf_Free(&buffer, allocTemp);
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            buffer.data = outBuffer.data;
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            buffer.size = outBuffer.size;
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sd.Data = buffer.data;
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sd.Size = buffer.size;
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            res = SzReadID(&sd, &type);
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (res == SZ_OK)
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (type == k7zIdHeader)
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          res = SzReadHeader(p, &sd, allocMain, allocTemp);
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          res = SZ_ERROR_UNSUPPORTED;
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Buf_Free(&buffer, allocTemp);
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return res;
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp)
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (res != SZ_OK)
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SzArEx_Free(p, allocMain);
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return res;
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SRes SzArEx_Extract(
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CSzArEx *p,
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ILookInStream *inStream,
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 fileIndex,
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 *blockIndex,
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Byte **outBuffer,
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t *outBufferSize,
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t *offset,
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t *outSizeProcessed,
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *allocMain,
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ISzAlloc *allocTemp)
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SRes res = SZ_OK;
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *offset = 0;
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *outSizeProcessed = 0;
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (folderIndex == (UInt32)-1)
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IAlloc_Free(allocMain, *outBuffer);
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *blockIndex = folderIndex;
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outBuffer = 0;
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outBufferSize = 0;
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SZ_OK;
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*outBuffer == 0 || *blockIndex != folderIndex)
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzFolder *folder = p->db.Folders + folderIndex;
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t unpackSize = (size_t)unpackSizeSpec;
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unpackSize != unpackSizeSpec)
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SZ_ERROR_MEM;
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *blockIndex = folderIndex;
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IAlloc_Free(allocMain, *outBuffer);
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outBuffer = 0;
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RINOK(LookInStream_SeekTo(inStream, startOffset));
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (res == SZ_OK)
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *outBufferSize = unpackSize;
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (unpackSize != 0)
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (*outBuffer == 0)
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          res = SZ_ERROR_MEM;
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (res == SZ_OK)
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        res = SzFolder_Decode(folder,
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex],
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          inStream, startOffset,
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *outBuffer, unpackSize, allocTemp);
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (res == SZ_OK)
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (folder->UnpackCRCDefined)
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          {
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              res = SZ_ERROR_CRC;
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (res == SZ_OK)
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 i;
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSzFileItem *fileItem = p->db.Files + fileIndex;
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *offset = 0;
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *offset += (UInt32)p->db.Files[i].Size;
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outSizeProcessed = (size_t)fileItem->Size;
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*offset + *outSizeProcessed > *outBufferSize)
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SZ_ERROR_FAIL;
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc)
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      res = SZ_ERROR_CRC;
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return res;
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1403