Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

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