diff options
Diffstat (limited to '3rdparty/lzma/CPP/7zip/Archive/XzHandler.cpp')
-rw-r--r-- | 3rdparty/lzma/CPP/7zip/Archive/XzHandler.cpp | 668 |
1 files changed, 416 insertions, 252 deletions
diff --git a/3rdparty/lzma/CPP/7zip/Archive/XzHandler.cpp b/3rdparty/lzma/CPP/7zip/Archive/XzHandler.cpp index 8383488b14f..11f4b44427c 100644 --- a/3rdparty/lzma/CPP/7zip/Archive/XzHandler.cpp +++ b/3rdparty/lzma/CPP/7zip/Archive/XzHandler.cpp @@ -7,8 +7,8 @@ #include "../../../C/XzEnc.h" #include "../../Common/ComTry.h" +#include "../../Common/Defs.h" #include "../../Common/IntToString.h" -#include "../../Common/StringConvert.h" #include "../ICoder.h" @@ -23,6 +23,8 @@ #include "Common/HandlerOut.h" +#include "XzHandler.h" + using namespace NWindows; namespace NCompress { @@ -32,16 +34,35 @@ HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzm }} -static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } -static void SzFree(void *, void *address) { MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; - namespace NArchive { namespace NXz { struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit; -static const wchar_t *k_LZMA2_Name = L"LZMA2"; +static const char *k_LZMA2_Name = "LZMA2"; + +void CStatInfo::Clear() +{ + InSize = 0; + OutSize = 0; + PhySize = 0; + + NumStreams = 0; + NumBlocks = 0; + + UnpackSize_Defined = false; + + NumStreams_Defined = false; + NumBlocks_Defined = false; + + IsArc = false; + UnexpectedEnd = false; + DataAfterEnd = false; + Unsupported = false; + HeadersError = false; + DataError = false; + CrcError = false; +} class CHandler: public IInArchive, @@ -53,19 +74,17 @@ class CHandler: #endif public CMyUnknownImp { - Int64 _startPosition; - UInt64 _packSize; - UInt64 _unpackSize; - UInt64 _numBlocks; - AString _methodsString; - bool _useSeq; - UInt64 _unpackSizeDefined; - UInt64 _packSizeDefined; + CStatInfo _stat; + + bool _isArc; + bool _needSeekToStart; + bool _phySize_Defined; CMyComPtr<IInStream> _stream; CMyComPtr<ISequentialInStream> _seqStream; UInt32 _filterId; + AString _methodsString; void Init() { @@ -73,7 +92,16 @@ class CHandler: CMultiMethodProps::Init(); } - HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback); + HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback); + + HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, + CDecoder &decoder, ICompressProgressInfo *progress) + { + RINOK(decoder.Decode(seqInStream, outStream, progress)); + _stat = decoder; + _phySize_Defined = true; + return S_OK; + } public: MY_QUERYINTERFACE_BEGIN2(IInArchive) @@ -90,7 +118,7 @@ public: #ifndef EXTRACT_ONLY INTERFACE_IOutArchive(;) - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); + STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); #endif CHandler(); @@ -101,60 +129,60 @@ CHandler::CHandler() Init(); } -static STATPROPSTG const kProps[] = +static const Byte kProps[] = { - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidMethod, VT_BSTR} + kpidSize, + kpidPackSize, + kpidMethod }; -static STATPROPSTG const kArcProps[] = +static const Byte kArcProps[] = { - { NULL, kpidMethod, VT_BSTR}, - { NULL, kpidNumBlocks, VT_UI4} + kpidMethod, + kpidNumStreams, + kpidNumBlocks }; IMP_IInArchive_Props IMP_IInArchive_ArcProps -static char GetHex(Byte value) +static inline char GetHex(unsigned value) { return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } -static inline void AddHexToString(AString &res, Byte value) +static inline void AddHexToString(AString &s, Byte value) { - res += GetHex((Byte)(value >> 4)); - res += GetHex((Byte)(value & 0xF)); + s += GetHex(value >> 4); + s += GetHex(value & 0xF); } -static AString ConvertUInt32ToString(UInt32 value) +static void AddUInt32ToString(AString &s, UInt32 value) { - char temp[32]; - ::ConvertUInt32ToString(value, temp); - return temp; + char temp[16]; + ConvertUInt32ToString(value, temp); + s += temp; } -static AString Lzma2PropToString(int prop) +static void Lzma2PropToString(AString &s, unsigned prop) { + char c = 0; + UInt32 size; if ((prop & 1) == 0) - return ConvertUInt32ToString(prop / 2 + 12); - AString res; - char c; - - UInt32 size = (2 | ((prop) & 1)) << ((prop) / 2 + 1); - - if (prop > 17) - { - res = ConvertUInt32ToString(size >> 10); - c = 'm'; - } + size = prop / 2 + 12; else { - res = ConvertUInt32ToString(size); c = 'k'; + size = (UInt32)(2 | (prop & 1)) << (prop / 2 + 1); + if (prop > 17) + { + size >>= 10; + c = 'm'; + } } - return res + c; + AddUInt32ToString(s, size); + if (c != 0) + s += c; } struct CMethodNamePair @@ -178,25 +206,29 @@ static const CMethodNamePair g_NamePairs[] = static AString GetMethodString(const CXzFilter &f) { - AString s; - - for (int i = 0; i < sizeof(g_NamePairs) / sizeof(g_NamePairs[i]); i++) + const char *p = NULL; + for (unsigned i = 0; i < ARRAY_SIZE(g_NamePairs); i++) if (g_NamePairs[i].Id == f.id) - s = g_NamePairs[i].Name; - if (s.IsEmpty()) + { + p = g_NamePairs[i].Name; + break; + } + char temp[32]; + if (!p) { - char temp[32]; ::ConvertUInt64ToString(f.id, temp); - s = temp; + p = temp; } + AString s = p; + if (f.propsSize > 0) { s += ':'; if (f.id == XZ_ID_LZMA2 && f.propsSize == 1) - s += Lzma2PropToString(f.props[0]); + Lzma2PropToString(s, f.props[0]); else if (f.id == XZ_ID_Delta && f.propsSize == 1) - s += ConvertUInt32ToString((UInt32)f.props[0] + 1); + AddUInt32ToString(s, (UInt32)f.props[0] + 1); else { s += '['; @@ -210,29 +242,28 @@ static AString GetMethodString(const CXzFilter &f) static void AddString(AString &dest, const AString &src) { - if (!dest.IsEmpty()) - dest += ' '; + dest.Add_Space_if_NotEmpty(); dest += src; } -static const char *kChecks[] = -{ - "NoCheck", - "CRC32", - NULL, - NULL, - "CRC64", - NULL, - NULL, - NULL, - NULL, - NULL, - "SHA256", - NULL, - NULL, - NULL, - NULL, - NULL +static const char * const kChecks[] = +{ + "NoCheck" + , "CRC32" + , NULL + , NULL + , "CRC64" + , NULL + , NULL + , NULL + , NULL + , NULL + , "SHA256" + , NULL + , NULL + , NULL + , NULL + , NULL }; static AString GetCheckString(const CXzs &xzs) @@ -249,7 +280,10 @@ static AString GetCheckString(const CXzs &xzs) if (kChecks[i]) s2 = kChecks[i]; else - s2 = "Check-" + ConvertUInt32ToString((UInt32)i); + { + s2 = "Check-"; + AddUInt32ToString(s2, (UInt32)i); + } AddString(s, s2); } return s; @@ -258,12 +292,26 @@ static AString GetCheckString(const CXzs &xzs) STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) + NCOM::CPropVariant prop; + switch (propID) { - case kpidNumBlocks: if (!_useSeq) prop = _numBlocks; break; - case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + case kpidPhySize: if (_phySize_Defined) prop = _stat.PhySize; break; + case kpidNumStreams: if (_stat.NumStreams_Defined) prop = _stat.NumStreams; break; + case kpidNumBlocks: if (_stat.NumBlocks_Defined) prop = _stat.NumBlocks; break; + case kpidUnpackSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break; case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;; + if (_stat.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd; + if (_stat.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; + if (_stat.HeadersError) v |= kpv_ErrorFlags_HeadersError; + if (_stat.Unsupported) v |= kpv_ErrorFlags_UnsupportedMethod; + if (_stat.DataError) v |= kpv_ErrorFlags_DataError; + if (_stat.CrcError) v |= kpv_ErrorFlags_CrcError; + prop = v; + } } prop.Detach(value); return S_OK; @@ -276,14 +324,14 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } -STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) + NCOM::CPropVariant prop; + switch (propID) { - case kpidSize: if (_unpackSizeDefined) prop = _unpackSize; break; - case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break; + case kpidPackSize: if (_phySize_Defined) prop = _stat.PhySize; break; case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; } prop.Detach(value); @@ -303,7 +351,8 @@ struct COpenCallbackWrap static SRes OpenCallbackProgress(void *pp, UInt64 inSize, UInt64 /* outSize */) { COpenCallbackWrap *p = (COpenCallbackWrap *)pp; - p->Res = p->OpenCallback->SetCompleted(NULL, &inSize); + if (p->OpenCallback) + p->Res = p->OpenCallback->SetCompleted(NULL, &inSize); return (SRes)p->Res; } @@ -321,82 +370,108 @@ struct CXzsCPP ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); } }; -HRESULT CHandler::Open2(IInStream *inStream, IArchiveOpenCallback *callback) +static HRESULT SRes_to_Open_HRESULT(SRes res) { - CSeekInStreamWrap inStreamImp(inStream); - - CLookToRead lookStream; - LookToRead_CreateVTable(&lookStream, True); - lookStream.realStream = &inStreamImp.p; - LookToRead_Init(&lookStream); + switch (res) + { + case SZ_OK: return S_OK; + case SZ_ERROR_MEM: return E_OUTOFMEMORY; + case SZ_ERROR_PROGRESS: return E_ABORT; + /* + case SZ_ERROR_UNSUPPORTED: + case SZ_ERROR_CRC: + case SZ_ERROR_DATA: + case SZ_ERROR_ARCHIVE: + case SZ_ERROR_NO_ARCHIVE: + return S_FALSE; + */ + } + return S_FALSE; +} - COpenCallbackWrap openWrap(callback); - RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize)); - RINOK(callback->SetTotal(NULL, &_packSize)); +HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback) +{ + _needSeekToStart = true; - CXzsCPP xzs; - SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &_startPosition, &openWrap.p, &g_Alloc); - if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0) - res = SZ_OK; - if (res == SZ_OK) { - _packSize -= _startPosition; - _unpackSize = Xzs_GetUnpackSize(&xzs.p); - _unpackSizeDefined = _packSizeDefined = true; - _numBlocks = (UInt64)Xzs_GetNumBlocks(&xzs.p); - - RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); CXzStreamFlags st; CSeqInStreamWrap inStreamWrap(inStream); - SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p); + SRes res = Xz_ReadHeader(&st, &inStreamWrap.p); + if (res != SZ_OK) + return SRes_to_Open_HRESULT(res); - if (res2 == SZ_OK) { CXzBlock block; Bool isIndex; UInt32 headerSizeRes; - res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes); + SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes); if (res2 == SZ_OK && !isIndex) { - int numFilters = XzBlock_GetNumFilters(&block); - for (int i = 0; i < numFilters; i++) + unsigned numFilters = XzBlock_GetNumFilters(&block); + for (unsigned i = 0; i < numFilters; i++) AddString(_methodsString, GetMethodString(block.filters[i])); } } - AddString(_methodsString, GetCheckString(xzs.p)); } - if (res != SZ_OK || _startPosition != 0) + RINOK(inStream->Seek(0, STREAM_SEEK_END, &_stat.PhySize)); + if (callback) { - RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); - CXzStreamFlags st; - CSeqInStreamWrap inStreamWrap(inStream); - SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p); - if (res2 == SZ_OK) - { - res = res2; - _startPosition = 0; - _useSeq = True; - _unpackSizeDefined = _packSizeDefined = false; - } + RINOK(callback->SetTotal(NULL, &_stat.PhySize)); } - if (res == SZ_ERROR_NO_ARCHIVE) - return S_FALSE; - RINOK(SResToHRESULT(res)); + + CSeekInStreamWrap inStreamImp(inStream); + + CLookToRead lookStream; + LookToRead_CreateVTable(&lookStream, True); + lookStream.realStream = &inStreamImp.p; + LookToRead_Init(&lookStream); + + COpenCallbackWrap openWrap(callback); + + CXzsCPP xzs; + Int64 startPosition; + SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &startPosition, &openWrap.p, &g_Alloc); + if (res == SZ_ERROR_PROGRESS) + return (openWrap.Res == S_OK) ? E_FAIL : openWrap.Res; + /* + if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0) + res = SZ_OK; + */ + if (res == SZ_OK && startPosition == 0) + { + _phySize_Defined = true; + + _stat.OutSize = Xzs_GetUnpackSize(&xzs.p); + _stat.UnpackSize_Defined = true; + + _stat.NumStreams = xzs.p.num; + _stat.NumStreams_Defined = true; + + _stat.NumBlocks = Xzs_GetNumBlocks(&xzs.p); + _stat.NumBlocks_Defined = true; + + AddString(_methodsString, GetCheckString(xzs.p)); + } + else + { + res = SZ_OK; + } + + RINOK(SRes_to_Open_HRESULT(res)); _stream = inStream; _seqStream = inStream; + _isArc = true; return S_OK; } STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback) { COM_TRY_BEGIN - try { Close(); return Open2(inStream, callback); } - catch(...) { return S_FALSE; } COM_TRY_END } @@ -404,15 +479,21 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) { Close(); _seqStream = stream; + _isArc = true; + _needSeekToStart = false; return S_OK; } STDMETHODIMP CHandler::Close() { - _numBlocks = 0; - _useSeq = true; - _unpackSizeDefined = _packSizeDefined = false; - _methodsString.Empty(); + _stat.Clear(); + + _isArc = false; + _needSeekToStart = false; + + _phySize_Defined = false; + + _methodsString.Empty(); _stream.Release(); _seqStream.Release(); return S_OK; @@ -437,146 +518,213 @@ STDMETHODIMP CSeekToSeqStream::Read(void *data, UInt32 size, UInt32 *processedSi STDMETHODIMP CSeekToSeqStream::Seek(Int64, UInt32, UInt64 *) { return E_NOTIMPL; } -struct CXzUnpackerCPP +CXzUnpackerCPP::CXzUnpackerCPP(): InBuf(0), OutBuf(0) { - Byte *InBuf; - Byte *OutBuf; - CXzUnpacker p; - CXzUnpackerCPP(): InBuf(0), OutBuf(0) - { - XzUnpacker_Construct(&p, &g_Alloc); - } - ~CXzUnpackerCPP() - { - XzUnpacker_Free(&p); - MyFree(InBuf); - MyFree(OutBuf); - } -}; + XzUnpacker_Construct(&p, &g_Alloc); +} -STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, - Int32 testMode, IArchiveExtractCallback *extractCallback) +CXzUnpackerCPP::~CXzUnpackerCPP() { - COM_TRY_BEGIN - if (numItems == 0) - return S_OK; - if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) - return E_INVALIDARG; - - extractCallback->SetTotal(_packSize); - UInt64 currentTotalPacked = 0; - RINOK(extractCallback->SetCompleted(¤tTotalPacked)); - CMyComPtr<ISequentialOutStream> realOutStream; - Int32 askMode = testMode ? - NExtract::NAskMode::kTest : - NExtract::NAskMode::kExtract; - - RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); - - if (!testMode && !realOutStream) - return S_OK; - - extractCallback->PrepareOperation(askMode); - - if (_stream) - { - RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); - } - - CLocalProgress *lps = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> progress = lps; - lps->Init(extractCallback, true); - - CCompressProgressWrap progressWrap(progress); + XzUnpacker_Free(&p); + MyFree(InBuf); + MyFree(OutBuf); +} - SRes res = S_OK; +HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) +{ + const size_t kInBufSize = 1 << 15; + const size_t kOutBufSize = 1 << 21; - const UInt32 kInBufSize = 1 << 15; - const UInt32 kOutBufSize = 1 << 21; + Clear(); + DecodeRes = SZ_OK; - UInt32 inPos = 0; - UInt32 inSize = 0; - UInt32 outPos = 0; - CXzUnpackerCPP xzu; XzUnpacker_Init(&xzu.p); - { + if (!xzu.InBuf) xzu.InBuf = (Byte *)MyAlloc(kInBufSize); + if (!xzu.OutBuf) xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize); - if (xzu.InBuf == 0 || xzu.OutBuf == 0) - res = SZ_ERROR_MEM; - } - if (res == SZ_OK) + + UInt32 inSize = 0; + SizeT inPos = 0; + SizeT outPos = 0; + for (;;) { if (inPos == inSize) { inPos = inSize = 0; - RINOK(_seqStream->Read(xzu.InBuf, kInBufSize, &inSize)); + RINOK(seqInStream->Read(xzu.InBuf, kInBufSize, &inSize)); } SizeT inLen = inSize - inPos; SizeT outLen = kOutBufSize - outPos; ECoderStatus status; - res = XzUnpacker_Code(&xzu.p, + + SRes res = XzUnpacker_Code(&xzu.p, xzu.OutBuf + outPos, &outLen, xzu.InBuf + inPos, &inLen, (inSize == 0 ? CODER_FINISH_END : CODER_FINISH_ANY), &status); - // printf("\n_inPos = %6d inLen = %5d, outLen = %5d", inPos, inLen, outLen); + inPos += inLen; + outPos += outLen; + + InSize += inLen; + OutSize += outLen; - inPos += (UInt32)inLen; - outPos += (UInt32)outLen; - lps->InSize += inLen; - lps->OutSize += outLen; + DecodeRes = res; - bool finished = (((inLen == 0) && (outLen == 0)) || res != SZ_OK); + bool finished = ((inLen == 0 && outLen == 0) || res != SZ_OK); - if (outPos == kOutBufSize || finished) + if (outStream) { - if (realOutStream && outPos > 0) + if (outPos == kOutBufSize || finished) { - RINOK(WriteStream(realOutStream, xzu.OutBuf, outPos)); + if (outPos != 0) + { + RINOK(WriteStream(outStream, xzu.OutBuf, outPos)); + outPos = 0; + } } + } + else outPos = 0; + + if (progress) + { + RINOK(progress->SetRatioInfo(&InSize, &OutSize)); } - RINOK(lps->SetCur()); + if (finished) { - _packSize = lps->InSize; - _unpackSize = lps->OutSize; - _packSizeDefined = _unpackSizeDefined = true; + PhySize = InSize; + NumStreams = xzu.p.numStartedStreams; + if (NumStreams > 0) + IsArc = true; + NumBlocks = xzu.p.numTotalBlocks; + + UnpackSize_Defined = true; + NumStreams_Defined = true; + NumBlocks_Defined = true; + + UInt64 extraSize = XzUnpacker_GetExtraSize(&xzu.p); + if (res == SZ_OK) { if (status == CODER_STATUS_NEEDS_MORE_INPUT) { - if (XzUnpacker_IsStreamWasFinished(&xzu.p)) - _packSize -= xzu.p.padSize; - else + extraSize = 0; + if (!XzUnpacker_IsStreamWasFinished(&xzu.p)) + { + // finished at padding bytes, but padding is not aligned for 4 + UnexpectedEnd = true; res = SZ_ERROR_DATA; + } } - else + else // status == CODER_STATUS_NOT_FINISHED res = SZ_ERROR_DATA; } + else if (res == SZ_ERROR_NO_ARCHIVE) + { + if (InSize == extraSize) + IsArc = false; + else + { + if (extraSize != 0 || inPos != inSize) + { + DataAfterEnd = true; + res = SZ_OK; + } + } + } + + DecodeRes = res; + PhySize -= extraSize; + + switch (res) + { + case SZ_OK: break; + case SZ_ERROR_NO_ARCHIVE: IsArc = false; break; + case SZ_ERROR_ARCHIVE: HeadersError = true; break; + case SZ_ERROR_UNSUPPORTED: Unsupported = true; break; + case SZ_ERROR_CRC: CrcError = true; break; + case SZ_ERROR_DATA: DataError = true; break; + default: DataError = true; break; + } + break; } } + return S_OK; +} + +Int32 CDecoder::Get_Extract_OperationResult() const +{ Int32 opRes; - switch(res) + if (!IsArc) + opRes = NExtract::NOperationResult::kIsNotArc; + else if (UnexpectedEnd) + opRes = NExtract::NOperationResult::kUnexpectedEnd; + else if (DataAfterEnd) + opRes = NExtract::NOperationResult::kDataAfterEnd; + else if (CrcError) + opRes = NExtract::NOperationResult::kCRCError; + else if (Unsupported) + opRes = NExtract::NOperationResult::kUnsupportedMethod; + else if (HeadersError) + opRes = NExtract::NOperationResult::kDataError; + else if (DataError) + opRes = NExtract::NOperationResult::kDataError; + else if (DecodeRes != SZ_OK) + opRes = NExtract::NOperationResult::kDataError; + else + opRes = NExtract::NOperationResult::kOK; + return opRes; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + if (numItems == 0) + return S_OK; + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + if (_phySize_Defined) + extractCallback->SetTotal(_stat.PhySize); + + UInt64 currentTotalPacked = 0; + RINOK(extractCallback->SetCompleted(¤tTotalPacked)); + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + + RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); + + if (!testMode && !realOutStream) + return S_OK; + + extractCallback->PrepareOperation(askMode); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> lpsRef = lps; + lps->Init(extractCallback, true); + + if (_needSeekToStart) { - case SZ_OK: - opRes = NExtract::NOperationResult::kOK; break; - case SZ_ERROR_UNSUPPORTED: - opRes = NExtract::NOperationResult::kUnSupportedMethod; break; - case SZ_ERROR_CRC: - opRes = NExtract::NOperationResult::kCRCError; break; - case SZ_ERROR_DATA: - case SZ_ERROR_ARCHIVE: - case SZ_ERROR_NO_ARCHIVE: - opRes = NExtract::NOperationResult::kDataError; break; - default: - return SResToHRESULT(res); + if (!_stream) + return E_FAIL; + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); } + else + _needSeekToStart = true; + + CDecoder decoder; + RINOK(Decode2(_seqStream, realOutStream, decoder, lpsRef)); + Int32 opRes = decoder.Get_Extract_OperationResult(); + realOutStream.Release(); return extractCallback->SetOperationResult(opRes); COM_TRY_END @@ -593,6 +741,8 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { + COM_TRY_BEGIN + CSeqOutStreamWrap seqOutStream(outStream); if (numItems == 0) @@ -648,7 +798,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt RINOK(NCompress::NLzma2::SetLzma2Prop(NCoderPropID::kReduceSize, prop, lzma2Props)); } - for (int i = 0; i < _methods.Size(); i++) + FOR_VECTOR (i, _methods) { COneMethodInfo &m = _methods[i]; SetGlobalLevelAndThreads(m @@ -657,7 +807,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt #endif ); { - for (int j = 0; j < m.Props.Size(); j++) + FOR_VECTOR (j, m.Props) { const CProp &prop = m.Props[j]; RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props)); @@ -692,7 +842,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (_filterId == XZ_ID_Delta) { bool deltaDefined = false; - for (int j = 0; j < _filterMethod.Props.Size(); j++) + FOR_VECTOR (j, _filterMethod.Props) { const CProp &prop = _filterMethod.Props[j]; if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4) @@ -712,32 +862,50 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); return SResToHRESULT(res); } + if (indexInArchive != 0) return E_INVALIDARG; + + CMyComPtr<IArchiveUpdateCallbackFile> opCallback; + updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); + if (opCallback) + { + RINOK(opCallback->ReportOperation(NEventIndexType::kInArcIndex, 0, NUpdateNotifyOp::kReplicate)) + } + if (_stream) - RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL)); - return NCompress::CopyStream(_stream, outStream, 0); -} + { + if (_phySize_Defined) + RINOK(updateCallback->SetTotal(_stat.PhySize)); + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); + } -#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(updateCallback, true); -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) + return NCompress::CopyStream(_stream, outStream, progress); + + COM_TRY_END +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { COM_TRY_BEGIN + Init(); - for (int i = 0; i < numProps; i++) + for (UInt32 i = 0; i < numProps; i++) { RINOK(SetProperty(names[i], values[i])); } if (!_filterMethod.MethodName.IsEmpty()) { - int k; + unsigned k; for (k = 0; k < ARRAY_SIZE(g_NamePairs); k++) { const CMethodNamePair &pair = g_NamePairs[k]; - UString m = GetUnicodeString(pair.Name); - if (_filterMethod.MethodName.CompareNoCase(m) == 0) + if (StringsAreEqualNoCase_Ascii(_filterMethod.MethodName, pair.Name)) { _filterId = pair.Id; break; @@ -747,34 +915,30 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v return E_INVALIDARG; } - int numEmptyMethods = GetNumEmptyMethods(); - _methods.Delete(0, numEmptyMethods); + _methods.DeleteFrontal(GetNumEmptyMethods()); if (_methods.Size() > 1) return E_INVALIDARG; if (_methods.Size() == 1) { - UString &methodName = _methods[0].MethodName; + AString &methodName = _methods[0].MethodName; if (methodName.IsEmpty()) methodName = k_LZMA2_Name; - else if (methodName.CompareNoCase(k_LZMA2_Name) != 0) + else if (!methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name)) return E_INVALIDARG; } + return S_OK; + COM_TRY_END } #endif -static IInArchive *CreateArc() { return new NArchive::NXz::CHandler; } -#ifndef EXTRACT_ONLY -static IOutArchive *CreateArcOut() { return new NArchive::NXz::CHandler; } -#else -#define CreateArcOut 0 -#endif - -static CArcInfo g_ArcInfo = - { L"xz", L"xz txz", L"* .tar", 0xC, {0xFD, '7' , 'z', 'X', 'Z', '\0'}, 6, true, CreateArc, CreateArcOut }; - -REGISTER_ARC(xz) +REGISTER_ARC_IO( + "xz", "xz txz", "* .tar", 0xC, + XZ_SIG, + 0, + NArcInfoFlags::kKeepName, + NULL) }} |