Home | History | Annotate | Download | only in C
      1 /* XzDec.c -- Xz Decode
      2 2010-04-16 : Igor Pavlov : Public domain */
      3 
      4 /* #define XZ_DUMP */
      5 
      6 #ifdef XZ_DUMP
      7 #include <stdio.h>
      8 #endif
      9 
     10 #include <stdlib.h>
     11 #include <string.h>
     12 
     13 #include "7zCrc.h"
     14 #include "Alloc.h"
     15 #include "Bra.h"
     16 #include "CpuArch.h"
     17 #include "Delta.h"
     18 #include "Lzma2Dec.h"
     19 
     20 #ifdef USE_SUBBLOCK
     21 #include "SbDec.h"
     22 #endif
     23 
     24 #include "Xz.h"
     25 
     26 #define XZ_CHECK_SIZE_MAX 64
     27 
     28 #define CODER_BUF_SIZE (1 << 17)
     29 
     30 unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
     31 {
     32   int i, limit;
     33   *value = 0;
     34   limit = (maxSize > 9) ? 9 : (int)maxSize;
     35 
     36   for (i = 0; i < limit;)
     37   {
     38     Byte b = p[i];
     39     *value |= (UInt64)(b & 0x7F) << (7 * i++);
     40     if ((b & 0x80) == 0)
     41       return (b == 0 && i != 1) ? 0 : i;
     42   }
     43   return 0;
     44 }
     45 
     46 /* ---------- BraState ---------- */
     47 
     48 #define BRA_BUF_SIZE (1 << 14)
     49 
     50 typedef struct
     51 {
     52   size_t bufPos;
     53   size_t bufConv;
     54   size_t bufTotal;
     55 
     56   UInt32 methodId;
     57   int encodeMode;
     58   UInt32 delta;
     59   UInt32 ip;
     60   UInt32 x86State;
     61   Byte deltaState[DELTA_STATE_SIZE];
     62 
     63   Byte buf[BRA_BUF_SIZE];
     64 } CBraState;
     65 
     66 void BraState_Free(void *pp, ISzAlloc *alloc)
     67 {
     68   alloc->Free(alloc, pp);
     69 }
     70 
     71 SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
     72 {
     73   CBraState *p = ((CBraState *)pp);
     74   alloc = alloc;
     75   p->encodeMode = 0;
     76   p->ip = 0;
     77   if (p->methodId == XZ_ID_Delta)
     78   {
     79     if (propSize != 1)
     80       return SZ_ERROR_UNSUPPORTED;
     81     p->delta = (unsigned)props[0] + 1;
     82   }
     83   else
     84   {
     85     if (propSize == 4)
     86     {
     87       UInt32 v = GetUi32(props);
     88       switch(p->methodId)
     89       {
     90         case XZ_ID_PPC:
     91         case XZ_ID_ARM:
     92         case XZ_ID_SPARC:
     93           if ((v & 3) != 0)
     94             return SZ_ERROR_UNSUPPORTED;
     95           break;
     96         case XZ_ID_ARMT:
     97           if ((v & 1) != 0)
     98             return SZ_ERROR_UNSUPPORTED;
     99           break;
    100         case XZ_ID_IA64:
    101           if ((v & 0xF) != 0)
    102             return SZ_ERROR_UNSUPPORTED;
    103           break;
    104       }
    105       p->ip = v;
    106     }
    107     else if (propSize != 0)
    108       return SZ_ERROR_UNSUPPORTED;
    109   }
    110   return SZ_OK;
    111 }
    112 
    113 void BraState_Init(void *pp)
    114 {
    115   CBraState *p = ((CBraState *)pp);
    116   p->bufPos = p->bufConv = p->bufTotal = 0;
    117   x86_Convert_Init(p->x86State);
    118   if (p->methodId == XZ_ID_Delta)
    119     Delta_Init(p->deltaState);
    120 }
    121 
    122 #define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: p->bufConv = isa ## _Convert(p->buf, p->bufTotal, p->ip, p->encodeMode); break;
    123 
    124 static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
    125     int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
    126 {
    127   CBraState *p = ((CBraState *)pp);
    128   SizeT destLenOrig = *destLen;
    129   SizeT srcLenOrig = *srcLen;
    130   *destLen = 0;
    131   *srcLen = 0;
    132   finishMode = finishMode;
    133   *wasFinished = 0;
    134   while (destLenOrig > 0)
    135   {
    136     if (p->bufPos != p->bufConv)
    137     {
    138       size_t curSize = p->bufConv - p->bufPos;
    139       if (curSize > destLenOrig)
    140         curSize = destLenOrig;
    141       memcpy(dest, p->buf + p->bufPos, curSize);
    142       p->bufPos += curSize;
    143       *destLen += curSize;
    144       dest += curSize;
    145       destLenOrig -= curSize;
    146       continue;
    147     }
    148     p->bufTotal -= p->bufPos;
    149     memmove(p->buf, p->buf + p->bufPos, p->bufTotal);
    150     p->bufPos = 0;
    151     p->bufConv = 0;
    152     {
    153       size_t curSize = BRA_BUF_SIZE - p->bufTotal;
    154       if (curSize > srcLenOrig)
    155         curSize = srcLenOrig;
    156       memcpy(p->buf + p->bufTotal, src, curSize);
    157       *srcLen += curSize;
    158       src += curSize;
    159       srcLenOrig -= curSize;
    160       p->bufTotal += curSize;
    161     }
    162     if (p->bufTotal == 0)
    163       break;
    164     switch(p->methodId)
    165     {
    166       case XZ_ID_Delta:
    167         if (p->encodeMode)
    168           Delta_Encode(p->deltaState, p->delta, p->buf, p->bufTotal);
    169         else
    170           Delta_Decode(p->deltaState, p->delta, p->buf, p->bufTotal);
    171         p->bufConv = p->bufTotal;
    172         break;
    173       case XZ_ID_X86:
    174         p->bufConv = x86_Convert(p->buf, p->bufTotal, p->ip, &p->x86State, p->encodeMode);
    175         break;
    176       CASE_BRA_CONV(PPC)
    177       CASE_BRA_CONV(IA64)
    178       CASE_BRA_CONV(ARM)
    179       CASE_BRA_CONV(ARMT)
    180       CASE_BRA_CONV(SPARC)
    181       default:
    182         return SZ_ERROR_UNSUPPORTED;
    183     }
    184     p->ip += (UInt32)p->bufConv;
    185 
    186     if (p->bufConv == 0)
    187     {
    188       if (!srcWasFinished)
    189         break;
    190       p->bufConv = p->bufTotal;
    191     }
    192   }
    193   if (p->bufTotal == p->bufPos && srcLenOrig == 0 && srcWasFinished)
    194     *wasFinished = 1;
    195   return SZ_OK;
    196 }
    197 
    198 SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc)
    199 {
    200   CBraState *decoder;
    201   if (id != XZ_ID_Delta &&
    202       id != XZ_ID_X86 &&
    203       id != XZ_ID_PPC &&
    204       id != XZ_ID_IA64 &&
    205       id != XZ_ID_ARM &&
    206       id != XZ_ID_ARMT &&
    207       id != XZ_ID_SPARC)
    208     return SZ_ERROR_UNSUPPORTED;
    209   p->p = 0;
    210   decoder = alloc->Alloc(alloc, sizeof(CBraState));
    211   if (decoder == 0)
    212     return SZ_ERROR_MEM;
    213   decoder->methodId = (UInt32)id;
    214   p->p = decoder;
    215   p->Free = BraState_Free;
    216   p->SetProps = BraState_SetProps;
    217   p->Init = BraState_Init;
    218   p->Code = BraState_Code;
    219   return SZ_OK;
    220 }
    221 
    222 /* ---------- SbState ---------- */
    223 
    224 #ifdef USE_SUBBLOCK
    225 
    226 static void SbState_Free(void *pp, ISzAlloc *alloc)
    227 {
    228   CSubblockDec *p = (CSubblockDec *)pp;
    229   SubblockDec_Free(p, alloc);
    230   alloc->Free(alloc, pp);
    231 }
    232 
    233 static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
    234 {
    235   pp = pp;
    236   props = props;
    237   alloc = alloc;
    238   return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
    239 }
    240 
    241 static void SbState_Init(void *pp)
    242 {
    243   SubblockDec_Init((CSubblockDec *)pp);
    244 }
    245 
    246 static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
    247     int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
    248 {
    249   ECoderStatus status;
    250   SRes res = SubblockDec_Decode((CSubblockDec *)pp, dest, destLen, src, srcLen, finishMode, &status);
    251   srcWasFinished = srcWasFinished;
    252   *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);
    253   return res;
    254 }
    255 
    256 SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
    257 {
    258   CSubblockDec *decoder;
    259   p->p = 0;
    260   decoder = alloc->Alloc(alloc, sizeof(CSubblockDec));
    261   if (decoder == 0)
    262     return SZ_ERROR_MEM;
    263   p->p = decoder;
    264   p->Free = SbState_Free;
    265   p->SetProps = SbState_SetProps;
    266   p->Init = SbState_Init;
    267   p->Code = SbState_Code;
    268   SubblockDec_Construct(decoder);
    269   return SZ_OK;
    270 }
    271 #endif
    272 
    273 /* ---------- Lzma2State ---------- */
    274 
    275 static void Lzma2State_Free(void *pp, ISzAlloc *alloc)
    276 {
    277   Lzma2Dec_Free((CLzma2Dec *)pp, alloc);
    278   alloc->Free(alloc, pp);
    279 }
    280 
    281 static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
    282 {
    283   if (propSize != 1)
    284     return SZ_ERROR_UNSUPPORTED;
    285   return Lzma2Dec_Allocate((CLzma2Dec *)pp, props[0], alloc);
    286 }
    287 
    288 static void Lzma2State_Init(void *pp)
    289 {
    290   Lzma2Dec_Init((CLzma2Dec *)pp);
    291 }
    292 
    293 static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
    294     int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
    295 {
    296   ELzmaStatus status;
    297   /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
    298   SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, finishMode, &status);
    299   srcWasFinished = srcWasFinished;
    300   *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);
    301   return res;
    302 }
    303 
    304 static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
    305 {
    306   CLzma2Dec *decoder = alloc->Alloc(alloc, sizeof(CLzma2Dec));
    307   p->p = decoder;
    308   if (decoder == 0)
    309     return SZ_ERROR_MEM;
    310   p->Free = Lzma2State_Free;
    311   p->SetProps = Lzma2State_SetProps;
    312   p->Init = Lzma2State_Init;
    313   p->Code = Lzma2State_Code;
    314   Lzma2Dec_Construct(decoder);
    315   return SZ_OK;
    316 }
    317 
    318 
    319 void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc)
    320 {
    321   int i;
    322   p->alloc = alloc;
    323   p->buf = 0;
    324   p->numCoders = 0;
    325   for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
    326     p->coders[i].p = NULL;
    327 }
    328 
    329 void MixCoder_Free(CMixCoder *p)
    330 {
    331   int i;
    332   for (i = 0; i < p->numCoders; i++)
    333   {
    334     IStateCoder *sc = &p->coders[i];
    335     if (p->alloc && sc->p)
    336       sc->Free(sc->p, p->alloc);
    337   }
    338   p->numCoders = 0;
    339   if (p->buf)
    340     p->alloc->Free(p->alloc, p->buf);
    341 }
    342 
    343 void MixCoder_Init(CMixCoder *p)
    344 {
    345   int i;
    346   for (i = 0; i < p->numCoders - 1; i++)
    347   {
    348     p->size[i] = 0;
    349     p->pos[i] = 0;
    350     p->finished[i] = 0;
    351   }
    352   for (i = 0; i < p->numCoders; i++)
    353   {
    354     IStateCoder *coder = &p->coders[i];
    355     coder->Init(coder->p);
    356   }
    357 }
    358 
    359 SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId)
    360 {
    361   IStateCoder *sc = &p->coders[coderIndex];
    362   p->ids[coderIndex] = methodId;
    363   switch(methodId)
    364   {
    365     case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, p->alloc);
    366     #ifdef USE_SUBBLOCK
    367     case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc);
    368     #endif
    369   }
    370   if (coderIndex == 0)
    371     return SZ_ERROR_UNSUPPORTED;
    372   return BraState_SetFromMethod(sc, methodId, p->alloc);
    373 }
    374 
    375 SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
    376     const Byte *src, SizeT *srcLen, int srcWasFinished,
    377     ECoderFinishMode finishMode, ECoderStatus *status)
    378 {
    379   SizeT destLenOrig = *destLen;
    380   SizeT srcLenOrig = *srcLen;
    381   Bool allFinished = True;
    382   *destLen = 0;
    383   *srcLen = 0;
    384   *status = CODER_STATUS_NOT_FINISHED;
    385 
    386   if (p->buf == 0)
    387   {
    388     p->buf = p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
    389     if (p->buf == 0)
    390       return SZ_ERROR_MEM;
    391   }
    392 
    393   if (p->numCoders != 1)
    394     finishMode = CODER_FINISH_ANY;
    395 
    396   for (;;)
    397   {
    398     Bool processed = False;
    399     int i;
    400     /*
    401     if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
    402       break;
    403     */
    404 
    405     for (i = 0; i < p->numCoders; i++)
    406     {
    407       SRes res;
    408       IStateCoder *coder = &p->coders[i];
    409       Byte *destCur;
    410       SizeT destLenCur, srcLenCur;
    411       const Byte *srcCur;
    412       int srcFinishedCur;
    413       int encodingWasFinished;
    414 
    415       if (i == 0)
    416       {
    417         srcCur = src;
    418         srcLenCur = srcLenOrig - *srcLen;
    419         srcFinishedCur = srcWasFinished;
    420       }
    421       else
    422       {
    423         srcCur = p->buf + (CODER_BUF_SIZE * (i - 1)) + p->pos[i - 1];
    424         srcLenCur = p->size[i - 1] - p->pos[i - 1];
    425         srcFinishedCur = p->finished[i - 1];
    426       }
    427 
    428       if (i == p->numCoders - 1)
    429       {
    430         destCur = dest;
    431         destLenCur = destLenOrig - *destLen;
    432       }
    433       else
    434       {
    435         if (p->pos[i] != p->size[i])
    436           continue;
    437         destCur = p->buf + (CODER_BUF_SIZE * i);
    438         destLenCur = CODER_BUF_SIZE;
    439       }
    440 
    441       res = coder->Code(coder->p, destCur, &destLenCur, srcCur, &srcLenCur, srcFinishedCur, finishMode, &encodingWasFinished);
    442 
    443       if (!encodingWasFinished)
    444         allFinished = False;
    445 
    446       if (i == 0)
    447       {
    448         *srcLen += srcLenCur;
    449         src += srcLenCur;
    450       }
    451       else
    452       {
    453         p->pos[i - 1] += srcLenCur;
    454       }
    455 
    456       if (i == p->numCoders - 1)
    457       {
    458         *destLen += destLenCur;
    459         dest += destLenCur;
    460       }
    461       else
    462       {
    463         p->size[i] = destLenCur;
    464         p->pos[i] = 0;
    465         p->finished[i] = encodingWasFinished;
    466       }
    467 
    468       if (res != SZ_OK)
    469         return res;
    470 
    471       if (destLenCur != 0 || srcLenCur != 0)
    472         processed = True;
    473     }
    474     if (!processed)
    475       break;
    476   }
    477   if (allFinished)
    478     *status = CODER_STATUS_FINISHED_WITH_MARK;
    479   return SZ_OK;
    480 }
    481 
    482 SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
    483 {
    484   *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);
    485   if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=
    486       GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))
    487     return SZ_ERROR_NO_ARCHIVE;
    488   return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
    489 }
    490 
    491 static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
    492 {
    493   return
    494       indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) &&
    495       (GetUi32(buf) == CrcCalc(buf + 4, 6) &&
    496       flags == GetBe16(buf + 8) &&
    497       memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0);
    498 }
    499 
    500 #define READ_VARINT_AND_CHECK(buf, pos, size, res) \
    501   { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
    502   if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
    503 
    504 
    505 SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
    506 {
    507   unsigned pos;
    508   int numFilters, i;
    509   UInt32 headerSize = (UInt32)header[0] << 2;
    510 
    511   if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
    512     return SZ_ERROR_ARCHIVE;
    513 
    514   pos = 1;
    515   if (pos == headerSize)
    516     return SZ_ERROR_ARCHIVE;
    517   p->flags = header[pos++];
    518 
    519   if (XzBlock_HasPackSize(p))
    520   {
    521     READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize);
    522     if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)
    523       return SZ_ERROR_ARCHIVE;
    524   }
    525 
    526   if (XzBlock_HasUnpackSize(p))
    527     READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);
    528 
    529   numFilters = XzBlock_GetNumFilters(p);
    530   for (i = 0; i < numFilters; i++)
    531   {
    532     CXzFilter *filter = p->filters + i;
    533     UInt64 size;
    534     READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id);
    535     READ_VARINT_AND_CHECK(header, pos, headerSize, &size);
    536     if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)
    537       return SZ_ERROR_ARCHIVE;
    538     filter->propsSize = (UInt32)size;
    539     memcpy(filter->props, header + pos, (size_t)size);
    540     pos += (unsigned)size;
    541 
    542     #ifdef XZ_DUMP
    543     printf("\nf[%d] = %2X: ", i, filter->id);
    544     {
    545       int i;
    546       for (i = 0; i < size; i++)
    547         printf(" %2X", filter->props[i]);
    548     }
    549     #endif
    550   }
    551 
    552   while (pos < headerSize)
    553     if (header[pos++] != 0)
    554       return SZ_ERROR_ARCHIVE;
    555   return SZ_OK;
    556 }
    557 
    558 SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)
    559 {
    560   int i;
    561   Bool needReInit = True;
    562   int numFilters = XzBlock_GetNumFilters(block);
    563   if (numFilters == p->numCoders)
    564   {
    565     for (i = 0; i < numFilters; i++)
    566       if (p->ids[i] != block->filters[numFilters - 1 - i].id)
    567         break;
    568     needReInit = (i != numFilters);
    569   }
    570   if (needReInit)
    571   {
    572     MixCoder_Free(p);
    573     p->numCoders = numFilters;
    574     for (i = 0; i < numFilters; i++)
    575     {
    576       const CXzFilter *f = &block->filters[numFilters - 1 - i];
    577       RINOK(MixCoder_SetFromMethod(p, i, f->id));
    578     }
    579   }
    580   for (i = 0; i < numFilters; i++)
    581   {
    582     const CXzFilter *f = &block->filters[numFilters - 1 - i];
    583     IStateCoder *sc = &p->coders[i];
    584     RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));
    585   }
    586   MixCoder_Init(p);
    587   return SZ_OK;
    588 }
    589 
    590 SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc)
    591 {
    592   MixCoder_Construct(&p->decoder, alloc);
    593   p->state = XZ_STATE_STREAM_HEADER;
    594   p->pos = 0;
    595   p->numStreams = 0;
    596   return SZ_OK;
    597 }
    598 
    599 void XzUnpacker_Free(CXzUnpacker *p)
    600 {
    601   MixCoder_Free(&p->decoder);
    602 }
    603 
    604 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
    605     const Byte *src, SizeT *srcLen, int finishMode, ECoderStatus *status)
    606 {
    607   SizeT destLenOrig = *destLen;
    608   SizeT srcLenOrig = *srcLen;
    609   *destLen = 0;
    610   *srcLen = 0;
    611   *status = CODER_STATUS_NOT_SPECIFIED;
    612   for (;;)
    613   {
    614     SizeT srcRem = srcLenOrig - *srcLen;
    615 
    616     if (p->state == XZ_STATE_BLOCK)
    617     {
    618       SizeT destLen2 = destLenOrig - *destLen;
    619       SizeT srcLen2 = srcLenOrig - *srcLen;
    620       SRes res;
    621       if (srcLen2 == 0 && destLen2 == 0)
    622       {
    623         *status = CODER_STATUS_NOT_FINISHED;
    624         return SZ_OK;
    625       }
    626 
    627       res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status);
    628       XzCheck_Update(&p->check, dest, destLen2);
    629 
    630       (*srcLen) += srcLen2;
    631       src += srcLen2;
    632       p->packSize += srcLen2;
    633 
    634       (*destLen) += destLen2;
    635       dest += destLen2;
    636       p->unpackSize += destLen2;
    637 
    638       RINOK(res);
    639 
    640       if (*status == CODER_STATUS_FINISHED_WITH_MARK)
    641       {
    642         Byte temp[32];
    643         unsigned num = Xz_WriteVarInt(temp, p->packSize + p->blockHeaderSize + XzFlags_GetCheckSize(p->streamFlags));
    644         num += Xz_WriteVarInt(temp + num, p->unpackSize);
    645         Sha256_Update(&p->sha, temp, num);
    646         p->indexSize += num;
    647         p->numBlocks++;
    648 
    649         p->state = XZ_STATE_BLOCK_FOOTER;
    650         p->pos = 0;
    651         p->alignPos = 0;
    652       }
    653       else if (srcLen2 == 0 && destLen2 == 0)
    654         return SZ_OK;
    655 
    656       continue;
    657     }
    658 
    659     if (srcRem == 0)
    660     {
    661       *status = CODER_STATUS_NEEDS_MORE_INPUT;
    662       return SZ_OK;
    663     }
    664 
    665     switch(p->state)
    666     {
    667       case XZ_STATE_STREAM_HEADER:
    668       {
    669         if (p->pos < XZ_STREAM_HEADER_SIZE)
    670         {
    671           if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
    672             return SZ_ERROR_NO_ARCHIVE;
    673           p->buf[p->pos++] = *src++;
    674           (*srcLen)++;
    675         }
    676         else
    677         {
    678           RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));
    679           p->state = XZ_STATE_BLOCK_HEADER;
    680           Sha256_Init(&p->sha);
    681           p->indexSize = 0;
    682           p->numBlocks = 0;
    683           p->pos = 0;
    684         }
    685         break;
    686       }
    687 
    688       case XZ_STATE_BLOCK_HEADER:
    689       {
    690         if (p->pos == 0)
    691         {
    692           p->buf[p->pos++] = *src++;
    693           (*srcLen)++;
    694           if (p->buf[0] == 0)
    695           {
    696             p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
    697             p->indexPos = p->indexPreSize;
    698             p->indexSize += p->indexPreSize;
    699             Sha256_Final(&p->sha, p->shaDigest);
    700             Sha256_Init(&p->sha);
    701             p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
    702             p->state = XZ_STATE_STREAM_INDEX;
    703           }
    704           p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;
    705         }
    706         else if (p->pos != p->blockHeaderSize)
    707         {
    708           UInt32 cur = p->blockHeaderSize - p->pos;
    709           if (cur > srcRem)
    710             cur = (UInt32)srcRem;
    711           memcpy(p->buf + p->pos, src, cur);
    712           p->pos += cur;
    713           (*srcLen) += cur;
    714           src += cur;
    715         }
    716         else
    717         {
    718           RINOK(XzBlock_Parse(&p->block, p->buf));
    719           p->state = XZ_STATE_BLOCK;
    720           p->packSize = 0;
    721           p->unpackSize = 0;
    722           XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
    723           RINOK(XzDec_Init(&p->decoder, &p->block));
    724         }
    725         break;
    726       }
    727 
    728       case XZ_STATE_BLOCK_FOOTER:
    729       {
    730         if (((p->packSize + p->alignPos) & 3) != 0)
    731         {
    732           (*srcLen)++;
    733           p->alignPos++;
    734           if (*src++ != 0)
    735             return SZ_ERROR_CRC;
    736         }
    737         else
    738         {
    739           UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);
    740           UInt32 cur = checkSize - p->pos;
    741           if (cur != 0)
    742           {
    743             if (cur > srcRem)
    744               cur = (UInt32)srcRem;
    745             memcpy(p->buf + p->pos, src, cur);
    746             p->pos += cur;
    747             (*srcLen) += cur;
    748             src += cur;
    749           }
    750           else
    751           {
    752             Byte digest[XZ_CHECK_SIZE_MAX];
    753             p->state = XZ_STATE_BLOCK_HEADER;
    754             p->pos = 0;
    755             if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
    756               return SZ_ERROR_CRC;
    757           }
    758         }
    759         break;
    760       }
    761 
    762       case XZ_STATE_STREAM_INDEX:
    763       {
    764         if (p->pos < p->indexPreSize)
    765         {
    766           (*srcLen)++;
    767           if (*src++ != p->buf[p->pos++])
    768             return SZ_ERROR_CRC;
    769         }
    770         else
    771         {
    772           if (p->indexPos < p->indexSize)
    773           {
    774             UInt64 cur = p->indexSize - p->indexPos;
    775             if (srcRem > cur)
    776               srcRem = (SizeT)cur;
    777             p->crc = CrcUpdate(p->crc, src, srcRem);
    778             Sha256_Update(&p->sha, src, srcRem);
    779             (*srcLen) += srcRem;
    780             src += srcRem;
    781             p->indexPos += srcRem;
    782           }
    783           else if ((p->indexPos & 3) != 0)
    784           {
    785             Byte b = *src++;
    786             p->crc = CRC_UPDATE_BYTE(p->crc, b);
    787             (*srcLen)++;
    788             p->indexPos++;
    789             p->indexSize++;
    790             if (b != 0)
    791               return SZ_ERROR_CRC;
    792           }
    793           else
    794           {
    795             Byte digest[SHA256_DIGEST_SIZE];
    796             p->state = XZ_STATE_STREAM_INDEX_CRC;
    797             p->indexSize += 4;
    798             p->pos = 0;
    799             Sha256_Final(&p->sha, digest);
    800             if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
    801               return SZ_ERROR_CRC;
    802           }
    803         }
    804         break;
    805       }
    806 
    807       case XZ_STATE_STREAM_INDEX_CRC:
    808       {
    809         if (p->pos < 4)
    810         {
    811           (*srcLen)++;
    812           p->buf[p->pos++] = *src++;
    813         }
    814         else
    815         {
    816           p->state = XZ_STATE_STREAM_FOOTER;
    817           p->pos = 0;
    818           if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))
    819             return SZ_ERROR_CRC;
    820         }
    821         break;
    822       }
    823 
    824       case XZ_STATE_STREAM_FOOTER:
    825       {
    826         UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;
    827         if (cur > srcRem)
    828           cur = (UInt32)srcRem;
    829         memcpy(p->buf + p->pos, src, cur);
    830         p->pos += cur;
    831         (*srcLen) += cur;
    832         src += cur;
    833         if (p->pos == XZ_STREAM_FOOTER_SIZE)
    834         {
    835           p->state = XZ_STATE_STREAM_PADDING;
    836           p->numStreams++;
    837           p->padSize = 0;
    838           if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))
    839             return SZ_ERROR_CRC;
    840         }
    841         break;
    842       }
    843 
    844       case XZ_STATE_STREAM_PADDING:
    845       {
    846         if (*src != 0)
    847         {
    848           if (((UInt32)p->padSize & 3) != 0)
    849             return SZ_ERROR_NO_ARCHIVE;
    850           p->pos = 0;
    851           p->state = XZ_STATE_STREAM_HEADER;
    852         }
    853         else
    854         {
    855           (*srcLen)++;
    856           src++;
    857           p->padSize++;
    858         }
    859         break;
    860       }
    861 
    862       case XZ_STATE_BLOCK: break; /* to disable GCC warning */
    863     }
    864   }
    865   /*
    866   if (p->state == XZ_STATE_FINISHED)
    867     *status = CODER_STATUS_FINISHED_WITH_MARK;
    868   return SZ_OK;
    869   */
    870 }
    871 
    872 Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p)
    873 {
    874   return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
    875 }
    876