diff options
Diffstat (limited to 'CPP/7zip/Archive/7z')
-rw-r--r-- | CPP/7zip/Archive/7z/7zCompressionMode.h | 17 | ||||
-rw-r--r-- | CPP/7zip/Archive/7z/7zDecode.cpp | 14 | ||||
-rw-r--r-- | CPP/7zip/Archive/7z/7zEncode.cpp | 34 | ||||
-rw-r--r-- | CPP/7zip/Archive/7z/7zExtract.cpp | 5 | ||||
-rw-r--r-- | CPP/7zip/Archive/7z/7zHandler.cpp | 16 | ||||
-rw-r--r-- | CPP/7zip/Archive/7z/7zHandler.h | 6 | ||||
-rw-r--r-- | CPP/7zip/Archive/7z/7zHandlerOut.cpp | 72 | ||||
-rw-r--r-- | CPP/7zip/Archive/7z/7zHeader.h | 5 | ||||
-rw-r--r-- | CPP/7zip/Archive/7z/7zIn.cpp | 45 | ||||
-rw-r--r-- | CPP/7zip/Archive/7z/7zIn.h | 25 | ||||
-rw-r--r-- | CPP/7zip/Archive/7z/7zItem.h | 2 | ||||
-rw-r--r-- | CPP/7zip/Archive/7z/7zOut.cpp | 309 | ||||
-rw-r--r-- | CPP/7zip/Archive/7z/7zOut.h | 52 | ||||
-rw-r--r-- | CPP/7zip/Archive/7z/7zUpdate.cpp | 307 | ||||
-rw-r--r-- | CPP/7zip/Archive/7z/7zUpdate.h | 23 |
15 files changed, 600 insertions, 332 deletions
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h index ac1f6ad..737722d 100644 --- a/CPP/7zip/Archive/7z/7zCompressionMode.h +++ b/CPP/7zip/Archive/7z/7zCompressionMode.h @@ -52,31 +52,30 @@ struct CCompressionMethodMode bool DefaultMethod_was_Inserted; bool Filter_was_Inserted; + bool PasswordIsDefined; + bool MemoryUsageLimit_WasSet; #ifndef Z7_ST - UInt32 NumThreads; bool NumThreads_WasForced; bool MultiThreadMixer; + UInt32 NumThreads; #endif - UInt64 MemoryUsageLimit; - bool MemoryUsageLimit_WasSet; - - bool PasswordIsDefined; UString Password; // _Wipe - + UInt64 MemoryUsageLimit; + bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } CCompressionMethodMode(): DefaultMethod_was_Inserted(false) , Filter_was_Inserted(false) + , PasswordIsDefined(false) + , MemoryUsageLimit_WasSet(false) #ifndef Z7_ST - , NumThreads(1) , NumThreads_WasForced(false) , MultiThreadMixer(true) + , NumThreads(1) #endif , MemoryUsageLimit((UInt64)1 << 30) - , MemoryUsageLimit_WasSet(false) - , PasswordIsDefined(false) {} #ifdef Z7_CPP_IS_SUPPORTED_default diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp index 5420dce..50cbff6 100644 --- a/CPP/7zip/Archive/7z/7zDecode.cpp +++ b/CPP/7zip/Archive/7z/7zDecode.cpp @@ -442,9 +442,10 @@ HRESULT CDecoder::Decode( len = password.Len(); } CByteBuffer_Wipe buffer(len * 2); + const LPCOLESTR psw = passwordBSTR; for (size_t k = 0; k < len; k++) { - const wchar_t c = passwordBSTR[k]; + const wchar_t c = psw[k]; ((Byte *)buffer)[k * 2] = (Byte)c; ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8); } @@ -501,8 +502,7 @@ HRESULT CDecoder::Decode( CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; - CLockedInStream *lockedInStreamSpec = new CLockedInStream; - CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec; + CMyComPtr2_Create<IUnknown, CLockedInStream> lockedInStream; #ifdef USE_MIXER_MT #ifdef USE_MIXER_ST @@ -514,8 +514,8 @@ HRESULT CDecoder::Decode( { // lockedInStream.Pos = (UInt64)(Int64)-1; // RINOK(InStream_GetPos(inStream, lockedInStream.Pos)) - RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStreamSpec->Pos)) - lockedInStreamSpec->Stream = inStream; + RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStream->Pos)) + lockedInStream->Stream = inStream; #ifdef USE_MIXER_MT #ifdef USE_MIXER_ST @@ -551,7 +551,7 @@ HRESULT CDecoder::Decode( { CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT; packStream = lockedStreamImpSpec; - lockedStreamImpSpec->Init(lockedInStreamSpec, packPos); + lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos); } #ifdef USE_MIXER_ST else @@ -561,7 +561,7 @@ HRESULT CDecoder::Decode( #ifdef USE_MIXER_ST CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST; packStream = lockedStreamImpSpec; - lockedStreamImpSpec->Init(lockedInStreamSpec, packPos); + lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos); #endif } } diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp index 78c91cf..71d1ddb 100644 --- a/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/CPP/7zip/Archive/7z/7zEncode.cpp @@ -299,10 +299,9 @@ static HRESULT FillProps_from_Coder(IUnknown *coder, CByteBuffer &props) writeCoderProperties, coder) if (writeCoderProperties) { - CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream; - CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec); + CMyComPtr2_Create<ISequentialOutStream, CDynBufSeqOutStream> outStreamSpec; outStreamSpec->Init(); - RINOK(writeCoderProperties->WriteCoderProperties(dynOutStream)) + RINOK(writeCoderProperties->WriteCoderProperties(outStreamSpec)) outStreamSpec->CopyToBuffer(props); } else @@ -332,11 +331,8 @@ HRESULT CEncoder::Encode1( RINOK(_mixer->ReInit2()) - CMtEncMultiProgress *mtProgressSpec = NULL; - CMyComPtr<ICompressProgressInfo> mtProgress; - - CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL; - CMyComPtr<ISequentialOutStream> mtOutStreamNotify; + CMyComPtr2<ICompressProgressInfo, CMtEncMultiProgress> mtProgress; + CMyComPtr2<ISequentialOutStream, CSequentialOutMtNotify> mtOutStreamNotify; CRecordVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs; CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; @@ -454,18 +450,16 @@ HRESULT CEncoder::Encode1( if (useMtProgress) { - mtProgressSpec = new CMtEncMultiProgress; - mtProgress = mtProgressSpec; - mtProgressSpec->Init(compressProgress); + mtProgress.SetFromCls(new CMtEncMultiProgress); + mtProgress->Init(compressProgress); - mtOutStreamNotifySpec = new CSequentialOutMtNotify; - mtOutStreamNotify = mtOutStreamNotifySpec; - mtOutStreamNotifySpec->_stream = outStream; - mtOutStreamNotifySpec->_mtProgressSpec = mtProgressSpec; + mtOutStreamNotify.SetFromCls(new CSequentialOutMtNotify); + mtOutStreamNotify->_stream = outStream; + mtOutStreamNotify->_mtProgressSpec = mtProgress.ClsPtr(); FOR_VECTOR (t, tempBufferSpecs) { - tempBufferSpecs[t]->_mtProgressSpec = mtProgressSpec; + tempBufferSpecs[t]->_mtProgressSpec = mtProgress.ClsPtr(); } } @@ -474,7 +468,8 @@ HRESULT CEncoder::Encode1( { outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; outStreamSizeCount = outStreamSizeCountSpec; - outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream); + outStreamSizeCountSpec->SetStream(mtOutStreamNotify.IsDefined() ? + mtOutStreamNotify.Interface() : outStream); outStreamSizeCountSpec->Init(); outStreamPointers.Add(outStreamSizeCount); } @@ -486,8 +481,9 @@ HRESULT CEncoder::Encode1( RINOK(_mixer->Code( &inStreamPointer, - &outStreamPointers.Front(), - mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress, dataAfterEnd_Error)) + outStreamPointers.ConstData(), + mtProgress.IsDefined() ? mtProgress.Interface() : + compressProgress, dataAfterEnd_Error)) if (_bindInfo.PackStreams.Size() != 0) packSizes.Add(outStreamSizeCountSpec->GetSize()); diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp index 5498c59..1c31e1d 100644 --- a/CPP/7zip/Archive/7z/7zExtract.cpp +++ b/CPP/7zip/Archive/7z/7zExtract.cpp @@ -271,8 +271,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->SetTotal(importantTotalUnpacked)) - CLocalProgress *lps = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> progress = lps; + CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; lps->Init(extractCallback, false); CDecoder decoder( @@ -385,7 +384,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, &curUnpacked, outStream, - progress, + lps, NULL // *inStreamMainRes , dataAfterEnd_Error diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp index 23d3a9d..81dd966 100644 --- a/CPP/7zip/Archive/7z/7zHandler.cpp +++ b/CPP/7zip/Archive/7z/7zHandler.cpp @@ -272,6 +272,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) prop = true; break; } + default: break; } return prop.Detach(value); #ifndef Z7_SFX @@ -291,7 +292,7 @@ bool CHandler::IsFolderEncrypted(CNum folderIndex) const if (folderIndex == kNumNoIndex) return false; const size_t startPos = _db.FoCodersDataOffset[folderIndex]; - const Byte *p = _db.CodersData + startPos; + const Byte *p = _db.CodersData.ConstData() + startPos; const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos; CInByte2 inByte; inByte.Init(p, size); @@ -350,11 +351,11 @@ Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data { if (_db.NameOffsets && _db.NamesBuf) { - size_t offset = _db.NameOffsets[index]; - size_t size = (_db.NameOffsets[index + 1] - offset) * 2; + const size_t offset = _db.NameOffsets[index]; + const size_t size = (_db.NameOffsets[index + 1] - offset) * 2; if (size < ((UInt32)1 << 31)) { - *data = (const void *)(_db.NamesBuf + offset * 2); + *data = (const void *)(_db.NamesBuf.ConstData() + offset * 2); *dataSize = (UInt32)size; *propType = NPropDataType::kUtf16z; } @@ -395,7 +396,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const temp[--pos] = 0; const size_t startPos = _db.FoCodersDataOffset[folderIndex]; - const Byte *p = _db.CodersData + startPos; + const Byte *p = _db.CodersData.ConstData() + startPos; const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos; CInByte2 inByte; inByte.Init(p, size); @@ -482,9 +483,9 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const if (propsSize == 1) ConvertUInt32ToString((UInt32)props[0] + 1, s); } - else if (id == k_ARM64) + else if (id == k_ARM64 || id == k_RISCV) { - name = "ARM64"; + name = id == k_ARM64 ? "ARM64" : "RISCV"; if (propsSize == 4) ConvertUInt32ToString(GetUi32(props), s); /* @@ -666,6 +667,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val #endif #endif + default: break; } // return prop.Detach(value); return S_OK; diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h index b1c0466..ed535f7 100644 --- a/CPP/7zip/Archive/7z/7zHandler.h +++ b/CPP/7zip/Archive/7z/7zHandler.h @@ -54,11 +54,13 @@ public: CBoolPair Write_Attrib; bool _useMultiThreadMixer; - bool _removeSfxBlock; - // bool _volumeMode; + UInt32 _decoderCompatibilityVersion; + CUIntVector _enabledFilters; + CUIntVector _disabledFilters; + void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } void InitSolid() diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp index ff8735f..ea5ea0f 100644 --- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp @@ -20,6 +20,9 @@ using namespace NWindows; namespace NArchive { namespace N7z { +static const UInt32 k_decoderCompatibilityVersion = 2301; +// 7-Zip version 2301 supports ARM64 filter + #define k_LZMA_Name "LZMA" #define kDefaultMethodName "LZMA2" #define k_Copy_Name "Copy" @@ -774,6 +777,11 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt options.MaxFilter = (level >= 8); options.AnalysisLevel = GetAnalysisLevel(); + options.SetFilterSupporting_ver_enabled_disabled( + _decoderCompatibilityVersion, + _enabledFilters, + _disabledFilters); + options.HeaderOptions.CompressMainHeader = compressMainHeader; /* options.HeaderOptions.WriteCTime = Write_CTime; @@ -858,6 +866,10 @@ void COutHandler::InitProps7z() InitSolid(); _useTypeSorting = false; + + _decoderCompatibilityVersion = k_decoderCompatibilityVersion; + _enabledFilters.Clear(); + _disabledFilters.Clear(); } void COutHandler::InitProps() @@ -944,6 +956,29 @@ static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest) return S_OK; } +struct C_Id_Name_pair +{ + UInt32 Id; + const char *Name; +}; + +static const C_Id_Name_pair g_filter_pairs[] = +{ + { k_Delta, "Delta" }, + { k_ARM64, "ARM64" }, + { k_RISCV, "RISCV" }, + { k_SWAP2, "SWAP2" }, + { k_SWAP4, "SWAP4" }, + { k_BCJ, "BCJ" }, + { k_BCJ2 , "BCJ2" }, + { k_PPC, "PPC" }, + { k_IA64, "IA64" }, + { k_ARM, "ARM" }, + { k_ARMT, "ARMT" }, + { k_SPARC, "SPARC" } +}; + + HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; @@ -1004,6 +1039,43 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting); + if (name.IsPrefixedBy_Ascii_NoCase("yv")) + { + name.Delete(0, 2); + UInt32 v = 1 << 16; // if no number is noit specified, we use big value + RINOK(ParsePropToUInt32(name, value, v)) + _decoderCompatibilityVersion = v; + // if (v == 0) _decoderCompatibilityVersion = k_decoderCompatibilityVersion; + return S_OK; + } + + if (name.IsPrefixedBy_Ascii_NoCase("yf")) + { + name.Delete(0, 2); + CUIntVector *vec; + if (name.IsEqualTo_Ascii_NoCase("a")) vec = &_enabledFilters; + else if (name.IsEqualTo_Ascii_NoCase("d")) vec = &_disabledFilters; + else return E_INVALIDARG; + + if (value.vt != VT_BSTR) + return E_INVALIDARG; + for (unsigned k = 0;; k++) + { + if (k == Z7_ARRAY_SIZE(g_filter_pairs)) + { + // maybe we can ignore unsupported filter names here? + return E_INVALIDARG; + } + const C_Id_Name_pair &pair = g_filter_pairs[k]; + if (StringsAreEqualNoCase_Ascii(value.bstrVal, pair.Name)) + { + vec->AddToUniqueSorted(pair.Id); + break; + } + } + return S_OK; + } + // if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode); } return CMultiMethodProps::SetProperty(name, value); diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h index bd96ca3..22e7960 100644 --- a/CPP/7zip/Archive/7z/7zHeader.h +++ b/CPP/7zip/Archive/7z/7zHeader.h @@ -100,6 +100,7 @@ namespace NID const UInt32 k_Copy = 0; const UInt32 k_Delta = 3; const UInt32 k_ARM64 = 0xa; +const UInt32 k_RISCV = 0xb; const UInt32 k_LZMA2 = 0x21; @@ -126,7 +127,7 @@ const UInt32 k_AES = 0x6F10701; // const UInt32 k_ZSTD = 0x4015D; // winzip zstd // 0x4F71101, 7z-zstd -static inline bool IsFilterMethod(UInt64 m) +inline bool IsFilterMethod(UInt64 m) { if (m > (UInt32)0xFFFFFFFF) return false; @@ -134,6 +135,7 @@ static inline bool IsFilterMethod(UInt64 m) { case k_Delta: case k_ARM64: + case k_RISCV: case k_BCJ: case k_BCJ2: case k_PPC: @@ -144,6 +146,7 @@ static inline bool IsFilterMethod(UInt64 m) case k_SWAP2: case k_SWAP4: return true; + default: break; } return false; } diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp index 4defd27..e2efc52 100644 --- a/CPP/7zip/Archive/7z/7zIn.cpp +++ b/CPP/7zip/Archive/7z/7zIn.cpp @@ -32,37 +32,45 @@ using namespace NWindows; using namespace NCOM; -namespace NArchive { -namespace N7z { - -#define k_Scan_NumCoders_MAX 64 -#define k_Scan_NumCodersStreams_in_Folder_MAX 64 - unsigned BoolVector_CountSum(const CBoolVector &v); +Z7_NO_INLINE unsigned BoolVector_CountSum(const CBoolVector &v) { unsigned sum = 0; const unsigned size = v.Size(); - for (unsigned i = 0; i < size; i++) - if (v[i]) - sum++; + if (size) + { + const bool *p = v.ConstData(); + const bool * const lim = p + size; + do + if (*p) + sum++; + while (++p != lim); + } return sum; } static inline bool BoolVector_Item_IsValidAndTrue(const CBoolVector &v, unsigned i) { - return (i < v.Size() ? v[i] : false); + return i < v.Size() ? v[i] : false; } +Z7_NO_INLINE static void BoolVector_Fill_False(CBoolVector &v, unsigned size) { v.ClearAndSetSize(size); - bool *p = &v[0]; + bool *p = v.NonConstData(); for (unsigned i = 0; i < size; i++) p[i] = false; } +namespace NArchive { +namespace N7z { + +#define k_Scan_NumCoders_MAX 64 +#define k_Scan_NumCodersStreams_in_Folder_MAX 64 + class CInArchiveException {}; class CUnsupportedFeatureException: public CInArchiveException {}; @@ -510,7 +518,7 @@ void CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const { const size_t startPos = FoCodersDataOffset[folderIndex]; CInByte2 inByte; - inByte.Init(CodersData + startPos, FoCodersDataOffset[folderIndex + 1] - startPos); + inByte.Init(CodersData.ConstData() + startPos, FoCodersDataOffset[folderIndex + 1] - startPos); inByte.ParseFolder(folder); if (inByte.GetRem() != 0) throw 20120424; @@ -1177,8 +1185,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( ThrowUnsupported(); data.Alloc(unpackSize); - CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; - CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; + CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStreamSpec; outStreamSpec->Init(data, unpackSize); bool dataAfterEnd_Error = false; @@ -1189,7 +1196,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( folders, i, NULL, // &unpackSize64 - outStream, + outStreamSpec, NULL, // *compressProgress NULL // **inStreamMainRes @@ -1280,7 +1287,7 @@ HRESULT CInArchive::ReadHeader( CBoolVector emptyStreamVector; CBoolVector emptyFileVector; CBoolVector antiFileVector; - CNum numEmptyStreams = 0; + unsigned numEmptyStreams = 0; for (;;) { @@ -1311,7 +1318,7 @@ HRESULT CInArchive::ReadHeader( for (i = 0; i < numFiles; i++) { const size_t curRem = (rem - pos) / 2; - const UInt16 *buf = (const UInt16 *)(const void *)(db.NamesBuf + pos); + const UInt16 *buf = (const UInt16 *)(const void *)(db.NamesBuf.ConstData() + pos); size_t j; for (j = 0; j < curRem && buf[j] != 0; j++); if (j == curRem) @@ -1457,7 +1464,7 @@ HRESULT CInArchive::ReadHeader( CNum emptyFileIndex = 0; CNum sizeIndex = 0; - const CNum numAntiItems = BoolVector_CountSum(antiFileVector); + const unsigned numAntiItems = BoolVector_CountSum(antiFileVector); if (numAntiItems != 0) db.IsAnti.ClearAndSetSize(numFiles); @@ -1649,7 +1656,7 @@ HRESULT CInArchive::ReadDatabase2( if (nextHeaderSize == 0) { - if (nextHeaderOffset != 0) + if (nextHeaderOffset != 0 || nextHeaderCRC != 0) return S_FALSE; db.IsArc = true; db.HeadersSize = HeadersSize; diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h index a9c14fb..ddbe020 100644 --- a/CPP/7zip/Archive/7z/7zIn.h +++ b/CPP/7zip/Archive/7z/7zIn.h @@ -273,33 +273,36 @@ struct CDbEx: public CDatabase void FillLinks(); - UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const + UInt64 GetFolderStreamPos(size_t folderIndex, size_t indexInFolder) const { - return ArcInfo.DataStartPosition + - PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder]; + return ArcInfo.DataStartPosition + PackPositions.ConstData() + [FoStartPackStreamIndex.ConstData()[folderIndex] + indexInFolder]; } - UInt64 GetFolderFullPackSize(CNum folderIndex) const + UInt64 GetFolderFullPackSize(size_t folderIndex) const { return - PackPositions[FoStartPackStreamIndex[folderIndex + 1]] - - PackPositions[FoStartPackStreamIndex[folderIndex]]; + PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex + 1]] - + PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex]]; } - UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const + UInt64 GetFolderPackStreamSize(size_t folderIndex, size_t streamIndex) const { - size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex; - return PackPositions[i + 1] - PackPositions[i]; + const size_t i = FoStartPackStreamIndex.ConstData()[folderIndex] + streamIndex; + return PackPositions.ConstData()[i + 1] - + PackPositions.ConstData()[i]; } - UInt64 GetFilePackSize(CNum fileIndex) const + /* + UInt64 GetFilePackSize(size_t fileIndex) const { - CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; + const CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex != kNumNoIndex) if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); return 0; } + */ }; const unsigned kNumBufLevelsMax = 4; diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h index e8c68be..06737c8 100644 --- a/CPP/7zip/Archive/7z/7zItem.h +++ b/CPP/7zip/Archive/7z/7zItem.h @@ -129,7 +129,7 @@ struct CUInt32DefVector bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; } void SetItem(unsigned index, bool defined, UInt32 value); - void if_NonEmpty_FillResedue_with_false(unsigned numItems) + void if_NonEmpty_FillResidue_with_false(unsigned numItems) { if (Defs.Size() != 0 && Defs.Size() < numItems) SetItem(numItems - 1, false, 0); diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp index 7f8fa5b..d0c8cf2 100644 --- a/CPP/7zip/Archive/7z/7zOut.cpp +++ b/CPP/7zip/Archive/7z/7zOut.cpp @@ -3,14 +3,34 @@ #include "StdAfx.h" #include "../../../../C/7zCrc.h" +#include "../../../../C/CpuArch.h" #include "../../../Common/AutoPtr.h" // #include "../../../Common/UTFConvert.h" #include "../../Common/StreamObjects.h" +#include "../Common/OutStreamWithCRC.h" #include "7zOut.h" +unsigned BoolVector_CountSum(const CBoolVector &v); + +static UInt64 UInt64Vector_CountSum(const CRecordVector<UInt64> &v) +{ + UInt64 sum = 0; + const unsigned size = v.Size(); + if (size) + { + const UInt64 *p = v.ConstData(); + const UInt64 * const lim = p + size; + do + sum += *p++; + while (p != lim); + } + return sum; +} + + namespace NArchive { namespace N7z { @@ -133,7 +153,7 @@ void COutArchive::WriteBytes(const void *data, size_t size) else if (_writeToStream) { _outByte.WriteBytes(data, size); - _crc = CrcUpdate(_crc, data, size); + // _crc = CrcUpdate(_crc, data, size); } else _outByte2.WriteBytes(data, size); @@ -144,14 +164,12 @@ void COutArchive::WriteByte(Byte b) if (_countMode) _countSize++; else if (_writeToStream) - { - _outByte.WriteByte(b); - _crc = CRC_UPDATE_BYTE(_crc, b); - } + WriteByte_ToStream(b); else _outByte2.WriteByte(b); } +/* void COutArchive::WriteUInt32(UInt32 value) { for (int i = 0; i < 4; i++) @@ -169,6 +187,7 @@ void COutArchive::WriteUInt64(UInt64 value) value >>= 8; } } +*/ void COutArchive::WriteNumber(UInt64 value) { @@ -288,7 +307,7 @@ void COutArchive::WriteFolder(const CFolder &folder) WriteNumber(folder.PackStreams[i]); } -void COutArchive::WriteBoolVector(const CBoolVector &boolVector) +void COutArchive::Write_BoolVector(const CBoolVector &boolVector) { Byte b = 0; Byte mask = 0x80; @@ -314,31 +333,32 @@ void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector) { WriteByte(id); WriteNumber(Bv_GetSizeInBytes(boolVector)); - WriteBoolVector(boolVector); + Write_BoolVector(boolVector); +} + +void COutArchive::Write_BoolVector_numDefined(const CBoolVector &boolVector, unsigned numDefined) +{ + if (numDefined == boolVector.Size()) + WriteByte(1); + else + { + WriteByte(0); + Write_BoolVector(boolVector); + } } -unsigned BoolVector_CountSum(const CBoolVector &v); void COutArchive::WriteHashDigests(const CUInt32DefVector &digests) { const unsigned numDefined = BoolVector_CountSum(digests.Defs); if (numDefined == 0) return; - WriteByte(NID::kCRC); - if (numDefined == digests.Defs.Size()) - WriteByte(1); - else - { - WriteByte(0); - WriteBoolVector(digests.Defs); - } - - for (unsigned i = 0; i < digests.Defs.Size(); i++) - if (digests.Defs[i]) - WriteUInt32(digests.Vals[i]); + Write_BoolVector_numDefined(digests.Defs, numDefined); + Write_UInt32DefVector_numDefined(digests, numDefined); } + void COutArchive::WritePackInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, @@ -467,17 +487,42 @@ void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, B WriteByte(type); WriteNumber(dataSize); - if (numDefined == v.Size()) - WriteByte(1); - else + Write_BoolVector_numDefined(v, numDefined); + WriteByte(0); // 0 means no switching to external stream +} + + +void COutArchive::Write_UInt32DefVector_numDefined(const CUInt32DefVector &v, unsigned numDefined) +{ + if (_countMode) { - WriteByte(0); - WriteBoolVector(v); + _countSize += (size_t)numDefined * 4; + return; } - WriteByte(0); // 0 means no switching to external stream + + const bool * const defs = v.Defs.ConstData(); + const UInt32 * const vals = v.Vals.ConstData(); + const size_t num = v.Defs.Size(); + + for (size_t i = 0; i < num; i++) + if (defs[i]) + { + UInt32 value = vals[i]; + for (int k = 0; k < 4; k++) + { + if (_writeToStream) + WriteByte_ToStream((Byte)value); + else + _outByte2.WriteByte((Byte)value); + // WriteByte((Byte)value); + value >>= 8; + } + // WriteUInt32(v.Vals[i]); + } } -void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) + +void COutArchive::Write_UInt64DefVector_type(const CUInt64DefVector &v, Byte type) { const unsigned numDefined = BoolVector_CountSum(v.Defs); if (numDefined == 0) @@ -485,18 +530,40 @@ void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) WriteAlignedBools(v.Defs, numDefined, type, 3); - for (unsigned i = 0; i < v.Defs.Size(); i++) - if (v.Defs[i]) - WriteUInt64(v.Vals[i]); + if (_countMode) + { + _countSize += (size_t)numDefined * 8; + return; + } + + const bool * const defs = v.Defs.ConstData(); + const UInt64 * const vals = v.Vals.ConstData(); + const size_t num = v.Defs.Size(); + + for (size_t i = 0; i < num; i++) + if (defs[i]) + { + UInt64 value = vals[i]; + for (int k = 0; k < 8; k++) + { + if (_writeToStream) + WriteByte_ToStream((Byte)value); + else + _outByte2.WriteByte((Byte)value); + // WriteByte((Byte)value); + value >>= 8; + } + // WriteUInt64(v.Vals[i]); + } } + HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders) { - CBufInStream *streamSpec = new CBufInStream; - CMyComPtr<ISequentialInStream> stream = streamSpec; + CMyComPtr2_Create<ISequentialInStream, CBufInStream> streamSpec; streamSpec->Init(data, data.Size()); outFolders.FolderUnpackCRCs.Defs.Add(true); outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size())); @@ -505,7 +572,7 @@ HRESULT COutArchive::EncodeStream( const UInt64 expectSize = data.Size(); RINOK(encoder.Encode1( EXTERNAL_CODECS_LOC_VARS - stream, + streamSpec, // NULL, &dataSize64, // inSizeForReduce expectSize, @@ -528,13 +595,7 @@ void COutArchive::WriteHeader( */ _useAlign = true; - { - UInt64 packSize = 0; - FOR_VECTOR (i, db.PackSizes) - packSize += db.PackSizes[i]; - headerOffset = packSize; - } - + headerOffset = UInt64Vector_CountSum(db.PackSizes); WriteByte(NID::kHeader); @@ -655,81 +716,97 @@ void COutArchive::WriteHeader( { /* ---------- Names ---------- */ - unsigned numDefined = 0; size_t namesDataSize = 0; - FOR_VECTOR (i, db.Files) { - const UString &name = db.Names[i]; - if (!name.IsEmpty()) - numDefined++; - const size_t numUtfChars = - /* - #if WCHAR_MAX > 0xffff + FOR_VECTOR (i, db.Files) + { + const UString &name = db.Names[i]; + const size_t numUtfChars = + /* + #if WCHAR_MAX > 0xffff Get_Num_Utf16_chars_from_wchar_string(name.Ptr()); - #else - */ + #else + */ name.Len(); - // #endif - namesDataSize += (numUtfChars + 1) * 2; + // #endif + namesDataSize += numUtfChars; + } } - - if (numDefined > 0) + if (namesDataSize) { - namesDataSize++; + namesDataSize += db.Files.Size(); // we will write tail zero wchar for each name + namesDataSize *= 2; // 2 bytes per wchar for UTF16 encoding + namesDataSize++; // for additional switch byte (zero value) SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4); - WriteByte(NID::kName); WriteNumber(namesDataSize); - WriteByte(0); - FOR_VECTOR (i, db.Files) + + if (_countMode) + _countSize += namesDataSize; + else { - const UString &name = db.Names[i]; - for (unsigned t = 0; t <= name.Len(); t++) + WriteByte(0); + FOR_VECTOR (i, db.Files) { - wchar_t c = name[t]; - - /* - #if WCHAR_MAX > 0xffff - if (c >= 0x10000) + const UString &name = db.Names[i]; + const wchar_t *p = name.Ptr(); + const size_t len = (size_t)name.Len() + 1; + const wchar_t * const lim = p + len; + if (_writeToStream) { - c -= 0x10000; - if (c < (1 << 20)) + do { - unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF); - WriteByte((Byte)c0); - WriteByte((Byte)(c0 >> 8)); - c = 0xdc00 + (c & 0x3FF); + const wchar_t c = *p++; + WriteByte_ToStream((Byte)c); + WriteByte_ToStream((Byte)(c >> 8)); } - else - c = '_'; // we change character unsupported by UTF16 + while (p != lim); + } + else + { + Byte *dest = _outByte2.GetDest_and_Update(len * 2); + do + { + /* + #if WCHAR_MAX > 0xffff + if (c >= 0x10000) + { + c -= 0x10000; + if (c < (1 << 20)) + { + unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF); + WriteByte((Byte)c0); + WriteByte((Byte)(c0 >> 8)); + c = 0xdc00 + (c & 0x3FF); + } + else + c = '_'; // we change character unsupported by UTF16 + } + #endif + */ + const wchar_t c = *p++; + SetUi16(dest, (UInt16)c) + dest += 2; + } + while (p != lim); } - #endif - */ - - WriteByte((Byte)c); - WriteByte((Byte)(c >> 8)); } } } } - /* if (headerOptions.WriteCTime) */ WriteUInt64DefVector(db.CTime, NID::kCTime); - /* if (headerOptions.WriteATime) */ WriteUInt64DefVector(db.ATime, NID::kATime); - /* if (headerOptions.WriteMTime) */ WriteUInt64DefVector(db.MTime, NID::kMTime); - WriteUInt64DefVector(db.StartPos, NID::kStartPos); + /* if (headerOptions.WriteCTime) */ Write_UInt64DefVector_type(db.CTime, NID::kCTime); + /* if (headerOptions.WriteATime) */ Write_UInt64DefVector_type(db.ATime, NID::kATime); + /* if (headerOptions.WriteMTime) */ Write_UInt64DefVector_type(db.MTime, NID::kMTime); + Write_UInt64DefVector_type(db.StartPos, NID::kStartPos); { /* ---------- Write Attrib ---------- */ const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs); - if (numDefined != 0) { WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2); - FOR_VECTOR (i, db.Attrib.Defs) - { - if (db.Attrib.Defs[i]) - WriteUInt32(db.Attrib.Vals[i]); - } + Write_UInt32DefVector_numDefined(db.Attrib, numDefined); } } @@ -765,13 +842,7 @@ void COutArchive::WriteHeader( WriteByte(NID::kParent); WriteNumber(dataSize); - if (numIsDir == boolVector.Size()) - WriteByte(1); - else - { - WriteByte(0); - WriteBoolVector(boolVector); - } + Write_BoolVector_numDefined(boolVector, numIsDir); for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; @@ -818,17 +889,17 @@ HRESULT COutArchive::WriteDatabase( if (!db.CheckNumFiles()) return E_FAIL; - UInt64 headerOffset; - UInt32 headerCRC; - UInt64 headerSize; - if (db.IsEmpty()) - { - headerSize = 0; - headerOffset = 0; - headerCRC = CrcCalc(NULL, 0); - } - else + CStartHeader sh; + sh.NextHeaderOffset = 0; + sh.NextHeaderSize = 0; + sh.NextHeaderCRC = 0; // CrcCalc(NULL, 0); + + if (!db.IsEmpty()) { + CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> crcStream; + crcStream->SetStream(SeqStream); + crcStream->Init(); + bool encodeHeaders = false; if (options) if (options->IsEmpty()) @@ -837,13 +908,15 @@ HRESULT COutArchive::WriteDatabase( if (options->PasswordIsDefined || headerOptions.CompressMainHeader) encodeHeaders = true; - _outByte.SetStream(SeqStream); + if (!_outByte.Create(1 << 16)) + return E_OUTOFMEMORY; + _outByte.SetStream(crcStream.Interface()); _outByte.Init(); - _crc = CRC_INIT_VAL; + // _crc = CRC_INIT_VAL; _countMode = encodeHeaders; _writeToStream = true; _countSize = 0; - WriteHeader(db, /* headerOptions, */ headerOffset); + WriteHeader(db, /* headerOptions, */ sh.NextHeaderOffset); if (encodeHeaders) { @@ -852,7 +925,7 @@ HRESULT COutArchive::WriteDatabase( _countMode = false; _writeToStream = false; - WriteHeader(db, /* headerOptions, */ headerOffset); + WriteHeader(db, /* headerOptions, */ sh.NextHeaderOffset); if (_countSize != _outByte2.GetPos()) return E_FAIL; @@ -876,15 +949,17 @@ HRESULT COutArchive::WriteDatabase( throw 1; WriteID(NID::kEncodedHeader); - WritePackInfo(headerOffset, packSizes, CUInt32DefVector()); + WritePackInfo(sh.NextHeaderOffset, packSizes, CUInt32DefVector()); WriteUnpackInfo(folders, outFolders); WriteByte(NID::kEnd); - FOR_VECTOR (i, packSizes) - headerOffset += packSizes[i]; + + sh.NextHeaderOffset += UInt64Vector_CountSum(packSizes); } RINOK(_outByte.Flush()) - headerCRC = CRC_GET_DIGEST(_crc); - headerSize = _outByte.GetProcessedSize(); + sh.NextHeaderCRC = crcStream->GetCRC(); + // sh.NextHeaderCRC = CRC_GET_DIGEST(_crc); + // if (CRC_GET_DIGEST(_crc) != sh.NextHeaderCRC) throw 1; + sh.NextHeaderSize = _outByte.GetProcessedSize(); } #ifdef Z7_7Z_VOL if (_endMarker) @@ -904,12 +979,8 @@ HRESULT COutArchive::WriteDatabase( #endif if (Stream) { - CStartHeader h; - h.NextHeaderSize = headerSize; - h.NextHeaderCRC = headerCRC; - h.NextHeaderOffset = headerOffset; RINOK(Stream->Seek((Int64)_signatureHeaderPos, STREAM_SEEK_SET, NULL)) - return WriteStartHeader(h); + return WriteStartHeader(sh); } return S_OK; } diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h index 940cafc..c65d268 100644 --- a/CPP/7zip/Archive/7z/7zOut.h +++ b/CPP/7zip/Archive/7z/7zOut.h @@ -19,32 +19,41 @@ const unsigned k_StartHeadersRewriteSize = 32; class CWriteBufferLoc { Byte *_data; - size_t _size; - size_t _pos; + Byte *_dataLim; + Byte *_dataBase; public: - CWriteBufferLoc(): _size(0), _pos(0) {} + // CWriteBufferLoc(): _data(NULL), _dataLim(NULL), _dataBase(NULL) {} void Init(Byte *data, size_t size) { _data = data; - _size = size; - _pos = 0; + _dataBase = data; + _dataLim = data + size; + } + + Byte *GetDest_and_Update(size_t size) + { + Byte *dest = _data; + if (size > (size_t)(_dataLim - dest)) + throw 1; + _data = dest + size; + return dest; } void WriteBytes(const void *data, size_t size) { if (size == 0) return; - if (size > _size - _pos) - throw 1; - memcpy(_data + _pos, data, size); - _pos += size; + Byte *dest = GetDest_and_Update(size); + memcpy(dest, data, size); } void WriteByte(Byte b) { - if (_size == _pos) + Byte *dest = _data; + if (dest == _dataLim) throw 1; - _data[_pos++] = b; + *dest++ = b; + _data = dest; } - size_t GetPos() const { return _pos; } + size_t GetPos() const { return (size_t)(_data - _dataBase); } }; @@ -248,14 +257,20 @@ class COutArchive void WriteBytes(const void *data, size_t size); void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); } void WriteByte(Byte b); - void WriteUInt32(UInt32 value); - void WriteUInt64(UInt64 value); + void WriteByte_ToStream(Byte b) + { + _outByte.WriteByte(b); + // _crc = CRC_UPDATE_BYTE(_crc, b); + } + // void WriteUInt32(UInt32 value); + // void WriteUInt64(UInt64 value); void WriteNumber(UInt64 value); void WriteID(UInt64 value) { WriteNumber(value); } void WriteFolder(const CFolder &folder); HRESULT WriteFileHeader(const CFileItem &itemInfo); - void WriteBoolVector(const CBoolVector &boolVector); + void Write_BoolVector(const CBoolVector &boolVector); + void Write_BoolVector_numDefined(const CBoolVector &boolVector, unsigned numDefined); void WritePropBoolVector(Byte id, const CBoolVector &boolVector); void WriteHashDigests(const CUInt32DefVector &digests); @@ -277,7 +292,8 @@ class COutArchive void SkipToAligned(unsigned pos, unsigned alignShifts); void WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts); - void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type); + void Write_UInt32DefVector_numDefined(const CUInt32DefVector &v, unsigned numDefined); + void Write_UInt64DefVector_type(const CUInt64DefVector &v, Byte type); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS @@ -294,7 +310,7 @@ class COutArchive #ifdef Z7_7Z_VOL bool _endMarker; #endif - UInt32 _crc; + // UInt32 _crc; size_t _countSize; CWriteBufferLoc _outByte2; COutBuffer _outByte; @@ -310,7 +326,7 @@ class COutArchive public: CMyComPtr<ISequentialOutStream> SeqStream; - COutArchive() { _outByte.Create(1 << 16); } + // COutArchive(); HRESULT Create_and_WriteStartPrefix(ISequentialOutStream *stream /* , bool endMarker */); void Close(); HRESULT WriteDatabase( diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index 4e9ea5d..d374a00 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -33,7 +33,7 @@ struct CFilterMode UInt32 Id; UInt32 Delta; // required File Size alignment, if Id is not k_Delta. // (Delta == 0) means unknown alignment - UInt32 Offset; // for k_ARM64 + UInt32 Offset; // for k_ARM64 / k_RISCV // UInt32 AlignSizeOpt; // for k_ARM64 CFilterMode(): @@ -59,7 +59,7 @@ struct CFilterMode Delta = 16; else if (Id == k_ARM64 || Id == k_ARM || Id == k_PPC || Id == k_SPARC) Delta = 4; - else if (Id == k_ARMT) + else if (Id == k_ARMT || Id == k_RISCV) Delta = 2; else if (Id == k_BCJ || Id == k_BCJ2) Delta = 1; // do we need it? @@ -95,7 +95,9 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) return 0; p += 4; - switch (GetUi16(p)) + const unsigned machine = GetUi16(p); + + switch (machine) { case 0x014C: case 0x8664: filterId = k_X86; break; @@ -112,11 +114,16 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) case 0x01C2: filterId = k_ARM; break; // WinCE new case 0x01C4: filterId = k_ARMT; break; // WinRT + case 0x5032: // RISCV32 + case 0x5064: // RISCV64 + // case 0x5128: // RISCV128 + filterId = k_RISCV; break; + case 0x0200: filterId = k_IA64; break; default: return 0; } - // const UInt32 numSections = GetUi16(p + 2); + const UInt32 numSections = GetUi16(p + 2); optHeaderSize = GetUi16(p + 16); if (optHeaderSize > (1 << 10)) return 0; @@ -132,34 +139,49 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) return 0; } - /* // Windows exe file sizes are not aligned for 4 KiB. // So we can't use (CFilterMode::Offset != 0) in solid archives. // So we just don't set Offset here. #define NUM_SCAN_SECTIONS_MAX (1 << 6) -#define EXE_SECTION_OFFSET_MAX (1 << 27) -#define EXE_SECTION_SIZE_MIN (1 << 8) -#define EXE_SECTION_SIZE_MAX (1 << 27) +// #define EXE_SECTION_OFFSET_MAX (1 << 27) +// #define EXE_SECTION_SIZE_MIN (1 << 8) +// #define EXE_SECTION_SIZE_MAX (1 << 27) #define PE_SectHeaderSize 40 -#define PE_SECT_EXECUTE 0x20000000 +// #define PE_SECT_EXECUTE 0x20000000 +/* if (numSections > NUM_SCAN_SECTIONS_MAX) return 0; +*/ + if ((size_t)(p - buf) + optHeaderSize <= size) + { p += optHeaderSize; +/* // UInt32 numExeSections = 0; // bool execute_finded = false; // UInt32 sect_va = 0; // UInt32 sect_size = 0; // UInt32 sect_offset = 0; - +*/ + if (numSections <= NUM_SCAN_SECTIONS_MAX) + if (machine == 0x8664) for (UInt32 i = 0; i < numSections - // && numExeSections < numSectionsMax ; i++, p += PE_SectHeaderSize) { - UInt32 characts, rawSize, offset; + // UInt32 characts, rawSize, offset; if ((UInt32)(p - buf) + PE_SectHeaderSize > size) - return 0; + { + // return 0; + break; + } + if (memcmp(p, ".a64xrm", 8) == 0) + { + // ARM64EC + filterId = k_ARM64; + break; + } +/* rawSize = GetUi32(p + 16); offset = GetUi32(p + 20); characts = GetUi32(p + 36); @@ -178,8 +200,11 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) break; } } +*/ + } } + /* filterMode->Offset = 0; if (filterId == k_ARM64) { @@ -243,8 +268,9 @@ static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode) case 43: filterId = k_SPARC; break; case 20: case 21: if (!be) return 0; filterId = k_PPC; break; - case 40: if ( be) return 0; filterId = k_ARM; break; + case 40: if (be) return 0; filterId = k_ARM; break; case 183: if (be) return 0; filterId = k_ARM64; break; + case 243: if (be) return 0; filterId = k_RISCV; break; /* Some IA-64 ELF executables have size that is not aligned for 16 bytes. So we don't use IA-64 filter for IA-64 ELF */ @@ -482,6 +508,7 @@ static inline bool IsExeFilter(CMethodId m) switch (m) { case k_ARM64: + case k_RISCV: case k_BCJ: case k_BCJ2: case k_ARM: @@ -490,6 +517,7 @@ static inline bool IsExeFilter(CMethodId m) case k_SPARC: case k_IA64: return true; + default: break; } return false; } @@ -521,7 +549,8 @@ static unsigned Get_FilterGroup_for_Folder( if (m.Id == k_BCJ2) m.Id = k_BCJ; m.SetDelta(); - if (m.Id == k_ARM64) + if (m.Id == k_ARM64 || + m.Id == k_RISCV) if (coder.Props.Size() == 4) m.Offset = GetUi32(coder.Props); } @@ -537,15 +566,12 @@ static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, UInt64 position, UInt64 size, ICompressProgressInfo *progress) { RINOK(InStream_SeekSet(inStream, position)) - CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; - CMyComPtr<ISequentialInStream> inStreamLimited(streamSpec); + CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> streamSpec; streamSpec->SetStream(inStream); streamSpec->Init(size); - - NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; - CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; - RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)) - return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL); + CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder; + RINOK(copyCoder.Interface()->Code(streamSpec, outStream, NULL, NULL, progress)) + return (copyCoder->TotalSize == size ? S_OK : E_FAIL); } /* @@ -759,9 +785,9 @@ struct CRefItem { if (sortByType) { - int slashPos = ui.Name.ReverseFind_PathSepar(); + const int slashPos = ui.Name.ReverseFind_PathSepar(); NamePos = (unsigned)(slashPos + 1); - int dotPos = ui.Name.ReverseFind_Dot(); + const int dotPos = ui.Name.ReverseFind_Dot(); if (dotPos <= slashPos) ExtensionPos = ui.Name.Len(); else @@ -772,7 +798,7 @@ struct CRefItem AString s; for (unsigned pos = ExtensionPos;; pos++) { - wchar_t c = ui.Name[pos]; + const wchar_t c = ui.Name[pos]; if (c >= 0x80) break; if (c == 0) @@ -780,7 +806,7 @@ struct CRefItem ExtensionIndex = GetExtIndex(s); break; } - s += (char)MyCharLower_Ascii((char)c); + s.Add_Char((char)MyCharLower_Ascii((char)c)); } } } @@ -1123,6 +1149,12 @@ HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMo #ifdef MY_CPU_ARM64 filterModeTemp.Id = k_ARM64; #endif + #ifdef MY_CPU_RISCV + filterModeTemp.Id = k_RISCV; + #endif + #ifdef MY_CPU_SPARC + filterModeTemp.Id = k_SPARC; + #endif parseRes = true; } @@ -1172,6 +1204,8 @@ static inline void GetMethodFull(UInt64 methodID, UInt32 numStreams, CMethodFull m.NumStreams = numStreams; } + +// we add bond for mode.Methods[0] that is filter static HRESULT AddBondForFilter(CCompressionMethodMode &mode) { for (unsigned c = 1; c < mode.Methods.Size(); c++) @@ -1189,16 +1223,19 @@ static HRESULT AddBondForFilter(CCompressionMethodMode &mode) return E_INVALIDARG; } -static HRESULT AddFilterBond(CCompressionMethodMode &mode) +/* +static HRESULT AddBondForFilter_if_ThereAreBonds(CCompressionMethodMode &mode) { if (!mode.Bonds.IsEmpty()) return AddBondForFilter(mode); return S_OK; } +*/ static HRESULT AddBcj2Methods(CCompressionMethodMode &mode) { // mode.Methods[0] must be k_BCJ2 method ! + // mode.Methods[1] : we expect that there is at least one method after BCJ2 CMethodFull m; GetMethodFull(k_LZMA, 1, m); @@ -1210,7 +1247,7 @@ static HRESULT AddBcj2Methods(CCompressionMethodMode &mode) m.AddProp32(NCoderPropID::kLitContextBits, 0); // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2"); - unsigned methodIndex = mode.Methods.Size(); + const unsigned methodIndex = mode.Methods.Size(); if (mode.Bonds.IsEmpty()) { @@ -1229,109 +1266,140 @@ static HRESULT AddBcj2Methods(CCompressionMethodMode &mode) RINOK(AddBondForFilter(mode)) CBond2 bond; - bond.OutCoder = 0; + bond.OutCoder = 0; // index of BCJ2 coder bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond); bond.InCoder = methodIndex + 1; bond.OutStream = 2; mode.Bonds.Add(bond); return S_OK; } + static HRESULT MakeExeMethod(CCompressionMethodMode &mode, - const CFilterMode &filterMode, /* bool addFilter, */ bool bcj2Filter) + const CFilterMode &filterMode, + const bool bcj2_IsAllowed, + const CUIntVector &disabledFilterIDs) { if (mode.Filter_was_Inserted) { + // filter was inserted, but bond for that filter was not added still. const CMethodFull &m = mode.Methods[0]; - const CMethodId id = m.Id; - if (id == k_BCJ2) + if (m.Id == k_BCJ2) return AddBcj2Methods(mode); if (!m.IsSimpleCoder()) return E_NOTIMPL; - // if (Bonds.IsEmpty()) we can create bonds later - return AddFilterBond(mode); + if (mode.Bonds.IsEmpty()) + return S_OK; + return AddBondForFilter(mode); } if (filterMode.Id == 0) return S_OK; - CMethodFull &m = mode.Methods.InsertNew(0); + unsigned nextCoder; - { - FOR_VECTOR (k, mode.Bonds) - { - CBond2 &bond = mode.Bonds[k]; - bond.InCoder++; - bond.OutCoder++; - } - } + const bool useBcj2 = bcj2_IsAllowed + && Is86Filter(filterMode.Id) + && disabledFilterIDs.FindInSorted(k_BCJ2) < 0; - HRESULT res; - - if (bcj2Filter && Is86Filter(filterMode.Id)) + if (!useBcj2 && disabledFilterIDs.FindInSorted(filterMode.Id) >= 0) { - GetMethodFull(k_BCJ2, 4, m); - res = AddBcj2Methods(mode); + // required filter is disabled, + // but we still can use information about data alignment. +#if 0 // 1 for debug + // we can return here, if we want default lzma properties + return S_OK; +#else + // we will try to change lzma/lzma2 properties + nextCoder = 0; + if (!mode.Bonds.IsEmpty()) + for (unsigned c = 0;; c++) + { + if (c == mode.Methods.Size()) + return S_OK; + if (!mode.IsThereBond_to_Coder(c)) + { + nextCoder = c; + break; + } + } +#endif } else { + // we insert new filter method: + CMethodFull &m = mode.Methods.InsertNew(0); // 0 == index of new inserted item + { + // we move all coder indexes in bonds up for 1 position: + FOR_VECTOR (k, mode.Bonds) + { + CBond2 &bond = mode.Bonds[k]; + bond.InCoder++; + bond.OutCoder++; + } + } + if (useBcj2) + { + GetMethodFull(k_BCJ2, 4, m); + return AddBcj2Methods(mode); + } + GetMethodFull(filterMode.Id, 1, m); + if (filterMode.Id == k_Delta) m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta); - else if (filterMode.Id == k_ARM64) + else if (filterMode.Id == k_ARM64 + || filterMode.Id == k_RISCV) { // if (filterMode.Offset != 0) - m.AddProp32( - NCoderPropID::kDefaultProp, - // NCoderPropID::kBranchOffset, - filterMode.Offset); + m.AddProp32( + NCoderPropID::kDefaultProp, + // NCoderPropID::kBranchOffset, + filterMode.Offset); } - res = AddFilterBond(mode); - - int alignBits = -1; + + nextCoder = 1; + if (!mode.Bonds.IsEmpty()) { - const UInt32 delta = filterMode.Delta; - if (delta == 0 || delta > 16) - { - // if (delta == 0) alignBits = GetAlignForFilterMethod(filterMode.Id); - } - else if ((delta & ((1 << 4) - 1)) == 0) alignBits = 4; - else if ((delta & ((1 << 3) - 1)) == 0) alignBits = 3; - else if ((delta & ((1 << 2) - 1)) == 0) alignBits = 2; - else if ((delta & ((1 << 1) - 1)) == 0) alignBits = 1; - // else alignBits = 0; - /* alignBits=0 is default mode for lzma/lzma2. - So we don't set alignBits=0 here. */ + RINOK(AddBondForFilter(mode)) + nextCoder = mode.Bonds.Back().InCoder; } - if (res == S_OK && alignBits > 0) + } + + if (nextCoder >= mode.Methods.Size()) + { + // we don't expect that case, if there was non-filter method. + // but we return S_OK to support filter-only case. + return S_OK; + } + + int alignBits = -1; + { + const UInt32 delta = filterMode.Delta; + if (delta == 0 || delta > 16) { - unsigned nextCoder = 1; - if (!mode.Bonds.IsEmpty()) - { - nextCoder = mode.Bonds.Back().InCoder; - } - if (nextCoder < mode.Methods.Size()) - { - CMethodFull &nextMethod = mode.Methods[nextCoder]; - if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2) - { - if (!nextMethod.Are_Lzma_Model_Props_Defined()) - { - if (alignBits != 0) - { - if (alignBits > 2 || filterMode.Id == k_Delta) - nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits); - unsigned lc = 0; - if (alignBits < 3) - lc = (unsigned)(3 - alignBits); - nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc); - nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits); - } - } - } - } + // if (delta == 0) alignBits = GetAlignForFilterMethod(filterMode.Id); } + else if ((delta & ((1 << 4) - 1)) == 0) alignBits = 4; + else if ((delta & ((1 << 3) - 1)) == 0) alignBits = 3; + else if ((delta & ((1 << 2) - 1)) == 0) alignBits = 2; + else if ((delta & ((1 << 1) - 1)) == 0) alignBits = 1; + // else alignBits = 0; + /* alignBits=0 is default mode for lzma/lzma2. + So we don't set alignBits=0 here. */ } - - return res; + if (alignBits <= 0) + return S_OK; + // (alignBits > 0) + CMethodFull &nextMethod = mode.Methods[nextCoder]; + if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2) + if (!nextMethod.Are_Lzma_Model_Props_Defined()) + { + if (alignBits > 2 || filterMode.Id == k_Delta) + nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits); + const unsigned lc = (alignBits < 3) ? (unsigned)(3 - alignBits) : 0u; + nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc); + nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits); + } + return S_OK; } @@ -1859,6 +1927,7 @@ HRESULT Update( CIntArr fileIndexToUpdateIndexMap; UInt64 complexity = 0; + bool isThere_UnknownSize = false; UInt64 inSizeForReduce2 = 0; #ifndef Z7_NO_CRYPTO @@ -1971,28 +2040,36 @@ HRESULT Update( UInt64 inSizeForReduce = 0; { - bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0); + const bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0); FOR_VECTOR (i, updateItems) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { - complexity += ui.Size; - if (isSolid) - inSizeForReduce += ui.Size; - else if (inSizeForReduce < ui.Size) - inSizeForReduce = ui.Size; + if (ui.Size == (UInt64)(Int64)-1) + isThere_UnknownSize = true; + else + { + complexity += ui.Size; + if (isSolid) + inSizeForReduce += ui.Size; + else if (inSizeForReduce < ui.Size) + inSizeForReduce = ui.Size; + } } } } + if (isThere_UnknownSize) + inSizeForReduce = (UInt64)(Int64)-1; + else + RINOK(updateCallback->SetTotal(complexity)) + if (inSizeForReduce < inSizeForReduce2) - inSizeForReduce = inSizeForReduce2; + inSizeForReduce = inSizeForReduce2; - RINOK(updateCallback->SetTotal(complexity)) - CLocalProgress *lps = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> progress = lps; + CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; lps->Init(updateCallback, true); #ifndef Z7_ST @@ -2232,12 +2309,13 @@ HRESULT Update( CCompressionMethodMode method = *options.Method; { const HRESULT res = MakeExeMethod(method, filterMode, + // bcj2_IsAllowed: #ifdef Z7_ST false #else options.MaxFilter && options.MultiThreadMixer #endif - ); + , options.DisabledFilterIDs); RINOK(res) } @@ -2299,7 +2377,7 @@ HRESULT Update( const UInt64 packSize = db->GetFolderFullPackSize(folderIndex); RINOK(WriteRange(inStream, archive.SeqStream, - db->GetFolderStreamPos(folderIndex, 0), packSize, progress)) + db->GetFolderStreamPos(folderIndex, 0), packSize, lps)) lps->ProgressOffset += packSize; const unsigned folderIndex_New = newDatabase.Folders.Size(); @@ -2321,7 +2399,7 @@ HRESULT Update( size_t indexStart = db->FoToCoderUnpackSizes[folderIndex]; const size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1]; for (; indexStart < indexEnd; indexStart++) - newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]); + newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes.ConstData()[indexStart]); } else { @@ -2481,7 +2559,7 @@ HRESULT Update( sizeToEncode, // expectedDataSize newDatabase.Folders.AddNew(), // newDatabase.CoderUnpackSizes, curUnpackSize, - archive.SeqStream, newDatabase.PackSizes, progress); + archive.SeqStream, newDatabase.PackSizes, lps); if (encodeRes == k_My_HRESULT_CRC_ERROR) return E_FAIL; @@ -2680,8 +2758,7 @@ HRESULT Update( */ - CFolderInStream *inStreamSpec = new CFolderInStream; - CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec); + CMyComPtr2_Create<ISequentialInStream, CFolderInStream> inStreamSpec; // solidInStream; // inStreamSpec->_reportArcProp = reportArcProp; @@ -2702,13 +2779,13 @@ HRESULT Update( RINOK(encoder.Encode1( EXTERNAL_CODECS_LOC_VARS - solidInStream, + inStreamSpec, // NULL, &inSizeForReduce, expectedDataSize, // expected size newDatabase.Folders.AddNew(), // newDatabase.CoderUnpackSizes, curFolderUnpackSize, - archive.SeqStream, newDatabase.PackSizes, progress)) + archive.SeqStream, newDatabase.PackSizes, lps)) if (!inStreamSpec->WasFinished()) return E_FAIL; @@ -2970,7 +3047,7 @@ HRESULT Update( if (newDatabase.NumUnpackStreamsVector.Size() != numFolders || newDatabase.FolderUnpackCRCs.Defs.Size() > numFolders) return E_FAIL; - newDatabase.FolderUnpackCRCs.if_NonEmpty_FillResedue_with_false(numFolders); + newDatabase.FolderUnpackCRCs.if_NonEmpty_FillResidue_with_false(numFolders); } updateItems.ClearAndFree(); diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h index de4117a..83a2774 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.h +++ b/CPP/7zip/Archive/7z/7zUpdate.h @@ -111,6 +111,25 @@ struct CUpdateOptions CHeaderOptions HeaderOptions; + CUIntVector DisabledFilterIDs; + + void Add_DisabledFilter_for_id(UInt32 id, + const CUIntVector &enabledFilters) + { + if (enabledFilters.FindInSorted(id) < 0) + DisabledFilterIDs.AddToUniqueSorted(id); + } + + void SetFilterSupporting_ver_enabled_disabled( + UInt32 compatVer, + const CUIntVector &enabledFilters, + const CUIntVector &disabledFilters) + { + DisabledFilterIDs = disabledFilters; + if (compatVer < 2300) Add_DisabledFilter_for_id(k_ARM64, enabledFilters); + if (compatVer < 2402) Add_DisabledFilter_for_id(k_RISCV, enabledFilters); + } + CUpdateOptions(): Method(NULL), HeaderMethod(NULL), @@ -128,7 +147,9 @@ struct CUpdateOptions Need_MTime(false), Need_Attrib(false) // , Need_Crc(true) - {} + { + DisabledFilterIDs.Add(k_RISCV); + } }; HRESULT Update( |