1 /* XzDec.c -- Xz Decode
2 2024-03-01 : Igor Pavlov : Public domain */
3
4 #include "Precomp.h"
5
6 // #include <stdio.h>
7
8 // #define XZ_DUMP
9
10 /* #define XZ_DUMP */
11
12 #ifdef XZ_DUMP
13 #include <stdio.h>
14 #endif
15
16 // #define SHOW_DEBUG_INFO
17
18 #ifdef SHOW_DEBUG_INFO
19 #include <stdio.h>
20 #endif
21
22 #ifdef SHOW_DEBUG_INFO
23 #define PRF(x) x
24 #else
25 #define PRF(x)
26 #endif
27
28 #define PRF_STR(s) PRF(printf("\n" s "\n"))
29 #define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d))
30
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include "7zCrc.h"
35 #include "Alloc.h"
36 #include "Bra.h"
37 #include "CpuArch.h"
38 #include "Delta.h"
39 #include "Lzma2Dec.h"
40
41 // #define USE_SUBBLOCK
42
43 #ifdef USE_SUBBLOCK
44 #include "Bcj3Dec.c"
45 #include "SbDec.h"
46 #endif
47
48 #include "Xz.h"
49
50 #define XZ_CHECK_SIZE_MAX 64
51
52 #define CODER_BUF_SIZE ((size_t)1 << 17)
53
Xz_ReadVarInt(const Byte * p,size_t maxSize,UInt64 * value)54 unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
55 {
56 unsigned i, limit;
57 *value = 0;
58 limit = (maxSize > 9) ? 9 : (unsigned)maxSize;
59
60 for (i = 0; i < limit;)
61 {
62 Byte b = p[i];
63 *value |= (UInt64)(b & 0x7F) << (7 * i++);
64 if ((b & 0x80) == 0)
65 return (b == 0 && i != 1) ? 0 : i;
66 }
67 return 0;
68 }
69
70
71 /* ---------- XzBcFilterState ---------- */
72
73 #define BRA_BUF_SIZE (1 << 14)
74
75 typedef struct
76 {
77 size_t bufPos;
78 size_t bufConv;
79 size_t bufTotal;
80 Byte *buf; // must be aligned for 4 bytes
81 Xz_Func_BcFilterStateBase_Filter filter_func;
82 // int encodeMode;
83 CXzBcFilterStateBase base;
84 // Byte buf[BRA_BUF_SIZE];
85 } CXzBcFilterState;
86
87
XzBcFilterState_Free(void * pp,ISzAllocPtr alloc)88 static void XzBcFilterState_Free(void *pp, ISzAllocPtr alloc)
89 {
90 if (pp)
91 {
92 CXzBcFilterState *p = ((CXzBcFilterState *)pp);
93 ISzAlloc_Free(alloc, p->buf);
94 ISzAlloc_Free(alloc, pp);
95 }
96 }
97
98
XzBcFilterState_SetProps(void * pp,const Byte * props,size_t propSize,ISzAllocPtr alloc)99 static SRes XzBcFilterState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
100 {
101 CXzBcFilterStateBase *p = &((CXzBcFilterState *)pp)->base;
102 UNUSED_VAR(alloc)
103 p->ip = 0;
104 if (p->methodId == XZ_ID_Delta)
105 {
106 if (propSize != 1)
107 return SZ_ERROR_UNSUPPORTED;
108 p->delta = (UInt32)props[0] + 1;
109 }
110 else
111 {
112 if (propSize == 4)
113 {
114 const UInt32 v = GetUi32(props);
115 switch (p->methodId)
116 {
117 case XZ_ID_PPC:
118 case XZ_ID_ARM:
119 case XZ_ID_SPARC:
120 case XZ_ID_ARM64:
121 if (v & 3)
122 return SZ_ERROR_UNSUPPORTED;
123 break;
124 case XZ_ID_ARMT:
125 case XZ_ID_RISCV:
126 if (v & 1)
127 return SZ_ERROR_UNSUPPORTED;
128 break;
129 case XZ_ID_IA64:
130 if (v & 0xf)
131 return SZ_ERROR_UNSUPPORTED;
132 break;
133 default: break;
134 }
135 p->ip = v;
136 }
137 else if (propSize != 0)
138 return SZ_ERROR_UNSUPPORTED;
139 }
140 return SZ_OK;
141 }
142
143
XzBcFilterState_Init(void * pp)144 static void XzBcFilterState_Init(void *pp)
145 {
146 CXzBcFilterState *p = ((CXzBcFilterState *)pp);
147 p->bufPos = p->bufConv = p->bufTotal = 0;
148 p->base.X86_State = Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL;
149 if (p->base.methodId == XZ_ID_Delta)
150 Delta_Init(p->base.delta_State);
151 }
152
153
154 static const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Dec[] =
155 {
156 Z7_BRANCH_CONV_DEC_2 (BranchConv_PPC),
157 Z7_BRANCH_CONV_DEC_2 (BranchConv_IA64),
158 Z7_BRANCH_CONV_DEC_2 (BranchConv_ARM),
159 Z7_BRANCH_CONV_DEC_2 (BranchConv_ARMT),
160 Z7_BRANCH_CONV_DEC_2 (BranchConv_SPARC),
161 Z7_BRANCH_CONV_DEC_2 (BranchConv_ARM64),
162 Z7_BRANCH_CONV_DEC_2 (BranchConv_RISCV)
163 };
164
XzBcFilterStateBase_Filter_Dec(CXzBcFilterStateBase * p,Byte * data,SizeT size)165 static SizeT XzBcFilterStateBase_Filter_Dec(CXzBcFilterStateBase *p, Byte *data, SizeT size)
166 {
167 switch (p->methodId)
168 {
169 case XZ_ID_Delta:
170 Delta_Decode(p->delta_State, p->delta, data, size);
171 break;
172 case XZ_ID_X86:
173 size = (SizeT)(z7_BranchConvSt_X86_Dec(data, size, p->ip, &p->X86_State) - data);
174 break;
175 default:
176 if (p->methodId >= XZ_ID_PPC)
177 {
178 const UInt32 i = p->methodId - XZ_ID_PPC;
179 if (i < Z7_ARRAY_SIZE(g_Funcs_BranchConv_RISC_Dec))
180 size = (SizeT)(g_Funcs_BranchConv_RISC_Dec[i](data, size, p->ip) - data);
181 }
182 break;
183 }
184 p->ip += (UInt32)size;
185 return size;
186 }
187
188
XzBcFilterState_Filter(void * pp,Byte * data,SizeT size)189 static SizeT XzBcFilterState_Filter(void *pp, Byte *data, SizeT size)
190 {
191 CXzBcFilterState *p = ((CXzBcFilterState *)pp);
192 return p->filter_func(&p->base, data, size);
193 }
194
195
XzBcFilterState_Code2(void * pp,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int srcWasFinished,ECoderFinishMode finishMode,ECoderStatus * status)196 static SRes XzBcFilterState_Code2(void *pp,
197 Byte *dest, SizeT *destLen,
198 const Byte *src, SizeT *srcLen, int srcWasFinished,
199 ECoderFinishMode finishMode,
200 // int *wasFinished
201 ECoderStatus *status)
202 {
203 CXzBcFilterState *p = ((CXzBcFilterState *)pp);
204 SizeT destRem = *destLen;
205 SizeT srcRem = *srcLen;
206 UNUSED_VAR(finishMode)
207
208 *destLen = 0;
209 *srcLen = 0;
210 // *wasFinished = False;
211 *status = CODER_STATUS_NOT_FINISHED;
212
213 while (destRem != 0)
214 {
215 {
216 size_t size = p->bufConv - p->bufPos;
217 if (size)
218 {
219 if (size > destRem)
220 size = destRem;
221 memcpy(dest, p->buf + p->bufPos, size);
222 p->bufPos += size;
223 *destLen += size;
224 dest += size;
225 destRem -= size;
226 continue;
227 }
228 }
229
230 p->bufTotal -= p->bufPos;
231 memmove(p->buf, p->buf + p->bufPos, p->bufTotal);
232 p->bufPos = 0;
233 p->bufConv = 0;
234 {
235 size_t size = BRA_BUF_SIZE - p->bufTotal;
236 if (size > srcRem)
237 size = srcRem;
238 memcpy(p->buf + p->bufTotal, src, size);
239 *srcLen += size;
240 src += size;
241 srcRem -= size;
242 p->bufTotal += size;
243 }
244 if (p->bufTotal == 0)
245 break;
246
247 p->bufConv = p->filter_func(&p->base, p->buf, p->bufTotal);
248
249 if (p->bufConv == 0)
250 {
251 if (!srcWasFinished)
252 break;
253 p->bufConv = p->bufTotal;
254 }
255 }
256
257 if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished)
258 {
259 *status = CODER_STATUS_FINISHED_WITH_MARK;
260 // *wasFinished = 1;
261 }
262
263 return SZ_OK;
264 }
265
266
267 #define XZ_IS_SUPPORTED_FILTER_ID(id) \
268 ((id) >= XZ_ID_Delta && (id) <= XZ_ID_RISCV)
269
Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder * p,UInt64 id,Xz_Func_BcFilterStateBase_Filter func,ISzAllocPtr alloc)270 SRes Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder *p, UInt64 id,
271 Xz_Func_BcFilterStateBase_Filter func, ISzAllocPtr alloc)
272 {
273 CXzBcFilterState *decoder;
274 if (!XZ_IS_SUPPORTED_FILTER_ID(id))
275 return SZ_ERROR_UNSUPPORTED;
276 decoder = (CXzBcFilterState *)p->p;
277 if (!decoder)
278 {
279 decoder = (CXzBcFilterState *)ISzAlloc_Alloc(alloc, sizeof(CXzBcFilterState));
280 if (!decoder)
281 return SZ_ERROR_MEM;
282 decoder->buf = ISzAlloc_Alloc(alloc, BRA_BUF_SIZE);
283 if (!decoder->buf)
284 {
285 ISzAlloc_Free(alloc, decoder);
286 return SZ_ERROR_MEM;
287 }
288 p->p = decoder;
289 p->Free = XzBcFilterState_Free;
290 p->SetProps = XzBcFilterState_SetProps;
291 p->Init = XzBcFilterState_Init;
292 p->Code2 = XzBcFilterState_Code2;
293 p->Filter = XzBcFilterState_Filter;
294 decoder->filter_func = func;
295 }
296 decoder->base.methodId = (UInt32)id;
297 // decoder->encodeMode = encodeMode;
298 return SZ_OK;
299 }
300
301
302
303 /* ---------- SbState ---------- */
304
305 #ifdef USE_SUBBLOCK
306
SbState_Free(void * pp,ISzAllocPtr alloc)307 static void SbState_Free(void *pp, ISzAllocPtr alloc)
308 {
309 CSbDec *p = (CSbDec *)pp;
310 SbDec_Free(p);
311 ISzAlloc_Free(alloc, pp);
312 }
313
SbState_SetProps(void * pp,const Byte * props,size_t propSize,ISzAllocPtr alloc)314 static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
315 {
316 UNUSED_VAR(pp)
317 UNUSED_VAR(props)
318 UNUSED_VAR(alloc)
319 return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
320 }
321
SbState_Init(void * pp)322 static void SbState_Init(void *pp)
323 {
324 SbDec_Init((CSbDec *)pp);
325 }
326
SbState_Code2(void * pp,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int srcWasFinished,ECoderFinishMode finishMode,ECoderStatus * status)327 static SRes SbState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
328 int srcWasFinished, ECoderFinishMode finishMode,
329 // int *wasFinished
330 ECoderStatus *status)
331 {
332 CSbDec *p = (CSbDec *)pp;
333 SRes res;
334 UNUSED_VAR(srcWasFinished)
335 p->dest = dest;
336 p->destLen = *destLen;
337 p->src = src;
338 p->srcLen = *srcLen;
339 p->finish = finishMode; /* change it */
340 res = SbDec_Decode((CSbDec *)pp);
341 *destLen -= p->destLen;
342 *srcLen -= p->srcLen;
343 // *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */
344 *status = (*destLen == 0 && *srcLen == 0) ?
345 CODER_STATUS_FINISHED_WITH_MARK :
346 CODER_STATUS_NOT_FINISHED;
347 return res;
348 }
349
SbState_SetFromMethod(IStateCoder * p,ISzAllocPtr alloc)350 static SRes SbState_SetFromMethod(IStateCoder *p, ISzAllocPtr alloc)
351 {
352 CSbDec *decoder = (CSbDec *)p->p;
353 if (!decoder)
354 {
355 decoder = (CSbDec *)ISzAlloc_Alloc(alloc, sizeof(CSbDec));
356 if (!decoder)
357 return SZ_ERROR_MEM;
358 p->p = decoder;
359 p->Free = SbState_Free;
360 p->SetProps = SbState_SetProps;
361 p->Init = SbState_Init;
362 p->Code2 = SbState_Code2;
363 p->Filter = NULL;
364 }
365 SbDec_Construct(decoder);
366 SbDec_SetAlloc(decoder, alloc);
367 return SZ_OK;
368 }
369
370 #endif
371
372
373
374 /* ---------- Lzma2 ---------- */
375
376 typedef struct
377 {
378 CLzma2Dec decoder;
379 BoolInt outBufMode;
380 } CLzma2Dec_Spec;
381
382
Lzma2State_Free(void * pp,ISzAllocPtr alloc)383 static void Lzma2State_Free(void *pp, ISzAllocPtr alloc)
384 {
385 CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
386 if (p->outBufMode)
387 Lzma2Dec_FreeProbs(&p->decoder, alloc);
388 else
389 Lzma2Dec_Free(&p->decoder, alloc);
390 ISzAlloc_Free(alloc, pp);
391 }
392
Lzma2State_SetProps(void * pp,const Byte * props,size_t propSize,ISzAllocPtr alloc)393 static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
394 {
395 if (propSize != 1)
396 return SZ_ERROR_UNSUPPORTED;
397 {
398 CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
399 if (p->outBufMode)
400 return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc);
401 else
402 return Lzma2Dec_Allocate(&p->decoder, props[0], alloc);
403 }
404 }
405
Lzma2State_Init(void * pp)406 static void Lzma2State_Init(void *pp)
407 {
408 Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder);
409 }
410
411
412 /*
413 if (outBufMode), then (dest) is not used. Use NULL.
414 Data is unpacked to (spec->decoder.decoder.dic) output buffer.
415 */
416
Lzma2State_Code2(void * pp,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int srcWasFinished,ECoderFinishMode finishMode,ECoderStatus * status)417 static SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
418 int srcWasFinished, ECoderFinishMode finishMode,
419 // int *wasFinished,
420 ECoderStatus *status)
421 {
422 CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp;
423 ELzmaStatus status2;
424 /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
425 SRes res;
426 UNUSED_VAR(srcWasFinished)
427 if (spec->outBufMode)
428 {
429 SizeT dicPos = spec->decoder.decoder.dicPos;
430 SizeT dicLimit = dicPos + *destLen;
431 res = Lzma2Dec_DecodeToDic(&spec->decoder, dicLimit, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
432 *destLen = spec->decoder.decoder.dicPos - dicPos;
433 }
434 else
435 res = Lzma2Dec_DecodeToBuf(&spec->decoder, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
436 // *wasFinished = (status2 == LZMA_STATUS_FINISHED_WITH_MARK);
437 // ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder
438 *status = (ECoderStatus)status2;
439 return res;
440 }
441
442
Lzma2State_SetFromMethod(IStateCoder * p,Byte * outBuf,size_t outBufSize,ISzAllocPtr alloc)443 static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc)
444 {
445 CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
446 if (!spec)
447 {
448 spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec));
449 if (!spec)
450 return SZ_ERROR_MEM;
451 p->p = spec;
452 p->Free = Lzma2State_Free;
453 p->SetProps = Lzma2State_SetProps;
454 p->Init = Lzma2State_Init;
455 p->Code2 = Lzma2State_Code2;
456 p->Filter = NULL;
457 Lzma2Dec_CONSTRUCT(&spec->decoder)
458 }
459 spec->outBufMode = False;
460 if (outBuf)
461 {
462 spec->outBufMode = True;
463 spec->decoder.decoder.dic = outBuf;
464 spec->decoder.decoder.dicBufSize = outBufSize;
465 }
466 return SZ_OK;
467 }
468
469
Lzma2State_ResetOutBuf(IStateCoder * p,Byte * outBuf,size_t outBufSize)470 static SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize)
471 {
472 CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
473 if ((spec->outBufMode && !outBuf) || (!spec->outBufMode && outBuf))
474 return SZ_ERROR_FAIL;
475 if (outBuf)
476 {
477 spec->decoder.decoder.dic = outBuf;
478 spec->decoder.decoder.dicBufSize = outBufSize;
479 }
480 return SZ_OK;
481 }
482
483
484
MixCoder_Construct(CMixCoder * p,ISzAllocPtr alloc)485 static void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc)
486 {
487 unsigned i;
488 p->alloc = alloc;
489 p->buf = NULL;
490 p->numCoders = 0;
491
492 p->outBufSize = 0;
493 p->outBuf = NULL;
494 // p->SingleBufMode = False;
495
496 for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
497 p->coders[i].p = NULL;
498 }
499
500
MixCoder_Free(CMixCoder * p)501 static void MixCoder_Free(CMixCoder *p)
502 {
503 unsigned i;
504 p->numCoders = 0;
505 for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
506 {
507 IStateCoder *sc = &p->coders[i];
508 if (sc->p)
509 {
510 sc->Free(sc->p, p->alloc);
511 sc->p = NULL;
512 }
513 }
514 if (p->buf)
515 {
516 ISzAlloc_Free(p->alloc, p->buf);
517 p->buf = NULL; /* 9.31: the BUG was fixed */
518 }
519 }
520
MixCoder_Init(CMixCoder * p)521 static void MixCoder_Init(CMixCoder *p)
522 {
523 unsigned i;
524 for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)
525 {
526 p->size[i] = 0;
527 p->pos[i] = 0;
528 p->finished[i] = 0;
529 }
530 for (i = 0; i < p->numCoders; i++)
531 {
532 IStateCoder *coder = &p->coders[i];
533 coder->Init(coder->p);
534 p->results[i] = SZ_OK;
535 }
536 p->outWritten = 0;
537 p->wasFinished = False;
538 p->res = SZ_OK;
539 p->status = CODER_STATUS_NOT_SPECIFIED;
540 }
541
542
MixCoder_SetFromMethod(CMixCoder * p,unsigned coderIndex,UInt64 methodId,Byte * outBuf,size_t outBufSize)543 static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
544 {
545 IStateCoder *sc = &p->coders[coderIndex];
546 p->ids[coderIndex] = methodId;
547 if (methodId == XZ_ID_LZMA2)
548 return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc);
549 #ifdef USE_SUBBLOCK
550 if (methodId == XZ_ID_Subblock)
551 return SbState_SetFromMethod(sc, p->alloc);
552 #endif
553 if (coderIndex == 0)
554 return SZ_ERROR_UNSUPPORTED;
555 return Xz_StateCoder_Bc_SetFromMethod_Func(sc, methodId,
556 XzBcFilterStateBase_Filter_Dec, p->alloc);
557 }
558
559
MixCoder_ResetFromMethod(CMixCoder * p,unsigned coderIndex,UInt64 methodId,Byte * outBuf,size_t outBufSize)560 static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
561 {
562 IStateCoder *sc = &p->coders[coderIndex];
563 if (methodId == XZ_ID_LZMA2)
564 return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize);
565 return SZ_ERROR_UNSUPPORTED;
566 }
567
568
569
570 /*
571 if (destFinish) - then unpack data block is finished at (*destLen) position,
572 and we can return data that were not processed by filter
573
574 output (status) can be :
575 CODER_STATUS_NOT_FINISHED
576 CODER_STATUS_FINISHED_WITH_MARK
577 CODER_STATUS_NEEDS_MORE_INPUT - not implemented still
578 */
579
MixCoder_Code(CMixCoder * p,Byte * dest,SizeT * destLen,int destFinish,const Byte * src,SizeT * srcLen,int srcWasFinished,ECoderFinishMode finishMode)580 static SRes MixCoder_Code(CMixCoder *p,
581 Byte *dest, SizeT *destLen, int destFinish,
582 const Byte *src, SizeT *srcLen, int srcWasFinished,
583 ECoderFinishMode finishMode)
584 {
585 SizeT destLenOrig = *destLen;
586 SizeT srcLenOrig = *srcLen;
587
588 *destLen = 0;
589 *srcLen = 0;
590
591 if (p->wasFinished)
592 return p->res;
593
594 p->status = CODER_STATUS_NOT_FINISHED;
595
596 // if (p->SingleBufMode)
597 if (p->outBuf)
598 {
599 SRes res;
600 SizeT destLen2, srcLen2;
601 int wasFinished;
602
603 PRF_STR("------- MixCoder Single ----------")
604
605 srcLen2 = srcLenOrig;
606 destLen2 = destLenOrig;
607
608 {
609 IStateCoder *coder = &p->coders[0];
610 res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode,
611 // &wasFinished,
612 &p->status);
613 wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK);
614 }
615
616 p->res = res;
617
618 /*
619 if (wasFinished)
620 p->status = CODER_STATUS_FINISHED_WITH_MARK;
621 else
622 {
623 if (res == SZ_OK)
624 if (destLen2 != destLenOrig)
625 p->status = CODER_STATUS_NEEDS_MORE_INPUT;
626 }
627 */
628
629
630 *srcLen = srcLen2;
631 src += srcLen2;
632 p->outWritten += destLen2;
633
634 if (res != SZ_OK || srcWasFinished || wasFinished)
635 p->wasFinished = True;
636
637 if (p->numCoders == 1)
638 *destLen = destLen2;
639 else if (p->wasFinished)
640 {
641 unsigned i;
642 size_t processed = p->outWritten;
643
644 for (i = 1; i < p->numCoders; i++)
645 {
646 IStateCoder *coder = &p->coders[i];
647 processed = coder->Filter(coder->p, p->outBuf, processed);
648 if (wasFinished || (destFinish && p->outWritten == destLenOrig))
649 processed = p->outWritten;
650 PRF_STR_INT("filter", i)
651 }
652 *destLen = processed;
653 }
654 return res;
655 }
656
657 PRF_STR("standard mix")
658
659 if (p->numCoders != 1)
660 {
661 if (!p->buf)
662 {
663 p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
664 if (!p->buf)
665 return SZ_ERROR_MEM;
666 }
667
668 finishMode = CODER_FINISH_ANY;
669 }
670
671 for (;;)
672 {
673 BoolInt processed = False;
674 BoolInt allFinished = True;
675 SRes resMain = SZ_OK;
676 unsigned i;
677
678 p->status = CODER_STATUS_NOT_FINISHED;
679 /*
680 if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
681 break;
682 */
683
684 for (i = 0; i < p->numCoders; i++)
685 {
686 SRes res;
687 IStateCoder *coder = &p->coders[i];
688 Byte *dest2;
689 SizeT destLen2, srcLen2; // destLen2_Orig;
690 const Byte *src2;
691 int srcFinished2;
692 int encodingWasFinished;
693 ECoderStatus status2;
694
695 if (i == 0)
696 {
697 src2 = src;
698 srcLen2 = srcLenOrig - *srcLen;
699 srcFinished2 = srcWasFinished;
700 }
701 else
702 {
703 size_t k = i - 1;
704 src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k];
705 srcLen2 = p->size[k] - p->pos[k];
706 srcFinished2 = p->finished[k];
707 }
708
709 if (i == p->numCoders - 1)
710 {
711 dest2 = dest;
712 destLen2 = destLenOrig - *destLen;
713 }
714 else
715 {
716 if (p->pos[i] != p->size[i])
717 continue;
718 dest2 = p->buf + (CODER_BUF_SIZE * i);
719 destLen2 = CODER_BUF_SIZE;
720 }
721
722 // destLen2_Orig = destLen2;
723
724 if (p->results[i] != SZ_OK)
725 {
726 if (resMain == SZ_OK)
727 resMain = p->results[i];
728 continue;
729 }
730
731 res = coder->Code2(coder->p,
732 dest2, &destLen2,
733 src2, &srcLen2, srcFinished2,
734 finishMode,
735 // &encodingWasFinished,
736 &status2);
737
738 if (res != SZ_OK)
739 {
740 p->results[i] = res;
741 if (resMain == SZ_OK)
742 resMain = res;
743 }
744
745 encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK);
746
747 if (!encodingWasFinished)
748 {
749 allFinished = False;
750 if (p->numCoders == 1 && res == SZ_OK)
751 p->status = status2;
752 }
753
754 if (i == 0)
755 {
756 *srcLen += srcLen2;
757 src += srcLen2;
758 }
759 else
760 p->pos[(size_t)i - 1] += srcLen2;
761
762 if (i == p->numCoders - 1)
763 {
764 *destLen += destLen2;
765 dest += destLen2;
766 }
767 else
768 {
769 p->size[i] = destLen2;
770 p->pos[i] = 0;
771 p->finished[i] = encodingWasFinished;
772 }
773
774 if (destLen2 != 0 || srcLen2 != 0)
775 processed = True;
776 }
777
778 if (!processed)
779 {
780 if (allFinished)
781 p->status = CODER_STATUS_FINISHED_WITH_MARK;
782 return resMain;
783 }
784 }
785 }
786
787
Xz_ParseHeader(CXzStreamFlags * p,const Byte * buf)788 SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
789 {
790 *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);
791 if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=
792 GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))
793 return SZ_ERROR_NO_ARCHIVE;
794 return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
795 }
796
Xz_CheckFooter(CXzStreamFlags flags,UInt64 indexSize,const Byte * buf)797 static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
798 {
799 return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2)
800 && GetUi32(buf) == CrcCalc(buf + 4, 6)
801 && flags == GetBe16(buf + 8)
802 && buf[10] == XZ_FOOTER_SIG_0
803 && buf[11] == XZ_FOOTER_SIG_1;
804 }
805
806 #define READ_VARINT_AND_CHECK(buf, pos, size, res) \
807 { const unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
808 if (s == 0) return SZ_ERROR_ARCHIVE; \
809 pos += s; }
810
811
XzBlock_AreSupportedFilters(const CXzBlock * p)812 static BoolInt XzBlock_AreSupportedFilters(const CXzBlock *p)
813 {
814 const unsigned numFilters = XzBlock_GetNumFilters(p) - 1;
815 unsigned i;
816 {
817 const CXzFilter *f = &p->filters[numFilters];
818 if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40)
819 return False;
820 }
821
822 for (i = 0; i < numFilters; i++)
823 {
824 const CXzFilter *f = &p->filters[i];
825 if (f->id == XZ_ID_Delta)
826 {
827 if (f->propsSize != 1)
828 return False;
829 }
830 else if (!XZ_IS_SUPPORTED_FILTER_ID(f->id)
831 || (f->propsSize != 0 && f->propsSize != 4))
832 return False;
833 }
834 return True;
835 }
836
837
XzBlock_Parse(CXzBlock * p,const Byte * header)838 SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
839 {
840 unsigned pos;
841 unsigned numFilters, i;
842 unsigned headerSize = (unsigned)header[0] << 2;
843
844 /* (headerSize != 0) : another code checks */
845
846 if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
847 return SZ_ERROR_ARCHIVE;
848
849 pos = 1;
850 p->flags = header[pos++];
851
852 p->packSize = (UInt64)(Int64)-1;
853 if (XzBlock_HasPackSize(p))
854 {
855 READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize)
856 if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)
857 return SZ_ERROR_ARCHIVE;
858 }
859
860 p->unpackSize = (UInt64)(Int64)-1;
861 if (XzBlock_HasUnpackSize(p))
862 {
863 READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize)
864 }
865
866 numFilters = XzBlock_GetNumFilters(p);
867 for (i = 0; i < numFilters; i++)
868 {
869 CXzFilter *filter = p->filters + i;
870 UInt64 size;
871 READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id)
872 READ_VARINT_AND_CHECK(header, pos, headerSize, &size)
873 if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)
874 return SZ_ERROR_ARCHIVE;
875 filter->propsSize = (UInt32)size;
876 memcpy(filter->props, header + pos, (size_t)size);
877 pos += (unsigned)size;
878
879 #ifdef XZ_DUMP
880 printf("\nf[%u] = %2X: ", i, (unsigned)filter->id);
881 {
882 unsigned i;
883 for (i = 0; i < size; i++)
884 printf(" %2X", filter->props[i]);
885 }
886 #endif
887 }
888
889 if (XzBlock_HasUnsupportedFlags(p))
890 return SZ_ERROR_UNSUPPORTED;
891
892 while (pos < headerSize)
893 if (header[pos++] != 0)
894 return SZ_ERROR_ARCHIVE;
895 return SZ_OK;
896 }
897
898
899
900
XzDecMix_Init(CMixCoder * p,const CXzBlock * block,Byte * outBuf,size_t outBufSize)901 static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize)
902 {
903 unsigned i;
904 BoolInt needReInit = True;
905 unsigned numFilters = XzBlock_GetNumFilters(block);
906
907 if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf)))
908 {
909 needReInit = False;
910 for (i = 0; i < numFilters; i++)
911 if (p->ids[i] != block->filters[numFilters - 1 - i].id)
912 {
913 needReInit = True;
914 break;
915 }
916 }
917
918 // p->SingleBufMode = (outBuf != NULL);
919 p->outBuf = outBuf;
920 p->outBufSize = outBufSize;
921
922 // p->SingleBufMode = False;
923 // outBuf = NULL;
924
925 if (needReInit)
926 {
927 MixCoder_Free(p);
928 for (i = 0; i < numFilters; i++)
929 {
930 RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize))
931 }
932 p->numCoders = numFilters;
933 }
934 else
935 {
936 RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize))
937 }
938
939 for (i = 0; i < numFilters; i++)
940 {
941 const CXzFilter *f = &block->filters[numFilters - 1 - i];
942 IStateCoder *sc = &p->coders[i];
943 RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc))
944 }
945
946 MixCoder_Init(p);
947 return SZ_OK;
948 }
949
950
951
XzUnpacker_Init(CXzUnpacker * p)952 void XzUnpacker_Init(CXzUnpacker *p)
953 {
954 p->state = XZ_STATE_STREAM_HEADER;
955 p->pos = 0;
956 p->numStartedStreams = 0;
957 p->numFinishedStreams = 0;
958 p->numTotalBlocks = 0;
959 p->padSize = 0;
960 p->decodeOnlyOneBlock = 0;
961
962 p->parseMode = False;
963 p->decodeToStreamSignature = False;
964
965 // p->outBuf = NULL;
966 // p->outBufSize = 0;
967 p->outDataWritten = 0;
968 }
969
970
XzUnpacker_SetOutBuf(CXzUnpacker * p,Byte * outBuf,size_t outBufSize)971 void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize)
972 {
973 p->outBuf = outBuf;
974 p->outBufSize = outBufSize;
975 }
976
977
XzUnpacker_Construct(CXzUnpacker * p,ISzAllocPtr alloc)978 void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc)
979 {
980 MixCoder_Construct(&p->decoder, alloc);
981 p->outBuf = NULL;
982 p->outBufSize = 0;
983 XzUnpacker_Init(p);
984 }
985
986
XzUnpacker_Free(CXzUnpacker * p)987 void XzUnpacker_Free(CXzUnpacker *p)
988 {
989 MixCoder_Free(&p->decoder);
990 }
991
992
XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker * p)993 void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p)
994 {
995 p->indexSize = 0;
996 p->numBlocks = 0;
997 Sha256_Init(&p->sha);
998 p->state = XZ_STATE_BLOCK_HEADER;
999 p->pos = 0;
1000 p->decodeOnlyOneBlock = 1;
1001 }
1002
1003
XzUnpacker_UpdateIndex(CXzUnpacker * p,UInt64 packSize,UInt64 unpackSize)1004 static void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize)
1005 {
1006 Byte temp[32];
1007 unsigned num = Xz_WriteVarInt(temp, packSize);
1008 num += Xz_WriteVarInt(temp + num, unpackSize);
1009 Sha256_Update(&p->sha, temp, num);
1010 p->indexSize += num;
1011 p->numBlocks++;
1012 }
1013
1014
1015
XzUnpacker_Code(CXzUnpacker * p,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,int srcFinished,ECoderFinishMode finishMode,ECoderStatus * status)1016 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
1017 const Byte *src, SizeT *srcLen, int srcFinished,
1018 ECoderFinishMode finishMode, ECoderStatus *status)
1019 {
1020 SizeT destLenOrig = *destLen;
1021 SizeT srcLenOrig = *srcLen;
1022 *destLen = 0;
1023 *srcLen = 0;
1024 *status = CODER_STATUS_NOT_SPECIFIED;
1025
1026 for (;;)
1027 {
1028 SizeT srcRem;
1029
1030 if (p->state == XZ_STATE_BLOCK)
1031 {
1032 SizeT destLen2 = destLenOrig - *destLen;
1033 SizeT srcLen2 = srcLenOrig - *srcLen;
1034 SRes res;
1035
1036 ECoderFinishMode finishMode2 = finishMode;
1037 BoolInt srcFinished2 = (BoolInt)srcFinished;
1038 BoolInt destFinish = False;
1039
1040 if (p->block.packSize != (UInt64)(Int64)-1)
1041 {
1042 UInt64 rem = p->block.packSize - p->packSize;
1043 if (srcLen2 >= rem)
1044 {
1045 srcFinished2 = True;
1046 srcLen2 = (SizeT)rem;
1047 }
1048 if (rem == 0 && p->block.unpackSize == p->unpackSize)
1049 return SZ_ERROR_DATA;
1050 }
1051
1052 if (p->block.unpackSize != (UInt64)(Int64)-1)
1053 {
1054 UInt64 rem = p->block.unpackSize - p->unpackSize;
1055 if (destLen2 >= rem)
1056 {
1057 destFinish = True;
1058 finishMode2 = CODER_FINISH_END;
1059 destLen2 = (SizeT)rem;
1060 }
1061 }
1062
1063 /*
1064 if (srcLen2 == 0 && destLen2 == 0)
1065 {
1066 *status = CODER_STATUS_NOT_FINISHED;
1067 return SZ_OK;
1068 }
1069 */
1070
1071 {
1072 res = MixCoder_Code(&p->decoder,
1073 (p->outBuf ? NULL : dest), &destLen2, destFinish,
1074 src, &srcLen2, srcFinished2,
1075 finishMode2);
1076
1077 *status = p->decoder.status;
1078 XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2);
1079 if (!p->outBuf)
1080 dest += destLen2;
1081 p->outDataWritten += destLen2;
1082 }
1083
1084 (*srcLen) += srcLen2;
1085 src += srcLen2;
1086 p->packSize += srcLen2;
1087 (*destLen) += destLen2;
1088 p->unpackSize += destLen2;
1089
1090 RINOK(res)
1091
1092 if (*status != CODER_STATUS_FINISHED_WITH_MARK)
1093 {
1094 if (p->block.packSize == p->packSize
1095 && *status == CODER_STATUS_NEEDS_MORE_INPUT)
1096 {
1097 PRF_STR("CODER_STATUS_NEEDS_MORE_INPUT")
1098 *status = CODER_STATUS_NOT_SPECIFIED;
1099 return SZ_ERROR_DATA;
1100 }
1101
1102 return SZ_OK;
1103 }
1104 {
1105 XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize);
1106 p->state = XZ_STATE_BLOCK_FOOTER;
1107 p->pos = 0;
1108 p->alignPos = 0;
1109 *status = CODER_STATUS_NOT_SPECIFIED;
1110
1111 if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize)
1112 || (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize))
1113 {
1114 PRF_STR("ERROR: block.size mismatch")
1115 return SZ_ERROR_DATA;
1116 }
1117 }
1118 // continue;
1119 }
1120
1121 srcRem = srcLenOrig - *srcLen;
1122
1123 // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes
1124 if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER)
1125 {
1126 *status = CODER_STATUS_NEEDS_MORE_INPUT;
1127 return SZ_OK;
1128 }
1129
1130 switch ((int)p->state)
1131 {
1132 case XZ_STATE_STREAM_HEADER:
1133 {
1134 if (p->pos < XZ_STREAM_HEADER_SIZE)
1135 {
1136 if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
1137 return SZ_ERROR_NO_ARCHIVE;
1138 if (p->decodeToStreamSignature)
1139 return SZ_OK;
1140 p->buf[p->pos++] = *src++;
1141 (*srcLen)++;
1142 }
1143 else
1144 {
1145 RINOK(Xz_ParseHeader(&p->streamFlags, p->buf))
1146 p->numStartedStreams++;
1147 p->indexSize = 0;
1148 p->numBlocks = 0;
1149 Sha256_Init(&p->sha);
1150 p->state = XZ_STATE_BLOCK_HEADER;
1151 p->pos = 0;
1152 }
1153 break;
1154 }
1155
1156 case XZ_STATE_BLOCK_HEADER:
1157 {
1158 if (p->pos == 0)
1159 {
1160 p->buf[p->pos++] = *src++;
1161 (*srcLen)++;
1162 if (p->buf[0] == 0)
1163 {
1164 if (p->decodeOnlyOneBlock)
1165 return SZ_ERROR_DATA;
1166 p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
1167 p->indexPos = p->indexPreSize;
1168 p->indexSize += p->indexPreSize;
1169 Sha256_Final(&p->sha, p->shaDigest);
1170 Sha256_Init(&p->sha);
1171 p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
1172 p->state = XZ_STATE_STREAM_INDEX;
1173 break;
1174 }
1175 p->blockHeaderSize = ((unsigned)p->buf[0] << 2) + 4;
1176 break;
1177 }
1178
1179 if (p->pos != p->blockHeaderSize)
1180 {
1181 unsigned cur = p->blockHeaderSize - p->pos;
1182 if (cur > srcRem)
1183 cur = (unsigned)srcRem;
1184 memcpy(p->buf + p->pos, src, cur);
1185 p->pos += cur;
1186 (*srcLen) += cur;
1187 src += cur;
1188 }
1189 else
1190 {
1191 RINOK(XzBlock_Parse(&p->block, p->buf))
1192 if (!XzBlock_AreSupportedFilters(&p->block))
1193 return SZ_ERROR_UNSUPPORTED;
1194 p->numTotalBlocks++;
1195 p->state = XZ_STATE_BLOCK;
1196 p->packSize = 0;
1197 p->unpackSize = 0;
1198 XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
1199 if (p->parseMode)
1200 {
1201 p->headerParsedOk = True;
1202 return SZ_OK;
1203 }
1204 RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize))
1205 }
1206 break;
1207 }
1208
1209 case XZ_STATE_BLOCK_FOOTER:
1210 {
1211 if ((((unsigned)p->packSize + p->alignPos) & 3) != 0)
1212 {
1213 if (srcRem == 0)
1214 {
1215 *status = CODER_STATUS_NEEDS_MORE_INPUT;
1216 return SZ_OK;
1217 }
1218 (*srcLen)++;
1219 p->alignPos++;
1220 if (*src++ != 0)
1221 return SZ_ERROR_CRC;
1222 }
1223 else
1224 {
1225 const unsigned checkSize = XzFlags_GetCheckSize(p->streamFlags);
1226 unsigned cur = checkSize - p->pos;
1227 if (cur != 0)
1228 {
1229 if (srcRem == 0)
1230 {
1231 *status = CODER_STATUS_NEEDS_MORE_INPUT;
1232 return SZ_OK;
1233 }
1234 if (cur > srcRem)
1235 cur = (unsigned)srcRem;
1236 memcpy(p->buf + p->pos, src, cur);
1237 p->pos += cur;
1238 (*srcLen) += cur;
1239 src += cur;
1240 if (checkSize != p->pos)
1241 break;
1242 }
1243 {
1244 Byte digest[XZ_CHECK_SIZE_MAX];
1245 p->state = XZ_STATE_BLOCK_HEADER;
1246 p->pos = 0;
1247 if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
1248 return SZ_ERROR_CRC;
1249 if (p->decodeOnlyOneBlock)
1250 {
1251 *status = CODER_STATUS_FINISHED_WITH_MARK;
1252 return SZ_OK;
1253 }
1254 }
1255 }
1256 break;
1257 }
1258
1259 case XZ_STATE_STREAM_INDEX:
1260 {
1261 if (p->pos < p->indexPreSize)
1262 {
1263 (*srcLen)++;
1264 if (*src++ != p->buf[p->pos++])
1265 return SZ_ERROR_CRC;
1266 }
1267 else
1268 {
1269 if (p->indexPos < p->indexSize)
1270 {
1271 UInt64 cur = p->indexSize - p->indexPos;
1272 if (srcRem > cur)
1273 srcRem = (SizeT)cur;
1274 p->crc = CrcUpdate(p->crc, src, srcRem);
1275 Sha256_Update(&p->sha, src, srcRem);
1276 (*srcLen) += srcRem;
1277 src += srcRem;
1278 p->indexPos += srcRem;
1279 }
1280 else if ((p->indexPos & 3) != 0)
1281 {
1282 Byte b = *src++;
1283 p->crc = CRC_UPDATE_BYTE(p->crc, b);
1284 (*srcLen)++;
1285 p->indexPos++;
1286 p->indexSize++;
1287 if (b != 0)
1288 return SZ_ERROR_CRC;
1289 }
1290 else
1291 {
1292 Byte digest[SHA256_DIGEST_SIZE];
1293 p->state = XZ_STATE_STREAM_INDEX_CRC;
1294 p->indexSize += 4;
1295 p->pos = 0;
1296 Sha256_Final(&p->sha, digest);
1297 if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
1298 return SZ_ERROR_CRC;
1299 }
1300 }
1301 break;
1302 }
1303
1304 case XZ_STATE_STREAM_INDEX_CRC:
1305 {
1306 if (p->pos < 4)
1307 {
1308 (*srcLen)++;
1309 p->buf[p->pos++] = *src++;
1310 }
1311 else
1312 {
1313 const Byte *ptr = p->buf;
1314 p->state = XZ_STATE_STREAM_FOOTER;
1315 p->pos = 0;
1316 if (CRC_GET_DIGEST(p->crc) != GetUi32(ptr))
1317 return SZ_ERROR_CRC;
1318 }
1319 break;
1320 }
1321
1322 case XZ_STATE_STREAM_FOOTER:
1323 {
1324 unsigned cur = XZ_STREAM_FOOTER_SIZE - p->pos;
1325 if (cur > srcRem)
1326 cur = (unsigned)srcRem;
1327 memcpy(p->buf + p->pos, src, cur);
1328 p->pos += cur;
1329 (*srcLen) += cur;
1330 src += cur;
1331 if (p->pos == XZ_STREAM_FOOTER_SIZE)
1332 {
1333 p->state = XZ_STATE_STREAM_PADDING;
1334 p->numFinishedStreams++;
1335 p->padSize = 0;
1336 if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))
1337 return SZ_ERROR_CRC;
1338 }
1339 break;
1340 }
1341
1342 case XZ_STATE_STREAM_PADDING:
1343 {
1344 if (*src != 0)
1345 {
1346 if (((UInt32)p->padSize & 3) != 0)
1347 return SZ_ERROR_NO_ARCHIVE;
1348 p->pos = 0;
1349 p->state = XZ_STATE_STREAM_HEADER;
1350 }
1351 else
1352 {
1353 (*srcLen)++;
1354 src++;
1355 p->padSize++;
1356 }
1357 break;
1358 }
1359
1360 case XZ_STATE_BLOCK: break; /* to disable GCC warning */
1361
1362 default: return SZ_ERROR_FAIL;
1363 }
1364 }
1365 /*
1366 if (p->state == XZ_STATE_FINISHED)
1367 *status = CODER_STATUS_FINISHED_WITH_MARK;
1368 return SZ_OK;
1369 */
1370 }
1371
1372
XzUnpacker_CodeFull(CXzUnpacker * p,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,ECoderFinishMode finishMode,ECoderStatus * status)1373 SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,
1374 const Byte *src, SizeT *srcLen,
1375 ECoderFinishMode finishMode, ECoderStatus *status)
1376 {
1377 XzUnpacker_Init(p);
1378 XzUnpacker_SetOutBuf(p, dest, *destLen);
1379
1380 return XzUnpacker_Code(p,
1381 NULL, destLen,
1382 src, srcLen, True,
1383 finishMode, status);
1384 }
1385
1386
XzUnpacker_IsBlockFinished(const CXzUnpacker * p)1387 BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p)
1388 {
1389 return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0);
1390 }
1391
XzUnpacker_IsStreamWasFinished(const CXzUnpacker * p)1392 BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p)
1393 {
1394 return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
1395 }
1396
XzUnpacker_GetExtraSize(const CXzUnpacker * p)1397 UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p)
1398 {
1399 UInt64 num = 0;
1400 if (p->state == XZ_STATE_STREAM_PADDING)
1401 num = p->padSize;
1402 else if (p->state == XZ_STATE_STREAM_HEADER)
1403 num = p->padSize + p->pos;
1404 return num;
1405 }
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427 #ifndef Z7_ST
1428 #include "MtDec.h"
1429 #endif
1430
1431
XzDecMtProps_Init(CXzDecMtProps * p)1432 void XzDecMtProps_Init(CXzDecMtProps *p)
1433 {
1434 p->inBufSize_ST = 1 << 18;
1435 p->outStep_ST = 1 << 20;
1436 p->ignoreErrors = False;
1437
1438 #ifndef Z7_ST
1439 p->numThreads = 1;
1440 p->inBufSize_MT = 1 << 18;
1441 p->memUseMax = sizeof(size_t) << 28;
1442 #endif
1443 }
1444
1445
1446
1447 #ifndef Z7_ST
1448
1449 /* ---------- CXzDecMtThread ---------- */
1450
1451 typedef struct
1452 {
1453 Byte *outBuf;
1454 size_t outBufSize;
1455 size_t outPreSize;
1456 size_t inPreSize;
1457 size_t inPreHeaderSize;
1458 size_t blockPackSize_for_Index; // including block header and checksum.
1459 size_t blockPackTotal; // including stream header, block header and checksum.
1460 size_t inCodeSize;
1461 size_t outCodeSize;
1462 ECoderStatus status;
1463 SRes codeRes;
1464 BoolInt skipMode;
1465 // BoolInt finishedWithMark;
1466 EMtDecParseState parseState;
1467 BoolInt parsing_Truncated;
1468 BoolInt atBlockHeader;
1469 CXzStreamFlags streamFlags;
1470 // UInt64 numFinishedStreams
1471 UInt64 numStreams;
1472 UInt64 numTotalBlocks;
1473 UInt64 numBlocks;
1474
1475 BoolInt dec_created;
1476 CXzUnpacker dec;
1477
1478 Byte mtPad[1 << 7];
1479 } CXzDecMtThread;
1480
1481 #endif
1482
1483
1484 /* ---------- CXzDecMt ---------- */
1485
1486 struct CXzDecMt
1487 {
1488 CAlignOffsetAlloc alignOffsetAlloc;
1489 ISzAllocPtr allocMid;
1490
1491 CXzDecMtProps props;
1492 size_t unpackBlockMaxSize;
1493
1494 ISeqInStreamPtr inStream;
1495 ISeqOutStreamPtr outStream;
1496 ICompressProgressPtr progress;
1497
1498 BoolInt finishMode;
1499 BoolInt outSize_Defined;
1500 UInt64 outSize;
1501
1502 UInt64 outProcessed;
1503 UInt64 inProcessed;
1504 UInt64 readProcessed;
1505 BoolInt readWasFinished;
1506 SRes readRes;
1507 SRes writeRes;
1508
1509 Byte *outBuf;
1510 size_t outBufSize;
1511 Byte *inBuf;
1512 size_t inBufSize;
1513
1514 CXzUnpacker dec;
1515
1516 ECoderStatus status;
1517 SRes codeRes;
1518
1519 #ifndef Z7_ST
1520 BoolInt mainDecoderWasCalled;
1521 // int statErrorDefined;
1522 int finishedDecoderIndex;
1523
1524 // global values that are used in Parse stage
1525 CXzStreamFlags streamFlags;
1526 // UInt64 numFinishedStreams
1527 UInt64 numStreams;
1528 UInt64 numTotalBlocks;
1529 UInt64 numBlocks;
1530
1531 // UInt64 numBadBlocks;
1532 SRes mainErrorCode; // it's set to error code, if the size Code() output doesn't patch the size from Parsing stage
1533 // it can be = SZ_ERROR_INPUT_EOF
1534 // it can be = SZ_ERROR_DATA, in some another cases
1535 BoolInt isBlockHeaderState_Parse;
1536 BoolInt isBlockHeaderState_Write;
1537 UInt64 outProcessed_Parse;
1538 BoolInt parsing_Truncated;
1539
1540 BoolInt mtc_WasConstructed;
1541 CMtDec mtc;
1542 CXzDecMtThread coders[MTDEC_THREADS_MAX];
1543 #endif
1544 };
1545
1546
1547
XzDecMt_Create(ISzAllocPtr alloc,ISzAllocPtr allocMid)1548 CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)
1549 {
1550 CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt));
1551 if (!p)
1552 return NULL;
1553
1554 AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);
1555 p->alignOffsetAlloc.baseAlloc = alloc;
1556 p->alignOffsetAlloc.numAlignBits = 7;
1557 p->alignOffsetAlloc.offset = 0;
1558
1559 p->allocMid = allocMid;
1560
1561 p->outBuf = NULL;
1562 p->outBufSize = 0;
1563 p->inBuf = NULL;
1564 p->inBufSize = 0;
1565
1566 XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt);
1567
1568 p->unpackBlockMaxSize = 0;
1569
1570 XzDecMtProps_Init(&p->props);
1571
1572 #ifndef Z7_ST
1573 p->mtc_WasConstructed = False;
1574 {
1575 unsigned i;
1576 for (i = 0; i < MTDEC_THREADS_MAX; i++)
1577 {
1578 CXzDecMtThread *coder = &p->coders[i];
1579 coder->dec_created = False;
1580 coder->outBuf = NULL;
1581 coder->outBufSize = 0;
1582 }
1583 }
1584 #endif
1585
1586 return (CXzDecMtHandle)p;
1587 }
1588
1589
1590 #ifndef Z7_ST
1591
XzDecMt_FreeOutBufs(CXzDecMt * p)1592 static void XzDecMt_FreeOutBufs(CXzDecMt *p)
1593 {
1594 unsigned i;
1595 for (i = 0; i < MTDEC_THREADS_MAX; i++)
1596 {
1597 CXzDecMtThread *coder = &p->coders[i];
1598 if (coder->outBuf)
1599 {
1600 ISzAlloc_Free(p->allocMid, coder->outBuf);
1601 coder->outBuf = NULL;
1602 coder->outBufSize = 0;
1603 }
1604 }
1605 p->unpackBlockMaxSize = 0;
1606 }
1607
1608 #endif
1609
1610
1611
XzDecMt_FreeSt(CXzDecMt * p)1612 static void XzDecMt_FreeSt(CXzDecMt *p)
1613 {
1614 XzUnpacker_Free(&p->dec);
1615
1616 if (p->outBuf)
1617 {
1618 ISzAlloc_Free(p->allocMid, p->outBuf);
1619 p->outBuf = NULL;
1620 }
1621 p->outBufSize = 0;
1622
1623 if (p->inBuf)
1624 {
1625 ISzAlloc_Free(p->allocMid, p->inBuf);
1626 p->inBuf = NULL;
1627 }
1628 p->inBufSize = 0;
1629 }
1630
1631
1632 // #define GET_CXzDecMt_p CXzDecMt *p = pp;
1633
XzDecMt_Destroy(CXzDecMtHandle p)1634 void XzDecMt_Destroy(CXzDecMtHandle p)
1635 {
1636 // GET_CXzDecMt_p
1637
1638 XzDecMt_FreeSt(p);
1639
1640 #ifndef Z7_ST
1641
1642 if (p->mtc_WasConstructed)
1643 {
1644 MtDec_Destruct(&p->mtc);
1645 p->mtc_WasConstructed = False;
1646 }
1647 {
1648 unsigned i;
1649 for (i = 0; i < MTDEC_THREADS_MAX; i++)
1650 {
1651 CXzDecMtThread *t = &p->coders[i];
1652 if (t->dec_created)
1653 {
1654 // we don't need to free dict here
1655 XzUnpacker_Free(&t->dec);
1656 t->dec_created = False;
1657 }
1658 }
1659 }
1660 XzDecMt_FreeOutBufs(p);
1661
1662 #endif
1663
1664 ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, p);
1665 }
1666
1667
1668
1669 #ifndef Z7_ST
1670
XzDecMt_Callback_Parse(void * obj,unsigned coderIndex,CMtDecCallbackInfo * cc)1671 static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)
1672 {
1673 CXzDecMt *me = (CXzDecMt *)obj;
1674 CXzDecMtThread *coder = &me->coders[coderIndex];
1675 size_t srcSize = cc->srcSize;
1676
1677 cc->srcSize = 0;
1678 cc->outPos = 0;
1679 cc->state = MTDEC_PARSE_CONTINUE;
1680
1681 cc->canCreateNewThread = True;
1682
1683 if (cc->startCall)
1684 {
1685 coder->outPreSize = 0;
1686 coder->inPreSize = 0;
1687 coder->inPreHeaderSize = 0;
1688 coder->parseState = MTDEC_PARSE_CONTINUE;
1689 coder->parsing_Truncated = False;
1690 coder->skipMode = False;
1691 coder->codeRes = SZ_OK;
1692 coder->status = CODER_STATUS_NOT_SPECIFIED;
1693 coder->inCodeSize = 0;
1694 coder->outCodeSize = 0;
1695
1696 coder->numStreams = me->numStreams;
1697 coder->numTotalBlocks = me->numTotalBlocks;
1698 coder->numBlocks = me->numBlocks;
1699
1700 if (!coder->dec_created)
1701 {
1702 XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt);
1703 coder->dec_created = True;
1704 }
1705
1706 XzUnpacker_Init(&coder->dec);
1707
1708 if (me->isBlockHeaderState_Parse)
1709 {
1710 coder->dec.streamFlags = me->streamFlags;
1711 coder->atBlockHeader = True;
1712 XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec);
1713 }
1714 else
1715 {
1716 coder->atBlockHeader = False;
1717 me->isBlockHeaderState_Parse = True;
1718 }
1719
1720 coder->dec.numStartedStreams = me->numStreams;
1721 coder->dec.numTotalBlocks = me->numTotalBlocks;
1722 coder->dec.numBlocks = me->numBlocks;
1723 }
1724
1725 while (!coder->skipMode)
1726 {
1727 ECoderStatus status;
1728 SRes res;
1729 size_t srcSize2 = srcSize;
1730 size_t destSize = (size_t)0 - 1;
1731
1732 coder->dec.parseMode = True;
1733 coder->dec.headerParsedOk = False;
1734
1735 PRF_STR_INT("Parse", srcSize2)
1736
1737 res = XzUnpacker_Code(&coder->dec,
1738 NULL, &destSize,
1739 cc->src, &srcSize2, cc->srcFinished,
1740 CODER_FINISH_END, &status);
1741
1742 // PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2));
1743
1744 coder->codeRes = res;
1745 coder->status = status;
1746 cc->srcSize += srcSize2;
1747 srcSize -= srcSize2;
1748 coder->inPreHeaderSize += srcSize2;
1749 coder->inPreSize = coder->inPreHeaderSize;
1750
1751 if (res != SZ_OK)
1752 {
1753 cc->state =
1754 coder->parseState = MTDEC_PARSE_END;
1755 /*
1756 if (res == SZ_ERROR_MEM)
1757 return res;
1758 return SZ_OK;
1759 */
1760 return; // res;
1761 }
1762
1763 if (coder->dec.headerParsedOk)
1764 {
1765 const CXzBlock *block = &coder->dec.block;
1766 if (XzBlock_HasUnpackSize(block)
1767 // && block->unpackSize <= me->props.outBlockMax
1768 && XzBlock_HasPackSize(block))
1769 {
1770 {
1771 if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax)
1772 {
1773 cc->state = MTDEC_PARSE_OVERFLOW;
1774 return; // SZ_OK;
1775 }
1776 }
1777 {
1778 const UInt64 packSize = block->packSize;
1779 const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
1780 const unsigned checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags);
1781 const UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize;
1782 // if (blockPackSum <= me->props.inBlockMax)
1783 // unpackBlockMaxSize
1784 {
1785 coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize);
1786 coder->blockPackTotal = (size_t)blockPackSum;
1787 coder->outPreSize = (size_t)block->unpackSize;
1788 coder->streamFlags = coder->dec.streamFlags;
1789 me->streamFlags = coder->dec.streamFlags;
1790 coder->skipMode = True;
1791 break;
1792 }
1793 }
1794 }
1795 }
1796 else
1797 // if (coder->inPreSize <= me->props.inBlockMax)
1798 {
1799 if (!cc->srcFinished)
1800 return; // SZ_OK;
1801 cc->state =
1802 coder->parseState = MTDEC_PARSE_END;
1803 return; // SZ_OK;
1804 }
1805 cc->state = MTDEC_PARSE_OVERFLOW;
1806 return; // SZ_OK;
1807 }
1808
1809 // ---------- skipMode ----------
1810 {
1811 UInt64 rem = coder->blockPackTotal - coder->inPreSize;
1812 size_t cur = srcSize;
1813 if (cur > rem)
1814 cur = (size_t)rem;
1815 cc->srcSize += cur;
1816 coder->inPreSize += cur;
1817 srcSize -= cur;
1818
1819 if (coder->inPreSize == coder->blockPackTotal)
1820 {
1821 if (srcSize == 0)
1822 {
1823 if (!cc->srcFinished)
1824 return; // SZ_OK;
1825 cc->state = MTDEC_PARSE_END;
1826 }
1827 else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block
1828 cc->state = MTDEC_PARSE_END;
1829 else
1830 {
1831 cc->state = MTDEC_PARSE_NEW;
1832
1833 {
1834 size_t blockMax = me->unpackBlockMaxSize;
1835 if (blockMax < coder->outPreSize)
1836 blockMax = coder->outPreSize;
1837 {
1838 UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2;
1839 if (me->props.memUseMax < required)
1840 cc->canCreateNewThread = False;
1841 }
1842 }
1843
1844 if (me->outSize_Defined)
1845 {
1846 // next block can be zero size
1847 const UInt64 rem2 = me->outSize - me->outProcessed_Parse;
1848 if (rem2 < coder->outPreSize)
1849 {
1850 coder->parsing_Truncated = True;
1851 cc->state = MTDEC_PARSE_END;
1852 }
1853 me->outProcessed_Parse += coder->outPreSize;
1854 }
1855 }
1856 }
1857 else if (cc->srcFinished)
1858 cc->state = MTDEC_PARSE_END;
1859 else
1860 return; // SZ_OK;
1861
1862 coder->parseState = cc->state;
1863 cc->outPos = coder->outPreSize;
1864
1865 me->numStreams = coder->dec.numStartedStreams;
1866 me->numTotalBlocks = coder->dec.numTotalBlocks;
1867 me->numBlocks = coder->dec.numBlocks + 1;
1868 return; // SZ_OK;
1869 }
1870 }
1871
1872
XzDecMt_Callback_PreCode(void * pp,unsigned coderIndex)1873 static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex)
1874 {
1875 CXzDecMt *me = (CXzDecMt *)pp;
1876 CXzDecMtThread *coder = &me->coders[coderIndex];
1877 Byte *dest;
1878
1879 if (!coder->dec.headerParsedOk)
1880 return SZ_OK;
1881
1882 dest = coder->outBuf;
1883
1884 if (!dest || coder->outBufSize < coder->outPreSize)
1885 {
1886 if (dest)
1887 {
1888 ISzAlloc_Free(me->allocMid, dest);
1889 coder->outBuf = NULL;
1890 coder->outBufSize = 0;
1891 }
1892 {
1893 size_t outPreSize = coder->outPreSize;
1894 if (outPreSize == 0)
1895 outPreSize = 1;
1896 dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize);
1897 }
1898 if (!dest)
1899 return SZ_ERROR_MEM;
1900 coder->outBuf = dest;
1901 coder->outBufSize = coder->outPreSize;
1902
1903 if (coder->outBufSize > me->unpackBlockMaxSize)
1904 me->unpackBlockMaxSize = coder->outBufSize;
1905 }
1906
1907 // return SZ_ERROR_MEM;
1908
1909 XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize);
1910
1911 {
1912 SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize);
1913 // res = SZ_ERROR_UNSUPPORTED; // to test
1914 coder->codeRes = res;
1915 if (res != SZ_OK)
1916 {
1917 // if (res == SZ_ERROR_MEM) return res;
1918 if (me->props.ignoreErrors && res != SZ_ERROR_MEM)
1919 return SZ_OK;
1920 return res;
1921 }
1922 }
1923
1924 return SZ_OK;
1925 }
1926
1927
XzDecMt_Callback_Code(void * pp,unsigned coderIndex,const Byte * src,size_t srcSize,int srcFinished,UInt64 * inCodePos,UInt64 * outCodePos,int * stop)1928 static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex,
1929 const Byte *src, size_t srcSize, int srcFinished,
1930 // int finished, int blockFinished,
1931 UInt64 *inCodePos, UInt64 *outCodePos, int *stop)
1932 {
1933 CXzDecMt *me = (CXzDecMt *)pp;
1934 CXzDecMtThread *coder = &me->coders[coderIndex];
1935
1936 *inCodePos = coder->inCodeSize;
1937 *outCodePos = coder->outCodeSize;
1938 *stop = True;
1939
1940 if (srcSize > coder->inPreSize - coder->inCodeSize)
1941 return SZ_ERROR_FAIL;
1942
1943 if (coder->inCodeSize < coder->inPreHeaderSize)
1944 {
1945 size_t step = coder->inPreHeaderSize - coder->inCodeSize;
1946 if (step > srcSize)
1947 step = srcSize;
1948 src += step;
1949 srcSize -= step;
1950 coder->inCodeSize += step;
1951 *inCodePos = coder->inCodeSize;
1952 if (coder->inCodeSize < coder->inPreHeaderSize)
1953 {
1954 *stop = False;
1955 return SZ_OK;
1956 }
1957 }
1958
1959 if (!coder->dec.headerParsedOk)
1960 return SZ_OK;
1961 if (!coder->outBuf)
1962 return SZ_OK;
1963
1964 if (coder->codeRes == SZ_OK)
1965 {
1966 ECoderStatus status;
1967 SRes res;
1968 size_t srcProcessed = srcSize;
1969 size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten;
1970
1971 // PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur));
1972
1973 res = XzUnpacker_Code(&coder->dec,
1974 NULL, &outSizeCur,
1975 src, &srcProcessed, srcFinished,
1976 // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY,
1977 CODER_FINISH_END,
1978 &status);
1979
1980 // PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur));
1981
1982 coder->codeRes = res;
1983 coder->status = status;
1984 coder->inCodeSize += srcProcessed;
1985 coder->outCodeSize = coder->dec.outDataWritten;
1986 *inCodePos = coder->inCodeSize;
1987 *outCodePos = coder->outCodeSize;
1988
1989 if (res == SZ_OK)
1990 {
1991 if (srcProcessed == srcSize)
1992 *stop = False;
1993 return SZ_OK;
1994 }
1995 }
1996
1997 if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM)
1998 {
1999 *inCodePos = coder->inPreSize;
2000 *outCodePos = coder->outPreSize;
2001 return SZ_OK;
2002 }
2003 return coder->codeRes;
2004 }
2005
2006
2007 #define XZDECMT_STREAM_WRITE_STEP (1 << 24)
2008
XzDecMt_Callback_Write(void * pp,unsigned coderIndex,BoolInt needWriteToStream,const Byte * src,size_t srcSize,BoolInt isCross,BoolInt * needContinue,BoolInt * canRecode)2009 static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex,
2010 BoolInt needWriteToStream,
2011 const Byte *src, size_t srcSize, BoolInt isCross,
2012 // int srcFinished,
2013 BoolInt *needContinue,
2014 BoolInt *canRecode)
2015 {
2016 CXzDecMt *me = (CXzDecMt *)pp;
2017 const CXzDecMtThread *coder = &me->coders[coderIndex];
2018
2019 // PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize));
2020
2021 *needContinue = False;
2022 *canRecode = True;
2023
2024 if (!needWriteToStream)
2025 return SZ_OK;
2026
2027 if (!coder->dec.headerParsedOk || !coder->outBuf)
2028 {
2029 if (me->finishedDecoderIndex < 0)
2030 me->finishedDecoderIndex = (int)coderIndex;
2031 return SZ_OK;
2032 }
2033
2034 if (me->finishedDecoderIndex >= 0)
2035 return SZ_OK;
2036
2037 me->mtc.inProcessed += coder->inCodeSize;
2038
2039 *canRecode = False;
2040
2041 {
2042 SRes res;
2043 size_t size = coder->outCodeSize;
2044 Byte *data = coder->outBuf;
2045
2046 // we use in me->dec: sha, numBlocks, indexSize
2047
2048 if (!me->isBlockHeaderState_Write)
2049 {
2050 XzUnpacker_PrepareToRandomBlockDecoding(&me->dec);
2051 me->dec.decodeOnlyOneBlock = False;
2052 me->dec.numStartedStreams = coder->dec.numStartedStreams;
2053 me->dec.streamFlags = coder->streamFlags;
2054
2055 me->isBlockHeaderState_Write = True;
2056 }
2057
2058 me->dec.numTotalBlocks = coder->dec.numTotalBlocks;
2059 XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize);
2060
2061 if (coder->outPreSize != size)
2062 {
2063 if (me->props.ignoreErrors)
2064 {
2065 memset(data + size, 0, coder->outPreSize - size);
2066 size = coder->outPreSize;
2067 }
2068 // me->numBadBlocks++;
2069 if (me->mainErrorCode == SZ_OK)
2070 {
2071 if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT)
2072 me->mainErrorCode = SZ_ERROR_INPUT_EOF;
2073 else
2074 me->mainErrorCode = SZ_ERROR_DATA;
2075 }
2076 }
2077
2078 if (me->writeRes != SZ_OK)
2079 return me->writeRes;
2080
2081 res = SZ_OK;
2082 {
2083 if (me->outSize_Defined)
2084 {
2085 const UInt64 rem = me->outSize - me->outProcessed;
2086 if (size > rem)
2087 size = (SizeT)rem;
2088 }
2089
2090 for (;;)
2091 {
2092 size_t cur = size;
2093 size_t written;
2094 if (cur > XZDECMT_STREAM_WRITE_STEP)
2095 cur = XZDECMT_STREAM_WRITE_STEP;
2096
2097 written = ISeqOutStream_Write(me->outStream, data, cur);
2098
2099 // PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written));
2100
2101 me->outProcessed += written;
2102 if (written != cur)
2103 {
2104 me->writeRes = SZ_ERROR_WRITE;
2105 res = me->writeRes;
2106 break;
2107 }
2108 data += cur;
2109 size -= cur;
2110 // PRF_STR_INT("Written size =", size)
2111 if (size == 0)
2112 break;
2113 res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0);
2114 if (res != SZ_OK)
2115 break;
2116 }
2117 }
2118
2119 if (coder->codeRes != SZ_OK)
2120 if (!me->props.ignoreErrors)
2121 {
2122 me->finishedDecoderIndex = (int)coderIndex;
2123 return res;
2124 }
2125
2126 RINOK(res)
2127
2128 if (coder->inPreSize != coder->inCodeSize
2129 || coder->blockPackTotal != coder->inCodeSize)
2130 {
2131 me->finishedDecoderIndex = (int)coderIndex;
2132 return SZ_OK;
2133 }
2134
2135 if (coder->parseState != MTDEC_PARSE_END)
2136 {
2137 *needContinue = True;
2138 return SZ_OK;
2139 }
2140 }
2141
2142 // (coder->state == MTDEC_PARSE_END) means that there are no other working threads
2143 // so we can use mtc variables without lock
2144
2145 PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed)
2146
2147 me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2148 {
2149 CXzUnpacker *dec = &me->dec;
2150
2151 PRF_STR_INT("PostSingle", srcSize)
2152
2153 {
2154 size_t srcProcessed = srcSize;
2155 ECoderStatus status;
2156 size_t outSizeCur = 0;
2157 SRes res;
2158
2159 // dec->decodeOnlyOneBlock = False;
2160 dec->decodeToStreamSignature = True;
2161
2162 me->mainDecoderWasCalled = True;
2163
2164 if (coder->parsing_Truncated)
2165 {
2166 me->parsing_Truncated = True;
2167 return SZ_OK;
2168 }
2169
2170 /*
2171 We have processed all xz-blocks of stream,
2172 And xz unpacker is at XZ_STATE_BLOCK_HEADER state, where
2173 (src) is a pointer to xz-Index structure.
2174 We finish reading of current xz-Stream, including Zero padding after xz-Stream.
2175 We exit, if we reach extra byte (first byte of new-Stream or another data).
2176 But we don't update input stream pointer for that new extra byte.
2177 If extra byte is not correct first byte of xz-signature,
2178 we have SZ_ERROR_NO_ARCHIVE error here.
2179 */
2180
2181 res = XzUnpacker_Code(dec,
2182 NULL, &outSizeCur,
2183 src, &srcProcessed,
2184 me->mtc.readWasFinished, // srcFinished
2185 CODER_FINISH_END, // CODER_FINISH_ANY,
2186 &status);
2187
2188 // res = SZ_ERROR_ARCHIVE; // for failure test
2189
2190 me->status = status;
2191 me->codeRes = res;
2192
2193 if (isCross)
2194 me->mtc.crossStart += srcProcessed;
2195
2196 me->mtc.inProcessed += srcProcessed;
2197 me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2198
2199 srcSize -= srcProcessed;
2200 src += srcProcessed;
2201
2202 if (res != SZ_OK)
2203 {
2204 return SZ_OK;
2205 // return res;
2206 }
2207
2208 if (dec->state == XZ_STATE_STREAM_HEADER)
2209 {
2210 *needContinue = True;
2211 me->isBlockHeaderState_Parse = False;
2212 me->isBlockHeaderState_Write = False;
2213
2214 if (!isCross)
2215 {
2216 Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2217 if (!crossBuf)
2218 return SZ_ERROR_MEM;
2219 if (srcSize != 0)
2220 memcpy(crossBuf, src, srcSize);
2221 me->mtc.crossStart = 0;
2222 me->mtc.crossEnd = srcSize;
2223 }
2224
2225 PRF_STR_INT("XZ_STATE_STREAM_HEADER crossEnd = ", (unsigned)me->mtc.crossEnd)
2226
2227 return SZ_OK;
2228 }
2229
2230 if (status != CODER_STATUS_NEEDS_MORE_INPUT || srcSize != 0)
2231 {
2232 return SZ_ERROR_FAIL;
2233 }
2234
2235 if (me->mtc.readWasFinished)
2236 {
2237 return SZ_OK;
2238 }
2239 }
2240
2241 {
2242 size_t inPos;
2243 size_t inLim;
2244 // const Byte *inData;
2245 UInt64 inProgressPrev = me->mtc.inProcessed;
2246
2247 // XzDecMt_Prepare_InBuf_ST(p);
2248 Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2249 if (!crossBuf)
2250 return SZ_ERROR_MEM;
2251
2252 inPos = 0;
2253 inLim = 0;
2254
2255 // inData = crossBuf;
2256
2257 for (;;)
2258 {
2259 SizeT inProcessed;
2260 SizeT outProcessed;
2261 ECoderStatus status;
2262 SRes res;
2263
2264 if (inPos == inLim)
2265 {
2266 if (!me->mtc.readWasFinished)
2267 {
2268 inPos = 0;
2269 inLim = me->mtc.inBufSize;
2270 me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)crossBuf, &inLim);
2271 me->mtc.readProcessed += inLim;
2272 if (inLim == 0 || me->mtc.readRes != SZ_OK)
2273 me->mtc.readWasFinished = True;
2274 }
2275 }
2276
2277 inProcessed = inLim - inPos;
2278 outProcessed = 0;
2279
2280 res = XzUnpacker_Code(dec,
2281 NULL, &outProcessed,
2282 crossBuf + inPos, &inProcessed,
2283 (inProcessed == 0), // srcFinished
2284 CODER_FINISH_END, &status);
2285
2286 me->codeRes = res;
2287 me->status = status;
2288 inPos += inProcessed;
2289 me->mtc.inProcessed += inProcessed;
2290 me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2291
2292 if (res != SZ_OK)
2293 {
2294 return SZ_OK;
2295 // return res;
2296 }
2297
2298 if (dec->state == XZ_STATE_STREAM_HEADER)
2299 {
2300 *needContinue = True;
2301 me->mtc.crossStart = inPos;
2302 me->mtc.crossEnd = inLim;
2303 me->isBlockHeaderState_Parse = False;
2304 me->isBlockHeaderState_Write = False;
2305 return SZ_OK;
2306 }
2307
2308 if (status != CODER_STATUS_NEEDS_MORE_INPUT)
2309 return SZ_ERROR_FAIL;
2310
2311 if (me->mtc.progress)
2312 {
2313 UInt64 inDelta = me->mtc.inProcessed - inProgressPrev;
2314 if (inDelta >= (1 << 22))
2315 {
2316 RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress))
2317 inProgressPrev = me->mtc.inProcessed;
2318 }
2319 }
2320 if (me->mtc.readWasFinished)
2321 return SZ_OK;
2322 }
2323 }
2324 }
2325 }
2326
2327
2328 #endif
2329
2330
2331
XzStatInfo_Clear(CXzStatInfo * p)2332 void XzStatInfo_Clear(CXzStatInfo *p)
2333 {
2334 p->InSize = 0;
2335 p->OutSize = 0;
2336
2337 p->NumStreams = 0;
2338 p->NumBlocks = 0;
2339
2340 p->UnpackSize_Defined = False;
2341
2342 p->NumStreams_Defined = False;
2343 p->NumBlocks_Defined = False;
2344
2345 p->DataAfterEnd = False;
2346 p->DecodingTruncated = False;
2347
2348 p->DecodeRes = SZ_OK;
2349 p->ReadRes = SZ_OK;
2350 p->ProgressRes = SZ_OK;
2351
2352 p->CombinedRes = SZ_OK;
2353 p->CombinedRes_Type = SZ_OK;
2354 }
2355
2356
2357
2358 /*
2359 XzDecMt_Decode_ST() can return SZ_OK or the following errors
2360 - SZ_ERROR_MEM for memory allocation error
2361 - error from XzUnpacker_Code() function
2362 - SZ_ERROR_WRITE for ISeqOutStream::Write(). stat->CombinedRes_Type = SZ_ERROR_WRITE in that case
2363 - ICompressProgress::Progress() error, stat->CombinedRes_Type = SZ_ERROR_PROGRESS.
2364 But XzDecMt_Decode_ST() doesn't return ISeqInStream::Read() errors.
2365 ISeqInStream::Read() result is set to p->readRes.
2366 also it can set stat->CombinedRes_Type to SZ_ERROR_WRITE or SZ_ERROR_PROGRESS.
2367 */
2368
XzDecMt_Decode_ST(CXzDecMt * p,BoolInt tMode,CXzStatInfo * stat)2369 static SRes XzDecMt_Decode_ST(CXzDecMt *p
2370 #ifndef Z7_ST
2371 , BoolInt tMode
2372 #endif
2373 , CXzStatInfo *stat)
2374 {
2375 size_t outPos;
2376 size_t inPos, inLim;
2377 const Byte *inData;
2378 UInt64 inPrev, outPrev;
2379
2380 CXzUnpacker *dec;
2381
2382 #ifndef Z7_ST
2383 if (tMode)
2384 {
2385 XzDecMt_FreeOutBufs(p);
2386 tMode = (BoolInt)MtDec_PrepareRead(&p->mtc);
2387 }
2388 #endif
2389
2390 if (!p->outBuf || p->outBufSize != p->props.outStep_ST)
2391 {
2392 ISzAlloc_Free(p->allocMid, p->outBuf);
2393 p->outBufSize = 0;
2394 p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST);
2395 if (!p->outBuf)
2396 return SZ_ERROR_MEM;
2397 p->outBufSize = p->props.outStep_ST;
2398 }
2399
2400 if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
2401 {
2402 ISzAlloc_Free(p->allocMid, p->inBuf);
2403 p->inBufSize = 0;
2404 p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
2405 if (!p->inBuf)
2406 return SZ_ERROR_MEM;
2407 p->inBufSize = p->props.inBufSize_ST;
2408 }
2409
2410 dec = &p->dec;
2411 dec->decodeToStreamSignature = False;
2412 // dec->decodeOnlyOneBlock = False;
2413
2414 XzUnpacker_SetOutBuf(dec, NULL, 0);
2415
2416 inPrev = p->inProcessed;
2417 outPrev = p->outProcessed;
2418
2419 inPos = 0;
2420 inLim = 0;
2421 inData = NULL;
2422 outPos = 0;
2423
2424 for (;;)
2425 {
2426 SizeT outSize;
2427 BoolInt finished;
2428 ECoderFinishMode finishMode;
2429 SizeT inProcessed;
2430 ECoderStatus status;
2431 SRes res;
2432
2433 SizeT outProcessed;
2434
2435
2436
2437 if (inPos == inLim)
2438 {
2439 #ifndef Z7_ST
2440 if (tMode)
2441 {
2442 inData = MtDec_Read(&p->mtc, &inLim);
2443 inPos = 0;
2444 if (inData)
2445 continue;
2446 tMode = False;
2447 inLim = 0;
2448 }
2449 #endif
2450
2451 if (!p->readWasFinished)
2452 {
2453 inPos = 0;
2454 inLim = p->inBufSize;
2455 inData = p->inBuf;
2456 p->readRes = ISeqInStream_Read(p->inStream, (void *)p->inBuf, &inLim);
2457 p->readProcessed += inLim;
2458 if (inLim == 0 || p->readRes != SZ_OK)
2459 p->readWasFinished = True;
2460 }
2461 }
2462
2463 outSize = p->props.outStep_ST - outPos;
2464
2465 finishMode = CODER_FINISH_ANY;
2466 if (p->outSize_Defined)
2467 {
2468 const UInt64 rem = p->outSize - p->outProcessed;
2469 if (outSize >= rem)
2470 {
2471 outSize = (SizeT)rem;
2472 if (p->finishMode)
2473 finishMode = CODER_FINISH_END;
2474 }
2475 }
2476
2477 inProcessed = inLim - inPos;
2478 outProcessed = outSize;
2479
2480 res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed,
2481 inData + inPos, &inProcessed,
2482 (inPos == inLim), // srcFinished
2483 finishMode, &status);
2484
2485 p->codeRes = res;
2486 p->status = status;
2487
2488 inPos += inProcessed;
2489 outPos += outProcessed;
2490 p->inProcessed += inProcessed;
2491 p->outProcessed += outProcessed;
2492
2493 finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK);
2494
2495 if (finished || outProcessed >= outSize)
2496 if (outPos != 0)
2497 {
2498 const size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos);
2499 // p->outProcessed += written; // 21.01: BUG fixed
2500 if (written != outPos)
2501 {
2502 stat->CombinedRes_Type = SZ_ERROR_WRITE;
2503 return SZ_ERROR_WRITE;
2504 }
2505 outPos = 0;
2506 }
2507
2508 if (p->progress && res == SZ_OK)
2509 {
2510 if (p->inProcessed - inPrev >= (1 << 22) ||
2511 p->outProcessed - outPrev >= (1 << 22))
2512 {
2513 res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed);
2514 if (res != SZ_OK)
2515 {
2516 stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2517 stat->ProgressRes = res;
2518 return res;
2519 }
2520 inPrev = p->inProcessed;
2521 outPrev = p->outProcessed;
2522 }
2523 }
2524
2525 if (finished)
2526 {
2527 // p->codeRes is preliminary error from XzUnpacker_Code.
2528 // and it can be corrected later as final result
2529 // so we return SZ_OK here instead of (res);
2530 return SZ_OK;
2531 // return res;
2532 }
2533 }
2534 }
2535
2536
2537
2538 /*
2539 XzStatInfo_SetStat() transforms
2540 CXzUnpacker return code and status to combined CXzStatInfo results.
2541 it can convert SZ_OK to SZ_ERROR_INPUT_EOF
2542 it can convert SZ_ERROR_NO_ARCHIVE to SZ_OK and (DataAfterEnd = 1)
2543 */
2544
XzStatInfo_SetStat(const CXzUnpacker * dec,int finishMode,UInt64 inProcessed,SRes res,ECoderStatus status,BoolInt decodingTruncated,CXzStatInfo * stat)2545 static void XzStatInfo_SetStat(const CXzUnpacker *dec,
2546 int finishMode,
2547 // UInt64 readProcessed,
2548 UInt64 inProcessed,
2549 SRes res, // it's result from CXzUnpacker unpacker
2550 ECoderStatus status,
2551 BoolInt decodingTruncated,
2552 CXzStatInfo *stat)
2553 {
2554 UInt64 extraSize;
2555
2556 stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0);
2557 stat->InSize = inProcessed;
2558 stat->NumStreams = dec->numStartedStreams;
2559 stat->NumBlocks = dec->numTotalBlocks;
2560
2561 stat->UnpackSize_Defined = True;
2562 stat->NumStreams_Defined = True;
2563 stat->NumBlocks_Defined = True;
2564
2565 extraSize = XzUnpacker_GetExtraSize(dec);
2566
2567 if (res == SZ_OK)
2568 {
2569 if (status == CODER_STATUS_NEEDS_MORE_INPUT)
2570 {
2571 // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams
2572 // any extra data is part of correct data
2573 extraSize = 0;
2574 // if xz stream was not finished, then we need more data
2575 if (!XzUnpacker_IsStreamWasFinished(dec))
2576 res = SZ_ERROR_INPUT_EOF;
2577 }
2578 else
2579 {
2580 // CODER_STATUS_FINISHED_WITH_MARK is not possible for multi stream xz decoding
2581 // so he we have (status == CODER_STATUS_NOT_FINISHED)
2582 // if (status != CODER_STATUS_FINISHED_WITH_MARK)
2583 if (!decodingTruncated || finishMode)
2584 res = SZ_ERROR_DATA;
2585 }
2586 }
2587 else if (res == SZ_ERROR_NO_ARCHIVE)
2588 {
2589 /*
2590 SZ_ERROR_NO_ARCHIVE is possible for 2 states:
2591 XZ_STATE_STREAM_HEADER - if bad signature or bad CRC
2592 XZ_STATE_STREAM_PADDING - if non-zero padding data
2593 extraSize and inProcessed don't include "bad" byte
2594 */
2595 // if (inProcessed == extraSize), there was no any good xz stream header, and we keep error
2596 if (inProcessed != extraSize) // if there were good xz streams before error
2597 {
2598 // if (extraSize != 0 || readProcessed != inProcessed)
2599 {
2600 // he we suppose that all xz streams were finsihed OK, and we have
2601 // some extra data after all streams
2602 stat->DataAfterEnd = True;
2603 res = SZ_OK;
2604 }
2605 }
2606 }
2607
2608 if (stat->DecodeRes == SZ_OK)
2609 stat->DecodeRes = res;
2610
2611 stat->InSize -= extraSize;
2612 }
2613
2614
2615
XzDecMt_Decode(CXzDecMtHandle p,const CXzDecMtProps * props,const UInt64 * outDataSize,int finishMode,ISeqOutStreamPtr outStream,ISeqInStreamPtr inStream,CXzStatInfo * stat,int * isMT,ICompressProgressPtr progress)2616 SRes XzDecMt_Decode(CXzDecMtHandle p,
2617 const CXzDecMtProps *props,
2618 const UInt64 *outDataSize, int finishMode,
2619 ISeqOutStreamPtr outStream,
2620 // Byte *outBuf, size_t *outBufSize,
2621 ISeqInStreamPtr inStream,
2622 // const Byte *inData, size_t inDataSize,
2623 CXzStatInfo *stat,
2624 int *isMT,
2625 ICompressProgressPtr progress)
2626 {
2627 // GET_CXzDecMt_p
2628 #ifndef Z7_ST
2629 BoolInt tMode;
2630 #endif
2631
2632 XzStatInfo_Clear(stat);
2633
2634 p->props = *props;
2635
2636 p->inStream = inStream;
2637 p->outStream = outStream;
2638 p->progress = progress;
2639 // p->stat = stat;
2640
2641 p->outSize = 0;
2642 p->outSize_Defined = False;
2643 if (outDataSize)
2644 {
2645 p->outSize_Defined = True;
2646 p->outSize = *outDataSize;
2647 }
2648
2649 p->finishMode = (BoolInt)finishMode;
2650
2651 // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test
2652
2653 p->writeRes = SZ_OK;
2654 p->outProcessed = 0;
2655 p->inProcessed = 0;
2656 p->readProcessed = 0;
2657 p->readWasFinished = False;
2658 p->readRes = SZ_OK;
2659
2660 p->codeRes = SZ_OK;
2661 p->status = CODER_STATUS_NOT_SPECIFIED;
2662
2663 XzUnpacker_Init(&p->dec);
2664
2665 *isMT = False;
2666
2667 /*
2668 p->outBuf = NULL;
2669 p->outBufSize = 0;
2670 if (!outStream)
2671 {
2672 p->outBuf = outBuf;
2673 p->outBufSize = *outBufSize;
2674 *outBufSize = 0;
2675 }
2676 */
2677
2678
2679 #ifndef Z7_ST
2680
2681 p->isBlockHeaderState_Parse = False;
2682 p->isBlockHeaderState_Write = False;
2683 // p->numBadBlocks = 0;
2684 p->mainErrorCode = SZ_OK;
2685 p->mainDecoderWasCalled = False;
2686
2687 tMode = False;
2688
2689 if (p->props.numThreads > 1)
2690 {
2691 IMtDecCallback2 vt;
2692 BoolInt needContinue;
2693 SRes res;
2694 // we just free ST buffers here
2695 // but we still keep state variables, that was set in XzUnpacker_Init()
2696 XzDecMt_FreeSt(p);
2697
2698 p->outProcessed_Parse = 0;
2699 p->parsing_Truncated = False;
2700
2701 p->numStreams = 0;
2702 p->numTotalBlocks = 0;
2703 p->numBlocks = 0;
2704 p->finishedDecoderIndex = -1;
2705
2706 if (!p->mtc_WasConstructed)
2707 {
2708 p->mtc_WasConstructed = True;
2709 MtDec_Construct(&p->mtc);
2710 }
2711
2712 p->mtc.mtCallback = &vt;
2713 p->mtc.mtCallbackObject = p;
2714
2715 p->mtc.progress = progress;
2716 p->mtc.inStream = inStream;
2717 p->mtc.alloc = &p->alignOffsetAlloc.vt;
2718 // p->mtc.inData = inData;
2719 // p->mtc.inDataSize = inDataSize;
2720 p->mtc.inBufSize = p->props.inBufSize_MT;
2721 // p->mtc.inBlockMax = p->props.inBlockMax;
2722 p->mtc.numThreadsMax = p->props.numThreads;
2723
2724 *isMT = True;
2725
2726 vt.Parse = XzDecMt_Callback_Parse;
2727 vt.PreCode = XzDecMt_Callback_PreCode;
2728 vt.Code = XzDecMt_Callback_Code;
2729 vt.Write = XzDecMt_Callback_Write;
2730
2731
2732 res = MtDec_Code(&p->mtc);
2733
2734
2735 stat->InSize = p->mtc.inProcessed;
2736
2737 p->inProcessed = p->mtc.inProcessed;
2738 p->readRes = p->mtc.readRes;
2739 p->readWasFinished = p->mtc.readWasFinished;
2740 p->readProcessed = p->mtc.readProcessed;
2741
2742 tMode = True;
2743 needContinue = False;
2744
2745 if (res == SZ_OK)
2746 {
2747 if (p->mtc.mtProgress.res != SZ_OK)
2748 {
2749 res = p->mtc.mtProgress.res;
2750 stat->ProgressRes = res;
2751 stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2752 }
2753 else
2754 needContinue = p->mtc.needContinue;
2755 }
2756
2757 if (!needContinue)
2758 {
2759 {
2760 SRes codeRes;
2761 BoolInt truncated = False;
2762 ECoderStatus status;
2763 const CXzUnpacker *dec;
2764
2765 stat->OutSize = p->outProcessed;
2766
2767 if (p->finishedDecoderIndex >= 0)
2768 {
2769 const CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex];
2770 codeRes = coder->codeRes;
2771 dec = &coder->dec;
2772 status = coder->status;
2773 }
2774 else if (p->mainDecoderWasCalled)
2775 {
2776 codeRes = p->codeRes;
2777 dec = &p->dec;
2778 status = p->status;
2779 truncated = p->parsing_Truncated;
2780 }
2781 else
2782 return SZ_ERROR_FAIL;
2783
2784 if (p->mainErrorCode != SZ_OK)
2785 stat->DecodeRes = p->mainErrorCode;
2786
2787 XzStatInfo_SetStat(dec, p->finishMode,
2788 // p->mtc.readProcessed,
2789 p->mtc.inProcessed,
2790 codeRes, status,
2791 truncated,
2792 stat);
2793 }
2794
2795 if (res == SZ_OK)
2796 {
2797 stat->ReadRes = p->mtc.readRes;
2798
2799 if (p->writeRes != SZ_OK)
2800 {
2801 res = p->writeRes;
2802 stat->CombinedRes_Type = SZ_ERROR_WRITE;
2803 }
2804 else if (p->mtc.readRes != SZ_OK
2805 // && p->mtc.inProcessed == p->mtc.readProcessed
2806 && stat->DecodeRes == SZ_ERROR_INPUT_EOF)
2807 {
2808 res = p->mtc.readRes;
2809 stat->CombinedRes_Type = SZ_ERROR_READ;
2810 }
2811 else if (stat->DecodeRes != SZ_OK)
2812 res = stat->DecodeRes;
2813 }
2814
2815 stat->CombinedRes = res;
2816 if (stat->CombinedRes_Type == SZ_OK)
2817 stat->CombinedRes_Type = res;
2818 return res;
2819 }
2820
2821 PRF_STR("----- decoding ST -----")
2822 }
2823
2824 #endif
2825
2826
2827 *isMT = False;
2828
2829 {
2830 SRes res = XzDecMt_Decode_ST(p
2831 #ifndef Z7_ST
2832 , tMode
2833 #endif
2834 , stat
2835 );
2836
2837 #ifndef Z7_ST
2838 // we must set error code from MT decoding at first
2839 if (p->mainErrorCode != SZ_OK)
2840 stat->DecodeRes = p->mainErrorCode;
2841 #endif
2842
2843 XzStatInfo_SetStat(&p->dec,
2844 p->finishMode,
2845 // p->readProcessed,
2846 p->inProcessed,
2847 p->codeRes, p->status,
2848 False, // truncated
2849 stat);
2850
2851 stat->ReadRes = p->readRes;
2852
2853 if (res == SZ_OK)
2854 {
2855 if (p->readRes != SZ_OK
2856 // && p->inProcessed == p->readProcessed
2857 && stat->DecodeRes == SZ_ERROR_INPUT_EOF)
2858 {
2859 // we set read error as combined error, only if that error was the reason
2860 // of decoding problem
2861 res = p->readRes;
2862 stat->CombinedRes_Type = SZ_ERROR_READ;
2863 }
2864 else if (stat->DecodeRes != SZ_OK)
2865 res = stat->DecodeRes;
2866 }
2867
2868 stat->CombinedRes = res;
2869 if (stat->CombinedRes_Type == SZ_OK)
2870 stat->CombinedRes_Type = res;
2871 return res;
2872 }
2873 }
2874
2875 #undef PRF
2876 #undef PRF_STR
2877 #undef PRF_STR_INT_2
2878