OLD | NEW |
(Empty) | |
| 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 *a
lloc) |
| 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->b
uf, 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->en
codeMode); |
| 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, ISzAl
loc *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, IS
zAlloc *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 *sr
c, SizeT *srcLen, |
| 294 int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished) |
| 295 { |
| 296 ELzmaStatus status; |
| 297 /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZ
MA_FINISH_END; */ |
| 298 SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, f
inishMode, &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_MA
X - 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_FINIS
H_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, srcF
inishedCur, 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 *b
uf) |
| 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, fi
nishMode, 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 + X
zFlags_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, check
Size) != 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 } |
OLD | NEW |