123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346 |
- /* 7zDecode.c */
- #include <memory.h>
- /* BEGIN PHYSFS CHANGE */
- #include <string.h>
- /* END PHYSFS CHANGE */
- #include "7zDecode.h"
- #ifdef _SZ_ONE_DIRECTORY
- #include "LzmaDecode.h"
- #else
- #include "../../Compress/Lzma/LzmaDecode.h"
- #include "../../Compress/Branch/BranchX86.h"
- #include "../../Compress/Branch/BranchX86_2.h"
- #endif
- #define k_Copy 0
- #define k_LZMA 0x30101
- #define k_BCJ 0x03030103
- #define k_BCJ2 0x0303011B
- #ifdef _LZMA_IN_CB
- typedef struct _CLzmaInCallbackImp
- {
- ILzmaInCallback InCallback;
- ISzInStream *InStream;
- CFileSize Size;
- } CLzmaInCallbackImp;
- int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size)
- {
- CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object;
- size_t processedSize;
- SZ_RESULT res;
- size_t curSize = (1 << 20);
- if (curSize > cb->Size)
- curSize = (size_t)cb->Size;
- *size = 0;
- res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, curSize, &processedSize);
- *size = (SizeT)processedSize;
- if (processedSize > curSize)
- return (int)SZE_FAIL;
- cb->Size -= processedSize;
- if (res == SZ_OK)
- return 0;
- return (int)res;
- }
- #endif
- SZ_RESULT SzDecodeLzma(CCoderInfo *coder, CFileSize inSize,
- #ifdef _LZMA_IN_CB
- ISzInStream *inStream,
- #else
- const Byte *inBuffer,
- #endif
- Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
- {
- #ifdef _LZMA_IN_CB
- CLzmaInCallbackImp lzmaCallback;
- #else
- SizeT inProcessed;
- #endif
-
- CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
- int result;
- SizeT outSizeProcessedLoc;
-
- #ifdef _LZMA_IN_CB
- lzmaCallback.Size = inSize;
- lzmaCallback.InStream = inStream;
- lzmaCallback.InCallback.Read = LzmaReadImp;
- #endif
-
- if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items,
- (unsigned)coder->Properties.Capacity) != LZMA_RESULT_OK)
- return SZE_FAIL;
-
- state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
- if (state.Probs == 0)
- return SZE_OUTOFMEMORY;
-
- #ifdef _LZMA_OUT_READ
- if (state.Properties.DictionarySize == 0)
- state.Dictionary = 0;
- else
- {
- state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize);
- if (state.Dictionary == 0)
- {
- allocMain->Free(state.Probs);
- return SZE_OUTOFMEMORY;
- }
- }
- LzmaDecoderInit(&state);
- #endif
-
- result = LzmaDecode(&state,
- #ifdef _LZMA_IN_CB
- &lzmaCallback.InCallback,
- #else
- inBuffer, (SizeT)inSize, &inProcessed,
- #endif
- outBuffer, (SizeT)outSize, &outSizeProcessedLoc);
- allocMain->Free(state.Probs);
- #ifdef _LZMA_OUT_READ
- allocMain->Free(state.Dictionary);
- #endif
- if (result == LZMA_RESULT_DATA_ERROR)
- return SZE_DATA_ERROR;
- if (result != LZMA_RESULT_OK)
- return SZE_FAIL;
- return (outSizeProcessedLoc == outSize) ? SZ_OK : SZE_DATA_ERROR;
- }
- #ifdef _LZMA_IN_CB
- SZ_RESULT SzDecodeCopy(CFileSize inSize, ISzInStream *inStream, Byte *outBuffer)
- {
- while (inSize > 0)
- {
- void *inBuffer;
- size_t processedSize, curSize = (1 << 18);
- if (curSize > inSize)
- curSize = (size_t)(inSize);
- RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, curSize, &processedSize));
- if (processedSize == 0)
- return SZE_DATA_ERROR;
- if (processedSize > curSize)
- return SZE_FAIL;
- memcpy(outBuffer, inBuffer, processedSize);
- outBuffer += processedSize;
- inSize -= processedSize;
- }
- return SZ_OK;
- }
- #endif
- #define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA)
- #define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1)
- #define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1)
- #define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1)
- SZ_RESULT CheckSupportedFolder(const CFolder *f)
- {
- if (f->NumCoders < 1 || f->NumCoders > 4)
- return SZE_NOTIMPL;
- if (IS_UNSUPPORTED_CODER(f->Coders[0]))
- return SZE_NOTIMPL;
- if (f->NumCoders == 1)
- {
- if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
- return SZE_NOTIMPL;
- return SZ_OK;
- }
- if (f->NumCoders == 2)
- {
- if (IS_NO_BCJ(f->Coders[1]) ||
- f->NumPackStreams != 1 || f->PackStreams[0] != 0 ||
- f->NumBindPairs != 1 ||
- f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0)
- return SZE_NOTIMPL;
- return SZ_OK;
- }
- if (f->NumCoders == 4)
- {
- if (IS_UNSUPPORTED_CODER(f->Coders[1]) ||
- IS_UNSUPPORTED_CODER(f->Coders[2]) ||
- IS_NO_BCJ2(f->Coders[3]))
- return SZE_NOTIMPL;
- if (f->NumPackStreams != 4 ||
- f->PackStreams[0] != 2 ||
- f->PackStreams[1] != 6 ||
- f->PackStreams[2] != 1 ||
- f->PackStreams[3] != 0 ||
- f->NumBindPairs != 3 ||
- f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
- f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
- f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
- return SZE_NOTIMPL;
- return SZ_OK;
- }
- return SZE_NOTIMPL;
- }
- CFileSize GetSum(const CFileSize *values, UInt32 index)
- {
- CFileSize sum = 0;
- UInt32 i;
- for (i = 0; i < index; i++)
- sum += values[i];
- return sum;
- }
- SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder,
- #ifdef _LZMA_IN_CB
- ISzInStream *inStream, CFileSize startPos,
- #else
- const Byte *inBuffer,
- #endif
- Byte *outBuffer, size_t outSize, ISzAlloc *allocMain,
- Byte *tempBuf[])
- {
- UInt32 ci;
- size_t tempSizes[3] = { 0, 0, 0};
- size_t tempSize3 = 0;
- Byte *tempBuf3 = 0;
- RINOK(CheckSupportedFolder(folder));
- for (ci = 0; ci < folder->NumCoders; ci++)
- {
- CCoderInfo *coder = &folder->Coders[ci];
- if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA)
- {
- UInt32 si = 0;
- CFileSize offset;
- CFileSize inSize;
- Byte *outBufCur = outBuffer;
- size_t outSizeCur = outSize;
- if (folder->NumCoders == 4)
- {
- UInt32 indices[] = { 3, 2, 0 };
- CFileSize unpackSize = folder->UnPackSizes[ci];
- si = indices[ci];
- if (ci < 2)
- {
- Byte *temp;
- outSizeCur = (size_t)unpackSize;
- if (outSizeCur != unpackSize)
- return SZE_OUTOFMEMORY;
- temp = (Byte *)allocMain->Alloc(outSizeCur);
- if (temp == 0 && outSizeCur != 0)
- return SZE_OUTOFMEMORY;
- outBufCur = tempBuf[1 - ci] = temp;
- tempSizes[1 - ci] = outSizeCur;
- }
- else if (ci == 2)
- {
- if (unpackSize > outSize)
- return SZE_OUTOFMEMORY;
- tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
- tempSize3 = outSizeCur = (size_t)unpackSize;
- }
- else
- return SZE_NOTIMPL;
- }
- offset = GetSum(packSizes, si);
- inSize = packSizes[si];
- #ifdef _LZMA_IN_CB
- RINOK(inStream->Seek(inStream, startPos + offset));
- #endif
- if (coder->MethodID == k_Copy)
- {
- if (inSize != outSizeCur)
- return SZE_DATA_ERROR;
-
- #ifdef _LZMA_IN_CB
- RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
- #else
- memcpy(outBufCur, inBuffer + (size_t)offset, (size_t)inSize);
- #endif
- }
- else
- {
- SZ_RESULT res = SzDecodeLzma(coder, inSize,
- #ifdef _LZMA_IN_CB
- inStream,
- #else
- inBuffer + (size_t)offset,
- #endif
- outBufCur, outSizeCur, allocMain);
- RINOK(res)
- }
- }
- else if (coder->MethodID == k_BCJ)
- {
- UInt32 state;
- if (ci != 1)
- return SZE_NOTIMPL;
- x86_Convert_Init(state);
- x86_Convert(outBuffer, outSize, 0, &state, 0);
- }
- else if (coder->MethodID == k_BCJ2)
- {
- CFileSize offset = GetSum(packSizes, 1);
- CFileSize s3Size = packSizes[1];
- SZ_RESULT res;
- if (ci != 3)
- return SZE_NOTIMPL;
- #ifdef _LZMA_IN_CB
- RINOK(inStream->Seek(inStream, startPos + offset));
- tempSizes[2] = (size_t)s3Size;
- if (tempSizes[2] != s3Size)
- return SZE_OUTOFMEMORY;
- tempBuf[2] = (Byte *)allocMain->Alloc(tempSizes[2]);
- if (tempBuf[2] == 0 && tempSizes[2] != 0)
- return SZE_OUTOFMEMORY;
- res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
- RINOK(res)
- #endif
- res = x86_2_Decode(
- tempBuf3, tempSize3,
- tempBuf[0], tempSizes[0],
- tempBuf[1], tempSizes[1],
- #ifdef _LZMA_IN_CB
- tempBuf[2], tempSizes[2],
- #else
- inBuffer + (size_t)offset, (size_t)s3Size,
- #endif
- outBuffer, outSize);
- RINOK(res)
- }
- else
- return SZE_NOTIMPL;
- }
- return SZ_OK;
- }
- SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
- #ifdef _LZMA_IN_CB
- ISzInStream *inStream, CFileSize startPos,
- #else
- const Byte *inBuffer,
- #endif
- Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
- {
- Byte *tempBuf[3] = { 0, 0, 0};
- int i;
- SZ_RESULT res = SzDecode2(packSizes, folder,
- #ifdef _LZMA_IN_CB
- inStream, startPos,
- #else
- inBuffer,
- #endif
- outBuffer, outSize, allocMain, tempBuf);
- for (i = 0; i < 3; i++)
- allocMain->Free(tempBuf[i]);
- return res;
- }
|