1 /* XzDec.c -- Xz Decode
\r
2 2015-11-09 : Igor Pavlov : Public domain */
\r
6 /* #define XZ_DUMP */
\r
18 #include "CpuArch.h"
\r
20 #include "Lzma2Dec.h"
\r
23 #include "Bcj3Dec.c"
\r
29 #define XZ_CHECK_SIZE_MAX 64
\r
31 #define CODER_BUF_SIZE (1 << 17)
\r
33 unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
\r
37 limit = (maxSize > 9) ? 9 : (unsigned)maxSize;
\r
39 for (i = 0; i < limit;)
\r
42 *value |= (UInt64)(b & 0x7F) << (7 * i++);
\r
43 if ((b & 0x80) == 0)
\r
44 return (b == 0 && i != 1) ? 0 : i;
\r
49 /* ---------- BraState ---------- */
\r
51 #define BRA_BUF_SIZE (1 << 14)
\r
64 Byte deltaState[DELTA_STATE_SIZE];
\r
66 Byte buf[BRA_BUF_SIZE];
\r
69 static void BraState_Free(void *pp, ISzAlloc *alloc)
\r
71 alloc->Free(alloc, pp);
\r
74 static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
\r
76 CBraState *p = ((CBraState *)pp);
\r
79 if (p->methodId == XZ_ID_Delta)
\r
82 return SZ_ERROR_UNSUPPORTED;
\r
83 p->delta = (unsigned)props[0] + 1;
\r
89 UInt32 v = GetUi32(props);
\r
90 switch (p->methodId)
\r
96 return SZ_ERROR_UNSUPPORTED;
\r
100 return SZ_ERROR_UNSUPPORTED;
\r
103 if ((v & 0xF) != 0)
\r
104 return SZ_ERROR_UNSUPPORTED;
\r
109 else if (propSize != 0)
\r
110 return SZ_ERROR_UNSUPPORTED;
\r
115 static void BraState_Init(void *pp)
\r
117 CBraState *p = ((CBraState *)pp);
\r
118 p->bufPos = p->bufConv = p->bufTotal = 0;
\r
119 x86_Convert_Init(p->x86State);
\r
120 if (p->methodId == XZ_ID_Delta)
\r
121 Delta_Init(p->deltaState);
\r
124 #define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: p->bufConv = isa ## _Convert(p->buf, p->bufTotal, p->ip, p->encodeMode); break;
\r
126 static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
\r
127 int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
\r
129 CBraState *p = ((CBraState *)pp);
\r
130 SizeT destLenOrig = *destLen;
\r
131 SizeT srcLenOrig = *srcLen;
\r
132 UNUSED_VAR(finishMode);
\r
136 while (destLenOrig > 0)
\r
138 if (p->bufPos != p->bufConv)
\r
140 size_t curSize = p->bufConv - p->bufPos;
\r
141 if (curSize > destLenOrig)
\r
142 curSize = destLenOrig;
\r
143 memcpy(dest, p->buf + p->bufPos, curSize);
\r
144 p->bufPos += curSize;
\r
145 *destLen += curSize;
\r
147 destLenOrig -= curSize;
\r
150 p->bufTotal -= p->bufPos;
\r
151 memmove(p->buf, p->buf + p->bufPos, p->bufTotal);
\r
155 size_t curSize = BRA_BUF_SIZE - p->bufTotal;
\r
156 if (curSize > srcLenOrig)
\r
157 curSize = srcLenOrig;
\r
158 memcpy(p->buf + p->bufTotal, src, curSize);
\r
159 *srcLen += curSize;
\r
161 srcLenOrig -= curSize;
\r
162 p->bufTotal += curSize;
\r
164 if (p->bufTotal == 0)
\r
166 switch (p->methodId)
\r
170 Delta_Encode(p->deltaState, p->delta, p->buf, p->bufTotal);
\r
172 Delta_Decode(p->deltaState, p->delta, p->buf, p->bufTotal);
\r
173 p->bufConv = p->bufTotal;
\r
176 p->bufConv = x86_Convert(p->buf, p->bufTotal, p->ip, &p->x86State, p->encodeMode);
\r
179 CASE_BRA_CONV(IA64)
\r
181 CASE_BRA_CONV(ARMT)
\r
182 CASE_BRA_CONV(SPARC)
\r
184 return SZ_ERROR_UNSUPPORTED;
\r
186 p->ip += (UInt32)p->bufConv;
\r
188 if (p->bufConv == 0)
\r
190 if (!srcWasFinished)
\r
192 p->bufConv = p->bufTotal;
\r
195 if (p->bufTotal == p->bufPos && srcLenOrig == 0 && srcWasFinished)
\r
200 SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc)
\r
202 CBraState *decoder;
\r
203 if (id != XZ_ID_Delta &&
\r
206 id != XZ_ID_IA64 &&
\r
208 id != XZ_ID_ARMT &&
\r
210 return SZ_ERROR_UNSUPPORTED;
\r
212 decoder = (CBraState *)alloc->Alloc(alloc, sizeof(CBraState));
\r
214 return SZ_ERROR_MEM;
\r
215 decoder->methodId = (UInt32)id;
\r
216 decoder->encodeMode = encodeMode;
\r
218 p->Free = BraState_Free;
\r
219 p->SetProps = BraState_SetProps;
\r
220 p->Init = BraState_Init;
\r
221 p->Code = BraState_Code;
\r
225 /* ---------- SbState ---------- */
\r
227 #ifdef USE_SUBBLOCK
\r
229 static void SbState_Free(void *pp, ISzAlloc *alloc)
\r
231 CSbDec *p = (CSbDec *)pp;
\r
233 alloc->Free(alloc, pp);
\r
236 static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
\r
241 return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
\r
244 static void SbState_Init(void *pp)
\r
246 SbDec_Init((CSbDec *)pp);
\r
249 static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
\r
250 int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
\r
252 CSbDec *p = (CSbDec *)pp;
\r
254 UNUSED_VAR(srcWasFinished);
\r
256 p->destLen = *destLen;
\r
258 p->srcLen = *srcLen;
\r
259 p->finish = finishMode; /* change it */
\r
260 res = SbDec_Decode((CSbDec *)pp);
\r
261 *destLen -= p->destLen;
\r
262 *srcLen -= p->srcLen;
\r
263 *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */
\r
267 SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
\r
271 decoder = alloc->Alloc(alloc, sizeof(CSbDec));
\r
273 return SZ_ERROR_MEM;
\r
275 p->Free = SbState_Free;
\r
276 p->SetProps = SbState_SetProps;
\r
277 p->Init = SbState_Init;
\r
278 p->Code = SbState_Code;
\r
279 SbDec_Construct(decoder);
\r
280 SbDec_SetAlloc(decoder, alloc);
\r
285 /* ---------- Lzma2State ---------- */
\r
287 static void Lzma2State_Free(void *pp, ISzAlloc *alloc)
\r
289 Lzma2Dec_Free((CLzma2Dec *)pp, alloc);
\r
290 alloc->Free(alloc, pp);
\r
293 static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
\r
296 return SZ_ERROR_UNSUPPORTED;
\r
297 return Lzma2Dec_Allocate((CLzma2Dec *)pp, props[0], alloc);
\r
300 static void Lzma2State_Init(void *pp)
\r
302 Lzma2Dec_Init((CLzma2Dec *)pp);
\r
305 static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
\r
306 int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
\r
308 ELzmaStatus status;
\r
309 /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
\r
310 SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status);
\r
311 UNUSED_VAR(srcWasFinished);
\r
312 *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);
\r
316 static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
\r
318 CLzma2Dec *decoder = (CLzma2Dec *)alloc->Alloc(alloc, sizeof(CLzma2Dec));
\r
321 return SZ_ERROR_MEM;
\r
322 p->Free = Lzma2State_Free;
\r
323 p->SetProps = Lzma2State_SetProps;
\r
324 p->Init = Lzma2State_Init;
\r
325 p->Code = Lzma2State_Code;
\r
326 Lzma2Dec_Construct(decoder);
\r
331 void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc)
\r
337 for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
\r
338 p->coders[i].p = NULL;
\r
341 void MixCoder_Free(CMixCoder *p)
\r
344 for (i = 0; i < p->numCoders; i++)
\r
346 IStateCoder *sc = &p->coders[i];
\r
347 if (p->alloc && sc->p)
\r
348 sc->Free(sc->p, p->alloc);
\r
353 p->alloc->Free(p->alloc, p->buf);
\r
354 p->buf = NULL; /* 9.31: the BUG was fixed */
\r
358 void MixCoder_Init(CMixCoder *p)
\r
361 for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)
\r
365 p->finished[i] = 0;
\r
367 for (i = 0; i < p->numCoders; i++)
\r
369 IStateCoder *coder = &p->coders[i];
\r
370 coder->Init(coder->p);
\r
374 SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId)
\r
376 IStateCoder *sc = &p->coders[coderIndex];
\r
377 p->ids[coderIndex] = methodId;
\r
380 case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, p->alloc);
\r
381 #ifdef USE_SUBBLOCK
\r
382 case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc);
\r
385 if (coderIndex == 0)
\r
386 return SZ_ERROR_UNSUPPORTED;
\r
387 return BraState_SetFromMethod(sc, methodId, 0, p->alloc);
\r
390 SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
\r
391 const Byte *src, SizeT *srcLen, int srcWasFinished,
\r
392 ECoderFinishMode finishMode, ECoderStatus *status)
\r
394 SizeT destLenOrig = *destLen;
\r
395 SizeT srcLenOrig = *srcLen;
\r
396 Bool allFinished = True;
\r
399 *status = CODER_STATUS_NOT_FINISHED;
\r
403 p->buf = (Byte *)p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
\r
405 return SZ_ERROR_MEM;
\r
408 if (p->numCoders != 1)
\r
409 finishMode = CODER_FINISH_ANY;
\r
413 Bool processed = False;
\r
416 if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
\r
420 for (i = 0; i < p->numCoders; i++)
\r
423 IStateCoder *coder = &p->coders[i];
\r
425 SizeT destLenCur, srcLenCur;
\r
426 const Byte *srcCur;
\r
427 int srcFinishedCur;
\r
428 int encodingWasFinished;
\r
433 srcLenCur = srcLenOrig - *srcLen;
\r
434 srcFinishedCur = srcWasFinished;
\r
438 srcCur = p->buf + (CODER_BUF_SIZE * (i - 1)) + p->pos[i - 1];
\r
439 srcLenCur = p->size[i - 1] - p->pos[i - 1];
\r
440 srcFinishedCur = p->finished[i - 1];
\r
443 if (i == p->numCoders - 1)
\r
446 destLenCur = destLenOrig - *destLen;
\r
450 if (p->pos[i] != p->size[i])
\r
452 destCur = p->buf + (CODER_BUF_SIZE * i);
\r
453 destLenCur = CODER_BUF_SIZE;
\r
456 res = coder->Code(coder->p, destCur, &destLenCur, srcCur, &srcLenCur, srcFinishedCur, finishMode, &encodingWasFinished);
\r
458 if (!encodingWasFinished)
\r
459 allFinished = False;
\r
463 *srcLen += srcLenCur;
\r
468 p->pos[i - 1] += srcLenCur;
\r
471 if (i == p->numCoders - 1)
\r
473 *destLen += destLenCur;
\r
474 dest += destLenCur;
\r
478 p->size[i] = destLenCur;
\r
480 p->finished[i] = encodingWasFinished;
\r
486 if (destLenCur != 0 || srcLenCur != 0)
\r
493 *status = CODER_STATUS_FINISHED_WITH_MARK;
\r
497 SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
\r
499 *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);
\r
500 if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=
\r
501 GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))
\r
502 return SZ_ERROR_NO_ARCHIVE;
\r
503 return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
\r
506 static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
\r
509 indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) &&
\r
510 (GetUi32(buf) == CrcCalc(buf + 4, 6) &&
\r
511 flags == GetBe16(buf + 8) &&
\r
512 memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0);
\r
515 #define READ_VARINT_AND_CHECK(buf, pos, size, res) \
\r
516 { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
\r
517 if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
\r
520 SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
\r
523 unsigned numFilters, i;
\r
524 unsigned headerSize = (unsigned)header[0] << 2;
\r
526 if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
\r
527 return SZ_ERROR_ARCHIVE;
\r
530 if (pos == headerSize)
\r
531 return SZ_ERROR_ARCHIVE;
\r
532 p->flags = header[pos++];
\r
534 if (XzBlock_HasPackSize(p))
\r
536 READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize);
\r
537 if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)
\r
538 return SZ_ERROR_ARCHIVE;
\r
541 if (XzBlock_HasUnpackSize(p))
\r
542 READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);
\r
544 numFilters = XzBlock_GetNumFilters(p);
\r
545 for (i = 0; i < numFilters; i++)
\r
547 CXzFilter *filter = p->filters + i;
\r
549 READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id);
\r
550 READ_VARINT_AND_CHECK(header, pos, headerSize, &size);
\r
551 if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)
\r
552 return SZ_ERROR_ARCHIVE;
\r
553 filter->propsSize = (UInt32)size;
\r
554 memcpy(filter->props, header + pos, (size_t)size);
\r
555 pos += (unsigned)size;
\r
558 printf("\nf[%u] = %2X: ", i, (unsigned)filter->id);
\r
561 for (i = 0; i < size; i++)
\r
562 printf(" %2X", filter->props[i]);
\r
567 while (pos < headerSize)
\r
568 if (header[pos++] != 0)
\r
569 return SZ_ERROR_ARCHIVE;
\r
573 SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)
\r
576 Bool needReInit = True;
\r
577 unsigned numFilters = XzBlock_GetNumFilters(block);
\r
579 if (numFilters == p->numCoders)
\r
581 for (i = 0; i < numFilters; i++)
\r
582 if (p->ids[i] != block->filters[numFilters - 1 - i].id)
\r
584 needReInit = (i != numFilters);
\r
590 p->numCoders = numFilters;
\r
591 for (i = 0; i < numFilters; i++)
\r
593 const CXzFilter *f = &block->filters[numFilters - 1 - i];
\r
594 RINOK(MixCoder_SetFromMethod(p, i, f->id));
\r
598 for (i = 0; i < numFilters; i++)
\r
600 const CXzFilter *f = &block->filters[numFilters - 1 - i];
\r
601 IStateCoder *sc = &p->coders[i];
\r
602 RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));
\r
609 void XzUnpacker_Init(CXzUnpacker *p)
\r
611 p->state = XZ_STATE_STREAM_HEADER;
\r
613 p->numStartedStreams = 0;
\r
614 p->numFinishedStreams = 0;
\r
615 p->numTotalBlocks = 0;
\r
619 void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc)
\r
621 MixCoder_Construct(&p->decoder, alloc);
\r
622 XzUnpacker_Init(p);
\r
625 void XzUnpacker_Free(CXzUnpacker *p)
\r
627 MixCoder_Free(&p->decoder);
\r
630 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
\r
631 const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode, ECoderStatus *status)
\r
633 SizeT destLenOrig = *destLen;
\r
634 SizeT srcLenOrig = *srcLen;
\r
637 *status = CODER_STATUS_NOT_SPECIFIED;
\r
640 SizeT srcRem = srcLenOrig - *srcLen;
\r
642 if (p->state == XZ_STATE_BLOCK)
\r
644 SizeT destLen2 = destLenOrig - *destLen;
\r
645 SizeT srcLen2 = srcLenOrig - *srcLen;
\r
647 if (srcLen2 == 0 && destLen2 == 0)
\r
649 *status = CODER_STATUS_NOT_FINISHED;
\r
653 res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status);
\r
654 XzCheck_Update(&p->check, dest, destLen2);
\r
656 (*srcLen) += srcLen2;
\r
658 p->packSize += srcLen2;
\r
660 (*destLen) += destLen2;
\r
662 p->unpackSize += destLen2;
\r
666 if (*status == CODER_STATUS_FINISHED_WITH_MARK)
\r
669 unsigned num = Xz_WriteVarInt(temp, p->packSize + p->blockHeaderSize + XzFlags_GetCheckSize(p->streamFlags));
\r
670 num += Xz_WriteVarInt(temp + num, p->unpackSize);
\r
671 Sha256_Update(&p->sha, temp, num);
\r
672 p->indexSize += num;
\r
675 p->state = XZ_STATE_BLOCK_FOOTER;
\r
679 else if (srcLen2 == 0 && destLen2 == 0)
\r
687 *status = CODER_STATUS_NEEDS_MORE_INPUT;
\r
693 case XZ_STATE_STREAM_HEADER:
\r
695 if (p->pos < XZ_STREAM_HEADER_SIZE)
\r
697 if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
\r
698 return SZ_ERROR_NO_ARCHIVE;
\r
699 p->buf[p->pos++] = *src++;
\r
704 RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));
\r
705 p->numStartedStreams++;
\r
706 p->state = XZ_STATE_BLOCK_HEADER;
\r
707 Sha256_Init(&p->sha);
\r
715 case XZ_STATE_BLOCK_HEADER:
\r
719 p->buf[p->pos++] = *src++;
\r
721 if (p->buf[0] == 0)
\r
723 p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
\r
724 p->indexPos = p->indexPreSize;
\r
725 p->indexSize += p->indexPreSize;
\r
726 Sha256_Final(&p->sha, p->shaDigest);
\r
727 Sha256_Init(&p->sha);
\r
728 p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
\r
729 p->state = XZ_STATE_STREAM_INDEX;
\r
731 p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;
\r
733 else if (p->pos != p->blockHeaderSize)
\r
735 UInt32 cur = p->blockHeaderSize - p->pos;
\r
737 cur = (UInt32)srcRem;
\r
738 memcpy(p->buf + p->pos, src, cur);
\r
745 RINOK(XzBlock_Parse(&p->block, p->buf));
\r
746 p->numTotalBlocks++;
\r
747 p->state = XZ_STATE_BLOCK;
\r
750 XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
\r
751 RINOK(XzDec_Init(&p->decoder, &p->block));
\r
756 case XZ_STATE_BLOCK_FOOTER:
\r
758 if (((p->packSize + p->alignPos) & 3) != 0)
\r
763 return SZ_ERROR_CRC;
\r
767 UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);
\r
768 UInt32 cur = checkSize - p->pos;
\r
772 cur = (UInt32)srcRem;
\r
773 memcpy(p->buf + p->pos, src, cur);
\r
780 Byte digest[XZ_CHECK_SIZE_MAX];
\r
781 p->state = XZ_STATE_BLOCK_HEADER;
\r
783 if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
\r
784 return SZ_ERROR_CRC;
\r
790 case XZ_STATE_STREAM_INDEX:
\r
792 if (p->pos < p->indexPreSize)
\r
795 if (*src++ != p->buf[p->pos++])
\r
796 return SZ_ERROR_CRC;
\r
800 if (p->indexPos < p->indexSize)
\r
802 UInt64 cur = p->indexSize - p->indexPos;
\r
804 srcRem = (SizeT)cur;
\r
805 p->crc = CrcUpdate(p->crc, src, srcRem);
\r
806 Sha256_Update(&p->sha, src, srcRem);
\r
807 (*srcLen) += srcRem;
\r
809 p->indexPos += srcRem;
\r
811 else if ((p->indexPos & 3) != 0)
\r
814 p->crc = CRC_UPDATE_BYTE(p->crc, b);
\r
819 return SZ_ERROR_CRC;
\r
823 Byte digest[SHA256_DIGEST_SIZE];
\r
824 p->state = XZ_STATE_STREAM_INDEX_CRC;
\r
827 Sha256_Final(&p->sha, digest);
\r
828 if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
\r
829 return SZ_ERROR_CRC;
\r
835 case XZ_STATE_STREAM_INDEX_CRC:
\r
840 p->buf[p->pos++] = *src++;
\r
844 p->state = XZ_STATE_STREAM_FOOTER;
\r
846 if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))
\r
847 return SZ_ERROR_CRC;
\r
852 case XZ_STATE_STREAM_FOOTER:
\r
854 UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;
\r
856 cur = (UInt32)srcRem;
\r
857 memcpy(p->buf + p->pos, src, cur);
\r
861 if (p->pos == XZ_STREAM_FOOTER_SIZE)
\r
863 p->state = XZ_STATE_STREAM_PADDING;
\r
864 p->numFinishedStreams++;
\r
866 if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))
\r
867 return SZ_ERROR_CRC;
\r
872 case XZ_STATE_STREAM_PADDING:
\r
876 if (((UInt32)p->padSize & 3) != 0)
\r
877 return SZ_ERROR_NO_ARCHIVE;
\r
879 p->state = XZ_STATE_STREAM_HEADER;
\r
890 case XZ_STATE_BLOCK: break; /* to disable GCC warning */
\r
894 if (p->state == XZ_STATE_FINISHED)
\r
895 *status = CODER_STATUS_FINISHED_WITH_MARK;
\r
900 Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p)
\r
902 return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
\r
905 UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p)
\r
908 if (p->state == XZ_STATE_STREAM_PADDING)
\r
910 else if (p->state == XZ_STATE_STREAM_HEADER)
\r
911 num += p->padSize + p->pos;
\r