diff options
Diffstat (limited to 'CPP/7zip/Archive/Zip/ZipUpdate.cpp')
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/Archive/Zip/ZipUpdate.cpp | 296 |
1 files changed, 159 insertions, 137 deletions
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index a91364be..2978e387 100755..100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -4,12 +4,12 @@ #include "../../../../C/Alloc.h" -#include "Common/AutoPtr.h" -#include "Common/Defs.h" -#include "Common/StringConvert.h" +#include "../../../Common/AutoPtr.h" +#include "../../../Common/Defs.h" +#include "../../../Common/StringConvert.h" -#include "Windows/Defs.h" -#include "Windows/Thread.h" +#include "../../../Windows/Defs.h" +#include "../../../Windows/Thread.h" #include "../../Common/CreateCoder.h" #include "../../Common/LimitedStreams.h" @@ -44,12 +44,12 @@ static const Byte kExtractHostOS = kHostOS; static const Byte kMethodForDirectory = NFileHeader::NCompressionMethod::kStored; -static HRESULT CopyBlockToArchive(ISequentialInStream *inStream, +static HRESULT CopyBlockToArchive(ISequentialInStream *inStream, UInt64 size, COutArchive &outArchive, ICompressProgressInfo *progress) { CMyComPtr<ISequentialOutStream> outStream; outArchive.CreateStreamForCopying(&outStream); - return NCompress::CopyStream(inStream, outStream, progress); + return NCompress::CopyStream_ExactSize(inStream, outStream, size, progress); } static HRESULT WriteRange(IInStream *inStream, COutArchive &outArchive, @@ -57,13 +57,7 @@ static HRESULT WriteRange(IInStream *inStream, COutArchive &outArchive, { UInt64 position; RINOK(inStream->Seek(range.Position, STREAM_SEEK_SET, &position)); - - CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; - CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec); - streamSpec->SetStream(inStream); - streamSpec->Init(range.Size); - - RINOK(CopyBlockToArchive(inStreamLimited, outArchive, progress)); + RINOK(CopyBlockToArchive(inStream, range.Size, outArchive, progress)); return progress->SetRatioInfo(&range.Size, &range.Size); } @@ -71,42 +65,42 @@ static void SetFileHeader( COutArchive &archive, const CCompressionMethodMode &options, const CUpdateItem &ui, - CItem &item) + CItemOut &item) { - item.UnPackSize = ui.Size; + item.Size = ui.Size; bool isDir; item.ClearFlags(); - if (ui.NewProperties) + if (ui.NewProps) { isDir = ui.IsDir; item.Name = ui.Name; item.SetUtf8(ui.IsUtf8); - item.ExternalAttributes = ui.Attributes; + item.ExternalAttrib = ui.Attrib; item.Time = ui.Time; - item.NtfsMTime = ui.NtfsMTime; - item.NtfsATime = ui.NtfsATime; - item.NtfsCTime = ui.NtfsCTime; + item.Ntfs_MTime = ui.Ntfs_MTime; + item.Ntfs_ATime = ui.Ntfs_ATime; + item.Ntfs_CTime = ui.Ntfs_CTime; item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; } else isDir = item.IsDir(); - item.LocalHeaderPosition = archive.GetCurrentPosition(); + item.LocalHeaderPos = archive.GetCurPos(); item.MadeByVersion.HostOS = kMadeByHostOS; item.MadeByVersion.Version = NFileHeader::NCompressionMethod::kMadeByProgramVersion; item.ExtractVersion.HostOS = kExtractHostOS; - item.InternalAttributes = 0; // test it + item.InternalAttrib = 0; // test it item.SetEncrypted(!isDir && options.PasswordIsDefined); if (isDir) { item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir; - item.CompressionMethod = kMethodForDirectory; + item.Method = kMethodForDirectory; item.PackSize = 0; - item.FileCRC = 0; // test it + item.Crc = 0; // test it } } @@ -114,9 +108,9 @@ static void SetItemInfoFromCompressingResult(const CCompressingResult &compressi bool isAesMode, Byte aesKeyMode, CItem &item) { item.ExtractVersion.Version = compressingResult.ExtractVersion; - item.CompressionMethod = compressingResult.Method; - item.FileCRC = compressingResult.CRC; - item.UnPackSize = compressingResult.UnpackSize; + item.Method = compressingResult.Method; + item.Crc = compressingResult.CRC; + item.Size = compressingResult.UnpackSize; item.PackSize = compressingResult.PackSize; item.LocalExtra.Clear(); @@ -124,11 +118,11 @@ static void SetItemInfoFromCompressingResult(const CCompressingResult &compressi if (isAesMode) { - CWzAesExtraField wzAesField; + CWzAesExtra wzAesField; wzAesField.Strength = aesKeyMode; wzAesField.Method = compressingResult.Method; - item.CompressionMethod = NFileHeader::NCompressionMethod::kWzAES; - item.FileCRC = 0; + item.Method = NFileHeader::NCompressionMethod::kWzAES; + item.Crc = 0; CExtraSubBlock sb; wzAesField.SetSubBlock(sb); item.LocalExtra.SubBlocks.Add(sb); @@ -142,10 +136,7 @@ static THREAD_FUNC_DECL CoderThread(void *threadCoderInfo); struct CThreadInfo { - #ifdef EXTERNAL_CODECS - CMyComPtr<ICompressCodecsInfo> _codecsInfo; - const CObjectVector<CCodecInfoEx> *_externalCodecs; - #endif + DECL_EXTERNAL_CODECS_LOC_VARS2; NWindows::CThread Thread; NWindows::NSynchronization::CAutoResetEvent CompressEvent; @@ -202,9 +193,7 @@ void CThreadInfo::WaitAndCode() if (ExitThread) return; Result = Coder.Compress( - #ifdef EXTERNAL_CODECS - _codecsInfo, _externalCodecs, - #endif + EXTERNAL_CODECS_LOC_VARS InStream, OutStream, Progress, CompressingResult); if (Result == S_OK && Progress) Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize); @@ -224,7 +213,7 @@ public: CObjectVector<CThreadInfo> Threads; ~CThreads() { - for (int i = 0; i < Threads.Size(); i++) + FOR_VECTOR (i, Threads) Threads[i].StopWaitClose(); } }; @@ -245,7 +234,7 @@ public: CMemRefs(CMemBlockManagerMt *manager): Manager(manager) {} ; ~CMemRefs() { - for (int i = 0; i < Refs.Size(); i++) + FOR_VECTOR (i, Refs) Refs[i].FreeOpt(Manager); } }; @@ -335,69 +324,74 @@ STDMETHODIMP CMtProgressMixer::SetRatioInfo(const UInt64 *inSize, const UInt64 * #endif -static HRESULT UpdateItemOldData(COutArchive &archive, - IInStream *inStream, - const CUpdateItem &ui, CItemEx &item, +static HRESULT UpdateItemOldData( + COutArchive &archive, + CInArchive *inArchive, + const CItemEx &itemEx, + const CUpdateItem &ui, + CItemOut &item, /* bool izZip64, */ ICompressProgressInfo *progress, UInt64 &complexity) { - if (ui.NewProperties) + if (ui.NewProps) { if (item.HasDescriptor()) return E_NOTIMPL; // use old name size. // CUpdateRange range(item.GetLocalExtraPosition(), item.LocalExtraSize + item.PackSize); - CUpdateRange range(item.GetDataPosition(), item.PackSize); + CUpdateRange range(inArchive->GetOffsetInStream(itemEx.GetDataPosition()), itemEx.PackSize); - // item.ExternalAttributes = ui.Attributes; - // Test it + // we keep ExternalAttrib and some another properties from old archive + // item.ExternalAttrib = ui.Attrib; + item.Name = ui.Name; item.SetUtf8(ui.IsUtf8); item.Time = ui.Time; - item.NtfsMTime = ui.NtfsMTime; - item.NtfsATime = ui.NtfsATime; - item.NtfsCTime = ui.NtfsCTime; + item.Ntfs_MTime = ui.Ntfs_MTime; + item.Ntfs_ATime = ui.Ntfs_ATime; + item.Ntfs_CTime = ui.Ntfs_CTime; item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; item.CentralExtra.RemoveUnknownSubBlocks(); item.LocalExtra.RemoveUnknownSubBlocks(); - - archive.PrepareWriteCompressedData2((UInt16)item.Name.Length(), item.UnPackSize, item.PackSize, item.LocalExtra.HasWzAesField()); - item.LocalHeaderPosition = archive.GetCurrentPosition(); - archive.SeekToPackedDataPosition(); - RINOK(WriteRange(inStream, archive, range, progress)); - complexity += range.Size; + item.LocalHeaderPos = archive.GetCurPos(); + + archive.PrepareWriteCompressedData2(item.Name.Len(), item.Size, item.PackSize, item.LocalExtra.HasWzAes()); archive.WriteLocalHeader(item); + RINOK(WriteRange(inArchive->Stream, archive, range, progress)); + complexity += range.Size; } else { - CUpdateRange range(item.LocalHeaderPosition, item.GetLocalFullSize()); + CUpdateRange range(inArchive->GetOffsetInStream(itemEx.LocalHeaderPos), itemEx.GetLocalFullSize()); // set new header position - item.LocalHeaderPosition = archive.GetCurrentPosition(); + item.LocalHeaderPos = archive.GetCurPos(); - RINOK(WriteRange(inStream, archive, range, progress)); + RINOK(WriteRange(inArchive->Stream, archive, range, progress)); complexity += range.Size; - archive.MoveBasePosition(range.Size); + archive.MoveCurPos(range.Size); } return S_OK; } static void WriteDirHeader(COutArchive &archive, const CCompressionMethodMode *options, - const CUpdateItem &ui, CItemEx &item) + const CUpdateItem &ui, CItemOut &item) { SetFileHeader(archive, *options, ui, item); - archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsRealAesMode()); - archive.WriteLocalHeader(item); + archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, + // options->IsRealAesMode() + false // fixed 9.31 + ); + archive.WriteLocalHeader_And_SeekToNextFile(item); } static HRESULT Update2St( DECL_EXTERNAL_CODECS_LOC_VARS COutArchive &archive, CInArchive *inArchive, - IInStream *inStream, const CObjectVector<CItemEx> &inputItems, const CObjectVector<CUpdateItem> &updateItems, const CCompressionMethodMode *options, @@ -410,26 +404,29 @@ static HRESULT Update2St( CAddCommon compressor(*options); - CObjectVector<CItem> items; + CObjectVector<CItemOut> items; UInt64 unpackSizeTotal = 0, packSizeTotal = 0; - for (int itemIndex = 0; itemIndex < updateItems.Size(); itemIndex++) + FOR_VECTOR (itemIndex, updateItems) { lps->InSize = unpackSizeTotal; lps->OutSize = packSizeTotal; RINOK(lps->SetCur()); const CUpdateItem &ui = updateItems[itemIndex]; - CItemEx item; - if (!ui.NewProperties || !ui.NewData) + CItemEx itemEx; + CItemOut item; + + if (!ui.NewProps || !ui.NewData) { - item = inputItems[ui.IndexInArchive]; - if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK) + itemEx = inputItems[ui.IndexInArc]; + if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK) return E_NOTIMPL; + (CItem &)item = itemEx; } if (ui.NewData) { - bool isDir = ((ui.NewProperties) ? ui.IsDir : item.IsDir()); + bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir()); if (isDir) { WriteDirHeader(archive, options, ui, item); @@ -445,10 +442,12 @@ static HRESULT Update2St( continue; } RINOK(res); + if (!fileInStream) + return E_INVALIDARG; // file Size can be 64-bit !!! SetFileHeader(archive, *options, ui, item); - archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsRealAesMode()); + archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, options->IsRealAesMode()); CCompressingResult compressingResult; CMyComPtr<IOutStream> outStream; archive.CreateStreamForCompressing(&outStream); @@ -456,9 +455,9 @@ static HRESULT Update2St( EXTERNAL_CODECS_LOC_VARS fileInStream, outStream, progress, compressingResult)); SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item); - archive.WriteLocalHeader(item); + archive.WriteLocalHeader_And_SeekToNextFile(item); RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); - unpackSizeTotal += item.UnPackSize; + unpackSizeTotal += item.Size; packSizeTotal += item.PackSize; } } @@ -466,12 +465,12 @@ static HRESULT Update2St( { UInt64 complexity = 0; lps->SendRatio = false; - RINOK(UpdateItemOldData(archive, inStream, ui, item, progress, complexity)); + RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, complexity)); lps->SendRatio = true; lps->ProgressOffset += complexity; } items.Add(item); - lps->ProgressOffset += NFileHeader::kLocalBlockSize; + lps->ProgressOffset += kLocalHeaderSize; } lps->InSize = unpackSizeTotal; lps->OutSize = packSizeTotal; @@ -484,7 +483,6 @@ static HRESULT Update2( DECL_EXTERNAL_CODECS_LOC_VARS COutArchive &archive, CInArchive *inArchive, - IInStream *inStream, const CObjectVector<CItemEx> &inputItems, const CObjectVector<CUpdateItem> &updateItems, const CCompressionMethodMode *options, @@ -495,7 +493,7 @@ static HRESULT Update2( UInt64 numFilesToCompress = 0; UInt64 numBytesToCompress = 0; - int i; + unsigned i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; @@ -511,18 +509,18 @@ static HRESULT Update2( } else { - CItemEx inputItem = inputItems[ui.IndexInArchive]; + CItemEx inputItem = inputItems[ui.IndexInArc]; if (inArchive->ReadLocalItemAfterCdItemFull(inputItem) != S_OK) return E_NOTIMPL; complexity += inputItem.GetLocalFullSize(); // complexity += inputItem.GetCentralExtraPlusCommentSize(); } - complexity += NFileHeader::kLocalBlockSize; - complexity += NFileHeader::kCentralBlockSize; + complexity += kLocalHeaderSize; + complexity += kCentralHeaderSize; } if (comment) - complexity += comment->GetCapacity(); + complexity += comment->Size(); complexity++; // end of central updateCallback->SetTotal(complexity); @@ -540,6 +538,9 @@ static HRESULT Update2( UInt32 numThreads = options->NumThreads; if (numThreads > kNumMaxThreads) numThreads = kNumMaxThreads; + if (numThreads < 1) + numThreads = 1; + const size_t kMemPerThread = (1 << 25); const size_t kBlockSize = 1 << 16; @@ -549,16 +550,18 @@ static HRESULT Update2( if (numFilesToCompress <= 1) mtMode = false; + Byte method = options->MethodSequence.Front(); if (!mtMode) { - if (numThreads < 2) - if (options2.MethodInfo.FindProp(NCoderPropID::kNumThreads) < 0 && - options2.NumThreadsWasChanged) - options2.MethodInfo.AddNumThreadsProp(1); + if (options2.MethodInfo.FindProp(NCoderPropID::kNumThreads) < 0) + { + // fixed for 9.31. bzip2 default is just one thread. + if (options2.NumThreadsWasChanged || method == NFileHeader::NCompressionMethod::kBZip2) + options2.MethodInfo.AddNumThreadsProp(numThreads); + } } else { - Byte method = options->MethodSequence.Front(); if (method == NFileHeader::NCompressionMethod::kStored && !options->PasswordIsDefined) numThreads = 1; if (method == NFileHeader::NCompressionMethod::kBZip2) @@ -594,13 +597,13 @@ static HRESULT Update2( #endif return Update2St( EXTERNAL_CODECS_LOC_VARS - archive, inArchive, inStream, + archive, inArchive, inputItems, updateItems, &options2, comment, updateCallback); #ifndef _7ZIP_ST - CObjectVector<CItem> items; + CObjectVector<CItemOut> items; CMtProgressMixer *mtProgressMixerSpec = new CMtProgressMixer; CMyComPtr<ICompressProgressInfo> progress = mtProgressMixerSpec; @@ -629,8 +632,7 @@ static HRESULT Update2( { CThreadInfo &threadInfo = threads.Threads[i]; #ifdef EXTERNAL_CODECS - threadInfo._codecsInfo = codecsInfo; - threadInfo._externalCodecs = externalCodecs; + threadInfo.__externalCodecs = __externalCodecs; #endif RINOK(threadInfo.CreateEvents()); threadInfo.OutStreamSpec = new COutMemStream(&memManager); @@ -643,9 +645,9 @@ static HRESULT Update2( RINOK(threadInfo.CreateThread()); } } - int mtItemIndex = 0; + unsigned mtItemIndex = 0; - int itemIndex = 0; + unsigned itemIndex = 0; int lastRealStreamItemIndex = -1; while (itemIndex < updateItems.Size()) @@ -655,17 +657,19 @@ static HRESULT Update2( const CUpdateItem &ui = updateItems[mtItemIndex++]; if (!ui.NewData) continue; - CItemEx item; - if (ui.NewProperties) + CItemEx itemEx; + CItemOut item; + if (ui.NewProps) { if (ui.IsDir) continue; } else { - item = inputItems[ui.IndexInArchive]; - if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK) + itemEx = inputItems[ui.IndexInArc]; + if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK) return E_NOTIMPL; + (CItem &)item = itemEx; if (item.IsDir()) continue; } @@ -676,13 +680,15 @@ static HRESULT Update2( if (res == S_FALSE) { complexity += ui.Size; - complexity += NFileHeader::kLocalBlockSize; + complexity += kLocalHeaderSize; mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity); RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); refs.Refs[mtItemIndex - 1].Skip = true; continue; } RINOK(res); + if (!fileInStream) + return E_INVALIDARG; RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); } @@ -719,29 +725,31 @@ static HRESULT Update2( const CUpdateItem &ui = updateItems[itemIndex]; - CItemEx item; - if (!ui.NewProperties || !ui.NewData) + CItemEx itemEx; + CItemOut item; + if (!ui.NewProps || !ui.NewData) { - item = inputItems[ui.IndexInArchive]; - if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK) + itemEx = inputItems[ui.IndexInArc]; + if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK) return E_NOTIMPL; + (CItem &)item = itemEx; } if (ui.NewData) { - bool isDir = ((ui.NewProperties) ? ui.IsDir : item.IsDir()); + bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir()); if (isDir) { WriteDirHeader(archive, options, ui, item); } else { - if (lastRealStreamItemIndex < itemIndex) + if (lastRealStreamItemIndex < (int)itemIndex) { lastRealStreamItemIndex = itemIndex; SetFileHeader(archive, *options, ui, item); // file Size can be 64-bit !!! - archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsRealAesMode()); + archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, options->IsRealAesMode()); } CMemBlocks2 &memRef = refs.Refs[itemIndex]; @@ -750,10 +758,13 @@ static HRESULT Update2( CMyComPtr<IOutStream> outStream; archive.CreateStreamForCompressing(&outStream); memRef.WriteToStream(memManager.GetBlockSize(), outStream); + SetFileHeader(archive, *options, ui, item); + // the BUG was fixed in 9.26: + // SetItemInfoFromCompressingResult must be after SetFileHeader + // to write correct Size. SetItemInfoFromCompressingResult(memRef.CompressingResult, options->IsRealAesMode(), options->AesKeyMode, item); - SetFileHeader(archive, *options, ui, item); - archive.WriteLocalHeader(item); + archive.WriteLocalHeader_And_SeekToNextFile(item); // RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); memRef.FreeOpt(&memManager); } @@ -783,10 +794,10 @@ static HRESULT Update2( { RINOK(threadInfo.OutStreamSpec->WriteToRealStream()); threadInfo.OutStreamSpec->ReleaseOutStream(); + SetFileHeader(archive, *options, ui, item); SetItemInfoFromCompressingResult(threadInfo.CompressingResult, options->IsRealAesMode(), options->AesKeyMode, item); - SetFileHeader(archive, *options, ui, item); - archive.WriteLocalHeader(item); + archive.WriteLocalHeader_And_SeekToNextFile(item); } else { @@ -801,10 +812,10 @@ static HRESULT Update2( } else { - RINOK(UpdateItemOldData(archive, inStream, ui, item, progress, complexity)); + RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, complexity)); } items.Add(item); - complexity += NFileHeader::kLocalBlockSize; + complexity += kLocalHeaderSize; mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity); itemIndex++; } @@ -993,15 +1004,18 @@ STDMETHODIMP CCacheOutStream::Write(const void *data, UInt32 size, UInt32 *proce STDMETHODIMP CCacheOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - switch(seekOrigin) + switch (seekOrigin) { - case STREAM_SEEK_SET: _virtPos = offset; break; - case STREAM_SEEK_CUR: _virtPos += offset; break; - case STREAM_SEEK_END: _virtPos = _virtSize + offset; break; + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += _virtSize; break; default: return STG_E_INVALIDFUNCTION; } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = offset; if (newPosition) - *newPosition = _virtPos; + *newPosition = offset; return S_OK; } @@ -1029,16 +1043,33 @@ HRESULT Update( const CObjectVector<CItemEx> &inputItems, const CObjectVector<CUpdateItem> &updateItems, ISequentialOutStream *seqOutStream, - CInArchive *inArchive, + CInArchive *inArchive, bool removeSfx, CCompressionMethodMode *compressionMethodMode, IArchiveUpdateCallback *updateCallback) { + if (inArchive) + { + if (!inArchive->CanUpdate()) + return E_NOTIMPL; + } + + CMyComPtr<IOutStream> outStream; { CMyComPtr<IOutStream> outStreamReal; seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStreamReal); if (!outStreamReal) return E_NOTIMPL; + + if (inArchive) + { + if (inArchive->ArcInfo.Base > 0 && !removeSfx) + { + RINOK(inArchive->Stream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(NCompress::CopyStream_ExactSize(inArchive->Stream, outStreamReal, inArchive->ArcInfo.Base, NULL)); + } + } + CCacheOutStream *cacheStream = new CCacheOutStream(); outStream = cacheStream; if (!cacheStream->Allocate()) @@ -1046,32 +1077,23 @@ HRESULT Update( RINOK(cacheStream->Init(outStreamReal)); } - if (inArchive) - { - if (inArchive->ArcInfo.Base != 0 || - inArchive->ArcInfo.StartPosition != 0 || - !inArchive->IsOkHeaders) - return E_NOTIMPL; - } - COutArchive outArchive; - outArchive.Create(outStream); - /* - if (inArchive && inArchive->ArcInfo.StartPosition > 0) + RINOK(outArchive.Create(outStream)); + + if (inArchive) { - CMyComPtr<ISequentialInStream> inStream; - inStream.Attach(inArchive->CreateLimitedStream(0, inArchive->ArcInfo.StartPosition)); - RINOK(CopyBlockToArchive(inStream, outArchive, NULL)); - outArchive.MoveBasePosition(inArchive->ArcInfo.StartPosition); + if ((Int64)inArchive->ArcInfo.MarkerPos2 > inArchive->ArcInfo.Base) + { + RINOK(inArchive->Stream->Seek(inArchive->ArcInfo.Base, STREAM_SEEK_SET, NULL)); + UInt64 embStubSize = inArchive->ArcInfo.MarkerPos2 - inArchive->ArcInfo.Base; + RINOK(NCompress::CopyStream_ExactSize(inArchive->Stream, outStream, embStubSize, NULL)); + outArchive.MoveCurPos(embStubSize); + } } - */ - CMyComPtr<IInStream> inStream; - if (inArchive) - inStream.Attach(inArchive->CreateStream()); return Update2( EXTERNAL_CODECS_LOC_VARS - outArchive, inArchive, inStream, + outArchive, inArchive, inputItems, updateItems, compressionMethodMode, inArchive ? &inArchive->ArcInfo.Comment : NULL, |