Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2015-06-15 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:16:54 +0300
commit54490d51d5c6b0d794dcbad2d634d4c95fc25b6c (patch)
treec3c413656432c0ef87b2841c80e42b55ad17d4e8 /CPP/7zip/Archive
parent0713a3ab803e57401f18432148b4139e5fe6e5dd (diff)
15.0515.05
Diffstat (limited to 'CPP/7zip/Archive')
-rw-r--r--CPP/7zip/Archive/7z/7z.dsp8
-rw-r--r--CPP/7zip/Archive/7z/7zCompressionMode.h43
-rw-r--r--CPP/7zip/Archive/7z/7zDecode.cpp520
-rw-r--r--CPP/7zip/Archive/7z/7zDecode.h51
-rw-r--r--CPP/7zip/Archive/7z/7zEncode.cpp580
-rw-r--r--CPP/7zip/Archive/7z/7zEncode.h67
-rw-r--r--CPP/7zip/Archive/7z/7zExtract.cpp460
-rw-r--r--CPP/7zip/Archive/7z/7zFolderInStream.cpp133
-rw-r--r--CPP/7zip/Archive/7z/7zFolderInStream.h39
-rw-r--r--CPP/7zip/Archive/7z/7zFolderOutStream.cpp146
-rw-r--r--CPP/7zip/Archive/7z/7zFolderOutStream.h52
-rw-r--r--CPP/7zip/Archive/7z/7zHandler.cpp76
-rw-r--r--CPP/7zip/Archive/7z/7zHandler.h25
-rw-r--r--CPP/7zip/Archive/7z/7zHandlerOut.cpp181
-rw-r--r--CPP/7zip/Archive/7z/7zHeader.h47
-rw-r--r--CPP/7zip/Archive/7z/7zIn.cpp279
-rw-r--r--CPP/7zip/Archive/7z/7zIn.h57
-rw-r--r--CPP/7zip/Archive/7z/7zItem.h63
-rw-r--r--CPP/7zip/Archive/7z/7zOut.cpp47
-rw-r--r--CPP/7zip/Archive/7z/7zOut.h4
-rw-r--r--CPP/7zip/Archive/7z/7zProperties.cpp48
-rw-r--r--CPP/7zip/Archive/7z/7zRegister.cpp14
-rw-r--r--CPP/7zip/Archive/7z/7zSpecStream.h10
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.cpp1625
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.h27
-rw-r--r--CPP/7zip/Archive/ApmHandler.cpp12
-rw-r--r--CPP/7zip/Archive/ArHandler.cpp37
-rw-r--r--CPP/7zip/Archive/Archive.def8
-rw-r--r--CPP/7zip/Archive/Archive2.def10
-rw-r--r--CPP/7zip/Archive/ArchiveExports.cpp30
-rw-r--r--CPP/7zip/Archive/ArjHandler.cpp230
-rw-r--r--CPP/7zip/Archive/Bz2Handler.cpp47
-rw-r--r--CPP/7zip/Archive/Cab/CabBlockInStream.cpp13
-rw-r--r--CPP/7zip/Archive/Cab/CabHandler.cpp99
-rw-r--r--CPP/7zip/Archive/Cab/CabHeader.cpp4
-rw-r--r--CPP/7zip/Archive/Cab/CabHeader.h4
-rw-r--r--CPP/7zip/Archive/Cab/CabIn.cpp3
-rw-r--r--CPP/7zip/Archive/Cab/CabIn.h13
-rw-r--r--CPP/7zip/Archive/Cab/CabItem.h2
-rw-r--r--CPP/7zip/Archive/Cab/CabRegister.cpp12
-rw-r--r--CPP/7zip/Archive/Chm/ChmHandler.cpp37
-rw-r--r--CPP/7zip/Archive/Chm/ChmIn.cpp23
-rw-r--r--CPP/7zip/Archive/Chm/ChmIn.h8
-rw-r--r--CPP/7zip/Archive/ComHandler.cpp84
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2.cpp1061
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2.h462
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2MT.cpp242
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2MT.h84
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2ST.cpp595
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2ST.h165
-rw-r--r--CPP/7zip/Archive/Common/CoderMixerMT.h2
-rw-r--r--CPP/7zip/Archive/Common/HandlerOut.cpp32
-rw-r--r--CPP/7zip/Archive/Common/HandlerOut.h4
-rw-r--r--CPP/7zip/Archive/Common/OutStreamWithSha1.cpp4
-rw-r--r--CPP/7zip/Archive/Common/OutStreamWithSha1.h10
-rw-r--r--CPP/7zip/Archive/CpioHandler.cpp27
-rw-r--r--CPP/7zip/Archive/CramfsHandler.cpp26
-rw-r--r--CPP/7zip/Archive/DllExports.cpp47
-rw-r--r--CPP/7zip/Archive/DllExports2.cpp50
-rw-r--r--CPP/7zip/Archive/DmgHandler.cpp153
-rw-r--r--CPP/7zip/Archive/ElfHandler.cpp12
-rw-r--r--CPP/7zip/Archive/FatHandler.cpp60
-rw-r--r--CPP/7zip/Archive/FlvHandler.cpp31
-rw-r--r--CPP/7zip/Archive/GzHandler.cpp130
-rw-r--r--CPP/7zip/Archive/HfsHandler.cpp39
-rw-r--r--CPP/7zip/Archive/IArchive.h124
-rw-r--r--CPP/7zip/Archive/IhexHandler.cpp26
-rw-r--r--CPP/7zip/Archive/Iso/IsoHandler.cpp37
-rw-r--r--CPP/7zip/Archive/Iso/IsoHeader.cpp9
-rw-r--r--CPP/7zip/Archive/Iso/IsoHeader.h8
-rw-r--r--CPP/7zip/Archive/Iso/IsoIn.cpp193
-rw-r--r--CPP/7zip/Archive/Iso/IsoIn.h132
-rw-r--r--CPP/7zip/Archive/Iso/IsoItem.h33
-rw-r--r--CPP/7zip/Archive/Iso/IsoRegister.cpp12
-rw-r--r--CPP/7zip/Archive/LzhHandler.cpp21
-rw-r--r--CPP/7zip/Archive/LzmaHandler.cpp91
-rw-r--r--CPP/7zip/Archive/MachoHandler.cpp30
-rw-r--r--CPP/7zip/Archive/MbrHandler.cpp33
-rw-r--r--CPP/7zip/Archive/MslzHandler.cpp28
-rw-r--r--CPP/7zip/Archive/MubHandler.cpp18
-rw-r--r--CPP/7zip/Archive/Nsis/NsisDecode.cpp24
-rw-r--r--CPP/7zip/Archive/Nsis/NsisDecode.h2
-rw-r--r--CPP/7zip/Archive/Nsis/NsisHandler.cpp17
-rw-r--r--CPP/7zip/Archive/Nsis/NsisIn.cpp103
-rw-r--r--CPP/7zip/Archive/Nsis/NsisIn.h3
-rw-r--r--CPP/7zip/Archive/Nsis/NsisRegister.cpp12
-rw-r--r--CPP/7zip/Archive/NtfsHandler.cpp652
-rw-r--r--CPP/7zip/Archive/PeHandler.cpp183
-rw-r--r--CPP/7zip/Archive/PpmdHandler.cpp21
-rw-r--r--CPP/7zip/Archive/Rar/RarHandler.cpp149
-rw-r--r--CPP/7zip/Archive/Rar/RarHandler.h17
-rw-r--r--CPP/7zip/Archive/Rar/RarItem.h8
-rw-r--r--CPP/7zip/Archive/RpmHandler.cpp27
-rw-r--r--CPP/7zip/Archive/SplitHandler.cpp106
-rw-r--r--CPP/7zip/Archive/SquashfsHandler.cpp33
-rw-r--r--CPP/7zip/Archive/SwfHandler.cpp39
-rw-r--r--CPP/7zip/Archive/Tar/TarHandler.cpp26
-rw-r--r--CPP/7zip/Archive/Tar/TarHandler.h2
-rw-r--r--CPP/7zip/Archive/Tar/TarHandlerOut.cpp4
-rw-r--r--CPP/7zip/Archive/Tar/TarIn.cpp40
-rw-r--r--CPP/7zip/Archive/Tar/TarItem.h2
-rw-r--r--CPP/7zip/Archive/Tar/TarRegister.cpp15
-rw-r--r--CPP/7zip/Archive/Tar/TarUpdate.cpp10
-rw-r--r--CPP/7zip/Archive/Udf/UdfHandler.cpp26
-rw-r--r--CPP/7zip/Archive/Udf/UdfIn.cpp26
-rw-r--r--CPP/7zip/Archive/Udf/UdfRegister.cpp7
-rw-r--r--CPP/7zip/Archive/UefiHandler.cpp509
-rw-r--r--CPP/7zip/Archive/VhdHandler.cpp66
-rw-r--r--CPP/7zip/Archive/Wim/WimHandler.cpp67
-rw-r--r--CPP/7zip/Archive/Wim/WimHandler.h2
-rw-r--r--CPP/7zip/Archive/Wim/WimHandlerOut.cpp43
-rw-r--r--CPP/7zip/Archive/Wim/WimIn.cpp90
-rw-r--r--CPP/7zip/Archive/Wim/WimIn.h4
-rw-r--r--CPP/7zip/Archive/Wim/WimRegister.cpp13
-rw-r--r--CPP/7zip/Archive/XarHandler.cpp61
-rw-r--r--CPP/7zip/Archive/XzHandler.cpp285
-rw-r--r--CPP/7zip/Archive/XzHandler.h65
-rw-r--r--CPP/7zip/Archive/ZHandler.cpp12
-rw-r--r--CPP/7zip/Archive/Zip/ZipAddCommon.cpp116
-rw-r--r--CPP/7zip/Archive/Zip/ZipAddCommon.h6
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandler.cpp180
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandler.h2
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandlerOut.cpp24
-rw-r--r--CPP/7zip/Archive/Zip/ZipHeader.h2
-rw-r--r--CPP/7zip/Archive/Zip/ZipIn.cpp23
-rw-r--r--CPP/7zip/Archive/Zip/ZipIn.h4
-rw-r--r--CPP/7zip/Archive/Zip/ZipItem.cpp7
-rw-r--r--CPP/7zip/Archive/Zip/ZipItem.h16
-rw-r--r--CPP/7zip/Archive/Zip/ZipOut.h2
-rw-r--r--CPP/7zip/Archive/Zip/ZipRegister.cpp21
-rw-r--r--CPP/7zip/Archive/Zip/ZipUpdate.cpp80
131 files changed, 8137 insertions, 4426 deletions
diff --git a/CPP/7zip/Archive/7z/7z.dsp b/CPP/7zip/Archive/7z/7z.dsp
index 53913f77..7fd1ccdc 100644
--- a/CPP/7zip/Archive/7z/7z.dsp
+++ b/CPP/7zip/Archive/7z/7z.dsp
@@ -350,14 +350,6 @@ SOURCE=..\Common\CoderMixer2.h
# End Source File
# Begin Source File
-SOURCE=..\Common\CoderMixer2MT.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\Common\CoderMixer2MT.h
-# End Source File
-# Begin Source File
-
SOURCE=..\Common\CrossThreadProgress.cpp
# End Source File
# Begin Source File
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h
index 5cde97c3..8105ff04 100644
--- a/CPP/7zip/Archive/7z/7zCompressionMode.h
+++ b/CPP/7zip/Archive/7z/7zCompressionMode.h
@@ -9,37 +9,62 @@
namespace NArchive {
namespace N7z {
-struct CMethodFull: public CProps
+struct CMethodFull: public CMethodProps
{
CMethodId Id;
- UInt32 NumInStreams;
- UInt32 NumOutStreams;
+ UInt32 NumStreams;
- bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
+ bool IsSimpleCoder() const { return NumStreams == 1; }
};
-struct CBind
+struct CBond2
{
- UInt32 InCoder;
- UInt32 InStream;
UInt32 OutCoder;
UInt32 OutStream;
+ UInt32 InCoder;
};
struct CCompressionMethodMode
{
+ /*
+ if (Bonds.Empty()), then default bonds must be created
+ if (Filter_was_Inserted)
+ {
+ Methods[0] is filter method
+ Bonds don't contain bonds for filter (these bonds must be created)
+ }
+ */
+
CObjectVector<CMethodFull> Methods;
- CRecordVector<CBind> Binds;
+ CRecordVector<CBond2> Bonds;
+
+ bool IsThereBond_to_Coder(unsigned coderIndex) const
+ {
+ FOR_VECTOR(i, Bonds)
+ if (Bonds[i].InCoder == coderIndex)
+ return true;
+ return false;
+ }
+
+ bool DefaultMethod_was_Inserted;
+ bool Filter_was_Inserted;
+
#ifndef _7ZIP_ST
UInt32 NumThreads;
+ bool MultiThreadMixer;
#endif
+
bool PasswordIsDefined;
UString Password;
bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
- CCompressionMethodMode(): PasswordIsDefined(false)
+ CCompressionMethodMode():
+ DefaultMethod_was_Inserted(false),
+ Filter_was_Inserted(false),
+ PasswordIsDefined(false)
#ifndef _7ZIP_ST
, NumThreads(1)
+ , MultiThreadMixer(true)
#endif
{}
};
diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp
index 7f0e45d1..d1a810cb 100644
--- a/CPP/7zip/Archive/7z/7zDecode.cpp
+++ b/CPP/7zip/Archive/7z/7zDecode.cpp
@@ -3,7 +3,6 @@
#include "StdAfx.h"
#include "../../Common/LimitedStreams.h"
-#include "../../Common/LockedStream.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamObjects.h"
@@ -12,50 +11,70 @@
namespace NArchive {
namespace N7z {
-static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
- CBindInfoEx &bindInfo)
+class CDecProgress:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
{
- bindInfo.Clear();
- bindInfo.BindPairs.ClearAndSetSize(folder.BindPairs.Size());
+ CMyComPtr<ICompressProgressInfo> _progress;
+public:
+ CDecProgress(ICompressProgressInfo *progress): _progress(progress) {}
+
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+STDMETHODIMP CDecProgress::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 *outSize)
+{
+ return _progress->SetRatioInfo(NULL, outSize);
+}
+
+static void Convert_FolderInfo_to_BindInfo(const CFolderEx &folder, CBindInfoEx &bi)
+{
+ bi.Clear();
+
+ bi.Bonds.ClearAndSetSize(folder.Bonds.Size());
unsigned i;
- for (i = 0; i < folder.BindPairs.Size(); i++)
+ for (i = 0; i < folder.Bonds.Size(); i++)
{
- NCoderMixer::CBindPair &bindPair = bindInfo.BindPairs[i];
- bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
- bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
+ NCoderMixer2::CBond &bond = bi.Bonds[i];
+ const N7z::CBond &folderBond = folder.Bonds[i];
+ bond.PackIndex = folderBond.PackIndex;
+ bond.UnpackIndex = folderBond.UnpackIndex;
}
- bindInfo.Coders.ClearAndSetSize(folder.Coders.Size());
- bindInfo.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
-
- UInt32 outStreamIndex = 0;
+ bi.Coders.ClearAndSetSize(folder.Coders.Size());
+ bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
for (i = 0; i < folder.Coders.Size(); i++)
{
- NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
const CCoderInfo &coderInfo = folder.Coders[i];
- coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
- coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
- bindInfo.CoderMethodIDs[i] = coderInfo.MethodID;
- for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
- if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
- bindInfo.OutStreams.Add(outStreamIndex);
+ bi.Coders[i].NumStreams = coderInfo.NumStreams;
+ bi.CoderMethodIDs[i] = coderInfo.MethodID;
}
- bindInfo.InStreams.ClearAndSetSize(folder.PackStreams.Size());
+
+ /*
+ if (!bi.SetUnpackCoder())
+ throw 1112;
+ */
+ bi.UnpackCoder = folder.UnpackCoder;
+ bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size());
for (i = 0; i < folder.PackStreams.Size(); i++)
- bindInfo.InStreams[i] = (UInt32)folder.PackStreams[i];
+ bi.PackStreams[i] = folder.PackStreams[i];
}
-static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,
- const NCoderMixer::CCoderStreamsInfo &a2)
+static inline bool AreCodersEqual(
+ const NCoderMixer2::CCoderStreamsInfo &a1,
+ const NCoderMixer2::CCoderStreamsInfo &a2)
{
- return (a1.NumInStreams == a2.NumInStreams) &&
- (a1.NumOutStreams == a2.NumOutStreams);
+ return (a1.NumStreams == a2.NumStreams);
}
-static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)
+static inline bool AreBondsEqual(
+ const NCoderMixer2::CBond &a1,
+ const NCoderMixer2::CBond &a2)
{
- return (a1.InIndex == a2.InIndex) &&
- (a1.OutIndex == a2.OutIndex);
+ return
+ (a1.PackIndex == a2.PackIndex) &&
+ (a1.UnpackIndex == a2.UnpackIndex);
}
static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
@@ -66,186 +85,284 @@ static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
for (i = 0; i < a1.Coders.Size(); i++)
if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
return false;
- if (a1.BindPairs.Size() != a2.BindPairs.Size())
+
+ if (a1.Bonds.Size() != a2.Bonds.Size())
return false;
- for (i = 0; i < a1.BindPairs.Size(); i++)
- if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
+ for (i = 0; i < a1.Bonds.Size(); i++)
+ if (!AreBondsEqual(a1.Bonds[i], a2.Bonds[i]))
return false;
+
for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
return false;
- if (a1.InStreams.Size() != a2.InStreams.Size())
+
+ if (a1.PackStreams.Size() != a2.PackStreams.Size())
return false;
- if (a1.OutStreams.Size() != a2.OutStreams.Size())
+ for (i = 0; i < a1.PackStreams.Size(); i++)
+ if (a1.PackStreams[i] != a2.PackStreams[i])
+ return false;
+
+ /*
+ if (a1.UnpackCoder != a2.UnpackCoder)
return false;
+ */
return true;
}
-CDecoder::CDecoder(bool multiThread)
+CDecoder::CDecoder(bool useMixerMT):
+ _bindInfoPrev_Defined(false),
+ _useMixerMT(useMixerMT)
+{}
+
+
+struct CLockedInStream:
+ public IUnknown,
+ public CMyUnknownImp
{
- #ifndef _ST_MODE
- multiThread = true;
+ CMyComPtr<IInStream> Stream;
+ UInt64 Pos;
+
+ MY_UNKNOWN_IMP
+
+ #ifdef USE_MIXER_MT
+ NWindows::NSynchronization::CCriticalSection CriticalSection;
#endif
- _multiThread = multiThread;
- _bindInfoExPrevIsDefined = false;
+};
+
+
+#ifdef USE_MIXER_MT
+
+class CLockedSequentialInStreamMT:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ CLockedInStream *_glob;
+ UInt64 _pos;
+ CMyComPtr<IUnknown> _globRef;
+public:
+ void Init(CLockedInStream *lockedInStream, UInt64 startPos)
+ {
+ _globRef = lockedInStream;
+ _glob = lockedInStream;
+ _pos = startPos;
+ }
+
+ MY_UNKNOWN_IMP1(ISequentialInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection);
+
+ if (_pos != _glob->Pos)
+ {
+ RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
+ _glob->Pos = _pos;
+ }
+
+ UInt32 realProcessedSize = 0;
+ HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
+ _pos += realProcessedSize;
+ _glob->Pos = _pos;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return res;
+}
+
+#endif
+
+
+#ifdef USE_MIXER_ST
+
+class CLockedSequentialInStreamST:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ CLockedInStream *_glob;
+ UInt64 _pos;
+ CMyComPtr<IUnknown> _globRef;
+public:
+ void Init(CLockedInStream *lockedInStream, UInt64 startPos)
+ {
+ _globRef = lockedInStream;
+ _glob = lockedInStream;
+ _pos = startPos;
+ }
+
+ MY_UNKNOWN_IMP1(ISequentialInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (_pos != _glob->Pos)
+ {
+ RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
+ _glob->Pos = _pos;
+ }
+
+ UInt32 realProcessedSize = 0;
+ HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
+ _pos += realProcessedSize;
+ _glob->Pos = _pos;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return res;
}
+#endif
+
+
+
HRESULT CDecoder::Decode(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream,
UInt64 startPos,
- const CFolders &folders, int folderIndex,
- ISequentialOutStream *outStream,
- ICompressProgressInfo *compressProgress
+ const CFolders &folders, unsigned folderIndex,
+ const UInt64 *unpackSize
+
+ , ISequentialOutStream *outStream
+ , ICompressProgressInfo *compressProgress
+ , ISequentialInStream **
+
+ #ifdef USE_MIXER_ST
+ inStreamMainRes
+ #endif
+
_7Z_DECODER_CRYPRO_VARS_DECL
+
#if !defined(_7ZIP_ST) && !defined(_SFX)
, bool mtMode, UInt32 numThreads
#endif
)
{
const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];
- CFolder folderInfo;
- folders.ParseFolderInfo(folderIndex, folderInfo);
+ CFolderEx folderInfo;
+ folders.ParseFolderEx(folderIndex, folderInfo);
- if (!folderInfo.CheckStructure(folders.GetNumFolderUnpackSizes(folderIndex)))
+ if (!folderInfo.IsDecodingSupported())
+ return E_NOTIMPL;
+
+ CBindInfoEx bindInfo;
+ Convert_FolderInfo_to_BindInfo(folderInfo, bindInfo);
+ if (!bindInfo.CalcMapsAndCheck())
return E_NOTIMPL;
+ UInt64 folderUnpackSize = folders.GetFolderUnpackSize(folderIndex);
+ bool fullUnpack = true;
+ if (unpackSize)
+ {
+ if (*unpackSize > folderUnpackSize)
+ return E_FAIL;
+ fullUnpack = (*unpackSize == folderUnpackSize);
+ }
+
/*
We don't need to init isEncrypted and passwordIsDefined
We must upgrade them only
+
#ifndef _NO_CRYPTO
isEncrypted = false;
passwordIsDefined = false;
#endif
*/
-
- CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
- CLockedInStream lockedInStream;
- lockedInStream.Init(inStream);
-
- for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
+ if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev))
{
- CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp;
- CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
- lockedStreamImpSpec->Init(&lockedInStream, startPos + packPositions[j]);
- CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
- CMyComPtr<ISequentialInStream> inStream = streamSpec;
- streamSpec->SetStream(lockedStreamImp);
- streamSpec->Init(packPositions[j + 1] - packPositions[j]);
- inStreams.Add(inStream);
- }
-
- unsigned numCoders = folderInfo.Coders.Size();
-
- CBindInfoEx bindInfo;
- ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
- bool createNewCoders;
- if (!_bindInfoExPrevIsDefined)
- createNewCoders = true;
- else
- createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
- if (createNewCoders)
- {
- unsigned i;
- _decoders.Clear();
- // _decoders2.Clear();
-
- _mixerCoder.Release();
+ _mixerRef.Release();
- if (_multiThread)
+ #ifdef USE_MIXER_MT
+ #ifdef USE_MIXER_ST
+ if (_useMixerMT)
+ #endif
{
- _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;
- _mixerCoder = _mixerCoderMTSpec;
- _mixerCoderCommon = _mixerCoderMTSpec;
+ _mixerMT = new NCoderMixer2::CMixerMT(false);
+ _mixerRef = _mixerMT;
+ _mixer = _mixerMT;
}
+ #ifdef USE_MIXER_ST
else
+ #endif
+ #endif
{
- #ifdef _ST_MODE
- _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;
- _mixerCoder = _mixerCoderSTSpec;
- _mixerCoderCommon = _mixerCoderSTSpec;
+ #ifdef USE_MIXER_ST
+ _mixerST = new NCoderMixer2::CMixerST(false);
+ _mixerRef = _mixerST;
+ _mixer = _mixerST;
#endif
}
- RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));
- for (i = 0; i < numCoders; i++)
+ RINOK(_mixer->SetBindInfo(bindInfo));
+
+ FOR_VECTOR(i, folderInfo.Coders)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
-
- CMyComPtr<ICompressCoder> decoder;
- CMyComPtr<ICompressCoder2> decoder2;
+ CCreatedCoder cod;
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
- coderInfo.MethodID, decoder, decoder2, false));
- CMyComPtr<IUnknown> decoderUnknown;
+ coderInfo.MethodID, false, cod));
+
if (coderInfo.IsSimpleCoder())
{
- if (decoder == 0)
+ if (!cod.Coder)
return E_NOTIMPL;
-
- decoderUnknown = (IUnknown *)decoder;
-
- if (_multiThread)
- _mixerCoderMTSpec->AddCoder(decoder);
- #ifdef _ST_MODE
- else
- _mixerCoderSTSpec->AddCoder(decoder, false);
- #endif
+ // CMethodId m = coderInfo.MethodID;
+ // isFilter = (IsFilterMethod(m) || m == k_AES);
}
else
{
- if (decoder2 == 0)
+ if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams)
return E_NOTIMPL;
- decoderUnknown = (IUnknown *)decoder2;
- if (_multiThread)
- _mixerCoderMTSpec->AddCoder2(decoder2);
- #ifdef _ST_MODE
- else
- _mixerCoderSTSpec->AddCoder2(decoder2, false);
- #endif
}
- _decoders.Add(decoderUnknown);
+ _mixer->AddCoder(cod);
+
+ // now there is no codec that uses another external codec
+ /*
#ifdef EXTERNAL_CODECS
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo)
{
+ // we must use g_ExternalCodecs also
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
}
#endif
+ */
}
- _bindInfoExPrev = bindInfo;
- _bindInfoExPrevIsDefined = true;
+
+ _bindInfoPrev = bindInfo;
+ _bindInfoPrev_Defined = true;
}
- unsigned i;
- _mixerCoderCommon->ReInit();
+
+ _mixer->ReInit();
UInt32 packStreamIndex = 0;
UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];
- UInt32 unpackStreamIndex = unpackStreamIndexStart;
- UInt32 coderIndex = 0;
- // UInt32 coder2Index = 0;
-
- for (i = 0; i < numCoders; i++)
+
+ unsigned i;
+
+ for (i = 0; i < folderInfo.Coders.Size(); i++)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
- CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];
-
+ IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();
+
{
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
- decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
+ decoder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
if (setDecoderProperties)
{
const CByteBuffer &props = coderInfo.Props;
size_t size = props.Size();
if (size > 0xFFFFFFFF)
return E_NOTIMPL;
- // if (size > 0)
- {
- RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size));
- }
+ HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size);
+ if (res == E_INVALIDARG)
+ res = E_NOTIMPL;
+ RINOK(res);
}
}
@@ -253,7 +370,7 @@ HRESULT CDecoder::Decode(
if (mtMode)
{
CMyComPtr<ICompressSetCoderMt> setCoderMt;
- decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
+ decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
if (setCoderMt)
{
RINOK(setCoderMt->SetNumberOfThreads(numThreads));
@@ -264,7 +381,7 @@ HRESULT CDecoder::Decode(
#ifndef _NO_CRYPTO
{
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
- decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
+ decoder->QueryInterface(IID_ICryptoSetPassword, (void **)&cryptoSetPassword);
if (cryptoSetPassword)
{
isEncrypted = true;
@@ -273,9 +390,13 @@ HRESULT CDecoder::Decode(
CMyComBSTR passwordBSTR;
RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));
passwordIsDefined = true;
+ password.Empty();
size_t len = 0;
if (passwordBSTR)
- len = MyStringLen((BSTR)passwordBSTR);
+ {
+ password = passwordBSTR;
+ len = password.Len();
+ }
CByteBuffer buffer(len * 2);
for (size_t i = 0; i < len; i++)
{
@@ -288,56 +409,129 @@ HRESULT CDecoder::Decode(
}
#endif
- coderIndex++;
+ {
+ CMyComPtr<ICompressSetFinishMode> setFinishMode;
+ decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
+ if (setFinishMode)
+ {
+ RINOK(setFinishMode->SetFinishMode(BoolToInt(fullUnpack)));
+ }
+ }
- UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
- UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
- CObjArray<UInt64> packSizes(numInStreams);
- CObjArray<const UInt64 *> packSizesPointers(numInStreams);
- CObjArray<const UInt64 *> unpackSizesPointers(numOutStreams);
- UInt32 j;
-
- for (j = 0; j < numOutStreams; j++, unpackStreamIndex++)
- unpackSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndex];
+ UInt32 numStreams = (UInt32)coderInfo.NumStreams;
- for (j = 0; j < numInStreams; j++, packStreamIndex++)
+ CObjArray<UInt64> packSizes(numStreams);
+ CObjArray<const UInt64 *> packSizesPointers(numStreams);
+
+ for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++)
{
- int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
- if (bindPairIndex >= 0)
- packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + (UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex];
+ int bond = folderInfo.FindBond_for_PackStream(packStreamIndex);
+
+ if (bond >= 0)
+ packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex];
else
{
- int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
+ int index = folderInfo.Find_in_PackStreams(packStreamIndex);
if (index < 0)
- return S_FALSE; // check it
- packSizes[j] = packPositions[index + 1] - packPositions[index];
+ return E_NOTIMPL;
+ packSizes[j] = packPositions[(unsigned)index + 1] - packPositions[(unsigned)index];
packSizesPointers[j] = &packSizes[j];
}
}
+
+ const UInt64 *unpackSizesPointer =
+ (unpackSize && i == bindInfo.UnpackCoder) ?
+ unpackSize :
+ &folders.CoderUnpackSizes[unpackStreamIndexStart + i];
- _mixerCoderCommon->SetCoderInfo(i, packSizesPointers, unpackSizesPointers);
+ _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers);
}
- UInt32 mainCoder, temp;
- bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
- if (_multiThread)
- _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
- /*
- else
- _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
- */
+ if (outStream)
+ {
+ _mixer->SelectMainCoder(!fullUnpack);
+ }
+
+ CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
+
+ CLockedInStream *lockedInStreamSpec = new CLockedInStream;
+ CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec;
+
+ bool needMtLock = false;
+
+ if (folderInfo.PackStreams.Size() > 1)
+ {
+ // lockedInStream.Pos = (UInt64)(Int64)-1;
+ // RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &lockedInStream.Pos));
+ RINOK(inStream->Seek(startPos + packPositions[0], STREAM_SEEK_SET, &lockedInStreamSpec->Pos));
+ lockedInStreamSpec->Stream = inStream;
+
+ #ifdef USE_MIXER_ST
+ if (_mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex))
+ #endif
+ needMtLock = true;
+ }
+
+ for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
+ {
+ CMyComPtr<ISequentialInStream> packStream;
+ UInt64 packPos = startPos + packPositions[j];
+
+ if (folderInfo.PackStreams.Size() == 1)
+ {
+ RINOK(inStream->Seek(packPos, STREAM_SEEK_SET, NULL));
+ packStream = inStream;
+ }
+ else
+ {
+ #ifdef USE_MIXER_MT
+ #ifdef USE_MIXER_ST
+ if (_useMixerMT || needMtLock)
+ #endif
+ {
+ CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;
+ packStream = lockedStreamImpSpec;
+ lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);
+ }
+ #ifdef USE_MIXER_ST
+ else
+ #endif
+ #endif
+ {
+ #ifdef USE_MIXER_ST
+ CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST;
+ packStream = lockedStreamImpSpec;
+ lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);
+ #endif
+ }
+ }
+
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ inStreams.AddNew() = streamSpec;
+ streamSpec->SetStream(packStream);
+ streamSpec->Init(packPositions[j + 1] - packPositions[j]);
+ }
- if (numCoders == 0)
- return 0;
unsigned num = inStreams.Size();
CObjArray<ISequentialInStream *> inStreamPointers(num);
for (i = 0; i < num; i++)
inStreamPointers[i] = inStreams[i];
- ISequentialOutStream *outStreamPointer = outStream;
- return _mixerCoder->Code(
- inStreamPointers, NULL, num,
- &outStreamPointer, NULL, 1,
- compressProgress);
+
+ if (outStream)
+ {
+ CMyComPtr<ICompressProgressInfo> progress2;
+ if (compressProgress && !_mixer->Is_PackSize_Correct_for_Coder(_mixer->MainCoderIndex))
+ progress2 = new CDecProgress(compressProgress);
+
+ ISequentialOutStream *outStreamPointer = outStream;
+ return _mixer->Code(inStreamPointers, &outStreamPointer, progress2 ? (ICompressProgressInfo *)progress2 : compressProgress);
+ }
+
+ #ifdef USE_MIXER_ST
+ return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes);
+ #else
+ return E_FAIL;
+ #endif
}
}}
diff --git a/CPP/7zip/Archive/7z/7zDecode.h b/CPP/7zip/Archive/7z/7zDecode.h
index 1361772c..5b729f6c 100644
--- a/CPP/7zip/Archive/7z/7zDecode.h
+++ b/CPP/7zip/Archive/7z/7zDecode.h
@@ -3,25 +3,17 @@
#ifndef __7Z_DECODE_H
#define __7Z_DECODE_H
-#include "../../IStream.h"
-#include "../../IPassword.h"
-
#include "../Common/CoderMixer2.h"
-#include "../Common/CoderMixer2MT.h"
-#ifdef _ST_MODE
-#include "../Common/CoderMixer2ST.h"
-#endif
-
-#include "../../Common/CreateCoder.h"
#include "7zIn.h"
namespace NArchive {
namespace N7z {
-struct CBindInfoEx: public NCoderMixer::CBindInfo
+struct CBindInfoEx: public NCoderMixer2::CBindInfo
{
CRecordVector<CMethodId> CoderMethodIDs;
+
void Clear()
{
CBindInfo::Clear();
@@ -31,29 +23,40 @@ struct CBindInfoEx: public NCoderMixer::CBindInfo
class CDecoder
{
- bool _bindInfoExPrevIsDefined;
- CBindInfoEx _bindInfoExPrev;
+ bool _bindInfoPrev_Defined;
+ CBindInfoEx _bindInfoPrev;
+
+ bool _useMixerMT;
- bool _multiThread;
- #ifdef _ST_MODE
- NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec;
+ #ifdef USE_MIXER_ST
+ NCoderMixer2::CMixerST *_mixerST;
#endif
- NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec;
- NCoderMixer::CCoderMixer2 *_mixerCoderCommon;
- CMyComPtr<ICompressCoder2> _mixerCoder;
- CObjectVector<CMyComPtr<IUnknown> > _decoders;
- // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2;
+ #ifdef USE_MIXER_MT
+ NCoderMixer2::CMixerMT *_mixerMT;
+ #endif
+
+ NCoderMixer2::CMixer *_mixer;
+ CMyComPtr<IUnknown> _mixerRef;
+
public:
- CDecoder(bool multiThread);
+
+ CDecoder(bool useMixerMT);
+
HRESULT Decode(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream,
UInt64 startPos,
- const CFolders &folders, int folderIndex,
- ISequentialOutStream *outStream,
- ICompressProgressInfo *compressProgress
+ const CFolders &folders, unsigned folderIndex,
+ const UInt64 *unpackSize // if (!unpackSize), then full folder is required
+ // if (unpackSize), then only *unpackSize bytes from folder are required
+
+ , ISequentialOutStream *outStream
+ , ICompressProgressInfo *compressProgress
+ , ISequentialInStream **inStreamMainRes
+
_7Z_DECODER_CRYPRO_VARS_DECL
+
#if !defined(_7ZIP_ST) && !defined(_SFX)
, bool mtMode, UInt32 numThreads
#endif
diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp
index 36ff5177..ab251711 100644
--- a/CPP/7zip/Archive/7z/7zEncode.cpp
+++ b/CPP/7zip/Archive/7z/7zEncode.cpp
@@ -12,43 +12,80 @@
#include "7zEncode.h"
#include "7zSpecStream.h"
-static const UInt64 k_Delta = 0x03;
-static const UInt64 k_BCJ = 0x03030103;
-static const UInt64 k_BCJ2 = 0x0303011B;
-
namespace NArchive {
namespace N7z {
-static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo,
- const CRecordVector<CMethodId> decompressionMethods,
- CFolder &folder)
+void CEncoder::InitBindConv()
+{
+ unsigned numIn = _bindInfo.Coders.Size();
+
+ _SrcIn_to_DestOut.ClearAndSetSize(numIn);
+ _DestOut_to_SrcIn.ClearAndSetSize(numIn);
+
+ unsigned numOut = _bindInfo.GetNum_Bonds_and_PackStreams();
+ _SrcOut_to_DestIn.ClearAndSetSize(numOut);
+ // _DestIn_to_SrcOut.ClearAndSetSize(numOut);
+
+ UInt32 destIn = 0;
+ UInt32 destOut = 0;
+
+ for (unsigned i = _bindInfo.Coders.Size(); i != 0;)
+ {
+ i--;
+
+ const NCoderMixer2::CCoderStreamsInfo &coder = _bindInfo.Coders[i];
+
+ numIn--;
+ numOut -= coder.NumStreams;
+
+ _SrcIn_to_DestOut[numIn] = destOut;
+ _DestOut_to_SrcIn[destOut] = numIn;
+
+ destOut++;
+
+ for (UInt32 j = 0; j < coder.NumStreams; j++, destIn++)
+ {
+ UInt32 index = numOut + j;
+ _SrcOut_to_DestIn[index] = destIn;
+ // _DestIn_to_SrcOut[destIn] = index;
+ }
+ }
+}
+
+void CEncoder::SetFolder(CFolder &folder)
{
- // bindInfo.CoderMethodIDs.Clear();
- // folder.OutStreams.Clear();
- folder.BindPairs.SetSize(bindInfo.BindPairs.Size());
+ folder.Bonds.SetSize(_bindInfo.Bonds.Size());
+
unsigned i;
- for (i = 0; i < bindInfo.BindPairs.Size(); i++)
+
+ for (i = 0; i < _bindInfo.Bonds.Size(); i++)
{
- CBindPair &bp = folder.BindPairs[i];
- const NCoderMixer::CBindPair &mixerBp = bindInfo.BindPairs[i];
- bp.InIndex = mixerBp.InIndex;
- bp.OutIndex = mixerBp.OutIndex;
+ CBond &fb = folder.Bonds[i];
+ const NCoderMixer2::CBond &mixerBond = _bindInfo.Bonds[_bindInfo.Bonds.Size() - 1 - i];
+ fb.PackIndex = _SrcOut_to_DestIn[mixerBond.PackIndex];
+ fb.UnpackIndex = _SrcIn_to_DestOut[mixerBond.UnpackIndex];
}
- folder.Coders.SetSize(bindInfo.Coders.Size());
- for (i = 0; i < bindInfo.Coders.Size(); i++)
+
+ folder.Coders.SetSize(_bindInfo.Coders.Size());
+
+ for (i = 0; i < _bindInfo.Coders.Size(); i++)
{
CCoderInfo &coderInfo = folder.Coders[i];
- const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
- coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;
- coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;
- coderInfo.MethodID = decompressionMethods[i];
- // coderInfo.Props can be nonFree;
+ const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[_bindInfo.Coders.Size() - 1 - i];
+
+ coderInfo.NumStreams = coderStreamsInfo.NumStreams;
+ coderInfo.MethodID = _decompressionMethods[i];
+ // we don't free coderInfo.Props here. So coderInfo.Props can be non-empty.
}
- folder.PackStreams.SetSize(bindInfo.InStreams.Size());
- for (i = 0; i < bindInfo.InStreams.Size(); i++)
- folder.PackStreams[i] = bindInfo.InStreams[i];
+
+ folder.PackStreams.SetSize(_bindInfo.PackStreams.Size());
+
+ for (i = 0; i < _bindInfo.PackStreams.Size(); i++)
+ folder.PackStreams[i] = _SrcOut_to_DestIn[_bindInfo.PackStreams[i]];
}
+
+
static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)
{
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
@@ -58,30 +95,75 @@ static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce,
return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;
}
+
+
+void CMtEncMultiProgress::Init(ICompressProgressInfo *progress)
+{
+ _progress = progress;
+ OutSize = 0;
+}
+
+STDMETHODIMP CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)
+{
+ UInt64 outSize2;
+ {
+ #ifndef _7ZIP_ST
+ NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
+ #endif
+ outSize2 = OutSize;
+ }
+
+ if (_progress)
+ return _progress->SetRatioInfo(inSize, &outSize2);
+
+ return S_OK;
+}
+
+
+
HRESULT CEncoder::CreateMixerCoder(
DECL_EXTERNAL_CODECS_LOC_VARS
const UInt64 *inSizeForReduce)
{
- _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT;
- _mixerCoder = _mixerCoderSpec;
- RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo));
+ #ifdef USE_MIXER_MT
+ #ifdef USE_MIXER_ST
+ if (_options.MultiThreadMixer)
+ #endif
+ {
+ _mixerMT = new NCoderMixer2::CMixerMT(true);
+ _mixerRef = _mixerMT;
+ _mixer = _mixerMT;
+ }
+ #ifdef USE_MIXER_ST
+ else
+ #endif
+ #endif
+ {
+ #ifdef USE_MIXER_ST
+ _mixerST = new NCoderMixer2::CMixerST(true);
+ _mixerRef = _mixerST;
+ _mixer = _mixerST;
+ #endif
+ }
+
+ RINOK(_mixer->SetBindInfo(_bindInfo));
+
FOR_VECTOR (i, _options.Methods)
{
const CMethodFull &methodFull = _options.Methods[i];
- CCoderInfo &encodingInfo = _codersInfo.AddNew();
- encodingInfo.MethodID = methodFull.Id;
- CMyComPtr<ICompressCoder> encoder;
- CMyComPtr<ICompressCoder2> encoder2;
-
+ CCreatedCoder cod;
+
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
- methodFull.Id, encoder, encoder2, true));
+ methodFull.Id, true, cod));
- if (!encoder && !encoder2)
+ if (cod.NumStreams != methodFull.NumStreams)
+ return E_FAIL;
+ if (!cod.Coder && !cod.Coder2)
return E_FAIL;
- CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2;
+ CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;
#ifndef _7ZIP_ST
{
@@ -105,21 +187,25 @@ HRESULT CEncoder::CreateMixerCoder(
}
*/
+ // now there is no codec that uses another external codec
+ /*
#ifdef EXTERNAL_CODECS
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo)
{
+ // we must use g_ExternalCodecs also
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
}
#endif
+ */
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
if (cryptoSetPassword)
{
- const UInt32 sizeInBytes = _options.Password.Len() * 2;
+ const unsigned sizeInBytes = _options.Password.Len() * 2;
CByteBuffer buffer(sizeInBytes);
for (unsigned i = 0; i < _options.Password.Len(); i++)
{
@@ -127,21 +213,79 @@ HRESULT CEncoder::CreateMixerCoder(
((Byte *)buffer)[i * 2] = (Byte)c;
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
}
- RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
+ RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes));
}
- if (encoder)
- _mixerCoderSpec->AddCoder(encoder);
- else
- _mixerCoderSpec->AddCoder2(encoder2);
+ _mixer->AddCoder(cod);
}
return S_OK;
}
+
+
+class CSequentialOutTempBufferImp2:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ CInOutTempBuffer *_buf;
+public:
+ CMtEncMultiProgress *_mtProgresSpec;
+
+ CSequentialOutTempBufferImp2(): _buf(0), _mtProgresSpec(NULL) {}
+ void Init(CInOutTempBuffer *buffer) { _buf = buffer; }
+ MY_UNKNOWN_IMP1(ISequentialOutStream)
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed)
+{
+ if (!_buf->Write(data, size))
+ {
+ if (processed)
+ *processed = 0;
+ return E_FAIL;
+ }
+ if (processed)
+ *processed = size;
+ if (_mtProgresSpec)
+ _mtProgresSpec->AddOutSize(size);
+ return S_OK;
+}
+
+
+class CSequentialOutMtNotify:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ CMyComPtr<ISequentialOutStream> _stream;
+ CMtEncMultiProgress *_mtProgresSpec;
+
+ CSequentialOutMtNotify(): _mtProgresSpec(NULL) {}
+ MY_UNKNOWN_IMP1(ISequentialOutStream)
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed)
+{
+ UInt32 realProcessed = 0;
+ HRESULT res = _stream->Write(data, size, &realProcessed);
+ if (processed)
+ *processed = realProcessed;
+ if (_mtProgresSpec)
+ _mtProgresSpec->AddOutSize(size);
+ return res;
+}
+
+
+
HRESULT CEncoder::Encode(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream,
- const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
+ // const UInt64 *inStreamSize,
+ const UInt64 *inSizeForReduce,
CFolder &folderItem,
CRecordVector<UInt64> &coderUnpackSizes,
UInt64 &unpackSize,
@@ -151,27 +295,37 @@ HRESULT CEncoder::Encode(
{
RINOK(EncoderConstr());
- if (!_mixerCoderSpec)
+ if (!_mixerRef)
{
RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
}
- _mixerCoderSpec->ReInit();
- // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress);
+
+ _mixer->ReInit();
+
+ CMtEncMultiProgress *mtProgressSpec = NULL;
+ CMyComPtr<ICompressProgressInfo> mtProgress;
+
+ CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL;
+ CMyComPtr<ISequentialOutStream> mtOutStreamNotify;
CObjectVector<CInOutTempBuffer> inOutTempBuffers;
- CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;
+ CObjectVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;
CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
+
unsigned numMethods = _bindInfo.Coders.Size();
+
unsigned i;
- for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{
CInOutTempBuffer &iotb = inOutTempBuffers.AddNew();
iotb.Create();
iotb.InitWriting();
}
- for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{
- CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp;
+ CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2;
CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
tempBuffers.Add(tempBuffer);
@@ -179,94 +333,111 @@ HRESULT CEncoder::Encode(
}
for (i = 0; i < numMethods; i++)
- _mixerCoderSpec->SetCoderInfo(i, NULL, NULL);
+ _mixer->SetCoderInfo(i, NULL, NULL);
- if (_bindInfo.InStreams.IsEmpty())
- return E_FAIL;
- UInt32 mainCoderIndex, mainStreamIndex;
- _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);
-
+
+ /* inStreamSize can be used by BCJ2 to set optimal range of conversion.
+ But current BCJ2 encoder uses also another way to check exact size of current file.
+ So inStreamSize is not required. */
+
+ /*
if (inStreamSize)
- {
- CRecordVector<const UInt64 *> sizePointers;
- for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)
- if (i == mainStreamIndex)
- sizePointers.Add(inStreamSize);
- else
- sizePointers.Add(NULL);
- _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL);
- }
+ _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL);
+ */
- // UInt64 outStreamStartPos;
- // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));
-
CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
+
CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;
CMyComPtr<ISequentialOutStream> outStreamSizeCount;
inStreamSizeCountSpec->Init(inStream);
- CRecordVector<ISequentialInStream *> inStreamPointers;
+ ISequentialInStream *inStreamPointer = inStreamSizeCount;
CRecordVector<ISequentialOutStream *> outStreamPointers;
- inStreamPointers.Add(inStreamSizeCount);
- if (_bindInfo.OutStreams.Size() != 0)
- {
- outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
- outStreamSizeCount = outStreamSizeCountSpec;
- outStreamSizeCountSpec->SetStream(outStream);
- outStreamSizeCountSpec->Init();
- outStreamPointers.Add(outStreamSizeCount);
- }
+ SetFolder(folderItem);
- for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
- outStreamPointers.Add(tempBuffers[i - 1]);
-
- for (i = 0; i < _codersInfo.Size(); i++)
+ for (i = 0; i < numMethods; i++)
{
- CCoderInfo &encodingInfo = _codersInfo[i];
-
+ IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
+
CMyComPtr<ICryptoResetInitVector> resetInitVector;
- _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
+ coder->QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
if (resetInitVector)
{
resetInitVector->ResetInitVector();
}
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
- _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
+ coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
+
+ CByteBuffer &props = folderItem.Coders[numMethods - 1 - i].Props;
+
if (writeCoderProperties)
{
CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
- CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+ CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec);
outStreamSpec->Init();
- writeCoderProperties->WriteCoderProperties(outStream);
- outStreamSpec->CopyToBuffer(encodingInfo.Props);
+ writeCoderProperties->WriteCoderProperties(dynOutStream);
+ outStreamSpec->CopyToBuffer(props);
}
+ else
+ props.Free();
}
- UInt32 progressIndex = mainCoderIndex;
+ _mixer->SelectMainCoder(false);
+ UInt32 mainCoder = _mixer->MainCoderIndex;
- for (i = 0; i + 1 < _codersInfo.Size(); i++)
+ bool useMtProgress = false;
+ if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder))
{
- UInt64 m = _codersInfo[i].MethodID;
- if (m == k_Delta || m == k_BCJ || m == k_BCJ2)
- progressIndex = i + 1;
+ #ifdef _7ZIP_ST
+ if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder))
+ #endif
+ useMtProgress = true;
}
- _mixerCoderSpec->SetProgressCoderIndex(progressIndex);
+ if (useMtProgress)
+ {
+ mtProgressSpec = new CMtEncMultiProgress;
+ mtProgress = mtProgressSpec;
+ mtProgressSpec->Init(compressProgress);
+
+ mtOutStreamNotifySpec = new CSequentialOutMtNotify;
+ mtOutStreamNotify = mtOutStreamNotifySpec;
+ mtOutStreamNotifySpec->_stream = outStream;
+ mtOutStreamNotifySpec->_mtProgresSpec = mtProgressSpec;
+
+ FOR_VECTOR(i, tempBufferSpecs)
+ {
+ tempBufferSpecs[i]->_mtProgresSpec = mtProgressSpec;
+ }
+ }
- RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,
- &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));
- ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem);
+ if (_bindInfo.PackStreams.Size() != 0)
+ {
+ outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
+ outStreamSizeCount = outStreamSizeCountSpec;
+ outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream);
+ outStreamSizeCountSpec->Init();
+ outStreamPointers.Add(outStreamSizeCount);
+ }
+
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
+ outStreamPointers.Add(tempBuffers[i - 1]);
+
+ RINOK(_mixer->Code(
+ &inStreamPointer,
+ &outStreamPointers.Front(),
+ mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress));
- if (_bindInfo.OutStreams.Size() != 0)
+ if (_bindInfo.PackStreams.Size() != 0)
packSizes.Add(outStreamSizeCountSpec->GetSize());
- for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{
CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
RINOK(inOutTempBuffer.WriteToStream(outStream));
@@ -274,37 +445,45 @@ HRESULT CEncoder::Encode(
}
unpackSize = 0;
- for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)
+
+ for (i = 0; i < _bindInfo.Coders.Size(); i++)
{
- int binder = _bindInfo.FindBinderForInStream(
- _bindReverseConverter->DestOutToSrcInMap[i]);
+ int bond = _bindInfo.FindBond_for_UnpackStream(_DestOut_to_SrcIn[i]);
UInt64 streamSize;
- if (binder < 0)
+ if (bond < 0)
{
streamSize = inStreamSizeCountSpec->GetSize();
unpackSize = streamSize;
}
else
- streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);
+ streamSize = _mixer->GetBondStreamSize(bond);
coderUnpackSizes.Add(streamSize);
}
- for (i = 0; i < numMethods; i++)
- folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props;
+
return S_OK;
}
CEncoder::CEncoder(const CCompressionMethodMode &options):
- _bindReverseConverter(0),
- _constructed(false)
+ _constructed(false)
{
if (options.IsEmpty())
throw 1;
_options = options;
- _mixerCoderSpec = NULL;
+
+ #ifdef USE_MIXER_ST
+ _mixerST = NULL;
+ #endif
+
+ #ifdef USE_MIXER_MT
+ _mixerMT = NULL;
+ #endif
+
+ _mixer = NULL;
}
+
HRESULT CEncoder::EncoderConstr()
{
if (_constructed)
@@ -314,112 +493,125 @@ HRESULT CEncoder::EncoderConstr()
// it has only password method;
if (!_options.PasswordIsDefined)
throw 1;
- if (!_options.Binds.IsEmpty())
+ if (!_options.Bonds.IsEmpty())
throw 1;
- NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
+
CMethodFull method;
-
- method.NumInStreams = 1;
- method.NumOutStreams = 1;
- coderStreamsInfo.NumInStreams = 1;
- coderStreamsInfo.NumOutStreams = 1;
method.Id = k_AES;
-
+ method.NumStreams = 1;
_options.Methods.Add(method);
+
+ NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
+ coderStreamsInfo.NumStreams = 1;
_bindInfo.Coders.Add(coderStreamsInfo);
- _bindInfo.InStreams.Add(0);
- _bindInfo.OutStreams.Add(0);
+ _bindInfo.PackStreams.Add(0);
+ _bindInfo.UnpackCoder = 0;
}
else
{
- UInt32 numInStreams = 0, numOutStreams = 0;
+ UInt32 numOutStreams = 0;
unsigned i;
+
for (i = 0; i < _options.Methods.Size(); i++)
{
const CMethodFull &methodFull = _options.Methods[i];
- NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
- coderStreamsInfo.NumInStreams = methodFull.NumOutStreams;
- coderStreamsInfo.NumOutStreams = methodFull.NumInStreams;
- if (_options.Binds.IsEmpty())
+ NCoderMixer2::CCoderStreamsInfo cod;
+
+ cod.NumStreams = methodFull.NumStreams;
+
+ if (_options.Bonds.IsEmpty())
{
- if (i < _options.Methods.Size() - 1)
+ // if there are no bonds in options, we create bonds via first streams of coders
+ if (i != _options.Methods.Size() - 1)
{
- NCoderMixer::CBindPair bindPair;
- bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams;
- bindPair.OutIndex = numOutStreams;
- _bindInfo.BindPairs.Add(bindPair);
+ NCoderMixer2::CBond bond;
+ bond.PackIndex = numOutStreams;
+ bond.UnpackIndex = i + 1; // it's next coder
+ _bindInfo.Bonds.Add(bond);
}
- else if (coderStreamsInfo.NumOutStreams != 0)
- _bindInfo.OutStreams.Insert(0, numOutStreams);
- for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)
- _bindInfo.OutStreams.Add(numOutStreams + j);
+ else if (cod.NumStreams != 0)
+ _bindInfo.PackStreams.Insert(0, numOutStreams);
+
+ for (UInt32 j = 1; j < cod.NumStreams; j++)
+ _bindInfo.PackStreams.Add(numOutStreams + j);
}
- numInStreams += coderStreamsInfo.NumInStreams;
- numOutStreams += coderStreamsInfo.NumOutStreams;
+ numOutStreams += cod.NumStreams;
- _bindInfo.Coders.Add(coderStreamsInfo);
+ _bindInfo.Coders.Add(cod);
}
- if (!_options.Binds.IsEmpty())
+ if (!_options.Bonds.IsEmpty())
{
- for (i = 0; i < _options.Binds.Size(); i++)
+ for (i = 0; i < _options.Bonds.Size(); i++)
{
- NCoderMixer::CBindPair bindPair;
- const CBind &bind = _options.Binds[i];
- bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream;
- bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream;
- _bindInfo.BindPairs.Add(bindPair);
+ NCoderMixer2::CBond mixerBond;
+ const CBond2 &bond = _options.Bonds[i];
+ if (bond.InCoder >= _bindInfo.Coders.Size()
+ || bond.OutCoder >= _bindInfo.Coders.Size()
+ || bond.OutStream >= _bindInfo.Coders[bond.OutCoder].NumStreams)
+ return E_INVALIDARG;
+ mixerBond.PackIndex = _bindInfo.GetStream_for_Coder(bond.OutCoder) + bond.OutStream;
+ mixerBond.UnpackIndex = bond.InCoder;
+ _bindInfo.Bonds.Add(mixerBond);
}
- for (i = 0; i < (int)numOutStreams; i++)
- if (_bindInfo.FindBinderForOutStream(i) == -1)
- _bindInfo.OutStreams.Add(i);
+
+ for (i = 0; i < numOutStreams; i++)
+ if (_bindInfo.FindBond_for_PackStream(i) == -1)
+ _bindInfo.PackStreams.Add(i);
}
- for (i = 0; i < (int)numInStreams; i++)
- if (_bindInfo.FindBinderForInStream(i) == -1)
- _bindInfo.InStreams.Add(i);
+ if (!_bindInfo.SetUnpackCoder())
+ return E_INVALIDARG;
- if (_bindInfo.InStreams.IsEmpty())
- throw 1; // this is error
+ if (!_bindInfo.CalcMapsAndCheck())
+ return E_INVALIDARG;
- // Make main stream first in list
- int inIndex = _bindInfo.InStreams[0];
- for (;;)
+ if (_bindInfo.PackStreams.Size() != 1)
{
- UInt32 coderIndex, coderStreamIndex;
- _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex);
- UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
- int binder = _bindInfo.FindBinderForOutStream(outIndex);
- if (binder >= 0)
+ /* main_PackStream is pack stream of main path of coders tree.
+ We find main_PackStream, and place to start of list of out streams.
+ It allows to use more optimal memory usage for temp buffers,
+ if main_PackStream is largest stream. */
+
+ UInt32 ci = _bindInfo.UnpackCoder;
+
+ for (;;)
{
- inIndex = _bindInfo.BindPairs[binder].InIndex;
- continue;
- }
- for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
- if (_bindInfo.OutStreams[i] == outIndex)
- {
- _bindInfo.OutStreams.Delete(i);
- _bindInfo.OutStreams.Insert(0, outIndex);
+ if (_bindInfo.Coders[ci].NumStreams == 0)
break;
+
+ UInt32 outIndex = _bindInfo.Coder_to_Stream[ci];
+ int bond = _bindInfo.FindBond_for_PackStream(outIndex);
+ if (bond >= 0)
+ {
+ ci = _bindInfo.Bonds[bond].UnpackIndex;
+ continue;
}
- break;
+
+ int i = _bindInfo.FindStream_in_PackStreams(outIndex);
+ if (i >= 0)
+ _bindInfo.PackStreams.MoveToFront(i);
+ break;
+ }
}
if (_options.PasswordIsDefined)
{
- unsigned numCryptoStreams = _bindInfo.OutStreams.Size();
+ unsigned numCryptoStreams = _bindInfo.PackStreams.Size();
+ unsigned numInStreams = _bindInfo.Coders.Size();
+
for (i = 0; i < numCryptoStreams; i++)
{
- NCoderMixer::CBindPair bindPair;
- bindPair.InIndex = numInStreams + i;
- bindPair.OutIndex = _bindInfo.OutStreams[i];
- _bindInfo.BindPairs.Add(bindPair);
+ NCoderMixer2::CBond bond;
+ bond.UnpackIndex = numInStreams + i;
+ bond.PackIndex = _bindInfo.PackStreams[i];
+ _bindInfo.Bonds.Add(bond);
}
- _bindInfo.OutStreams.Clear();
+ _bindInfo.PackStreams.Clear();
/*
if (numCryptoStreams == 0)
@@ -428,37 +620,37 @@ HRESULT CEncoder::EncoderConstr()
for (i = 0; i < numCryptoStreams; i++)
{
- NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
CMethodFull method;
- method.NumInStreams = 1;
- method.NumOutStreams = 1;
- coderStreamsInfo.NumInStreams = method.NumOutStreams;
- coderStreamsInfo.NumOutStreams = method.NumInStreams;
+ method.NumStreams = 1;
method.Id = k_AES;
-
_options.Methods.Add(method);
- _bindInfo.Coders.Add(coderStreamsInfo);
- _bindInfo.OutStreams.Add(numOutStreams + i);
+
+ NCoderMixer2::CCoderStreamsInfo cod;
+ cod.NumStreams = 1;
+ _bindInfo.Coders.Add(cod);
+
+ _bindInfo.PackStreams.Add(numOutStreams++);
}
}
}
- for (int i = _options.Methods.Size() - 1; i >= 0; i--)
- {
- const CMethodFull &methodFull = _options.Methods[i];
- _decompressionMethods.Add(methodFull.Id);
- }
+ for (unsigned i = _options.Methods.Size(); i != 0;)
+ _decompressionMethods.Add(_options.Methods[--i].Id);
- _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo);
- _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo);
+ if (_bindInfo.Coders.Size() > 16)
+ return E_INVALIDARG;
+ if (_bindInfo.GetNum_Bonds_and_PackStreams() > 16)
+ return E_INVALIDARG;
+
+ if (!_bindInfo.CalcMapsAndCheck())
+ return E_INVALIDARG;
+
+ InitBindConv();
_constructed = true;
return S_OK;
}
-CEncoder::~CEncoder()
-{
- delete _bindReverseConverter;
-}
+CEncoder::~CEncoder() {}
}}
diff --git a/CPP/7zip/Archive/7z/7zEncode.h b/CPP/7zip/Archive/7z/7zEncode.h
index 8e20bdb5..f1a9b5ad 100644
--- a/CPP/7zip/Archive/7z/7zEncode.h
+++ b/CPP/7zip/Archive/7z/7zEncode.h
@@ -3,47 +3,82 @@
#ifndef __7Z_ENCODE_H
#define __7Z_ENCODE_H
-// #include "../../Common/StreamObjects.h"
-
#include "7zCompressionMode.h"
#include "../Common/CoderMixer2.h"
-#include "../Common/CoderMixer2MT.h"
-#ifdef _ST_MODE
-#include "../Common/CoderMixer2ST.h"
-#endif
-#include "7zItem.h"
-#include "../../Common/CreateCoder.h"
+#include "7zItem.h"
namespace NArchive {
namespace N7z {
-class CEncoder
+class CMtEncMultiProgress:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
{
- NCoderMixer::CCoderMixer2MT *_mixerCoderSpec;
- CMyComPtr<ICompressCoder2> _mixerCoder;
+ CMyComPtr<ICompressProgressInfo> _progress;
+ #ifndef _7ZIP_ST
+ NWindows::NSynchronization::CCriticalSection CriticalSection;
+ #endif
+
+public:
+ UInt64 OutSize;
+
+ CMtEncMultiProgress(): OutSize(0) {}
+
+ void Init(ICompressProgressInfo *progress);
- CObjectVector<CCoderInfo> _codersInfo;
+ void AddOutSize(UInt64 addOutSize)
+ {
+ #ifndef _7ZIP_ST
+ NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
+ #endif
+ OutSize += addOutSize;
+ }
+
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
+
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+class CEncoder
+{
+ #ifdef USE_MIXER_ST
+ NCoderMixer2::CMixerST *_mixerST;
+ #endif
+ #ifdef USE_MIXER_MT
+ NCoderMixer2::CMixerMT *_mixerMT;
+ #endif
+
+ NCoderMixer2::CMixer *_mixer;
+ CMyComPtr<IUnknown> _mixerRef;
CCompressionMethodMode _options;
- NCoderMixer::CBindInfo _bindInfo;
- NCoderMixer::CBindInfo _decompressBindInfo;
- NCoderMixer::CBindReverseConverter *_bindReverseConverter;
+ NCoderMixer2::CBindInfo _bindInfo;
CRecordVector<CMethodId> _decompressionMethods;
+ CRecordVector<UInt32> _SrcIn_to_DestOut;
+ CRecordVector<UInt32> _SrcOut_to_DestIn;
+ // CRecordVector<UInt32> _DestIn_to_SrcOut;
+ CRecordVector<UInt32> _DestOut_to_SrcIn;
+
+ void InitBindConv();
+ void SetFolder(CFolder &folder);
+
HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS
const UInt64 *inSizeForReduce);
bool _constructed;
public:
+
CEncoder(const CCompressionMethodMode &options);
~CEncoder();
HRESULT EncoderConstr();
HRESULT Encode(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream,
- const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
+ // const UInt64 *inStreamSize,
+ const UInt64 *inSizeForReduce,
CFolder &folderItem,
CRecordVector<UInt64> &coderUnpackSizes,
UInt64 &unpackSize,
diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp
index 6d2c5b06..d21bafdb 100644
--- a/CPP/7zip/Archive/7z/7zExtract.cpp
+++ b/CPP/7zip/Archive/7z/7zExtract.cpp
@@ -2,205 +2,327 @@
#include "StdAfx.h"
+#include "../../../../C/7zCrc.h"
+
#include "../../../Common/ComTry.h"
#include "../../Common/ProgressUtils.h"
#include "7zDecode.h"
-// #include "7z1Decode.h"
-#include "7zFolderOutStream.h"
#include "7zHandler.h"
+// EXTERN_g_ExternalCodecs
+
namespace NArchive {
namespace N7z {
-struct CExtractFolderInfo
+class CFolderOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
{
- #ifdef _7Z_VOL
- int VolumeIndex;
- #endif
- CNum FileIndex;
- CNum FolderIndex;
- CBoolVector ExtractStatuses;
- UInt64 UnpackSize;
- CExtractFolderInfo(
- #ifdef _7Z_VOL
- int volumeIndex,
- #endif
- CNum fileIndex, CNum folderIndex):
- #ifdef _7Z_VOL
- VolumeIndex(volumeIndex),
- #endif
- FileIndex(fileIndex),
- FolderIndex(folderIndex),
- UnpackSize(0)
+ CMyComPtr<ISequentialOutStream> _stream;
+public:
+ bool TestMode;
+ bool CheckCrc;
+private:
+ bool _fileIsOpen;
+ bool _calcCrc;
+ UInt32 _crc;
+ UInt64 _rem;
+
+ const UInt32 *_indexes;
+ unsigned _numFiles;
+ unsigned _fileIndex;
+
+ HRESULT OpenFile(bool isCorrupted = false);
+ HRESULT CloseFile_and_SetResult(Int32 res);
+ HRESULT CloseFile();
+ HRESULT ProcessEmptyFiles();
+
+public:
+ MY_UNKNOWN_IMP1(ISequentialOutStream)
+
+ const CDbEx *_db;
+ CMyComPtr<IArchiveExtractCallback> ExtractCallback;
+
+ bool ExtraWriteWasCut;
+
+ CFolderOutStream():
+ TestMode(false),
+ CheckCrc(true)
+ {}
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+
+ HRESULT Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles);
+ HRESULT FlushCorrupted(Int32 callbackOperationResult);
+
+ bool WasWritingFinished() const { return _numFiles == 0; }
+};
+
+
+HRESULT CFolderOutStream::Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles)
+{
+ _fileIndex = startIndex;
+ _indexes = indexes;
+ _numFiles = numFiles;
+
+ _fileIsOpen = false;
+ ExtraWriteWasCut = false;
+
+ return ProcessEmptyFiles();
+}
+
+HRESULT CFolderOutStream::OpenFile(bool isCorrupted)
+{
+ const CFileItem &fi = _db->Files[_fileIndex];
+ UInt32 nextFileIndex = (_indexes ? *_indexes : _fileIndex);
+ Int32 askMode = (_fileIndex == nextFileIndex) ?
+ (TestMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract) :
+ NExtract::NAskMode::kSkip;
+
+ if (isCorrupted
+ && askMode == NExtract::NAskMode::kExtract
+ && !_db->IsItemAnti(_fileIndex)
+ && !fi.IsDir)
+ askMode = NExtract::NAskMode::kTest;
+
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ RINOK(ExtractCallback->GetStream(_fileIndex, &realOutStream, askMode));
+
+ _stream = realOutStream;
+ _crc = CRC_INIT_VAL;
+ _calcCrc = (CheckCrc && fi.CrcDefined && !fi.IsDir);
+
+ _fileIsOpen = true;
+ _rem = fi.Size;
+
+ if (askMode == NExtract::NAskMode::kExtract
+ && !realOutStream
+ && !_db->IsItemAnti(_fileIndex)
+ && !fi.IsDir)
+ askMode = NExtract::NAskMode::kSkip;
+ return ExtractCallback->PrepareOperation(askMode);
+}
+
+HRESULT CFolderOutStream::CloseFile_and_SetResult(Int32 res)
+{
+ _stream.Release();
+ _fileIsOpen = false;
+
+ if (!_indexes)
+ _numFiles--;
+ else if (*_indexes == _fileIndex)
+ {
+ _indexes++;
+ _numFiles--;
+ }
+
+ _fileIndex++;
+ return ExtractCallback->SetOperationResult(res);
+}
+
+HRESULT CFolderOutStream::CloseFile()
+{
+ const CFileItem &fi = _db->Files[_fileIndex];
+ return CloseFile_and_SetResult((!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc)) ?
+ NExtract::NOperationResult::kOK :
+ NExtract::NOperationResult::kCRCError);
+}
+
+HRESULT CFolderOutStream::ProcessEmptyFiles()
+{
+ while (_numFiles != 0 && _db->Files[_fileIndex].Size == 0)
{
- if (fileIndex != kNumNoIndex)
+ RINOK(OpenFile());
+ RINOK(CloseFile());
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+
+ while (size != 0)
+ {
+ if (_fileIsOpen)
{
- ExtractStatuses.ClearAndSetSize(1);
- ExtractStatuses[0] = true;
+ UInt32 cur = (size < _rem ? size : (UInt32)_rem);
+ HRESULT result = S_OK;
+ if (_stream)
+ result = _stream->Write(data, cur, &cur);
+ if (_calcCrc)
+ _crc = CrcUpdate(_crc, data, cur);
+ if (processedSize)
+ *processedSize += cur;
+ data = (const Byte *)data + cur;
+ size -= cur;
+ _rem -= cur;
+ if (_rem == 0)
+ {
+ RINOK(CloseFile());
+ RINOK(ProcessEmptyFiles());
+ }
+ RINOK(result);
+ if (cur == 0)
+ break;
+ continue;
}
- };
-};
+
+ RINOK(ProcessEmptyFiles());
+ if (_numFiles == 0)
+ {
+ // we support partial extracting
+ /*
+ if (processedSize)
+ *processedSize += size;
+ break;
+ */
+ ExtraWriteWasCut = true;
+ // return S_FALSE;
+ return k_My_HRESULT_WritingWasCut;
+ }
+ RINOK(OpenFile());
+ }
+
+ return S_OK;
+}
+
+HRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult)
+{
+ while (_numFiles != 0)
+ {
+ if (_fileIsOpen)
+ {
+ RINOK(CloseFile_and_SetResult(callbackOperationResult));
+ }
+ else
+ {
+ RINOK(OpenFile(true));
+ }
+ }
+ return S_OK;
+}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)
{
COM_TRY_BEGIN
- bool testMode = (testModeSpec != 0);
+
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
+
UInt64 importantTotalUnpacked = 0;
+ // numItems = (UInt32)(Int32)-1;
+
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
if (allFilesMode)
- numItems =
- #ifdef _7Z_VOL
- _refs.Size();
- #else
- _db.Files.Size();
- #endif
+ numItems = _db.Files.Size();
- if(numItems == 0)
+ if (numItems == 0)
return S_OK;
- /*
- if(_volumes.Size() != 1)
- return E_FAIL;
- const CVolume &volume = _volumes.Front();
- const CDbEx &_db = volume.Database;
- IInStream *_inStream = volume.Stream;
- */
-
- CObjectVector<CExtractFolderInfo> extractFolderInfoVector;
- for (UInt32 ii = 0; ii < numItems; ii++)
{
- // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex];
- UInt32 ref2Index = allFilesMode ? ii : indices[ii];
- // const CRef2 &ref2 = _refs[ref2Index];
-
- // for (UInt32 ri = 0; ri < ref2.Refs.Size(); ri++)
+ CNum prevFolder = kNumNoIndex;
+ UInt32 nextFile = 0;
+
+ UInt32 i;
+
+ for (i = 0; i < numItems; i++)
{
- #ifdef _7Z_VOL
- // const CRef &ref = ref2.Refs[ri];
- const CRef &ref = _refs[ref2Index];
-
- int volumeIndex = ref.VolumeIndex;
- const CVolume &volume = _volumes[volumeIndex];
- const CDbEx &db = volume.Database;
- UInt32 fileIndex = ref.ItemIndex;
- #else
- const CDbEx &db = _db;
- UInt32 fileIndex = ref2Index;
- #endif
-
- CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex];
+ UInt32 fileIndex = allFilesMode ? i : indices[i];
+ CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
if (folderIndex == kNumNoIndex)
- {
- extractFolderInfoVector.Add(CExtractFolderInfo(
- #ifdef _7Z_VOL
- volumeIndex,
- #endif
- fileIndex, kNumNoIndex));
continue;
- }
- if (extractFolderInfoVector.IsEmpty() ||
- folderIndex != extractFolderInfoVector.Back().FolderIndex
- #ifdef _7Z_VOL
- || volumeIndex != extractFolderInfoVector.Back().VolumeIndex
- #endif
- )
- {
- extractFolderInfoVector.Add(CExtractFolderInfo(
- #ifdef _7Z_VOL
- volumeIndex,
- #endif
- kNumNoIndex, folderIndex));
- UInt64 unpackSize = db.GetFolderUnpackSize(folderIndex);
- importantTotalUnpacked += unpackSize;
- extractFolderInfoVector.Back().UnpackSize = unpackSize;
- }
-
- CExtractFolderInfo &efi = extractFolderInfoVector.Back();
-
- // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex];
- CNum startIndex = db.FolderStartFileIndex[folderIndex];
- for (CNum index = efi.ExtractStatuses.Size();
- index <= fileIndex - startIndex; index++)
- {
- // UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize;
- // Count partial_folder_size
- // efi.UnpackSize += unpackSize;
- // importantTotalUnpacked += unpackSize;
- efi.ExtractStatuses.Add(index == fileIndex - startIndex);
- }
+ if (folderIndex != prevFolder || fileIndex < nextFile)
+ nextFile = _db.FolderStartFileIndex[folderIndex];
+ for (CNum index = nextFile; index <= fileIndex; index++)
+ importantTotalUnpacked += _db.Files[index].Size;
+ nextFile = fileIndex + 1;
+ prevFolder = folderIndex;
}
}
RINOK(extractCallback->SetTotal(importantTotalUnpacked));
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(extractCallback, false);
+
CDecoder decoder(
- #ifdef _ST_MODE
- false
+ #ifndef USE_MIXER_ST
+ false
#else
- true
+ _useMultiThreadMixer
#endif
);
- // CDecoder1 decoder;
- UInt64 totalPacked = 0;
- UInt64 totalUnpacked = 0;
UInt64 curPacked, curUnpacked;
- CLocalProgress *lps = new CLocalProgress;
- CMyComPtr<ICompressProgressInfo> progress = lps;
- lps->Init(extractCallback, false);
+ CMyComPtr<IArchiveExtractCallbackMessage> callbackMessage;
+ extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage, &callbackMessage);
+
+ CFolderOutStream *folderOutStream = new CFolderOutStream;
+ CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
- for (unsigned i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked)
+ folderOutStream->_db = &_db;
+ folderOutStream->ExtractCallback = extractCallback;
+ folderOutStream->TestMode = (testModeSpec != 0);
+ folderOutStream->CheckCrc = (_crcSize != 0);
+
+ for (UInt32 i = 0;; lps->OutSize += curUnpacked, lps->InSize += curPacked)
{
- lps->OutSize = totalUnpacked;
- lps->InSize = totalPacked;
RINOK(lps->SetCur());
- if (i >= extractFolderInfoVector.Size())
+ if (i >= numItems)
break;
-
- const CExtractFolderInfo &efi = extractFolderInfoVector[i];
- curUnpacked = efi.UnpackSize;
+
+ curUnpacked = 0;
curPacked = 0;
- CFolderOutStream *folderOutStream = new CFolderOutStream;
- CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
+ UInt32 fileIndex = allFilesMode ? i : indices[i];
+ CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
- #ifdef _7Z_VOL
- const CVolume &volume = _volumes[efi.VolumeIndex];
- const CDbEx &db = volume.Database;
- #else
- const CDbEx &db = _db;
- #endif
+ UInt32 numSolidFiles = 1;
- CNum startIndex;
- if (efi.FileIndex != kNumNoIndex)
- startIndex = efi.FileIndex;
- else
- startIndex = db.FolderStartFileIndex[efi.FolderIndex];
+ if (folderIndex != kNumNoIndex)
+ {
+ curPacked = _db.GetFolderFullPackSize(folderIndex);
+ UInt32 nextFile = fileIndex + 1;
+ fileIndex = _db.FolderStartFileIndex[folderIndex];
+ UInt32 k;
+
+ for (k = i + 1; k < numItems; k++)
+ {
+ UInt32 fileIndex2 = allFilesMode ? k : indices[k];
+ if (_db.FileIndexToFolderIndexMap[fileIndex2] != folderIndex
+ || fileIndex2 < nextFile)
+ break;
+ nextFile = fileIndex2 + 1;
+ }
+
+ numSolidFiles = k - i;
+
+ for (k = fileIndex; k < nextFile; k++)
+ curUnpacked += _db.Files[k].Size;
+ }
+
+ HRESULT result = folderOutStream->Init(fileIndex,
+ allFilesMode ? NULL : indices + i,
+ numSolidFiles);
- HRESULT result = folderOutStream->Init(&db,
- #ifdef _7Z_VOL
- volume.StartRef2Index,
- #else
- 0,
- #endif
- startIndex,
- &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0);
+ i += numSolidFiles;
RINOK(result);
- if (efi.FileIndex != kNumNoIndex)
+ // to test solid block with zero unpacked size we disable that code
+ if (folderOutStream->WasWritingFinished())
continue;
- CNum folderIndex = efi.FolderIndex;
- curPacked = _db.GetFolderFullPackSize(folderIndex);
-
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
if (extractCallback)
@@ -212,50 +334,64 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
#ifndef _NO_CRYPTO
bool isEncrypted = false;
bool passwordIsDefined = false;
+ UString password;
#endif
+
HRESULT result = decoder.Decode(
EXTERNAL_CODECS_VARS
- #ifdef _7Z_VOL
- volume.Stream,
- #else
- _inStream,
- #endif
- db.ArcInfo.DataStartPosition,
- db, folderIndex,
+ _inStream,
+ _db.ArcInfo.DataStartPosition,
+ _db, folderIndex,
+ &curUnpacked,
+
outStream,
- progress
+ progress,
+ NULL // *inStreamMainRes
+
_7Z_DECODER_CRYPRO_VARS
#if !defined(_7ZIP_ST) && !defined(_SFX)
, true, _numThreads
#endif
);
- if (result == S_FALSE)
+ if (result == S_FALSE || result == E_NOTIMPL)
{
- RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
- continue;
- }
- if (result == E_NOTIMPL)
- {
- RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnsupportedMethod));
+ bool wasFinished = folderOutStream->WasWritingFinished();
+
+ int resOp = (result == S_FALSE ?
+ NExtract::NOperationResult::kDataError :
+ NExtract::NOperationResult::kUnsupportedMethod);
+
+ RINOK(folderOutStream->FlushCorrupted(resOp));
+
+ if (wasFinished)
+ {
+ // we don't show error, if it's after required files
+ if (/* !folderOutStream->ExtraWriteWasCut && */ callbackMessage)
+ {
+ RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, resOp));
+ }
+ }
continue;
}
+
if (result != S_OK)
return result;
- if (folderOutStream->WasWritingFinished() != S_OK)
- {
- RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
- continue;
- }
+
+ RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
+ continue;
}
catch(...)
{
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
- continue;
+ // continue;
+ return E_FAIL;
}
}
+
return S_OK;
+
COM_TRY_END
}
diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
index 3f420a51..14cdc436 100644
--- a/CPP/7zip/Archive/7z/7zFolderInStream.cpp
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
@@ -7,96 +7,103 @@
namespace NArchive {
namespace N7z {
-CFolderInStream::CFolderInStream()
-{
- _inStreamWithHashSpec = new CSequentialInStreamWithCRC;
- _inStreamWithHash = _inStreamWithHashSpec;
-}
-
void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
- const UInt32 *fileIndices, UInt32 numFiles)
+ const UInt32 *indexes, unsigned numFiles)
{
_updateCallback = updateCallback;
+ _indexes = indexes;
_numFiles = numFiles;
- _fileIndex = 0;
- _fileIndices = fileIndices;
- Processed.Clear();
- CRCs.Clear();
- Sizes.Clear();
- _fileIsOpen = false;
- _currentSizeIsDefined = false;
+ _index = 0;
+
+ Processed.ClearAndReserve(numFiles);
+ CRCs.ClearAndReserve(numFiles);
+ Sizes.ClearAndReserve(numFiles);
+
+ _pos = 0;
+ _crc = CRC_INIT_VAL;
+ _size_Defined = false;
+ _size = 0;
+
+ _stream.Release();
}
HRESULT CFolderInStream::OpenStream()
{
- _filePos = 0;
- while (_fileIndex < _numFiles)
+ _pos = 0;
+ _crc = CRC_INIT_VAL;
+ _size_Defined = false;
+ _size = 0;
+
+ while (_index < _numFiles)
{
CMyComPtr<ISequentialInStream> stream;
- HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream);
- if (result != S_OK && result != S_FALSE)
- return result;
- _fileIndex++;
- _inStreamWithHashSpec->SetStream(stream);
- _inStreamWithHashSpec->Init();
+ HRESULT result = _updateCallback->GetStream(_indexes[_index], &stream);
+ if (result != S_OK)
+ {
+ if (result != S_FALSE)
+ return result;
+ }
+
+ _stream = stream;
+
if (stream)
{
- _fileIsOpen = true;
CMyComPtr<IStreamGetSize> streamGetSize;
stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
if (streamGetSize)
{
- RINOK(streamGetSize->GetSize(&_currentSize));
- _currentSizeIsDefined = true;
+ if (streamGetSize->GetSize(&_size) == S_OK)
+ _size_Defined = true;
}
return S_OK;
}
+
+ _index++;
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
- Sizes.Add(0);
- Processed.Add(result == S_OK);
- AddDigest();
+ AddFileInfo(result == S_OK);
}
return S_OK;
}
-void CFolderInStream::AddDigest()
+void CFolderInStream::AddFileInfo(bool isProcessed)
{
- CRCs.Add(_inStreamWithHashSpec->GetCRC());
-}
-
-HRESULT CFolderInStream::CloseStream()
-{
- RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
- _inStreamWithHashSpec->ReleaseStream();
- _fileIsOpen = false;
- _currentSizeIsDefined = false;
- Processed.Add(true);
- Sizes.Add(_filePos);
- AddDigest();
- return S_OK;
+ Processed.Add(isProcessed);
+ Sizes.Add(_pos);
+ CRCs.Add(CRC_GET_DIGEST(_crc));
}
STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != 0)
+ if (processedSize)
*processedSize = 0;
- while (size > 0)
+ while (size != 0)
{
- if (_fileIsOpen)
+ if (_stream)
{
UInt32 processed2;
- RINOK(_inStreamWithHash->Read(data, size, &processed2));
- if (processed2 == 0)
+ RINOK(_stream->Read(data, size, &processed2));
+ if (processed2 != 0)
{
- RINOK(CloseStream());
- continue;
+ _crc = CrcUpdate(_crc, data, processed2);
+ _pos += processed2;
+ if (processedSize)
+ *processedSize = processed2;
+ return S_OK;
}
- if (processedSize != 0)
- *processedSize = processed2;
- _filePos += processed2;
- break;
+
+ _stream.Release();
+ _index++;
+ AddFileInfo(true);
+
+ _pos = 0;
+ _crc = CRC_INIT_VAL;
+ _size_Defined = false;
+ _size = 0;
+
+ RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
}
- if (_fileIndex >= _numFiles)
+
+ if (_index >= _numFiles)
break;
RINOK(OpenStream());
}
@@ -106,17 +113,23 @@ STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSiz
STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
{
*value = 0;
- unsigned index2 = (unsigned)subStream;
if (subStream > Sizes.Size())
- return E_FAIL;
- if (index2 < Sizes.Size())
+ return S_FALSE; // E_FAIL;
+
+ unsigned index = (unsigned)subStream;
+ if (index < Sizes.Size())
{
- *value = Sizes[index2];
+ *value = Sizes[index];
return S_OK;
}
- if (!_currentSizeIsDefined)
+
+ if (!_size_Defined)
+ {
+ *value = _pos;
return S_FALSE;
- *value = _currentSize;
+ }
+
+ *value = (_pos > _size ? _pos : _size);
return S_OK;
}
diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.h b/CPP/7zip/Archive/7z/7zFolderInStream.h
index 4ed4b2dd..805db54e 100644
--- a/CPP/7zip/Archive/7z/7zFolderInStream.h
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.h
@@ -3,11 +3,13 @@
#ifndef __7Z_FOLDER_IN_STREAM_H
#define __7Z_FOLDER_IN_STREAM_H
+#include "../../../../C/7zCrc.h"
+
+#include "../../../Common/MyCom.h"
+#include "../../../Common/MyVector.h"
+
#include "../../ICoder.h"
#include "../IArchive.h"
-#include "../Common/InStreamWithCRC.h"
-
-#include "7zItem.h"
namespace NArchive {
namespace N7z {
@@ -17,33 +19,34 @@ class CFolderInStream:
public ICompressGetSubStreamSize,
public CMyUnknownImp
{
- CSequentialInStreamWithCRC *_inStreamWithHashSpec;
- CMyComPtr<ISequentialInStream> _inStreamWithHash;
- CMyComPtr<IArchiveUpdateCallback> _updateCallback;
+ CMyComPtr<ISequentialInStream> _stream;
+ UInt64 _pos;
+ UInt32 _crc;
+ bool _size_Defined;
+ UInt64 _size;
- bool _currentSizeIsDefined;
- bool _fileIsOpen;
- UInt64 _currentSize;
- UInt64 _filePos;
- const UInt32 *_fileIndices;
- UInt32 _numFiles;
- UInt32 _fileIndex;
+ const UInt32 *_indexes;
+ unsigned _numFiles;
+ unsigned _index;
+
+ CMyComPtr<IArchiveUpdateCallback> _updateCallback;
HRESULT OpenStream();
- HRESULT CloseStream();
- void AddDigest();
+ void AddFileInfo(bool isProcessed);
public:
CRecordVector<bool> Processed;
CRecordVector<UInt32> CRCs;
CRecordVector<UInt64> Sizes;
- MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
+ MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
- CFolderInStream();
- void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles);
+ void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles);
+
+ bool WasFinished() const { return _index == _numFiles; }
+
UInt64 GetFullSize() const
{
UInt64 size = 0;
diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
index 847f65bf..e63ee925 100644
--- a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
+++ b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
@@ -1,149 +1,3 @@
// 7zFolderOutStream.cpp
#include "StdAfx.h"
-
-#include "7zFolderOutStream.h"
-
-namespace NArchive {
-namespace N7z {
-
-CFolderOutStream::CFolderOutStream()
-{
- _crcStreamSpec = new COutStreamWithCRC;
- _crcStream = _crcStreamSpec;
-}
-
-HRESULT CFolderOutStream::Init(
- const CDbEx *db,
- UInt32 ref2Offset, UInt32 startIndex,
- const CBoolVector *extractStatuses,
- IArchiveExtractCallback *extractCallback,
- bool testMode, bool checkCrc)
-{
- _db = db;
- _ref2Offset = ref2Offset;
- _startIndex = startIndex;
-
- _extractStatuses = extractStatuses;
- _extractCallback = extractCallback;
- _testMode = testMode;
- _checkCrc = checkCrc;
-
- _currentIndex = 0;
- _fileIsOpen = false;
- return ProcessEmptyFiles();
-}
-
-HRESULT CFolderOutStream::OpenFile()
-{
- Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ?
- NExtract::NAskMode::kTest :
- NExtract::NAskMode::kExtract) :
- NExtract::NAskMode::kSkip;
- CMyComPtr<ISequentialOutStream> realOutStream;
- UInt32 index = _startIndex + _currentIndex;
- RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
- _crcStreamSpec->SetStream(realOutStream);
- _crcStreamSpec->Init(_checkCrc);
- _fileIsOpen = true;
- const CFileItem &fi = _db->Files[index];
- _rem = fi.Size;
- if (askMode == NExtract::NAskMode::kExtract && !realOutStream &&
- !_db->IsItemAnti(index) && !fi.IsDir)
- askMode = NExtract::NAskMode::kSkip;
- return _extractCallback->PrepareOperation(askMode);
-}
-
-HRESULT CFolderOutStream::CloseFileAndSetResult(Int32 res)
-{
- _crcStreamSpec->ReleaseStream();
- _fileIsOpen = false;
- _currentIndex++;
- return _extractCallback->SetOperationResult(res);
-}
-
-HRESULT CFolderOutStream::CloseFileAndSetResult()
-{
- const CFileItem &fi = _db->Files[_startIndex + _currentIndex];
- return CloseFileAndSetResult(
- (fi.IsDir || !fi.CrcDefined || !_checkCrc || fi.Crc == _crcStreamSpec->GetCRC()) ?
- NExtract::NOperationResult::kOK :
- NExtract::NOperationResult::kCRCError);
-}
-
-HRESULT CFolderOutStream::ProcessEmptyFiles()
-{
- while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)
- {
- RINOK(OpenFile());
- RINOK(CloseFileAndSetResult());
- }
- return S_OK;
-}
-
-STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
-{
- if (processedSize != NULL)
- *processedSize = 0;
- while (size != 0)
- {
- if (_fileIsOpen)
- {
- UInt32 cur = size < _rem ? size : (UInt32)_rem;
- RINOK(_crcStream->Write(data, cur, &cur));
- if (cur == 0)
- break;
- data = (const Byte *)data + cur;
- size -= cur;
- _rem -= cur;
- if (processedSize != NULL)
- *processedSize += cur;
- if (_rem == 0)
- {
- RINOK(CloseFileAndSetResult());
- RINOK(ProcessEmptyFiles());
- continue;
- }
- }
- else
- {
- RINOK(ProcessEmptyFiles());
- if (_currentIndex == _extractStatuses->Size())
- {
- // we support partial extracting
- if (processedSize != NULL)
- *processedSize += size;
- break;
- }
- RINOK(OpenFile());
- }
- }
- return S_OK;
-}
-
-STDMETHODIMP CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
-{
- *value = 0;
- if ((int)subStream >= _extractStatuses->Size())
- return S_FALSE;
- *value = _db->Files[_startIndex + (int)subStream].Size;
- return S_OK;
-}
-
-HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
-{
- while (_currentIndex < _extractStatuses->Size())
- {
- if (_fileIsOpen)
- {
- RINOK(CloseFileAndSetResult(resultEOperationResult));
- }
- else
- {
- RINOK(OpenFile());
- }
- }
- return S_OK;
-}
-
-}}
diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.h b/CPP/7zip/Archive/7z/7zFolderOutStream.h
index cc2d7734..a32b22e0 100644
--- a/CPP/7zip/Archive/7z/7zFolderOutStream.h
+++ b/CPP/7zip/Archive/7z/7zFolderOutStream.h
@@ -3,56 +3,4 @@
#ifndef __7Z_FOLDER_OUT_STREAM_H
#define __7Z_FOLDER_OUT_STREAM_H
-#include "../../IStream.h"
-#include "../IArchive.h"
-#include "../Common/OutStreamWithCRC.h"
-
-#include "7zIn.h"
-
-namespace NArchive {
-namespace N7z {
-
-class CFolderOutStream:
- public ISequentialOutStream,
- public ICompressGetSubStreamSize,
- public CMyUnknownImp
-{
- COutStreamWithCRC *_crcStreamSpec;
- CMyComPtr<ISequentialOutStream> _crcStream;
- const CDbEx *_db;
- const CBoolVector *_extractStatuses;
- CMyComPtr<IArchiveExtractCallback> _extractCallback;
- UInt32 _ref2Offset;
- UInt32 _startIndex;
- unsigned _currentIndex;
- bool _testMode;
- bool _checkCrc;
- bool _fileIsOpen;
- UInt64 _rem;
-
- HRESULT OpenFile();
- HRESULT CloseFileAndSetResult(Int32 res);
- HRESULT CloseFileAndSetResult();
- HRESULT ProcessEmptyFiles();
-public:
- MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
-
- CFolderOutStream();
-
- STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
- STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
-
- HRESULT Init(
- const CDbEx *db,
- UInt32 ref2Offset, UInt32 startIndex,
- const CBoolVector *extractStatuses,
- IArchiveExtractCallback *extractCallback,
- bool testMode, bool checkCrc);
- HRESULT FlushCorrupted(Int32 resultEOperationResult);
- HRESULT WasWritingFinished() const
- { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }
-};
-
-}}
-
#endif
diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp
index 2b86ed22..d397e818 100644
--- a/CPP/7zip/Archive/7z/7zHandler.cpp
+++ b/CPP/7zip/Archive/7z/7zHandler.cpp
@@ -150,22 +150,12 @@ static char *AddProp32(char *s, const char *name, UInt32 v)
void CHandler::AddMethodName(AString &s, UInt64 id)
{
- UString methodName;
- FindMethod(EXTERNAL_CODECS_VARS id, methodName);
- if (methodName.IsEmpty())
- {
- for (unsigned i = 0; i < methodName.Len(); i++)
- if (methodName[i] >= 0x80)
- {
- methodName.Empty();
- break;
- }
- }
- if (methodName.IsEmpty())
+ AString name;
+ FindMethod(EXTERNAL_CODECS_VARS id, name);
+ if (name.IsEmpty())
ConvertMethodIdToString(s, id);
else
- for (unsigned i = 0; i < methodName.Len(); i++)
- s += (char)methodName[i];
+ s += name;
}
#endif
@@ -186,8 +176,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
FOR_VECTOR (i, pm.IDs)
{
UInt64 id = pm.IDs[i];
- if (!s.IsEmpty())
- s += ' ';
+ s.Add_Space_if_NotEmpty();
char temp[16];
if (id == k_LZMA2)
{
@@ -376,6 +365,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
// numCoders == 0 ???
CNum numCoders = inByte.ReadNum();
bool needSpace = false;
+
for (; numCoders != 0; numCoders--, needSpace = true)
{
if (pos < 32) // max size of property
@@ -500,17 +490,8 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
}
else
{
- UString methodName;
+ AString methodName;
FindMethod(EXTERNAL_CODECS_VARS id64, methodName);
- if (methodName.IsEmpty())
- {
- for (unsigned j = 0; j < methodName.Len(); j++)
- if (methodName[j] >= 0x80)
- {
- methodName.Empty();
- break;
- }
- }
if (needSpace)
temp[--pos] = ' ';
if (methodName.IsEmpty())
@@ -522,10 +503,11 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
break;
pos -= len;
for (unsigned i = 0; i < len; i++)
- temp[pos + i] = (char)methodName[i];
+ temp[pos + i] = methodName[i];
}
}
}
+
if (numCoders != 0 && pos >= 4)
{
temp[--pos] = ' ';
@@ -533,6 +515,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
temp[--pos] = '.';
temp[--pos] = '.';
}
+
return PropVarEm_Set_Str(prop, temp + pos);
// }
}
@@ -555,7 +538,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
const CFileItem &item = _db.Files[index];
UInt32 index2 = index;
- switch(propID)
+ switch (propID)
{
case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;
case kpidSize:
@@ -608,7 +591,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
*/
case kpidPath: return _db.GetPath_Prop(index, value);
+
#ifndef _SFX
+
case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);
case kpidBlock:
{
@@ -617,30 +602,29 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
PropVarEm_Set_UInt32(value, (UInt32)folderIndex);
}
break;
+ /*
case kpidPackedSize0:
case kpidPackedSize1:
case kpidPackedSize2:
case kpidPackedSize3:
case kpidPackedSize4:
{
- /*
CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex)
{
- const CFolder &folderInfo = _db.Folders[folderIndex];
if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
- folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))
+ _db.FoStartPackStreamIndex[folderIndex + 1] -
+ _db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0))
{
- prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);
+ PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0));
}
- else
- prop = (UInt64)0;
}
else
- prop = (UInt64)0;
- */
+ PropVarEm_Set_UInt64(value, 0);
}
break;
+ */
+
#endif
}
// prop.Detach(value);
@@ -668,7 +652,13 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
#endif
- CInArchive archive;
+ CInArchive archive(
+ #ifdef __7Z_SET_PROPERTIES
+ _useMultiThreadMixer
+ #else
+ true
+ #endif
+ );
_db.IsArc = false;
RINOK(archive.Open(stream, maxCheckStartPosition));
_db.IsArc = true;
@@ -677,7 +667,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
EXTERNAL_CODECS_VARS
_db
#ifndef _NO_CRYPTO
- , getTextPassword, _isEncrypted, _passwordIsDefined
+ , getTextPassword, _isEncrypted, _passwordIsDefined, _password
#endif
);
RINOK(result);
@@ -688,8 +678,9 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
{
Close();
// return E_INVALIDARG;
+ // return S_FALSE;
// we must return out_of_memory here
- return S_FALSE;
+ return E_OUTOFMEMORY;
}
// _inStream = stream;
#ifndef _SFX
@@ -707,6 +698,7 @@ STDMETHODIMP CHandler::Close()
#ifndef _NO_CRYPTO
_isEncrypted = false;
_passwordIsDefined = false;
+ _password.Empty();
#endif
return S_OK;
COM_TRY_END
@@ -715,11 +707,12 @@ STDMETHODIMP CHandler::Close()
#ifdef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
COM_TRY_BEGIN
const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
_numThreads = numProcessors;
+ _useMultiThreadMixer = true;
for (UInt32 i = 0; i < numProps; i++)
{
@@ -732,7 +725,8 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
int index = ParseStringToUInt32(name, number);
if (index == 0)
{
- if (name.IsPrefixedBy(L"mt"))
+ if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
+ if (name.IsPrefixedBy_Ascii_NoCase("mt"))
{
RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads));
continue;
diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h
index c33617c4..8a078e19 100644
--- a/CPP/7zip/Archive/7z/7zHandler.h
+++ b/CPP/7zip/Archive/7z/7zHandler.h
@@ -18,16 +18,6 @@
namespace NArchive {
namespace N7z {
-const UInt32 k_Copy = 0x0;
-const UInt32 k_Delta = 3;
-const UInt32 k_LZMA2 = 0x21;
-const UInt32 k_LZMA = 0x030101;
-const UInt32 k_PPMD = 0x030401;
-const UInt32 k_BCJ = 0x03030103;
-const UInt32 k_BCJ2 = 0x0303011B;
-const UInt32 k_Deflate = 0x040108;
-const UInt32 k_BZip2 = 0x040202;
-
#ifndef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
@@ -64,7 +54,9 @@ public:
CBoolPair Write_ATime;
CBoolPair Write_MTime;
- bool _volumeMode;
+ bool _useMultiThreadMixer;
+
+ // bool _volumeMode;
void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
@@ -117,7 +109,7 @@ public:
INTERFACE_IArchiveGetRawProps(;)
#ifdef __7Z_SET_PROPERTIES
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
#endif
#ifndef EXTRACT_ONLY
@@ -131,28 +123,29 @@ public:
private:
CMyComPtr<IInStream> _inStream;
NArchive::N7z::CDbEx _db;
+
#ifndef _NO_CRYPTO
bool _isEncrypted;
bool _passwordIsDefined;
+ UString _password;
#endif
#ifdef EXTRACT_ONLY
#ifdef __7Z_SET_PROPERTIES
UInt32 _numThreads;
+ bool _useMultiThreadMixer;
#endif
UInt32 _crcSize;
#else
- CRecordVector<CBind> _binds;
+ CRecordVector<CBond2> _bonds;
HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m);
HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod);
- void AddDefaultMethod();
- HRESULT SetMainMethod(CCompressionMethodMode &method,
- CObjectVector<COneMethodInfo> &methodsInfo
+ HRESULT SetMainMethod(CCompressionMethodMode &method
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
index 5e113207..5cab6a82 100644
--- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp
+++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -18,11 +18,11 @@ using namespace NWindows;
namespace NArchive {
namespace N7z {
-static const wchar_t *k_LZMA_Name = L"LZMA";
-static const wchar_t *kDefaultMethodName = L"LZMA2";
-static const wchar_t *k_Copy_Name = L"Copy";
+static const char *k_LZMA_Name = "LZMA";
+static const char *kDefaultMethodName = "LZMA2";
+static const char *k_Copy_Name = "Copy";
-static const wchar_t *k_MatchFinder_ForHeaders = L"BT2";
+static const char *k_MatchFinder_ForHeaders = "BT2";
static const UInt32 k_NumFastBytes_ForHeaders = 273;
static const UInt32 k_Level_ForHeaders = 5;
static const UInt32 k_Dictionary_ForHeaders =
@@ -42,7 +42,7 @@ HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodI
{
if (!FindMethod(
EXTERNAL_CODECS_VARS
- m.MethodName, dest.Id, dest.NumInStreams, dest.NumOutStreams))
+ m.MethodName, dest.Id, dest.NumStreams))
return E_INVALIDARG;
(CProps &)dest = (CProps &)m;
return S_OK;
@@ -54,48 +54,62 @@ HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod)
return S_OK;
COneMethodInfo m;
m.MethodName = k_LZMA_Name;
- m.AddPropString(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders);
- m.AddProp32(NCoderPropID::kLevel, k_Level_ForHeaders);
+ m.AddProp_Ascii(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders);
+ m.AddProp_Level(k_Level_ForHeaders);
m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders);
m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders);
- m.AddNumThreadsProp(1);
+ m.AddProp_NumThreads(1);
- CMethodFull methodFull;
- RINOK(PropsMethod_To_FullMethod(methodFull, m));
- headerMethod.Methods.Add(methodFull);
- return S_OK;
-}
-
-void CHandler::AddDefaultMethod()
-{
- FOR_VECTOR (i, _methods)
- {
- UString &methodName = _methods[i].MethodName;
- if (methodName.IsEmpty())
- methodName = kDefaultMethodName;
- }
- if (_methods.IsEmpty())
- {
- COneMethodInfo m;
- m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);
- _methods.Add(m);
- }
+ CMethodFull &methodFull = headerMethod.Methods.AddNew();
+ return PropsMethod_To_FullMethod(methodFull, m);
}
HRESULT CHandler::SetMainMethod(
- CCompressionMethodMode &methodMode,
- CObjectVector<COneMethodInfo> &methods
+ CCompressionMethodMode &methodMode
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
)
{
- AddDefaultMethod();
+ methodMode.Bonds = _bonds;
+
+ CObjectVector<COneMethodInfo> methods = _methods;
+
+ {
+ FOR_VECTOR (i, methods)
+ {
+ AString &methodName = methods[i].MethodName;
+ if (methodName.IsEmpty())
+ methodName = kDefaultMethodName;
+ }
+ if (methods.IsEmpty())
+ {
+ COneMethodInfo &m = methods.AddNew();
+ m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);
+ methodMode.DefaultMethod_was_Inserted = true;
+ }
+ }
+
+ if (!_filterMethod.MethodName.IsEmpty())
+ {
+ // if (methodMode.Bonds.IsEmpty())
+ {
+ FOR_VECTOR (k, methodMode.Bonds)
+ {
+ CBond2 &bond = methodMode.Bonds[k];
+ bond.InCoder++;
+ bond.OutCoder++;
+ }
+ methods.Insert(0, _filterMethod);
+ methodMode.Filter_was_Inserted = true;
+ }
+ }
const UInt64 kSolidBytes_Min = (1 << 24);
const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1;
bool needSolid = false;
+
FOR_VECTOR (i, methods)
{
COneMethodInfo &oneMethodInfo = methods[i];
@@ -105,9 +119,8 @@ HRESULT CHandler::SetMainMethod(
#endif
);
- CMethodFull methodFull;
+ CMethodFull &methodFull = methodMode.Methods.AddNew();
RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo));
- methodMode.Methods.Add(methodFull);
if (methodFull.Id != k_Copy)
needSolid = true;
@@ -125,6 +138,7 @@ HRESULT CHandler::SetMainMethod(
case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break;
default: continue;
}
+
_numSolidBytes = (UInt64)dicSize << 7;
if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min;
if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max;
@@ -517,18 +531,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
CCompressionMethodMode methodMode, headerMethod;
- HRESULT res = SetMainMethod(methodMode, _methods
+ HRESULT res = SetMainMethod(methodMode
#ifndef _7ZIP_ST
, _numThreads
#endif
);
RINOK(res);
- methodMode.Binds = _binds;
RINOK(SetHeaderMethod(headerMethod));
+
#ifndef _7ZIP_ST
methodMode.NumThreads = _numThreads;
+ methodMode.MultiThreadMixer = _useMultiThreadMixer;
headerMethod.NumThreads = 1;
+ headerMethod.MultiThreadMixer = _useMultiThreadMixer;
#endif
CMyComPtr<ICryptoGetTextPassword2> getPassword2;
@@ -542,7 +558,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
Int32 passwordIsDefined;
RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
- if (methodMode.PasswordIsDefined && (BSTR)password)
+ if (methodMode.PasswordIsDefined && password)
methodMode.Password = password;
}
@@ -550,6 +566,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
bool encryptHeaders = false;
+ #ifndef _NO_CRYPTO
+ if (!methodMode.PasswordIsDefined && _passwordIsDefined)
+ {
+ // if header is compressed, we use that password for updated archive
+ methodMode.PasswordIsDefined = true;
+ methodMode.Password = _password;
+ }
+ #endif
+
if (methodMode.PasswordIsDefined)
{
if (_encryptHeadersSpecified)
@@ -569,12 +594,14 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (numItems < 2)
compressMainHeader = false;
+ int level = GetLevel();
+
CUpdateOptions options;
options.Method = &methodMode;
- options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0;
- int level = GetLevel();
- options.UseFilters = level != 0 && _autoFilter;
- options.MaxFilter = level >= 8;
+ options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : NULL;
+ options.UseFilters = (level != 0 && _autoFilter && !methodMode.Filter_was_Inserted);
+ options.MaxFilter = (level >= 8);
+ options.AnalysisLevel = GetAnalysisLevel();
options.HeaderOptions.CompressMainHeader = compressMainHeader;
/*
@@ -587,7 +614,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options.NumSolidBytes = _numSolidBytes;
options.SolidExtension = _solidExtension;
options.RemoveSfxBlock = _removeSfxBlock;
- options.VolumeMode = _volumeMode;
+ // options.VolumeMode = _volumeMode;
+
+ options.MultiThreadMixer = _useMultiThreadMixer;
COutArchive archive;
CArchiveDatabaseOut newDatabase;
@@ -635,20 +664,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
COM_TRY_END
}
-static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream)
+static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream)
{
stream = 0;
int index = ParseStringToUInt32(srcString, coder);
if (index == 0)
return E_INVALIDARG;
- srcString.Delete(0, index);
+ srcString.DeleteFrontal(index);
if (srcString[0] == 's')
{
srcString.Delete(0);
int index = ParseStringToUInt32(srcString, stream);
if (index == 0)
return E_INVALIDARG;
- srcString.Delete(0, index);
+ srcString.DeleteFrontal(index);
}
return S_OK;
}
@@ -667,7 +696,10 @@ void COutHandler::InitProps()
Write_ATime.Init();
Write_MTime.Init();
- _volumeMode = false;
+ _useMultiThreadMixer = true;
+
+ // _volumeMode = false;
+
InitSolid();
}
@@ -762,7 +794,7 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
UInt32 number;
int index = ParseStringToUInt32(name, number);
- UString realName = name.Ptr(index);
+ // UString realName = name.Ptr(index);
if (index == 0)
{
if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock);
@@ -787,15 +819,17 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime);
if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime);
- if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
+ if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
+
+ // if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
}
return CMultiMethodProps::SetProperty(name, value);
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
COM_TRY_BEGIN
- _binds.Clear();
+ _bonds.Clear();
InitProps();
for (UInt32 i = 0; i < numProps; i++)
@@ -812,15 +846,19 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
if (value.vt != VT_EMPTY)
return E_INVALIDARG;
name.Delete(0);
- CBind bind;
- RINOK(GetBindInfoPart(name, bind.OutCoder, bind.OutStream));
+
+ CBond2 bond;
+ RINOK(ParseBond(name, bond.OutCoder, bond.OutStream));
if (name[0] != ':')
return E_INVALIDARG;
name.Delete(0);
- RINOK(GetBindInfoPart(name, bind.InCoder, bind.InStream));
+ UInt32 inStream = 0;
+ RINOK(ParseBond(name, bond.InCoder, inStream));
+ if (inStream != 0)
+ return E_INVALIDARG;
if (!name.IsEmpty())
return E_INVALIDARG;
- _binds.Add(bind);
+ _bonds.Add(bond);
continue;
}
@@ -831,40 +869,27 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
if (numEmptyMethods > 0)
{
unsigned k;
- for (k = 0; k < _binds.Size(); k++)
+ for (k = 0; k < _bonds.Size(); k++)
{
- const CBind &bind = _binds[k];
- if (bind.InCoder < (UInt32)numEmptyMethods ||
- bind.OutCoder < (UInt32)numEmptyMethods)
+ const CBond2 &bond = _bonds[k];
+ if (bond.InCoder < (UInt32)numEmptyMethods ||
+ bond.OutCoder < (UInt32)numEmptyMethods)
return E_INVALIDARG;
}
- for (k = 0; k < _binds.Size(); k++)
+ for (k = 0; k < _bonds.Size(); k++)
{
- CBind &bind = _binds[k];
- bind.InCoder -= (UInt32)numEmptyMethods;
- bind.OutCoder -= (UInt32)numEmptyMethods;
+ CBond2 &bond = _bonds[k];
+ bond.InCoder -= (UInt32)numEmptyMethods;
+ bond.OutCoder -= (UInt32)numEmptyMethods;
}
_methods.DeleteFrontal(numEmptyMethods);
}
- AddDefaultMethod();
-
- if (!_filterMethod.MethodName.IsEmpty())
- {
- FOR_VECTOR (k, _binds)
- {
- CBind &bind = _binds[k];
- bind.InCoder++;
- bind.OutCoder++;
- }
- _methods.Insert(0, _filterMethod);
- }
-
- FOR_VECTOR (k, _binds)
+ FOR_VECTOR (k, _bonds)
{
- const CBind &bind = _binds[k];
- if (bind.InCoder >= (UInt32)_methods.Size() ||
- bind.OutCoder >= (UInt32)_methods.Size())
+ const CBond2 &bond = _bonds[k];
+ if (bond.InCoder >= (UInt32)_methods.Size() ||
+ bond.OutCoder >= (UInt32)_methods.Size())
return E_INVALIDARG;
}
diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h
index d72fdefa..d7f0ae36 100644
--- a/CPP/7zip/Archive/7z/7zHeader.h
+++ b/CPP/7zip/Archive/7z/7zHeader.h
@@ -96,6 +96,53 @@ namespace NID
};
}
+
+const UInt32 k_Copy = 0;
+const UInt32 k_Delta = 3;
+
+const UInt32 k_LZMA2 = 0x21;
+
+const UInt32 k_SWAP2 = 0x20302;
+const UInt32 k_SWAP4 = 0x20304;
+
+const UInt32 k_LZMA = 0x30101;
+const UInt32 k_PPMD = 0x30401;
+
+const UInt32 k_Deflate = 0x40108;
+const UInt32 k_BZip2 = 0x40202;
+
+const UInt32 k_BCJ = 0x3030103;
+const UInt32 k_BCJ2 = 0x303011B;
+const UInt32 k_PPC = 0x3030205;
+const UInt32 k_IA64 = 0x3030401;
+const UInt32 k_ARM = 0x3030501;
+const UInt32 k_ARMT = 0x3030701;
+const UInt32 k_SPARC = 0x3030805;
+
+const UInt32 k_AES = 0x6F10701;
+
+
+static inline bool IsFilterMethod(UInt64 m)
+{
+ if (m > (UInt64)0xFFFFFFFF)
+ return false;
+ switch ((UInt32)m)
+ {
+ case k_Delta:
+ case k_BCJ:
+ case k_BCJ2:
+ case k_PPC:
+ case k_IA64:
+ case k_ARM:
+ case k_ARMT:
+ case k_SPARC:
+ case k_SWAP2:
+ case k_SWAP4:
+ return true;
+ }
+ return false;
+}
+
}}
#endif
diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp
index 4f04aa83..bd6c4d95 100644
--- a/CPP/7zip/Archive/7z/7zIn.cpp
+++ b/CPP/7zip/Archive/7z/7zIn.cpp
@@ -32,9 +32,6 @@ using namespace NCOM;
namespace NArchive {
namespace N7z {
-static const UInt32 k_LZMA2 = 0x21;
-static const UInt32 k_LZMA = 0x030101;
-
static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
{
v.ClearAndSetSize(size);
@@ -43,78 +40,6 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
p[i] = false;
}
-static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index)
-{
- if (index >= (UInt32)v.Size())
- return true;
- bool res = v[index];
- v[index] = true;
- return res;
-}
-
-bool CFolder::CheckStructure(unsigned numUnpackSizes) const
-{
- const unsigned kNumCodersMax = sizeof(UInt32) * 8; // don't change it
- const unsigned kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax
- const unsigned kNumBindsMax = 32;
-
- if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax)
- return false;
-
- {
- CBoolVector v;
- BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size());
-
- unsigned i;
- for (i = 0; i < BindPairs.Size(); i++)
- if (BoolVector_GetAndSet(v, BindPairs[i].InIndex))
- return false;
- for (i = 0; i < PackStreams.Size(); i++)
- if (BoolVector_GetAndSet(v, PackStreams[i]))
- return false;
-
- BoolVector_Fill_False(v, numUnpackSizes);
- for (i = 0; i < BindPairs.Size(); i++)
- if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex))
- return false;
- }
-
- UInt32 mask[kMaskSize];
- unsigned i;
- for (i = 0; i < kMaskSize; i++)
- mask[i] = 0;
-
- {
- CUIntVector inStreamToCoder, outStreamToCoder;
- for (i = 0; i < Coders.Size(); i++)
- {
- CNum j;
- const CCoderInfo &coder = Coders[i];
- for (j = 0; j < coder.NumInStreams; j++)
- inStreamToCoder.Add(i);
- for (j = 0; j < coder.NumOutStreams; j++)
- outStreamToCoder.Add(i);
- }
-
- for (i = 0; i < BindPairs.Size(); i++)
- {
- const CBindPair &bp = BindPairs[i];
- mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]);
- }
- }
-
- for (i = 0; i < kMaskSize; i++)
- for (unsigned j = 0; j < kMaskSize; j++)
- if (((1 << j) & mask[i]) != 0)
- mask[i] |= mask[j];
-
- for (i = 0; i < kMaskSize; i++)
- if (((1 << i) & mask[i]) != 0)
- return false;
-
- return true;
-}
-
class CInArchiveException {};
class CUnsupportedFeatureException: public CInArchiveException {};
@@ -193,6 +118,8 @@ Byte CInByte2::ReadByte()
void CInByte2::ReadBytes(Byte *data, size_t size)
{
+ if (size == 0)
+ return;
if (size > _size - _pos)
ThrowEndOfData();
memcpy(data, _buffer + _pos, size);
@@ -218,41 +145,48 @@ static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed)
processed = 0;
return 0;
}
- Byte firstByte = *p++;
+
+ unsigned b = *p++;
size--;
- if ((firstByte & 0x80) == 0)
+
+ if ((b & 0x80) == 0)
{
processed = 1;
- return firstByte;
+ return b;
}
- Byte mask = 0x40;
+
if (size == 0)
{
processed = 0;
return 0;
}
+
UInt64 value = (UInt64)*p;
p++;
size--;
+
for (unsigned i = 1; i < 8; i++)
{
- if ((firstByte & mask) == 0)
+ unsigned mask = (unsigned)0x80 >> i;
+ if ((b & mask) == 0)
{
- UInt64 highPart = firstByte & (mask - 1);
- value += (highPart << (i * 8));
+ UInt64 high = b & (mask - 1);
+ value |= (high << (i * 8));
processed = i + 1;
return value;
}
+
if (size == 0)
{
processed = 0;
return 0;
}
+
value |= ((UInt64)*p << (i * 8));
p++;
size--;
- mask >>= 1;
}
+
processed = 9;
return value;
}
@@ -344,6 +278,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
for (;;)
{
UInt32 readSize = kBufSize - kHeaderSize;
+ if (searchHeaderSizeLimit)
{
UInt64 rem = *searchHeaderSizeLimit - offset;
if (readSize > rem)
@@ -351,10 +286,12 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
if (readSize == 0)
return S_FALSE;
}
+
UInt32 processed = 0;
RINOK(stream->Read(buf + kHeaderSize, readSize, &processed));
if (processed == 0)
return S_FALSE;
+
for (UInt32 pos = 0;;)
{
const Byte *p = buf + pos + 1;
@@ -376,6 +313,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL);
}
}
+
offset += processed;
memmove(buf, buf + processed, kHeaderSize);
}
@@ -415,13 +353,15 @@ void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
void CInByte2::ParseFolder(CFolder &folder)
{
- CNum numCoders = ReadNum();
+ UInt32 numCoders = ReadNum();
+
+ if (numCoders == 0)
+ ThrowUnsupported();
folder.Coders.SetSize(numCoders);
- CNum numInStreams = 0;
- CNum numOutStreams = 0;
- CNum i;
+ UInt32 numInStreams = 0;
+ UInt32 i;
for (i = 0; i < numCoders; i++)
{
CCoderInfo &coder = folder.Coders[i];
@@ -441,14 +381,14 @@ void CInByte2::ParseFolder(CFolder &folder)
if ((mainByte & 0x10) != 0)
{
- coder.NumInStreams = ReadNum();
- coder.NumOutStreams = ReadNum();
+ coder.NumStreams = ReadNum();
+ /* numOutStreams = */ ReadNum();
}
else
{
- coder.NumInStreams = 1;
- coder.NumOutStreams = 1;
+ coder.NumStreams = 1;
}
+
if ((mainByte & 0x20) != 0)
{
CNum propsSize = ReadNum();
@@ -458,27 +398,27 @@ void CInByte2::ParseFolder(CFolder &folder)
else
coder.Props.Free();
}
- numInStreams += coder.NumInStreams;
- numOutStreams += coder.NumOutStreams;
+ numInStreams += coder.NumStreams;
}
- CNum numBindPairs = numOutStreams - 1;
- folder.BindPairs.SetSize(numBindPairs);
- for (i = 0; i < numBindPairs; i++)
+ UInt32 numBonds = numCoders - 1;
+ folder.Bonds.SetSize(numBonds);
+ for (i = 0; i < numBonds; i++)
{
- CBindPair &bp = folder.BindPairs[i];
- bp.InIndex = ReadNum();
- bp.OutIndex = ReadNum();
+ CBond &bp = folder.Bonds[i];
+ bp.PackIndex = ReadNum();
+ bp.UnpackIndex = ReadNum();
}
- if (numInStreams < numBindPairs)
+ if (numInStreams < numBonds)
ThrowUnsupported();
- CNum numPackStreams = numInStreams - numBindPairs;
+ UInt32 numPackStreams = numInStreams - numBonds;
folder.PackStreams.SetSize(numPackStreams);
+
if (numPackStreams == 1)
{
for (i = 0; i < numInStreams; i++)
- if (folder.FindBindPairForInStream(i) < 0)
+ if (folder.FindBond_for_PackStream(i) < 0)
{
folder.PackStreams[0] = i;
break;
@@ -509,12 +449,12 @@ void CDatabase::GetPath(unsigned index, UString &path) const
return;
size_t offset = NameOffsets[index];
- size_t size = NameOffsets[index + 1] - offset - 1;
+ size_t size = NameOffsets[index + 1] - offset;
- if (size >= (1 << 20))
+ if (size >= (1 << 28))
return;
- wchar_t *s = path.GetBuffer((unsigned)size);
+ wchar_t *s = path.GetBuf((unsigned)size - 1);
const Byte *p = ((const Byte *)NamesBuf + offset * 2);
@@ -533,7 +473,7 @@ void CDatabase::GetPath(unsigned index, UString &path) const
#endif
- path.ReleaseBuffer((unsigned)size);
+ path.ReleaseBuf_SetLen((unsigned)size - 1);
}
HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
@@ -592,7 +532,7 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
{
unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1);
const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2;
- do
+ for (; len != 0; len--)
{
p -= 2;
--s;
@@ -601,7 +541,7 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
c = WCHAR_PATH_SEPARATOR;
*s = c;
}
- while (--len);
+
const CFileItem &file = Files[cur];
cur = file.Parent;
if (cur < 0)
@@ -639,6 +579,9 @@ void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)
}
}
+#define k_Scan_NumCoders_MAX 64
+#define k_Scan_NumCodersStreams_in_Folder_MAX 64
+
void CInArchive::ReadPackInfo(CFolders &f)
{
CNum numPackStreams = ReadNum();
@@ -692,27 +635,31 @@ void CInArchive::ReadUnpackInfo(
folders.FoCodersDataOffset.Alloc(numFolders + 1);
folders.FoToCoderUnpackSizes.Alloc(numFolders + 1);
- CRecordVector<bool> InStreamUsed;
- CRecordVector<bool> OutStreamUsed;
+ CBoolVector StreamUsed;
+ CBoolVector CoderUsed;
CNum packStreamIndex = 0;
CNum fo;
CInByte2 *inByte = _inByteBack;
+
for (fo = 0; fo < numFolders; fo++)
{
- UInt32 numOutStreams = 0;
UInt32 indexOfMainStream = 0;
UInt32 numPackStreams = 0;
folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;
- numOutStreams = 0;
CNum numInStreams = 0;
CNum numCoders = inByte->ReadNum();
+
+ if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
+ ThrowUnsupported();
+
for (CNum ci = 0; ci < numCoders; ci++)
{
Byte mainByte = inByte->ReadByte();
if ((mainByte & 0xC0) != 0)
ThrowUnsupported();
+
unsigned idSize = (mainByte & 0xF);
if (idSize > 8)
ThrowUnsupported();
@@ -725,19 +672,21 @@ void CInArchive::ReadUnpackInfo(
inByte->SkipDataNoCheck(idSize);
if (folders.ParsedMethods.IDs.Size() < 128)
folders.ParsedMethods.IDs.AddToUniqueSorted(id);
+
CNum coderInStreams = 1;
- CNum coderOutStreams = 1;
if ((mainByte & 0x10) != 0)
{
coderInStreams = inByte->ReadNum();
- coderOutStreams = inByte->ReadNum();
+ if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
+ ThrowUnsupported();
+ if (inByte->ReadNum() != 1)
+ ThrowUnsupported();
}
+
numInStreams += coderInStreams;
- if (numInStreams < coderInStreams)
- ThrowUnsupported();
- numOutStreams += coderOutStreams;
- if (numOutStreams < coderOutStreams)
+ if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
ThrowUnsupported();
+
if ((mainByte & 0x20) != 0)
{
CNum propsSize = inByte->ReadNum();
@@ -759,7 +708,7 @@ void CInArchive::ReadUnpackInfo(
}
}
- if (numOutStreams == 1 && numInStreams == 1)
+ if (numCoders == 1 && numInStreams == 1)
{
indexOfMainStream = 0;
numPackStreams = 1;
@@ -767,55 +716,55 @@ void CInArchive::ReadUnpackInfo(
else
{
UInt32 i;
- if (numOutStreams == 0)
- ThrowUnsupported();
- CNum numBindPairs = numOutStreams - 1;
- if (numInStreams < numBindPairs)
- ThrowUnsupported();
- if (numInStreams >= 256 || numOutStreams >= 256)
+ CNum numBonds = numCoders - 1;
+ if (numInStreams < numBonds)
ThrowUnsupported();
- InStreamUsed.ClearAndSetSize(numInStreams);
- for (i = 0; i < numInStreams; i++)
- InStreamUsed[i] = false;
+ BoolVector_Fill_False(StreamUsed, numInStreams);
+ BoolVector_Fill_False(CoderUsed, numCoders);
- OutStreamUsed.ClearAndSetSize(numOutStreams);
- for (i = 0; i < numOutStreams; i++)
- OutStreamUsed[i] = false;
-
- for (i = 0; i < numBindPairs; i++)
+ for (i = 0; i < numBonds; i++)
{
CNum index = ReadNum();
- if (index >= numInStreams || InStreamUsed[index])
+ if (index >= numInStreams || StreamUsed[index])
ThrowUnsupported();
- InStreamUsed[index] = true;
+ StreamUsed[index] = true;
+
index = ReadNum();
- if (index >= numOutStreams || OutStreamUsed[index])
+ if (index >= numCoders || CoderUsed[index])
ThrowUnsupported();
- OutStreamUsed[index] = true;
+ CoderUsed[index] = true;
}
- numPackStreams = numInStreams - numBindPairs;
+ numPackStreams = numInStreams - numBonds;
if (numPackStreams != 1)
for (i = 0; i < numPackStreams; i++)
- inByte->ReadNum(); // PackStreams
+ {
+ CNum index = inByte->ReadNum(); // PackStreams
+ if (index >= numInStreams || StreamUsed[index])
+ ThrowUnsupported();
+ StreamUsed[index] = true;
+ }
- for (i = 0; i < numOutStreams; i++)
- if (!OutStreamUsed[i])
+ for (i = 0; i < numCoders; i++)
+ if (!CoderUsed[i])
{
indexOfMainStream = i;
break;
}
- if (i == numOutStreams)
+
+ if (i == numCoders)
ThrowUnsupported();
}
+
folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
- numCodersOutStreams += numOutStreams;
+ numCodersOutStreams += numCoders;
folders.FoStartPackStreamIndex[fo] = packStreamIndex;
packStreamIndex += numPackStreams;
folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
}
+
size_t dataSize = _inByteBack->GetPtr() - startBufPtr;
folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
folders.FoStartPackStreamIndex[fo] = packStreamIndex;
@@ -1105,13 +1054,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
unpackSizes,
digests);
- CDecoder decoder(
- #ifdef _ST_MODE
- false
- #else
- true
- #endif
- );
+ CDecoder decoder(_useMixerMT);
for (CNum i = 0; i < folders.NumFolders; i++)
{
@@ -1127,14 +1070,20 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
outStreamSpec->Init(data, unpackSize);
HRESULT result = decoder.Decode(
- EXTERNAL_CODECS_LOC_VARS
- _stream, baseOffset + dataOffset,
- folders, i,
- outStream, NULL
- _7Z_DECODER_CRYPRO_VARS
- #if !defined(_7ZIP_ST) && !defined(_SFX)
- , false, 1
- #endif
+ EXTERNAL_CODECS_LOC_VARS
+ _stream, baseOffset + dataOffset,
+ folders, i,
+ NULL, // *unpackSize
+
+ outStream,
+ NULL, // *compressProgress
+ NULL // **inStreamMainRes
+
+ _7Z_DECODER_CRYPRO_VARS
+ #if !defined(_7ZIP_ST) && !defined(_SFX)
+ , false // mtMode
+ , 1 // numThreads
+ #endif
);
RINOK(result);
@@ -1208,7 +1157,7 @@ HRESULT CInArchive::ReadHeader(
db.ArcInfo.FileInfoPopIDs.Add(NID::kSize);
// if (!db.PackSizes.IsEmpty())
db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo);
- if (numFiles > 0 && !digests.Defs.IsEmpty())
+ if (numFiles > 0 && !digests.Defs.IsEmpty())
db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC);
CBoolVector emptyStreamVector;
@@ -1396,6 +1345,9 @@ HRESULT CInArchive::ReadHeader(
type = ReadID(); // Read (NID::kEnd) end of headers
+ if (numFiles - numEmptyStreams != unpackSizes.Size())
+ ThrowUnsupported();
+
CNum emptyFileIndex = 0;
CNum sizeIndex = 0;
@@ -1403,7 +1355,7 @@ HRESULT CInArchive::ReadHeader(
for (i = 0; i < numEmptyStreams; i++)
if (antiFileVector[i])
numAntiItems++;
-
+
for (i = 0; i < numFiles; i++)
{
CFileItem &file = db.Files[i];
@@ -1444,13 +1396,13 @@ HRESULT CInArchive::ReadHeader(
void CDbEx::FillLinks()
{
- FolderStartFileIndex.ClearAndSetSize(NumFolders);
-
- FileIndexToFolderIndexMap.ClearAndSetSize(Files.Size());
+ FolderStartFileIndex.Alloc(NumFolders);
+ FileIndexToFolderIndexMap.Alloc(Files.Size());
CNum folderIndex = 0;
CNum indexInFolder = 0;
unsigned i;
+
for (i = 0; i < Files.Size(); i++)
{
bool emptyStream = !Files[i].HasStream;
@@ -1489,6 +1441,7 @@ void CDbEx::FillLinks()
if (indexInFolder != 0)
ThrowIncorrect();
*/
+
for (;;)
{
if (folderIndex >= NumFolders)
diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h
index 373000f7..ad8ceba5 100644
--- a/CPP/7zip/Archive/7z/7zIn.h
+++ b/CPP/7zip/Archive/7z/7zIn.h
@@ -26,8 +26,8 @@ namespace N7z {
#define _7Z_DECODER_CRYPRO_VARS_DECL
#define _7Z_DECODER_CRYPRO_VARS
#else
-#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined
-#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined
+#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password
+#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined, password
#endif
struct CParsedMethods
@@ -39,6 +39,11 @@ struct CParsedMethods
CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {}
};
+struct CFolderEx: public CFolder
+{
+ unsigned UnpackCoder;
+};
+
struct CFolders
{
CNum NumPackStreams;
@@ -47,10 +52,10 @@ struct CFolders
CObjArray<UInt64> PackPositions; // NumPackStreams + 1
// CUInt32DefVector PackCRCs; // we don't use PackCRCs now
- CUInt32DefVector FolderCRCs; // NumFolders
+ CUInt32DefVector FolderCRCs; // NumFolders
CObjArray<CNum> NumUnpackStreamsVector; // NumFolders
- CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders
+ CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
CObjArray<CNum> FoToCoderUnpackSizes; // NumFolders + 1
CObjArray<CNum> FoStartPackStreamIndex; // NumFolders + 1
CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders
@@ -61,10 +66,15 @@ struct CFolders
CParsedMethods ParsedMethods;
void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const;
+ void ParseFolderEx(unsigned folderIndex, CFolderEx &folder) const
+ {
+ ParseFolderInfo(folderIndex, folder);
+ folder.UnpackCoder = FoToMainUnpackSizeIndex[folderIndex];
+ }
unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const
{
- return FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex];
+ return (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]);
}
UInt64 GetFolderUnpackSize(unsigned folderIndex) const
@@ -103,9 +113,9 @@ struct CDatabase: public CFolders
CUInt64DefVector ATime;
CUInt64DefVector MTime;
CUInt64DefVector StartPos;
- CRecordVector<bool> IsAnti;
+ CBoolVector IsAnti;
/*
- CRecordVector<bool> IsAux;
+ CBoolVector IsAux;
CByteBuffer SecureBuf;
CRecordVector<UInt32> SecureIDs;
*/
@@ -148,13 +158,14 @@ struct CDatabase: public CFolders
bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
// bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }
- const void * GetName(unsigned index) const
+ /*
+ const void* GetName(unsigned index) const
{
if (!NameOffsets || !NamesBuf)
return NULL;
- return (const void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);
+ return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);
};
-
+ */
void GetPath(unsigned index, UString &path) const;
HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw();
};
@@ -181,8 +192,9 @@ struct CInArchiveInfo
struct CDbEx: public CDatabase
{
CInArchiveInfo ArcInfo;
- CRecordVector<CNum> FolderStartFileIndex;
- CRecordVector<CNum> FileIndexToFolderIndexMap;
+
+ CObjArray<CNum> FolderStartFileIndex;
+ CObjArray<CNum> FileIndexToFolderIndexMap;
UInt64 HeadersSize;
UInt64 PhySize;
@@ -234,8 +246,8 @@ struct CDbEx: public CDatabase
// SecureOffsets.Clear();
ArcInfo.Clear();
- FolderStartFileIndex.Clear();
- FileIndexToFolderIndexMap.Clear();
+ FolderStartFileIndex.Free();
+ FileIndexToFolderIndexMap.Free();
HeadersSize = 0;
PhySize = 0;
@@ -243,22 +255,22 @@ struct CDbEx: public CDatabase
void FillLinks();
- UInt64 GetFolderStreamPos(unsigned folderIndex, unsigned indexInFolder) const
+ UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const
{
return ArcInfo.DataStartPosition +
PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
}
- UInt64 GetFolderFullPackSize(unsigned folderIndex) const
+ UInt64 GetFolderFullPackSize(CNum folderIndex) const
{
return
PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
PackPositions[FoStartPackStreamIndex[folderIndex]];
}
- UInt64 GetFolderPackStreamSize(unsigned folderIndex, unsigned streamIndex) const
+ UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const
{
- unsigned i = FoStartPackStreamIndex[folderIndex] + streamIndex;
+ size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex;
return PackPositions[i + 1] - PackPositions[i];
}
@@ -327,6 +339,8 @@ class CInArchive
UInt64 HeadersSize;
+ bool _useMixerMT;
+
void AddByteStream(const Byte *buffer, size_t size);
void DeleteByteStream(bool needUpdatePos)
@@ -340,7 +354,6 @@ class CInArchive
}
}
-private:
HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
@@ -396,7 +409,11 @@ private:
_7Z_DECODER_CRYPRO_VARS_DECL
);
public:
- CInArchive(): _numInByteBufs(0) { }
+ CInArchive(bool useMixerMT):
+ _numInByteBufs(0),
+ _useMixerMT(useMixerMT)
+ {}
+
HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
void Close();
diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h
index 02a86196..5e2b58f2 100644
--- a/CPP/7zip/Archive/7z/7zItem.h
+++ b/CPP/7zip/Archive/7z/7zItem.h
@@ -13,8 +13,6 @@
namespace NArchive {
namespace N7z {
-const UInt64 k_AES = 0x06F10701;
-
typedef UInt32 CNum;
const CNum kNumMax = 0x7FFFFFFF;
const CNum kNumNoIndex = 0xFFFFFFFF;
@@ -23,71 +21,70 @@ struct CCoderInfo
{
CMethodId MethodID;
CByteBuffer Props;
- CNum NumInStreams;
- CNum NumOutStreams;
+ UInt32 NumStreams;
- bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
+ bool IsSimpleCoder() const { return NumStreams == 1; }
};
-struct CBindPair
+struct CBond
{
- CNum InIndex;
- CNum OutIndex;
+ UInt32 PackIndex;
+ UInt32 UnpackIndex;
};
struct CFolder
{
+ CLASS_NO_COPY(CFolder)
+public:
CObjArray2<CCoderInfo> Coders;
- CObjArray2<CBindPair> BindPairs;
- CObjArray2<CNum> PackStreams;
+ CObjArray2<CBond> Bonds;
+ CObjArray2<UInt32> PackStreams;
- CNum GetNumOutStreams() const
- {
- CNum result = 0;
- FOR_VECTOR(i, Coders)
- result += Coders[i].NumOutStreams;
- return result;
- }
+ CFolder() {}
- int FindBindPairForInStream(CNum inStreamIndex) const
+ bool IsDecodingSupported() const { return Coders.Size() <= 32; }
+
+ int Find_in_PackStreams(UInt32 packStream) const
{
- FOR_VECTOR(i, BindPairs)
- if (BindPairs[i].InIndex == inStreamIndex)
+ FOR_VECTOR(i, PackStreams)
+ if (PackStreams[i] == packStream)
return i;
return -1;
}
- int FindBindPairForOutStream(CNum outStreamIndex) const
+
+ int FindBond_for_PackStream(UInt32 packStream) const
{
- FOR_VECTOR(i, BindPairs)
- if (BindPairs[i].OutIndex == outStreamIndex)
+ FOR_VECTOR(i, Bonds)
+ if (Bonds[i].PackIndex == packStream)
return i;
return -1;
}
- int FindPackStreamArrayIndex(CNum inStreamIndex) const
+
+ /*
+ int FindBond_for_UnpackStream(UInt32 unpackStream) const
{
- FOR_VECTOR(i, PackStreams)
- if (PackStreams[i] == inStreamIndex)
+ FOR_VECTOR(i, Bonds)
+ if (Bonds[i].UnpackIndex == unpackStream)
return i;
return -1;
}
- int GetIndexOfMainOutStream() const
+ int FindOutCoder() const
{
- for (int i = (int)GetNumOutStreams() - 1; i >= 0; i--)
- if (FindBindPairForOutStream(i) < 0)
+ for (int i = (int)Coders.Size() - 1; i >= 0; i--)
+ if (FindBond_for_UnpackStream(i) < 0)
return i;
- throw 1;
+ return -1;
}
+ */
bool IsEncrypted() const
{
- for (int i = Coders.Size() - 1; i >= 0; i--)
+ FOR_VECTOR(i, Coders)
if (Coders[i].MethodID == k_AES)
return true;
return false;
}
-
- bool CheckStructure(unsigned numUnpackSizes) const;
};
struct CUInt32DefVector
diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp
index 9ff97595..2f906588 100644
--- a/CPP/7zip/Archive/7z/7zOut.cpp
+++ b/CPP/7zip/Archive/7z/7zOut.cpp
@@ -199,7 +199,7 @@ void COutArchive::WriteNumber(UInt64 value)
mask >>= 1;
}
WriteByte(firstByte);
- for (;i > 0; i--)
+ for (; i > 0; i--)
{
WriteByte((Byte)value);
value >>= 8;
@@ -254,31 +254,33 @@ void COutArchive::WriteFolder(const CFolder &folder)
{
WriteNumber(folder.Coders.Size());
unsigned i;
+
for (i = 0; i < folder.Coders.Size(); i++)
{
const CCoderInfo &coder = folder.Coders[i];
{
- size_t propsSize = coder.Props.Size();
-
UInt64 id = coder.MethodID;
- int idSize;
+ unsigned idSize;
for (idSize = 1; idSize < sizeof(id); idSize++)
if ((id >> (8 * idSize)) == 0)
break;
- Byte longID[15];
- for (int t = idSize - 1; t >= 0 ; t--, id >>= 8)
- longID[t] = (Byte)(id & 0xFF);
- Byte b;
- b = (Byte)(idSize & 0xF);
+ idSize &= 0xF;
+ Byte temp[16];
+ for (unsigned t = idSize; t != 0; t--, id >>= 8)
+ temp[t] = (Byte)(id & 0xFF);
+
+ Byte b = (Byte)(idSize);
bool isComplex = !coder.IsSimpleCoder();
b |= (isComplex ? 0x10 : 0);
- b |= ((propsSize != 0) ? 0x20 : 0 );
- WriteByte(b);
- WriteBytes(longID, idSize);
+
+ size_t propsSize = coder.Props.Size();
+ b |= ((propsSize != 0) ? 0x20 : 0);
+ temp[0] = b;
+ WriteBytes(temp, idSize + 1);
if (isComplex)
{
- WriteNumber(coder.NumInStreams);
- WriteNumber(coder.NumOutStreams);
+ WriteNumber(coder.NumStreams);
+ WriteNumber(1); // NumOutStreams;
}
if (propsSize == 0)
continue;
@@ -286,17 +288,17 @@ void COutArchive::WriteFolder(const CFolder &folder)
WriteBytes(coder.Props, propsSize);
}
}
- for (i = 0; i < folder.BindPairs.Size(); i++)
+
+ for (i = 0; i < folder.Bonds.Size(); i++)
{
- const CBindPair &bindPair = folder.BindPairs[i];
- WriteNumber(bindPair.InIndex);
- WriteNumber(bindPair.OutIndex);
+ const CBond &bond = folder.Bonds[i];
+ WriteNumber(bond.PackIndex);
+ WriteNumber(bond.UnpackIndex);
}
+
if (folder.PackStreams.Size() > 1)
for (i = 0; i < folder.PackStreams.Size(); i++)
- {
WriteNumber(folder.PackStreams[i]);
- }
}
void COutArchive::WriteBoolVector(const CBoolVector &boolVector)
@@ -521,7 +523,10 @@ HRESULT COutArchive::EncodeStream(
UInt64 unpackSize;
RINOK(encoder.Encode(
EXTERNAL_CODECS_LOC_VARS
- stream, NULL, &dataSize64, folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))
+ stream,
+ // NULL,
+ &dataSize64,
+ folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))
return S_OK;
}
diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h
index cead4bce..6c902668 100644
--- a/CPP/7zip/Archive/7z/7zOut.h
+++ b/CPP/7zip/Archive/7z/7zOut.h
@@ -29,6 +29,8 @@ public:
}
void WriteBytes(const void *data, size_t size)
{
+ if (size == 0)
+ return;
if (size > _size - _pos)
throw 1;
memcpy(_data + _pos, data, size);
@@ -92,7 +94,7 @@ struct COutFolders
CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only.
CRecordVector<CNum> NumUnpackStreamsVector;
- CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders
+ CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
void OutFoldersClear()
{
diff --git a/CPP/7zip/Archive/7z/7zProperties.cpp b/CPP/7zip/Archive/7z/7zProperties.cpp
index 5ed36947..a2c9bf31 100644
--- a/CPP/7zip/Archive/7z/7zProperties.cpp
+++ b/CPP/7zip/Archive/7z/7zProperties.cpp
@@ -13,7 +13,7 @@ namespace N7z {
struct CPropMap
{
- UInt64 FilePropID;
+ UInt32 FilePropID;
STATPROPSTG StatPROPSTG;
};
@@ -35,7 +35,7 @@ static const CPropMap kPropMap[] =
{ NID::kMTime, { NULL, kpidMTime, VT_FILETIME } },
{ NID::kATime, { NULL, kpidATime, VT_FILETIME } },
{ NID::kWinAttrib, { NULL, kpidAttrib, VT_UI4 } },
- { NID::kStartPos, { NULL, kpidPosition, VT_UI4 } },
+ { NID::kStartPos, { NULL, kpidPosition, VT_UI8 } },
{ NID::kCRC, { NULL, kpidCRC, VT_UI4 } },
@@ -44,20 +44,12 @@ static const CPropMap kPropMap[] =
#ifndef _SFX
,
- { 97, { NULL,kpidEncrypted, VT_BOOL } },
- { 98, { NULL,kpidMethod, VT_BSTR } },
- { 99, { NULL,kpidBlock, VT_UI4 } }
+ { 97, { NULL, kpidEncrypted, VT_BOOL } },
+ { 98, { NULL, kpidMethod, VT_BSTR } },
+ { 99, { NULL, kpidBlock, VT_UI4 } }
#endif
};
-static int FindPropInMap(UInt64 filePropID)
-{
- for (int i = 0; i < ARRAY_SIZE(kPropMap); i++)
- if (kPropMap[i].FilePropID == filePropID)
- return i;
- return -1;
-}
-
static void CopyOneItem(CRecordVector<UInt64> &src,
CRecordVector<UInt64> &dest, UInt32 item)
{
@@ -131,6 +123,7 @@ void CHandler::FillPopIDs()
_fileInfoPopIDs.Add(98);
_fileInfoPopIDs.Add(99);
#endif
+
#ifdef _MULTI_PACK
_fileInfoPopIDs.Add(100);
_fileInfoPopIDs.Add(101);
@@ -155,16 +148,27 @@ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
{
- if ((int)index >= _fileInfoPopIDs.Size())
+ if (index >= _fileInfoPopIDs.Size())
return E_INVALIDARG;
- int indexInMap = FindPropInMap(_fileInfoPopIDs[index]);
- if (indexInMap == -1)
- return E_INVALIDARG;
- const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG;
- *propID = srcItem.propid;
- *varType = srcItem.vt;
- *name = 0;
- return S_OK;
+ UInt64 id = _fileInfoPopIDs[index];
+ for (unsigned i = 0; i < ARRAY_SIZE(kPropMap); i++)
+ {
+ const CPropMap &pr = kPropMap[i];
+ if (pr.FilePropID == id)
+ {
+ const STATPROPSTG &st = pr.StatPROPSTG;
+ *propID = st.propid;
+ *varType = st.vt;
+ /*
+ if (st.lpwstrName)
+ *name = ::SysAllocString(st.lpwstrName);
+ else
+ */
+ *name = NULL;
+ return S_OK;
+ }
+ }
+ return E_INVALIDARG;
}
}}
diff --git a/CPP/7zip/Archive/7z/7zRegister.cpp b/CPP/7zip/Archive/7z/7zRegister.cpp
index 37ea29d3..389b5407 100644
--- a/CPP/7zip/Archive/7z/7zRegister.cpp
+++ b/CPP/7zip/Archive/7z/7zRegister.cpp
@@ -9,17 +9,13 @@
namespace NArchive {
namespace N7z {
-IMP_CreateArcIn
-IMP_CreateArcOut
+static Byte k_Signature_Dec[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C};
-static CArcInfo g_ArcInfo =
- { "7z", "7z", 0, 7,
- 6, {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C},
+REGISTER_ARC_IO_DECREMENT_SIG(
+ "7z", "7z", NULL, 7,
+ k_Signature_Dec,
0,
NArcInfoFlags::kFindSignature,
- REF_CreateArc_Pair };
-
-REGISTER_ARC_DEC_SIG(7z)
-// REGISTER_ARC(7z)
+ NULL);
}}
diff --git a/CPP/7zip/Archive/7z/7zSpecStream.h b/CPP/7zip/Archive/7z/7zSpecStream.h
index 2e26efd5..21155069 100644
--- a/CPP/7zip/Archive/7z/7zSpecStream.h
+++ b/CPP/7zip/Archive/7z/7zSpecStream.h
@@ -3,10 +3,10 @@
#ifndef __7Z_SPEC_STREAM_H
#define __7Z_SPEC_STREAM_H
-#include "../../IStream.h"
-#include "../../ICoder.h"
#include "../../../Common/MyCom.h"
+#include "../../ICoder.h"
+
class CSequentialInStreamSizeCount2:
public ISequentialInStream,
public ICompressGetSubStreamSize,
@@ -18,14 +18,14 @@ class CSequentialInStreamSizeCount2:
public:
void Init(ISequentialInStream *stream)
{
+ _size = 0;
+ _getSubStreamSize.Release();
_stream = stream;
- _getSubStreamSize = 0;
_stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);
- _size = 0;
}
UInt64 GetSize() const { return _size; }
- MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
+ MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
index 7875ed5b..e7c9ecc6 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.cpp
+++ b/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -13,7 +13,6 @@
#include "../../Compress/CopyCoder.h"
#include "../Common/ItemNameUtils.h"
-#include "../Common/OutStreamWithCRC.h"
#include "7zDecode.h"
#include "7zEncode.h"
@@ -25,9 +24,392 @@
namespace NArchive {
namespace N7z {
-#ifdef MY_CPU_X86_OR_AMD64
-#define USE_86_FILTER
-#endif
+
+#define k_X86 k_BCJ
+
+struct CFilterMode
+{
+ UInt32 Id;
+ UInt32 Delta;
+
+ CFilterMode(): Id(0), Delta(0) {}
+
+ void SetDelta()
+ {
+ if (Id == k_IA64)
+ Delta = 16;
+ else if (Id == k_ARM || Id == k_PPC || Id == k_PPC)
+ Delta = 4;
+ else if (Id == k_ARMT)
+ Delta = 2;
+ else
+ Delta = 0;
+ }
+};
+
+
+/* ---------- PE ---------- */
+
+#define MZ_SIG 0x5A4D
+
+#define PE_SIG 0x00004550
+#define PE_OptHeader_Magic_32 0x10B
+#define PE_OptHeader_Magic_64 0x20B
+#define PE_SectHeaderSize 40
+#define PE_SECT_EXECUTE 0x20000000
+
+static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
+{
+ if (size < 512 || GetUi16(buf) != MZ_SIG)
+ return 0;
+
+ const Byte *p;
+ UInt32 peOffset, optHeaderSize, filterId;
+
+ peOffset = GetUi32(buf + 0x3C);
+ if (peOffset >= 0x1000 || peOffset + 512 > size || (peOffset & 7) != 0)
+ return 0;
+ p = buf + peOffset;
+ if (GetUi32(p) != PE_SIG)
+ return 0;
+ p += 4;
+
+ switch (GetUi16(p))
+ {
+ case 0x014C:
+ case 0x8664: filterId = k_X86; break;
+
+ /*
+ IMAGE_FILE_MACHINE_ARM 0x01C0 // ARM LE
+ IMAGE_FILE_MACHINE_THUMB 0x01C2 // ARM Thumb / Thumb-2 LE
+ IMAGE_FILE_MACHINE_ARMNT 0x01C4 // ARM Thumb-2, LE
+ Note: We use ARM filter for 0x01C2. (WinCE 5 - 0x01C2) files mostly contain ARM code (not Thumb/Thumb-2).
+ */
+
+ case 0x01C0: // WinCE old
+ case 0x01C2: filterId = k_ARM; break; // WinCE new
+ case 0x01C4: filterId = k_ARMT; break; // WinRT
+
+ case 0x0200: filterId = k_IA64; break;
+ default: return 0;
+ }
+
+ optHeaderSize = GetUi16(p + 16);
+ if (optHeaderSize > (1 << 10))
+ return 0;
+
+ p += 20; /* headerSize */
+
+ switch (GetUi16(p))
+ {
+ case PE_OptHeader_Magic_32:
+ case PE_OptHeader_Magic_64:
+ break;
+ default:
+ return 0;
+ }
+
+ filterMode->Id = filterId;
+ return 1;
+}
+
+
+/* ---------- ELF ---------- */
+
+#define ELF_SIG 0x464C457F
+
+#define ELF_CLASS_32 1
+#define ELF_CLASS_64 2
+
+#define ELF_DATA_2LSB 1
+#define ELF_DATA_2MSB 2
+
+static UInt16 Get16(const Byte *p, Bool be) { if (be) return (UInt16)GetBe16(p); return (UInt16)GetUi16(p); }
+static UInt32 Get32(const Byte *p, Bool be) { if (be) return GetBe32(p); return GetUi32(p); }
+// static UInt64 Get64(const Byte *p, Bool be) { if (be) return GetBe64(p); return GetUi64(p); }
+
+static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode)
+{
+ Bool /* is32, */ be;
+ UInt32 filterId;
+
+ if (size < 512 || buf[6] != 1) /* ver */
+ return 0;
+
+ if (GetUi32(buf) != ELF_SIG)
+ return 0;
+
+ switch (buf[4])
+ {
+ case ELF_CLASS_32: /* is32 = True; */ break;
+ case ELF_CLASS_64: /* is32 = False; */ break;
+ default: return 0;
+ }
+
+ switch (buf[5])
+ {
+ case ELF_DATA_2LSB: be = False; break;
+ case ELF_DATA_2MSB: be = True; break;
+ default: return 0;
+ }
+
+ switch (Get16(buf + 0x12, be))
+ {
+ case 3:
+ case 6:
+ case 62: filterId = k_X86; break;
+ case 2:
+ case 18:
+ 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;
+
+ /* Some IA-64 ELF exacutable have size that is not aligned for 16 bytes.
+ So we don't use IA-64 filter for IA-64 ELF */
+ // case 50: if ( be) return 0; filterId = k_IA64; break;
+
+ default: return 0;
+ }
+
+ filterMode->Id = filterId;
+ return 1;
+}
+
+
+
+/* ---------- Mach-O ---------- */
+
+#define MACH_SIG_BE_32 0xCEFAEDFE
+#define MACH_SIG_BE_64 0xCFFAEDFE
+#define MACH_SIG_LE_32 0xFEEDFACE
+#define MACH_SIG_LE_64 0xFEEDFACF
+
+#define MACH_ARCH_ABI64 (1 << 24)
+#define MACH_MACHINE_386 7
+#define MACH_MACHINE_ARM 12
+#define MACH_MACHINE_SPARC 14
+#define MACH_MACHINE_PPC 18
+#define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC)
+#define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386)
+
+static unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode)
+{
+ UInt32 filterId, numCommands, commandsSize;
+
+ if (size < 512)
+ return 0;
+
+ Bool /* mode64, */ be;
+ switch (GetUi32(buf))
+ {
+ case MACH_SIG_BE_32: /* mode64 = False; */ be = True; break;
+ case MACH_SIG_BE_64: /* mode64 = True; */ be = True; break;
+ case MACH_SIG_LE_32: /* mode64 = False; */ be = False; break;
+ case MACH_SIG_LE_64: /* mode64 = True; */ be = False; break;
+ default: return 0;
+ }
+
+ switch (Get32(buf + 4, be))
+ {
+ case MACH_MACHINE_386:
+ case MACH_MACHINE_AMD64: filterId = k_X86; break;
+ case MACH_MACHINE_ARM: if ( be) return 0; filterId = k_ARM; break;
+ case MACH_MACHINE_SPARC: if (!be) return 0; filterId = k_SPARC; break;
+ case MACH_MACHINE_PPC:
+ case MACH_MACHINE_PPC64: if (!be) return 0; filterId = k_PPC; break;
+ default: return 0;
+ }
+
+ numCommands = Get32(buf + 0x10, be);
+ commandsSize = Get32(buf + 0x14, be);
+
+ if (commandsSize > (1 << 24) || numCommands > (1 << 18))
+ return 0;
+
+ filterMode->Id = filterId;
+ return 1;
+}
+
+
+/* ---------- WAV ---------- */
+
+#define WAV_SUBCHUNK_fmt 0x20746D66
+#define WAV_SUBCHUNK_data 0x61746164
+
+#define RIFF_SIG 0x46464952
+
+static Bool Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode)
+{
+ UInt32 subChunkSize, pos;
+ if (size < 0x2C)
+ return False;
+
+ if (GetUi32(buf + 0) != RIFF_SIG ||
+ GetUi32(buf + 8) != 0x45564157 || // WAVE
+ GetUi32(buf + 0xC) != WAV_SUBCHUNK_fmt)
+ return False;
+ subChunkSize = GetUi32(buf + 0x10);
+ /* [0x14 = format] = 1 (PCM) */
+ if (subChunkSize < 0x10 || subChunkSize > 0x12 || GetUi16(buf + 0x14) != 1)
+ return False;
+
+ unsigned numChannels = GetUi16(buf + 0x16);
+ unsigned bitsPerSample = GetUi16(buf + 0x22);
+
+ if ((bitsPerSample & 0x7) != 0 || bitsPerSample >= 256 || numChannels >= 256)
+ return False;
+
+ pos = 0x14 + subChunkSize;
+
+ const int kNumSubChunksTests = 10;
+ // Do we need to scan more than 3 sub-chunks?
+ for (int i = 0; i < kNumSubChunksTests; i++)
+ {
+ if (pos + 8 > size)
+ return False;
+ subChunkSize = GetUi32(buf + pos + 4);
+ if (GetUi32(buf + pos) == WAV_SUBCHUNK_data)
+ {
+ unsigned delta = numChannels * (bitsPerSample >> 3);
+ if (delta >= 256)
+ return False;
+ filterMode->Id = k_Delta;
+ filterMode->Delta = delta;
+ return True;
+ }
+ if (subChunkSize > (1 << 16))
+ return False;
+ pos += subChunkSize + 8;
+ }
+ return False;
+}
+
+static Bool ParseFile(const Byte *buf, size_t size, CFilterMode *filterMode)
+{
+ filterMode->Id = 0;
+ filterMode->Delta = 0;
+
+ if (Parse_EXE(buf, size, filterMode)) return True;
+ if (Parse_ELF(buf, size, filterMode)) return True;
+ if (Parse_MACH(buf, size, filterMode)) return True;
+ return Parse_WAV(buf, size, filterMode);
+}
+
+
+
+
+struct CFilterMode2: public CFilterMode
+{
+ bool Encrypted;
+ unsigned GroupIndex;
+
+ CFilterMode2(): Encrypted(false) {}
+
+ int Compare(const CFilterMode2 &m) const
+ {
+ if (!Encrypted)
+ {
+ if (m.Encrypted)
+ return -1;
+ }
+ else if (!m.Encrypted)
+ return 1;
+
+ if (Id < m.Id) return -1;
+ if (Id > m.Id) return 1;
+
+ if (Delta < m.Delta) return -1;
+ if (Delta > m.Delta) return 1;
+
+ return 0;
+ }
+
+ bool operator ==(const CFilterMode2 &m) const
+ {
+ return Id == m.Id && Delta == m.Delta && Encrypted == m.Encrypted;
+ }
+};
+
+static unsigned GetGroup(CRecordVector<CFilterMode2> &filters, const CFilterMode2 &m)
+{
+ unsigned i;
+ for (i = 0; i < filters.Size(); i++)
+ {
+ const CFilterMode2 &m2 = filters[i];
+ if (m == m2)
+ return i;
+ /*
+ if (m.Encrypted != m2.Encrypted)
+ {
+ if (!m.Encrypted)
+ break;
+ continue;
+ }
+
+ if (m.Id < m2.Id) break;
+ if (m.Id != m2.Id) continue;
+
+ if (m.Delta < m2.Delta) break;
+ if (m.Delta != m2.Delta) continue;
+ */
+ }
+ // filters.Insert(i, m);
+ // return i;
+ return filters.Add(m);
+}
+
+static inline bool Is86Filter(CMethodId m)
+{
+ return (m == k_BCJ || m == k_BCJ2);
+}
+
+static inline bool IsExeFilter(CMethodId m)
+{
+ switch (m)
+ {
+ case k_BCJ:
+ case k_BCJ2:
+ case k_ARM:
+ case k_ARMT:
+ case k_PPC:
+ case k_SPARC:
+ case k_IA64:
+ return true;
+ }
+ return false;
+}
+
+static unsigned Get_FilterGroup_for_Folder(CRecordVector<CFilterMode2> &filters, const CFolderEx &f)
+{
+ CFilterMode2 m;
+ m.Id = 0;
+ m.Delta = 0;
+ m.Encrypted = f.IsEncrypted();
+
+ const CCoderInfo &coder = f.Coders[f.UnpackCoder];
+
+ if (coder.MethodID == k_Delta)
+ {
+ if (coder.Props.Size() == 1)
+ {
+ m.Delta = (unsigned)coder.Props[0] + 1;
+ m.Id = k_Delta;
+ }
+ }
+ else if (IsExeFilter(coder.MethodID))
+ {
+ m.Id = (UInt32)coder.MethodID;
+ if (m.Id == k_BCJ2)
+ m.Id = k_BCJ;
+ m.SetDelta();
+ }
+
+ return GetGroup(filters, m);
+}
+
+
+
static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,
UInt64 position, UInt64 size, ICompressProgressInfo *progress)
@@ -44,21 +426,12 @@ static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,
return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL);
}
-static int GetReverseSlashPos(const UString &name)
-{
- int slashPos = name.ReverseFind(L'/');
- #ifdef _WIN32
- int slash1Pos = name.ReverseFind(L'\\');
- slashPos = MyMax(slashPos, slash1Pos);
- #endif
- return slashPos;
-}
-
-int CUpdateItem::GetExtensionPos() const
+/*
+unsigned CUpdateItem::GetExtensionPos() const
{
- int slashPos = GetReverseSlashPos(Name);
- int dotPos = Name.ReverseFind(L'.');
- if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))
+ int slashPos = Name.ReverseFind_PathSepar();
+ int dotPos = Name.ReverseFind_Dot();
+ if (dotPos <= slashPos)
return Name.Len();
return dotPos + 1;
}
@@ -67,6 +440,7 @@ UString CUpdateItem::GetExtension() const
{
return Name.Ptr(GetExtensionPos());
}
+*/
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
@@ -91,7 +465,7 @@ static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2)
return CompareBuffers(c1.Props, c2.Props);
}
-static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2)
+static int CompareBonds(const CBond &b1, const CBond &b2)
{
RINOZ_COMP(b1.InIndex, b2.InIndex);
return MyCompare(b1.OutIndex, b2.OutIndex);
@@ -105,11 +479,11 @@ static int CompareFolders(const CFolder &f1, const CFolder &f2)
int i;
for (i = 0; i < s1; i++)
RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i]));
- s1 = f1.BindPairs.Size();
- s2 = f2.BindPairs.Size();
+ s1 = f1.Bonds.Size();
+ s2 = f2.Bonds.Size();
RINOZ_COMP(s1, s2);
for (i = 0; i < s1; i++)
- RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i]));
+ RINOZ(CompareBonds(f1.Bonds[i], f2.Bonds[i]));
return 0;
}
*/
@@ -123,36 +497,34 @@ static int CompareFiles(const CFileItem &f1, const CFileItem &f2)
struct CFolderRepack
{
- int FolderIndex;
- int Group;
+ unsigned FolderIndex;
CNum NumCopyFiles;
};
-static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void * /* param */)
+/*
+static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *)
{
- RINOZ_COMP(p1->Group, p2->Group);
int i1 = p1->FolderIndex;
int i2 = p2->FolderIndex;
- /*
// In that version we don't want to parse folders here, so we don't compare folders
// probably it must be improved in future
- const CDbEx &db = *(const CDbEx *)param;
- RINOZ(CompareFolders(
- db.Folders[i1],
- db.Folders[i2]));
- */
+ // const CDbEx &db = *(const CDbEx *)param;
+ // RINOZ(CompareFolders(
+ // db.Folders[i1],
+ // db.Folders[i2]));
+
return MyCompare(i1, i2);
- /*
- RINOZ_COMP(
- db.NumUnpackStreamsVector[i1],
- db.NumUnpackStreamsVector[i2]);
- if (db.NumUnpackStreamsVector[i1] == 0)
- return 0;
- return CompareFiles(
- db.Files[db.FolderStartFileIndex[i1]],
- db.Files[db.FolderStartFileIndex[i2]]);
- */
+
+ // RINOZ_COMP(
+ // db.NumUnpackStreamsVector[i1],
+ // db.NumUnpackStreamsVector[i2]);
+ // if (db.NumUnpackStreamsVector[i1] == 0)
+ // return 0;
+ // return CompareFiles(
+ // db.Files[db.FolderStartFileIndex[i1]],
+ // db.Files[db.FolderStartFileIndex[i2]]);
}
+*/
/*
we sort empty files and dirs in such order:
@@ -162,7 +534,7 @@ static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2
- Dir.Anti (reverse name sorted)
*/
-static int CompareEmptyItems(const int *p1, const int *p2, void *param)
+static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param)
{
const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param;
const CUpdateItem &u1 = updateItems[*p1];
@@ -211,9 +583,9 @@ static const char *g_Exts =
" exe dll ocx vbx sfx sys tlb awx com obj lib out o so "
" pdb pch idb ncb opt";
-static int GetExtIndex(const char *ext)
+static unsigned GetExtIndex(const char *ext)
{
- int extIndex = 1;
+ unsigned extIndex = 1;
const char *p = g_Exts;
for (;;)
{
@@ -222,7 +594,7 @@ static int GetExtIndex(const char *ext)
return extIndex;
if (c == ' ')
continue;
- int pos = 0;
+ unsigned pos = 0;
for (;;)
{
char c2 = ext[pos++];
@@ -248,8 +620,8 @@ struct CRefItem
{
const CUpdateItem *UpdateItem;
UInt32 Index;
- UInt32 ExtensionPos;
- UInt32 NamePos;
+ unsigned ExtensionPos;
+ unsigned NamePos;
unsigned ExtensionIndex;
CRefItem() {};
@@ -262,10 +634,10 @@ struct CRefItem
{
if (sortByType)
{
- int slashPos = GetReverseSlashPos(ui.Name);
+ int slashPos = ui.Name.ReverseFind_PathSepar();
NamePos = slashPos + 1;
- int dotPos = ui.Name.ReverseFind(L'.');
- if (dotPos < 0 || dotPos < slashPos)
+ int dotPos = ui.Name.ReverseFind_Dot();
+ if (dotPos <= slashPos)
ExtensionPos = ui.Name.Len();
else
{
@@ -396,35 +768,193 @@ static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *para
struct CSolidGroup
{
CRecordVector<UInt32> Indices;
+
+ CRecordVector<CFolderRepack> folderRefs;
};
-static const wchar_t *g_ExeExts[] =
+static const char *g_ExeExts[] =
{
- L"dll"
- , L"exe"
- , L"ocx"
- , L"sfx"
- , L"sys"
+ "dll"
+ , "exe"
+ , "ocx"
+ , "sfx"
+ , "sys"
};
static bool IsExeExt(const wchar_t *ext)
{
- for (int i = 0; i < ARRAY_SIZE(g_ExeExts); i++)
- if (MyStringCompareNoCase(ext, g_ExeExts[i]) == 0)
+ for (unsigned i = 0; i < ARRAY_SIZE(g_ExeExts); i++)
+ if (StringsAreEqualNoCase_Ascii(ext, g_ExeExts[i]))
return true;
return false;
}
+struct CAnalysis
+{
+ CMyComPtr<IArchiveUpdateCallbackFile> Callback;
+ CByteBuffer Buffer;
+
+ bool ParseWav;
+ bool ParseExe;
+ bool ParseAll;
-static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &m)
+ CAnalysis():
+ ParseWav(true),
+ ParseExe(false),
+ ParseAll(false)
+ {}
+
+ HRESULT GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode);
+};
+
+static const size_t kAnalysisBufSize = 1 << 14;
+
+HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode)
+{
+ filterMode.Id = 0;
+ filterMode.Delta = 0;
+
+ CFilterMode filterModeTemp = filterMode;
+
+ int slashPos = ui.Name.ReverseFind_PathSepar();
+ int dotPos = ui.Name.ReverseFind_Dot();
+
+ // if (dotPos > slashPos)
+ {
+ bool needReadFile = ParseAll;
+
+ bool probablyIsSameIsa = false;
+
+ if (!needReadFile || !Callback)
+ {
+ const wchar_t *ext;
+ if (dotPos > slashPos)
+ ext = ui.Name.Ptr(dotPos + 1);
+ else
+ ext = ui.Name.RightPtr(0);
+
+ // p7zip uses the trick to store posix attributes in high 16 bits
+ if (ui.Attrib & 0x8000)
+ {
+ unsigned st_mode = ui.Attrib >> 16;
+ // st_mode = 00111;
+ if ((st_mode & 00111) && (ui.Size >= 2048))
+ {
+ #ifndef _WIN32
+ probablyIsSameIsa = true;
+ #endif
+ needReadFile = true;
+ }
+ }
+
+ if (IsExeExt(ext))
+ {
+ needReadFile = true;
+ #ifdef _WIN32
+ probablyIsSameIsa = true;
+ needReadFile = ParseExe;
+ #endif
+ }
+ else if (StringsAreEqualNoCase_Ascii(ext, "wav"))
+ {
+ needReadFile = ParseWav;
+ }
+ /*
+ else if (!needReadFile && ParseUnixExt)
+ {
+ if (StringsAreEqualNoCase_Ascii(ext, "so")
+ || StringsAreEqualNoCase_Ascii(ext, ""))
+
+ needReadFile = true;
+ }
+ */
+ }
+
+ if (needReadFile && Callback)
+ {
+ if (Buffer.Size() != kAnalysisBufSize)
+ {
+ Buffer.Alloc(kAnalysisBufSize);
+ }
+ {
+ CMyComPtr<ISequentialInStream> stream;
+ HRESULT result = Callback->GetStream2(index, &stream, NUpdateNotifyOp::kAnalyze);
+ if (result == S_OK && stream)
+ {
+ size_t size = kAnalysisBufSize;
+ result = ReadStream(stream, Buffer, &size);
+ stream.Release();
+ // RINOK(Callback->SetOperationResult2(index, NUpdate::NOperationResult::kOK));
+ if (result == S_OK)
+ {
+ Bool parseRes = ParseFile(Buffer, size, &filterModeTemp);
+ if (parseRes && filterModeTemp.Delta == 0)
+ {
+ filterModeTemp.SetDelta();
+ if (filterModeTemp.Delta != 0 && filterModeTemp.Id != k_Delta)
+ {
+ if (ui.Size % filterModeTemp.Delta != 0)
+ {
+ parseRes = false;
+ }
+ }
+ }
+ if (!parseRes)
+ {
+ filterModeTemp.Id = 0;
+ filterModeTemp.Delta = 0;
+ }
+ }
+ }
+ }
+ }
+ else if ((needReadFile && !Callback) || probablyIsSameIsa)
+ {
+ #ifdef MY_CPU_X86_OR_AMD64
+ if (probablyIsSameIsa)
+ filterModeTemp.Id = k_X86;
+ #endif
+ }
+ }
+
+ filterMode = filterModeTemp;
+ return S_OK;
+}
+
+static inline void GetMethodFull(UInt64 methodID, UInt32 numStreams, CMethodFull &m)
{
m.Id = methodID;
- m.NumInStreams = numInStreams;
- m.NumOutStreams = 1;
+ m.NumStreams = numStreams;
+}
+
+static HRESULT AddBondForFilter(CCompressionMethodMode &mode)
+{
+ for (unsigned c = 1; c < mode.Methods.Size(); c++)
+ {
+ if (!mode.IsThereBond_to_Coder(c))
+ {
+ CBond2 bond;
+ bond.OutCoder = 0;
+ bond.OutStream = 0;
+ bond.InCoder = c;
+ mode.Bonds.Add(bond);
+ return S_OK;
+ }
+ }
+ return E_INVALIDARG;
}
-static void AddBcj2Methods(CCompressionMethodMode &mode)
+static HRESULT AddFilterBond(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 !
+
CMethodFull m;
GetMethodFull(k_LZMA, 1, m);
@@ -433,54 +963,121 @@ static void AddBcj2Methods(CCompressionMethodMode &mode)
m.AddProp32(NCoderPropID::kNumThreads, 1);
m.AddProp32(NCoderPropID::kLitPosBits, 2);
m.AddProp32(NCoderPropID::kLitContextBits, 0);
- // m.AddPropString(NCoderPropID::kMatchFinder, L"BT2");
+ // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2");
+
+ unsigned methodIndex = mode.Methods.Size();
+
+ if (mode.Bonds.IsEmpty())
+ {
+ for (unsigned i = 1; i + 1 < mode.Methods.Size(); i++)
+ {
+ CBond2 bond;
+ bond.OutCoder = i;
+ bond.OutStream = 0;
+ bond.InCoder = i + 1;
+ mode.Bonds.Add(bond);
+ }
+ }
mode.Methods.Add(m);
mode.Methods.Add(m);
- CBind bind;
- bind.OutCoder = 0;
- bind.InStream = 0;
- bind.InCoder = 1; bind.OutStream = 0; mode.Binds.Add(bind);
- bind.InCoder = 2; bind.OutStream = 1; mode.Binds.Add(bind);
- bind.InCoder = 3; bind.OutStream = 2; mode.Binds.Add(bind);
+ RINOK(AddBondForFilter(mode));
+ CBond2 bond;
+ bond.OutCoder = 0;
+ 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 void MakeExeMethod(CCompressionMethodMode &mode,
- bool useFilters, bool addFilter, bool bcj2Filter)
+static HRESULT MakeExeMethod(CCompressionMethodMode &mode,
+ const CFilterMode &filterMode, /* bool addFilter, */ bool bcj2Filter)
{
- if (!mode.Binds.IsEmpty() || !useFilters || mode.Methods.Size() > 2)
- return;
- if (mode.Methods.Size() == 2)
+ if (mode.Filter_was_Inserted)
{
- if (mode.Methods[0].Id == k_BCJ2)
- AddBcj2Methods(mode);
- return;
+ const CMethodFull &m = mode.Methods[0];
+ CMethodId id = m.Id;
+ if (id == k_BCJ2)
+ return AddBcj2Methods(mode);
+ if (!m.IsSimpleCoder())
+ return E_NOTIMPL;
+ // if (Bonds.IsEmpty()) we can create bonds later
+ return AddFilterBond(mode);
+ }
+
+ if (filterMode.Id == 0)
+ return S_OK;
+
+ CMethodFull &m = mode.Methods.InsertNew(0);
+
+ {
+ FOR_VECTOR(k, mode.Bonds)
+ {
+ CBond2 &bond = mode.Bonds[k];
+ bond.InCoder++;
+ bond.OutCoder++;
+ }
}
- if (!addFilter)
- return;
- bcj2Filter = bcj2Filter;
- #ifdef USE_86_FILTER
- if (bcj2Filter)
+
+ HRESULT res;
+
+ if (bcj2Filter && Is86Filter(filterMode.Id))
{
- CMethodFull m;
GetMethodFull(k_BCJ2, 4, m);
- mode.Methods.Insert(0, m);
- AddBcj2Methods(mode);
+ res = AddBcj2Methods(mode);
}
else
{
- CMethodFull m;
- GetMethodFull(k_BCJ, 1, m);
- mode.Methods.Insert(0, m);
- CBind bind;
- bind.OutCoder = 0;
- bind.InStream = 0;
- bind.InCoder = 1;
- bind.OutStream = 0;
- mode.Binds.Add(bind);
+ GetMethodFull(filterMode.Id, 1, m);
+ if (filterMode.Id == k_Delta)
+ m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta);
+ res = AddFilterBond(mode);
+
+ int alignBits = -1;
+ if (filterMode.Id == k_Delta || filterMode.Delta != 0)
+ {
+ if (filterMode.Delta == 1) alignBits = 0;
+ else if (filterMode.Delta == 2) alignBits = 1;
+ else if (filterMode.Delta == 4) alignBits = 2;
+ else if (filterMode.Delta == 8) alignBits = 3;
+ else if (filterMode.Delta == 16) alignBits = 4;
+ }
+ else
+ {
+ // alignBits = GetAlignForFilterMethod(filterMode.Id);
+ }
+
+ if (res == S_OK && alignBits >= 0)
+ {
+ 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, alignBits);
+ unsigned lc = 0;
+ if (alignBits < 3)
+ lc = 3 - alignBits;
+ nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc);
+ nextMethod.AddProp32(NCoderPropID::kLitPosBits, alignBits);
+ }
+ }
+ }
+ }
+ }
}
- #endif
+
+ return res;
}
@@ -503,133 +1100,336 @@ static void FromUpdateItemToFileItem(const CUpdateItem &ui,
// file.IsAltStream = ui.IsAltStream;
}
-class CFolderOutStream2:
- public ISequentialOutStream,
+class CRepackInStreamWithSizes:
+ public ISequentialInStream,
+ public ICompressGetSubStreamSize,
public CMyUnknownImp
{
- COutStreamWithCRC *_crcStreamSpec;
- CMyComPtr<ISequentialOutStream> _crcStream;
- const CDbEx *_db;
+ CMyComPtr<ISequentialInStream> _stream;
+ // UInt64 _size;
const CBoolVector *_extractStatuses;
- CMyComPtr<ISequentialOutStream> _outStream;
UInt32 _startIndex;
- unsigned _currentIndex;
+public:
+ const CDbEx *_db;
+
+ void Init(ISequentialInStream *stream, UInt32 startIndex, const CBoolVector *extractStatuses)
+ {
+ _startIndex = startIndex;
+ _extractStatuses = extractStatuses;
+ // _size = 0;
+ _stream = stream;
+ }
+ // UInt64 GetSize() const { return _size; }
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+ STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
+};
+
+STDMETHODIMP CRepackInStreamWithSizes::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ return _stream->Read(data, size, processedSize);
+ /*
+ UInt32 realProcessedSize;
+ HRESULT result = _stream->Read(data, size, &realProcessedSize);
+ _size += realProcessedSize;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return result;
+ */
+}
+
+STDMETHODIMP CRepackInStreamWithSizes::GetSubStreamSize(UInt64 subStream, UInt64 *value)
+{
+ *value = 0;
+ if (subStream >= _extractStatuses->Size())
+ return S_FALSE; // E_FAIL;
+ unsigned index = (unsigned)subStream;
+ if ((*_extractStatuses)[index])
+ {
+ const CFileItem &fi = _db->Files[_startIndex + index];
+ if (fi.HasStream)
+ *value = fi.Size;
+ }
+ return S_OK;
+}
+
+
+class CRepackStreamBase
+{
+protected:
+ bool _needWrite;
bool _fileIsOpen;
+ bool _calcCrc;
+ UInt32 _crc;
UInt64 _rem;
- void OpenFile();
- void CloseFile();
- HRESULT CloseFileAndSetResult();
+ const CBoolVector *_extractStatuses;
+ UInt32 _startIndex;
+ unsigned _currentIndex;
+
+ HRESULT OpenFile();
+ HRESULT CloseFile();
HRESULT ProcessEmptyFiles();
+
public:
- MY_UNKNOWN_IMP
-
- CFolderOutStream2()
- {
- _crcStreamSpec = new COutStreamWithCRC;
- _crcStream = _crcStreamSpec;
- }
+ const CDbEx *_db;
+ CMyComPtr<IArchiveUpdateCallbackFile> _opCallback;
+ CMyComPtr<IArchiveExtractCallbackMessage> _extractCallback;
- HRESULT Init(const CDbEx *db, UInt32 startIndex,
- const CBoolVector *extractStatuses, ISequentialOutStream *outStream);
- void ReleaseOutStream();
+ HRESULT Init(UInt32 startIndex, const CBoolVector *extractStatuses);
HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }
-
- STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
};
-HRESULT CFolderOutStream2::Init(const CDbEx *db, UInt32 startIndex,
- const CBoolVector *extractStatuses, ISequentialOutStream *outStream)
+HRESULT CRepackStreamBase::Init(UInt32 startIndex, const CBoolVector *extractStatuses)
{
- _db = db;
_startIndex = startIndex;
_extractStatuses = extractStatuses;
- _outStream = outStream;
_currentIndex = 0;
_fileIsOpen = false;
+
return ProcessEmptyFiles();
}
-void CFolderOutStream2::ReleaseOutStream()
+HRESULT CRepackStreamBase::OpenFile()
{
- _outStream.Release();
- _crcStreamSpec->ReleaseStream();
-}
+ UInt32 arcIndex = _startIndex + _currentIndex;
+ const CFileItem &fi = _db->Files[arcIndex];
+
+ _needWrite = (*_extractStatuses)[_currentIndex];
+ if (_opCallback)
+ {
+ RINOK(_opCallback->ReportOperation(
+ NEventIndexType::kInArcIndex, arcIndex,
+ _needWrite ?
+ NUpdateNotifyOp::kRepack :
+ NUpdateNotifyOp::kSkip));
+ }
+
+ _crc = CRC_INIT_VAL;
+ _calcCrc = (fi.CrcDefined && !fi.IsDir);
-void CFolderOutStream2::OpenFile()
-{
- _crcStreamSpec->SetStream((*_extractStatuses)[_currentIndex] ? _outStream : NULL);
- _crcStreamSpec->Init(true);
_fileIsOpen = true;
- _rem = _db->Files[_startIndex + _currentIndex].Size;
+ _rem = fi.Size;
+ return S_OK;
}
-void CFolderOutStream2::CloseFile()
+const HRESULT k_My_HRESULT_CRC_ERROR = 0x20000002;
+
+HRESULT CRepackStreamBase::CloseFile()
{
- _crcStreamSpec->ReleaseStream();
+ UInt32 arcIndex = _startIndex + _currentIndex;
+ const CFileItem &fi = _db->Files[arcIndex];
_fileIsOpen = false;
_currentIndex++;
-}
+ if (!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc))
+ return S_OK;
-HRESULT CFolderOutStream2::CloseFileAndSetResult()
-{
- const CFileItem &file = _db->Files[_startIndex + _currentIndex];
- CloseFile();
- return (file.IsDir || !file.CrcDefined || file.Crc == _crcStreamSpec->GetCRC()) ? S_OK: S_FALSE;
+ if (_extractCallback)
+ {
+ RINOK(_extractCallback->ReportExtractResult(
+ NEventIndexType::kInArcIndex, arcIndex,
+ NExtract::NOperationResult::kCRCError));
+ }
+ // return S_FALSE;
+ return k_My_HRESULT_CRC_ERROR;
}
-HRESULT CFolderOutStream2::ProcessEmptyFiles()
+HRESULT CRepackStreamBase::ProcessEmptyFiles()
{
while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)
{
- OpenFile();
- RINOK(CloseFileAndSetResult());
+ RINOK(OpenFile());
+ RINOK(CloseFile());
}
return S_OK;
}
+
+
+
+#ifndef _7ZIP_ST
+
+class CFolderOutStream2:
+ public CRepackStreamBase,
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ CMyComPtr<ISequentialOutStream> _stream;
+
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = 0;
+
while (size != 0)
{
if (_fileIsOpen)
{
- UInt32 cur = size < _rem ? size : (UInt32)_rem;
- RINOK(_crcStream->Write(data, cur, &cur));
- if (cur == 0)
- break;
+ UInt32 cur = (size < _rem ? size : (UInt32)_rem);
+ HRESULT result = S_OK;
+ if (_needWrite)
+ result = _stream->Write(data, cur, &cur);
+ if (_calcCrc)
+ _crc = CrcUpdate(_crc, data, cur);
+ if (processedSize)
+ *processedSize += cur;
data = (const Byte *)data + cur;
size -= cur;
_rem -= cur;
- if (processedSize != NULL)
- *processedSize += cur;
if (_rem == 0)
{
- RINOK(CloseFileAndSetResult());
+ RINOK(CloseFile());
RINOK(ProcessEmptyFiles());
- continue;
}
+ RINOK(result);
+ if (cur == 0)
+ break;
+ continue;
}
- else
+
+ RINOK(ProcessEmptyFiles());
+ if (_currentIndex == _extractStatuses->Size())
{
- RINOK(ProcessEmptyFiles());
- if (_currentIndex == _extractStatuses->Size())
+ // we don't support write cut here
+ return E_FAIL;
+ }
+ RINOK(OpenFile());
+ }
+
+ return S_OK;
+}
+
+#endif
+
+
+
+static const UInt32 kTempBufSize = 1 << 16;
+
+class CFolderInStream2:
+ public CRepackStreamBase,
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ Byte *_buf;
+public:
+ CMyComPtr<ISequentialInStream> _inStream;
+ HRESULT Result;
+
+ MY_UNKNOWN_IMP
+
+ CFolderInStream2():
+ Result(S_OK)
+ {
+ _buf = new Byte[kTempBufSize];
+ }
+
+ ~CFolderInStream2()
+ {
+ delete []_buf;
+ }
+
+ void Init() { Result = S_OK; }
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CFolderInStream2::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+
+ while (size != 0)
+ {
+ if (_fileIsOpen)
+ {
+ UInt32 cur = (size < _rem ? size : (UInt32)_rem);
+
+ void *buf;
+ if (_needWrite)
+ buf = data;
+ else
{
- // we don't support partial extracting
- return E_FAIL;
+ buf = _buf;
+ if (cur > kTempBufSize)
+ cur = kTempBufSize;
}
- OpenFile();
+
+ HRESULT result = _inStream->Read(buf, cur, &cur);
+ _crc = CrcUpdate(_crc, buf, cur);
+ _rem -= cur;
+
+ if (_needWrite)
+ {
+ data = (Byte *)data + cur;
+ size -= cur;
+ if (processedSize)
+ *processedSize += cur;
+ }
+
+ if (result != S_OK)
+ Result = result;
+
+ if (_rem == 0)
+ {
+ RINOK(CloseFile());
+ RINOK(ProcessEmptyFiles());
+ }
+
+ RINOK(result);
+
+ if (cur == 0)
+ return E_FAIL;
+
+ continue;
}
+
+ RINOK(ProcessEmptyFiles());
+ if (_currentIndex == _extractStatuses->Size())
+ {
+ return S_OK;
+ }
+ RINOK(OpenFile());
}
+
return S_OK;
}
-class CThreadDecoder: public CVirtThread
+
+class CThreadDecoder
+ #ifndef _7ZIP_ST
+ : public CVirtThread
+ #endif
{
public:
+ CDecoder Decoder;
+
+ CThreadDecoder(bool multiThreadMixer):
+ Decoder(multiThreadMixer)
+ {
+ #ifndef _7ZIP_ST
+ if (multiThreadMixer)
+ {
+ MtMode = false;
+ NumThreads = 1;
+ FosSpec = new CFolderOutStream2;
+ Fos = FosSpec;
+ Result = E_FAIL;
+ }
+ #endif
+ // UnpackSize = 0;
+ // send_UnpackSize = false;
+ }
+
+ #ifndef _7ZIP_ST
+
HRESULT Result;
CMyComPtr<IInStream> InStream;
@@ -639,33 +1439,30 @@ public:
UInt64 StartPos;
const CFolders *Folders;
int FolderIndex;
+
+ // bool send_UnpackSize;
+ // UInt64 UnpackSize;
+
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
#endif
DECL_EXTERNAL_CODECS_LOC_VARS2;
- CDecoder Decoder;
#ifndef _7ZIP_ST
bool MtMode;
UInt32 NumThreads;
#endif
- CThreadDecoder():
- Decoder(true)
- {
- #ifndef _7ZIP_ST
- MtMode = false;
- NumThreads = 1;
- #endif
- FosSpec = new CFolderOutStream2;
- Fos = FosSpec;
- Result = E_FAIL;
- }
+
~CThreadDecoder() { CVirtThread::WaitThreadFinish(); }
virtual void Execute();
+
+ #endif
};
+#ifndef _7ZIP_ST
+
void CThreadDecoder::Execute()
{
try
@@ -673,6 +1470,7 @@ void CThreadDecoder::Execute()
#ifndef _NO_CRYPTO
bool isEncrypted = false;
bool passwordIsDefined = false;
+ UString password;
#endif
Result = Decoder.Decode(
@@ -680,8 +1478,14 @@ void CThreadDecoder::Execute()
InStream,
StartPos,
*Folders, FolderIndex,
+
+ // send_UnpackSize ? &UnpackSize : NULL,
+ NULL, // unpackSize : FULL unpack
+
Fos,
- NULL
+ NULL, // compressProgress
+ NULL // *inStreamMainRes
+
_7Z_DECODER_CRYPRO_VARS
#ifndef _7ZIP_ST
, MtMode, NumThreads
@@ -692,21 +1496,15 @@ void CThreadDecoder::Execute()
{
Result = E_FAIL;
}
+
+ /*
if (Result == S_OK)
Result = FosSpec->CheckFinishedState();
- FosSpec->ReleaseOutStream();
+ */
+ FosSpec->_stream.Release();
}
-bool static Is86FilteredFolder(const CFolder &f)
-{
- FOR_VECTOR(i, f.Coders)
- {
- CMethodId m = f.Coders[i].MethodID;
- if (m == k_BCJ || m == k_BCJ2)
- return true;
- }
- return false;
-}
+#endif
#ifndef _NO_CRYPTO
@@ -728,14 +1526,8 @@ STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password)
#endif
-static const int kNumGroupsMax = 4;
-
-static bool Is86Group(int group) { return (group & 1) != 0; }
-static bool IsEncryptedGroup(int group) { return (group & 2) != 0; }
-static int GetGroupIndex(bool encrypted, int bcjFiltered)
- { return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); }
-static void GetFile(const CDatabase &inDb, int index, CFileItem &file, CFileItem2 &file2)
+static void GetFile(const CDatabase &inDb, unsigned index, CFileItem &file, CFileItem2 &file2)
{
file = inDb.Files[index];
file2.CTimeDefined = inDb.CTime.GetItem(index, file2.CTime);
@@ -767,6 +1559,12 @@ HRESULT Update(
if (numSolidFiles == 0)
numSolidFiles = 1;
+ CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
+ updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
+
+ CMyComPtr<IArchiveExtractCallbackMessage> extractCallback;
+ updateCallback->QueryInterface(IID_IArchiveExtractCallbackMessage, (void **)&extractCallback);
+
// size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes();
/*
@@ -783,14 +1581,19 @@ HRESULT Update(
}
CIntArr fileIndexToUpdateIndexMap;
- CRecordVector<CFolderRepack> folderRefs;
UInt64 complexity = 0;
UInt64 inSizeForReduce2 = 0;
bool needEncryptedRepack = false;
+
+ CRecordVector<CFilterMode2> filters;
+ CObjectVector<CSolidGroup> groups;
+ bool thereAreRepacks = false;
+
if (db != 0)
{
fileIndexToUpdateIndexMap.Alloc(db->Files.Size());
unsigned i;
+
for (i = 0; i < db->Files.Size(); i++)
fileIndexToUpdateIndexMap[i] = -1;
@@ -798,15 +1601,16 @@ HRESULT Update(
{
int index = updateItems[i].IndexInArchive;
if (index != -1)
- fileIndexToUpdateIndexMap[index] = i;
+ fileIndexToUpdateIndexMap[(unsigned)index] = i;
}
- for (i = 0; i < (int)db->NumFolders; i++)
+ for (i = 0; i < db->NumFolders; i++)
{
CNum indexInFolder = 0;
CNum numCopyItems = 0;
CNum numUnpackStreams = db->NumUnpackStreamsVector[i];
UInt64 repackSize = 0;
+
for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++)
{
const CFileItem &file = db->Files[fi];
@@ -828,23 +1632,30 @@ HRESULT Update(
CFolderRepack rep;
rep.FolderIndex = i;
rep.NumCopyFiles = numCopyItems;
- CFolder f;
- db->ParseFolderInfo(i, f);
+ CFolderEx f;
+ db->ParseFolderEx(i, f);
+
bool isEncrypted = f.IsEncrypted();
- rep.Group = GetGroupIndex(isEncrypted, Is86FilteredFolder(f));
- folderRefs.Add(rep);
+
+ unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f);
+
+ while (groupIndex >= groups.Size())
+ groups.AddNew();
+
+ groups[groupIndex].folderRefs.Add(rep);
+
if (numCopyItems == numUnpackStreams)
complexity += db->GetFolderFullPackSize(i);
else
{
+ thereAreRepacks = true;
complexity += repackSize;
- if (repackSize > inSizeForReduce2)
+ if (inSizeForReduce2 < repackSize)
inSizeForReduce2 = repackSize;
if (isEncrypted)
needEncryptedRepack = true;
}
}
- folderRefs.Sort(CompareFolderRepacks, (void *)db);
}
UInt64 inSizeForReduce = 0;
@@ -857,12 +1668,12 @@ HRESULT Update(
complexity += ui.Size;
if (numSolidFiles != 1)
inSizeForReduce += ui.Size;
- else if (ui.Size > inSizeForReduce)
+ else if (inSizeForReduce < ui.Size)
inSizeForReduce = ui.Size;
}
}
- if (inSizeForReduce2 > inSizeForReduce)
+ if (inSizeForReduce < inSizeForReduce2)
inSizeForReduce = inSizeForReduce2;
RINOK(updateCallback->SetTotal(complexity));
@@ -871,52 +1682,102 @@ HRESULT Update(
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(updateCallback, true);
+ #ifndef _7ZIP_ST
+
CStreamBinder sb;
- RINOK(sb.CreateEvents());
+ if (options.MultiThreadMixer)
+ {
+ RINOK(sb.CreateEvents());
+ }
+
+ #endif
- CThreadDecoder threadDecoder;
- if (!folderRefs.IsEmpty())
+ CThreadDecoder threadDecoder(options.MultiThreadMixer);
+
+ #ifndef _7ZIP_ST
+ if (options.MultiThreadMixer && thereAreRepacks)
{
#ifdef EXTERNAL_CODECS
threadDecoder.__externalCodecs = __externalCodecs;
#endif
RINOK(threadDecoder.Create());
}
-
- CObjectVector<CSolidGroup> groups;
- for (i = 0; i < kNumGroupsMax; i++)
- groups.AddNew();
+ #endif
{
+ CAnalysis analysis;
+ if (options.AnalysisLevel == 0)
+ {
+ analysis.ParseWav = false;
+ analysis.ParseExe = false;
+ analysis.ParseAll = false;
+ }
+ else
+ {
+ analysis.Callback = opCallback;
+ if (options.AnalysisLevel > 0)
+ {
+ analysis.ParseWav = true;
+ if (options.AnalysisLevel >= 7)
+ {
+ analysis.ParseExe = true;
+ if (options.AnalysisLevel >= 9)
+ analysis.ParseAll = true;
+ }
+ }
+ }
+
// ---------- Split files to groups ----------
bool useFilters = options.UseFilters;
const CCompressionMethodMode &method = *options.Method;
- if (method.Methods.Size() != 1 || method.Binds.Size() != 0)
+
+ if (useFilters)
+ for (i = 0; i < method.Methods.Size(); i++)
+ if (IsFilterMethod(method.Methods[i].Id))
+ {
+ useFilters = false;
+ break;
+ }
+
+ /*
+ if (!method.Bonds.IsEmpty())
useFilters = false;
+ */
+
for (i = 0; i < updateItems.Size(); i++)
{
const CUpdateItem &ui = updateItems[i];
if (!ui.NewData || !ui.HasStream())
continue;
- bool filteredGroup = false;
+
+ CFilterMode2 fm;
if (useFilters)
{
- int dotPos = ui.Name.ReverseFind(L'.');
- if (dotPos >= 0)
- filteredGroup = IsExeExt(ui.Name.Ptr(dotPos + 1));
+ RINOK(analysis.GetFilterGroup(i, ui, fm));
}
- groups[GetGroupIndex(method.PasswordIsDefined, filteredGroup)].Indices.Add(i);
+ fm.Encrypted = method.PasswordIsDefined;
+
+ unsigned groupIndex = GetGroup(filters, fm);
+ while (groupIndex >= groups.Size())
+ groups.AddNew();
+ groups[groupIndex].Indices.Add(i);
}
}
+
#ifndef _NO_CRYPTO
CCryptoGetTextPassword *getPasswordSpec = NULL;
+ CMyComPtr<ICryptoGetTextPassword> getTextPassword;
if (needEncryptedRepack)
{
getPasswordSpec = new CCryptoGetTextPassword;
+ getTextPassword = getPasswordSpec;
+
+ #ifndef _7ZIP_ST
threadDecoder.getTextPassword = getPasswordSpec;
+ #endif
if (options.Method->PasswordIsDefined)
getPasswordSpec->Password = options.Method->Password;
@@ -926,7 +1787,7 @@ HRESULT Update(
return E_NOTIMPL;
CMyComBSTR password;
RINOK(getDecoderPassword->CryptoGetTextPassword(&password));
- if ((BSTR)password)
+ if (password)
getPasswordSpec->Password = password;
}
}
@@ -986,7 +1847,8 @@ HRESULT Update(
{
/* ---------- Write non-AUX dirs and Empty files ---------- */
- CRecordVector<int> emptyRefs;
+ CUIntVector emptyRefs;
+
for (i = 0; i < updateItems.Size(); i++)
{
const CUpdateItem &ui = updateItems[i];
@@ -1003,7 +1865,9 @@ HRESULT Update(
*/
emptyRefs.Add(i);
}
+
emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);
+
for (i = 0; i < emptyRefs.Size(); i++)
{
const CUpdateItem &ui = updateItems[emptyRefs[i]];
@@ -1030,17 +1894,34 @@ HRESULT Update(
}
}
- unsigned folderRefIndex = 0;
lps->ProgressOffset = 0;
- for (int groupIndex = 0; groupIndex < kNumGroupsMax; groupIndex++)
{
- const CSolidGroup &group = groups[groupIndex];
+ // ---------- Sort Filters ----------
+
+ FOR_VECTOR (i, filters)
+ {
+ filters[i].GroupIndex = i;
+ }
+ filters.Sort2();
+ }
+
+ for (unsigned groupIndex = 0; groupIndex < filters.Size(); groupIndex++)
+ {
+ const CFilterMode2 &filterMode = filters[groupIndex];
CCompressionMethodMode method = *options.Method;
- MakeExeMethod(method, options.UseFilters, Is86Group(groupIndex), options.MaxFilter);
+ HRESULT res = MakeExeMethod(method, filterMode,
+ #ifdef _7ZIP_ST
+ false
+ #else
+ options.MaxFilter && options.MultiThreadMixer
+ #endif
+ );
+
+ RINOK(res);
- if (IsEncryptedGroup(groupIndex))
+ if (filterMode.Encrypted)
{
if (!method.PasswordIsDefined)
{
@@ -1059,83 +1940,260 @@ HRESULT Update(
CEncoder encoder(method);
- for (; folderRefIndex < folderRefs.Size(); folderRefIndex++)
+ // ---------- Repack and copy old solid blocks ----------
+
+ const CSolidGroup &group = groups[filterMode.GroupIndex];
+
+ FOR_VECTOR(folderRefIndex, group.folderRefs)
{
- const CFolderRepack &rep = folderRefs[folderRefIndex];
- if (rep.Group != groupIndex)
- break;
- int folderIndex = rep.FolderIndex;
+ const CFolderRepack &rep = group.folderRefs[folderRefIndex];
+
+ unsigned folderIndex = rep.FolderIndex;
- if (rep.NumCopyFiles == db->NumUnpackStreamsVector[folderIndex])
+ CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
+
+ if (rep.NumCopyFiles == numUnpackStreams)
{
+ if (opCallback)
+ {
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kBlockIndex, (UInt32)folderIndex,
+ NUpdateNotifyOp::kReplicate));
+
+ // ---------- Copy old solid block ----------
+ {
+ CNum indexInFolder = 0;
+ for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
+ {
+ if (db->Files[fi].HasStream)
+ {
+ indexInFolder++;
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kInArcIndex, (UInt32)fi,
+ NUpdateNotifyOp::kReplicate));
+ }
+ }
+ }
+ }
+
UInt64 packSize = db->GetFolderFullPackSize(folderIndex);
RINOK(WriteRange(inStream, archive.SeqStream,
- db->GetFolderStreamPos(folderIndex, 0), packSize, progress));
+ db->GetFolderStreamPos(folderIndex, 0), packSize, progress));
lps->ProgressOffset += packSize;
CFolder &folder = newDatabase.Folders.AddNew();
db->ParseFolderInfo(folderIndex, folder);
CNum startIndex = db->FoStartPackStreamIndex[folderIndex];
- for (unsigned j = 0; j < folder.PackStreams.Size(); j++)
+ FOR_VECTOR(j, folder.PackStreams)
{
newDatabase.PackSizes.Add(db->GetStreamPackSize(startIndex + j));
// newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]);
// newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]);
}
- UInt32 indexStart = db->FoToCoderUnpackSizes[folderIndex];
- UInt32 indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1];
+ size_t indexStart = db->FoToCoderUnpackSizes[folderIndex];
+ size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1];
for (; indexStart < indexEnd; indexStart++)
newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]);
}
else
{
+ // ---------- Repack old solid block ----------
+
CBoolVector extractStatuses;
- CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
CNum indexInFolder = 0;
-
+
+ if (opCallback)
+ {
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kBlockIndex, (UInt32)folderIndex,
+ NUpdateNotifyOp::kRepack))
+ }
+
+ /* We could reduce data size of decoded folder, if we don't need to repack
+ last files in folder. But the gain in speed is small in most cases.
+ So we unpack full folder. */
+
+ UInt64 sizeToEncode = 0;
+
+ /*
+ UInt64 importantUnpackSize = 0;
+ unsigned numImportantFiles = 0;
+ UInt64 decodeSize = 0;
+ */
+
for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
{
bool needExtract = false;
- if (db->Files[fi].HasStream)
+ const CFileItem &file = db->Files[fi];
+
+ if (file.HasStream)
{
indexInFolder++;
int updateIndex = fileIndexToUpdateIndexMap[fi];
if (updateIndex >= 0 && !updateItems[updateIndex].NewData)
needExtract = true;
+ // decodeSize += file.Size;
}
+
extractStatuses.Add(needExtract);
+ if (needExtract)
+ {
+ sizeToEncode += file.Size;
+ /*
+ numImportantFiles = extractStatuses.Size();
+ importantUnpackSize = decodeSize;
+ */
+ }
}
+ // extractStatuses.DeleteFrom(numImportantFiles);
+
unsigned startPackIndex = newDatabase.PackSizes.Size();
UInt64 curUnpackSize;
{
+
CMyComPtr<ISequentialInStream> sbInStream;
+ CRepackStreamBase *repackBase;
+ CFolderInStream2 *FosSpec2 = NULL;
+
+ CRepackInStreamWithSizes *inStreamSizeCountSpec = new CRepackInStreamWithSizes;
+ CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
{
- CMyComPtr<ISequentialOutStream> sbOutStream;
- sb.CreateStreams(&sbInStream, &sbOutStream);
- sb.ReInit();
- RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream));
- }
-
- threadDecoder.InStream = inStream;
- threadDecoder.Folders = (const CFolders *)db;
- threadDecoder.FolderIndex = folderIndex;
- threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0);
-
- threadDecoder.Start();
+ #ifndef _7ZIP_ST
+ if (options.MultiThreadMixer)
+ {
+ repackBase = threadDecoder.FosSpec;
+ CMyComPtr<ISequentialOutStream> sbOutStream;
+ sb.CreateStreams(&sbInStream, &sbOutStream);
+ sb.ReInit();
+
+ threadDecoder.FosSpec->_stream = sbOutStream;
+
+ threadDecoder.InStream = inStream;
+ threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0);
+ threadDecoder.Folders = (const CFolders *)db;
+ threadDecoder.FolderIndex = folderIndex;
+
+ // threadDecoder.UnpackSize = importantUnpackSize;
+ // threadDecoder.send_UnpackSize = true;
+ }
+ else
+ #endif
+ {
+ FosSpec2 = new CFolderInStream2;
+ FosSpec2->Init();
+ sbInStream = FosSpec2;
+ repackBase = FosSpec2;
+
+ #ifndef _NO_CRYPTO
+ bool isEncrypted = false;
+ bool passwordIsDefined = false;
+ UString password;
+ #endif
+
+ CMyComPtr<ISequentialInStream> decodedStream;
+ HRESULT res = threadDecoder.Decoder.Decode(
+ EXTERNAL_CODECS_LOC_VARS
+ inStream,
+ db->ArcInfo.DataStartPosition, // db->GetFolderStreamPos(folderIndex, 0);,
+ *db, folderIndex,
+ // &importantUnpackSize, // *unpackSize
+ NULL, // *unpackSize : FULL unpack
+
+ NULL, // *outStream
+ NULL, // *compressProgress
+ &decodedStream
+
+ _7Z_DECODER_CRYPRO_VARS
+ #ifndef _7ZIP_ST
+ , false // mtMode
+ , 1 // numThreads
+ #endif
+ );
- RINOK(encoder.Encode(
+ RINOK(res);
+ if (!decodedStream)
+ return E_FAIL;
+
+ FosSpec2->_inStream = decodedStream;
+ }
+
+ repackBase->_db = db;
+ repackBase->_opCallback = opCallback;
+ repackBase->_extractCallback = extractCallback;
+
+ UInt32 startIndex = db->FolderStartFileIndex[folderIndex];
+ RINOK(repackBase->Init(startIndex, &extractStatuses));
+
+ inStreamSizeCountSpec->_db = db;
+ inStreamSizeCountSpec->Init(sbInStream, startIndex, &extractStatuses);
+
+ #ifndef _7ZIP_ST
+ if (options.MultiThreadMixer)
+ {
+ threadDecoder.Start();
+ }
+ #endif
+ }
+
+
+ HRESULT encodeRes = encoder.Encode(
EXTERNAL_CODECS_LOC_VARS
- sbInStream, NULL, &inSizeForReduce,
+ inStreamSizeCount,
+ // NULL,
+ &inSizeForReduce,
newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curUnpackSize,
- archive.SeqStream, newDatabase.PackSizes, progress));
-
- threadDecoder.WaitExecuteFinish();
- }
+ archive.SeqStream, newDatabase.PackSizes, progress);
- RINOK(threadDecoder.Result);
+ if (encodeRes == k_My_HRESULT_CRC_ERROR)
+ return E_FAIL;
+
+ #ifndef _7ZIP_ST
+ if (options.MultiThreadMixer)
+ {
+ threadDecoder.WaitExecuteFinish();
+ HRESULT decodeRes = threadDecoder.Result;
+ // if (res == k_My_HRESULT_CRC_ERROR)
+ if (decodeRes == S_FALSE)
+ {
+ if (extractCallback)
+ {
+ RINOK(extractCallback->ReportExtractResult(
+ NEventIndexType::kInArcIndex, db->FolderStartFileIndex[folderIndex],
+ // NEventIndexType::kBlockIndex, (UInt32)folderIndex,
+ NExtract::NOperationResult::kDataError));
+ }
+ return E_FAIL;
+ }
+ RINOK(decodeRes);
+ if (encodeRes == S_OK)
+ if (sb.ProcessedSize != sizeToEncode)
+ encodeRes = E_FAIL;
+ }
+ else
+ #endif
+ {
+ if (FosSpec2->Result == S_FALSE)
+ {
+ if (extractCallback)
+ {
+ RINOK(extractCallback->ReportExtractResult(
+ NEventIndexType::kBlockIndex, (UInt32)folderIndex,
+ NExtract::NOperationResult::kDataError));
+ }
+ return E_FAIL;
+ }
+ RINOK(FosSpec2->Result);
+ }
+
+ RINOK(encodeRes);
+ RINOK(repackBase->CheckFinishedState());
+
+ if (curUnpackSize != sizeToEncode)
+ return E_FAIL;
+ }
for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)
lps->OutSize += newDatabase.PackSizes[startPackIndex];
@@ -1144,8 +2202,6 @@ HRESULT Update(
newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles);
- CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
-
CNum indexInFolder = 0;
for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
{
@@ -1187,6 +2243,9 @@ HRESULT Update(
}
}
+
+ // ---------- Compress files to new solid blocks ----------
+
unsigned numFiles = group.Indices.Size();
if (numFiles == 0)
continue;
@@ -1222,10 +2281,11 @@ HRESULT Update(
for (i = 0; i < numFiles;)
{
UInt64 totalSize = 0;
- int numSubFiles;
- UString prevExtension;
- for (numSubFiles = 0; i + numSubFiles < numFiles &&
- numSubFiles < numSolidFiles; numSubFiles++)
+ unsigned numSubFiles;
+
+ const wchar_t *prevExtension = NULL;
+
+ for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++)
{
const CUpdateItem &ui = updateItems[indices[i + numSubFiles]];
totalSize += ui.Size;
@@ -1233,17 +2293,21 @@ HRESULT Update(
break;
if (options.SolidExtension)
{
- UString ext = ui.GetExtension();
+ int slashPos = ui.Name.ReverseFind_PathSepar();
+ int dotPos = ui.Name.ReverseFind_Dot();
+ const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : dotPos + 1);
if (numSubFiles == 0)
prevExtension = ext;
- else
- if (!ext.IsEqualToNoCase(prevExtension))
- break;
+ else if (!StringsAreEqualNoCase(ext, prevExtension))
+ break;
}
}
+
if (numSubFiles < 1)
numSubFiles = 1;
+ RINOK(lps->SetCur());
+
CFolderInStream *inStreamSpec = new CFolderInStream;
CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);
inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);
@@ -1252,10 +2316,15 @@ HRESULT Update(
UInt64 curFolderUnpackSize;
RINOK(encoder.Encode(
EXTERNAL_CODECS_LOC_VARS
- solidInStream, NULL, &inSizeForReduce,
+ solidInStream,
+ // NULL,
+ &inSizeForReduce,
newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curFolderUnpackSize,
archive.SeqStream, newDatabase.PackSizes, progress));
+ if (!inStreamSpec->WasFinished())
+ return E_FAIL;
+
for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)
lps->OutSize += newDatabase.PackSizes[startPackIndex];
@@ -1263,9 +2332,11 @@ HRESULT Update(
// for ()
// newDatabase.PackCRCsDefined.Add(false);
// newDatabase.PackCRCs.Add(0);
-
+
CNum numUnpackStreams = 0;
- for (int subIndex = 0; subIndex < numSubFiles; subIndex++)
+ UInt64 skippedSize = 0;
+
+ for (unsigned subIndex = 0; subIndex < numSubFiles; subIndex++)
{
const CUpdateItem &ui = updateItems[indices[i + subIndex]];
CFileItem file;
@@ -1290,12 +2361,15 @@ HRESULT Update(
*/
if (!inStreamSpec->Processed[subIndex])
{
+ skippedSize += ui.Size;
continue;
- // file.Name += L".locked";
+ // file.Name.AddAscii(".locked");
}
file.Crc = inStreamSpec->CRCs[subIndex];
file.Size = inStreamSpec->Sizes[subIndex];
+
+ // if (file.Size >= 0) // test purposes
if (file.Size != 0)
{
file.CrcDefined = true;
@@ -1307,6 +2381,7 @@ HRESULT Update(
file.CrcDefined = false;
file.HasStream = false;
}
+
/*
file.Parent = ui.ParentFolderIndex;
if (ui.TreeFolderIndex >= 0)
@@ -1316,20 +2391,23 @@ HRESULT Update(
*/
newDatabase.AddFile(file, file2, name);
}
+
// numUnpackStreams = 0 is very bad case for locked files
// v3.13 doesn't understand it.
newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams);
i += numSubFiles;
+
+ if (skippedSize != 0 && complexity >= skippedSize)
+ {
+ complexity -= skippedSize;
+ RINOK(updateCallback->SetTotal(complexity));
+ }
}
}
- if (folderRefIndex != folderRefs.Size())
- return E_FAIL;
-
RINOK(lps->SetCur());
/*
- folderRefs.ClearAndFree();
fileIndexToUpdateIndexMap.ClearAndFree();
groups.ClearAndFree();
*/
@@ -1350,13 +2428,18 @@ HRESULT Update(
{
const CByteBuffer &buf = secureBlocks.Bufs[secureBlocks.Sorted[i]];
size_t size = buf.GetCapacity();
- memcpy(newDatabase.SecureBuf + pos, buf, size);
+ if (size != 0)
+ memcpy(newDatabase.SecureBuf + pos, buf, size);
newDatabase.SecureSizes.Add((UInt32)size);
pos += size;
}
}
*/
newDatabase.ReserveDown();
+
+ if (opCallback)
+ RINOK(opCallback->ReportOperation(NEventIndexType::kNoIndex, (UInt32)(Int32)-1, NUpdateNotifyOp::kHeader));
+
return S_OK;
}
diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h
index d00276e0..3986af43 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.h
+++ b/CPP/7zip/Archive/7z/7zUpdate.h
@@ -65,6 +65,7 @@ struct CUpdateItem
// int SecureIndex; // 0 means (no_security)
bool HasStream() const { return !IsDir && !IsAnti && Size != 0; }
+ // bool HasStream() const { return !IsDir && !IsAnti /* && Size != 0 */; } // for test purposes
CUpdateItem():
// ParentSortIndex(-1),
@@ -77,18 +78,19 @@ struct CUpdateItem
MTimeDefined(false)
// SecureIndex(0)
{}
- void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); };
+ void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }
- int GetExtensionPos() const;
- UString GetExtension() const;
+ // unsigned GetExtensionPos() const;
+ // UString GetExtension() const;
};
struct CUpdateOptions
{
const CCompressionMethodMode *Method;
const CCompressionMethodMode *HeaderMethod;
- bool UseFilters;
- bool MaxFilter;
+ bool UseFilters; // use additional filters for some files
+ bool MaxFilter; // use BCJ2 filter instead of BCJ
+ int AnalysisLevel;
CHeaderOptions HeaderOptions;
@@ -96,7 +98,20 @@ struct CUpdateOptions
UInt64 NumSolidBytes;
bool SolidExtension;
bool RemoveSfxBlock;
- bool VolumeMode;
+ bool MultiThreadMixer;
+
+ CUpdateOptions():
+ Method(NULL),
+ HeaderMethod(NULL),
+ UseFilters(false),
+ MaxFilter(false),
+ AnalysisLevel(-1),
+ NumSolidFiles((UInt64)(Int64)(-1)),
+ NumSolidBytes((UInt64)(Int64)(-1)),
+ SolidExtension(false),
+ RemoveSfxBlock(false),
+ MultiThreadMixer(true)
+ {}
};
HRESULT Update(
diff --git a/CPP/7zip/Archive/ApmHandler.cpp b/CPP/7zip/Archive/ApmHandler.cpp
index 96656733..d5a111e9 100644
--- a/CPP/7zip/Archive/ApmHandler.cpp
+++ b/CPP/7zip/Archive/ApmHandler.cpp
@@ -376,15 +376,13 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { kSig0, kSig1 };
-static CArcInfo g_ArcInfo =
- { "APM", "apm", 0, 0xD4,
- 2, { kSig0, kSig1 },
+REGISTER_ARC_I(
+ "APM", "apm", 0, 0xD4,
+ k_Signature,
0,
0,
- CreateArc, NULL, IsArc_Apm };
-
-REGISTER_ARC(Apm)
+ IsArc_Apm)
}}
diff --git a/CPP/7zip/Archive/ArHandler.cpp b/CPP/7zip/Archive/ArHandler.cpp
index b7dcda85..1eec728f 100644
--- a/CPP/7zip/Archive/ArHandler.cpp
+++ b/CPP/7zip/Archive/ArHandler.cpp
@@ -77,7 +77,7 @@ enum EType
kType_Lib
};
-static const char *k_TypeExtionsions[] =
+static const char * const k_TypeExtionsions[] =
{
"ar"
, "a"
@@ -121,7 +121,7 @@ struct CItem
int SameNameIndex;
CItem(): TextFileIndex(-1), SameNameIndex(-1) {}
- UInt64 GetDataPos() const { return HeaderPos + HeaderSize; };
+ UInt64 GetDataPos() const { return HeaderPos + HeaderSize; }
};
class CInArchive
@@ -257,10 +257,9 @@ HRESULT CInArchive::GetNextItem(CItem &item, bool &filled)
{
SubType = kSubType_BSD;
size_t processedSize = longNameLen;
- char *s = item.Name.GetBuffer(longNameLen);
+ char *s = item.Name.GetBuf(longNameLen);
HRESULT res = ReadStream(m_Stream, s, &processedSize);
- s[longNameLen] = 0;
- item.Name.ReleaseBuffer();
+ item.Name.ReleaseBuf_CalcLen(longNameLen);
RINOK(res);
if (processedSize != longNameLen)
return S_OK;
@@ -683,11 +682,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
case kpidPhySize: prop = _phySize; break;
case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
- case kpidExtension: prop = k_TypeExtionsions[_type]; break;
+ case kpidExtension: prop = k_TypeExtionsions[(unsigned)_type]; break;
case kpidShortComment:
case kpidSubType:
{
- AString s = k_TypeExtionsions[_type];
+ AString s = k_TypeExtionsions[(unsigned)_type];
if (_subType == kSubType_BSD)
s += ":BSD";
prop = s;
@@ -724,7 +723,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidSize:
case kpidPackSize:
if (item.TextFileIndex >= 0)
- prop = (UInt64)_libFiles[item.TextFileIndex].Len();
+ prop = (UInt64)_libFiles[(unsigned)item.TextFileIndex].Len();
else
prop = item.Size;
break;
@@ -766,7 +765,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
const CItem &item = _items[allFilesMode ? i : indices[i]];
totalSize +=
(item.TextFileIndex >= 0) ?
- (UInt64)_libFiles[item.TextFileIndex].Len() : item.Size;
+ (UInt64)_libFiles[(unsigned)item.TextFileIndex].Len() : item.Size;
}
extractCallback->SetTotal(totalSize);
@@ -795,7 +794,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
const CItem &item = _items[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
currentTotalSize += (item.TextFileIndex >= 0) ?
- (UInt64)_libFiles[item.TextFileIndex].Len() : item.Size;
+ (UInt64)_libFiles[(unsigned)item.TextFileIndex].Len() : item.Size;
if (!testMode && !realOutStream)
continue;
@@ -808,7 +807,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
bool isOk = true;
if (item.TextFileIndex >= 0)
{
- const AString &f = _libFiles[item.TextFileIndex];
+ const AString &f = _libFiles[(unsigned)item.TextFileIndex];
if (realOutStream)
RINOK(WriteStream(realOutStream, f, f.Len()));
}
@@ -834,8 +833,8 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
const CItem &item = _items[index];
if (item.TextFileIndex >= 0)
{
- const AString &f = _libFiles[item.TextFileIndex];
- Create_BufInStream_WithNewBuf((const void *)(const char *)f, f.Len(), stream);
+ const AString &f = _libFiles[(unsigned)item.TextFileIndex];
+ Create_BufInStream_WithNewBuffer((const void *)(const char *)f, f.Len(), stream);
return S_OK;
}
else
@@ -843,15 +842,11 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Ar", "ar a deb lib", 0, 0xEC,
- kSignatureLen, SIGNATURE,
+REGISTER_ARC_I(
+ "Ar", "ar a deb lib", 0, 0xEC,
+ kSignature,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Ar)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/Archive.def b/CPP/7zip/Archive/Archive.def
index 55b530b2..145516d7 100644
--- a/CPP/7zip/Archive/Archive.def
+++ b/CPP/7zip/Archive/Archive.def
@@ -1,6 +1,12 @@
EXPORTS
CreateObject PRIVATE
+
GetHandlerProperty PRIVATE
GetNumberOfFormats PRIVATE
GetHandlerProperty2 PRIVATE
- CreateObject PRIVATE
+ GetIsArc PRIVATE
+
+ SetCodecs PRIVATE
+
+ SetLargePageMode PRIVATE
+ SetCaseSensitive PRIVATE
diff --git a/CPP/7zip/Archive/Archive2.def b/CPP/7zip/Archive/Archive2.def
index 66feb41d..c7582742 100644
--- a/CPP/7zip/Archive/Archive2.def
+++ b/CPP/7zip/Archive/Archive2.def
@@ -1,11 +1,19 @@
EXPORTS
CreateObject PRIVATE
+
GetHandlerProperty PRIVATE
GetNumberOfFormats PRIVATE
GetHandlerProperty2 PRIVATE
+ GetIsArc PRIVATE
+
GetNumberOfMethods PRIVATE
GetMethodProperty PRIVATE
+ CreateDecoder PRIVATE
+ CreateEncoder PRIVATE
+
GetHashers PRIVATE
+
+ SetCodecs PRIVATE
+
SetLargePageMode PRIVATE
SetCaseSensitive PRIVATE
- GetIsArc PRIVATE \ No newline at end of file
diff --git a/CPP/7zip/Archive/ArchiveExports.cpp b/CPP/7zip/Archive/ArchiveExports.cpp
index 0a520413..28e9946d 100644
--- a/CPP/7zip/Archive/ArchiveExports.cpp
+++ b/CPP/7zip/Archive/ArchiveExports.cpp
@@ -22,17 +22,19 @@ void RegisterArc(const CArcInfo *arcInfo) throw()
const char *p = arcInfo->Name;
if (p[0] == '7' && p[1] == 'z' && p[2] == 0)
g_DefaultArcIndex = g_NumArcs;
- g_Arcs[g_NumArcs] = arcInfo;
- g_NumArcs++;
+ g_Arcs[g_NumArcs++] = arcInfo;
}
}
DEFINE_GUID(CLSID_CArchiveHandler,
-0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
+ k_7zip_GUID_Data1,
+ k_7zip_GUID_Data2,
+ k_7zip_GUID_Data3_Common,
+ 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
#define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5])
-static inline HRESULT SetPropString(const char *s, unsigned size, PROPVARIANT *value)
+static inline HRESULT SetPropStrFromBin(const char *s, unsigned size, PROPVARIANT *value)
{
if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)
value->vt = VT_BSTR;
@@ -41,18 +43,18 @@ static inline HRESULT SetPropString(const char *s, unsigned size, PROPVARIANT *v
static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
{
- return SetPropString((const char *)&guid, sizeof(GUID), value);
+ return SetPropStrFromBin((const char *)&guid, sizeof(guid), value);
}
-int FindFormatCalssId(const GUID *clsID)
+int FindFormatCalssId(const GUID *clsid)
{
- GUID cls = *clsID;
+ GUID cls = *clsid;
CLS_ARC_ID_ITEM(cls) = 0;
if (cls != CLSID_CArchiveHandler)
return -1;
- Byte id = CLS_ARC_ID_ITEM(*clsID);
+ Byte id = CLS_ARC_ID_ITEM(*clsid);
for (unsigned i = 0; i < g_NumArcs; i++)
- if (g_Arcs[i]->ClassId == id)
+ if (g_Arcs[i]->Id == id)
return (int)i;
return -1;
}
@@ -101,7 +103,7 @@ STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value
case NArchive::NHandlerPropID::kClassID:
{
GUID clsId = CLSID_CArchiveHandler;
- CLS_ARC_ID_ITEM(clsId) = arc.ClassId;
+ CLS_ARC_ID_ITEM(clsId) = arc.Id;
return SetPropGUID(clsId, value);
}
case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break;
@@ -115,12 +117,12 @@ STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value
// case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break;
case NArchive::NHandlerPropID::kSignature:
- if (!arc.IsMultiSignature())
- return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);
+ if (arc.SignatureSize != 0 && !arc.IsMultiSignature())
+ return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);
break;
case NArchive::NHandlerPropID::kMultiSignature:
- if (arc.IsMultiSignature())
- return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);
+ if (arc.SignatureSize != 0 && arc.IsMultiSignature())
+ return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);
break;
}
prop.Detach(value);
diff --git a/CPP/7zip/Archive/ArjHandler.cpp b/CPP/7zip/Archive/ArjHandler.cpp
index 737b8fc9..90819753 100644
--- a/CPP/7zip/Archive/ArjHandler.cpp
+++ b/CPP/7zip/Archive/ArjHandler.cpp
@@ -17,13 +17,180 @@
#include "../Common/StreamObjects.h"
#include "../Common/StreamUtils.h"
-#include "../Compress/ArjDecoder1.h"
-#include "../Compress/ArjDecoder2.h"
#include "../Compress/CopyCoder.h"
+#include "../Compress/LzhDecoder.h"
#include "Common/ItemNameUtils.h"
#include "Common/OutStreamWithCRC.h"
+namespace NCompress {
+namespace NArj {
+namespace NDecoder {
+
+static const unsigned kMatchMinLen = 3;
+
+static const UInt32 kWindowSize = 1 << 15; // must be >= (1 << 14)
+
+class CCoder:
+ public ICompressCoder,
+ public CMyUnknownImp
+{
+ CLzOutWindow _outWindow;
+ NBitm::CDecoder<CInBuffer> _inBitStream;
+
+ class CCoderReleaser
+ {
+ CCoder *_coder;
+ public:
+ CCoderReleaser(CCoder *coder): _coder(coder) {}
+ void Disable() { _coder = NULL; }
+ ~CCoderReleaser() { if (_coder) _coder->_outWindow.Flush(); }
+ };
+ friend class CCoderReleaser;
+
+ HRESULT CodeReal(UInt64 outSize, ICompressProgressInfo *progress);
+public:
+ MY_UNKNOWN_IMP
+
+ bool FinishMode;
+ CCoder(): FinishMode(false) {}
+
+ STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+ UInt64 GetInputProcessedSize() const { return _inBitStream.GetProcessedSize(); }
+};
+
+HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
+{
+ const UInt32 kStep = 1 << 20;
+ UInt64 next = 0;
+ if (rem > kStep && progress)
+ next = rem - kStep;
+
+ while (rem != 0)
+ {
+ if (rem <= next)
+ {
+ if (_inBitStream.ExtraBitsWereRead())
+ return S_FALSE;
+
+ UInt64 packSize = _inBitStream.GetProcessedSize();
+ UInt64 pos = _outWindow.GetProcessedSize();
+ RINOK(progress->SetRatioInfo(&packSize, &pos));
+ next = 0;
+ if (rem > kStep)
+ next = rem - kStep;
+ }
+
+ UInt32 len;
+
+ {
+ const unsigned kNumBits = 7 + 7;
+ UInt32 val = _inBitStream.GetValue(kNumBits);
+
+ if ((val & (1 << (kNumBits - 1))) == 0)
+ {
+ _outWindow.PutByte((Byte)(val >> 5));
+ _inBitStream.MovePos(1 + 8);
+ rem--;
+ continue;
+ }
+
+ UInt32 mask = 1 << (kNumBits - 2);
+ unsigned w;
+
+ for (w = 1; w < 7; w++, mask >>= 1)
+ if ((val & mask) == 0)
+ break;
+
+ unsigned readBits = (w != 7 ? 1 : 0);
+ readBits += w + w;
+ len = (1 << w) - 1 + kMatchMinLen - 1 +
+ (((val >> (kNumBits - readBits)) & ((1 << w) - 1)));
+ _inBitStream.MovePos(readBits);
+ }
+
+ {
+ const unsigned kNumBits = 4 + 13;
+ UInt32 val = _inBitStream.GetValue(kNumBits);
+
+ unsigned readBits = 1;
+ unsigned w;
+
+ if ((val & ((UInt32)1 << 16)) == 0) w = 9;
+ else if ((val & ((UInt32)1 << 15)) == 0) w = 10;
+ else if ((val & ((UInt32)1 << 14)) == 0) w = 11;
+ else if ((val & ((UInt32)1 << 13)) == 0) w = 12;
+ else { w = 13; readBits = 0; }
+
+ readBits += w + w - 9;
+
+ UInt32 dist = ((UInt32)1 << w) - (1 << 9) +
+ (((val >> (kNumBits - readBits)) & ((1 << w) - 1)));
+ _inBitStream.MovePos(readBits);
+
+ if (len > rem)
+ len = (UInt32)rem;
+
+ if (!_outWindow.CopyBlock(dist, len))
+ return S_FALSE;
+ rem -= len;
+ }
+ }
+
+ if (FinishMode)
+ {
+ if (_inBitStream.ReadAlignBits() != 0)
+ return S_FALSE;
+ }
+
+ if (_inBitStream.ExtraBitsWereRead())
+ return S_FALSE;
+
+ return S_OK;
+}
+
+
+
+STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
+{
+ try
+ {
+ if (!outSize)
+ return E_INVALIDARG;
+
+ if (!_outWindow.Create(kWindowSize))
+ return E_OUTOFMEMORY;
+ if (!_inBitStream.Create(1 << 17))
+ return E_OUTOFMEMORY;
+
+ _outWindow.SetStream(outStream);
+ _outWindow.Init(false);
+ _inBitStream.SetStream(inStream);
+ _inBitStream.Init();
+
+ CCoderReleaser coderReleaser(this);
+ HRESULT res;
+ {
+ res = CodeReal(*outSize, progress);
+ if (res != S_OK)
+ return res;
+ }
+
+ coderReleaser.Disable();
+ return _outWindow.Flush();
+ }
+ catch(const CInBufferException &e) { return e.ErrorCode; }
+ catch(const CLzOutWindowException &e) { return e.ErrorCode; }
+ catch(...) { return S_FALSE; }
+}
+
+}}}
+
+
+
+
using namespace NWindows;
#define Get16(p) GetUi16(p)
@@ -95,7 +262,7 @@ namespace NHostOS
};
}
-static const char *kHostOS[] =
+static const char * const kHostOS[] =
{
"MSDOS"
, "PRIMOS"
@@ -164,10 +331,10 @@ API_FUNC_static_IsArc IsArc_Arj(const Byte *p, size_t size)
static HRESULT ReadString(const Byte *p, unsigned &size, AString &res)
{
- for (unsigned i = 0; i < size;)
+ unsigned num = size;
+ for (unsigned i = 0; i < num;)
{
- char c = (char)p[i++];
- if (c == 0)
+ if (p[i++] == 0)
{
size = i;
res = (const char *)p;
@@ -656,15 +823,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
const CItem &item = _items[allFilesMode ? i : indices[i]];
totalUnpacked += item.Size;
- totalPacked += item.PackSize;
+ // totalPacked += item.PackSize;
}
extractCallback->SetTotal(totalUnpacked);
totalUnpacked = totalPacked = 0;
UInt64 curUnpacked, curPacked;
- CMyComPtr<ICompressCoder> arj1Decoder;
- CMyComPtr<ICompressCoder> arj2Decoder;
+ NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = NULL;
+ CMyComPtr<ICompressCoder> lzhDecoder;
+
+ NCompress::NArj::NDecoder::CCoder *arjDecoderSpec = NULL;
+ CMyComPtr<ICompressCoder> arjDecoder;
+
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
@@ -741,22 +912,37 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
case NCompressionMethod::kCompressed1b:
case NCompressionMethod::kCompressed1c:
{
- if (!arj1Decoder)
- arj1Decoder = new NCompress::NArj::NDecoder1::CCoder;
- result = arj1Decoder->Code(inStream, outStream, NULL, &curUnpacked, progress);
+ if (!lzhDecoder)
+ {
+ lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder;
+ lzhDecoder = lzhDecoderSpec;
+ }
+ lzhDecoderSpec->FinishMode = true;
+ const UInt32 kHistorySize = 26624;
+ lzhDecoderSpec->SetDictSize(kHistorySize);
+ result = lzhDecoder->Code(inStream, outStream, NULL, &curUnpacked, progress);
+ if (result == S_OK && lzhDecoderSpec->GetInputProcessedSize() != item.PackSize)
+ result = S_FALSE;
break;
}
case NCompressionMethod::kCompressed2:
{
- if (!arj2Decoder)
- arj2Decoder = new NCompress::NArj::NDecoder2::CCoder;
- result = arj2Decoder->Code(inStream, outStream, NULL, &curUnpacked, progress);
+ if (!arjDecoder)
+ {
+ arjDecoderSpec = new NCompress::NArj::NDecoder::CCoder;
+ arjDecoder = arjDecoderSpec;
+ }
+ arjDecoderSpec->FinishMode = true;
+ result = arjDecoder->Code(inStream, outStream, NULL, &curUnpacked, progress);
+ if (result == S_OK && arjDecoderSpec->GetInputProcessedSize() != item.PackSize)
+ result = S_FALSE;
break;
}
default:
opRes = NExtract::NOperationResult::kUnsupportedMethod;
}
}
+
if (opRes == NExtract::NOperationResult::kOK)
{
if (result == S_FALSE)
@@ -769,23 +955,23 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
NExtract::NOperationResult::kCRCError;
}
}
+
outStream.Release();
RINOK(extractCallback->SetOperationResult(opRes));
}
}
+
return S_OK;
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { kSig0, kSig1 };
-static CArcInfo g_ArcInfo =
- { "Arj", "arj", 0, 4,
- 2, { kSig0, kSig1 },
+REGISTER_ARC_I(
+ "Arj", "arj", 0, 4,
+ k_Signature,
0,
0,
- CreateArc, NULL, IsArc_Arj };
-
-REGISTER_ARC(Arj)
+ IsArc_Arj)
}}
diff --git a/CPP/7zip/Archive/Bz2Handler.cpp b/CPP/7zip/Archive/Bz2Handler.cpp
index a49e8293..d1d5f727 100644
--- a/CPP/7zip/Archive/Bz2Handler.cpp
+++ b/CPP/7zip/Archive/Bz2Handler.cpp
@@ -56,7 +56,7 @@ public:
INTERFACE_IInArchive(;)
INTERFACE_IOutArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
CHandler() { }
};
@@ -367,6 +367,8 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *updateCallback)
{
+ COM_TRY_BEGIN
+
if (numItems != 1)
return E_INVALIDARG;
@@ -381,13 +383,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
- if (prop.vt == VT_BOOL)
- {
- if (prop.boolVal != VARIANT_FALSE)
+ if (prop.vt != VT_EMPTY)
+ if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)
return E_INVALIDARG;
- }
- else if (prop.vt != VT_EMPTY)
- return E_INVALIDARG;
}
}
@@ -403,28 +401,43 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
}
return UpdateArchive(size, outStream, _props, updateCallback);
}
+
if (indexInArchive != 0)
return E_INVALIDARG;
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(updateCallback, true);
+
+ CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
+ updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
+ if (opCallback)
+ {
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kInArcIndex, 0,
+ NUpdateNotifyOp::kReplicate))
+ }
+
if (_stream)
RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
- return NCompress::CopyStream(_stream, outStream, NULL);
+
+ return NCompress::CopyStream(_stream, outStream, progress);
+
+ COM_TRY_END
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
return _props.SetProperties(names, values, numProps);
}
-IMP_CreateArcIn
-IMP_CreateArcOut
+static const Byte k_Signature[] = { 'B', 'Z', 'h' };
-static CArcInfo g_ArcInfo =
- { "bzip2", "bz2 bzip2 tbz2 tbz", "* * .tar .tar", 2,
- 3, { 'B', 'Z', 'h' },
+REGISTER_ARC_IO(
+ "bzip2", "bz2 bzip2 tbz2 tbz", "* * .tar .tar", 2,
+ k_Signature,
0,
NArcInfoFlags::kKeepName,
- REF_CreateArc_Pair, IsArc_BZip2 };
-
-REGISTER_ARC(BZip2)
+ IsArc_BZip2)
}}
diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
index cebec610..625276f3 100644
--- a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
+++ b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
@@ -75,11 +75,14 @@ HRESULT CCabBlockInStream::PreRead(ISequentialInStream *stream, UInt32 &packSize
STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- UInt32 rem = _size - _pos;
- if (size > rem)
- size = rem;
- memcpy(data, _buf + _pos, size);
- _pos += size;
+ if (size != 0)
+ {
+ UInt32 rem = _size - _pos;
+ if (size > rem)
+ size = rem;
+ memcpy(data, _buf + _pos, size);
+ _pos += size;
+ }
if (processedSize)
*processedSize = size;
return S_OK;
diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp
index 22bc93a0..4235ec34 100644
--- a/CPP/7zip/Archive/Cab/CabHandler.cpp
+++ b/CPP/7zip/Archive/Cab/CabHandler.cpp
@@ -71,7 +71,7 @@ static const Byte kArcProps[] =
IMP_IInArchive_Props
IMP_IInArchive_ArcProps
-static const char *kMethods[] =
+static const char * const kMethods[] =
{
"None"
, "MSZip"
@@ -124,17 +124,19 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
}
}
}
+
AString s;
+
for (unsigned i = 0; i < kNumMethodsMax; i++)
{
if ((mask & (1 << i)) == 0)
continue;
- if (!s.IsEmpty())
- s += ' ';
+ s.Add_Space_if_NotEmpty();
char temp[kMethodNameBufSize];
SetMethodName(temp, i, params[i == NHeader::NMethod::kQuantum ? 0 : 1]);
s += temp;
}
+
prop = s;
break;
}
@@ -466,8 +468,8 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
return result;
if (!_errorMessage.IsEmpty())
- _errorMessage += L"\n";
- _errorMessage += L"Can't open volume: ";
+ _errorMessage.Add_LF();
+ _errorMessage.AddAscii("Can't open volume: ");
_errorMessage += fullName;
if (prevChecked)
@@ -528,7 +530,7 @@ private:
Byte *TempBuf;
UInt32 TempBufSize;
- int NumIdenticalFiles;
+ unsigned NumIdenticalFiles;
bool TempBufMode;
UInt32 m_BufStartFolderOffset;
@@ -619,8 +621,9 @@ HRESULT CFolderOutStream::OpenFile()
{
const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];
const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
- int numExtractItems = 0;
+ unsigned numExtractItems = 0;
unsigned curIndex;
+
for (curIndex = m_CurrentIndex; curIndex < m_ExtractStatuses->Size(); curIndex++)
{
const CMvItem &mvItem2 = m_Database->Items[m_StartIndex + curIndex];
@@ -632,10 +635,12 @@ HRESULT CFolderOutStream::OpenFile()
if (!m_TestMode && (*m_ExtractStatuses)[curIndex])
numExtractItems++;
}
+
NumIdenticalFiles = (curIndex - m_CurrentIndex);
if (NumIdenticalFiles == 0)
NumIdenticalFiles = 1;
TempBufMode = false;
+
if (numExtractItems > 1)
{
if (!TempBuf || item.Size > TempBufSize)
@@ -699,7 +704,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
{
COM_TRY_BEGIN
UInt32 realProcessed = 0;
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = 0;
while (size != 0)
{
@@ -707,7 +712,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
{
UInt32 numBytesToWrite = MyMin(m_RemainFileSize, size);
HRESULT res = S_OK;
- if (numBytesToWrite > 0)
+ if (numBytesToWrite != 0)
{
if (!isOK)
m_IsOk = false;
@@ -721,7 +726,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
memcpy(TempBuf + (m_PosInFolder - m_BufStartFolderOffset), data, numBytesToWrite);
}
realProcessed += numBytesToWrite;
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = realProcessed;
data = (const void *)((const Byte *)data + numBytesToWrite);
size -= numBytesToWrite;
@@ -773,7 +778,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
{
UInt32 numBytesToWrite = MyMin(fileOffset - (UInt32)m_PosInFolder, size);
realProcessed += numBytesToWrite;
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = realProcessed;
data = (const void *)((const Byte *)data + numBytesToWrite);
size -= numBytesToWrite;
@@ -799,24 +804,24 @@ STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *proc
HRESULT CFolderOutStream::FlushCorrupted()
{
- const UInt32 kBufferSize = (1 << 10);
- Byte buffer[kBufferSize];
- for (int i = 0; i < kBufferSize; i++)
- buffer[i] = 0;
+ const unsigned kBufSize = (1 << 10);
+ Byte buf[kBufSize];
+ for (unsigned i = 0; i < kBufSize; i++)
+ buf[i] = 0;
for (;;)
{
UInt64 remain = GetRemain();
if (remain == 0)
return S_OK;
- UInt32 size = (UInt32)MyMin(remain, (UInt64)kBufferSize);
+ UInt32 size = (remain < kBufSize ? (UInt32)remain : (UInt32)kBufSize);
UInt32 processedSizeLocal = 0;
- RINOK(Write2(buffer, size, &processedSizeLocal, false));
+ RINOK(Write2(buf, size, &processedSizeLocal, false));
}
}
HRESULT CFolderOutStream::Unsupported()
{
- while(m_CurrentIndex < m_ExtractStatuses->Size())
+ while (m_CurrentIndex < m_ExtractStatuses->Size())
{
HRESULT result = OpenFile();
if (result != S_FALSE && result != S_OK)
@@ -844,9 +849,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt32 i;
int lastFolder = -2;
UInt64 lastFolderSize = 0;
- for(i = 0; i < numItems; i++)
+
+ for (i = 0; i < numItems; i++)
{
- int index = allFilesMode ? i : indices[i];
+ unsigned index = allFilesMode ? i : indices[i];
const CMvItem &mvItem = m_Database.Items[index];
const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
if (item.IsDir())
@@ -857,6 +863,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
lastFolder = folderIndex;
lastFolderSize = item.GetEndOffset();
}
+
totalUnPacked += lastFolderSize;
extractCallback->SetTotal(totalUnPacked);
@@ -887,9 +894,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
return E_OUTOFMEMORY;
CRecordVector<bool> extractStatuses;
- for(i = 0; i < numItems;)
+
+ for (i = 0; i < numItems;)
{
- int index = allFilesMode ? i : indices[i];
+ unsigned index = allFilesMode ? i : indices[i];
const CMvItem &mvItem = m_Database.Items[index];
const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex];
@@ -909,7 +917,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue;
}
+
int folderIndex = m_Database.GetFolderIndex(&mvItem);
+
if (folderIndex < 0)
{
// If we need previous archive
@@ -923,17 +933,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError));
continue;
}
- int startIndex2 = m_Database.FolderStartFileIndex[folderIndex];
- int startIndex = startIndex2;
+
+ unsigned startIndex2 = m_Database.FolderStartFileIndex[folderIndex];
+ unsigned startIndex = startIndex2;
extractStatuses.Clear();
for (; startIndex < index; startIndex++)
extractStatuses.Add(false);
extractStatuses.Add(true);
startIndex++;
UInt64 curUnpack = item.GetEndOffset();
+
for (; i < numItems; i++)
{
- int indexNext = allFilesMode ? i : indices[i];
+ unsigned indexNext = allFilesMode ? i : indices[i];
const CMvItem &mvItem = m_Database.Items[indexNext];
const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
if (item.IsDir())
@@ -963,6 +975,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
cabBlockInStreamSpec->MsZip = false;
HRESULT res = S_OK;
+
switch (folder.GetMethod())
{
case NHeader::NMethod::kNone:
@@ -1009,7 +1022,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
int locFolderIndex = item.GetFolderIndex(db.Folders.Size());
bool keepHistory = false;
bool keepInputBuffer = false;
- for (UInt32 f = 0; cabFolderOutStream->GetRemain() != 0;)
+
+ for (UInt32 bl = 0; cabFolderOutStream->GetRemain() != 0;)
{
if (volIndex >= m_Database.Volumes.Size())
{
@@ -1019,19 +1033,32 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
const CDatabaseEx &db = m_Database.Volumes[volIndex];
const CFolder &folder = db.Folders[locFolderIndex];
- if (f == 0)
+
+ if (bl == 0)
{
cabBlockInStreamSpec->ReservedSize = db.ArcInfo.GetDataBlockReserveSize();
RINOK(db.Stream->Seek(db.StartPosition + folder.DataStart, STREAM_SEEK_SET, NULL));
}
- if (f == folder.NumDataBlocks)
+
+ if (bl == folder.NumDataBlocks)
{
- volIndex++;
- locFolderIndex = 0;
- f = 0;
- continue;
+ /*
+ CFolder::NumDataBlocks (CFFOLDER::cCFData in CAB specification) is 16-bit.
+ But there are some big CAB archives from MS that contain more
+ than (0xFFFF) CFDATA blocks in folder.
+ Old cab extracting software can show error (or ask next volume)
+ but cab extracting library in new Windows ignores this error.
+ 15.00 : We also try to ignore such error, if archive is not multi-volume.
+ */
+ if (m_Database.Volumes.Size() > 1)
+ {
+ volIndex++;
+ locFolderIndex = 0;
+ bl = 0;
+ continue;
+ }
}
- f++;
+ bl++;
if (!keepInputBuffer)
cabBlockInStreamSpec->InitForNewBlock();
@@ -1059,7 +1086,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
unpackRemain = kBlockSizeMax;
if (unpackRemain > unpackSize)
unpackRemain = unpackSize;
-
+
switch (folder.GetMethod())
{
case NHeader::NMethod::kNone:
@@ -1092,14 +1119,17 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
res = quantumDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
break;
}
+
if (res != S_OK)
{
if (res != S_FALSE)
RINOK(res);
break;
}
+
keepHistory = true;
}
+
if (res == S_OK)
{
RINOK(cabFolderOutStream->WriteEmptyFiles());
@@ -1111,6 +1141,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
totalUnPacked += curUnpack;
}
+
return S_OK;
COM_TRY_END
}
diff --git a/CPP/7zip/Archive/Cab/CabHeader.cpp b/CPP/7zip/Archive/Cab/CabHeader.cpp
index 0cba1b0b..370a2f1e 100644
--- a/CPP/7zip/Archive/Cab/CabHeader.cpp
+++ b/CPP/7zip/Archive/Cab/CabHeader.cpp
@@ -8,8 +8,8 @@ namespace NArchive {
namespace NCab {
namespace NHeader {
-Byte kMarker[kMarkerSize] = {'M', 'S', 'C', 'F', 0, 0, 0, 0 };
+const Byte kMarker[kMarkerSize] = {'M', 'S', 'C', 'F', 0, 0, 0, 0 };
-// struct CSignatureInitializer { CSignatureInitializer() { kMarker[0]--; }; } g_SignatureInitializer;
+// struct CSignatureInitializer { CSignatureInitializer() { kMarker[0]--; } } g_SignatureInitializer;
}}}
diff --git a/CPP/7zip/Archive/Cab/CabHeader.h b/CPP/7zip/Archive/Cab/CabHeader.h
index 9ec0760a..2f2bd109 100644
--- a/CPP/7zip/Archive/Cab/CabHeader.h
+++ b/CPP/7zip/Archive/Cab/CabHeader.h
@@ -1,4 +1,4 @@
-// Archive/Cab/Header.h
+// Archive/CabHeader.h
#ifndef __ARCHIVE_CAB_HEADER_H
#define __ARCHIVE_CAB_HEADER_H
@@ -10,7 +10,7 @@ namespace NCab {
namespace NHeader {
const unsigned kMarkerSize = 8;
-extern Byte kMarker[kMarkerSize];
+extern const Byte kMarker[kMarkerSize];
namespace NArcFlags
{
diff --git a/CPP/7zip/Archive/Cab/CabIn.cpp b/CPP/7zip/Archive/Cab/CabIn.cpp
index c499f05f..a72e05f7 100644
--- a/CPP/7zip/Archive/Cab/CabIn.cpp
+++ b/CPP/7zip/Archive/Cab/CabIn.cpp
@@ -40,8 +40,7 @@ void CInArchive::ReadName(AString &s)
throw CUnexpectedEndException();
if (b == 0)
{
- memcpy(s.GetBuffer((unsigned)i), _tempBuf, i);
- s.ReleaseBuffer((unsigned)i);
+ s.SetFrom((const char *)(const Byte *)_tempBuf, (unsigned)i);
return;
}
if (_tempBuf.Size() == i)
diff --git a/CPP/7zip/Archive/Cab/CabIn.h b/CPP/7zip/Archive/Cab/CabIn.h
index 4fdab77b..baeeb7b2 100644
--- a/CPP/7zip/Archive/Cab/CabIn.h
+++ b/CPP/7zip/Archive/Cab/CabIn.h
@@ -17,6 +17,12 @@ struct COtherArc
{
AString FileName;
AString DiskName;
+
+ void Clear()
+ {
+ FileName.Empty();
+ DiskName.Empty();
+ }
};
struct CArchInfo
@@ -43,7 +49,9 @@ struct CArchInfo
CArchInfo()
{
- Clear();
+ PerCabinet_AreaSize = 0;
+ PerFolder_AreaSize = 0;
+ PerDataBlock_AreaSize = 0;
}
void Clear()
@@ -51,6 +59,9 @@ struct CArchInfo
PerCabinet_AreaSize = 0;
PerFolder_AreaSize = 0;
PerDataBlock_AreaSize = 0;
+
+ PrevArc.Clear();
+ NextArc.Clear();
}
};
diff --git a/CPP/7zip/Archive/Cab/CabItem.h b/CPP/7zip/Archive/Cab/CabItem.h
index eda62bda..9b513202 100644
--- a/CPP/7zip/Archive/Cab/CabItem.h
+++ b/CPP/7zip/Archive/Cab/CabItem.h
@@ -51,7 +51,7 @@ struct CItem
FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext;
}
- int GetFolderIndex(int numFolders) const
+ int GetFolderIndex(unsigned numFolders) const
{
if (ContinuedFromPrev())
return 0;
diff --git a/CPP/7zip/Archive/Cab/CabRegister.cpp b/CPP/7zip/Archive/Cab/CabRegister.cpp
index acad4c4a..0b5cc93a 100644
--- a/CPP/7zip/Archive/Cab/CabRegister.cpp
+++ b/CPP/7zip/Archive/Cab/CabRegister.cpp
@@ -9,15 +9,11 @@
namespace NArchive {
namespace NCab {
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Cab", "cab", 0, 8,
- 8, { 'M', 'S', 'C', 'F', 0, 0, 0, 0 },
+REGISTER_ARC_I(
+ "Cab", "cab", 0, 8,
+ NHeader::kMarker,
0,
NArcInfoFlags::kFindSignature,
- CreateArc };
-
-REGISTER_ARC(Cab)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/Chm/ChmHandler.cpp b/CPP/7zip/Archive/Chm/ChmHandler.cpp
index c67ded28..3035ef9e 100644
--- a/CPP/7zip/Archive/Chm/ChmHandler.cpp
+++ b/CPP/7zip/Archive/Chm/ChmHandler.cpp
@@ -123,15 +123,16 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidPath:
{
UString us;
- if (ConvertUTF8ToUnicode(item.Name, us))
+ // if (
+ ConvertUTF8ToUnicode(item.Name, us);
{
if (!m_Database.LowLevel)
{
- if (us.Len() > 1)
- if (us[0] == L'/')
- us.Delete(0);
+ if (us.Len() > 1 && us[0] == L'/')
+ us.Delete(0);
}
- prop = NItemName::GetOSName2(us);
+ NItemName::ConvertToOSName2(us);
+ prop = us;
}
break;
}
@@ -141,7 +142,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
if (!item.IsDir())
if (item.Section == 0)
- prop = L"Copy";
+ prop = "Copy";
else if (item.Section < m_Database.Sections.Size())
prop = m_Database.Sections[(int)item.Section].GetMethodName();
break;
@@ -734,30 +735,30 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
namespace NChm {
-IMP_CreateArcIn_2(CHandler(false))
+static const Byte k_Signature[] = { 'I', 'T', 'S', 'F', 3, 0, 0, 0, 0x60, 0, 0, 0 };
-static CArcInfo g_ArcInfo =
- { "Chm", "chm chi chq chw", 0, 0xE9,
- 12, { 'I', 'T', 'S', 'F', 3, 0, 0, 0, 0x60, 0, 0, 0 },
+REGISTER_ARC_I_CLS(
+ CHandler(false),
+ "Chm", "chm chi chq chw", 0, 0xE9,
+ k_Signature,
0,
0,
- CreateArc };
+ NULL)
-REGISTER_ARC(Chm)
}
namespace NHxs {
-IMP_CreateArcIn_2(CHandler(true))
+static const Byte k_Signature[] = { 'I', 'T', 'O', 'L', 'I', 'T', 'L', 'S', 1, 0, 0, 0, 0x28, 0, 0, 0 };
-static CArcInfo g_ArcInfo =
- { "Hxs", "hxs hxi hxr hxq hxw lit", 0, 0xCE,
- 16, { 'I', 'T', 'O', 'L', 'I', 'T', 'L', 'S', 1, 0, 0, 0, 0x28, 0, 0, 0 },
+REGISTER_ARC_I_CLS(
+ CHandler(true),
+ "Hxs", "hxs hxi hxr hxq hxw lit", 0, 0xCE,
+ k_Signature,
0,
NArcInfoFlags::kFindSignature,
- CreateArc };
+ NULL)
-REGISTER_ARC(Hxs)
}
}}
diff --git a/CPP/7zip/Archive/Chm/ChmIn.cpp b/CPP/7zip/Archive/Chm/ChmIn.cpp
index 9b0bb199..e8da227d 100644
--- a/CPP/7zip/Archive/Chm/ChmIn.cpp
+++ b/CPP/7zip/Archive/Chm/ChmIn.cpp
@@ -107,10 +107,10 @@ UString CMethodInfo::GetName() const
UString s;
if (IsLzx())
{
- s = L"LZX:";
- wchar_t temp[16];
+ s.SetFromAscii("LZX:");
+ char temp[16];
ConvertUInt32ToString(LzxInfo.GetNumDictBits(), temp);
- s += temp;
+ s.AddAscii(temp);
}
else
{
@@ -147,12 +147,12 @@ UString CSectionInfo::GetMethodName() const
UString temp;
if (ConvertUTF8ToUnicode(Name, temp))
s += temp;
- s += L": ";
+ s.AddAscii(": ");
}
FOR_VECTOR (i, Methods)
{
if (i != 0)
- s += L' ';
+ s.Add_Space();
s += Methods[i].GetName();
}
return s;
@@ -584,9 +584,9 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
AString s;
ConvertUnicodeToUTF8(name, s);
Byte b = ReadByte();
- s += ' ';
+ s.Add_Space();
PrintByte(b, s);
- s += ' ';
+ s.Add_Space();
UInt64 len = ReadEncInt();
// then number of items ?
// then length ?
@@ -641,7 +641,10 @@ static const char *kTransformList = "List";
static AString GetSectionPrefix(const AString &name)
{
- return AString(kStorage) + name + AString("/");
+ AString s = kStorage;
+ s += name;
+ s += '/';
+ return s;
}
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
@@ -721,8 +724,8 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
ReadUString(nameLen, name);
if (ReadUInt16() != 0)
return S_FALSE;
- if (!ConvertUnicodeToUTF8(name, section.Name))
- return S_FALSE;
+ ConvertUnicodeToUTF8(name, section.Name);
+ // if (!ConvertUnicodeToUTF8(name, section.Name)) return S_FALSE;
database.Sections.Add(section);
}
}
diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h
index 70764ab9..c4ce83ed 100644
--- a/CPP/7zip/Archive/Chm/ChmIn.h
+++ b/CPP/7zip/Archive/Chm/ChmIn.h
@@ -120,10 +120,10 @@ struct CLzxInfo
return 0;
}
- UInt64 GetFolderSize() const { return ResetTable.BlockSize * ResetInterval; };
- UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); };
- UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); };
- UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex * ResetInterval; };
+ UInt64 GetFolderSize() const { return ResetTable.BlockSize * ResetInterval; }
+ UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); }
+ UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); }
+ UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex * ResetInterval; }
bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const
{
UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);
diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp
index fc686b94..9cfd40cc 100644
--- a/CPP/7zip/Archive/ComHandler.cpp
+++ b/CPP/7zip/Archive/ComHandler.cpp
@@ -27,8 +27,7 @@ namespace NArchive {
namespace NCom {
#define SIGNATURE { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }
-static const UInt32 kSignatureSize = 8;
-static const Byte kSignature[kSignatureSize] = SIGNATURE;
+static const Byte kSignature[] = SIGNATURE;
enum EType
{
@@ -40,7 +39,7 @@ enum EType
k_Type_Xls,
};
-static const char *kExtensions[] =
+static const char * const kExtensions[] =
{
"compound"
, "msi"
@@ -240,8 +239,8 @@ HRESULT CDatabase::AddNode(int parent, UInt32 did)
return S_OK;
}
-static const char kCharOpenBracket = '[';
-static const char kCharCloseBracket = ']';
+static const wchar_t kCharOpenBracket = L'[';
+static const wchar_t kCharCloseBracket = L']';
static UString CompoundNameToFileName(const UString &s)
{
@@ -263,23 +262,25 @@ static UString CompoundNameToFileName(const UString &s)
return res;
}
-static char g_MsiChars[] =
+static const char k_Msi_Chars[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._";
-static const wchar_t *kMsi_ID = L""; // L"{msi}";
+// static const char *k_Msi_ID = ""; // "{msi}";
+static const wchar_t k_Msi_SpecChar = L'!';
+
+static const unsigned k_Msi_NumBits = 6;
+static const unsigned k_Msi_NumChars = 1 << k_Msi_NumBits;
+static const unsigned k_Msi_CharMask = k_Msi_NumChars - 1;
+static const unsigned k_Msi_StartUnicodeChar = 0x3800;
+static const unsigned k_Msi_UnicodeRange = k_Msi_NumChars * (k_Msi_NumChars + 1);
-static const unsigned kMsiNumBits = 6;
-static const UInt32 kMsiNumChars = 1 << kMsiNumBits;
-static const UInt32 kMsiCharMask = kMsiNumChars - 1;
-static const UInt32 kMsiStartUnicodeChar = 0x3800;
-static const UInt32 kMsiUnicodeRange = kMsiNumChars * (kMsiNumChars + 1);
static bool IsMsiName(const Byte *p)
{
UInt32 c = Get16(p);
return
- c >= kMsiStartUnicodeChar &&
- c <= kMsiStartUnicodeChar + kMsiUnicodeRange;
+ c >= k_Msi_StartUnicodeChar &&
+ c <= k_Msi_StartUnicodeChar + k_Msi_UnicodeRange;
}
static bool AreEqualNames(const Byte *rawName, const char *asciiName)
@@ -296,30 +297,32 @@ static bool AreEqualNames(const Byte *rawName, const char *asciiName)
return false;
}
-static bool CompoundMsiNameToFileName(const UString &name, UString &resultName)
+static bool CompoundMsiNameToFileName(const UString &name, UString &res)
{
- resultName.Empty();
+ res.Empty();
for (unsigned i = 0; i < name.Len(); i++)
{
wchar_t c = name[i];
- if (c < kMsiStartUnicodeChar || c > kMsiStartUnicodeChar + kMsiUnicodeRange)
+ if (c < k_Msi_StartUnicodeChar || c > k_Msi_StartUnicodeChar + k_Msi_UnicodeRange)
return false;
+ /*
if (i == 0)
- resultName += kMsi_ID;
- c -= kMsiStartUnicodeChar;
+ res += k_Msi_ID;
+ */
+ c -= k_Msi_StartUnicodeChar;
- UInt32 c0 = c & kMsiCharMask;
- UInt32 c1 = c >> kMsiNumBits;
+ unsigned c0 = (unsigned)c & k_Msi_CharMask;
+ unsigned c1 = (unsigned)c >> k_Msi_NumBits;
- if (c1 <= kMsiNumChars)
+ if (c1 <= k_Msi_NumChars)
{
- resultName += (wchar_t)g_MsiChars[c0];
- if (c1 == kMsiNumChars)
+ res += (wchar_t)(Byte)k_Msi_Chars[c0];
+ if (c1 == k_Msi_NumChars)
break;
- resultName += (wchar_t)g_MsiChars[c1];
+ res += (wchar_t)(Byte)k_Msi_Chars[c1];
}
else
- resultName += L'!';
+ res += k_Msi_SpecChar;
}
return true;
}
@@ -328,6 +331,7 @@ static UString ConvertName(const Byte *p, bool &isMsi)
{
isMsi = false;
UString s;
+
for (unsigned i = 0; i < kNameSizeMax; i += 2)
{
wchar_t c = Get16(p + i);
@@ -335,6 +339,7 @@ static UString ConvertName(const Byte *p, bool &isMsi)
break;
s += c;
}
+
UString msiName;
if (CompoundMsiNameToFileName(s, msiName))
{
@@ -416,7 +421,7 @@ HRESULT CDatabase::Open(IInStream *inStream)
Byte p[kHeaderSize];
PhySize = kHeaderSize;
RINOK(ReadStream_FALSE(inStream, p, kHeaderSize));
- if (memcmp(p, kSignature, kSignatureSize) != 0)
+ if (memcmp(p, kSignature, ARRAY_SIZE(kSignature)) != 0)
return S_FALSE;
if (Get16(p + 0x1A) > 4) // majorVer
return S_FALSE;
@@ -573,11 +578,14 @@ HRESULT CDatabase::Open(IInStream *inStream)
continue;
bool isMsiName;
UString msiName = ConvertName(item.Name, isMsiName);
- if (isMsiName && msiName.Len() >= 4 &&
- MyStringCompareNoCase(msiName.RightPtr(4), L".cab") == 0)
+ if (isMsiName)
{
- numCabs++;
- MainSubfile = i;
+ if (msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab")
+ || msiName.Len() >= 3 && msiName[0] != k_Msi_SpecChar && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe"))
+ {
+ numCabs++;
+ MainSubfile = i;
+ }
}
}
if (numCabs > 1)
@@ -663,7 +671,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
NWindows::NCOM::CPropVariant prop;
switch (propID)
{
- case kpidExtension: prop = kExtensions[_db.Type]; break;
+ case kpidExtension: prop = kExtensions[(unsigned)_db.Type]; break;
case kpidPhySize: prop = _db.PhySize; break;
case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break;
case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break;
@@ -861,15 +869,11 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Compound", "msi msp doc xls ppt", 0, 0xE5,
- kSignatureSize, SIGNATURE,
+REGISTER_ARC_I(
+ "Compound", "msi msp doc xls ppt", 0, 0xE5,
+ kSignature,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Com)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp
index 13019d1f..41b5805c 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp
@@ -4,116 +4,1041 @@
#include "CoderMixer2.h"
-namespace NCoderMixer {
+#ifdef USE_MIXER_ST
-CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):
- _srcBindInfo(srcBindInfo)
+STDMETHODIMP CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams);
+ UInt32 realProcessed = 0;
+ HRESULT result = S_OK;
+ if (_stream)
+ result = _stream->Read(data, size, &realProcessed);
+ _size += realProcessed;
+ if (size != 0 && realProcessed == 0)
+ _wasFinished = true;
+ if (processedSize)
+ *processedSize = realProcessed;
+ return result;
+}
+
- UInt32 j;
- _srcInToDestOutMap.ClearAndSetSize(NumSrcInStreams);
- DestOutToSrcInMap.ClearAndSetSize(NumSrcInStreams);
+STDMETHODIMP COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ HRESULT result = S_OK;
+ if (_stream)
+ result = _stream->Write(data, size, &size);
+ _size += size;
+ if (processedSize)
+ *processedSize = size;
+ return result;
+}
- for (j = 0; j < NumSrcInStreams; j++)
+STDMETHODIMP COutStreamCalcSize::OutStreamFinish()
+{
+ HRESULT result = S_OK;
+ if (_stream)
{
- _srcInToDestOutMap[j] = 0;
- DestOutToSrcInMap[j] = 0;
+ CMyComPtr<IOutStreamFinish> outStreamFinish;
+ _stream.QueryInterface(IID_IOutStreamFinish, &outStreamFinish);
+ if (outStreamFinish)
+ result = outStreamFinish->OutStreamFinish();
}
+ return result;
+}
- _srcOutToDestInMap.ClearAndSetSize(_numSrcOutStreams);
- _destInToSrcOutMap.ClearAndSetSize(_numSrcOutStreams);
+#endif
- for (j = 0; j < _numSrcOutStreams; j++)
+
+
+
+namespace NCoderMixer2 {
+
+static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
+{
+ v.ClearAndSetSize(size);
+ bool *p = &v[0];
+ for (unsigned i = 0; i < size; i++)
+ p[i] = false;
+}
+
+class CBondsChecks
+{
+ CBoolVector _coderUsed;
+
+ bool Init();
+ bool CheckCoder(unsigned coderIndex);
+public:
+ const CBindInfo *BindInfo;
+
+ bool Check();
+};
+
+bool CBondsChecks::CheckCoder(unsigned coderIndex)
+{
+ const CCoderStreamsInfo &coder = BindInfo->Coders[coderIndex];
+
+ if (coderIndex >= _coderUsed.Size() || _coderUsed[coderIndex])
+ return false;
+ _coderUsed[coderIndex] = true;
+
+ UInt32 start = BindInfo->Coder_to_Stream[coderIndex];
+
+ for (unsigned i = 0; i < coder.NumStreams; i++)
{
- _srcOutToDestInMap[j] = 0;
- _destInToSrcOutMap[j] = 0;
+ UInt32 ind = start + i;
+
+ if (BindInfo->IsStream_in_PackStreams(ind))
+ continue;
+
+ int bond = BindInfo->FindBond_for_PackStream(ind);
+ if (bond < 0)
+ return false;
+ if (!CheckCoder(BindInfo->Bonds[bond].UnpackIndex))
+ return false;
}
+
+ return true;
+}
+
+bool CBondsChecks::Check()
+{
+ BoolVector_Fill_False(_coderUsed, BindInfo->Coders.Size());
+
+ if (!CheckCoder(BindInfo->UnpackCoder))
+ return false;
+
+ FOR_VECTOR(i, _coderUsed)
+ if (!_coderUsed[i])
+ return false;
+
+ return true;
+}
+
+void CBindInfo::ClearMaps()
+{
+ Coder_to_Stream.Clear();
+ Stream_to_Coder.Clear();
+}
- UInt32 destInOffset = 0;
- UInt32 destOutOffset = 0;
- UInt32 srcInOffset = NumSrcInStreams;
- UInt32 srcOutOffset = _numSrcOutStreams;
+bool CBindInfo::CalcMapsAndCheck()
+{
+ ClearMaps();
+
+ UInt32 numStreams = 0;
+
+ if (Coders.Size() == 0)
+ return false;
+ if (Coders.Size() - 1 != Bonds.Size())
+ return false;
- for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--)
+ FOR_VECTOR(i, Coders)
{
- const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i];
+ Coder_to_Stream.Add(numStreams);
+
+ const CCoderStreamsInfo &c = Coders[i];
+
+ for (unsigned j = 0; j < c.NumStreams; j++)
+ Stream_to_Coder.Add(i);
+
+ numStreams += c.NumStreams;
+ }
+
+ if (numStreams != GetNum_Bonds_and_PackStreams())
+ return false;
+
+ CBondsChecks bc;
+ bc.BindInfo = this;
+ return bc.Check();
+}
+
+
+void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes)
+{
+ if (unpackSize)
+ {
+ UnpackSize = *unpackSize;
+ UnpackSizePointer = &UnpackSize;
+ }
+ else
+ {
+ UnpackSize = 0;
+ UnpackSizePointer = NULL;
+ }
+
+ PackSizes.ClearAndSetSize((unsigned)NumStreams);
+ PackSizePointers.ClearAndSetSize((unsigned)NumStreams);
+
+ for (unsigned i = 0; i < NumStreams; i++)
+ {
+ if (packSizes && packSizes[i])
+ {
+ PackSizes[i] = *(packSizes[i]);
+ PackSizePointers[i] = &PackSizes[i];
+ }
+ else
+ {
+ PackSizes[i] = 0;
+ PackSizePointers[i] = NULL;
+ }
+ }
+}
+
+bool CMixer::Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex)
+{
+ if (coderIndex == _bi.UnpackCoder)
+ return true;
+
+ int bond = _bi.FindBond_for_UnpackStream(coderIndex);
+ if (bond < 0)
+ throw 20150213;
+
+ /*
+ UInt32 coderIndex, coderStreamIndex;
+ _bi.GetCoder_for_Stream(_bi.Bonds[bond].PackIndex, coderIndex, coderStreamIndex);
+ */
+ UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[bond].PackIndex];
+
+ if (!IsFilter_Vector[nextCoder])
+ return false;
+
+ return Is_UnpackSize_Correct_for_Coder(nextCoder);
+}
+
+bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex)
+{
+ if (_bi.IsStream_in_PackStreams(streamIndex))
+ return true;
+
+ int bond = _bi.FindBond_for_PackStream(streamIndex);
+ if (bond < 0)
+ throw 20150213;
+
+ UInt32 nextCoder = _bi.Bonds[bond].UnpackIndex;
+
+ if (!IsFilter_Vector[nextCoder])
+ return false;
+
+ return Is_PackSize_Correct_for_Coder(nextCoder);
+}
+
+bool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex)
+{
+ UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
+ UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
+ for (UInt32 i = 0; i < numStreams; i++)
+ if (!Is_PackSize_Correct_for_Stream(startIndex + i))
+ return false;
+ return true;
+}
+
+bool CMixer::IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex)
+{
+ if (IsExternal_Vector[coderIndex])
+ return true;
+ UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
+ UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
+ for (UInt32 i = 0; i < numStreams; i++)
+ {
+ UInt32 si = startIndex + i;
+ if (_bi.IsStream_in_PackStreams(si))
+ continue;
+
+ int bond = _bi.FindBond_for_PackStream(si);
+ if (bond < 0)
+ throw 20150213;
+
+ if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[bond].UnpackIndex))
+ return true;
+ }
+ return false;
+}
+
+
+
+
+#ifdef USE_MIXER_ST
+
+CMixerST::CMixerST(bool encodeMode):
+ CMixer(encodeMode)
+ {}
+
+CMixerST::~CMixerST() {}
+
+void CMixerST::AddCoder(const CCreatedCoder &cod)
+{
+ IsFilter_Vector.Add(cod.IsFilter);
+ IsExternal_Vector.Add(cod.IsExternal);
+ // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
+ CCoderST &c2 = _coders.AddNew();
+ c2.NumStreams = cod.NumStreams;
+ c2.Coder = cod.Coder;
+ c2.Coder2 = cod.Coder2;
- srcInOffset -= srcCoderInfo.NumInStreams;
- srcOutOffset -= srcCoderInfo.NumOutStreams;
+ /*
+ if (isFilter)
+ {
+ c2.CanRead = true;
+ c2.CanWrite = true;
+ }
+ else
+ */
+ {
+ IUnknown *unk = (cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2);
+ {
+ CMyComPtr<ISequentialInStream> s;
+ unk->QueryInterface(IID_ISequentialInStream, (void**)&s);
+ c2.CanRead = (s != NULL);
+ }
+ {
+ CMyComPtr<ISequentialOutStream> s;
+ unk->QueryInterface(IID_ISequentialOutStream, (void**)&s);
+ c2.CanWrite = (s != NULL);
+ }
+ }
+}
+
+CCoder &CMixerST::GetCoder(unsigned index)
+{
+ return _coders[index];
+}
+
+void CMixerST::ReInit() {}
+
+HRESULT CMixerST::GetInStream2(
+ ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 outStreamIndex, ISequentialInStream **inStreamRes)
+{
+ UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0;
+
+ if (EncodeMode)
+ {
+ _bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex);
+ if (coderStreamIndex != 0)
+ return E_NOTIMPL;
+ }
+
+ const CCoder &coder = _coders[coderIndex];
+
+ CMyComPtr<ISequentialInStream> seqInStream;
+ coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream);
+ if (!seqInStream)
+ return E_NOTIMPL;
+
+ UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams;
+ UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex];
+
+ bool isSet = false;
+
+ if (numInStreams == 1)
+ {
+ CMyComPtr<ICompressSetInStream> setStream;
+ coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream);
+ if (setStream)
+ {
+ CMyComPtr<ISequentialInStream> seqInStream2;
+ RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2));
+ RINOK(setStream->SetInStream(seqInStream2));
+ isSet = true;
+ }
+ }
+
+ if (!isSet && numInStreams != 0)
+ {
+ CMyComPtr<ICompressSetInStream2> setStream2;
+ coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2);
+ if (!setStream2)
+ return E_NOTIMPL;
- UInt32 j;
- for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++)
+ for (UInt32 i = 0; i < numInStreams; i++)
+ {
+ CMyComPtr<ISequentialInStream> seqInStream2;
+ RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2));
+ RINOK(setStream2->SetInStream2(i, seqInStream2));
+ }
+ }
+
+ *inStreamRes = seqInStream.Detach();
+ return S_OK;
+}
+
+
+HRESULT CMixerST::GetInStream(
+ ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 inStreamIndex, ISequentialInStream **inStreamRes)
+{
+ CMyComPtr<ISequentialInStream> seqInStream;
+
+ {
+ int index = -1;
+ if (EncodeMode)
+ {
+ if (_bi.UnpackCoder == inStreamIndex)
+ index = 0;
+ }
+ else
+ index = _bi.FindStream_in_PackStreams(inStreamIndex);
+
+ if (index >= 0)
+ {
+ seqInStream = inStreams[(unsigned)index];
+ *inStreamRes = seqInStream.Detach();
+ return S_OK;
+ }
+ }
+
+ int bond = FindBond_for_Stream(
+ true, // forInputStream
+ inStreamIndex);
+ if (bond < 0)
+ return E_INVALIDARG;
+
+ RINOK(GetInStream2(inStreams, /* inSizes, */
+ _bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream));
+
+ while (_binderStreams.Size() <= (unsigned)bond)
+ _binderStreams.AddNew();
+ CStBinderStream &bs = _binderStreams[bond];
+
+ if (bs.StreamRef || bs.InStreamSpec)
+ return E_NOTIMPL;
+
+ CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize;
+ bs.StreamRef = spec;
+ bs.InStreamSpec = spec;
+
+ spec->SetStream(seqInStream);
+ spec->Init();
+
+ seqInStream = bs.InStreamSpec;
+
+ *inStreamRes = seqInStream.Detach();
+ return S_OK;
+}
+
+
+HRESULT CMixerST::GetOutStream(
+ ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
+ UInt32 outStreamIndex, ISequentialOutStream **outStreamRes)
+{
+ CMyComPtr<ISequentialOutStream> seqOutStream;
+
+ {
+ int index = -1;
+ if (!EncodeMode)
+ {
+ if (_bi.UnpackCoder == outStreamIndex)
+ index = 0;
+ }
+ else
+ index = _bi.FindStream_in_PackStreams(outStreamIndex);
+
+ if (index >= 0)
+ {
+ seqOutStream = outStreams[(unsigned)index];
+ *outStreamRes = seqOutStream.Detach();
+ return S_OK;
+ }
+ }
+
+ int bond = FindBond_for_Stream(
+ false, // forInputStream
+ outStreamIndex);
+ if (bond < 0)
+ return E_INVALIDARG;
+
+ UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
+
+ UInt32 coderIndex = inStreamIndex;
+ UInt32 coderStreamIndex = 0;
+
+ if (!EncodeMode)
+ _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
+
+ CCoder &coder = _coders[coderIndex];
+
+ /*
+ if (!coder.Coder)
+ return E_NOTIMPL;
+ */
+
+ coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream);
+ if (!seqOutStream)
+ return E_NOTIMPL;
+
+ UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
+ UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
+
+ bool isSet = false;
+
+ if (numOutStreams == 1)
+ {
+ CMyComPtr<ICompressSetOutStream> setOutStream;
+ coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
+ if (setOutStream)
+ {
+ CMyComPtr<ISequentialOutStream> seqOutStream2;
+ RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2));
+ RINOK(setOutStream->SetOutStream(seqOutStream2));
+ isSet = true;
+ }
+ }
+
+ if (!isSet && numOutStreams != 0)
+ {
+ return E_NOTIMPL;
+ /*
+ CMyComPtr<ICompressSetOutStream2> setStream2;
+ coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2);
+ if (!setStream2)
+ return E_NOTIMPL;
+ for (UInt32 i = 0; i < numOutStreams; i++)
+ {
+ CMyComPtr<ISequentialOutStream> seqOutStream2;
+ RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2));
+ RINOK(setStream2->SetOutStream2(i, seqOutStream2));
+ }
+ */
+ }
+
+ while (_binderStreams.Size() <= (unsigned)bond)
+ _binderStreams.AddNew();
+ CStBinderStream &bs = _binderStreams[bond];
+
+ if (bs.StreamRef || bs.OutStreamSpec)
+ return E_NOTIMPL;
+
+ COutStreamCalcSize *spec = new COutStreamCalcSize;
+ bs.StreamRef = (ISequentialOutStream *)spec;
+ bs.OutStreamSpec = spec;
+
+ spec->SetStream(seqOutStream);
+ spec->Init();
+
+ seqOutStream = bs.OutStreamSpec;
+
+ *outStreamRes = seqOutStream.Detach();
+ return S_OK;
+}
+
+
+static HRESULT GetError(HRESULT res, HRESULT res2)
+{
+ if (res == res2)
+ return res;
+ if (res == S_OK)
+ return res2;
+ if (res == k_My_HRESULT_WritingWasCut)
+ {
+ if (res2 != S_OK)
+ return res2;
+ }
+ return res;
+}
+
+
+HRESULT CMixerST::FinishStream(UInt32 streamIndex)
+{
+ {
+ int index = -1;
+ if (!EncodeMode)
{
- UInt32 index = srcInOffset + j;
- _srcInToDestOutMap[index] = destOutOffset;
- DestOutToSrcInMap[destOutOffset] = index;
+ if (_bi.UnpackCoder == streamIndex)
+ index = 0;
}
- for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++)
+ else
+ index = _bi.FindStream_in_PackStreams(streamIndex);
+
+ if (index >= 0)
+ return S_OK;
+ }
+
+ int bond = FindBond_for_Stream(
+ false, // forInputStream
+ streamIndex);
+ if (bond < 0)
+ return E_INVALIDARG;
+
+ UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
+
+ UInt32 coderIndex = inStreamIndex;
+ UInt32 coderStreamIndex = 0;
+ if (!EncodeMode)
+ _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
+
+ CCoder &coder = _coders[coderIndex];
+ CMyComPtr<IOutStreamFinish> finish;
+ coder.QueryInterface(IID_IOutStreamFinish, (void **)&finish);
+ HRESULT res = S_OK;
+ if (finish)
+ {
+ res = finish->OutStreamFinish();
+ }
+ return GetError(res, FinishCoder(coderIndex));
+}
+
+
+HRESULT CMixerST::FinishCoder(UInt32 coderIndex)
+{
+ CCoder &coder = _coders[coderIndex];
+
+ UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
+ UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
+
+ HRESULT res = S_OK;
+ for (unsigned i = 0; i < numOutStreams; i++)
+ res = GetError(res, FinishStream(startIndex + i));
+ return res;
+}
+
+
+void CMixerST::SelectMainCoder(bool useFirst)
+{
+ unsigned ci = _bi.UnpackCoder;
+
+ int firstNonFilter = -1;
+ int firstAllowed = ci;
+
+ for (;;)
+ {
+ const CCoderST &coder = _coders[ci];
+ // break;
+
+ if (ci != _bi.UnpackCoder)
+ if (EncodeMode ? !coder.CanWrite : !coder.CanRead)
+ {
+ firstAllowed = ci;
+ firstNonFilter = -2;
+ }
+
+ if (coder.NumStreams != 1)
+ break;
+
+ UInt32 st = _bi.Coder_to_Stream[ci];
+ if (_bi.IsStream_in_PackStreams(st))
+ break;
+ int bond = _bi.FindBond_for_PackStream(st);
+ if (bond < 0)
+ throw 20150213;
+
+ if (EncodeMode ? !coder.CanRead : !coder.CanWrite)
+ break;
+
+ if (firstNonFilter == -1 && !IsFilter_Vector[ci])
+ firstNonFilter = ci;
+
+ ci = _bi.Bonds[bond].UnpackIndex;
+ }
+
+ if (useFirst)
+ ci = firstAllowed;
+ else if (firstNonFilter >= 0)
+ ci = firstNonFilter;
+
+ MainCoderIndex = ci;
+}
+
+
+HRESULT CMixerST::Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress)
+{
+ _binderStreams.Clear();
+ unsigned ci = MainCoderIndex;
+
+ const CCoder &mainCoder = _coders[MainCoderIndex];
+
+ CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
+ CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
+
+ UInt32 numInStreams = EncodeMode ? 1 : mainCoder.NumStreams;
+ UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams;
+
+ UInt32 startInIndex = EncodeMode ? ci : _bi.Coder_to_Stream[ci];
+ UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci];
+
+ UInt32 i;
+
+ for (i = 0; i < numInStreams; i++)
+ {
+ CMyComPtr<ISequentialInStream> seqInStream;
+ RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream));
+ seqInStreams.Add(seqInStream);
+ }
+
+ for (i = 0; i < numOutStreams; i++)
+ {
+ CMyComPtr<ISequentialOutStream> seqOutStream;
+ RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream));
+ seqOutStreams.Add(seqOutStream);
+ }
+
+ CRecordVector< ISequentialInStream * > seqInStreamsSpec;
+ CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;
+
+ for (i = 0; i < numInStreams; i++)
+ seqInStreamsSpec.Add(seqInStreams[i]);
+ for (i = 0; i < numOutStreams; i++)
+ seqOutStreamsSpec.Add(seqOutStreams[i]);
+
+ for (i = 0; i < _coders.Size(); i++)
+ {
+ if (i == ci)
+ continue;
+
+ CCoder &coder = _coders[i];
+
+ if (EncodeMode)
+ {
+ CMyComPtr<ICompressInitEncoder> initEncoder;
+ coder.QueryInterface(IID_ICompressInitEncoder, (void **)&initEncoder);
+ if (initEncoder)
+ RINOK(initEncoder->InitEncoder());
+ }
+ else
+ {
+ CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
+ coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
+ if (setOutStreamSize)
+ RINOK(setOutStreamSize->SetOutStreamSize(
+ EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer));
+ }
+ }
+
+ const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front();
+ const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer;
+
+ HRESULT res;
+ if (mainCoder.Coder)
+ {
+ res = mainCoder.Coder->Code(
+ seqInStreamsSpec[0], seqOutStreamsSpec[0],
+ isSizes2[0], outSizes2[0],
+ progress);
+ }
+ else
+ {
+ res = mainCoder.Coder2->Code(
+ &seqInStreamsSpec.Front(), isSizes2, numInStreams,
+ &seqOutStreamsSpec.Front(), outSizes2, numOutStreams,
+ progress);
+ }
+
+ if (res == k_My_HRESULT_WritingWasCut)
+ res = S_OK;
+
+ if (res == S_OK || res == S_FALSE)
+ {
+ res = GetError(res, FinishCoder(ci));
+ }
+
+ for (i = 0; i < _binderStreams.Size(); i++)
+ {
+ const CStBinderStream &bs = _binderStreams[i];
+ if (bs.InStreamSpec)
+ bs.InStreamSpec->ReleaseStream();
+ else
+ bs.OutStreamSpec->ReleaseStream();
+ }
+
+ if (res == k_My_HRESULT_WritingWasCut)
+ res = S_OK;
+ return res;
+}
+
+
+HRESULT CMixerST::GetMainUnpackStream(
+ ISequentialInStream * const *inStreams,
+ ISequentialInStream **inStreamRes)
+{
+ CMyComPtr<ISequentialInStream> seqInStream;
+
+ RINOK(GetInStream2(inStreams, /* inSizes, */
+ _bi.UnpackCoder, &seqInStream))
+
+ FOR_VECTOR (i, _coders)
+ {
+ CCoder &coder = _coders[i];
+ CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
+ coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
+ if (setOutStreamSize)
{
- UInt32 index = srcOutOffset + j;
- _srcOutToDestInMap[index] = destInOffset;
- _destInToSrcOutMap[destInOffset] = index;
+ RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer));
}
}
+
+ *inStreamRes = seqInStream.Detach();
+ return S_OK;
}
-void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo)
+
+UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const
{
- destBindInfo.Coders.ClearAndReserve(_srcBindInfo.Coders.Size());
- destBindInfo.BindPairs.ClearAndReserve(_srcBindInfo.BindPairs.Size());
- destBindInfo.InStreams.ClearAndReserve(_srcBindInfo.OutStreams.Size());
- destBindInfo.OutStreams.ClearAndReserve(_srcBindInfo.InStreams.Size());
+ const CStBinderStream &bs = _binderStreams[bondIndex];
+ if (bs.InStreamSpec)
+ return bs.InStreamSpec->GetSize();
+ return bs.OutStreamSpec->GetSize();
+}
+
+#endif
+
+
+
+
+
+
+#ifdef USE_MIXER_MT
+
+
+void CCoderMT::Execute()
+{
+ try
+ {
+ Code(NULL);
+ }
+ catch(...)
+ {
+ Result = E_FAIL;
+ }
+}
+
+void CCoderMT::Code(ICompressProgressInfo *progress)
+{
+ unsigned numInStreams = EncodeMode ? 1 : NumStreams;
+ unsigned numOutStreams = EncodeMode ? NumStreams : 1;
+
+ InStreamPointers.ClearAndReserve(numInStreams);
+ OutStreamPointers.ClearAndReserve(numOutStreams);
unsigned i;
- for (i = _srcBindInfo.Coders.Size(); i != 0;)
+
+ for (i = 0; i < numInStreams; i++)
+ InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);
+
+ for (i = 0; i < numOutStreams; i++)
+ OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);
+
+ // we suppose that UnpackSizePointer and PackSizePointers contain correct pointers.
+ /*
+ if (UnpackSizePointer)
+ UnpackSizePointer = &UnpackSize;
+ for (i = 0; i < NumStreams; i++)
+ if (PackSizePointers[i])
+ PackSizePointers[i] = &PackSizes[i];
+ */
+
+ CReleaser releaser(*this);
+
+ if (Coder)
+ Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
+ EncodeMode ? UnpackSizePointer : PackSizePointers[0],
+ EncodeMode ? PackSizePointers[0] : UnpackSizePointer,
+ progress);
+ else
+ Result = Coder2->Code(
+ &InStreamPointers.Front(), EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams,
+ &OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams,
+ progress);
+}
+
+HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo)
+{
+ CMixer::SetBindInfo(bindInfo);
+
+ _streamBinders.Clear();
+ FOR_VECTOR (i, _bi.Bonds)
{
- i--;
- const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i];
- CCoderStreamsInfo destCoderInfo;
- destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams;
- destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams;
- destBindInfo.Coders.AddInReserved(destCoderInfo);
+ RINOK(_streamBinders.AddNew().CreateEvents());
}
- for (i = _srcBindInfo.BindPairs.Size(); i != 0;)
+ return S_OK;
+}
+
+void CMixerMT::AddCoder(const CCreatedCoder &cod)
+{
+ IsFilter_Vector.Add(cod.IsFilter);
+ IsExternal_Vector.Add(cod.IsExternal);
+ // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
+ CCoderMT &c2 = _coders.AddNew();
+ c2.NumStreams = cod.NumStreams;
+ c2.Coder = cod.Coder;
+ c2.Coder2 = cod.Coder2;
+ c2.EncodeMode = EncodeMode;
+}
+
+CCoder &CMixerMT::GetCoder(unsigned index)
+{
+ return _coders[index];
+}
+
+void CMixerMT::ReInit()
+{
+ FOR_VECTOR (i, _streamBinders)
+ _streamBinders[i].ReInit();
+}
+
+void CMixerMT::SelectMainCoder(bool useFirst)
+{
+ unsigned ci = _bi.UnpackCoder;
+
+ if (!useFirst)
+ for (;;)
{
- i--;
- const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i];
- CBindPair destBindPair;
- destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex];
- destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex];
- destBindInfo.BindPairs.AddInReserved(destBindPair);
+ if (_coders[ci].NumStreams != 1)
+ break;
+ if (!IsFilter_Vector[ci])
+ break;
+
+ UInt32 st = _bi.Coder_to_Stream[ci];
+ if (_bi.IsStream_in_PackStreams(st))
+ break;
+ int bond = _bi.FindBond_for_PackStream(st);
+ if (bond < 0)
+ throw 20150213;
+ ci = _bi.Bonds[bond].UnpackIndex;
}
- for (i = 0; i < _srcBindInfo.InStreams.Size(); i++)
- destBindInfo.OutStreams.AddInReserved(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]);
- for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++)
- destBindInfo.InStreams.AddInReserved(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);
+
+ MainCoderIndex = ci;
}
-void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
- CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
+HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)
{
- sizes.ClearAndSetSize(numItems);
- sizePointers.ClearAndSetSize(numItems);
- for(UInt32 i = 0; i < numItems; i++)
+ unsigned i;
+
+ for (i = 0; i < _coders.Size(); i++)
+ {
+ CCoderMT &coderInfo = _coders[i];
+ const CCoderStreamsInfo &csi = _bi.Coders[i];
+
+ UInt32 j;
+
+ unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams;
+ unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1;
+
+ coderInfo.InStreams.Clear();
+ for (j = 0; j < numInStreams; j++)
+ coderInfo.InStreams.AddNew();
+
+ coderInfo.OutStreams.Clear();
+ for (j = 0; j < numOutStreams; j++)
+ coderInfo.OutStreams.AddNew();
+ }
+
+ for (i = 0; i < _bi.Bonds.Size(); i++)
{
- if (!srcSizes || !srcSizes[i])
+ const CBond &bond = _bi.Bonds[i];
+
+ UInt32 inCoderIndex, inCoderStreamIndex;
+ UInt32 outCoderIndex, outCoderStreamIndex;
+
+ {
+ UInt32 coderIndex, coderStreamIndex;
+ _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex);
+
+ inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex;
+ outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex;
+
+ inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex;
+ outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;
+ }
+
+ _streamBinders[i].CreateStreams(
+ &_coders[inCoderIndex].InStreams[inCoderStreamIndex],
+ &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
+
+ CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;
+ _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);
+ _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);
+ if (inSetSize && outSetSize)
{
- sizes[i] = 0;
- sizePointers[i] = NULL;
+ const UInt32 kBufSize = 1 << 19;
+ inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);
+ outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);
}
+ }
+
+ {
+ CCoderMT &cod = _coders[_bi.UnpackCoder];
+ if (EncodeMode)
+ cod.InStreams[0] = inStreams[0];
else
+ cod.OutStreams[0] = outStreams[0];
+ }
+
+ for (i = 0; i < _bi.PackStreams.Size(); i++)
+ {
+ UInt32 coderIndex, coderStreamIndex;
+ _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex);
+ CCoderMT &cod = _coders[coderIndex];
+ if (EncodeMode)
+ cod.OutStreams[coderStreamIndex] = outStreams[i];
+ else
+ cod.InStreams[coderStreamIndex] = inStreams[i];
+ }
+
+ return S_OK;
+}
+
+HRESULT CMixerMT::ReturnIfError(HRESULT code)
+{
+ FOR_VECTOR (i, _coders)
+ if (_coders[i].Result == code)
+ return code;
+ return S_OK;
+}
+
+HRESULT CMixerMT::Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress)
+{
+ Init(inStreams, outStreams);
+
+ unsigned i;
+ for (i = 0; i < _coders.Size(); i++)
+ if (i != MainCoderIndex)
{
- sizes[i] = *(srcSizes[i]);
- sizePointers[i] = &sizes[i];
+ RINOK(_coders[i].Create());
}
+
+ for (i = 0; i < _coders.Size(); i++)
+ if (i != MainCoderIndex)
+ _coders[i].Start();
+
+ _coders[MainCoderIndex].Code(progress);
+
+ for (i = 0; i < _coders.Size(); i++)
+ if (i != MainCoderIndex)
+ _coders[i].WaitExecuteFinish();
+
+ RINOK(ReturnIfError(E_ABORT));
+ RINOK(ReturnIfError(E_OUTOFMEMORY));
+
+ for (i = 0; i < _coders.Size(); i++)
+ {
+ HRESULT result = _coders[i].Result;
+ if (result != S_OK
+ && result != k_My_HRESULT_WritingWasCut
+ && result != S_FALSE
+ && result != E_FAIL)
+ return result;
+ }
+
+ RINOK(ReturnIfError(S_FALSE));
+
+ for (i = 0; i < _coders.Size(); i++)
+ {
+ HRESULT result = _coders[i].Result;
+ if (result != S_OK && result != k_My_HRESULT_WritingWasCut)
+ return result;
}
+
+ return S_OK;
}
-void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)
+UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
{
- SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
- SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
+ return _streamBinders[bondIndex].ProcessedSize;
}
+#endif
+
}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h
index 50e7077a..e63f2ff0 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2.h
+++ b/CPP/7zip/Archive/Common/CoderMixer2.h
@@ -8,172 +8,430 @@
#include "../../ICoder.h"
-namespace NCoderMixer {
+#include "../../Common/CreateCoder.h"
-struct CBindPair
+#ifdef _7ZIP_ST
+ #define USE_MIXER_ST
+#else
+ #define USE_MIXER_MT
+ #ifndef _SFX
+ #define USE_MIXER_ST
+ #endif
+#endif
+
+#ifdef USE_MIXER_MT
+#include "../../Common/StreamBinder.h"
+#include "../../Common/VirtThread.h"
+#endif
+
+
+
+#ifdef USE_MIXER_ST
+
+class CSequentialInStreamCalcSize:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(ISequentialInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+private:
+ CMyComPtr<ISequentialInStream> _stream;
+ UInt64 _size;
+ bool _wasFinished;
+public:
+ void SetStream(ISequentialInStream *stream) { _stream = stream; }
+ void Init()
+ {
+ _size = 0;
+ _wasFinished = false;
+ }
+ void ReleaseStream() { _stream.Release(); }
+ UInt64 GetSize() const { return _size; }
+ bool WasFinished() const { return _wasFinished; }
+};
+
+
+class COutStreamCalcSize:
+ public ISequentialOutStream,
+ public IOutStreamFinish,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialOutStream> _stream;
+ UInt64 _size;
+public:
+ MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFinish)
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(OutStreamFinish)();
+
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void ReleaseStream() { _stream.Release(); }
+ void Init() { _size = 0; }
+ UInt64 GetSize() const { return _size; }
+};
+
+#endif
+
+
+
+namespace NCoderMixer2 {
+
+struct CBond
{
- UInt32 InIndex;
- UInt32 OutIndex;
+ UInt32 PackIndex;
+ UInt32 UnpackIndex;
+
+ UInt32 Get_InIndex(bool encodeMode) const { return encodeMode ? UnpackIndex : PackIndex; }
+ UInt32 Get_OutIndex(bool encodeMode) const { return encodeMode ? PackIndex : UnpackIndex; }
};
+
struct CCoderStreamsInfo
{
- UInt32 NumInStreams;
- UInt32 NumOutStreams;
+ UInt32 NumStreams;
};
+
struct CBindInfo
{
CRecordVector<CCoderStreamsInfo> Coders;
- CRecordVector<CBindPair> BindPairs;
- CRecordVector<UInt32> InStreams;
- CRecordVector<UInt32> OutStreams;
+ CRecordVector<CBond> Bonds;
+ CRecordVector<UInt32> PackStreams;
+ unsigned UnpackCoder;
- void Clear()
+ unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); }
+
+ int FindBond_for_PackStream(UInt32 packStream) const
{
- Coders.Clear();
- BindPairs.Clear();
- InStreams.Clear();
- OutStreams.Clear();
+ FOR_VECTOR (i, Bonds)
+ if (Bonds[i].PackIndex == packStream)
+ return i;
+ return -1;
}
- /*
- UInt32 GetCoderStartOutStream(UInt32 coderIndex) const
+ int FindBond_for_UnpackStream(UInt32 unpackStream) const
{
- UInt32 numOutStreams = 0;
- for (UInt32 i = 0; i < coderIndex; i++)
- numOutStreams += Coders[i].NumOutStreams;
- return numOutStreams;
+ FOR_VECTOR (i, Bonds)
+ if (Bonds[i].UnpackIndex == unpackStream)
+ return i;
+ return -1;
}
- */
-
- void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const
+ bool SetUnpackCoder()
{
- numInStreams = 0;
- numOutStreams = 0;
- FOR_VECTOR (i, Coders)
+ bool isOk = false;
+ FOR_VECTOR(i, Coders)
{
- const CCoderStreamsInfo &coderStreamsInfo = Coders[i];
- numInStreams += coderStreamsInfo.NumInStreams;
- numOutStreams += coderStreamsInfo.NumOutStreams;
+ if (FindBond_for_UnpackStream(i) < 0)
+ {
+ if (isOk)
+ return false;
+ UnpackCoder = i;
+ isOk = true;
+ }
}
+ return isOk;
}
-
- int FindBinderForInStream(UInt32 inStream) const
+
+ bool IsStream_in_PackStreams(UInt32 streamIndex) const
{
- FOR_VECTOR (i, BindPairs)
- if (BindPairs[i].InIndex == inStream)
- return i;
- return -1;
+ return FindStream_in_PackStreams(streamIndex) >= 0;
}
- int FindBinderForOutStream(UInt32 outStream) const
+
+ int FindStream_in_PackStreams(UInt32 streamIndex) const
{
- FOR_VECTOR (i, BindPairs)
- if (BindPairs[i].OutIndex == outStream)
+ FOR_VECTOR(i, PackStreams)
+ if (PackStreams[i] == streamIndex)
return i;
return -1;
}
- UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const
+
+ // that function is used before Maps is calculated
+
+ UInt32 GetStream_for_Coder(UInt32 coderIndex) const
{
UInt32 streamIndex = 0;
for (UInt32 i = 0; i < coderIndex; i++)
- streamIndex += Coders[i].NumInStreams;
+ streamIndex += Coders[i].NumStreams;
return streamIndex;
}
+
+ // ---------- Maps Section ----------
+
+ CRecordVector<UInt32> Coder_to_Stream;
+ CRecordVector<UInt32> Stream_to_Coder;
+
+ void ClearMaps();
+ bool CalcMapsAndCheck();
+
+ // ---------- End of Maps Section ----------
- UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const
+ void Clear()
{
- UInt32 streamIndex = 0;
- for (UInt32 i = 0; i < coderIndex; i++)
- streamIndex += Coders[i].NumOutStreams;
- return streamIndex;
+ Coders.Clear();
+ Bonds.Clear();
+ PackStreams.Clear();
+
+ ClearMaps();
}
+
+ void GetCoder_for_Stream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const
+ {
+ coderIndex = Stream_to_Coder[streamIndex];
+ coderStreamIndex = streamIndex - Coder_to_Stream[coderIndex];
+ }
+};
- void FindInStream(UInt32 streamIndex, UInt32 &coderIndex,
- UInt32 &coderStreamIndex) const
+
+class CCoder
+{
+ CLASS_NO_COPY(CCoder);
+public:
+ CMyComPtr<ICompressCoder> Coder;
+ CMyComPtr<ICompressCoder2> Coder2;
+ UInt32 NumStreams;
+
+ UInt64 UnpackSize;
+ const UInt64 *UnpackSizePointer;
+
+ CRecordVector<UInt64> PackSizes;
+ CRecordVector<const UInt64 *> PackSizePointers;
+
+ CCoder() {}
+
+ void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes);
+
+ IUnknown *GetUnknown() const
{
- for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
- {
- UInt32 curSize = Coders[coderIndex].NumInStreams;
- if (streamIndex < curSize)
- {
- coderStreamIndex = streamIndex;
- return;
- }
- streamIndex -= curSize;
- }
- throw 1;
+ return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;
}
- void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex,
- UInt32 &coderStreamIndex) const
+
+ HRESULT QueryInterface(REFGUID iid, void** pp) const
{
- for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
- {
- UInt32 curSize = Coders[coderIndex].NumOutStreams;
- if (streamIndex < curSize)
+ return GetUnknown()->QueryInterface(iid, pp);
+ }
+};
+
+
+
+class CMixer
+{
+ bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex);
+
+protected:
+ CBindInfo _bi;
+
+ int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const
+ {
+ if (EncodeMode == forInputStream)
+ return _bi.FindBond_for_UnpackStream(streamIndex);
+ else
+ return _bi.FindBond_for_PackStream(streamIndex);
+ }
+
+ CBoolVector IsFilter_Vector;
+ CBoolVector IsExternal_Vector;
+ bool EncodeMode;
+public:
+ unsigned MainCoderIndex;
+
+ CMixer(bool encodeMode):
+ EncodeMode(encodeMode),
+ MainCoderIndex(0)
+ {}
+
+ /*
+ Sequence of calling:
+
+ SetBindInfo();
+ for each coder
+ AddCoder();
+ SelectMainCoder();
+
+ for each file
{
- coderStreamIndex = streamIndex;
- return;
+ ReInit()
+ for each coder
+ SetCoderInfo();
+ Code();
}
- streamIndex -= curSize;
- }
- throw 1;
+ */
+
+ virtual HRESULT SetBindInfo(const CBindInfo &bindInfo)
+ {
+ _bi = bindInfo;
+ IsFilter_Vector.Clear();
+ MainCoderIndex = 0;
+ return S_OK;
}
+
+ virtual void AddCoder(const CCreatedCoder &cod) = 0;
+ virtual CCoder &GetCoder(unsigned index) = 0;
+ virtual void SelectMainCoder(bool useFirst) = 0;
+ virtual void ReInit() = 0;
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) = 0;
+ virtual HRESULT Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress) = 0;
+ virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0;
+
+ bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex);
+ bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex);
+ bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex);
};
-class CBindReverseConverter
+
+
+
+#ifdef USE_MIXER_ST
+
+struct CCoderST: public CCoder
{
- UInt32 _numSrcOutStreams;
- NCoderMixer::CBindInfo _srcBindInfo;
- CRecordVector<UInt32> _srcInToDestOutMap;
- CRecordVector<UInt32> _srcOutToDestInMap;
- CRecordVector<UInt32> _destInToSrcOutMap;
-public:
- UInt32 NumSrcInStreams;
- CRecordVector<UInt32> DestOutToSrcInMap;
+ bool CanRead;
+ bool CanWrite;
+
+ CCoderST(): CanRead(false), CanWrite(false) {}
+};
- CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo);
- void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo);
+
+struct CStBinderStream
+{
+ CSequentialInStreamCalcSize *InStreamSpec;
+ COutStreamCalcSize *OutStreamSpec;
+ CMyComPtr<IUnknown> StreamRef;
+
+ CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {}
};
-void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
- CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems);
-struct CCoderInfo2
+class CMixerST:
+ public IUnknown,
+ public CMixer,
+ public CMyUnknownImp
{
- CMyComPtr<ICompressCoder> Coder;
- CMyComPtr<ICompressCoder2> Coder2;
- UInt32 NumInStreams;
- UInt32 NumOutStreams;
+ HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 outStreamIndex, ISequentialInStream **inStreamRes);
+ HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 inStreamIndex, ISequentialInStream **inStreamRes);
+ HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
+ UInt32 outStreamIndex, ISequentialOutStream **outStreamRes);
- CRecordVector<UInt64> InSizes;
- CRecordVector<UInt64> OutSizes;
- CRecordVector<const UInt64 *> InSizePointers;
- CRecordVector<const UInt64 *> OutSizePointers;
+ HRESULT FinishStream(UInt32 streamIndex);
+ HRESULT FinishCoder(UInt32 coderIndex);
- CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams):
- NumInStreams(numInStreams),
- NumOutStreams(numOutStreams) {}
- void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
+public:
+ CObjectVector<CCoderST> _coders;
+
+ CObjectVector<CStBinderStream> _binderStreams;
- HRESULT QueryInterface(REFGUID iid, void** pp) const
+ MY_UNKNOWN_IMP
+
+ CMixerST(bool encodeMode);
+ ~CMixerST();
+
+ virtual void AddCoder(const CCreatedCoder &cod);
+ virtual CCoder &GetCoder(unsigned index);
+ virtual void SelectMainCoder(bool useFirst);
+ virtual void ReInit();
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
+ { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
+ virtual HRESULT Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress);
+ virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
+
+ HRESULT GetMainUnpackStream(
+ ISequentialInStream * const *inStreams,
+ ISequentialInStream **inStreamRes);
+};
+
+#endif
+
+
+
+
+#ifdef USE_MIXER_MT
+
+class CCoderMT: public CCoder, public CVirtThread
+{
+ CLASS_NO_COPY(CCoderMT)
+ CRecordVector<ISequentialInStream*> InStreamPointers;
+ CRecordVector<ISequentialOutStream*> OutStreamPointers;
+
+private:
+ void Execute();
+public:
+ bool EncodeMode;
+ HRESULT Result;
+ CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
+ CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
+
+ void Release()
{
- IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;
- return p->QueryInterface(iid, pp);
+ InStreamPointers.Clear();
+ OutStreamPointers.Clear();
+ unsigned i;
+ for (i = 0; i < InStreams.Size(); i++)
+ InStreams[i].Release();
+ for (i = 0; i < OutStreams.Size(); i++)
+ OutStreams[i].Release();
}
+
+ class CReleaser
+ {
+ CLASS_NO_COPY(CReleaser)
+ CCoderMT &_c;
+ public:
+ CReleaser(CCoderMT &c): _c(c) {}
+ ~CReleaser() { _c.Release(); }
+ };
+
+ CCoderMT(): EncodeMode(false) {}
+ ~CCoderMT() { CVirtThread::WaitThreadFinish(); }
+
+ void Code(ICompressProgressInfo *progress);
};
-class CCoderMixer2
+
+class CMixerMT:
+ public IUnknown,
+ public CMixer,
+ public CMyUnknownImp
{
+ CObjectVector<CStreamBinder> _streamBinders;
+
+ HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
+ HRESULT ReturnIfError(HRESULT code);
+
public:
- virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0;
- virtual void ReInit() = 0;
- virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0;
+ CObjectVector<CCoderMT> _coders;
+
+ MY_UNKNOWN_IMP
+
+ virtual HRESULT SetBindInfo(const CBindInfo &bindInfo);
+ virtual void AddCoder(const CCreatedCoder &cod);
+ virtual CCoder &GetCoder(unsigned index);
+ virtual void SelectMainCoder(bool useFirst);
+ virtual void ReInit();
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
+ { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
+ virtual HRESULT Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress);
+ virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
+
+ CMixerMT(bool encodeMode): CMixer(encodeMode) {}
};
+#endif
+
}
#endif
diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
index 5288fbc1..c0139862 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
@@ -4,125 +4,153 @@
#include "CoderMixer2MT.h"
-namespace NCoderMixer {
+namespace NCoderMixer2 {
-CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams):
- CCoderInfo2(numInStreams, numOutStreams)
+void CCoderMT::Execute() { Code(NULL); }
+
+void CCoderMT::Code(ICompressProgressInfo *progress)
{
- InStreams.ClearAndReserve(NumInStreams);
- OutStreams.ClearAndReserve(NumOutStreams);
-}
+ unsigned numInStreams = EncodeMode ? 1 : NumStreams;
+ unsigned numOutStreams = EncodeMode ? NumStreams : 1;
-void CCoder2::Execute() { Code(NULL); }
+ InStreamPointers.ClearAndReserve(numInStreams);
+ OutStreamPointers.ClearAndReserve(numOutStreams);
-void CCoder2::Code(ICompressProgressInfo *progress)
-{
- InStreamPointers.ClearAndReserve(NumInStreams);
- OutStreamPointers.ClearAndReserve(NumOutStreams);
- UInt32 i;
- for (i = 0; i < NumInStreams; i++)
- {
- if (InSizePointers[i])
- InSizePointers[i] = &InSizes[i];
+ unsigned i;
+
+ for (i = 0; i < numInStreams; i++)
InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);
- }
- for (i = 0; i < NumOutStreams; i++)
- {
- if (OutSizePointers[i])
- OutSizePointers[i] = &OutSizes[i];
+
+ for (i = 0; i < numOutStreams; i++)
OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);
- }
+
+ // we suppose that UnpackSizePointer and PackSizePointers contain correct pointers.
+ /*
+ if (UnpackSizePointer)
+ UnpackSizePointer = &UnpackSize;
+ for (i = 0; i < NumStreams; i++)
+ if (PackSizePointers[i])
+ PackSizePointers[i] = &PackSizes[i];
+ */
+
if (Coder)
Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
- InSizePointers[0], OutSizePointers[0], progress);
+ EncodeMode ? UnpackSizePointer : PackSizePointers[0],
+ EncodeMode ? PackSizePointers[0] : UnpackSizePointer,
+ progress);
else
- Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams,
- &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress);
- {
- unsigned i;
- for (i = 0; i < InStreams.Size(); i++)
- InStreams[i].Release();
- for (i = 0; i < OutStreams.Size(); i++)
- OutStreams[i].Release();
- }
-}
+ Result = Coder2->Code(
+ &InStreamPointers.Front(), EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams,
+ &OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams,
+ progress);
+
+ InStreamPointers.Clear();
+ OutStreamPointers.Clear();
-/*
-void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)
-{
- SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
- SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
+ for (i = 0; i < InStreams.Size(); i++)
+ InStreams[i].Release();
+ for (i = 0; i < OutStreams.Size(); i++)
+ OutStreams[i].Release();
}
-*/
-
-//////////////////////////////////////
-// CCoderMixer2MT
-HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
+HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo)
{
- _bindInfo = bindInfo;
+ CMixer::SetBindInfo(bindInfo);
+
_streamBinders.Clear();
- FOR_VECTOR (i, _bindInfo.BindPairs)
+ FOR_VECTOR (i, _bi.Bonds)
{
RINOK(_streamBinders.AddNew().CreateEvents());
}
return S_OK;
}
-void CCoderMixer2MT::AddCoderCommon()
-{
- const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()];
- CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams);
- _coders.Add(threadCoderInfo);
-}
-
-void CCoderMixer2MT::AddCoder(ICompressCoder *coder)
+void CMixerMT::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter)
{
- AddCoderCommon();
- _coders.Back().Coder = coder;
+ const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
+ CCoderMT &c2 = _coders.AddNew();
+ c2.NumStreams = c.NumStreams;
+ c2.EncodeMode = EncodeMode;
+ c2.Coder = coder;
+ c2.Coder2 = coder2;
+ IsFilter_Vector.Add(isFilter);
}
-void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
+CCoder &CMixerMT::GetCoder(unsigned index)
{
- AddCoderCommon();
- _coders.Back().Coder2 = coder;
+ return _coders[index];
}
-
-void CCoderMixer2MT::ReInit()
+void CMixerMT::ReInit()
{
FOR_VECTOR (i, _streamBinders)
_streamBinders[i].ReInit();
}
+void CMixerMT::SelectMainCoder(bool useFirst)
+{
+ unsigned ci = _bi.UnpackCoder;
+
+ if (!useFirst)
+ for (;;)
+ {
+ if (_coders[ci].NumStreams != 1)
+ break;
+ if (!IsFilter_Vector[ci])
+ break;
+
+ UInt32 st = _bi.Coder_to_Stream[ci];
+ if (_bi.IsStream_in_PackStreams(st))
+ break;
+ int bond = _bi.FindBond_for_PackStream(st);
+ if (bond < 0)
+ throw 20150213;
+ ci = _bi.Bonds[bond].UnpackIndex;
+ }
+
+ MainCoderIndex = ci;
+}
-HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams)
+HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)
{
- /*
- if (_coders.Size() != _bindInfo.Coders.Size())
- throw 0;
- */
unsigned i;
+
for (i = 0; i < _coders.Size(); i++)
{
- CCoder2 &coderInfo = _coders[i];
- const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];
- coderInfo.InStreams.Clear();
+ CCoderMT &coderInfo = _coders[i];
+ const CCoderStreamsInfo &csi = _bi.Coders[i];
+
UInt32 j;
- for (j = 0; j < coderStreamsInfo.NumInStreams; j++)
- coderInfo.InStreams.Add(NULL);
+
+ unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams;
+ unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1;
+
+ coderInfo.InStreams.Clear();
+ for (j = 0; j < numInStreams; j++)
+ coderInfo.InStreams.AddNew();
+
coderInfo.OutStreams.Clear();
- for (j = 0; j < coderStreamsInfo.NumOutStreams; j++)
- coderInfo.OutStreams.Add(NULL);
+ for (j = 0; j < numOutStreams; j++)
+ coderInfo.OutStreams.AddNew();
}
- for (i = 0; i < _bindInfo.BindPairs.Size(); i++)
+ for (i = 0; i < _bi.Bonds.Size(); i++)
{
- const CBindPair &bindPair = _bindInfo.BindPairs[i];
+ const CBond &bond = _bi.Bonds[i];
+
UInt32 inCoderIndex, inCoderStreamIndex;
UInt32 outCoderIndex, outCoderStreamIndex;
- _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);
- _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);
+
+ {
+ UInt32 coderIndex, coderStreamIndex;
+ _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex);
+
+ inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex;
+ outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex;
+
+ inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex;
+ outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;
+ }
_streamBinders[i].CreateStreams(
&_coders[inCoderIndex].InStreams[inCoderStreamIndex],
@@ -139,23 +167,29 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre
}
}
- for (i = 0; i < _bindInfo.InStreams.Size(); i++)
{
- UInt32 inCoderIndex, inCoderStreamIndex;
- _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);
- _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];
+ CCoderMT &cod = _coders[_bi.UnpackCoder];
+ if (EncodeMode)
+ cod.InStreams[0] = inStreams[0];
+ else
+ cod.OutStreams[0] = outStreams[0];
}
-
- for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
+
+ for (i = 0; i < _bi.PackStreams.Size(); i++)
{
- UInt32 outCoderIndex, outCoderStreamIndex;
- _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);
- _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i];
+ UInt32 coderIndex, coderStreamIndex;
+ _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex);
+ CCoderMT &cod = _coders[coderIndex];
+ if (EncodeMode)
+ cod.OutStreams[coderStreamIndex] = outStreams[i];
+ else
+ cod.InStreams[coderStreamIndex] = inStreams[i];
}
+
return S_OK;
}
-HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)
+HRESULT CMixerMT::ReturnIfError(HRESULT code)
{
FOR_VECTOR (i, _coders)
if (_coders[i].Result == code)
@@ -163,35 +197,28 @@ HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)
return S_OK;
}
-STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
- const UInt64 ** /* inSizes */,
- UInt32 numInStreams,
- ISequentialOutStream **outStreams,
- const UInt64 ** /* outSizes */,
- UInt32 numOutStreams,
- ICompressProgressInfo *progress)
+HRESULT CMixerMT::Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress)
{
- if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
- numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
- return E_INVALIDARG;
-
Init(inStreams, outStreams);
unsigned i;
for (i = 0; i < _coders.Size(); i++)
- if (i != _progressCoderIndex)
+ if (i != MainCoderIndex)
{
RINOK(_coders[i].Create());
}
for (i = 0; i < _coders.Size(); i++)
- if (i != _progressCoderIndex)
+ if (i != MainCoderIndex)
_coders[i].Start();
- _coders[_progressCoderIndex].Code(progress);
+ _coders[MainCoderIndex].Code(progress);
for (i = 0; i < _coders.Size(); i++)
- if (i != _progressCoderIndex)
+ if (i != MainCoderIndex)
_coders[i].WaitExecuteFinish();
RINOK(ReturnIfError(E_ABORT));
@@ -200,7 +227,10 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
for (i = 0; i < _coders.Size(); i++)
{
HRESULT result = _coders[i].Result;
- if (result != S_OK && result != E_FAIL && result != S_FALSE)
+ if (result != S_OK
+ && result != k_My_HRESULT_WritingWasCut
+ && result != S_FALSE
+ && result != E_FAIL)
return result;
}
@@ -209,10 +239,16 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
for (i = 0; i < _coders.Size(); i++)
{
HRESULT result = _coders[i].Result;
- if (result != S_OK)
+ if (result != S_OK && result != k_My_HRESULT_WritingWasCut)
return result;
}
+
return S_OK;
}
+UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
+{
+ return _streamBinders[bondIndex].ProcessedSize;
+}
+
}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h
index ba475cec..41bb3e1c 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2MT.h
+++ b/CPP/7zip/Archive/Common/CoderMixer2MT.h
@@ -3,81 +3,75 @@
#ifndef __CODER_MIXER2_MT_H
#define __CODER_MIXER2_MT_H
-#include "CoderMixer2.h"
#include "../../../Common/MyCom.h"
+
#include "../../Common/StreamBinder.h"
#include "../../Common/VirtThread.h"
-namespace NCoderMixer {
+#include "CoderMixer2.h"
+
+namespace NCoderMixer2 {
-struct CCoder2: public CCoderInfo2, public CVirtThread
+class CCoderMT: public CCoder, public CVirtThread
{
+ CLASS_NO_COPY(CCoderMT)
CRecordVector<ISequentialInStream*> InStreamPointers;
CRecordVector<ISequentialOutStream*> OutStreamPointers;
+private:
+ void Execute();
public:
+ bool EncodeMode;
HRESULT Result;
CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
- CCoder2(UInt32 numInStreams, UInt32 numOutStreams);
- ~CCoder2() { CVirtThread::WaitThreadFinish(); }
- // void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
- virtual void Execute();
+ CCoderMT(): EncodeMode(false) {}
+ ~CCoderMT() { CVirtThread::WaitThreadFinish(); }
+
void Code(ICompressProgressInfo *progress);
};
-/*
- SetBindInfo()
- for each coder
- AddCoder[2]()
- SetProgressIndex(UInt32 coderIndex);
-
- for each file
- {
- ReInit()
- for each coder
- SetCoderInfo
- Code
- }
-*/
-
-class CCoderMixer2MT:
- public ICompressCoder2,
- public CCoderMixer2,
+
+class CMixerMT:
+ public IUnknown,
+ public CMixer,
public CMyUnknownImp
{
- CBindInfo _bindInfo;
CObjectVector<CStreamBinder> _streamBinders;
- unsigned _progressCoderIndex;
- void AddCoderCommon();
- HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams);
+ HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
HRESULT ReturnIfError(HRESULT code);
+
public:
- CObjectVector<CCoder2> _coders;
+ CObjectVector<CCoderMT> _coders;
+
MY_UNKNOWN_IMP
- STDMETHOD(Code)(ISequentialInStream **inStreams,
- const UInt64 **inSizes,
- UInt32 numInStreams,
- ISequentialOutStream **outStreams,
- const UInt64 **outSizes,
- UInt32 numOutStreams,
+ virtual HRESULT SetBindInfo(const CBindInfo &bindInfo);
+
+ virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter);
+
+ virtual CCoder &GetCoder(unsigned index);
+
+ virtual void SelectMainCoder(bool useFirst);
+
+ virtual void ReInit();
+
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
+ { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
+
+ virtual HRESULT Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
ICompressProgressInfo *progress);
- HRESULT SetBindInfo(const CBindInfo &bindInfo);
- void AddCoder(ICompressCoder *coder);
- void AddCoder2(ICompressCoder2 *coder);
- void SetProgressCoderIndex(unsigned coderIndex) { _progressCoderIndex = coderIndex; }
+ virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
- void ReInit();
- void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)
- { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }
- UInt64 GetWriteProcessedSize(UInt32 binderIndex) const
- { return _streamBinders[binderIndex].ProcessedSize; }
+ CMixerMT(bool encodeMode): CMixer(encodeMode) {}
};
}
+
#endif
diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
index a94ba115..127c1ed4 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
@@ -4,236 +4,559 @@
#include "CoderMixer2ST.h"
-namespace NCoderMixer {
+STDMETHODIMP CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessed = 0;
+ HRESULT result = S_OK;
+ if (_stream)
+ result = _stream->Read(data, size, &realProcessed);
+ _size += realProcessed;
+ if (size != 0 && realProcessed == 0)
+ _wasFinished = true;
+ if (processedSize)
+ *processedSize = realProcessed;
+ return result;
+}
-CCoderMixer2ST::CCoderMixer2ST() {}
-CCoderMixer2ST::~CCoderMixer2ST(){ }
-HRESULT CCoderMixer2ST::SetBindInfo(const CBindInfo &bindInfo)
+STDMETHODIMP COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
- _bindInfo = bindInfo;
- return S_OK;
+ HRESULT result = S_OK;
+ if (_stream)
+ result = _stream->Write(data, size, &size);
+ _size += size;
+ if (processedSize)
+ *processedSize = size;
+ return result;
}
-void CCoderMixer2ST::AddCoderCommon(bool isMain)
+STDMETHODIMP COutStreamCalcSize::Flush()
{
- const CCoderStreamsInfo &csi = _bindInfo.Coders[_coders.Size()];
- _coders.Add(CSTCoderInfo(csi.NumInStreams, csi.NumOutStreams, isMain));
+ HRESULT result = S_OK;
+ if (_stream)
+ {
+ CMyComPtr<IOutStreamFlush> outStreamFlush;
+ _stream.QueryInterface(IID_IOutStreamFlush, &outStreamFlush);
+ if (outStreamFlush)
+ result = outStreamFlush->Flush();;
+ }
+ return result;
}
-void CCoderMixer2ST::AddCoder(ICompressCoder *coder, bool isMain)
+
+
+namespace NCoderMixer2 {
+
+CMixerST::CMixerST(bool encodeMode):
+ CMixer(encodeMode)
+ {}
+
+CMixerST::~CMixerST() {}
+
+void CMixerST::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter)
{
- AddCoderCommon(isMain);
- _coders.Back().Coder = coder;
+ IsFilter_Vector.Add(isFilter);
+ const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
+ CCoderST &c2 = _coders.AddNew();
+ c2.NumStreams = c.NumStreams;
+ c2.Coder = coder;
+ c2.Coder2 = coder2;
+
+ /*
+ if (isFilter)
+ {
+ c2.CanRead = true;
+ c2.CanWrite = true;
+ }
+ else
+ */
+ {
+ IUnknown *unk = (coder ? (IUnknown *)coder : (IUnknown *)coder2);
+ {
+ CMyComPtr<ISequentialInStream> s;
+ unk->QueryInterface(IID_ISequentialInStream, (void**)&s);
+ c2.CanRead = (s != NULL);
+ }
+ {
+ CMyComPtr<ISequentialOutStream> s;
+ unk->QueryInterface(IID_ISequentialOutStream, (void**)&s);
+ c2.CanWrite = (s != NULL);
+ }
+ }
}
-void CCoderMixer2ST::AddCoder2(ICompressCoder2 *coder, bool isMain)
+CCoder &CMixerST::GetCoder(unsigned index)
{
- AddCoderCommon(isMain);
- _coders.Back().Coder2 = coder;
+ return _coders[index];
+}
+
+void CMixerST::ReInit() {}
+
+HRESULT CMixerST::GetInStream2(
+ ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 outStreamIndex, ISequentialInStream **inStreamRes)
+{
+ UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0;
+
+ if (EncodeMode)
+ {
+ _bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex);
+ if (coderStreamIndex != 0)
+ return E_NOTIMPL;
+ }
+
+ const CCoder &coder = _coders[coderIndex];
+
+ CMyComPtr<ISequentialInStream> seqInStream;
+ coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream);
+ if (!seqInStream)
+ return E_NOTIMPL;
+
+ UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams;
+ UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex];
+
+ bool isSet = false;
+
+ if (numInStreams == 1)
+ {
+ CMyComPtr<ICompressSetInStream> setStream;
+ coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream);
+ if (setStream)
+ {
+ CMyComPtr<ISequentialInStream> seqInStream2;
+ RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2));
+ RINOK(setStream->SetInStream(seqInStream2));
+ isSet = true;
+ }
+ }
+
+ if (!isSet && numInStreams != 0)
+ {
+ CMyComPtr<ICompressSetInStream2> setStream2;
+ coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2);
+ if (!setStream2)
+ return E_NOTIMPL;
+
+ for (UInt32 i = 0; i < numInStreams; i++)
+ {
+ CMyComPtr<ISequentialInStream> seqInStream2;
+ RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2));
+ RINOK(setStream2->SetInStream2(i, seqInStream2));
+ }
+ }
+
+ *inStreamRes = seqInStream.Detach();
+ return S_OK;
}
-void CCoderMixer2ST::ReInit() { }
-HRESULT CCoderMixer2ST::GetInStream(
- ISequentialInStream **inStreams, const UInt64 **inSizes,
- UInt32 streamIndex, ISequentialInStream **inStreamRes)
+HRESULT CMixerST::GetInStream(
+ ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 inStreamIndex, ISequentialInStream **inStreamRes)
{
CMyComPtr<ISequentialInStream> seqInStream;
- int i;
- for (i = 0; i < _bindInfo.InStreams.Size(); i++)
- if (_bindInfo.InStreams[i] == streamIndex)
+
+ {
+ int index = -1;
+ if (EncodeMode)
+ {
+ if (_bi.UnpackCoder == inStreamIndex)
+ index = 0;
+ }
+ else
+ index = _bi.FindStream_in_PackStreams(inStreamIndex);
+
+ if (index >= 0)
{
- seqInStream = inStreams[i];
+ seqInStream = inStreams[index];
*inStreamRes = seqInStream.Detach();
return S_OK;
}
- int binderIndex = _bindInfo.FindBinderForInStream(streamIndex);
- if (binderIndex < 0)
+ }
+
+ int bond = FindBond_for_Stream(
+ true, // forInputStream
+ inStreamIndex);
+ if (bond < 0)
return E_INVALIDARG;
- UInt32 coderIndex, coderStreamIndex;
- _bindInfo.FindOutStream(_bindInfo.BindPairs[binderIndex].OutIndex,
- coderIndex, coderStreamIndex);
-
- CCoderInfo2 &coder = _coders[coderIndex];
- if (!coder.Coder)
- return E_NOTIMPL;
- coder.Coder.QueryInterface(IID_ISequentialInStream, &seqInStream);
- if (!seqInStream)
- return E_NOTIMPL;
+ RINOK(GetInStream2(inStreams, /* inSizes, */
+ _bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream));
- UInt32 startIndex = _bindInfo.GetCoderInStreamIndex(coderIndex);
+ while (_binderStreams.Size() <= (unsigned)bond)
+ _binderStreams.AddNew();
+ CStBinderStream &bs = _binderStreams[bond];
- CMyComPtr<ICompressSetInStream> setInStream;
- if (!coder.Coder)
- return E_NOTIMPL;
- coder.Coder.QueryInterface(IID_ICompressSetInStream, &setInStream);
- if (!setInStream)
+ if (bs.StreamRef || bs.InStreamSpec)
return E_NOTIMPL;
+
+ CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize;
+ bs.StreamRef = spec;
+ bs.InStreamSpec = spec;
+
+ spec->SetStream(seqInStream);
+ spec->Init();
+
+ seqInStream = bs.InStreamSpec;
- if (coder.NumInStreams > 1)
- return E_NOTIMPL;
- for (i = 0; i < (int)coder.NumInStreams; i++)
- {
- CMyComPtr<ISequentialInStream> seqInStream2;
- RINOK(GetInStream(inStreams, inSizes, startIndex + i, &seqInStream2));
- RINOK(setInStream->SetInStream(seqInStream2));
- }
*inStreamRes = seqInStream.Detach();
return S_OK;
}
-HRESULT CCoderMixer2ST::GetOutStream(
- ISequentialOutStream **outStreams, const UInt64 **outSizes,
- UInt32 streamIndex, ISequentialOutStream **outStreamRes)
+
+HRESULT CMixerST::GetOutStream(
+ ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
+ UInt32 outStreamIndex, ISequentialOutStream **outStreamRes)
{
CMyComPtr<ISequentialOutStream> seqOutStream;
- int i;
- for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
- if (_bindInfo.OutStreams[i] == streamIndex)
+
+ {
+ int index = -1;
+ if (!EncodeMode)
+ {
+ if (_bi.UnpackCoder == outStreamIndex)
+ index = 0;
+ }
+ else
+ index = _bi.FindStream_in_PackStreams(outStreamIndex);
+
+ if (index >= 0)
{
- seqOutStream = outStreams[i];
+ seqOutStream = outStreams[index];
*outStreamRes = seqOutStream.Detach();
return S_OK;
}
- int binderIndex = _bindInfo.FindBinderForOutStream(streamIndex);
- if (binderIndex < 0)
+ }
+
+ int bond = FindBond_for_Stream(
+ false, // forInputStream
+ outStreamIndex);
+ if (bond < 0)
return E_INVALIDARG;
- UInt32 coderIndex, coderStreamIndex;
- _bindInfo.FindInStream(_bindInfo.BindPairs[binderIndex].InIndex,
- coderIndex, coderStreamIndex);
+ UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
+
+ UInt32 coderIndex = inStreamIndex;
+ UInt32 coderStreamIndex = 0;
+
+ if (!EncodeMode)
+ _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
+
+ CCoder &coder = _coders[coderIndex];
- CCoderInfo2 &coder = _coders[coderIndex];
+ /*
if (!coder.Coder)
return E_NOTIMPL;
- coder.Coder.QueryInterface(IID_ISequentialOutStream, &seqOutStream);
+ */
+
+ coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream);
if (!seqOutStream)
return E_NOTIMPL;
- UInt32 startIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
+ UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
+ UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
- CMyComPtr<ICompressSetOutStream> setOutStream;
- if (!coder.Coder)
- return E_NOTIMPL;
- coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
- if (!setOutStream)
- return E_NOTIMPL;
+ bool isSet = false;
- if (coder.NumOutStreams > 1)
- return E_NOTIMPL;
- for (i = 0; i < (int)coder.NumOutStreams; i++)
+ if (numOutStreams == 1)
{
- CMyComPtr<ISequentialOutStream> seqOutStream2;
- RINOK(GetOutStream(outStreams, outSizes, startIndex + i, &seqOutStream2));
- RINOK(setOutStream->SetOutStream(seqOutStream2));
+ CMyComPtr<ICompressSetOutStream> setOutStream;
+ coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
+ if (setOutStream)
+ {
+ CMyComPtr<ISequentialOutStream> seqOutStream2;
+ RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2));
+ RINOK(setOutStream->SetOutStream(seqOutStream2));
+ isSet = true;
+ }
}
+
+ if (!isSet && numOutStreams != 0)
+ {
+ // return E_NOTIMPL;
+ // /*
+ CMyComPtr<ICompressSetOutStream2> setStream2;
+ coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2);
+ if (!setStream2)
+ return E_NOTIMPL;
+ for (UInt32 i = 0; i < numOutStreams; i++)
+ {
+ CMyComPtr<ISequentialOutStream> seqOutStream2;
+ RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2));
+ RINOK(setStream2->SetOutStream2(i, seqOutStream2));
+ }
+ // */
+ }
+
+ while (_binderStreams.Size() <= (unsigned)bond)
+ _binderStreams.AddNew();
+ CStBinderStream &bs = _binderStreams[bond];
+
+ if (bs.StreamRef || bs.OutStreamSpec)
+ return E_NOTIMPL;
+
+ COutStreamCalcSize *spec = new COutStreamCalcSize;
+ bs.StreamRef = (ISequentialOutStream *)spec;
+ bs.OutStreamSpec = spec;
+
+ spec->SetStream(seqOutStream);
+ spec->Init();
+
+ seqOutStream = bs.OutStreamSpec;
+
*outStreamRes = seqOutStream.Detach();
return S_OK;
}
-
-STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams,
- const UInt64 **inSizes,
- UInt32 numInStreams,
- ISequentialOutStream **outStreams,
- const UInt64 **outSizes,
- UInt32 numOutStreams,
- ICompressProgressInfo *progress)
+
+static HRESULT GetError(HRESULT res, HRESULT res2)
{
- if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
- numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
- return E_INVALIDARG;
+ if (res == res2)
+ return res;
+ if (res == S_OK)
+ return res2;
+ if (res == k_My_HRESULT_WritingWasCut)
+ {
+ if (res2 != S_OK)
+ return res2;
+ }
+ return res;
+}
- // Find main coder
- int _mainCoderIndex = -1;
- int i;
- for (i = 0; i < _coders.Size(); i++)
- if (_coders[i].IsMain)
- {
- _mainCoderIndex = i;
- break;
- }
- if (_mainCoderIndex < 0)
- for (i = 0; i < _coders.Size(); i++)
- if (_coders[i].NumInStreams > 1)
+
+HRESULT CMixerST::FlushStream(UInt32 streamIndex)
+{
+ {
+ int index = -1;
+ if (!EncodeMode)
{
- if (_mainCoderIndex >= 0)
- return E_NOTIMPL;
- _mainCoderIndex = i;
+ if (_bi.UnpackCoder == streamIndex)
+ index = 0;
}
- if (_mainCoderIndex < 0)
- _mainCoderIndex = 0;
+ else
+ index = _bi.FindStream_in_PackStreams(streamIndex);
+
+ if (index >= 0)
+ return S_OK;
+ }
+
+ int bond = FindBond_for_Stream(
+ false, // forInputStream
+ streamIndex);
+ if (bond < 0)
+ return E_INVALIDARG;
+
+ UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
+
+ UInt32 coderIndex = inStreamIndex;
+ UInt32 coderStreamIndex = 0;
+ if (!EncodeMode)
+ _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
+
+ CCoder &coder = _coders[coderIndex];
+ CMyComPtr<IOutStreamFlush> flush;
+ coder.QueryInterface(IID_IOutStreamFlush, (void **)&flush);
+ HRESULT res = S_OK;
+ if (flush)
+ {
+ res = flush->Flush();
+ }
+ return GetError(res, FlushCoder(coderIndex));
+}
+
+
+HRESULT CMixerST::FlushCoder(UInt32 coderIndex)
+{
+ CCoder &coder = _coders[coderIndex];
+
+ UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
+ UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
+
+ HRESULT res = S_OK;
+ for (unsigned i = 0; i < numOutStreams; i++)
+ res = GetError(res, FlushStream(startIndex + i));
+ return res;
+}
+
+
+void CMixerST::SelectMainCoder(bool useFirst)
+{
+ unsigned ci = _bi.UnpackCoder;
+
+ int firstNonFilter = -1;
+ int firstAllowed = ci;
+
+ for (;;)
+ {
+ const CCoderST &coder = _coders[ci];
+ // break;
+
+ if (ci != _bi.UnpackCoder)
+ if (EncodeMode ? !coder.CanWrite : !coder.CanRead)
+ {
+ firstAllowed = ci;
+ firstNonFilter = -2;
+ }
+
+ if (coder.NumStreams != 1)
+ break;
+
+ UInt32 st = _bi.Coder_to_Stream[ci];
+ if (_bi.IsStream_in_PackStreams(st))
+ break;
+ int bond = _bi.FindBond_for_PackStream(st);
+ if (bond < 0)
+ throw 20150213;
+
+ if (EncodeMode ? !coder.CanRead : !coder.CanWrite)
+ break;
+
+ if (firstNonFilter == -1 && !IsFilter_Vector[ci])
+ firstNonFilter = ci;
+
+ ci = _bi.Bonds[bond].UnpackIndex;
+ }
+
+ ci = firstNonFilter;
+ if (firstNonFilter < 0 || useFirst)
+ ci = firstAllowed;
+ MainCoderIndex = ci;
+}
+
+
+HRESULT CMixerST::Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress)
+{
+ _binderStreams.Clear();
+ unsigned ci = MainCoderIndex;
- // _mainCoderIndex = 0;
- // _mainCoderIndex = _coders.Size() - 1;
- CCoderInfo2 &mainCoder = _coders[_mainCoderIndex];
+ const CCoder &mainCoder = _coders[MainCoderIndex];
CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
- UInt32 startInIndex = _bindInfo.GetCoderInStreamIndex(_mainCoderIndex);
- UInt32 startOutIndex = _bindInfo.GetCoderOutStreamIndex(_mainCoderIndex);
- for (i = 0; i < (int)mainCoder.NumInStreams; i++)
+
+ UInt32 numInStreams = EncodeMode ? 1 : mainCoder.NumStreams;
+ UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams;
+
+ UInt32 startInIndex = EncodeMode ? ci : _bi.Coder_to_Stream[ci];
+ UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci];
+
+ UInt32 i;
+
+ for (i = 0; i < numInStreams; i++)
{
CMyComPtr<ISequentialInStream> seqInStream;
- RINOK(GetInStream(inStreams, inSizes, startInIndex + i, &seqInStream));
+ RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream));
seqInStreams.Add(seqInStream);
}
- for (i = 0; i < (int)mainCoder.NumOutStreams; i++)
+
+ for (i = 0; i < numOutStreams; i++)
{
CMyComPtr<ISequentialOutStream> seqOutStream;
- RINOK(GetOutStream(outStreams, outSizes, startOutIndex + i, &seqOutStream));
+ RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream));
seqOutStreams.Add(seqOutStream);
}
+
CRecordVector< ISequentialInStream * > seqInStreamsSpec;
CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;
- for (i = 0; i < (int)mainCoder.NumInStreams; i++)
+
+ for (i = 0; i < numInStreams; i++)
seqInStreamsSpec.Add(seqInStreams[i]);
- for (i = 0; i < (int)mainCoder.NumOutStreams; i++)
+ for (i = 0; i < numOutStreams; i++)
seqOutStreamsSpec.Add(seqOutStreams[i]);
for (i = 0; i < _coders.Size(); i++)
{
- if (i == _mainCoderIndex)
+ if (i == ci)
continue;
- CCoderInfo2 &coder = _coders[i];
+
+ CCoder &coder = _coders[i];
+
CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
- coder.Coder.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
+ coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
if (setOutStreamSize)
{
- RINOK(setOutStreamSize->SetOutStreamSize(coder.OutSizePointers[0]));
+ RINOK(setOutStreamSize->SetOutStreamSize(
+ EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer));
}
}
+
+ const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front();
+ const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer;
+
+ HRESULT res;
if (mainCoder.Coder)
{
- RINOK(mainCoder.Coder->Code(
+ res = mainCoder.Coder->Code(
seqInStreamsSpec[0], seqOutStreamsSpec[0],
- mainCoder.InSizePointers[0], mainCoder.OutSizePointers[0],
- progress));
+ isSizes2[0], outSizes2[0],
+ progress);
}
else
{
- RINOK(mainCoder.Coder2->Code(
- &seqInStreamsSpec.Front(),
- &mainCoder.InSizePointers.Front(), mainCoder.NumInStreams,
- &seqOutStreamsSpec.Front(),
- &mainCoder.OutSizePointers.Front(), mainCoder.NumOutStreams,
- progress));
+ res = mainCoder.Coder2->Code(
+ &seqInStreamsSpec.Front(), isSizes2, numInStreams,
+ &seqOutStreamsSpec.Front(), outSizes2, numOutStreams,
+ progress);
}
- CMyComPtr<IOutStreamFlush> flush;
- seqOutStreams.Front().QueryInterface(IID_IOutStreamFlush, &flush);
- if (flush)
- return flush->Flush();
+
+ if (res == k_My_HRESULT_WritingWasCut)
+ res = S_OK;
+
+ if (res == S_OK || res == S_FALSE)
+ {
+ res = GetError(res, FlushCoder(ci));
+ }
+
+ for (i = 0; i < _binderStreams.Size(); i++)
+ {
+ const CStBinderStream &bs = _binderStreams[i];
+ if (bs.InStreamSpec)
+ bs.InStreamSpec->ReleaseStream();
+ else
+ bs.OutStreamSpec->ReleaseStream();
+ }
+
+ if (res == k_My_HRESULT_WritingWasCut)
+ res = S_OK;
+ return res;
+}
+
+
+HRESULT CMixerST::GetMainUnpackStream(
+ ISequentialInStream * const *inStreams,
+ ISequentialInStream **inStreamRes)
+{
+ CMyComPtr<ISequentialInStream> seqInStream;
+
+ RINOK(GetInStream2(inStreams, /* inSizes, */
+ _bi.UnpackCoder, &seqInStream))
+
+ FOR_VECTOR (i, _coders)
+ {
+ CCoder &coder = _coders[i];
+ CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
+ coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
+ if (setOutStreamSize)
+ {
+ RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer));
+ }
+ }
+
+ *inStreamRes = seqInStream.Detach();
return S_OK;
}
-/*
-UInt64 CCoderMixer2ST::GetWriteProcessedSize(UInt32 binderIndex) const
+
+UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const
{
- return _streamBinders[binderIndex].ProcessedSize;
+ const CStBinderStream &bs = _binderStreams[bondIndex];
+ if (bs.InStreamSpec)
+ return bs.InStreamSpec->GetSize();
+ return bs.OutStreamSpec->GetSize();
}
-*/
}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.h b/CPP/7zip/Archive/Common/CoderMixer2ST.h
index d35655ba..f2f7c4cb 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2ST.h
+++ b/CPP/7zip/Archive/Common/CoderMixer2ST.h
@@ -3,84 +3,125 @@
#ifndef __CODER_MIXER2_ST_H
#define __CODER_MIXER2_ST_H
-#include "CoderMixer2.h"
#include "../../../Common/MyCom.h"
+
#include "../../ICoder.h"
-namespace NCoderMixer {
-
-// SetBindInfo()
-// for each coder
-// {
-// AddCoder[2]()
-// }
-//
-// for each file
-// {
-// ReInit()
-// for each coder
-// {
-// SetCoderInfo
-// }
-// SetProgressIndex(UInt32 coderIndex);
-// Code
-// }
-
-struct CSTCoderInfo: public CCoderInfo2
+#include "CoderMixer2.h"
+
+class CSequentialInStreamCalcSize:
+ public ISequentialInStream,
+ public CMyUnknownImp
{
- bool IsMain;
- CSTCoderInfo(UInt32 numInStreams, UInt32 numOutStreams, bool isMain):
- CCoderInfo2(numInStreams, numOutStreams), IsMain(isMain) {}
+public:
+ MY_UNKNOWN_IMP1(ISequentialInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+private:
+ CMyComPtr<ISequentialInStream> _stream;
+ UInt64 _size;
+ bool _wasFinished;
+public:
+ void SetStream(ISequentialInStream *stream) { _stream = stream; }
+ void Init()
+ {
+ _size = 0;
+ _wasFinished = false;
+ }
+ void ReleaseStream() { _stream.Release(); }
+ UInt64 GetSize() const { return _size; }
+ bool WasFinished() const { return _wasFinished; }
};
-class CCoderMixer2ST:
- public ICompressCoder2,
- public CCoderMixer2,
+
+class COutStreamCalcSize:
+ public ISequentialOutStream,
+ public IOutStreamFlush,
public CMyUnknownImp
{
- MY_UNKNOWN_IMP
-
- HRESULT GetInStream(
- ISequentialInStream **inStreams, const UInt64 **inSizes,
- UInt32 streamIndex, ISequentialInStream **inStreamRes);
- HRESULT GetOutStream(
- ISequentialOutStream **outStreams, const UInt64 **outSizes,
- UInt32 streamIndex, ISequentialOutStream **outStreamRes);
+ CMyComPtr<ISequentialOutStream> _stream;
+ UInt64 _size;
public:
- STDMETHOD(Code)(ISequentialInStream **inStreams,
- const UInt64 **inSizes,
- UInt32 numInStreams,
- ISequentialOutStream **outStreams,
- const UInt64 **outSizes,
- UInt32 numOutStreams,
- ICompressProgressInfo *progress);
+ MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFlush)
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Flush)();
+
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void ReleaseStream() { _stream.Release(); }
+ void Init() { _size = 0; }
+ UInt64 GetSize() const { return _size; }
+};
- CCoderMixer2ST();
- ~CCoderMixer2ST();
- void AddCoderCommon(bool isMain);
- void AddCoder(ICompressCoder *coder, bool isMain);
- void AddCoder2(ICompressCoder2 *coder, bool isMain);
- void ReInit();
- void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)
- {
- { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }
- }
- void SetProgressCoderIndex(UInt32 /*coderIndex*/)
- {
- // _progressCoderIndex = coderIndex;
- }
+namespace NCoderMixer2 {
- // UInt64 GetWriteProcessedSize(UInt32 binderIndex) const;
+struct CCoderST: public CCoder
+{
+ bool CanRead;
+ bool CanWrite;
+
+ CCoderST(): CanRead(false), CanWrite(false) {}
+};
+
+
+struct CStBinderStream
+{
+ CSequentialInStreamCalcSize *InStreamSpec;
+ COutStreamCalcSize *OutStreamSpec;
+ CMyComPtr<IUnknown> StreamRef;
+
+ CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {}
+};
+
+
+class CMixerST:
+ public IUnknown,
+ public CMixer,
+ public CMyUnknownImp
+{
+ HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 outStreamIndex, ISequentialInStream **inStreamRes);
+ HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 inStreamIndex, ISequentialInStream **inStreamRes);
+ HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
+ UInt32 outStreamIndex, ISequentialOutStream **outStreamRes);
+
+ HRESULT FlushStream(UInt32 streamIndex);
+ HRESULT FlushCoder(UInt32 coderIndex);
-private:
- CBindInfo _bindInfo;
- CObjectVector<CSTCoderInfo> _coders;
- int _mainCoderIndex;
public:
- HRESULT SetBindInfo(const CBindInfo &bindInfo);
+ CObjectVector<CCoderST> _coders;
+
+ CObjectVector<CStBinderStream> _binderStreams;
+
+ MY_UNKNOWN_IMP
+
+ CMixerST(bool encodeMode);
+ ~CMixerST();
+
+ virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter);
+
+ virtual CCoder &GetCoder(unsigned index);
+
+ virtual void SelectMainCoder(bool useFirst);
+
+ virtual void ReInit();
+
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
+ { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
+
+ virtual HRESULT Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress);
+
+ virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
+ HRESULT GetMainUnpackStream(
+ ISequentialInStream * const *inStreams,
+ ISequentialInStream **inStreamRes);
};
}
diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.h b/CPP/7zip/Archive/Common/CoderMixerMT.h
index 9491a965..d2891b26 100644
--- a/CPP/7zip/Archive/Common/CoderMixerMT.h
+++ b/CPP/7zip/Archive/Common/CoderMixerMT.h
@@ -18,7 +18,7 @@ struct CCoder: public CCoderInfo, public CVirtThread
virtual void Execute();
void Code(ICompressProgressInfo *progress);
- ~CCoder() { CVirtThread::WaitThreadFinish(); }
+ virtual ~CCoder() { CVirtThread::WaitThreadFinish(); }
};
/*
diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp
index 18ad5580..9c11b31d 100644
--- a/CPP/7zip/Archive/Common/HandlerOut.cpp
+++ b/CPP/7zip/Archive/Common/HandlerOut.cpp
@@ -29,6 +29,7 @@ void CMultiMethodProps::SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo
UInt32 level = _level;
if (level != (UInt32)(Int32)-1)
SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);
+
#ifndef _7ZIP_ST
SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
#endif
@@ -41,6 +42,8 @@ void CMultiMethodProps::Init()
#endif
_level = (UInt32)(Int32)-1;
+ _analysisLevel = -1;
+
_autoFilter = true;
_crcSize = 4;
_filterMethod.Clear();
@@ -60,8 +63,17 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
_level = 9;
return ParsePropToUInt32(name, value, _level);
}
+
+ if (name.IsPrefixedBy_Ascii_NoCase("yx"))
+ {
+ name.Delete(0, 2);
+ UInt32 v = 9;
+ RINOK(ParsePropToUInt32(name, value, v));
+ _analysisLevel = (int)v;
+ return S_OK;
+ }
- if (name == L"crc")
+ if (name.IsEqualTo("crc"))
{
name.Delete(0, 3);
_crcSize = 4;
@@ -73,11 +85,12 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
UString realName = name.Ptr(index);
if (index == 0)
{
- if (name.IsPrefixedBy(L"mt"))
+ if (name.IsPrefixedBy_Ascii_NoCase("mt"))
{
#ifndef _7ZIP_ST
RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));
#endif
+
return S_OK;
}
if (name.IsEqualTo("f"))
@@ -87,7 +100,7 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
return res;
if (value.vt != VT_BSTR)
return E_INVALIDARG;
- return _filterMethod.ParseMethodFromPROPVARIANT(L"", value);
+ return _filterMethod.ParseMethodFromPROPVARIANT(UString(), value);
}
number = 0;
}
@@ -101,14 +114,15 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
void CSingleMethodProps::Init()
{
Clear();
+ _level = (UInt32)(Int32)-1;
+
#ifndef _7ZIP_ST
_numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors();
- AddNumThreadsProp(_numThreads);
+ AddProp_NumThreads(_numThreads);
#endif
- _level = (UInt32)(Int32)-1;
}
-HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
Init();
for (UInt32 i = 0; i < numProps; i++)
@@ -123,13 +137,13 @@ HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIA
UInt32 a = 9;
RINOK(ParsePropToUInt32(name.Ptr(1), value, a));
_level = a;
- AddLevelProp(a);
+ AddProp_Level(a);
}
- else if (name.IsPrefixedBy(L"mt"))
+ else if (name.IsPrefixedBy_Ascii_NoCase("mt"))
{
#ifndef _7ZIP_ST
RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));
- AddNumThreadsProp(_numThreads);
+ AddProp_NumThreads(_numThreads);
#endif
}
else
diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h
index 40a4a698..5a18d980 100644
--- a/CPP/7zip/Archive/Common/HandlerOut.h
+++ b/CPP/7zip/Archive/Common/HandlerOut.h
@@ -10,6 +10,7 @@ namespace NArchive {
class CMultiMethodProps
{
UInt32 _level;
+ int _analysisLevel;
public:
#ifndef _7ZIP_ST
UInt32 _numThreads;
@@ -37,6 +38,7 @@ public:
}
int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
+ int GetAnalysisLevel() const { return _analysisLevel; }
void Init();
@@ -57,7 +59,7 @@ public:
void Init();
CSingleMethodProps() { Init(); }
int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
- HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
};
}
diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
index 0526c1b1..77252938 100644
--- a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
+++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
@@ -10,9 +10,9 @@ STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *pr
if (_stream)
result = _stream->Write(data, size, &size);
if (_calculate)
- _sha.Update((const Byte *)data, size);
+ Sha1_Update(&_sha, (const Byte *)data, size);
_size += size;
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = size;
return result;
}
diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.h b/CPP/7zip/Archive/Common/OutStreamWithSha1.h
index 3bbfbbe1..41a84cd6 100644
--- a/CPP/7zip/Archive/Common/OutStreamWithSha1.h
+++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.h
@@ -3,7 +3,7 @@
#ifndef __OUT_STREAM_WITH_SHA1_H
#define __OUT_STREAM_WITH_SHA1_H
-#include "../../Crypto/Sha1.h"
+#include "../../../../C/Sha1.h"
#include "../../../Common/MyCom.h"
@@ -15,7 +15,7 @@ class COutStreamWithSha1:
{
CMyComPtr<ISequentialOutStream> _stream;
UInt64 _size;
- NCrypto::NSha1::CContext _sha;
+ CSha1 _sha;
bool _calculate;
public:
MY_UNKNOWN_IMP
@@ -26,11 +26,11 @@ public:
{
_size = 0;
_calculate = calculate;
- _sha.Init();
+ Sha1_Init(&_sha);
}
- void InitSha1() { _sha.Init(); }
+ void InitSha1() { Sha1_Init(&_sha); }
UInt64 GetSize() const { return _size; }
- void Final(Byte *digest) { _sha.Final(digest); }
+ void Final(Byte *digest) { Sha1_Final(&_sha, digest); }
};
#endif
diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp
index 431d315d..2436fb5e 100644
--- a/CPP/7zip/Archive/CpioHandler.cpp
+++ b/CPP/7zip/Archive/CpioHandler.cpp
@@ -87,7 +87,7 @@ enum EType
k_Type_HexCrc
};
-static const char *k_Types[] =
+static const char * const k_Types[] =
{
"Binary LE"
, "Binary BE"
@@ -396,11 +396,10 @@ HRESULT CInArchive::GetNextItem(CItem &item, EErrorType &errorType)
return S_FALSE;
if (nameSize == 0 || nameSize >= kNameSizeMax)
return S_OK;
- char *s = item.Name.GetBuffer(nameSize);
+ char *s = item.Name.GetBuf(nameSize);
size_t processedSize = nameSize;
RINOK(Read(s, &processedSize));
- s[nameSize] = 0;
- item.Name.ReleaseBuffer();
+ item.Name.ReleaseBuf_CalcLen(nameSize);
if (processedSize != nameSize)
{
errorType = k_ErrorType_UnexpectedEnd;
@@ -451,7 +450,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
NCOM::CPropVariant prop;
switch (propID)
{
- case kpidSubType: prop = k_Types[_Type]; break;
+ case kpidSubType: prop = k_Types[(unsigned)_Type]; break;
case kpidPhySize: prop = _phySize; break;
case kpidErrorFlags:
{
@@ -780,20 +779,16 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Cpio", "cpio", 0, 0xED,
- 3 + 5 + 2 + 2,
- {
+static const Byte k_Signature[] = {
5, '0', '7', '0', '7', '0',
2, kMagicBin0, kMagicBin1,
- 2, kMagicBin1, kMagicBin0,
- },
+ 2, kMagicBin1, kMagicBin0 };
+
+REGISTER_ARC_I(
+ "Cpio", "cpio", 0, 0xED,
+ k_Signature,
0,
NArcInfoFlags::kMultiSignature,
- CreateArc, NULL, IsArc_Cpio };
-
-REGISTER_ARC(Cpio)
+ IsArc_Cpio)
}}
diff --git a/CPP/7zip/Archive/CramfsHandler.cpp b/CPP/7zip/Archive/CramfsHandler.cpp
index 3764f1af..e776b3c7 100644
--- a/CPP/7zip/Archive/CramfsHandler.cpp
+++ b/CPP/7zip/Archive/CramfsHandler.cpp
@@ -26,8 +26,7 @@ namespace NCramfs {
#define SIGNATURE { 'C','o','m','p','r','e','s','s','e','d',' ','R','O','M','F','S' }
-static const UInt32 kSignatureSize = 16;
-static const char kSignature[kSignatureSize] = SIGNATURE;
+static const Byte kSignature[] = SIGNATURE;
static const UInt32 kArcSizeMax = (256 + 16) << 20;
static const UInt32 kNumFilesMax = (1 << 19);
@@ -55,7 +54,7 @@ static const unsigned k_Flags_Method_Mask = 3;
#define k_Flags_Method_ZLIB 1
#define k_Flags_Method_LZMA 2
-static const char *k_Methods[] =
+static const char * const k_Methods[] =
{
"Copy"
, "ZLIB"
@@ -145,7 +144,7 @@ struct CHeader
bool Parse(const Byte *p)
{
- if (memcmp(p + 16, kSignature, kSignatureSize) != 0)
+ if (memcmp(p + 16, kSignature, ARRAY_SIZE(kSignature)) != 0)
return false;
switch(GetUi32(p))
{
@@ -408,7 +407,7 @@ AString CHandler::GetPath(int index) const
len--;
AString path;
- char *dest = path.GetBuffer(len) + len;
+ char *dest = path.GetBuf_SetEnd(len) + len;
index = indexMem;
for (;;)
{
@@ -425,7 +424,6 @@ AString CHandler::GetPath(int index) const
break;
*(--dest) = CHAR_PATH_SEPARATOR;
}
- path.ReleaseBuffer(len);
return path;
}
@@ -565,10 +563,6 @@ HRESULT CCramfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSi
return Handler->ReadBlock(blockIndex, dest, blockSize);
}
-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
-static void SzFree(void *p, void *address) { p = p; MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
-
HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
{
if (_method == k_Flags_Method_ZLIB)
@@ -789,15 +783,11 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "CramFS", "cramfs", 0, 0xD3,
- kSignatureSize, SIGNATURE,
+REGISTER_ARC_I(
+ "CramFS", "cramfs", 0, 0xD3,
+ kSignature,
16,
0,
- CreateArc };
-
-REGISTER_ARC(Cramfs)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/DllExports.cpp b/CPP/7zip/Archive/DllExports.cpp
index 37f53cd7..7aee235e 100644
--- a/CPP/7zip/Archive/DllExports.cpp
+++ b/CPP/7zip/Archive/DllExports.cpp
@@ -13,10 +13,13 @@
#include "../../Windows/NtCheck.h"
#include "../../Windows/PropVariant.h"
-#include "IArchive.h"
#include "../ICoder.h"
#include "../IPassword.h"
+#include "../Common/CreateCoder.h"
+
+#include "IArchive.h"
+
HINSTANCE g_hInstance;
#define NT_CHECK_FAIL_ACTION return FALSE;
@@ -33,7 +36,10 @@ BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
}
DEFINE_GUID(CLSID_CArchiveHandler,
-0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
+ k_7zip_GUID_Data1,
+ k_7zip_GUID_Data2,
+ k_7zip_GUID_Data3_Common,
+ 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject);
@@ -49,3 +55,40 @@ STDAPI SetLargePageMode()
#endif
return S_OK;
}
+
+extern bool g_CaseSensitive;
+
+STDAPI SetCaseSensitive(Int32 caseSensitive)
+{
+ g_CaseSensitive = (caseSensitive != 0);
+ return S_OK;
+}
+
+#ifdef EXTERNAL_CODECS
+
+CExternalCodecs g_ExternalCodecs;
+
+STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo)
+{
+ COM_TRY_BEGIN
+
+ // OutputDebugStringA(compressCodecsInfo ? "SetCodecs" : "SetCodecs NULL");
+ if (compressCodecsInfo)
+ {
+ g_ExternalCodecs.GetCodecs = compressCodecsInfo;
+ return g_ExternalCodecs.Load();
+ }
+ g_ExternalCodecs.ClearAndRelease();
+ return S_OK;
+
+ COM_TRY_END
+}
+
+#else
+
+STDAPI SetCodecs(ICompressCodecsInfo *)
+{
+ return S_OK;
+}
+
+#endif
diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp
index aa023524..2b196abe 100644
--- a/CPP/7zip/Archive/DllExports2.cpp
+++ b/CPP/7zip/Archive/DllExports2.cpp
@@ -16,6 +16,8 @@
#include "../ICoder.h"
#include "../IPassword.h"
+#include "../Common/CreateCoder.h"
+
#include "IArchive.h"
HINSTANCE g_hInstance;
@@ -33,23 +35,28 @@ BOOL WINAPI DllMain(
{
if (dwReason == DLL_PROCESS_ATTACH)
{
+ // OutputDebugStringA("7z.dll DLL_PROCESS_ATTACH");
g_hInstance = (HINSTANCE)hInstance;
NT_CHECK;
}
+ /*
+ if (dwReason == DLL_PROCESS_DETACH)
+ {
+ OutputDebugStringA("7z.dll DLL_PROCESS_DETACH");
+ }
+ */
return TRUE;
}
DEFINE_GUID(CLSID_CArchiveHandler,
-0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
-
-static const UInt16 kDecodeId = 0x2790;
-
-DEFINE_GUID(CLSID_CCodec,
-0x23170F69, 0x40C1, kDecodeId, 0, 0, 0, 0, 0, 0, 0, 0);
+ k_7zip_GUID_Data1,
+ k_7zip_GUID_Data2,
+ k_7zip_GUID_Data3_Common,
+ 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);
STDAPI CreateHasher(const GUID *clsid, IHasher **hasher);
-STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject);
+STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject);
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
{
@@ -80,3 +87,32 @@ STDAPI SetCaseSensitive(Int32 caseSensitive)
g_CaseSensitive = (caseSensitive != 0);
return S_OK;
}
+
+#ifdef EXTERNAL_CODECS
+
+CExternalCodecs g_ExternalCodecs;
+
+STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo)
+{
+ COM_TRY_BEGIN
+
+ // OutputDebugStringA(compressCodecsInfo ? "SetCodecs" : "SetCodecs NULL");
+ if (compressCodecsInfo)
+ {
+ g_ExternalCodecs.GetCodecs = compressCodecsInfo;
+ return g_ExternalCodecs.Load();
+ }
+ g_ExternalCodecs.ClearAndRelease();
+ return S_OK;
+
+ COM_TRY_END
+}
+
+#else
+
+STDAPI SetCodecs(ICompressCodecsInfo *)
+{
+ return S_OK;
+}
+
+#endif
diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp
index 7166f2ce..208f2a82 100644
--- a/CPP/7zip/Archive/DmgHandler.cpp
+++ b/CPP/7zip/Archive/DmgHandler.cpp
@@ -48,6 +48,7 @@ static Byte *Base64ToBin(Byte *dest, const char *src)
{
UInt32 val = 1;
UInt32 c = k_Base64Table[(Byte)(*src++)];
+
for (;;)
{
/*
@@ -88,12 +89,14 @@ static Byte *Base64ToBin(Byte *dest, const char *src)
break;
c = k_Base64Table[(Byte)(*src++)];
}
+
if (val >= ((UInt32)1 << 12))
{
if (val >= ((UInt32)1 << 18))
*dest++ = (Byte)(val >> 16);
*dest++ = (Byte)(val);
}
+
return dest;
}
@@ -195,7 +198,8 @@ public:
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
};
-const UInt32 kXmlSizeMax = ((UInt32)1 << 31) - (1 << 14);
+// that limit can be increased, if there are such dmg files
+static const size_t kXmlSizeMax = 0xFFFF0000; // 4 GB - 64 KB;
struct CMethods
{
@@ -216,7 +220,9 @@ void CMethods::Update(const CFile &file)
void CMethods::GetString(AString &res) const
{
res.Empty();
+
unsigned i;
+
for (i = 0; i < Types.Size(); i++)
{
UInt32 type = Types[i];
@@ -234,10 +240,10 @@ void CMethods::GetString(AString &res) const
case METHOD_BZIP2: s = "BZip2"; break;
default: ConvertUInt32ToString(type, buf); s = buf;
}
- if (!res.IsEmpty())
- res += ' ';
+ res.Add_Space_if_NotEmpty();
res += s;
}
+
for (i = 0; i < ChecksumTypes.Size(); i++)
{
UInt32 type = ChecksumTypes[i];
@@ -250,8 +256,7 @@ void CMethods::GetString(AString &res) const
ConvertUInt32ToString(type, MyStpCpy(buf, "Check"));
s = buf;
}
- if (!res.IsEmpty())
- res += ' ';
+ res.Add_Space_if_NotEmpty();
res += s;
}
}
@@ -325,8 +330,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidMainSubfile:
{
int mainIndex = -1;
- int numFS = 0;
- int numUnknown = 0;
+ unsigned numFS = 0;
+ unsigned numUnknown = 0;
FOR_VECTOR (i, _files)
{
const AString &name = _files[i].Name;
@@ -334,7 +339,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
for (n = 0; n < kNumAppleNames; n++)
{
const CAppleName &appleName = k_Names[n];
- if (name.Find(appleName.AppleName) >= 0)
+ // if (name.Find(appleName.AppleName) >= 0)
+ if (strstr(name, appleName.AppleName))
{
if (appleName.IsFs)
{
@@ -404,6 +410,7 @@ HRESULT CFile::Parse(const Byte *p, UInt32 size)
p += kHeadSize;
UInt32 i;
+
for (i = 0; i < numBlocks; i++, p += kRecordSize)
{
CBlock b;
@@ -426,6 +433,7 @@ HRESULT CFile::Parse(const Byte *p, UInt32 size)
if (b.Type == METHOD_END)
break;
PackSize += b.PackSize;
+
if (b.UnpSize != 0)
{
if (b.Type == METHOD_ZERO_2)
@@ -433,12 +441,14 @@ HRESULT CFile::Parse(const Byte *p, UInt32 size)
Blocks.AddInReserved(b);
}
}
+
if (i != numBlocks - 1)
return S_FALSE;
if (!Blocks.IsEmpty())
Size = Blocks.Back().GetNextUnpPos();
if (Size != (numSectors << 9))
return S_FALSE;
+
return S_OK;
}
@@ -463,8 +473,12 @@ static const AString *GetStringFromKeyPair(const CXmlItem &item, const AString &
static const unsigned HEADER_SIZE = 0x200;
-static bool IsKoly(const Byte *p)
+static const Byte k_Signature[] = { 'k','o','l','y', 0, 0, 0, 4, 0, 0, 2, 0 };
+
+static inline bool IsKoly(const Byte *p)
{
+ return memcmp(p, k_Signature, ARRAY_SIZE(k_Signature)) == 0;
+ /*
if (Get32(p) != 0x6B6F6C79) // "koly" signature
return false;
if (Get32(p + 4) != 4) // version
@@ -472,6 +486,7 @@ static bool IsKoly(const Byte *p)
if (Get32(p + 8) != HEADER_SIZE)
return false;
return true;
+ */
}
HRESULT CHandler::Open2(IInStream *stream)
@@ -510,6 +525,14 @@ HRESULT CHandler::Open2(IInStream *stream)
UInt64 xmlOffset = Get64(buf + 0xD8);
UInt64 xmlLen = Get64(buf + 0xE0);
+ if ( headerPos < dataForkOffset
+ || headerPos - dataForkOffset < dataForkLen
+ || headerPos < rsrcOffset
+ || headerPos - rsrcOffset < rsrcLen
+ || headerPos < xmlOffset
+ || headerPos - xmlOffset < xmlLen)
+ return S_FALSE;
+
UInt64 totalLen = dataForkLen + rsrcLen + xmlLen;
if (totalLen > headerPos)
return S_FALSE;
@@ -517,14 +540,6 @@ HRESULT CHandler::Open2(IInStream *stream)
_phySize = totalLen + HEADER_SIZE;
headerPos = totalLen;
- if (headerPos < dataForkOffset ||
- headerPos < dataForkOffset + dataForkLen ||
- headerPos < rsrcOffset ||
- headerPos < rsrcOffset + rsrcLen ||
- headerPos < xmlOffset ||
- headerPos < xmlOffset + xmlLen)
- return S_FALSE;
-
// Byte reserved[0x78]
CChecksum masterChecksum;
@@ -620,9 +635,7 @@ HRESULT CHandler::Open2(IInStream *stream)
ConvertUInt32ToString(_files.Size(), extraName);
extra.Name = extraName;
}
- CByteBuffer &rawBuf = extra.Data;
- rawBuf.SetCapacity(blockSize);
- memcpy(rawBuf, pBlock + 4, blockSize);
+ extra.Data.CopyFrom(pBlock + 4, blockSize);
}
#endif
@@ -638,10 +651,10 @@ HRESULT CHandler::Open2(IInStream *stream)
return S_FALSE;
for (UInt32 r = 1; r <= nameLen; r++)
{
- char c = namePtr[r];
+ Byte c = namePtr[r];
if (c < 0x20 || c >= 0x80)
break;
- file.Name += c;
+ file.Name += (char)c;
}
}
RINOK(file.Parse(pBlock + 4, blockSize));
@@ -652,36 +665,28 @@ HRESULT CHandler::Open2(IInStream *stream)
{
if (xmlLen >= kXmlSizeMax || xmlLen == 0)
return S_FALSE;
- RINOK(stream->Seek(_startPos + dataForkLen, STREAM_SEEK_SET, NULL));
size_t size = (size_t)xmlLen;
+ if (size != xmlLen)
+ return S_FALSE;
+
+ RINOK(stream->Seek(_startPos + dataForkLen, STREAM_SEEK_SET, NULL));
CXml xml;
{
- AString xmlStr;
- char *ss = xmlStr.GetBuffer((int)size + 1);
- RINOK(ReadStream_FALSE(stream, ss, size));
- ss[size] = 0;
- {
- const char *p = ss;
- for (;;)
- {
- if (*p == 0) break; p++;
- if (*p == 0) break; p++;
- if (*p == 0) break; p++;
- if (*p == 0) break; p++;
- }
- xmlStr.ReleaseBuffer((int)(p - ss));
- }
+ CObjArray<char> xmlStr(size + 1);
+ RINOK(ReadStream_FALSE(stream, xmlStr, size));
+ xmlStr[size] = 0;
+ // if (strlen(xmlStr) != size) return S_FALSE;
if (!xml.Parse(xmlStr))
return S_FALSE;
#ifdef DMG_SHOW_RAW
CExtraFile &extra = _extras.AddNew();
extra.Name = "a.xml";
- extra.Data.SetCapacity(size);
- memcpy(extra.Data, ss, size);
+ extra.Data.CopyFrom((const Byte *)(const char *)xmlStr, size);
#endif
}
+
if (xml.Root.Name != "plist")
return S_FALSE;
@@ -708,14 +713,14 @@ HRESULT CHandler::Open2(IInStream *stream)
continue;
CByteBuffer rawBuf;
- int destLen = 0;
+ unsigned destLen = 0;
{
const AString *dataString = GetStringFromKeyPair(item, "Data", "data");
if (!dataString)
return S_FALSE;
destLen = dataString->Len() / 4 * 3 + 4;
rawBuf.Alloc(destLen);
- destLen = (int)(Base64ToBin(rawBuf, *dataString) - rawBuf);
+ destLen = (unsigned)(Base64ToBin(rawBuf, *dataString) - rawBuf);
#ifdef DMG_SHOW_RAW
CExtraFile &extra = _extras.AddNew();
{
@@ -723,8 +728,7 @@ HRESULT CHandler::Open2(IInStream *stream)
ConvertUInt32ToString(_files.Size(), extraName);
extra.Name = extraName;
}
- extra.Data.SetCapacity(destLen);
- memcpy(extra.Data, rawBuf, destLen);
+ extra.Data.CopyFrom(rawBuf, destLen);
#endif
}
CFile &file = _files.AddNew();
@@ -805,7 +809,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
NWindows::NCOM::CPropVariant prop;
#ifdef DMG_SHOW_RAW
- if ((int)index >= _files.Size())
+ if (index >= _files.Size())
{
const CExtraFile &extra = _extras[index - _files.Size()];
switch (propID)
@@ -897,7 +901,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
UString name2;
ConvertUTF8ToUnicode(item.Name, name2);
if (!name2.IsEmpty())
- name += L" - ";
+ name.AddAscii(" - ");
name += name2;
}
prop = name;
@@ -1060,9 +1064,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
return S_OK;
UInt64 totalSize = 0;
UInt32 i;
+
for (i = 0; i < numItems; i++)
{
- int index = (int)(allFilesMode ? i : indices[i]);
+ UInt32 index = (allFilesMode ? i : indices[i]);
#ifdef DMG_SHOW_RAW
if (index >= _files.Size())
totalSize += _extras[index - _files.Size()].Data.Size();
@@ -1112,7 +1117,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
- Int32 index = allFilesMode ? i : indices[i];
+ UInt32 index = allFilesMode ? i : indices[i];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
if (!testMode && !realOutStream)
@@ -1225,6 +1230,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
opRes = NExtract::NOperationResult::kUnsupportedMethod;
break;
}
+
if (res != S_OK)
{
if (res != S_FALSE)
@@ -1232,7 +1238,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (opRes == NExtract::NOperationResult::kOK)
opRes = NExtract::NOperationResult::kDataError;
}
+
unpPos += block.UnpSize;
+
if (!outStreamSpec->IsFinishedOK())
{
if (realMethod && opRes == NExtract::NOperationResult::kOK)
@@ -1247,6 +1255,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
}
}
+
if (needCrc && opRes == NExtract::NOperationResult::kOK)
{
if (outCrcStreamSpec->GetCRC() != item.Checksum.GetCrc32())
@@ -1256,6 +1265,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
outStream.Release();
RINOK(extractCallback->SetOperationResult(opRes));
}
+
return S_OK;
COM_TRY_END
}
@@ -1322,12 +1332,12 @@ public:
};
-int FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos)
+unsigned FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos)
{
- int left = 0, right = blocks.Size();
+ unsigned left = 0, right = blocks.Size();
for (;;)
{
- int mid = (left + right) / 2;
+ unsigned mid = (left + right) / 2;
if (mid == left)
return left;
if (pos < blocks[mid].UnpPos)
@@ -1359,23 +1369,27 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
if (_virtPos < block.UnpPos || (_virtPos - block.UnpPos) >= block.UnpSize)
_latestBlock = -1;
}
+
if (_latestBlock < 0)
{
_latestChunk = -1;
- int blockIndex = FindBlock(File->Blocks, _virtPos);
+ unsigned blockIndex = FindBlock(File->Blocks, _virtPos);
const CBlock &block = File->Blocks[blockIndex];
+
if (!block.IsZeroMethod() && block.Type != METHOD_COPY)
{
unsigned i;
for (i = 0; i < _chunks.Size(); i++)
- if (_chunks[i].BlockIndex == blockIndex)
+ if (_chunks[i].BlockIndex == (int)blockIndex)
break;
+
if (i != _chunks.Size())
_latestChunk = i;
else
{
- const int kNumChunksMax = 128;
- int chunkIndex;
+ const unsigned kNumChunksMax = 128;
+ unsigned chunkIndex;
+
if (_chunks.Size() != kNumChunksMax)
chunkIndex = _chunks.Add(CChunk());
else
@@ -1385,9 +1399,11 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
if (_chunks[i].AccessMark < _chunks[chunkIndex].AccessMark)
chunkIndex = i;
}
+
CChunk &chunk = _chunks[chunkIndex];
chunk.BlockIndex = -1;
chunk.AccessMark = 0;
+
if (chunk.Buf.Size() < block.UnpSize)
{
chunk.Buf.Free();
@@ -1395,12 +1411,14 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
return E_FAIL;
chunk.Buf.Alloc((size_t)block.UnpSize);
}
+
outStreamSpec->Init(chunk.Buf, (size_t)block.UnpSize);
RINOK(Stream->Seek(_startPos + File->StartPos + block.PackPos, STREAM_SEEK_SET, NULL));
limitedStreamSpec->Init(block.PackSize);
HRESULT res = S_OK;
+
switch (block.Type)
{
case METHOD_COPY:
@@ -1443,6 +1461,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
default:
return E_FAIL;
}
+
if (res != S_OK)
return res;
if (block.Type != METHOD_COPY && outStreamSpec->GetPos() != block.UnpSize)
@@ -1450,8 +1469,10 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
chunk.BlockIndex = blockIndex;
_latestChunk = chunkIndex;
}
+
_chunks[_latestChunk].AccessMark = _accessMark++;
}
+
_latestBlock = blockIndex;
}
@@ -1462,6 +1483,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
size = (UInt32)rem;
HRESULT res = S_OK;
+
if (block.Type == METHOD_COPY)
{
RINOK(Stream->Seek(_startPos + File->StartPos + block.PackPos + offset, STREAM_SEEK_SET, NULL));
@@ -1469,11 +1491,13 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
}
else if (block.IsZeroMethod())
memset(data, 0, size);
- else
+ else if (size != 0)
memcpy(data, _chunks[_latestChunk].Buf + offset, size);
+
_virtPos += size;
if (processedSize)
*processedSize = size;
+
return res;
COM_TRY_END
}
@@ -1498,14 +1522,17 @@ STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPositio
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{
COM_TRY_BEGIN
+
#ifdef DMG_SHOW_RAW
if (index >= (UInt32)_files.Size())
return S_FALSE;
#endif
+
CInStream *spec = new CInStream;
CMyComPtr<ISequentialInStream> specStream = spec;
spec->File = &_files[index];
const CFile &file = *spec->File;
+
FOR_VECTOR (i, file.Blocks)
{
const CBlock &block = file.Blocks[i];
@@ -1523,24 +1550,22 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
return S_FALSE;
}
}
+
spec->Stream = _inStream;
spec->Size = spec->File->Size;
RINOK(spec->InitAndSeek(_startPos));
*stream = specStream.Detach();
return S_OK;
+
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Dmg", "dmg", 0, 0xE4,
- 12, { 'k','o','l','y', 0, 0, 0, 4, 0, 0, 2, 0 },
+REGISTER_ARC_I(
+ "Dmg", "dmg", 0, 0xE4,
+ k_Signature,
0,
NArcInfoFlags::kBackwardOpen |
NArcInfoFlags::kUseGlobalOffset,
- CreateArc };
-
-REGISTER_ARC(Dmg)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp
index 5e378ba8..089d1023 100644
--- a/CPP/7zip/Archive/ElfHandler.cpp
+++ b/CPP/7zip/Archive/ElfHandler.cpp
@@ -963,15 +963,13 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail)
return S_OK;
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 0x7F, 'E', 'L', 'F' };
-static CArcInfo g_ArcInfo =
- { "ELF", "elf", 0, 0xDE,
- 4, { 0x7F, 'E', 'L', 'F' },
+REGISTER_ARC_I(
+ "ELF", "elf", 0, 0xDE,
+ k_Signature,
0,
NArcInfoFlags::kPreArc,
- CreateArc };
-
-REGISTER_ARC(Elf)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp
index 970330cc..649d54bd 100644
--- a/CPP/7zip/Archive/FatHandler.cpp
+++ b/CPP/7zip/Archive/FatHandler.cpp
@@ -272,19 +272,27 @@ struct CItem
UString GetVolName() const;
};
-static int CopyAndTrim(char *dest, const char *src, int size, bool toLower)
+static unsigned CopyAndTrim(char *dest, const char *src, unsigned size, bool toLower)
{
- int i;
memcpy(dest, src, size);
if (toLower)
- for (i = 0; i < size; i++)
+ {
+ for (unsigned i = 0; i < size; i++)
{
char c = dest[i];
if (c >= 'A' && c <= 'Z')
dest[i] = (char)(c + 0x20);
}
- for (i = size - 1; i >= 0 && dest[i] == ' '; i--);
- return i + 1;
+ }
+
+ for (unsigned i = size;;)
+ {
+ if (i == 0)
+ return 0;
+ if (dest[i - 1] != ' ')
+ return i;
+ i--;
+ }
}
static UString FatStringToUnicode(const char *s)
@@ -295,11 +303,11 @@ static UString FatStringToUnicode(const char *s)
UString CItem::GetShortName() const
{
char s[16];
- int i = CopyAndTrim(s, DosName, 8, NameIsLow());
+ unsigned i = CopyAndTrim(s, DosName, 8, NameIsLow());
s[i++] = '.';
- int j = CopyAndTrim(s + i, DosName + 8, 3, ExtIsLow());
+ unsigned j = CopyAndTrim(s + i, DosName + 8, 3, ExtIsLow());
if (j == 0)
- j--;
+ i--;
s[i + j] = 0;
return FatStringToUnicode(s);
}
@@ -316,7 +324,7 @@ UString CItem::GetVolName() const
if (!UName.IsEmpty())
return UName;
char s[12];
- int i = CopyAndTrim(s, DosName, 11, false);
+ unsigned i = CopyAndTrim(s, DosName, 11, false);
s[i] = 0;
return FatStringToUnicode(s);
}
@@ -348,7 +356,7 @@ struct CDatabase
UString GetItemPath(Int32 index) const;
HRESULT Open();
- HRESULT ReadDir(Int32 parent, UInt32 cluster, int level);
+ HRESULT ReadDir(Int32 parent, UInt32 cluster, unsigned level);
UInt64 GetHeadersSize() const
{
@@ -420,9 +428,9 @@ UString CDatabase::GetItemPath(Int32 index) const
}
}
-static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, int numChars)
+static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, unsigned numChars)
{
- for (int i = 0; i < numChars; i++)
+ for (unsigned i = 0; i < numChars; i++)
{
wchar_t c = Get16(p + i * 2);
if (c != 0 && c != 0xFFFF)
@@ -432,9 +440,9 @@ static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, int numChars)
return dest;
}
-HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
+HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level)
{
- int startIndex = Items.Size();
+ unsigned startIndex = Items.Size();
if (startIndex >= (1 << 30) || level > 256)
return S_FALSE;
@@ -451,6 +459,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
UString curName;
int checkSum = -1;
int numLongRecords = -1;
+
for (UInt32 pos = blockSize;; pos += 32)
{
if (pos == blockSize)
@@ -483,7 +492,9 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize));
}
+
const Byte *p = ByteBuf + pos;
+
if (p[0] == 0)
{
/*
@@ -493,6 +504,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
*/
break;
}
+
if (p[0] == 0xE5)
{
if (numLongRecords > 0)
@@ -545,7 +557,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
if (checkSum >= 0)
{
Byte sum = 0;
- for (int i = 0; i < 11; i++)
+ for (unsigned i = 0; i < 11; i++)
sum = (Byte)(((sum & 1) ? 0x80 : 0) + (sum >> 1) + (Byte)item.DosName[i]);
if (sum == checkSum)
item.UName = curName;
@@ -590,8 +602,8 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
}
}
- int finishIndex = Items.Size();
- for (int i = startIndex; i < finishIndex; i++)
+ unsigned finishIndex = Items.Size();
+ for (unsigned i = startIndex; i < finishIndex; i++)
{
const CItem &item = Items[i];
if (item.IsDir())
@@ -831,7 +843,7 @@ static void FatTimeToProp(UInt32 dosTime, UInt32 ms10, NWindows::NCOM::CPropVari
}
/*
-static void StringToProp(const Byte *src, int size, NWindows::NCOM::CPropVariant &prop)
+static void StringToProp(const Byte *src, unsigned size, NWindows::NCOM::CPropVariant &prop)
{
char dest[32];
memcpy(dest, src, size);
@@ -1021,15 +1033,13 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK;
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 0x55, 0xAA };
-static CArcInfo g_ArcInfo =
- { "FAT", "fat img", 0, 0xDA,
- 2, { 0x55, 0xAA },
+REGISTER_ARC_I(
+ "FAT", "fat img", 0, 0xDA,
+ k_Signature,
0x1FE,
0,
- CreateArc, NULL, IsArc_Fat };
-
-REGISTER_ARC(Fat)
+ IsArc_Fat)
}}
diff --git a/CPP/7zip/Archive/FlvHandler.cpp b/CPP/7zip/Archive/FlvHandler.cpp
index 577224b2..dafb250b 100644
--- a/CPP/7zip/Archive/FlvHandler.cpp
+++ b/CPP/7zip/Archive/FlvHandler.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+// #include <stdio.h>
+
#include "../../../C/CpuArch.h"
#include "../../Common/ComTry.h"
@@ -69,12 +71,12 @@ class CHandler:
{
CMyComPtr<IInStream> _stream;
CObjectVector<CItem2> _items2;
- // CByteBuffer _metadata;
+ CByteBuffer _metadata;
bool _isRaw;
UInt64 _phySize;
HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
- AString GetComment();
+ // AString GetComment();
public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive(;)
@@ -195,10 +197,7 @@ AString CHandler::GetComment()
break;
{
AString temp;
- char *sz = temp.GetBuffer(len);
- memcpy(sz, p, len);
- sz[len] = 0;
- temp.ReleaseBuffer();
+ temp.SetFrom_CalcLen((const char *)p, len);
if (!res.IsEmpty())
res += '\n';
res += temp;
@@ -251,7 +250,6 @@ AString CHandler::GetComment()
}
return res;
}
-
*/
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
@@ -413,8 +411,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
src += kTagHeaderSize + 1;
size -= (kTagHeaderSize + 4 + 1);
}
- memcpy(item2.BufSpec->Buf + item2.Size, src, size);
- item2.Size += size;
+ if (size != 0)
+ {
+ memcpy(item2.BufSpec->Buf + item2.Size, src, size);
+ item2.Size += size;
+ }
}
return S_OK;
}
@@ -513,15 +514,13 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 'F', 'L', 'V', 1, };
-static CArcInfo g_ArcInfo =
- { "FLV", "flv", 0, 0xD6,
- 4, { 'F', 'L', 'V', 1, },
+REGISTER_ARC_I(
+ "FLV", "flv", 0, 0xD6,
+ k_Signature,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Flv)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp
index 766cefbf..d8979ada 100644
--- a/CPP/7zip/Archive/GzHandler.cpp
+++ b/CPP/7zip/Archive/GzHandler.cpp
@@ -44,10 +44,10 @@ namespace NGz {
namespace NFlags
{
- const Byte kIsText = 1 << 0;
- const Byte kCrc = 1 << 1;
- const Byte kExtra = 1 << 2;
- const Byte kName = 1 << 3;
+ const Byte kIsText = 1 << 0;
+ const Byte kCrc = 1 << 1;
+ const Byte kExtra = 1 << 2;
+ const Byte kName = 1 << 3;
const Byte kComment = 1 << 4;
const Byte kReserved = 0xE0;
}
@@ -85,7 +85,7 @@ namespace NGz {
};
}
-static const char *kHostOSes[] =
+static const char * const kHostOSes[] =
{
"FAT"
, "AMIGA"
@@ -126,19 +126,44 @@ public:
AString Comment;
// CByteBuffer Extra;
- // bool IsText() const { return TestFlag(NFlags::kIsText); }
- bool HeaderCrcIsPresent() const { return TestFlag(NFlags::kCrc); }
- bool ExtraFieldIsPresent() const { return TestFlag(NFlags::kExtra); }
- bool NameIsPresent() const { return TestFlag(NFlags::kName); }
- bool CommentIsPresent() const { return TestFlag(NFlags::kComment); }
- bool IsSupported() const { return (Flags & NFlags::kReserved) == 0; }
+ CItem():
+ Flags(0),
+ ExtraFlags(0),
+ HostOS(0),
+ Time(0),
+ Crc(0),
+ Size32(0) {}
void Clear()
{
Name.Empty();
Comment.Empty();
- // Extra.SetCapacity(0);
+ // Extra.Free();
+ }
+
+ void CopyMetaPropsFrom(const CItem &a)
+ {
+ Flags = a.Flags;
+ HostOS = a.HostOS;
+ Time = a.Time;
+ Name = a.Name;
+ Comment = a.Comment;
+ // Extra = a.Extra;
+ }
+
+ void CopyDataPropsFrom(const CItem &a)
+ {
+ ExtraFlags = a.ExtraFlags;
+ Crc = a.Crc;
+ Size32 = a.Size32;
}
+
+ // bool IsText() const { return TestFlag(NFlags::kIsText); }
+ bool HeaderCrcIsPresent() const { return TestFlag(NFlags::kCrc); }
+ bool ExtraFieldIsPresent() const { return TestFlag(NFlags::kExtra); }
+ bool NameIsPresent() const { return TestFlag(NFlags::kName); }
+ bool CommentIsPresent() const { return TestFlag(NFlags::kComment); }
+ bool IsSupported() const { return (Flags & NFlags::kReserved) == 0; }
HRESULT ReadHeader(NDecoder::CCOMCoder *stream);
HRESULT ReadFooter1(NDecoder::CCOMCoder *stream);
@@ -459,7 +484,7 @@ public:
INTERFACE_IInArchive(;)
INTERFACE_IOutArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
CHandler()
{
@@ -510,7 +535,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
}
case kpidName:
if (_item.NameIsPresent())
- prop = MultiByteToUnicodeString(_item.Name, CP_ACP) + L".gz";
+ {
+ UString s = MultiByteToUnicodeString(_item.Name, CP_ACP);
+ s.AddAscii(".gz");
+ prop = s;
+ }
break;
}
prop.Detach(value);
@@ -656,7 +685,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG;
- // if (_stream) extractCallback->SetTotal(_packSize);
+ if (_packSize_Defined)
+ extractCallback->SetTotal(_packSize);
// UInt64 currentTotalPacked = 0;
// RINOK(extractCallback->SetCompleted(&currentTotalPacked));
CMyComPtr<ISequentialOutStream> realOutStream;
@@ -794,6 +824,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
result = S_FALSE;
break;
}
+
+ // break; // we can use break, if we need only first stream
}
} catch(const CInBufferException &e) { return e.ErrorCode; }
@@ -844,7 +876,7 @@ static const Byte kHostOS =
static HRESULT UpdateArchive(
ISequentialOutStream *outStream,
UInt64 unpackSize,
- const CItem &newItem,
+ CItem &item,
const CSingleMethodProps &props,
IArchiveUpdateCallback *updateCallback)
{
@@ -865,7 +897,6 @@ static HRESULT UpdateArchive(
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(updateCallback, true);
- CItem item = newItem;
item.ExtraFlags = props.GetLevel() >= 7 ?
NExtraFlags::kMaximum :
NExtraFlags::kFastest;
@@ -894,6 +925,8 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *updateCallback)
{
+ COM_TRY_BEGIN
+
if (numItems != 1)
return E_INVALIDARG;
@@ -903,11 +936,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return E_FAIL;
RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));
- CItem newItem = _item;
- newItem.ExtraFlags = 0;
- newItem.Flags = 0;
- if (IntToBool(newProps))
+ CItem newItem;
+
+ if (!IntToBool(newProps))
+ {
+ newItem.CopyMetaPropsFrom(_item);
+ }
+ else
{
+ newItem.HostOS = kHostOS;
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidMTime, &prop));
@@ -924,9 +961,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (prop.vt == VT_BSTR)
{
UString name = prop.bstrVal;
- int dirDelimiterPos = name.ReverseFind(WCHAR_PATH_SEPARATOR);
- if (dirDelimiterPos >= 0)
- name = name.Ptr(dirDelimiterPos + 1);
+ int slashPos = name.ReverseFind_PathSepar();
+ if (slashPos >= 0)
+ name.DeleteFrontal(slashPos + 1);
newItem.Name = UnicodeStringToMultiByte(name, CP_ACP);
if (!newItem.Name.IsEmpty())
newItem.Flags |= NFlags::kName;
@@ -937,13 +974,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
- if (prop.vt == VT_BOOL)
- {
- if (prop.boolVal != VARIANT_FALSE)
+ if (prop.vt != VT_EMPTY)
+ if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)
return E_INVALIDARG;
- }
- else if (prop.vt != VT_EMPTY)
- return E_INVALIDARG;
}
}
@@ -959,13 +992,28 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
}
return UpdateArchive(outStream, size, newItem, _props, updateCallback);
}
-
+
if (indexInArchive != 0)
return E_INVALIDARG;
if (!_stream)
return E_NOTIMPL;
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(updateCallback, true);
+
+ CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
+ updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
+ if (opCallback)
+ {
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kInArcIndex, 0,
+ NUpdateNotifyOp::kReplicate))
+ }
+
+ newItem.CopyDataPropsFrom(_item);
+
UInt64 offset = 0;
if (IntToBool(newProps))
{
@@ -973,24 +1021,24 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
offset += _headerSize;
}
RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));
- return NCompress::CopyStream(_stream, outStream, NULL);
+
+ return NCompress::CopyStream(_stream, outStream, progress);
+
+ COM_TRY_END
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
return _props.SetProperties(names, values, numProps);
}
-IMP_CreateArcIn
-IMP_CreateArcOut
+static const Byte k_Signature[] = { kSignature_0, kSignature_1, kSignature_2 };
-static CArcInfo g_ArcInfo =
- { "gzip", "gz gzip tgz tpz", "* * .tar .tar", 0xEF,
- 3, { kSignature_0, kSignature_1, kSignature_2 },
+REGISTER_ARC_IO(
+ "gzip", "gz gzip tgz tpz", "* * .tar .tar", 0xEF,
+ k_Signature,
0,
NArcInfoFlags::kKeepName,
- REF_CreateArc_Pair, IsArc_Gz };
-
-REGISTER_ARC(GZip)
+ IsArc_Gz)
}}
diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp
index ca1370d8..8459280d 100644
--- a/CPP/7zip/Archive/HfsHandler.cpp
+++ b/CPP/7zip/Archive/HfsHandler.cpp
@@ -28,7 +28,7 @@
namespace NArchive {
namespace NHfs {
-static const wchar_t *kResFileName = L"rsrc"; // L"com.apple.ResourceFork";
+static const char *kResFileName = "rsrc"; // "com.apple.ResourceFork";
struct CExtent
{
@@ -655,12 +655,17 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec
static void LoadName(const Byte *data, unsigned len, UString &dest)
{
- wchar_t *p = dest.GetBuffer(len);
+ wchar_t *p = dest.GetBuf(len);
unsigned i;
for (i = 0; i < len; i++)
- p[i] = Get16(data + i * 2);
+ {
+ wchar_t c = Get16(data + i * 2);
+ if (c == 0)
+ break;
+ p[i] = c;
+ }
p[i] = 0;
- dest.ReleaseBuffer();
+ dest.ReleaseBuf_SetLen(i);
}
static bool IsNameEqualTo(const Byte *data, const char *name)
@@ -805,7 +810,7 @@ static const UInt32 kMethod_Resource = 4; // data stored in resource fork
bool CDatabase::Parse_decmpgfs(const CAttr &attr, CItem &item, bool &skip)
{
skip = false;
- if (attr.Name != L"com.apple.decmpfs")
+ if (!attr.Name.IsEqualTo("com.apple.decmpfs"))
return true;
if (item.UseAttr || !item.DataFork.IsEmpty())
return false;
@@ -961,13 +966,13 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
IsNameEqualTo(name + 8, "HFS+ Private Data"))
{
// it's folder for "Hard Links" files
- item.Name = L"[HFS+ Private Data]";
+ item.Name.SetFromAscii("[HFS+ Private Data]");
}
}
// Some dmg files have ' ' folder item.
if (item.Name.IsEmpty() || item.Name[0] == L' ')
- item.Name = L"[]";
+ item.Name.SetFromAscii("[]");
}
}
@@ -1221,7 +1226,7 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress)
return S_FALSE;
*/
- ResFileName = kResFileName;
+ ResFileName.SetFromAscii(kResFileName);
CFork extentsFork, catalogFork, attrFork;
// allocationFork.Parse(p + 0x70 + 0x50 * 0);
@@ -1856,19 +1861,15 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
return GetForkStream(item.GetFork(ref.IsResource), stream);
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "HFS", "hfs hfsx", 0, 0xE3,
- 2 * (4 + 1),
- {
+static const Byte k_Signature[] = {
4, 'H', '+', 0, 4,
- 4, 'H', 'X', 0, 5,
- },
+ 4, 'H', 'X', 0, 5 };
+
+REGISTER_ARC_I(
+ "HFS", "hfs hfsx", 0, 0xE3,
+ k_Signature,
kHeaderPadSize,
NArcInfoFlags::kMultiSignature,
- CreateArc };
-
-REGISTER_ARC(Hfs)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h
index a57a9b8f..84a4cc4b 100644
--- a/CPP/7zip/Archive/IArchive.h
+++ b/CPP/7zip/Archive/IArchive.h
@@ -82,10 +82,22 @@ namespace NArchive
kUnexpectedEnd,
kDataAfterEnd,
kIsNotArc,
- kHeadersError
+ kHeadersError,
+ kWrongPassword
};
}
}
+
+ namespace NEventIndexType
+ {
+ enum
+ {
+ kNoIndex = 0,
+ kInArcIndex,
+ kBlockIndex,
+ kOutArcIndex
+ };
+ }
namespace NUpdate
{
@@ -110,17 +122,59 @@ ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10)
};
/*
-IArchiveExtractCallback::GetStream
- Result:
+IArchiveExtractCallback::
+
+7-Zip doesn't call IArchiveExtractCallback functions
+ GetStream()
+ PrepareOperation()
+ SetOperationResult()
+from different threads simultaneously.
+But 7-Zip can call functions for IProgress or ICompressProgressInfo functions
+from another threads simultaneously with calls for IArchiveExtractCallback interface.
+
+IArchiveExtractCallback::GetStream()
+ UInt32 index - index of item in Archive
+ Int32 askExtractMode (Extract::NAskMode)
+ if (askMode != NExtract::NAskMode::kExtract)
+ {
+ then the callee can not real stream: (*inStream == NULL)
+ }
+
+ Out:
(*inStream == NULL) - for directories
(*inStream == NULL) - if link (hard link or symbolic link) was created
+ if (*inStream == NULL && askMode == NExtract::NAskMode::kExtract)
+ {
+ then the caller must skip extracting of that file.
+ }
+
+ returns:
+ S_OK : OK
+ S_FALSE : data error (for decoders)
+
+if (IProgress::SetTotal() was called)
+{
+ IProgress::SetCompleted(completeValue) uses
+ packSize - for some stream formats (xz, gz, bz2, lzma, z, ppmd).
+ unpackSize - for another formats.
+}
+else
+{
+ IProgress::SetCompleted(completeValue) uses packSize.
+}
+
+SetOperationResult()
+ 7-Zip calls SetOperationResult at the end of extracting,
+ so the callee can close the file, set attributes, timestamps and security information.
+
+ Int32 opRes (NExtract::NOperationResult)
*/
#define INTERFACE_IArchiveExtractCallback(x) \
INTERFACE_IProgress(x) \
STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \
STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \
- STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \
+ STDMETHOD(SetOperationResult)(Int32 opRes) x; \
ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)
{
@@ -128,6 +182,25 @@ ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)
};
+
+/*
+IArchiveExtractCallbackMessage can be requested from IArchiveExtractCallback object
+ by Extract() or UpdateItems() functions to report about extracting errors
+ReportExtractResult()
+ UInt32 indexType (NEventIndexType)
+ UInt32 index
+ Int32 opRes (NExtract::NOperationResult)
+*/
+
+#define INTERFACE_IArchiveExtractCallbackMessage(x) \
+ STDMETHOD(ReportExtractResult)(UInt32 indexType, UInt32 index, Int32 opRes) x; \
+
+ARCHIVE_INTERFACE_SUB(IArchiveExtractCallbackMessage, IProgress, 0x21)
+{
+ INTERFACE_IArchiveExtractCallbackMessage(PURE)
+};
+
+
#define INTERFACE_IArchiveOpenVolumeCallback(x) \
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \
@@ -183,9 +256,6 @@ Notes:
Some IInArchive handlers will work incorrectly in that case.
*/
-/* MSVC allows the code where there is throw() in declaration of function,
- but there is no throw() in definition of function. */
-
#ifdef _MSC_VER
#define MY_NO_THROW_DECL_ONLY throw()
#else
@@ -202,7 +272,7 @@ Notes:
STDMETHOD(GetNumberOfProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \
STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \
STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \
- STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x;
+ STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \
ARCHIVE_INTERFACE(IInArchive, 0x60)
{
@@ -324,6 +394,8 @@ The order of calling for hard links:
- GetStream()
- GetProperty(kpidHardLink)
+SetOperationResult()
+ Int32 opRes (NExtract::NOperationResult::kOK)
*/
#define INTERFACE_IArchiveUpdateCallback(x) \
@@ -348,6 +420,40 @@ ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82)
INTERFACE_IArchiveUpdateCallback2(PURE);
};
+namespace NUpdateNotifyOp
+{
+ enum
+ {
+ kAdd = 0,
+ kUpdate,
+ kAnalyze,
+ kReplicate,
+ kRepack,
+ kSkip,
+ kDelete,
+ kHeader
+
+ // kNumDefined
+ };
+};
+
+/*
+IArchiveUpdateCallbackFile::ReportOperation
+ UInt32 indexType (NEventIndexType)
+ UInt32 index
+ UInt32 notifyOp (NUpdateNotifyOp)
+*/
+
+#define INTERFACE_IArchiveUpdateCallbackFile(x) \
+ STDMETHOD(GetStream2)(UInt32 index, ISequentialInStream **inStream, UInt32 notifyOp) x; \
+ STDMETHOD(ReportOperation)(UInt32 indexType, UInt32 index, UInt32 notifyOp) x; \
+
+ARCHIVE_INTERFACE(IArchiveUpdateCallbackFile, 0x83)
+{
+ INTERFACE_IArchiveUpdateCallbackFile(PURE);
+};
+
+
/*
UpdateItems()
-------------
@@ -382,7 +488,7 @@ ARCHIVE_INTERFACE(IOutArchive, 0xA0)
ARCHIVE_INTERFACE(ISetProperties, 0x03)
{
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) PURE;
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) PURE;
};
ARCHIVE_INTERFACE(IArchiveKeepModeForNextOpen, 0x04)
diff --git a/CPP/7zip/Archive/IhexHandler.cpp b/CPP/7zip/Archive/IhexHandler.cpp
index 00816f0c..00ff80a7 100644
--- a/CPP/7zip/Archive/IhexHandler.cpp
+++ b/CPP/7zip/Archive/IhexHandler.cpp
@@ -85,7 +85,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
const CBlock &block = _blocks[index];
switch (propID)
{
- case kpidSize: prop = block.Data.GetPos(); break;
+ case kpidSize: prop = (UInt64)block.Data.GetPos(); break;
case kpidVa: prop = block.Offset; break;
case kpidPath:
{
@@ -103,7 +103,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END
}
-static inline int HexToByte(char c)
+static inline int HexToByte(unsigned c)
{
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
@@ -138,9 +138,9 @@ API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size)
p++;
size--;
- const int kNumLinesToCheck = 3; // 1 line is OK also, but we don't want false detection
+ const unsigned kNumLinesToCheck = 3; // 1 line is OK also, but we don't want false detection
- for (int j = 0; j < kNumLinesToCheck; j++)
+ for (unsigned j = 0; j < kNumLinesToCheck; j++)
{
if (size < 4 * 2)
return k_IsArc_Res_NEED_MORE;
@@ -279,7 +279,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
}
{
- size_t numPairs = (num + 4);
+ size_t numPairs = ((unsigned)num + 4);
size_t numBytes = numPairs * 2;
if (s.ReadBytes(temp, numBytes) != numBytes)
{
@@ -287,7 +287,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
return S_FALSE;
}
- int sum = num;
+ unsigned sum = num;
for (size_t i = 0; i < numPairs; i++)
{
int a = Parse(temp + i * 2);
@@ -339,7 +339,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
block = &_blocks.AddNew();
block->Offset = offs;
}
- memcpy(block->Data.GetCurPtrAndGrow(num), temp + 3, num);
+ block->Data.AddData(temp + 3, (unsigned)num);
}
}
else if (type == kType_Eof)
@@ -486,16 +486,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
COM_TRY_END
}
-IMP_CreateArcIn
+// k_Signature: { ':', '1' }
-static CArcInfo g_ArcInfo =
- { "IHex", "ihex", 0, 0xCD,
- 0, { 0 },
- // 2, { ':', '1' },
+REGISTER_ARC_I_NO_SIG(
+ "IHex", "ihex", 0, 0xCD,
0,
NArcInfoFlags::kStartOpen,
- CreateArc, NULL, IsArc_Ihex };
-
-REGISTER_ARC(Z)
+ IsArc_Ihex)
}}
diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp
index aef920b0..713764d9 100644
--- a/CPP/7zip/Archive/Iso/IsoHandler.cpp
+++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp
@@ -79,8 +79,7 @@ static void AddString(AString &s, const char *name, const Byte *p, unsigned size
if (i != 0)
{
AString d;
- memcpy(d.GetBuffer(i), p, i);
- d.ReleaseBuffer(i);
+ d.SetFrom((const char *)p, i);
s += '\n';
s += name;
s += ": ";
@@ -170,11 +169,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
case kpidPath:
{
- // char name[16];
- // ConvertUInt32ToString(index + 1, name);
AString s = "[BOOT]" STRING_PATH_SEPARATOR;
- // s += name;
- // s += '-';
+ if (_archive.BootEntries.Size() != 1)
+ {
+ char temp[16];
+ ConvertUInt32ToString(index + 1, temp);
+ s += temp;
+ s += '-';
+ }
s += be.GetName();
prop = s;
break;
@@ -197,18 +199,18 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
UString s;
if (_archive.IsJoliet())
- s = item.GetPathU();
+ item.GetPathU(s);
else
s = MultiByteToUnicodeString(item.GetPath(_archive.IsSusp, _archive.SuspSkipSize), CP_OEMCP);
- int pos = s.ReverseFind(L';');
- if (pos >= 0 && pos == (int)s.Len() - 2)
- if (s.Back() == L'1')
- s.DeleteFrom(pos);
- if (!s.IsEmpty())
- if (s.Back() == L'.')
- s.DeleteBack();
- prop = (const wchar_t *)NItemName::GetOSName2(s);
+ if (s.Len() >= 2 && s[s.Len() - 2] == ';' && s.Back() == '1')
+ s.DeleteFrom(s.Len() - 2);
+
+ if (!s.IsEmpty() && s.Back() == L'.')
+ s.DeleteBack();
+
+ NItemName::ConvertToOSName2(s);
+ prop = s;
}
break;
case kpidIsDir: prop = item.IsDir(); break;
@@ -319,8 +321,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt64 offset = 0;
for (UInt32 e = 0; e < ref.NumExtents; e++)
{
- if (e != 0)
- lps->InSize = lps->OutSize = currentTotalSize + offset;
+ lps->InSize = lps->OutSize = currentTotalSize + offset;
const CDir &item2 = ref.Dir->_subItems[ref.Index + e];
RINOK(_stream->Seek((UInt64)item2.ExtentLocation * _archive.BlockSize, STREAM_SEEK_SET, NULL));
streamSpec->Init(item2.Size);
@@ -356,6 +357,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
*stream = 0;
UInt64 blockIndex;
UInt64 currentItemSize;
+
if (index < (UInt32)_archive.Refs.Size())
{
const CRef &ref = _archive.Refs[index];
@@ -402,6 +404,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
currentItemSize = _archive.GetBootItemSize(bootIndex);
blockIndex = be.LoadRBA;
}
+
return CreateLimitedInStream(_stream, blockIndex * _archive.BlockSize, currentItemSize, stream);
COM_TRY_END
}
diff --git a/CPP/7zip/Archive/Iso/IsoHeader.cpp b/CPP/7zip/Archive/Iso/IsoHeader.cpp
index 1cd2516c..59c283c1 100644
--- a/CPP/7zip/Archive/Iso/IsoHeader.cpp
+++ b/CPP/7zip/Archive/Iso/IsoHeader.cpp
@@ -9,13 +9,4 @@ namespace NIso {
const char *kElToritoSpec = "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0";
-const char *kMediaTypes[5] =
-{
- "NoEmulation"
- , "1.2M"
- , "1.44M"
- , "2.88M"
- , "HardDisk"
-};
-
}}
diff --git a/CPP/7zip/Archive/Iso/IsoHeader.h b/CPP/7zip/Archive/Iso/IsoHeader.h
index ce21b0ff..db0b1df9 100644
--- a/CPP/7zip/Archive/Iso/IsoHeader.h
+++ b/CPP/7zip/Archive/Iso/IsoHeader.h
@@ -34,6 +34,11 @@ namespace NBootEntryId
const Byte kValidationEntry = 1;
const Byte kInitialEntryNotBootable = 0;
const Byte kInitialEntryBootable = 0x88;
+
+ const Byte kMoreHeaders = 0x90;
+ const Byte kFinalHeader = 0x91;
+
+ const Byte kExtensionIndicator = 0x44;
}
namespace NBootPlatformId
@@ -54,9 +59,6 @@ namespace NBootMediaType
const Byte kHardDisk = 4;
}
-const unsigned kNumBootMediaTypes = 5;
-extern const char *kMediaTypes[];
-
}}
#endif
diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp
index ba12acae..b72e8687 100644
--- a/CPP/7zip/Archive/Iso/IsoIn.cpp
+++ b/CPP/7zip/Archive/Iso/IsoIn.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../../C/CpuArch.h"
+
#include "../../../Common/MyException.h"
#include "../../Common/StreamUtils.h"
@@ -10,11 +12,78 @@
namespace NArchive {
namespace NIso {
-
+
struct CUnexpectedEndException {};
struct CHeaderErrorException {};
struct CEndianErrorException {};
+static const char * const kMediaTypes[] =
+{
+ "NoEmul"
+ , "1.2M"
+ , "1.44M"
+ , "2.88M"
+ , "HardDisk"
+};
+
+bool CBootInitialEntry::Parse(const Byte *p)
+{
+ Bootable = (p[0] == NBootEntryId::kInitialEntryBootable);
+ BootMediaType = p[1];
+ LoadSegment = GetUi16(p + 2);
+ SystemType = p[4];
+ SectorCount = GetUi16(p + 6);
+ LoadRBA = GetUi32(p + 8);
+ memcpy(VendorSpec, p + 12, 20);
+ if (p[5] != 0)
+ return false;
+ if (p[0] != NBootEntryId::kInitialEntryBootable
+ && p[0] != NBootEntryId::kInitialEntryNotBootable)
+ return false;
+ return true;
+}
+
+AString CBootInitialEntry::GetName() const
+{
+ AString s = (Bootable ? "Boot" : "NotBoot");
+ s += '-';
+
+ if (BootMediaType < ARRAY_SIZE(kMediaTypes))
+ s += kMediaTypes[BootMediaType];
+ else
+ {
+ char name[16];
+ ConvertUInt32ToString(BootMediaType, name);
+ s += name;
+ }
+
+ if (VendorSpec[0] == 1)
+ {
+ // "Language and Version Information (IBM)"
+
+ unsigned i;
+ for (i = 1; i < sizeof(VendorSpec); i++)
+ if (VendorSpec[i] > 0x7F)
+ break;
+ if (i == sizeof(VendorSpec))
+ {
+ s += '-';
+ for (i = 1; i < sizeof(VendorSpec); i++)
+ {
+ char c = VendorSpec[i];
+ if (c == 0)
+ break;
+ if (c == '\\' || c == '/')
+ c = '_';
+ s += c;
+ }
+ }
+ }
+
+ s += ".img";
+ return s;
+}
+
Byte CInArchive::ReadByte()
{
if (m_BufferPos >= BlockSize)
@@ -58,15 +127,6 @@ void CInArchive::SkipZeros(size_t size)
}
}
-UInt16 CInArchive::ReadUInt16Spec()
-{
- UInt16 val = 0;
- for (int i = 0; i < 2; i++)
- val |= ((UInt16)(ReadByte()) << (8 * i));
- return val;
-}
-
-
UInt16 CInArchive::ReadUInt16()
{
Byte b[4];
@@ -179,15 +239,15 @@ void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len)
Byte idLen = ReadByte();
r.FileId.Alloc(idLen);
ReadBytes((Byte *)r.FileId, idLen);
- int padSize = 1 - (idLen & 1);
+ unsigned padSize = 1 - (idLen & 1);
- // SkipZeros(1 - (idLen & 1));
- Skip(1 - (idLen & 1)); // it's bug in some cd's. Must be zeros
+ // SkipZeros(padSize);
+ Skip(padSize); // it's bug in some cd's. Must be zeros
- int curPos = 33 + idLen + padSize;
+ unsigned curPos = 33 + idLen + padSize;
if (curPos > len)
throw CHeaderErrorException();
- int rem = len - curPos;
+ unsigned rem = len - curPos;
r.SystemUse.Alloc(rem);
ReadBytes((Byte *)r.SystemUse, rem);
}
@@ -349,45 +409,94 @@ void CInArchive::ReadBootInfo()
{
if (!_bootIsDefined)
return;
+ HeadersError = true;
+
if (memcmp(_bootDesc.BootSystemId, kElToritoSpec, sizeof(_bootDesc.BootSystemId)) != 0)
return;
- const Byte *p = (const Byte *)_bootDesc.BootSystemUse;
- UInt32 blockIndex = p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24);
+ UInt32 blockIndex = GetUi32(_bootDesc.BootSystemUse);
SeekToBlock(blockIndex);
- Byte b = ReadByte();
- if (b != NBootEntryId::kValidationEntry)
+
+ Byte buf[32];
+ ReadBytes(buf, 32);
+
+ if (buf[0] != NBootEntryId::kValidationEntry
+ || buf[2] != 0
+ || buf[3] != 0
+ || buf[30] != 0x55
+ || buf[31] != 0xAA)
return;
+
{
+ UInt32 sum = 0;
+ for (unsigned i = 0; i < 32; i += 2)
+ sum += GetUi16(buf + i);
+ if ((sum & 0xFFFF) != 0)
+ return;
+ /*
CBootValidationEntry e;
- e.PlatformId = ReadByte();
- if (ReadUInt16Spec() != 0)
- throw CHeaderErrorException();
- ReadBytes(e.Id, sizeof(e.Id));
- /* UInt16 checkSum = */ ReadUInt16Spec();
- if (ReadByte() != 0x55)
- throw CHeaderErrorException();
- if (ReadByte() != 0xAA)
- throw CHeaderErrorException();
+ e.PlatformId = buf[1];
+ memcpy(e.Id, buf + 4, sizeof(e.Id));
+ // UInt16 checkSum = GetUi16(p + 28);
+ */
}
- b = ReadByte();
- if (b == NBootEntryId::kInitialEntryBootable || b == NBootEntryId::kInitialEntryNotBootable)
+
+ ReadBytes(buf, 32);
{
CBootInitialEntry e;
- e.Bootable = (b == NBootEntryId::kInitialEntryBootable);
- e.BootMediaType = ReadByte();
- e.LoadSegment = ReadUInt16Spec();
- e.SystemType = ReadByte();
- if (ReadByte() != 0)
- throw CHeaderErrorException();
- e.SectorCount = ReadUInt16Spec();
- e.LoadRBA = ReadUInt32Le();
- if (ReadByte() != 0)
- throw CHeaderErrorException();
+ if (!e.Parse(buf))
+ return;
BootEntries.Add(e);
}
- else
- return;
+
+ bool error = false;
+
+ for (;;)
+ {
+ ReadBytes(buf, 32);
+ Byte headerIndicator = buf[0];
+ if (headerIndicator != NBootEntryId::kMoreHeaders
+ && headerIndicator != NBootEntryId::kFinalHeader)
+ break;
+
+ // Section Header
+ // Byte platform = p[1];
+ unsigned numEntries = GetUi16(buf + 2);
+ // id[28]
+
+ for (unsigned i = 0; i < numEntries; i++)
+ {
+ ReadBytes(buf, 32);
+ CBootInitialEntry e;
+ if (!e.Parse(buf))
+ {
+ error = true;
+ break;
+ }
+ if (e.BootMediaType & (1 << 5))
+ {
+ // Section entry extension
+ for (unsigned j = 0;; j++)
+ {
+ ReadBytes(buf, 32);
+ if (j > 32 || buf[0] != NBootEntryId::kExtensionIndicator)
+ {
+ error = true;
+ break;
+ }
+ if ((buf[1] & (1 << 5)) == 0)
+ break;
+ // info += (buf + 2, 30)
+ }
+ }
+ BootEntries.Add(e);
+ }
+
+ if (headerIndicator != NBootEntryId::kMoreHeaders)
+ break;
+ }
+
+ HeadersError = error;
}
HRESULT CInArchive::Open2()
diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h
index 614b3744..c2007bce 100644
--- a/CPP/7zip/Archive/Iso/IsoIn.h
+++ b/CPP/7zip/Archive/Iso/IsoIn.h
@@ -25,77 +25,92 @@ struct CDir: public CDirRecord
_subItems.Clear();
}
- unsigned GetLen(bool checkSusp, unsigned skipSize) const
- {
- unsigned len = GetLenCur(checkSusp, skipSize);
- if (Parent != 0)
- if (Parent->Parent != 0)
- len += 1 + Parent->GetLen(checkSusp, skipSize);
- return len;
- }
-
- unsigned GetLenU() const
- {
- unsigned len = (unsigned)(FileId.Size() / 2);
- if (Parent != 0)
- if (Parent->Parent != 0)
- len += 1 + Parent->GetLenU();
- return len;
- }
-
AString GetPath(bool checkSusp, unsigned skipSize) const
{
AString s;
- unsigned len = GetLen(checkSusp, skipSize);
- char *p = s.GetBuffer(len);
- p += len;
- *p = 0;
+
+ unsigned len = 0;
const CDir *cur = this;
+
for (;;)
{
- unsigned curLen = cur->GetLenCur(checkSusp, skipSize);
- p -= curLen;
- memcpy(p, (const char *)(const Byte *)cur->GetNameCur(checkSusp, skipSize), curLen);
+ unsigned curLen;
+ cur->GetNameCur(checkSusp, skipSize, curLen);
+ len += curLen;
cur = cur->Parent;
- if (cur == 0)
+ if (!cur || !cur->Parent)
break;
- if (cur->Parent == 0)
+ len++;
+ }
+
+ char *p = s.GetBuf_SetEnd(len) + len;
+
+ cur = this;
+
+ for (;;)
+ {
+ unsigned curLen;
+ const Byte *name = cur->GetNameCur(checkSusp, skipSize, curLen);
+ p -= curLen;
+ if (curLen != 0)
+ memcpy(p, name, curLen);
+ cur = cur->Parent;
+ if (!cur || !cur->Parent)
break;
p--;
*p = CHAR_PATH_SEPARATOR;
}
- s.ReleaseBuffer();
+
return s;
}
- UString GetPathU() const
+ void GetPathU(UString &s) const
{
- UString s;
- unsigned len = GetLenU();
- wchar_t *p = s.GetBuffer(len);
- p += len;
- *p = 0;
+ s.Empty();
+
+ unsigned len = 0;
const CDir *cur = this;
+
for (;;)
{
unsigned curLen = (unsigned)(cur->FileId.Size() / 2);
- p -= curLen;
- for (unsigned i = 0; i < curLen; i++)
- {
- Byte b0 = ((const Byte *)cur->FileId)[i * 2];
- Byte b1 = ((const Byte *)cur->FileId)[i * 2 + 1];
- p[i] = (wchar_t)(((wchar_t)b0 << 8) | b1);
- }
+ const Byte *fid = cur->FileId;
+
+ unsigned i;
+ for (i = 0; i < curLen; i++)
+ if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0)
+ break;
+ len += i;
cur = cur->Parent;
- if (cur == 0)
+ if (!cur || !cur->Parent)
break;
- if (cur->Parent == 0)
+ len++;
+ }
+
+ wchar_t *p = s.GetBuf_SetEnd(len) + len;
+
+ cur = this;
+
+ for (;;)
+ {
+ unsigned curLen = (unsigned)(cur->FileId.Size() / 2);
+ const Byte *fid = cur->FileId;
+
+ unsigned i;
+ for (i = 0; i < curLen; i++)
+ if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0)
+ break;
+ curLen = i;
+
+ p -= curLen;
+ for (i = 0; i < curLen; i++)
+ p[i] = (wchar_t)(((wchar_t)fid[i * 2] << 8) | fid[i * 2 + 1]);
+ cur = cur->Parent;
+ if (!cur || !cur->Parent)
break;
p--;
*p = WCHAR_PATH_SEPARATOR;
}
- s.ReleaseBuffer();
- return s;
}
};
@@ -109,6 +124,7 @@ struct CDateTime
Byte Second;
Byte Hundredths;
signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.
+
bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 &&
Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; }
@@ -118,7 +134,7 @@ struct CDateTime
bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, value);
if (res)
{
- value -= (UInt64)((Int64)GmtOffset * 15 * 60);
+ value -= (Int64)((Int32)GmtOffset * 15 * 60);
value *= 10000000;
}
ft.dwLowDateTime = (DWORD)value;
@@ -157,27 +173,16 @@ struct CBootInitialEntry
UInt32 LoadRBA; // This is the start address of the virtual disk. CD’s use
// Relative/Logical block addressing.
- UInt64 GetSize() const
+ Byte VendorSpec[20];
+
+ UInt32 GetSize() const
{
// if (BootMediaType == NBootMediaType::k1d44Floppy) (1440 << 10);
- return SectorCount * 512;
+ return (UInt32)SectorCount * 512;
}
- AString GetName() const
- {
- AString s = (Bootable ? "Bootable" : "NotBootable");
- s += '_';
- if (BootMediaType < kNumBootMediaTypes)
- s += kMediaTypes[BootMediaType];
- else
- {
- char name[16];
- ConvertUInt32ToString(BootMediaType, name);
- s += name;
- }
- s += ".img";
- return s;
- }
+ bool Parse(const Byte *p);
+ AString GetName() const;
};
struct CVolumeDescriptor
@@ -247,7 +252,6 @@ class CInArchive
void SkipZeros(size_t size);
Byte ReadByte();
void ReadBytes(Byte *data, UInt32 size);
- UInt16 ReadUInt16Spec();
UInt16 ReadUInt16();
UInt32 ReadUInt32Le();
UInt32 ReadUInt32Be();
diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h
index b6ae21b7..2603afdb 100644
--- a/CPP/7zip/Archive/Iso/IsoItem.h
+++ b/CPP/7zip/Archive/Iso/IsoItem.h
@@ -29,7 +29,7 @@ struct CRecordingDateTime
bool res = NWindows::NTime::GetSecondsSince1601(Year + 1900, Month, Day, Hour, Minute, Second, value);
if (res)
{
- value -= (UInt64)((Int64)GmtOffset * 15 * 60);
+ value -= (Int64)((Int32)GmtOffset * 15 * 60);
value *= 10000000;
}
ft.dwLowDateTime = (DWORD)value;
@@ -94,28 +94,23 @@ struct CDirRecord
return 0;
}
- unsigned GetLenCur(bool checkSusp, int skipSize) const
+ const Byte* GetNameCur(bool checkSusp, int skipSize, unsigned &nameLenRes) const
{
+ const Byte *res = NULL;
+ unsigned len = 0;
if (checkSusp)
+ res = FindSuspName(skipSize, len);
+ if (!res)
{
- unsigned len;
- const Byte *res = FindSuspName(skipSize, len);
- if (res != 0)
- return len;
+ res = (const Byte *)FileId;
+ len = (unsigned)FileId.Size();
}
- return (unsigned)FileId.Size();
- }
-
- const Byte* GetNameCur(bool checkSusp, int skipSize) const
- {
- if (checkSusp)
- {
- unsigned len;
- const Byte *res = FindSuspName(skipSize, len);
- if (res != 0)
- return res;
- }
- return (const Byte *)FileId;
+ unsigned i;
+ for (i = 0; i < len; i++)
+ if (res[i] == 0)
+ break;
+ nameLenRes = i;
+ return res;
}
diff --git a/CPP/7zip/Archive/Iso/IsoRegister.cpp b/CPP/7zip/Archive/Iso/IsoRegister.cpp
index c6f4a521..0205238d 100644
--- a/CPP/7zip/Archive/Iso/IsoRegister.cpp
+++ b/CPP/7zip/Archive/Iso/IsoRegister.cpp
@@ -9,15 +9,13 @@
namespace NArchive {
namespace NIso {
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 'C', 'D', '0', '0', '1' };
-static CArcInfo g_ArcInfo =
- { "Iso", "iso img", 0, 0xE7,
- 5, { 'C', 'D', '0', '0', '1' },
+REGISTER_ARC_I(
+ "Iso", "iso img", 0, 0xE7,
+ k_Signature,
NArchive::NIso::kStartPos + 1,
0,
- CreateArc };
-
-REGISTER_ARC(Iso)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp
index ef4b4196..c8d3ff6d 100644
--- a/CPP/7zip/Archive/LzhHandler.cpp
+++ b/CPP/7zip/Archive/LzhHandler.cpp
@@ -660,8 +660,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0;
CMyComPtr<ICompressCoder> lzhDecoder;
- CMyComPtr<ICompressCoder> lzh1Decoder;
- CMyComPtr<ICompressCoder> arj2Decoder;
+ // CMyComPtr<ICompressCoder> lzh1Decoder;
+ // CMyComPtr<ICompressCoder> arj2Decoder;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
@@ -736,8 +736,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder;
lzhDecoder = lzhDecoderSpec;
}
- lzhDecoderSpec->SetDictionary(item.GetNumDictBits());
+ lzhDecoderSpec->FinishMode = true;
+ lzhDecoderSpec->SetDictSize(1 << item.GetNumDictBits());
result = lzhDecoder->Code(inStream, outStream, NULL, &currentItemUnPacked, progress);
+ if (result == S_OK && lzhDecoderSpec->GetInputProcessedSize() != item.PackSize)
+ result = S_FALSE;
}
/*
else if (item.IsLh1GroupMethod())
@@ -773,15 +776,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { '-', 'l', 'h' };
-static CArcInfo g_ArcInfo =
- { "Lzh", "lzh lha", 0, 6,
- 3, { '-', 'l', 'h' },
+REGISTER_ARC_I(
+ "Lzh", "lzh lha", 0, 6,
+ k_Signature,
2,
0,
- CreateArc, NULL, IsArc_Lzh };
-
-REGISTER_ARC(Lzh)
+ IsArc_Lzh)
}}
diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp
index 04aa4685..e4ac2a42 100644
--- a/CPP/7zip/Archive/LzmaHandler.cpp
+++ b/CPP/7zip/Archive/LzmaHandler.cpp
@@ -9,11 +9,12 @@
#include "../../Windows/PropVariant.h"
-#include "../Common/CreateCoder.h"
+#include "../Common/FilterCoder.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"
+#include "../Compress/BcjCoder.h"
#include "../Compress/LzmaDecoder.h"
#include "Common/DummyOutStream.h"
@@ -75,14 +76,14 @@ bool CHeader::Parse(const Byte *buf, bool isThereFilter)
class CDecoder
{
- CMyComPtr<ICompressCoder> _lzmaDecoder;
CMyComPtr<ISequentialOutStream> _bcjStream;
+ CFilterCoder *_filterCoder;
+ CMyComPtr<ICompressCoder> _lzmaDecoder;
public:
NCompress::NLzma::CDecoder *_lzmaDecoderSpec;
~CDecoder();
- HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS
- bool filtered, ISequentialInStream *inStream);
+ HRESULT Create(bool filtered, ISequentialInStream *inStream);
HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress);
@@ -94,11 +95,7 @@ public:
{ return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); }
};
-static const UInt32 k_BCJ = 0x03030103;
-
-HRESULT CDecoder::Create(
- DECL_EXTERNAL_CODECS_LOC_VARS
- bool filteredMode, ISequentialInStream *inStream)
+HRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream)
{
if (!_lzmaDecoder)
{
@@ -111,13 +108,10 @@ HRESULT CDecoder::Create(
{
if (!_bcjStream)
{
- CMyComPtr<ICompressCoder> coder;
- RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false));
- if (!coder)
- return E_NOTIMPL;
- coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream);
- if (!_bcjStream)
- return E_NOTIMPL;
+ _filterCoder = new CFilterCoder(false);
+ CMyComPtr<ICompressCoder> coder = _filterCoder;
+ _filterCoder->Filter = new CBcjCoder(false);
+ _bcjStream = _filterCoder;
}
}
@@ -143,17 +137,13 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
RINOK(setDecoderProperties->SetDecoderProperties2(header.LzmaProps, 5));
}
- CMyComPtr<ICompressSetOutStream> setOutStream;
-
bool filteredMode = (header.FilterID == 1);
if (filteredMode)
{
- _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
- if (!setOutStream)
- return E_NOTIMPL;
- RINOK(setOutStream->SetOutStream(outStream));
+ RINOK(_filterCoder->SetOutStream(outStream));
outStream = _bcjStream;
+ RINOK(_filterCoder->SetOutStreamSize(NULL));
}
const UInt64 *Size = header.HasSize() ? &header.Size : NULL;
@@ -161,18 +151,16 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
if (filteredMode)
{
- CMyComPtr<IOutStreamFlush> flush;
- _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush);
- if (flush)
{
- HRESULT res2 = flush->Flush();
+ HRESULT res2 = _filterCoder->OutStreamFinish();
if (res == S_OK)
res = res2;
}
- HRESULT res2 = setOutStream->ReleaseOutStream();
+ HRESULT res2 = _filterCoder->ReleaseOutStream();
if (res == S_OK)
res = res2;
}
+
RINOK(res);
if (header.HasSize())
@@ -186,7 +174,6 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
class CHandler:
public IInArchive,
public IArchiveOpenSeq,
- PUBLIC_ISetCompressCodecsInfo
public CMyUnknownImp
{
CHeader _header;
@@ -210,15 +197,8 @@ class CHandler:
UInt64 _unpackSize;
UInt64 _numStreams;
- DECL_EXTERNAL_CODECS_VARS
- DECL_ISetCompressCodecsInfo
-
public:
- MY_QUERYINTERFACE_BEGIN2(IInArchive)
- MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq)
- QUERY_ENTRY_ISetCompressCodecsInfo
- MY_QUERYINTERFACE_END
- MY_ADDREF_RELEASE
+ MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)
INTERFACE_IInArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
@@ -427,6 +407,7 @@ 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))
@@ -466,9 +447,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
_needSeekToStart = true;
CDecoder decoder;
- HRESULT result = decoder.Create(
- EXTERNAL_CODECS_VARS
- _lzma86, _seqStream);
+ HRESULT result = decoder.Create(_lzma86, _seqStream);
RINOK(result);
bool firstItem = true;
@@ -562,43 +541,33 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
outStream.Release();
return extractCallback->SetOperationResult(opResult);
+
COM_TRY_END
}
-IMPL_ISetCompressCodecsInfo
-
namespace NLzmaAr {
-IMP_CreateArcIn_2(CHandler(false))
+// 2, { 0x5D, 0x00 },
-static CArcInfo g_ArcInfo =
- { "lzma", "lzma", 0, 0xA,
- 0, { 0 },
- // 2, { 0x5D, 0x00 },
+REGISTER_ARC_I_CLS_NO_SIG(
+ CHandler(false),
+ "lzma", "lzma", 0, 0xA,
0,
NArcInfoFlags::kStartOpen |
NArcInfoFlags::kKeepName,
- CreateArc, NULL,
- IsArc_Lzma };
-
-REGISTER_ARC(Lzma)
-
+ IsArc_Lzma)
+
}
namespace NLzma86Ar {
-IMP_CreateArcIn_2(CHandler(true))
-
-static CArcInfo g_ArcInfo =
- { "lzma86", "lzma86", 0, 0xB,
- 0, { 0 },
+REGISTER_ARC_I_CLS_NO_SIG(
+ CHandler(true),
+ "lzma86", "lzma86", 0, 0xB,
0,
NArcInfoFlags::kKeepName,
- CreateArc, NULL,
- IsArc_Lzma86 };
-
-REGISTER_ARC(Lzma86)
-
+ IsArc_Lzma86)
+
}
}}
diff --git a/CPP/7zip/Archive/MachoHandler.cpp b/CPP/7zip/Archive/MachoHandler.cpp
index 11ff9703..00dc571b 100644
--- a/CPP/7zip/Archive/MachoHandler.cpp
+++ b/CPP/7zip/Archive/MachoHandler.cpp
@@ -42,7 +42,7 @@ namespace NMacho {
#define CPU_SUBTYPE_POWERPC_970 100
-static const char *k_PowerPc_SubTypes[] =
+static const char * const k_PowerPc_SubTypes[] =
{
NULL
, "601"
@@ -297,7 +297,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
ConvertUInt32ToString(t, temp);
n = temp;
}
- s += ' ';
+ s.Add_Space();
s += n;
}
prop = s;
@@ -310,7 +310,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
AString s = FlagsToString(g_ArcFlags, ARRAY_SIZE(g_ArcFlags), _flags);
if (!s.IsEmpty())
{
- res += ' ';
+ res.Add_Space();
res += s;
}
prop = res;
@@ -354,7 +354,7 @@ static AString SectFlagsToString(UInt32 flags)
AString s = FlagsToString(g_Flags, ARRAY_SIZE(g_Flags), flags & SECT_ATTR_MASK);
if (!s.IsEmpty())
{
- res += ' ';
+ res.Add_Space();
res += s;
}
return res;
@@ -643,22 +643,18 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail)
return S_OK;
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = {
+ 4, 0xCE, 0xFA, 0xED, 0xFE,
+ 4, 0xCF, 0xFA, 0xED, 0xFE,
+ 4, 0xFE, 0xED, 0xFA, 0xCE,
+ 4, 0xFE, 0xED, 0xFA, 0xCF };
-#define k_Signature { \
- 4, 0xCE, 0xFA, 0xED, 0xFE, \
- 4, 0xCF, 0xFA, 0xED, 0xFE, \
- 4, 0xFE, 0xED, 0xFA, 0xCE, \
- 4, 0xFE, 0xED, 0xFA, 0xCF }
-
-static CArcInfo g_ArcInfo =
- { "MachO", "macho", 0, 0xDF,
- 4 * 5, k_Signature,
+REGISTER_ARC_I(
+ "MachO", "macho", 0, 0xDF,
+ k_Signature,
0,
NArcInfoFlags::kMultiSignature |
NArcInfoFlags::kPreArc,
- CreateArc };
-
-REGISTER_ARC(Macho)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/MbrHandler.cpp b/CPP/7zip/Archive/MbrHandler.cpp
index abc981f3..c4e4cc60 100644
--- a/CPP/7zip/Archive/MbrHandler.cpp
+++ b/CPP/7zip/Archive/MbrHandler.cpp
@@ -169,7 +169,7 @@ static const CPartType kPartTypes[] =
static int FindPartType(UInt32 type)
{
- for (int i = 0; i < ARRAY_SIZE(kPartTypes); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(kPartTypes); i++)
if (kPartTypes[i].Id == type)
return i;
return -1;
@@ -193,19 +193,19 @@ class CHandler:
UInt64 _totalSize;
CByteBuffer _buffer;
- HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level);
+ HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level);
public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
};
-HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level)
+HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level)
{
if (level >= 128 || _items.Size() >= 128)
return S_FALSE;
- const int kNumHeaderParts = 4;
+ const unsigned kNumHeaderParts = 4;
CPartition parts[kNumHeaderParts];
{
@@ -221,7 +221,7 @@ HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int
if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)
return S_FALSE;
- for (int i = 0; i < kNumHeaderParts; i++)
+ for (unsigned i = 0; i < kNumHeaderParts; i++)
if (!parts[i].Parse(buf + 0x1BE + 16 * i))
return S_FALSE;
}
@@ -232,13 +232,13 @@ HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int
if (limLba == 0)
return S_FALSE;
- for (int i = 0; i < kNumHeaderParts; i++)
+ for (unsigned i = 0; i < kNumHeaderParts; i++)
{
CPartition &part = parts[i];
if (part.IsEmpty())
continue;
- PRF(printf("\n %2d ", (int)level));
+ PRF(printf("\n %2d ", (unsigned)level));
#ifdef SHOW_DEBUG_INFO
part.Print();
#endif
@@ -402,8 +402,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
int typeIndex = FindPartType(part.Type);
s += '.';
const char *ext = "img";
- if (typeIndex >= 0 && kPartTypes[typeIndex].Ext != 0)
- ext = kPartTypes[typeIndex].Ext;
+ if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Ext)
+ ext = kPartTypes[(unsigned)typeIndex].Ext;
s += ext;
}
prop = s;
@@ -416,8 +416,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
ConvertUInt32ToString(part.Type, s);
const char *res = s;
int typeIndex = FindPartType(part.Type);
- if (typeIndex >= 0 && kPartTypes[typeIndex].Name)
- res = kPartTypes[typeIndex].Name;
+ if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Name)
+ res = kPartTypes[(unsigned)typeIndex].Name;
prop = res;
}
break;
@@ -499,17 +499,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-static CArcInfo g_ArcInfo =
- { "MBR", "mbr", 0, 0xDB,
// 3, { 1, 1, 0 },
// 2, { 0x55, 0x1FF },
- 0, { 0 },
+
+REGISTER_ARC_I_NO_SIG(
+ "MBR", "mbr", 0, 0xDB,
0,
NArcInfoFlags::kPureStartOpen,
- CreateArc };
-
-REGISTER_ARC(Mbr)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/MslzHandler.cpp b/CPP/7zip/Archive/MslzHandler.cpp
index cb124c40..ec375733 100644
--- a/CPP/7zip/Archive/MslzHandler.cpp
+++ b/CPP/7zip/Archive/MslzHandler.cpp
@@ -111,11 +111,13 @@ static const unsigned kHeaderSize = kSignatureSize + 1 + 4;
static const Byte kSignature[kSignatureSize] = MSLZ_SIGNATURE;
// we support only 3 chars strings here
-static const char *g_Exts[] =
+static const char * const g_Exts[] =
{
- "dll"
+ "bin"
+ , "dll"
, "exe"
, "kmd"
+ , "pdf"
, "sys"
};
@@ -147,14 +149,15 @@ void CHandler::ParseName(Byte replaceByte, IArchiveOpenCallback *callback)
for (unsigned i = 0; i < ARRAY_SIZE(g_Exts); i++)
{
const char *ext = g_Exts[i];
- if (s[s.Len() - 2] == ext[0] &&
- s[s.Len() - 1] == ext[1])
+ if (s[s.Len() - 2] == (Byte)ext[0] &&
+ s[s.Len() - 1] == (Byte)ext[1])
{
replaceByte = ext[2];
break;
}
}
}
+
if (replaceByte >= 0x20 && replaceByte < 0x80)
_name += (wchar_t)replaceByte;
}
@@ -225,6 +228,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn
Byte buf[kBufSize];
UInt32 dest = 0;
memset(buf, ' ', kBufSize);
+
while (dest < unpackSize)
{
Byte b;
@@ -233,6 +237,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn
needMoreData = true;
return S_FALSE;
}
+
for (unsigned mask = (unsigned)b | 0x100; mask > 1 && dest < unpackSize; mask >>= 1)
{
if (!inStream.ReadByte(b))
@@ -240,6 +245,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn
needMoreData = true;
return S_FALSE;
}
+
if (mask & 1)
{
buf[dest++ & kMask] = b;
@@ -258,6 +264,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn
unsigned len = (b1 & 0xF) + 3;
if (len > kMaxLen || dest + len > unpackSize)
return S_FALSE;
+
do
{
buf[dest++ & kMask] = buf[src++ & kMask];
@@ -267,6 +274,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn
}
}
}
+
if (outStream)
RINOK(WriteStream(outStream, buf, dest & kMask));
return S_OK;
@@ -379,15 +387,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "MsLZ", "mslz", 0, 0xD5,
- kSignatureSize, MSLZ_SIGNATURE,
+REGISTER_ARC_I(
+ "MsLZ", "mslz", 0, 0xD5,
+ kSignature,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Mslz)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/MubHandler.cpp b/CPP/7zip/Archive/MubHandler.cpp
index 39f8de27..a84c3120 100644
--- a/CPP/7zip/Archive/MubHandler.cpp
+++ b/CPP/7zip/Archive/MubHandler.cpp
@@ -292,22 +292,18 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-
namespace NBe {
-static CArcInfo g_ArcInfo =
- { "Mub", "mub", 0, 0xE2,
- 2 + 7 + 4,
- {
+static const Byte k_Signature[] = {
7, 0xCA, 0xFE, 0xBA, 0xBE, 0, 0, 0,
- 4, 0xB9, 0xFA, 0xF1, 0x0E
- },
+ 4, 0xB9, 0xFA, 0xF1, 0x0E };
+
+REGISTER_ARC_I(
+ "Mub", "mub", 0, 0xE2,
+ k_Signature,
0,
NArcInfoFlags::kMultiSignature,
- CreateArc };
-
-REGISTER_ARC(Mub)
+ NULL)
}
diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.cpp b/CPP/7zip/Archive/Nsis/NsisDecode.cpp
index bb73d273..68243129 100644
--- a/CPP/7zip/Archive/Nsis/NsisDecode.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisDecode.cpp
@@ -7,7 +7,6 @@
#include "NsisDecode.h"
#include "../../Common/CreateCoder.h"
-#include "../../Common/FilterCoder.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/MethodId.h"
@@ -58,18 +57,11 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
{
if (!_filterInStream)
{
- CFilterCoder *coderSpec = new CFilterCoder;
- CMyComPtr<ICompressCoder> coder = coderSpec;
- coderSpec->Filter = new CBCJ_x86_Decoder();
- coder.QueryInterface(IID_ISequentialInStream, &_filterInStream);
- if (!_filterInStream)
- return E_NOTIMPL;
+ _filter = new CFilterCoder(false);
+ _filterInStream = _filter;
+ _filter->Filter = new CBcjCoder(false);
}
- CMyComPtr<ICompressSetInStream> setInStream;
- _filterInStream.QueryInterface(IID_ICompressSetInStream, &setInStream);
- if (!setInStream)
- return E_NOTIMPL;
- RINOK(setInStream->SetInStream(_codecInStream));
+ RINOK(_filter->SetInStream(_codecInStream));
_decoderInStream = _filterInStream;
}
@@ -99,13 +91,7 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
if (useFilter)
{
- /*
- CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
- _filterInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
- if (!setOutStreamSize)
- return E_NOTIMPL;
- RINOK(setOutStreamSize->SetOutStreamSize(NULL));
- */
+ RINOK(_filter->SetOutStreamSize(NULL));
}
return S_OK;
diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.h b/CPP/7zip/Archive/Nsis/NsisDecode.h
index 0b95d4b2..7b22181e 100644
--- a/CPP/7zip/Archive/Nsis/NsisDecode.h
+++ b/CPP/7zip/Archive/Nsis/NsisDecode.h
@@ -5,6 +5,7 @@
#include "../../../Common/MyBuffer.h"
+#include "../../Common/FilterCoder.h"
#include "../../Common/StreamUtils.h"
#include "../../Compress/LzmaDecoder.h"
@@ -31,6 +32,7 @@ class CDecoder
{
NMethodType::EEnum _curMethod; // method of created decoder
+ CFilterCoder *_filter;
CMyComPtr<ISequentialInStream> _filterInStream;
CMyComPtr<ISequentialInStream> _codecInStream;
CMyComPtr<ISequentialInStream> _decoderInStream;
diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
index 233edd52..971c8464 100644
--- a/CPP/7zip/Archive/Nsis/NsisHandler.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
@@ -26,7 +26,7 @@ namespace NNsis {
static const char *kBcjMethod = "BCJ";
static const char *kUnknownMethod = "Unknown";
-static const char *kMethods[] =
+static const char * const kMethods[] =
{
"Copy"
, "Deflate"
@@ -84,9 +84,9 @@ static AString GetMethod(bool useFilter, NMethodType::EEnum method, UInt32 dict)
if (useFilter)
{
s += kBcjMethod;
- s += ' ';
+ s.Add_Space();
}
- s += (method < ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod;
+ s += ((unsigned)method < ARRAY_SIZE(kMethods)) ? kMethods[(unsigned)method] : kUnknownMethod;
if (method == NMethodType::kLZMA)
{
s += ':';
@@ -102,7 +102,7 @@ AString CHandler::GetMethod(NMethodType::EEnum method, bool useItemFilter, UInt3
if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && useItemFilter)
{
s += kBcjMethod;
- s += ' ';
+ s.Add_Space();
}
s += (method < ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod;
if (method == NMethodType::kLZMA)
@@ -126,8 +126,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
AString s = _archive.GetFormatDescription();
if (!_archive.IsInstaller)
{
- if (!s.IsEmpty())
- s += ' ';
+ s.Add_Space_if_NotEmpty();
s += "(Uninstall)";
}
if (!s.IsEmpty())
@@ -138,8 +137,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidMethod: prop = _methodString; break;
case kpidSolid: prop = _archive.IsSolid; break;
case kpidOffset: prop = _archive.StartOffset; break;
- case kpidPhySize: prop = _archive.ExeStub.Size() + _archive.FirstHeader.ArcSize; break;
- case kpidEmbeddedStubSize: prop = _archive.ExeStub.Size(); break;
+ case kpidPhySize: prop = (UInt64)((UInt64)_archive.ExeStub.Size() + _archive.FirstHeader.ArcSize); break;
+ case kpidEmbeddedStubSize: prop = (UInt64)_archive.ExeStub.Size(); break;
case kpidHeadersSize: prop = _archive.FirstHeader.HeaderSize; break;
case kpidErrorFlags:
@@ -611,7 +610,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
HRESULT res = _archive.Decoder.Decode(
writeToTemp1 ? &tempBuf : NULL,
item.IsUninstaller, item.PatchSize,
- item.IsUninstaller ? NULL : realOutStream,
+ item.IsUninstaller ? NULL : (ISequentialOutStream *)realOutStream,
progress,
curPacked, curUnpacked32);
curUnpacked = curUnpacked32;
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp
index dc570ec2..6ca87df4 100644
--- a/CPP/7zip/Archive/Nsis/NsisIn.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp
@@ -20,7 +20,7 @@ namespace NNsis {
static const size_t kInputBufSize = 1 << 20;
-static const Byte kSignature[kSignatureSize] = NSIS_SIGNATURE;
+const Byte kSignature[kSignatureSize] = NSIS_SIGNATURE;
static const UInt32 kMask_IsCompressed = (UInt32)1 << 31;
static const unsigned kNumCommandParams = 6;
@@ -30,7 +30,7 @@ static const unsigned kCmdSize = 4 + kNumCommandParams * 4;
#define CR_LF "\x0D\x0A"
#endif
-static const char *kErrorStr = "$_ERROR_STR_";
+static const char * const kErrorStr = "$_ERROR_STR_";
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
@@ -244,7 +244,7 @@ static const CCommandInfo k_Commands[kNumCmds] =
#ifdef NSIS_SCRIPT
-static const char *k_CommandNames[kNumCmds] =
+static const char * const k_CommandNames[kNumCmds] =
{
"Invalid"
, NULL // Return
@@ -331,7 +331,7 @@ static const char *k_CommandNames[kNumCmds] =
Some NSIS shell names are not identical to WIN32 CSIDL_* names.
NSIS doesn't use some CSIDL_* values. But we add name for all CSIDL_ (marked with '+'). */
-static const char *kShellStrings[] =
+static const char * const kShellStrings[] =
{
"DESKTOP" // +
, "INTERNET" // +
@@ -526,7 +526,7 @@ void CInArchive::AddLicense(UInt32 param, Int32 langID)
#define kVar_Spec_OUTDIR 31 // NSIS 2.26+
-static const char *kVarStrings[] =
+static const char * const kVarStrings[] =
{
"CMDLINE"
, "INSTDIR"
@@ -963,8 +963,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p)
else // if (c == PARK_CODE_LANG)
Add_LangStr(Raw_AString, n);
}
- for (const Byte *s = (const Byte *)(const char *)Raw_AString; *s != 0; s++)
- Raw_UString += *s;
+ Raw_UString.AddAscii(Raw_AString);
continue;
}
c = n;
@@ -1010,8 +1009,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p)
else // if (c == NS_3_CODE_LANG)
Add_LangStr(Raw_AString, n);
}
- for (const Byte *s = (const Byte *)(const char *)Raw_AString; *s != 0; s++)
- Raw_UString += (wchar_t)*s;
+ Raw_UString.AddAscii(Raw_AString);
}
}
@@ -1147,8 +1145,7 @@ void CInArchive::ReadString2_Raw(UInt32 pos)
GetNsisString_Raw(_data + _stringsPos + pos);
return;
}
- for (const char *s = (const char *)Raw_AString; *s != 0; s++)
- Raw_UString += *s;
+ Raw_UString.SetFromAscii(Raw_AString);
}
bool CInArchive::IsGoodString(UInt32 param) const
@@ -1417,7 +1414,7 @@ static const char *g_WinAttrib[] =
#define FLAGS_DELIMITER '|'
-static void FlagsToString2(CDynLimBuf &s, const char **table, unsigned num, UInt32 flags)
+static void FlagsToString2(CDynLimBuf &s, const char * const *table, unsigned num, UInt32 flags)
{
bool filled = false;
for (unsigned i = 0; i < num; i++)
@@ -1536,7 +1533,7 @@ inline bool IsProbablyEndOfFunc(UInt32 flag)
return (flag != 0 && flag != CMD_REF_Goto);
}
-static const char *kOnFunc[] =
+static const char * const kOnFunc[] =
{
"Init"
, "InstSuccess"
@@ -1622,12 +1619,12 @@ static bool NoLabels(const UInt32 *labels, UInt32 num)
return true;
}
-static const char *k_REBOOTOK = " /REBOOTOK";
+static const char * const k_REBOOTOK = " /REBOOTOK";
#define MY__MB_ABORTRETRYIGNORE 2
#define MY__MB_RETRYCANCEL 5
-static const char *k_MB_Buttons[] =
+static const char * const k_MB_Buttons[] =
{
"OK"
, "OKCANCEL"
@@ -1640,7 +1637,7 @@ static const char *k_MB_Buttons[] =
#define MY__MB_ICONSTOP (1 << 4)
-static const char *k_MB_Icons[] =
+static const char * const k_MB_Icons[] =
{
NULL
, "ICONSTOP"
@@ -1649,7 +1646,7 @@ static const char *k_MB_Icons[] =
, "ICONINFORMATION"
};
-static const char *k_MB_Flags[] =
+static const char * const k_MB_Flags[] =
{
"HELP"
, "NOFOCUS"
@@ -1664,7 +1661,7 @@ static const char *k_MB_Flags[] =
#define MY__IDCANCEL 2
#define MY__IDIGNORE 5
-static const char *k_Button_IDs[] =
+static const char * const k_Button_IDs[] =
{
"0"
, "IDOK"
@@ -1702,31 +1699,6 @@ bool CInArchive::IsDirectString_Equal(UInt32 offset, const char *s) const
return strcmp((const char *)(const Byte *)_data + _stringsPos + offset, s) == 0;
}
-static UInt32 ConvertHexStringToUInt32(const char *s, const char **end)
-{
- UInt32 result = 0;
- for (int i = 0; i < 8; i++)
- {
- char c = *s;
- UInt32 v;
- if (c >= '0' && c <= '9') v = (c - '0');
- else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A');
- else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a');
- else
- {
- if (end != NULL)
- *end = s;
- return result;
- }
- result <<= 4;
- result |= v;
- s++;
- }
- if (end != NULL)
- *end = s;
- return 0;
-}
-
static bool StringToUInt32(const char *s, UInt32 &res)
{
const char *end;
@@ -1816,7 +1788,7 @@ void CInArchive::Add_Color(UInt32 v)
#define MY__SW_SHOWMINNOACTIVE 7
#define MY__SW_SHOWNA 8
-static const char *kShowWindow_Commands[] =
+static const char * const kShowWindow_Commands[] =
{
"HIDE"
, "SHOWNORMAL" // "NORMAL"
@@ -1854,7 +1826,7 @@ void CInArchive::Add_ShowWindow_Cmd(UInt32 cmd)
Add_UInt(cmd);
}
-void CInArchive::Add_TypeFromList(const char **table, unsigned tableSize, UInt32 type)
+void CInArchive::Add_TypeFromList(const char * const *table, unsigned tableSize, UInt32 type)
{
if (type < tableSize)
Script += table[type];
@@ -1886,7 +1858,7 @@ enum
};
// Names for NSIS exec_flags_t structure vars
-static const char *kExecFlags_VarsNames[] =
+static const char * const kExecFlags_VarsNames[] =
{
"AutoClose" // autoclose;
, "ShellVarContext" // all_user_var;
@@ -1940,7 +1912,7 @@ enum
PWP_CUSTOM
};
-static const char *kPageTypes[] =
+static const char * const kPageTypes[] =
{
"license"
, "components"
@@ -2062,7 +2034,7 @@ void CInArchive::AddStringLF(const char *s)
// ---------- Section ----------
-static const char *kSection_VarsNames[] =
+static const char * const kSection_VarsNames[] =
{
"Text"
, "InstTypes"
@@ -2240,7 +2212,7 @@ void CInArchive::NewLine()
static const UInt32 kPageSize = 16 * 4;
-static const char *k_SetOverwrite_Modes[] =
+static const char * const k_SetOverwrite_Modes[] =
{
"on"
, "off"
@@ -2294,7 +2266,7 @@ void CInArchive::MessageBox_MB_Part(UInt32 param)
else if (modal == 2) Script += "|MB_TASKMODAL";
else if (modal == 3) Script += "|0x3000";
UInt32 flags = (param >> 14);
- for (int i = 0; i < ARRAY_SIZE(k_MB_Flags); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(k_MB_Flags); i++)
if ((flags & (1 << i)) != 0)
{
Script += "|MB_";
@@ -2327,8 +2299,7 @@ static const UInt32 kSectionSize_16bit_Big = kSectionSize_base + 8196 * 2;
static void AddString(AString &dest, const char *src)
{
- if (!dest.IsEmpty())
- dest += ' ';
+ dest.Add_Space_if_NotEmpty();
dest += src;
}
@@ -3133,7 +3104,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
}
default: continue;
}
- for (int i = 0; mask != 0; i++, mask >>= 1)
+ for (unsigned i = 0; mask != 0; i++, mask >>= 1)
if (mask & 1)
{
UInt32 param = Get32(p + 4 + 4 * i);
@@ -3535,17 +3506,11 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
pars[i] = Get32(p2 + i * 4 + 4);
if (pars[0] == 10 + 4 && pars[2] == 0 && pars[3] == 0) // 10 + 4 means $R4
{
- ReadString2_Raw(pars[1]);
- if (IsUnicode)
- {
- if (!Raw_UString.IsEmpty())
- item.NameU = Raw_UString;
- }
- else
- {
- if (!Raw_AString.IsEmpty())
- item.NameA = Raw_AString;
- }
+ item.Prefix = -1;
+ item.NameA.Empty();
+ item.NameU.Empty();
+ SetItemName(item, pars[1]);
+ // maybe here we can restore original item name, if new name is empty
}
}
}
@@ -5011,7 +4976,7 @@ HRESULT CInArchive::SortItems()
#define CH_FLAGS_COMP_ONLY_ON_CUSTOM 256
#define CH_FLAGS_NO_CUSTOM 512
-static const char *k_PostStrings[] =
+static const char * const k_PostStrings[] =
{
"install_directory_auto_append"
, "uninstchild" // NSIS 2.25+, used by uninstaller:
@@ -5242,7 +5207,7 @@ HRESULT CInArchive::Parse()
AddRegRoot(rootKey);
AddParam(subKey);
AddParam(value);
- NewLine();
+ AddLF();
}
}
@@ -5296,6 +5261,9 @@ HRESULT CInArchive::Parse()
UInt32 langtable_size = Get32(p2 + 32);
if (bhLangTables.Num > 0)
{
+ if (langtable_size == (UInt32)(Int32)-1)
+ return E_NOTIMPL; // maybe it's old NSIS archive()
+
UInt32 numStrings = (langtable_size - 10) / 4;
_numLangStrings = numStrings;
AddLF();
@@ -5310,7 +5278,7 @@ HRESULT CInArchive::Parse()
{
const Byte *p = _data + bhLangTables.Offset + langtable_size * i;
LANGID langID = Get16(p);
- UInt32 val = Get32(p + 10 + licenseLangIndex * 4);
+ UInt32 val = Get32(p + 10 + (UInt32)licenseLangIndex * 4);
if (val != 0)
{
Script += "LicenseLangString ";
@@ -5902,6 +5870,7 @@ void CInArchive::Clear2()
Script.Empty();
LicenseFiles.Clear();
_numRootLicenses = 0;
+ _numLangStrings = 0;
langStrIDs.Clear();
LangComment.Empty();
noParseStringIndexes.Clear();
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h
index 3acd9ee5..2bab5299 100644
--- a/CPP/7zip/Archive/Nsis/NsisIn.h
+++ b/CPP/7zip/Archive/Nsis/NsisIn.h
@@ -24,6 +24,7 @@ namespace NNsis {
const size_t kScriptSizeLimit = 1 << 27;
const unsigned kSignatureSize = 16;
+extern const Byte kSignature[kSignatureSize];
#define NSIS_SIGNATURE { 0xEF, 0xBE, 0xAD, 0xDE, 'N', 'u', 'l', 'l', 's', 'o', 'f', 't', 'I', 'n', 's', 't' }
const UInt32 kFlagsMask = 0xF;
@@ -261,7 +262,7 @@ private:
void Add_ButtonID(UInt32 buttonID);
void Add_ShowWindow_Cmd(UInt32 cmd);
- void Add_TypeFromList(const char **table, unsigned tableSize, UInt32 type);
+ void Add_TypeFromList(const char * const *table, unsigned tableSize, UInt32 type);
void Add_ExecFlags(UInt32 flagsType);
void Add_SectOp(UInt32 opType);
diff --git a/CPP/7zip/Archive/Nsis/NsisRegister.cpp b/CPP/7zip/Archive/Nsis/NsisRegister.cpp
index b363bdec..7230c3c2 100644
--- a/CPP/7zip/Archive/Nsis/NsisRegister.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisRegister.cpp
@@ -9,16 +9,12 @@
namespace NArchive {
namespace NNsis {
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Nsis", "nsis", 0, 0x9,
- NArchive::NNsis::kSignatureSize, NSIS_SIGNATURE,
+REGISTER_ARC_I(
+ "Nsis", "nsis", 0, 0x9,
+ kSignature,
4,
NArcInfoFlags::kFindSignature |
NArcInfoFlags::kUseGlobalOffset,
- CreateArc };
-
-REGISTER_ARC(Nsis)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp
index 6661492f..ee630a66 100644
--- a/CPP/7zip/Archive/NtfsHandler.cpp
+++ b/CPP/7zip/Archive/NtfsHandler.cpp
@@ -22,6 +22,7 @@
#include "../Common/MethodProps.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
+#include "../Common/StreamObjects.h"
#include "../Common/StreamUtils.h"
#include "../Compress/CopyCoder.h"
@@ -62,6 +63,7 @@ static const wchar_t *kVirtualFolder_Lost_Deleted = L"[UNKNOWN]";
static const unsigned kNumSysRecs = 16;
static const unsigned kRecIndex_Volume = 3;
+static const unsigned kRecIndex_RootDir = 5;
static const unsigned kRecIndex_BadClus = 8;
static const unsigned kRecIndex_Security = 9;
@@ -198,10 +200,18 @@ enum
DEF_ATTR_TYPE(0x1000, FIRST_USER_DEFINED_ATTRIBUTE)
};
-static const Byte kFileNameType_Posix = 0;
-static const Byte kFileNameType_Win32 = 1;
-static const Byte kFileNameType_Dos = 2;
-static const Byte kFileNameType_Win32Dos = 3;
+
+/* WinXP-64:
+ Probably only one short name (dos name) per record is allowed.
+ There are no short names for hard links.
+ The pair (Win32,Dos) can be in any order.
+ Posix name can be after or before Win32 name
+*/
+
+static const Byte kFileNameType_Posix = 0; // for hard links
+static const Byte kFileNameType_Win32 = 1; // after Dos name
+static const Byte kFileNameType_Dos = 2; // short name
+static const Byte kFileNameType_Win32Dos = 3; // short and full name are same
struct CFileNameAttr
{
@@ -215,21 +225,31 @@ struct CFileNameAttr
// UInt64 AllocatedSize;
// UInt64 DataSize;
// UInt16 PackedEaSize;
- UString Name;
+ UString2 Name;
UInt32 Attrib;
Byte NameType;
bool IsDos() const { return NameType == kFileNameType_Dos; }
+ bool IsWin32() const { return (NameType == kFileNameType_Win32); }
+
bool Parse(const Byte *p, unsigned size);
};
-static void GetString(const Byte *p, unsigned len, UString &res)
+static void GetString(const Byte *p, unsigned len, UString2 &res)
{
- wchar_t *s = res.GetBuffer(len);
- for (unsigned i = 0; i < len; i++)
- s[i] = Get16(p + i * 2);
- s[len] = 0;
- res.ReleaseBuffer();
+ if (len == 0 && res.IsEmpty())
+ return;
+ wchar_t *s = res.GetBuf(len);
+ unsigned i;
+ for (i = 0; i < len; i++)
+ {
+ wchar_t c = Get16(p + i * 2);
+ if (c == 0)
+ break;
+ s[i] = c;
+ }
+ s[i] = 0;
+ res.ReleaseBuf_SetLen(i);
}
bool CFileNameAttr::Parse(const Byte *p, unsigned size)
@@ -249,7 +269,8 @@ bool CFileNameAttr::Parse(const Byte *p, unsigned size)
unsigned len = p[0x40];
if (0x42 + len > size)
return false;
- GetString(p + 0x42, len, Name);
+ if (len != 0)
+ GetString(p + 0x42, len, Name);
return true;
}
@@ -321,7 +342,7 @@ struct CAttr
{
UInt32 Type;
// UInt32 Len;
- UString Name;
+ UString2 Name;
// UInt16 Flags;
// UInt16 Instance;
CByteBuffer Data;
@@ -364,7 +385,17 @@ static int CompareAttr(void *const *elem1, void *const *elem2, void *)
const CAttr &a1 = *(*((const CAttr **)elem1));
const CAttr &a2 = *(*((const CAttr **)elem2));
RINOZ(MyCompare(a1.Type, a2.Type));
- RINOZ(wcscmp(a1.Name, a2.Name));
+ if (a1.Name.IsEmpty())
+ {
+ if (!a2.Name.IsEmpty())
+ return -1;
+ }
+ else if (a2.Name.IsEmpty())
+ return 1;
+ else
+ {
+ RINOZ(wcscmp(a1.Name.GetRawPtr(), a2.Name.GetRawPtr()));
+ }
return MyCompare(a1.LowVcn, a2.LowVcn);
}
@@ -387,13 +418,13 @@ UInt32 CAttr::Parse(const Byte *p, unsigned size)
return 0;
NonResident = p[0x08];
{
- unsigned nameLength = p[9];
+ unsigned nameLen = p[9];
UInt32 nameOffset = Get16(p + 0x0A);
- if (nameLength != 0)
+ if (nameLen != 0)
{
- if (nameOffset + nameLength * 2 > len)
+ if (nameOffset + nameLen * 2 > len)
return 0;
- GetString(p + nameOffset, nameLength, Name);
+ GetString(p + nameOffset, nameLen, Name);
PRF(printf(" N="));
PRF_UTF16(Name);
}
@@ -485,10 +516,11 @@ bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax,
if (num == 0 || num > 8 || num > size)
return false;
- int i;
- UInt64 vSize = p[num - 1];
- for (i = (int)num - 2; i >= 0; i--)
- vSize = (vSize << 8) | p[i];
+ UInt64 vSize = 0;
+ {
+ unsigned i = num;
+ do vSize = (vSize << 8) | p[--i]; while(i);
+ }
if (vSize == 0)
return false;
p += num;
@@ -510,8 +542,10 @@ bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax,
else
{
Int64 v = (signed char)p[num - 1];
- for (i = (int)num - 2; i >= 0; i--)
- v = (v << 8) | p[i];
+ {
+ for (unsigned i = num - 1; i != 0;)
+ v = (v << 8) | p[--i];
+ }
p += num;
size -= num;
lcn += v;
@@ -617,7 +651,7 @@ static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte
{
if (destSize + (1 << 12) > outBufLim || (src[0] & 1) != 0)
return 0;
- int numDistBits = 4;
+ unsigned numDistBits = 4;
UInt32 sbOffset = 0;
UInt32 pos = 0;
@@ -669,7 +703,7 @@ static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte
STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = 0;
if (_virtPos >= Size)
return (Size == _virtPos) ? S_OK: E_FAIL;
@@ -830,7 +864,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
res = Stream->Read(data, size, &size);
_physPos += size;
}
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = size;
_virtPos += size;
_curRem -= size;
@@ -858,54 +892,6 @@ STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPositio
return S_OK;
}
-class CByteBufStream:
- public IInStream,
- public CMyUnknownImp
-{
- UInt64 _virtPos;
-public:
- CByteBuffer Buf;
- void Init() { _virtPos = 0; }
-
- MY_UNKNOWN_IMP1(IInStream)
-
- STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
- STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
-};
-
-STDMETHODIMP CByteBufStream::Read(void *data, UInt32 size, UInt32 *processedSize)
-{
- if (processedSize != NULL)
- *processedSize = 0;
- if (_virtPos >= Buf.Size())
- return (_virtPos == Buf.Size()) ? S_OK: E_FAIL;
- UInt64 rem = Buf.Size() - _virtPos;
- if (rem < size)
- size = (UInt32)rem;
- memcpy(data, Buf + (size_t)_virtPos, size);
- if (processedSize != NULL)
- *processedSize = size;
- _virtPos += size;
- return S_OK;
-}
-
-STDMETHODIMP CByteBufStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
-{
- switch (seekOrigin)
- {
- case STREAM_SEEK_SET: break;
- case STREAM_SEEK_CUR: offset += _virtPos; break;
- case STREAM_SEEK_END: offset += Buf.Size(); break;
- default: return STG_E_INVALIDFUNCTION;
- }
- if (offset < 0)
- return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
- _virtPos = offset;
- if (newPosition)
- *newPosition = offset;
- return S_OK;
-}
-
static HRESULT DataParseExtents(unsigned clusterSizeLog, const CObjectVector<CAttr> &attrs,
unsigned attrIndex, unsigned attrIndexLim, UInt64 numPhysClusters, CRecordVector<CExtent> &Extents)
{
@@ -966,7 +952,9 @@ struct CMftRec
// UInt16 NextAttrInstance;
CMftRef BaseMftRef;
// UInt32 ThisRecNumber;
+
UInt32 MyNumNameLinks;
+ int MyItemIndex; // index in Items[] of main item for that record, or -1 if there is no item for that record
CObjectVector<CAttr> DataAttrs;
CObjectVector<CFileNameAttr> FileNames;
@@ -977,12 +965,40 @@ struct CMftRec
CByteBuffer ReparseData;
+ int FindWin32Name_for_DosName(unsigned dosNameIndex) const
+ {
+ const CFileNameAttr &cur = FileNames[dosNameIndex];
+ if (cur.IsDos())
+ for (unsigned i = 0; i < FileNames.Size(); i++)
+ {
+ const CFileNameAttr &next = FileNames[i];
+ if (next.IsWin32() && cur.ParentDirRef.Val == next.ParentDirRef.Val)
+ return i;
+ }
+ return -1;
+ }
+
+ int FindDosName(unsigned nameIndex) const
+ {
+ const CFileNameAttr &cur = FileNames[nameIndex];
+ if (cur.IsWin32())
+ for (unsigned i = 0; i < FileNames.Size(); i++)
+ {
+ const CFileNameAttr &next = FileNames[i];
+ if (next.IsDos() && cur.ParentDirRef.Val == next.ParentDirRef.Val)
+ return i;
+ }
+ return -1;
+ }
+
+ /*
bool IsAltStream(int dataIndex) const
{
return dataIndex >= 0 && (
(IsDir() ||
!DataAttrs[DataRefs[dataIndex].Start].Name.IsEmpty()));
}
+ */
void MoveAttrsFrom(CMftRec &src)
{
@@ -1016,7 +1032,7 @@ struct CMftRec
UInt64 GetSize(unsigned dataIndex) const { return DataAttrs[DataRefs[dataIndex].Start].GetSize(); }
- CMftRec(): MyNumNameLinks(0) {}
+ CMftRec(): MyNumNameLinks(0), MyItemIndex(-1) {}
};
void CMftRec::ParseDataNames()
@@ -1040,12 +1056,10 @@ HRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex,
unsigned clusterSizeLog, UInt64 numPhysClusters, IInStream **destStream) const
{
*destStream = 0;
- CByteBufStream *streamSpec = new CByteBufStream;
+ CBufferInStream *streamSpec = new CBufferInStream;
CMyComPtr<IInStream> streamTemp = streamSpec;
- if (dataIndex < 0)
- return E_FAIL;
-
+ if (dataIndex >= 0)
if ((unsigned)dataIndex < DataRefs.Size())
{
const CDataRef &ref = DataRefs[dataIndex];
@@ -1231,26 +1245,42 @@ bool CMftRec::Parse(Byte *p, unsigned sectorSizeLog, UInt32 numSectors, UInt32 r
return true;
}
+/*
+ NTFS probably creates empty DATA_ATTRIBUTE for empty file,
+ But it doesn't do it for
+ $Secure (:$SDS),
+ $Extend\$Quota
+ $Extend\$ObjId
+ $Extend\$Reparse
+*/
+
+static const int k_Item_DataIndex_IsEmptyFile = -1; // file without unnamed data stream
+static const int k_Item_DataIndex_IsDir = -2;
+
+// static const int k_ParentFolderIndex_Root = -1;
+static const int k_ParentFolderIndex_Lost = -2;
+static const int k_ParentFolderIndex_Deleted = -3;
+
struct CItem
{
unsigned RecIndex; // index in Recs array
unsigned NameIndex; // index in CMftRec::FileNames
int DataIndex; /* index in CMftRec::DataRefs
- -1: for folders
- -1: for files that have no DATA_ATRIBUTE */
+ -1: file without unnamed data stream
+ -2: for directories */
int ParentFolder; /* index in Items array
-1: for root items
-2: [LOST] folder
-3: [UNKNOWN] folder (deleted lost) */
int ParentHost; /* index in Items array, if it's AltStream
- -1: if it's not AltStream
- -1: if there is no Host item */
+ -1: if it's not AltStream */
- CItem(): DataIndex(-1), ParentFolder(-1), ParentHost(-1) {}
+ CItem(): DataIndex(k_Item_DataIndex_IsDir), ParentFolder(-1), ParentHost(-1) {}
- bool IsDir() const { return DataIndex < 0; }
+ bool IsAltStream() const { return ParentHost != -1; }
+ bool IsDir() const { return DataIndex == k_Item_DataIndex_IsDir; }
// check it !!!
// probably NTFS for empty file still creates empty DATA_ATTRIBUTE
// But it doesn't do it for $Secure:$SDS
@@ -1276,7 +1306,9 @@ struct CDatabase
bool _showSystemFiles;
bool _showDeletedFiles;
- UStringVector VirtFolderNames;
+ CObjectVector<UString2> VirtFolderNames;
+ UString EmptyString;
+
int _systemFolderIndex;
int _lostFolderIndex_Normal;
int _lostFolderIndex_Deleted;
@@ -1311,6 +1343,8 @@ struct CDatabase
const CMftRec &rec = Recs[(unsigned)recIndex];
if (!rec.IsDir())
return -1;
+ return rec.MyItemIndex;
+ /*
unsigned left = 0, right = Items.Size();
while (left != right)
{
@@ -1319,9 +1353,9 @@ struct CDatabase
UInt64 midValue = item.RecIndex;
if (recIndex == midValue)
{
- // if (!item.IsAltStream)
- // if (!rec.IsAltStream(item.DataIndex))
- if (item.DataIndex < 0)
+ // if item is not dir (file or alt stream we don't return it)
+ // if (item.DataIndex < 0)
+ if (item.IsDir())
return mid;
right = mid;
}
@@ -1331,6 +1365,7 @@ struct CDatabase
left = mid + 1;
}
return -1;
+ */
}
bool FindSecurityDescritor(UInt32 id, UInt64 &offset, UInt32 &size) const;
@@ -1374,8 +1409,6 @@ void CDatabase::ClearAndClose()
InStream.Release();
}
-#define MY_DIR_PREFIX(x) L"[" x L"]" WSTRING_PATH_SEPARATOR
-
void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
{
const CItem *item = &Items[index];
@@ -1383,22 +1416,24 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
const CMftRec &rec = Recs[item->RecIndex];
size += rec.FileNames[item->NameIndex].Name.Len();
- bool isAltStream = rec.IsAltStream(item->DataIndex);
+ bool isAltStream = item->IsAltStream();
+
if (isAltStream)
{
const CAttr &data = rec.DataAttrs[rec.DataRefs[item->DataIndex].Start];
+ if (item->RecIndex == kRecIndex_RootDir)
+ {
+ wchar_t *s = path.AllocBstr(data.Name.Len() + 1);
+ s[0] = L':';
+ if (!data.Name.IsEmpty())
+ MyStringCopy(s + 1, data.Name.GetRawPtr());
+ return;
+ }
+
size += data.Name.Len();
size++;
}
- /*
- if (item->ParentHost >= 0)
- {
- item = &Items[item->ParentHost];
- size += item->Name.Len() + 1;
- }
- */
-
for (unsigned i = 0;; i++)
{
if (i > 256)
@@ -1407,7 +1442,8 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
return;
}
const wchar_t *servName;
- if (item->RecIndex < kNumSysRecs)
+ if (item->RecIndex < kNumSysRecs
+ /* && item->RecIndex != kRecIndex_RootDir */)
servName = kVirtualFolder_System;
else
{
@@ -1420,7 +1456,7 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
}
if (index2 == -1)
break;
- servName = (index2 == -2) ?
+ servName = (index2 == k_ParentFolderIndex_Lost) ?
kVirtualFolder_Lost_Normal :
kVirtualFolder_Lost_Deleted;
}
@@ -1435,47 +1471,31 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
bool needColon = false;
if (isAltStream)
{
- const UString &name = rec.DataAttrs[rec.DataRefs[item->DataIndex].Start].Name;
- size -= name.Len();
- MyStringCopy(s + size, (const wchar_t *)name);
+ const UString2 &name = rec.DataAttrs[rec.DataRefs[item->DataIndex].Start].Name;
+ if (!name.IsEmpty())
+ {
+ size -= name.Len();
+ MyStringCopy(s + size, name.GetRawPtr());
+ }
s[--size] = ':';
needColon = true;
}
{
- const UString &name = rec.FileNames[item->NameIndex].Name;
+ const UString2 &name = rec.FileNames[item->NameIndex].Name;
unsigned len = name.Len();
- MyStringCopy(s + size - len, (const wchar_t *)name);
+ if (len != 0)
+ MyStringCopy(s + size - len, name.GetRawPtr());
if (needColon)
s[size] = ':';
size -= len;
}
- /*
- {
- unsigned len = item->Name.Len();
- size -= len;
- MyStringCopy(s + size, (const wchar_t *)item->Name);
- }
- */
-
-
- /*
- if (item->ParentHost >= 0)
- {
- item = &Items[item->ParentHost];
- unsigned len = item->Name.Len();
- size--;
- size -= len;
- MyStringCopy(s + size, (const wchar_t *)item->Name);
- s[size + len] = ':';
- }
- */
-
for (;;)
{
const wchar_t *servName;
- if (item->RecIndex < kNumSysRecs)
+ if (item->RecIndex < kNumSysRecs
+ /* && && item->RecIndex != kRecIndex_RootDir */)
servName = kVirtualFolder_System;
else
{
@@ -1483,17 +1503,20 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
if (index2 >= 0)
{
item = &Items[index2];
- const UString &name = Recs[item->RecIndex].FileNames[item->NameIndex].Name;
+ const UString2 &name = Recs[item->RecIndex].FileNames[item->NameIndex].Name;
unsigned len = name.Len();
size--;
- size -= len;
- MyStringCopy(s + size, (const wchar_t *)name);
+ if (len != 0)
+ {
+ size -= len;
+ MyStringCopy(s + size, name.GetRawPtr());
+ }
s[size + len] = WCHAR_PATH_SEPARATOR;
continue;
}
if (index2 == -1)
break;
- servName = (index2 == -2) ?
+ servName = (index2 == k_ParentFolderIndex_Lost) ?
kVirtualFolder_Lost_Normal :
kVirtualFolder_Lost_Deleted;
}
@@ -1800,120 +1823,110 @@ HRESULT CDatabase::Open()
if (!rec.InUse() && !_showDeletedFiles)
continue;
- unsigned numNames = 0;
+ rec.MyNumNameLinks = rec.FileNames.Size();
+
// printf("\n%4d: ", i);
- FOR_VECTOR (t, rec.FileNames)
- {
- const CFileNameAttr &fna = rec.FileNames[t];
- // PRF(printf("%4d ", (int)fna.NameType));
- // PRF_UTF16(fna.Name)
- // PRF(printf(" | "));
- if (fna.IsDos())
- continue;
- unsigned numDatas = rec.DataRefs.Size();
-
- /*
- // we can use that code to reduce the number of alt streams
- // For hard linked files we show alt streams only for first Name.
- if (numDatas > 1 && numNames > 0)
- numDatas = 1;
- */
+
+ /* Actually DataAttrs / DataRefs are sorted by name.
+ It can not be more than one unnamed stream in DataRefs
+ And indexOfUnnamedStream <= 0.
+ */
- numNames++;
+ int indexOfUnnamedStream = -1;
+ if (!rec.IsDir())
+ {
+ FOR_VECTOR(di, rec.DataRefs)
+ if (rec.DataAttrs[rec.DataRefs[di].Start].Name.IsEmpty())
+ {
+ indexOfUnnamedStream = di;
+ break;
+ }
+ }
- // here we suppose that first stream is main stream (unnamed stream).
- // IS IT SO ????
- int hostIndex = -1;
- if (rec.IsDir())
+ if (rec.FileNames.IsEmpty())
+ {
+ bool needShow = true;
+ if (i < kNumSysRecs)
{
- CItem item;
- item.NameIndex = t;
- item.RecIndex = i;
- // item.ParentRef = fna.ParentDirRef;
- // item.Attrib = rec.SiAttr.Attrib | 0x10;
- // item.Attrib = fna.Attrib;
- hostIndex = Items.Add(item);
+ needShow = false;
+ FOR_VECTOR(di, rec.DataRefs)
+ if (rec.GetSize(di) != 0)
+ {
+ needShow = true;
+ break;
+ }
}
- else
+ if (needShow)
{
-
- // probably NTFS for empty file still creates empty DATA_ATTRIBUTE
- // But it doesn't do it for $Secure:$SDS
- if (rec.DataRefs.IsEmpty() ||
- !rec.DataAttrs[rec.DataRefs[0].Start].Name.IsEmpty())
- {
- CItem item;
- item.NameIndex = t;
- item.RecIndex = i;
- // item.ParentRef = fna.ParentDirRef;
- // item.Attrib = rec.SiAttr.Attrib;
- hostIndex = Items.Add(item);
- }
+ CFileNameAttr &fna = rec.FileNames.AddNew();
+ // we set incorrect ParentDirRef, that will place item to [LOST] folder
+ fna.ParentDirRef.Val = (UInt64)(Int64)-1;
+ char s[16 + 16];
+ ConvertUInt32ToString(i, MyStpCpy(s, "[NONAME]-"));
+ fna.Name.SetFromAscii(s);
+ fna.NameType = kFileNameType_Win32Dos;
+ fna.Attrib = 0;
}
+ }
+
+ // bool isMainName = true;
+
+ FOR_VECTOR (t, rec.FileNames)
+ {
+ #ifdef SHOW_DEBUG_INFO
+ const CFileNameAttr &fna = rec.FileNames[t];
+ #endif
+ PRF(printf("\n %4d ", (int)fna.NameType));
+ PRF_UTF16(fna.Name);
+ // PRF(printf(" | "));
+ if (rec.FindWin32Name_for_DosName(t) >= 0)
{
- bool isThereUnNamedStream = false;
- for (unsigned di = 0; di < numDatas; di++)
- {
- const UString &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name;
- if (subName.IsEmpty())
- isThereUnNamedStream = true;
- }
- if (!rec.IsDir() && !isThereUnNamedStream)
- {
- // return S_FALSE;
- }
+ rec.MyNumNameLinks--;
+ continue;
}
+
+ CItem item;
+ item.NameIndex = t;
+ item.RecIndex = i;
+ item.DataIndex = rec.IsDir() ?
+ k_Item_DataIndex_IsDir :
+ (indexOfUnnamedStream < 0 ?
+ k_Item_DataIndex_IsEmptyFile :
+ indexOfUnnamedStream);
+
+ if (rec.MyItemIndex < 0)
+ rec.MyItemIndex = Items.Size();
+ item.ParentHost = Items.Add(item);
+
+ /* we can use that code to reduce the number of alt streams:
+ it will not show how alt streams for hard links. */
+ // if (!isMainName) continue; isMainName = false;
+
+ unsigned numAltStreams = 0;
- for (unsigned di = 0; di < numDatas; di++)
+ FOR_VECTOR(di, rec.DataRefs)
{
- CItem item;
- item.NameIndex = t;
- // item.FileNameAttr = fna;
- // item.Name = fna.Name;
- // item.Attrib = rec.SiAttr.Attrib;
- const UString &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name;
- if (subName.IsEmpty())
- {
- if (hostIndex >= 0)
- continue;
- hostIndex = Items.Size();
- }
- else
+ if (!rec.IsDir() && (int)di == indexOfUnnamedStream)
+ continue;
+
+ const UString2 &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name;
+
+ PRF(printf("\n alt stream: "));
+ PRF_UTF16(subName);
+
{
// $BadClus:$Bad is sparse file for all clusters. So we skip it.
if (i == kRecIndex_BadClus && subName == L"$Bad")
continue;
- if (hostIndex >= 0)
- {
- // item.Name = subName;
- }
- else
- {
- // there is no host file for some streams
- // return E_FAIL;
- // item.Name += L":";
- // item.Name += subName;
- }
- // item.Attrib = fna.Attrib;
- item.ParentHost = hostIndex;
- // item.IsAltStream = true;
- ThereAreAltStreams = true;
}
-
- PRF(printf("\n%3d", i));
- PRF(printf(" attrib=%2x ", rec.SiAttr.Attrib));
- // PRF_UTF16(item.Name);
-
- item.RecIndex = i;
- item.DataIndex = di;
- // item.ParentRef = fna.ParentDirRef;
+ numAltStreams++;
+ ThereAreAltStreams = true;
+ item.DataIndex = di;
Items.Add(item);
- rec.MyNumNameLinks++;
}
}
- // rec.FileNames.ClearAndFree();
}
if (Recs.Size() > kRecIndex_Security)
@@ -1959,7 +1972,7 @@ HRESULT CDatabase::Open()
const CFileNameAttr &fn = rec.FileNames[item.NameIndex];
const CMftRef &parentDirRef = fn.ParentDirRef;
UInt64 refIndex = parentDirRef.GetIndex();
- if (refIndex == 5)
+ if (refIndex == kRecIndex_RootDir)
item.ParentFolder = -1;
else
{
@@ -1970,12 +1983,12 @@ HRESULT CDatabase::Open()
if (Recs[item.RecIndex].InUse())
{
thereAreUnknownFolders_Normal = true;
- index = -2;
+ index = k_ParentFolderIndex_Lost;
}
else
{
thereAreUnknownFolders_Deleted = true;
- index = -3;
+ index = k_ParentFolderIndex_Deleted;
}
}
item.ParentFolder = index;
@@ -2019,7 +2032,7 @@ public:
INTERFACE_IInArchive(;)
INTERFACE_IArchiveGetRawProps(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
};
STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps)
@@ -2038,29 +2051,30 @@ STDMETHODIMP CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID)
STDMETHODIMP CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType)
{
*parentType = NParentType::kDir;
- *parent = (UInt32)(Int32)-1;
+ int par = -1;
- if (index >= Items.Size())
- return S_OK;
- const CItem &item = Items[index];
-
- if (item.ParentHost >= 0)
- {
- *parentType = NParentType::kAltStream;
- *parent = (UInt32)(Int32)item.ParentHost;
- return S_OK;
- }
- if (item.RecIndex < kNumSysRecs)
+ if (index < Items.Size())
{
- if (_showSystemFiles)
- *parent = _systemFolderIndex;
- }
- else if (item.ParentFolder >= 0)
- *parent = item.ParentFolder;
- else if (item.ParentFolder == -2)
- *parent = _lostFolderIndex_Normal;
- else if (item.ParentFolder == -3)
- *parent = _lostFolderIndex_Deleted;
+ const CItem &item = Items[index];
+
+ if (item.ParentHost >= 0)
+ {
+ *parentType = NParentType::kAltStream;
+ par = (item.RecIndex == kRecIndex_RootDir ? -1 : item.ParentHost);
+ }
+ else if (item.RecIndex < kNumSysRecs)
+ {
+ if (_showSystemFiles)
+ par = _systemFolderIndex;
+ }
+ else if (item.ParentFolder >= 0)
+ par = item.ParentFolder;
+ else if (item.ParentFolder == k_ParentFolderIndex_Lost)
+ par = _lostFolderIndex_Normal;
+ else if (item.ParentFolder == k_ParentFolderIndex_Deleted)
+ par = _lostFolderIndex_Deleted;
+ }
+ *parent = (UInt32)(Int32)par;
return S_OK;
}
@@ -2073,30 +2087,22 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data
if (propID == kpidName)
{
#ifdef MY_CPU_LE
- const UString *s;
+ const UString2 *s;
if (index >= Items.Size())
s = &VirtFolderNames[index - Items.Size()];
else
{
const CItem &item = Items[index];
const CMftRec &rec = Recs[item.RecIndex];
-
- // fix it for no HOST case !!
- // if (item.IsAltStream && item.DataIndex >= 0)
- if (rec.IsAltStream(item.DataIndex))
- {
- if (item.ParentHost < 0)
- return S_OK;
- const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];
- s = &data.Name;
- }
+ if (item.IsAltStream())
+ s = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start].Name;
else
- {
s = &rec.FileNames[item.NameIndex].Name;
- }
- // s = &item.Name;
}
- *data = (const wchar_t *)*s;
+ if (s->IsEmpty())
+ *data = (const wchar_t *)EmptyString;
+ else
+ *data = s->GetRawPtr();
*dataSize = (s->Len() + 1) * sizeof(wchar_t);
*propType = PROP_DATA_TYPE_wchar_t_PTR_Z_LE;
#endif
@@ -2209,6 +2215,9 @@ static const Byte kProps[] =
kpidLinks,
kpidINode,
kpidNumBlocks,
+ kpidNumAltStreams,
+ kpidIsAltStream,
+ kpidShortName,
kpidIsDeleted
};
@@ -2293,9 +2302,10 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
const CAttr &attr = VolAttrs[i];
if (attr.Type == ATTR_TYPE_VOLUME_NAME)
{
- UString name;
+ UString2 name;
GetString(attr.Data, (unsigned)attr.Data.Size() / 2, name);
- prop = name;
+ if (!name.IsEmpty())
+ prop = name.GetRawPtr();
break;
}
}
@@ -2312,7 +2322,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
CVolInfo vi;
if (attr.ParseVolInfo(vi))
{
- s += ' ';
+ s.Add_Space();
char temp[16];
ConvertUInt32ToString(vi.MajorVer, temp);
s += temp;
@@ -2339,6 +2349,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidWarning:
if (_lostFolderIndex_Normal >= 0)
prop = "There are lost files";
+ break;
/*
case kpidWarningFlags:
@@ -2372,7 +2383,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
case kpidName:
case kpidPath:
- prop = VirtFolderNames[index - Items.Size()];
+ prop = VirtFolderNames[index - Items.Size()].GetRawPtr();
break;
case kpidIsDir: prop = true; break;
case kpidIsAux: prop = true; break;
@@ -2433,35 +2444,46 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = item.RecIndex;
break;
}
+ case kpidStreamId:
+ {
+ if (item.DataIndex >= 0)
+ prop = ((UInt64)item.RecIndex << 32) | (unsigned)item.DataIndex;
+ break;
+ }
case kpidName:
{
- // prop = item.Name;
- const UString *s;
- if (rec.IsAltStream(item.DataIndex))
+ const UString2 *s;
+ if (item.IsAltStream())
+ s = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start].Name;
+ else
+ s = &rec.FileNames[item.NameIndex].Name;
+ if (s->IsEmpty())
+ prop = (const wchar_t *)EmptyString;
+ else
+ prop = s->GetRawPtr();
+ break;
+ }
+
+ case kpidShortName:
+ {
+ if (!item.IsAltStream())
{
- const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];
- s = &data.Name;
- if (item.ParentHost < 0)
+ int dosNameIndex = rec.FindDosName(item.NameIndex);
+ if (dosNameIndex >= 0)
{
- UString s2 = rec.FileNames[item.NameIndex].Name;
- s2 += L':';
- s2 += *s;
- prop = s2;
- break;
+ const UString2 &s = rec.FileNames[dosNameIndex].Name;
+ if (s.IsEmpty())
+ prop = (const wchar_t *)EmptyString;
+ else
+ prop = s.GetRawPtr();
}
}
- else
- {
- s = &rec.FileNames[item.NameIndex].Name;
- }
- prop = *s;
-
break;
}
case kpidIsDir: prop = item.IsDir(); break;
- case kpidIsAltStream: prop = rec.IsAltStream(item.DataIndex); break;
+ case kpidIsAltStream: prop = item.IsAltStream(); break;
case kpidIsDeleted: prop = !rec.InUse(); break;
case kpidIsAux: prop = false; break;
@@ -2491,12 +2513,35 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
if (item.IsDir())
attrib |= FILE_ATTRIBUTE_DIRECTORY;
+ /* some system entries can contain extra flags (Index View).
+ // 0x10000000 (Directory)
+ // 0x20000000 FILE_ATTR_VIEW_INDEX_PRESENT MFT_RECORD_IS_VIEW_INDEX (Index View)
+ But we don't need them */
+ attrib &= 0xFFFF;
+
prop = attrib;
break;
}
- case kpidLinks: prop = rec.MyNumNameLinks; break;
- case kpidSize: if (data) prop = data->GetSize(); break;
- case kpidPackSize: if (data) prop = data->GetPackSize(); break;
+ case kpidLinks: if (rec.MyNumNameLinks != 1) prop = rec.MyNumNameLinks; break;
+
+ case kpidNumAltStreams:
+ {
+ if (!item.IsAltStream())
+ {
+ unsigned num = rec.DataRefs.Size();
+ if (num > 0)
+ {
+ if (!rec.IsDir() && rec.DataAttrs[rec.DataRefs[0].Start].Name.IsEmpty())
+ num--;
+ if (num > 0)
+ prop = num;
+ }
+ }
+ break;
+ }
+
+ case kpidSize: if (data) prop = data->GetSize(); else if (!item.IsDir()) prop = (UInt64)0; break;
+ case kpidPackSize: if (data) prop = data->GetPackSize(); else if (!item.IsDir()) prop = (UInt64)0; break;
case kpidNumBlocks: if (data) prop = (UInt32)rec.GetNumExtents(item.DataIndex, Header.ClusterSizeLog, Header.NumClusters); break;
}
prop.Detach(value);
@@ -2603,7 +2648,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
outStreamSpec->Init();
const CMftRec &rec = Recs[item.RecIndex];
- const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];
int res = NExtract::NOperationResult::kDataError;
{
@@ -2626,8 +2670,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
}
}
- totalPackSize += data.GetPackSize();
- totalSize += data.GetSize();
+ if (item.DataIndex >= 0)
+ {
+ const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];
+ totalPackSize += data.GetPackSize();
+ totalSize += data.GetSize();
+ }
outStreamSpec->ReleaseStream();
RINOK(extractCallback->SetOperationResult(res));
}
@@ -2641,7 +2689,7 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK;
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
InitProps();
@@ -2668,15 +2716,13 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
return S_OK;
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 };
-static CArcInfo g_ArcInfo =
- { "NTFS", "ntfs img", 0, 0xD9,
- 9, { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 },
+REGISTER_ARC_I(
+ "NTFS", "ntfs img", 0, 0xD9,
+ k_Signature,
3,
0,
- CreateArc };
-
-REGISTER_ARC(Ntfs)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp
index ae7553df..43450e80 100644
--- a/CPP/7zip/Archive/PeHandler.cpp
+++ b/CPP/7zip/Archive/PeHandler.cpp
@@ -37,7 +37,7 @@ using namespace NWindows;
namespace NArchive {
namespace NPe {
-static const UInt32 k_Signature = 0x00004550;
+static const UInt32 k_Signature32 = 0x00004550;
static HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 excludePos, UInt32 &res)
{
@@ -137,7 +137,7 @@ struct CHeader
bool CHeader::Parse(const Byte *p)
{
- if (Get32(p) != k_Signature)
+ if (Get32(p) != k_Signature32)
return false;
p += 4;
G16( 0, Machine);
@@ -364,19 +364,14 @@ struct CSection
static const unsigned kNameSize = 8;
-static AString GetName(const Byte *name)
+static void GetName(const Byte *name, AString &res)
{
- AString res;
- char *p = res.GetBuffer(kNameSize);
- memcpy(p, name, kNameSize);
- p[kNameSize] = 0;
- res.ReleaseBuffer();
- return res;
+ res.SetFrom_CalcLen((const char *)name, kNameSize);
}
void CSection::Parse(const Byte *p)
{
- Name = GetName(p);
+ GetName(p, Name);
G32( 8, VSize);
G32(12, Va);
G32(16, PSize);
@@ -484,33 +479,33 @@ static const CUInt32PCharPair g_SubSystems[] =
{ 14, "XBOX" }
};
-static const wchar_t *g_ResTypes[] =
+static const char * const g_ResTypes[] =
{
NULL
- , L"CURSOR"
- , L"BITMAP"
- , L"ICON"
- , L"MENU"
- , L"DIALOG"
- , L"STRING"
- , L"FONTDIR"
- , L"FONT"
- , L"ACCELERATOR"
- , L"RCDATA"
- , L"MESSAGETABLE"
- , L"GROUP_CURSOR"
+ , "CURSOR"
+ , "BITMAP"
+ , "ICON"
+ , "MENU"
+ , "DIALOG"
+ , "STRING"
+ , "FONTDIR"
+ , "FONT"
+ , "ACCELERATOR"
+ , "RCDATA"
+ , "MESSAGETABLE"
+ , "GROUP_CURSOR"
, NULL
- , L"GROUP_ICON"
+ , "GROUP_ICON"
, NULL
- , L"VERSION"
- , L"DLGINCLUDE"
+ , "VERSION"
+ , "DLGINCLUDE"
, NULL
- , L"PLUGPLAY"
- , L"VXD"
- , L"ANICURSOR"
- , L"ANIICON"
- , L"HTML"
- , L"MANIFEST"
+ , "PLUGPLAY"
+ , "VXD"
+ , "ANICURSOR"
+ , "ANIICON"
+ , "HTML"
+ , "MANIFEST"
};
static const UInt32 kFlag = (UInt32)1 << 31;
@@ -561,7 +556,10 @@ struct CTextFile
void NewLine();
void AddString(const char *s);
void AddSpaces(int num);
- void AddBytes(const Byte *p, size_t len);
+ void AddBytes(const Byte *p, size_t size)
+ {
+ Buf.AddData(p, size);
+ }
void OpenBlock(int num)
{
@@ -623,12 +621,6 @@ void CTextFile::AddSpaces(int num)
AddChar(' ');
}
-void CTextFile::AddBytes(const Byte *data, size_t size)
-{
- Byte *p = Buf.GetCurPtrAndGrow(size);
- memcpy(p, data, size);
-}
-
struct CStringItem: public CTextFile
{
UInt32 Lang;
@@ -648,7 +640,7 @@ struct CMixItem
int VersionIndex;
CMixItem(): SectionIndex(-1), ResourceIndex(-1), StringIndex(-1), VersionIndex(-1) {}
- bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0 && VersionIndex < 0; };
+ bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0 && VersionIndex < 0; }
};
struct CUsedBitmap
@@ -802,6 +794,7 @@ static const STATPROPSTG kArcProps[] =
{ (LPOLESTR)L"Heap Commit", kpidHeapCommit, VT_UI8},
{ (LPOLESTR)L"Image Base", kpidImageBase, VT_UI8},
{ NULL, kpidComment, VT_BSTR},
+
// { (LPOLESTR)L"Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8},
// { (LPOLESTR)L"Base Of Code", kpidBaseOfCode, VT_UI8},
// { (LPOLESTR)L"Base Of Data", kpidBaseOfData32, VT_UI8},
@@ -913,7 +906,7 @@ HRESULT CHandler::ReadString(UInt32 offset, UString &dest) const
if ((rem - 2) / 2 < len)
return S_FALSE;
dest.Empty();
- wchar_t *destBuf = dest.GetBuffer(len);
+ wchar_t *destBuf = dest.GetBuf(len);
offset += 2;
const Byte *src = _buf + offset;
unsigned i;
@@ -924,7 +917,8 @@ HRESULT CHandler::ReadString(UInt32 offset, UString &dest) const
break;
destBuf[i] = c;
}
- dest.ReleaseBuffer(i);
+ destBuf[i] = 0;
+ dest.ReleaseBuf_SetLen(i);
return S_OK;
}
@@ -960,7 +954,7 @@ void CHandler::AddLangPrefix(UString &s, UInt32 lang) const
if (!_oneLang)
{
AddResNameToString(s, lang);
- s += WCHAR_PATH_SEPARATOR;
+ s.Add_PathSepar();
}
}
@@ -978,7 +972,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
UString s = _resourcesPrefix;
AddLangPrefix(s, item.Lang);
- s += L"string.txt";
+ s.AddAscii("string.txt");
prop = s;
break;
}
@@ -996,7 +990,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
UString s = _resourcesPrefix;
AddLangPrefix(s, item.Lang);
- s += L"version.txt";
+ s.AddAscii("version.txt");
prop = s;
break;
}
@@ -1015,22 +1009,22 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
UString s = _resourcesPrefix;
AddLangPrefix(s, item.Lang);
{
- const wchar_t *p = NULL;
+ const char *p = NULL;
if (item.Type < ARRAY_SIZE(g_ResTypes))
p = g_ResTypes[item.Type];
if (p)
- s += p;
+ s.AddAscii(p);
else
AddResNameToString(s, item.Type);
}
- s += WCHAR_PATH_SEPARATOR;
+ s.Add_PathSepar();
AddResNameToString(s, item.ID);
if (item.HeaderSize != 0)
{
if (item.IsBmp())
- s += L".bmp";
+ s.AddAscii(".bmp");
else if (item.IsIcon())
- s += L".ico";
+ s.AddAscii(".ico");
}
prop = s;
break;
@@ -1199,11 +1193,14 @@ static UInt32 SetBitmapHeader(Byte *dest, const Byte *src, UInt32 size)
return 0;
if (h.YSize < 0)
h.YSize = -h.YSize;
- if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 || h.BitCount > 32 ||
- h.Compression != 0) // BI_RGB
+ if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 || h.BitCount > 32)
return 0;
if (h.SizeImage == 0)
+ {
+ if (h.Compression != 0) // BI_RGB
+ return 0;
h.SizeImage = GetImageSize(h.XSize, h.YSize, h.BitCount);
+ }
UInt32 totalSize = kBmpHeaderSize + size;
UInt32 offBits = totalSize - h.SizeImage;
// BITMAPFILEHEADER
@@ -1413,7 +1410,7 @@ static void PrintVersion(UString &s, UInt32 ms, UInt32 ls)
PrintUInt32(s, LOWORD(ls));
}
-static const char *k_VS_FileFlags[] =
+static const char * const k_VS_FileFlags[] =
{
"DEBUG"
, "PRERELEASE"
@@ -1432,7 +1429,7 @@ static const CUInt32PCharPair k_VS_FileOS[] =
{ 0x40004, "VOS_NT_WINDOWS32" }
};
-static const char *k_VS_FileOS_High[] =
+static const char * const k_VS_FileOS_High[] =
{
"VOS_UNKNOWN"
, "VOS_DOS"
@@ -1445,7 +1442,7 @@ static const char *k_VS_FileOS_High[] =
static const UInt32 kMY_VFT_DRV = 3;
static const UInt32 kMY_VFT_FONT = 4;
-static const char *k_VS_FileOS_Low[] =
+static const char * const k_VS_FileOS_Low[] =
{
"VOS__BASE"
, "VOS__WINDOWS16"
@@ -1454,7 +1451,7 @@ static const char *k_VS_FileOS_Low[] =
, "VOS__WINDOWS32"
};
-static const char *k_VS_FileType[] =
+static const char * const k_VS_FileType[] =
{
"VFT_UNKNOWN"
, "VFT_APP"
@@ -1467,7 +1464,7 @@ static const char *k_VS_FileType[] =
};
// Subtype for VFT_DRV Type
-static const char *k_VS_FileSubType_DRV[] =
+static const char * const k_VS_FileSubType_DRV[] =
{
"0"
, "PRINTER"
@@ -1485,7 +1482,7 @@ static const char *k_VS_FileSubType_DRV[] =
};
// Subtype for VFT_FONT Type
-static const char *k_VS_FileSubType_FONT[] =
+static const char * const k_VS_FileSubType_FONT[] =
{
"0"
, "VFT2_FONT_RASTER"
@@ -1493,10 +1490,10 @@ static const char *k_VS_FileSubType_FONT[] =
, "VFT2_FONT_TRUETYPE"
};
-static int FindKey(CObjectVector<CStringKeyValue> &v, const UString &key)
+static int FindKey(CObjectVector<CStringKeyValue> &v, const char *key)
{
FOR_VECTOR (i, v)
- if (v[i].Key == key)
+ if (v[i].Key.IsEqualTo(key))
return i;
return -1;
}
@@ -1665,7 +1662,7 @@ struct CVersionBlock
UInt32 TotalLen;
UInt32 ValueLen;
bool IsTextValue;
- int StrSize;
+ unsigned StrSize;
bool Parse(const Byte *p, UInt32 size);
};
@@ -1691,7 +1688,7 @@ bool CVersionBlock::Parse(const Byte *p, UInt32 size)
return false;
TotalLen = Get16(p);
ValueLen = Get16(p + 2);
- if (TotalLen > size)
+ if (TotalLen == 0 || TotalLen > size)
return false;
switch (Get16(p + 4))
{
@@ -1699,8 +1696,12 @@ bool CVersionBlock::Parse(const Byte *p, UInt32 size)
case 1: IsTextValue = true; break;
default: return false;
}
- StrSize = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size, TotalLen - k_ResoureBlockHeader_Size);
- return StrSize >= 0;
+ StrSize = 0;
+ int t = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size, TotalLen - k_ResoureBlockHeader_Size);
+ if (t < 0)
+ return false;
+ StrSize = t;
+ return true;
}
static void AddParamString(CTextFile &f, const Byte *p, size_t sLen)
@@ -1868,7 +1869,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
int sLen = Get_Utf16Str_Len_InBytes(p + pos, endPos3 - pos);
if (sLen < 0)
return false;
- AddParamString(f, p + pos, sLen);
+ AddParamString(f, p + pos, (unsigned)sLen);
CopyToUString(p + pos, value);
pos += sLen + 2;
}
@@ -2276,6 +2277,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
// _parseResources = false;
UInt64 mainSize = 0, mainSize2 = 0;
+
for (i = 0; i < _sections.Size(); i++)
{
const CSection &sect = _sections[i];
@@ -2287,7 +2289,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
if (res == S_OK)
{
_resourcesPrefix.SetFromAscii(sect.Name);
- _resourcesPrefix += WCHAR_PATH_SEPARATOR;
+ _resourcesPrefix.Add_PathSepar();
FOR_VECTOR (j, _items)
{
const CResItem &item = _items[j];
@@ -2348,7 +2350,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
mainSize = sect.PSize;
_mainSubfile = _mixItems.Size();
}
- else
+ else if (sect.PSize >= mainSize2)
mainSize2 = sect.PSize;
}
_mixItems.Add(mixItem);
@@ -2370,7 +2372,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
for (i = 0; i < _versionKeys.Size(); i++)
{
if (i != 0)
- _versionFullString += L'\n';
+ _versionFullString.Add_LF();
const CStringKeyValue &k = _versionKeys[i];
_versionFullString += k.Key;
_versionFullString += L": ";
@@ -2378,20 +2380,20 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
}
{
- int keyIndex = FindKey(_versionKeys, L"OriginalFilename");
+ int keyIndex = FindKey(_versionKeys, "OriginalFilename");
if (keyIndex >= 0)
_originalFilename = _versionKeys[keyIndex].Value;
}
{
- int keyIndex = FindKey(_versionKeys, L"FileDescription");
+ int keyIndex = FindKey(_versionKeys, "FileDescription");
if (keyIndex >= 0)
_versionShortString = _versionKeys[keyIndex].Value;
}
{
- int keyIndex = FindKey(_versionKeys, L"FileVersion");
+ int keyIndex = FindKey(_versionKeys, "FileVersion");
if (keyIndex >= 0)
{
- _versionShortString += L' ';
+ _versionShortString.Add_Space();
_versionShortString += _versionKeys[keyIndex].Value;
}
}
@@ -2597,7 +2599,8 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
}
referenceBuf->Buf.Alloc(item.HeaderSize + item.Size);
memcpy(referenceBuf->Buf, item.Header, item.HeaderSize);
- memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size);
+ if (item.Size != 0)
+ memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size);
}
inStreamSpec->Init(referenceBuf);
@@ -2612,17 +2615,15 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail)
return S_OK;
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 'M', 'Z' };
-static CArcInfo g_ArcInfo =
- { "PE", "exe dll sys", 0, 0xDD,
- 2, { 'M', 'Z' },
+REGISTER_ARC_I(
+ "PE", "exe dll sys", 0, 0xDD,
+ k_Signature,
0,
NArcInfoFlags::kPreArc,
- CreateArc, NULL, IsArc_Pe };
-
-REGISTER_ARC(Pe)
-
+ IsArc_Pe)
+
}
@@ -2836,7 +2837,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
const CSection &item = _items[index];
switch (propID)
{
- case kpidPath: prop = MultiByteToUnicodeString(NPe::GetName(item.Name)); break;
+ case kpidPath:
+ {
+ AString name;
+ NPe::GetName(item.Name, name);
+ prop = MultiByteToUnicodeString(name);
+ break;
+ }
case kpidSize:
case kpidPackSize: prop = (UInt64)item.PSize; break;
case kpidVirtualSize: prop = (UInt64)item.VSize; break;
@@ -2995,16 +3002,14 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail)
return S_OK;
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 'V', 'Z' };
-static CArcInfo g_ArcInfo =
- { "TE", "te", 0, 0xCF,
- 2, { 'V', 'Z' },
+REGISTER_ARC_I(
+ "TE", "te", 0, 0xCF,
+ k_Signature,
0,
NArcInfoFlags::kPreArc,
- CreateArc, NULL, IsArc_Te };
-
-REGISTER_ARC(TE)
+ IsArc_Te)
}
}
diff --git a/CPP/7zip/Archive/PpmdHandler.cpp b/CPP/7zip/Archive/PpmdHandler.cpp
index 70e9ffac..86927f8f 100644
--- a/CPP/7zip/Archive/PpmdHandler.cpp
+++ b/CPP/7zip/Archive/PpmdHandler.cpp
@@ -28,10 +28,6 @@ using namespace NWindows;
namespace NArchive {
namespace NPpmd {
-static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
-static void SzBigFree(void *, void *address) { BigFree(address); }
-static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
-
static const UInt32 kBufSize = (1 << 20);
struct CBuf
@@ -90,11 +86,10 @@ HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize)
nameLen &= 0x3FFF;
if (nameLen > (1 << 9))
return S_FALSE;
- char *name = Name.GetBuffer(nameLen + 1);
+ char *name = Name.GetBuf(nameLen);
HRESULT res = ReadStream_FALSE(s, name, nameLen);
- name[nameLen] = 0;
+ Name.ReleaseBuf_CalcLen(nameLen);
headerSize = kHeaderSize + nameLen;
- Name.ReleaseBuffer();
return res;
}
@@ -449,15 +444,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
return extractCallback->SetOperationResult(opRes);
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 0x8F, 0xAF, 0xAC, 0x84 };
-static CArcInfo g_ArcInfo =
- { "Ppmd", "pmd", 0, 0xD,
- 4, { 0x8F, 0xAF, 0xAC, 0x84 },
+REGISTER_ARC_I(
+ "Ppmd", "pmd", 0, 0xD,
+ k_Signature,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Ppmd)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp
index c26d72f9..516e5d7f 100644
--- a/CPP/7zip/Archive/Rar/RarHandler.cpp
+++ b/CPP/7zip/Archive/Rar/RarHandler.cpp
@@ -89,7 +89,7 @@ UInt32 CItem::GetWinAttrib() const
return a;
}
-static const char *kHostOS[] =
+static const char * const kHostOS[] =
{
"MS DOS"
, "OS/2"
@@ -354,7 +354,7 @@ static int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime)
}
#define READ_TIME(_mask_, _ttt_) \
- { int size2 = ReadTime(p, size, _mask_, _ttt_); if (size2 < 0) return false; p += size2, size -= size2; }
+ { int size2 = ReadTime(p, size, _mask_, _ttt_); if (size2 < 0) return false; p += (unsigned)size2, size -= (unsigned)size2; }
#define READ_TIME_2(_mask_, _def_, _ttt_) \
_def_ = ((_mask_ & 8) != 0); if (_def_) \
@@ -421,7 +421,7 @@ bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item)
{
item.IsAltStream = true;
item.Name.Empty();
- item.UnicodeName = L".ACL";
+ item.UnicodeName.SetFromAscii(".ACL");
}
else if (item.Name == "STM" && size != 0 && (size & 1) == 0)
{
@@ -517,7 +517,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
RINOK(getTextPassword->CryptoGetTextPassword(&password))
unsigned len = 0;
if (password)
- len = MyStringLen((BSTR)password);
+ len = MyStringLen(password);
CByteBuffer buffer(len * 2);
for (unsigned i = 0; i < len; i++)
{
@@ -645,6 +645,8 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
error = k_ErrorType_Corrupted;
ArcInfo.VolNumber = (UInt32)Get16(m_FileHeaderData + offset);
}
+
+ ArcInfo.EndOfArchive_was_Read = true;
}
m_Position += processed;
FinishCryptoBlock();
@@ -668,7 +670,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
bool okItem = ReadHeaderReal(m_FileHeaderData + 7, m_BlockHeader.HeadSize - 7, item);
if (okItem)
{
- if (!CheckHeaderCrc(m_FileHeaderData, m_BlockHeader.HeadSize - item.CommentSize))
+ if (!CheckHeaderCrc(m_FileHeaderData, (unsigned)m_BlockHeader.HeadSize - item.CommentSize))
{
error = k_ErrorType_Corrupted; // ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError);
return S_OK;
@@ -802,8 +804,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
// FLAGS_TO_PROP(k_Flags, _arcInfo.Flags, prop);
if (_arcInfo.Is_DataCRC_Defined())
{
- if (!s.IsEmpty())
- s += ' ';
+ s.Add_Space_if_NotEmpty();
s += "VolCRC";
}
prop = s;
@@ -1008,27 +1009,28 @@ public:
{
_first = true;
_newStyle = newStyle;
- int dotPos = name.ReverseFind('.');
+ int dotPos = name.ReverseFind_Dot();
UString basePart = name;
+
if (dotPos >= 0)
{
UString ext = name.Ptr(dotPos + 1);
- if (ext.IsEqualToNoCase(L"rar"))
+ if (ext.IsEqualTo_Ascii_NoCase("rar"))
{
_afterPart = name.Ptr(dotPos);
basePart = name.Left(dotPos);
}
- else if (ext.IsEqualToNoCase(L"exe"))
+ else if (ext.IsEqualTo_Ascii_NoCase("exe"))
{
- _afterPart = L".rar";
+ _afterPart.SetFromAscii(".rar");
basePart = name.Left(dotPos);
}
else if (!_newStyle)
{
- if (ext.IsEqualToNoCase(L"000") ||
- ext.IsEqualToNoCase(L"001") ||
- ext.IsEqualToNoCase(L"r00") ||
- ext.IsEqualToNoCase(L"r01"))
+ if (ext.IsEqualTo_Ascii_NoCase("000") ||
+ ext.IsEqualTo_Ascii_NoCase("001") ||
+ ext.IsEqualTo_Ascii_NoCase("r00") ||
+ ext.IsEqualTo_Ascii_NoCase("r01"))
{
_afterPart.Empty();
_first = false;
@@ -1042,18 +1044,21 @@ public:
if (!_newStyle)
{
_afterPart.Empty();
- _unchangedPart = basePart + UString(L".");
- _changedPart = L"r00";
+ _unchangedPart = basePart;
+ _unchangedPart += L'.';
+ _changedPart.SetFromAscii("r00");
return true;
}
if (basePart.IsEmpty())
return false;
unsigned i = basePart.Len();
+
do
if (!IsDigit(basePart[i - 1]))
break;
while (--i);
+
_unchangedPart = basePart.Left(i);
_changedPart = basePart.Ptr(i);
return true;
@@ -1071,34 +1076,59 @@ public:
UString GetNextName()
{
- UString newName;
if (_newStyle || !_first)
{
- for (int i = (int)_changedPart.Len() - 1; i >= 0; i--)
+ unsigned i = _changedPart.Len();
+ for (;;)
{
- wchar_t c = _changedPart[i];
+ wchar_t c = _changedPart[--i];
if (c == L'9')
{
c = L'0';
- newName.InsertAtFront(c);
+ _changedPart.ReplaceOneCharAtPos(i, c);
if (i == 0)
- newName.InsertAtFront(L'1');
+ {
+ _changedPart.InsertAtFront(L'1');
+ break;
+ }
continue;
}
c++;
- newName = UString(c) + newName;
- i--;
- for (; i >= 0; i--)
- newName.InsertAtFront(_changedPart[i]);
+ _changedPart.ReplaceOneCharAtPos(i, c);
break;
}
- _changedPart = newName;
}
+
_first = false;
return _unchangedPart + _changedPart + _afterPart;
}
};
+static HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
+{
+ areThereNonZeros = false;
+ numZeros = 0;
+ const size_t kBufSize = 1 << 9;
+ Byte buf[kBufSize];
+ for (;;)
+ {
+ UInt32 size = 0;
+ HRESULT(stream->Read(buf, kBufSize, &size));
+ if (size == 0)
+ return S_OK;
+ for (UInt32 i = 0; i < size; i++)
+ if (buf[i] != 0)
+ {
+ areThereNonZeros = true;
+ numZeros += i;
+ return S_OK;
+ }
+ numZeros += size;
+ if (numZeros > maxSize)
+ return S_OK;
+ }
+}
+
HRESULT CHandler::Open2(IInStream *stream,
const UInt64 *maxCheckStartPosition,
IArchiveOpenCallback *openCallback)
@@ -1174,6 +1204,7 @@ HRESULT CHandler::Open2(IInStream *stream,
RINOK(archive.Open(inStream, maxCheckStartPosition));
_isArc = true;
CItem item;
+
for (;;)
{
if (archive.m_Position > endPos)
@@ -1181,11 +1212,13 @@ HRESULT CHandler::Open2(IInStream *stream,
_errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
break;
}
+
EErrorType error;
// bool decryptionError;
// AString errorMessageLoc;
bool filled;
HRESULT result = archive.GetNextItem(item, getTextPassword, filled, error);
+
if (error != k_ErrorType_OK)
{
if (error == k_ErrorType_UnexpectedEnd)
@@ -1198,16 +1231,33 @@ HRESULT CHandler::Open2(IInStream *stream,
// AddErrorMessage(errorMessageLoc);
}
RINOK(result);
+
if (!filled)
{
if (error == k_ErrorType_DecryptionError && _items.IsEmpty())
return S_FALSE;
+
+ if (archive.ArcInfo.ExtraZeroTail_is_Possible())
+ {
+ /* if there is recovery record for multivolume archive,
+ RAR adds 18 bytes (ZERO bytes) at the end for alignment.
+ We must skip these bytes to prevent phySize warning. */
+ RINOK(inStream->Seek(archive.ArcInfo.EndPos, STREAM_SEEK_SET, NULL));
+ bool areThereNonZeros;
+ UInt64 numZeros;
+ const UInt64 maxSize = 1 << 12;
+ RINOK(ReadZeroTail(inStream, areThereNonZeros, numZeros, maxSize));
+ if (!areThereNonZeros && numZeros != 0 && numZeros <= maxSize)
+ archive.ArcInfo.EndPos += numZeros;
+ }
break;
}
+
if (item.IgnoreItem())
continue;
bool needAdd = true;
+
if (item.IsSplitBefore())
{
if (!_refItems.IsEmpty())
@@ -1217,6 +1267,7 @@ HRESULT CHandler::Open2(IInStream *stream,
needAdd = false;
}
}
+
if (needAdd)
{
CRefItem refItem;
@@ -1225,7 +1276,9 @@ HRESULT CHandler::Open2(IInStream *stream,
refItem.VolumeIndex = _arcs.Size();
_refItems.Add(refItem);
}
+
_items.Add(item);
+
if (openCallback && _items.Size() % 100 == 0)
{
UInt64 numFiles = _items.Size();
@@ -1256,7 +1309,7 @@ HRESULT CHandler::Open2(IInStream *stream,
/*
int baseFileIndex = -1;
- for (int i = 0; i < _refItems.Size(); i++)
+ for (unsigned i = 0; i < _refItems.Size(); i++)
{
CItem &item = _items[_refItems[i].ItemIndex];
if (item.IsAltStream)
@@ -1430,7 +1483,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (numItems == 0)
return S_OK;
unsigned lastIndex = 0;
- CRecordVector<int> importantIndexes;
+ CRecordVector<unsigned> importantIndexes;
CRecordVector<bool> extractStatuses;
for (UInt32 t = 0; t < numItems; t++)
@@ -1470,7 +1523,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
- CFilterCoder *filterStreamSpec = new CFilterCoder;
+ CFilterCoder *filterStreamSpec = new CFilterCoder(false);
CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;
NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL;
@@ -1576,22 +1629,25 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
// unpackedPos += 0;
CMyComPtr<ISequentialInStream> inStream;
+
if (item.IsEncrypted())
{
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
+
if (item.UnPackVersion >= 29)
{
if (!rar29CryptoDecoder)
{
rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder;
rar29CryptoDecoder = rar29CryptoDecoderSpec;
- // RINOK(rar29CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar29Decoder));
}
rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
+ /*
CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;
RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
&cryptoProperties));
- RINOK(cryptoProperties->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
+ */
+ RINOK(rar29CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
filterStreamSpec->Filter = rar29CryptoDecoder;
}
else if (item.UnPackVersion >= 20)
@@ -1600,7 +1656,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder;
rar20CryptoDecoder = rar20CryptoDecoderSpec;
- // RINOK(rar20CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar20Decoder));
}
filterStreamSpec->Filter = rar20CryptoDecoder;
}
@@ -1610,8 +1665,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
continue;
}
- RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword,
- &cryptoSetPassword));
+
+ RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
if (!getTextPassword)
extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
@@ -1624,7 +1679,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UString unicodePassword;
unsigned len = 0;
if (password)
- len = MyStringLen((BSTR)password);
+ len = MyStringLen(password);
CByteBuffer buffer(len * 2);
for (unsigned i = 0; i < len; i++)
{
@@ -1646,14 +1701,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
}
+
filterStreamSpec->SetInStream(folderInStream);
+ filterStreamSpec->SetOutStreamSize(NULL);
inStream = filterStream;
}
else
{
inStream = folderInStream;
}
+
CMyComPtr<ICompressCoder> commonCoder;
+
switch(item.Method)
{
case '0':
@@ -1679,14 +1738,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
mi.Coder.Release();
if (item.UnPackVersion <= 40)
{
- UInt32 methodID = 0x040300;
+ UInt32 methodID = 0x40300;
if (item.UnPackVersion < 20)
methodID += 1;
else if (item.UnPackVersion < 29)
methodID += 2;
else
methodID += 3;
- RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, mi.Coder, false));
+ RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, false, mi.Coder));
}
if (mi.Coder == 0)
@@ -1722,7 +1781,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
continue;
}
+
HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress);
+
if (item.IsEncrypted())
filterStreamSpec->ReleaseInStream();
if (result == S_FALSE)
@@ -1771,15 +1832,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
IMPL_ISetCompressCodecsInfo
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Rar", "rar r00", 0, 3,
- NHeader::kMarkerSize, SIGNATURE,
+REGISTER_ARC_I(
+ "Rar", "rar r00", 0, 3,
+ kMarker,
0,
NArcInfoFlags::kFindSignature,
- CreateArc };
-
-REGISTER_ARC(Rar)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/Rar/RarHandler.h b/CPP/7zip/Archive/Rar/RarHandler.h
index 81191be9..dd3daa5d 100644
--- a/CPP/7zip/Archive/Rar/RarHandler.h
+++ b/CPP/7zip/Archive/Rar/RarHandler.h
@@ -1,4 +1,4 @@
-// Rar/Handler.h
+// RarHandler.h
#ifndef __RAR_HANDLER_H
#define __RAR_HANDLER_H
@@ -24,18 +24,25 @@ struct CInArcInfo
UInt32 EndFlags;
UInt32 VolNumber;
UInt32 DataCRC;
+ bool EndOfArchive_was_Read;
- CInArcInfo(): EndFlags(0) {}
+ CInArcInfo(): EndFlags(0), EndOfArchive_was_Read(false) {}
UInt64 GetPhySize() const { return EndPos - StartPos; }
- bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; }
- bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; }
+ bool ExtraZeroTail_is_Possible() const { return IsVolume() && IsRecovery() && EndOfArchive_was_Read; }
+
bool IsVolume() const { return (Flags & NHeader::NArchive::kVolume) != 0; }
+ bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; }
+ // kLock
+ bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; }
bool HaveNewVolumeName() const { return (Flags & NHeader::NArchive::kNewVolName) != 0; }
- bool IsFirstVolume() const { return (Flags & NHeader::NArchive::kFirstVolume) != 0; }
+ // kAuthenticity
+ bool IsRecovery() const { return (Flags & NHeader::NArchive::kRecovery) != 0; }
bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; }
+ bool IsFirstVolume() const { return (Flags & NHeader::NArchive::kFirstVolume) != 0; }
bool IsThereEncryptVer() const { return (Flags & NHeader::NArchive::kEncryptVer) != 0; }
+
bool IsEncryptOld() const { return (!IsThereEncryptVer() || EncryptVersion < 36); }
bool Is_VolNumber_Defined() const { return (EndFlags & NHeader::NArchive::kEndOfArc_Flags_VolNumber) != 0; }
diff --git a/CPP/7zip/Archive/Rar/RarItem.h b/CPP/7zip/Archive/Rar/RarItem.h
index 56d25f2c..13daa1cb 100644
--- a/CPP/7zip/Archive/Rar/RarItem.h
+++ b/CPP/7zip/Archive/Rar/RarItem.h
@@ -84,10 +84,10 @@ struct CItem
CItem() { Clear(); }
- UInt64 GetFullSize() const { return MainPartSize + CommentSize + AlignSize + PackSize; };
- // DWORD GetHeaderWithCommentSize() const { return MainPartSize + CommentSize; };
- UInt64 GetCommentPosition() const { return Position + MainPartSize; };
- UInt64 GetDataPosition() const { return GetCommentPosition() + CommentSize + AlignSize; };
+ UInt64 GetFullSize() const { return MainPartSize + CommentSize + AlignSize + PackSize; }
+ // DWORD GetHeaderWithCommentSize() const { return MainPartSize + CommentSize; }
+ UInt64 GetCommentPosition() const { return Position + MainPartSize; }
+ UInt64 GetDataPosition() const { return GetCommentPosition() + CommentSize + AlignSize; }
};
}}
diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp
index 220bc650..268e0837 100644
--- a/CPP/7zip/Archive/RpmHandler.cpp
+++ b/CPP/7zip/Archive/RpmHandler.cpp
@@ -77,7 +77,7 @@ enum
k_EntryType_I18NSTRING
};
-static const char *k_CPUs[] =
+static const char * const k_CPUs[] =
{
"noarch"
, "i386"
@@ -101,7 +101,7 @@ static const char *k_CPUs[] =
, "aarch64" // 19
};
-static const char *k_OS[] =
+static const char * const k_OS[] =
{
"0"
, "Linux"
@@ -299,12 +299,7 @@ AString CHandler::GetBaseName() const
}
}
else
- {
- char *p = s.GetBuffer(kNameSize);
- memcpy(p, _lead.Name, kNameSize);
- p[kNameSize] = 0;
- s.ReleaseBuffer();
- }
+ s.SetFrom_CalcLen(_lead.Name, kNameSize);
s += '.';
if (_lead.Type == kRpmType_Src)
@@ -553,7 +548,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
for (UInt32 t = 0; t < entry.Count; t++)
{
if (t != 0)
- _metadata += ' ';
+ _metadata.Add_Space();
char temp[16];
ConvertUInt32ToString(Get32(p + t * 4), temp);
_metadata += temp;
@@ -592,7 +587,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
for (UInt32 t = 0; t < entry.Count; t++)
{
if (t != 0)
- _metadata += ' ';
+ _metadata.Add_Space();
char temp[16];
ConvertUInt32ToString(Get16(p + t * 2), temp);
_metadata += temp;
@@ -777,15 +772,13 @@ STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 0xED, 0xAB, 0xEE, 0xDB};
-static CArcInfo g_ArcInfo =
- { "Rpm", "rpm", 0, 0xEB,
- 4, { 0xED, 0xAB, 0xEE, 0xDB},
+REGISTER_ARC_I(
+ "Rpm", "rpm", 0, 0xEB,
+ k_Signature,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Rpm)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp
index 19dc1b47..23187064 100644
--- a/CPP/7zip/Archive/SplitHandler.cpp
+++ b/CPP/7zip/Archive/SplitHandler.cpp
@@ -71,68 +71,53 @@ struct CSeqName
UString _changedPart;
bool _splitStyle;
- UString GetNextName()
+ bool GetNextName(UString &s)
{
- UString newName;
- if (_splitStyle)
{
- int i;
- int numLetters = _changedPart.Len();
- for (i = numLetters - 1; i >= 0; i--)
+ unsigned i = _changedPart.Len();
+ for (;;)
{
- wchar_t c = _changedPart[i];
- if (c == 'z')
+ wchar_t c = _changedPart[--i];
+
+ if (_splitStyle)
{
- newName.InsertAtFront('a');
- continue;
+ if (c == 'z')
+ {
+ _changedPart.ReplaceOneCharAtPos(i, L'a');
+ if (i == 0)
+ return false;
+ continue;
+ }
+ else if (c == 'Z')
+ {
+ _changedPart.ReplaceOneCharAtPos(i, L'A');
+ if (i == 0)
+ return false;
+ continue;
+ }
}
- else if (c == 'Z')
+ else
{
- newName.InsertAtFront('A');
- continue;
- }
- c++;
- if ((c == 'z' || c == 'Z') && i == 0)
- {
- _unchangedPart += c;
- wchar_t newChar = (c == 'z') ? L'a' : L'A';
- newName.Empty();
- numLetters++;
- for (int k = 0; k < numLetters; k++)
- newName += newChar;
- break;
- }
- newName.InsertAtFront(c);
- i--;
- for (; i >= 0; i--)
- newName.InsertAtFront(_changedPart[i]);
- break;
- }
- }
- else
- {
- int i;
- int numLetters = _changedPart.Len();
- for (i = numLetters - 1; i >= 0; i--)
- {
- wchar_t c = _changedPart[i];
- if (c == '9')
- {
- newName.InsertAtFront('0');
- if (i == 0)
- newName.InsertAtFront('1');
- continue;
+ if (c == '9')
+ {
+ _changedPart.ReplaceOneCharAtPos(i, L'0');
+ if (i == 0)
+ {
+ _changedPart.InsertAtFront(L'1');
+ break;
+ }
+ continue;
+ }
}
+
c++;
- newName.InsertAtFront(c);
- i--;
- for (; i >= 0; i--)
- newName.InsertAtFront(_changedPart[i]);
+ _changedPart.ReplaceOneCharAtPos(i, c);
break;
}
}
- _changedPart = newName;
- return _unchangedPart + _changedPart;
+
+ s = _unchangedPart + _changedPart;
+ return true;
}
};
@@ -156,7 +141,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
name = prop.bstrVal;
}
- int dotPos = name.ReverseFind('.');
+ int dotPos = name.ReverseFind_Dot();
const UString prefix = name.Left(dotPos + 1);
const UString ext = name.Ptr(dotPos + 1);
UString ext2 = ext;
@@ -196,7 +181,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
seqName._splitStyle = splitStyle;
if (prefix.Len() < 1)
- _subName = L"file";
+ _subName.SetFromAscii("file");
else
_subName.SetFrom(prefix, prefix.Len() - 1);
@@ -220,7 +205,9 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
for (;;)
{
- const UString fullName = seqName.GetNextName();
+ UString fullName;
+ if (!seqName.GetNextName(fullName))
+ break;
CMyComPtr<IInStream> nextStream;
HRESULT result = volumeCallback->GetStream(fullName, &nextStream);
if (result == S_FALSE)
@@ -355,15 +342,10 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Split", "001", 0, 0xEA,
- 0, { 0 },
+REGISTER_ARC_I_NO_SIG(
+ "Split", "001", 0, 0xEA,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Split)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp
index 1f70bb8e..c65067af 100644
--- a/CPP/7zip/Archive/SquashfsHandler.cpp
+++ b/CPP/7zip/Archive/SquashfsHandler.cpp
@@ -28,10 +28,6 @@
namespace NArchive {
namespace NSquashfs {
-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
-static void SzFree(void *p, void *address) { p = p; MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
-
static const UInt32 kNumFilesMax = (1 << 28);
static const unsigned kNumDirLevelsMax = (1 << 10);
@@ -68,7 +64,7 @@ static const UInt32 kSignature32_LZ = 0x71736873;
#define kMethod_LZO 3
#define kMethod_XZ 4
-static const char *k_Methods[] =
+static const char * const k_Methods[] =
{
"Unknown"
, "ZLIB"
@@ -1652,13 +1648,12 @@ AString CHandler::GetPath(int index) const
len--;
AString path;
- char *dest = path.GetBuffer(len) + len;
+ char *dest = path.GetBuf_SetEnd(len) + len;
index = indexMem;
for (;;)
{
const CItem &item = _items[index];
index = item.Parent;
-
const Byte *p = _dirs.Data + item.Ptr;
unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1;
p += _h.GetFileNameOffset();
@@ -1670,7 +1665,6 @@ AString CHandler::GetPath(int index) const
break;
*(--dest) = CHAR_PATH_SEPARATOR;
}
- path.ReleaseBuffer(len);
return path;
}
@@ -1846,7 +1840,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
AString res = "SquashFS";
if (_h.SeveralMethods)
res += "-LZMA";
- res += ' ';
+ res.Add_Space();
char s[16];
ConvertUInt32ToString(_h.Major, s);
res += s;
@@ -2049,7 +2043,8 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
}
if (offsetInBlock + blockSize > _cachedUnpackBlockSize)
return S_FALSE;
- memcpy(dest, _cachedBlock + offsetInBlock, blockSize);
+ if (blockSize != 0)
+ memcpy(dest, _cachedBlock + offsetInBlock, blockSize);
return S_OK;
}
@@ -2208,20 +2203,16 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "SquashFS", "squashfs", 0, 0xD2,
- 3 * (1 + 4),
- {
+static const Byte k_Signature[] = {
4, 'h', 's', 'q', 's',
4, 's', 'q', 's', 'h',
- 4, 's', 'h', 's', 'q',
- },
+ 4, 's', 'h', 's', 'q' };
+
+REGISTER_ARC_I(
+ "SquashFS", "squashfs", 0, 0xD2,
+ k_Signature,
0,
NArcInfoFlags::kMultiSignature,
- CreateArc };
-
-REGISTER_ARC(Cramfs)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp
index 85c61fe2..77d2ad7d 100644
--- a/CPP/7zip/Archive/SwfHandler.cpp
+++ b/CPP/7zip/Archive/SwfHandler.cpp
@@ -170,7 +170,7 @@ public:
INTERFACE_IInArchive(;)
INTERFACE_IOutArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
};
static const Byte kProps[] =
@@ -218,7 +218,7 @@ static void DicSizeToString(char *s, UInt32 val)
else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
}
::ConvertUInt32ToString(val, s);
- int pos = MyStringLen(s);
+ unsigned pos = MyStringLen(s);
s[pos++] = c;
s[pos] = 0;
}
@@ -558,11 +558,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return NCompress::CopyStream(_seqStream, outStream, NULL);
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
_lzmaMode = false;
RINOK(_props.SetProperties(names, values, numProps));
- UString m = _props.MethodName;
+ AString m = _props.MethodName;
m.MakeLower_Ascii();
if (m.IsEqualTo("lzma"))
{
@@ -576,21 +576,16 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
return S_OK;
}
-IMP_CreateArcIn
-IMP_CreateArcOut
-
-static CArcInfo g_ArcInfo =
- { "SWFc", "swf", "~.swf", 0xD8,
- 2 + 3 + 3,
- {
+static const Byte k_Signature[] = {
3, 'C', 'W', 'S',
- 3, 'Z', 'W', 'S',
- },
+ 3, 'Z', 'W', 'S' };
+
+REGISTER_ARC_IO(
+ "SWFc", "swf", "~.swf", 0xD8,
+ k_Signature,
0,
NArcInfoFlags::kMultiSignature,
- REF_CreateArc_Pair, IsArc_Swfc };
-
-REGISTER_ARC(Swfc)
+ IsArc_Swfc)
}
@@ -978,15 +973,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 'F', 'W', 'S' };
-static CArcInfo g_ArcInfo =
- { "SWF", "swf", 0, 0xD7,
- 3, { 'F', 'W', 'S' },
+REGISTER_ARC_I(
+ "SWF", "swf", 0, 0xD7,
+ k_Signature,
0,
NArcInfoFlags::kKeepName,
- CreateArc, NULL, NSwfc::IsArc_Swf };
-
-REGISTER_ARC(Swf)
+ NSwfc::IsArc_Swf)
}}
diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp
index 5b587529..d1eec144 100644
--- a/CPP/7zip/Archive/Tar/TarHandler.cpp
+++ b/CPP/7zip/Archive/Tar/TarHandler.cpp
@@ -143,10 +143,10 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
if (!_forceCodePage)
{
- if (utf8_OK) utf8_OK = CheckUTF8(item.Name);
+ if (utf8_OK) utf8_OK = CheckUTF8(item.Name, item.NameCouldBeReduced);
+ if (utf8_OK) utf8_OK = CheckUTF8(item.LinkName, item.LinkNameCouldBeReduced);
if (utf8_OK) utf8_OK = CheckUTF8(item.User);
if (utf8_OK) utf8_OK = CheckUTF8(item.Group);
- if (utf8_OK) utf8_OK = CheckUTF8(item.LinkName);
}
RINOK(stream->Seek(item.GetPackSizeAligned(), STREAM_SEEK_CUR, &_phySize));
@@ -298,19 +298,12 @@ void CHandler::TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant
{
UString dest;
if (_curCodePage == CP_UTF8)
- {
- if (!ConvertUTF8ToUnicode(s, dest))
- {
- prop = "[ERROR-NAME]";
- return;
- }
- }
+ ConvertUTF8ToUnicode(s, dest);
else
- dest = MultiByteToUnicodeString(s, _curCodePage);
+ MultiByteToUnicodeString2(dest, s, _curCodePage);
if (toOs)
- prop = NItemName::GetOSName2(dest);
- else
- prop = dest;
+ NItemName::ConvertToOSName2(dest);
+ prop = dest;
}
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
@@ -632,10 +625,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
if (item.IsSymLink())
{
- CBufInStream *streamSpec = new CBufInStream;
- CMyComPtr<IInStream> streamTemp = streamSpec;
- streamSpec->Init((const Byte *)(const char *)item.LinkName, item.LinkName.Len(), (IInArchive *)this);
- *stream = streamTemp.Detach();
+ Create_BufInStream_WithReference((const Byte *)(const char *)item.LinkName, item.LinkName.Len(), (IInArchive *)this, stream);
return S_OK;
}
@@ -651,7 +641,7 @@ void CHandler::Init()
_curCodePage = _specifiedCodePage = CP_UTF8; // CP_OEMCP;
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
Init();
diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h
index 23854767..42d57d45 100644
--- a/CPP/7zip/Archive/Tar/TarHandler.h
+++ b/CPP/7zip/Archive/Tar/TarHandler.h
@@ -67,7 +67,7 @@ public:
INTERFACE_IOutArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
void Init();
CHandler();
diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
index b909e96c..ae005ac5 100644
--- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
+++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
@@ -36,8 +36,8 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro
s = NItemName::MakeLegalName(s);
if (codePage == CP_UTF8)
{
- if (!ConvertUnicodeToUTF8(s, res))
- return E_INVALIDARG;
+ ConvertUnicodeToUTF8(s, res);
+ // if (!ConvertUnicodeToUTF8(s, res)) // return E_INVALIDARG;
}
else
UnicodeStringToMultiByte2(res, s, codePage);
diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp
index 1584a520..80200c3b 100644
--- a/CPP/7zip/Archive/Tar/TarIn.cpp
+++ b/CPP/7zip/Archive/Tar/TarIn.cpp
@@ -180,6 +180,9 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
error = k_ErrorType_Corrupted;
ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize;
+ item.NameCouldBeReduced =
+ (item.Name.Len() == NFileHeader::kNameSize ||
+ item.Name.Len() == NFileHeader::kNameSize - 1);
RIF(OctalToNumber32(p, 8, item.Mode)); p += 8;
@@ -198,6 +201,9 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
item.LinkFlag = *p++;
ReadString(p, NFileHeader::kNameSize, item.LinkName); p += NFileHeader::kNameSize;
+ item.LinkNameCouldBeReduced =
+ (item.LinkName.Len() == NFileHeader::kNameSize ||
+ item.LinkName.Len() == NFileHeader::kNameSize - 1);
memcpy(item.Magic, p, 8); p += 8;
@@ -207,12 +213,17 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
item.DeviceMajorDefined = (p[0] != 0); if (item.DeviceMajorDefined) { RIF(OctalToNumber32(p, 8, item.DeviceMajor)); } p += 8;
item.DeviceMinorDefined = (p[0] != 0); if (item.DeviceMinorDefined) { RIF(OctalToNumber32(p, 8, item.DeviceMinor)); } p += 8;
- AString prefix;
- ReadString(p, NFileHeader::kPrefixSize, prefix);
+ if (p[0] != 0)
+ {
+ AString prefix;
+ ReadString(p, NFileHeader::kPrefixSize, prefix);
+ if (!prefix.IsEmpty()
+ && item.IsUstarMagic()
+ && (item.LinkFlag != 'L' /* || prefix != "00000000000" */ ))
+ item.Name = prefix + '/' + item.Name;
+ }
+
p += NFileHeader::kPrefixSize;
- if (!prefix.IsEmpty() && item.IsUstarMagic() &&
- (item.LinkFlag != 'L' /* || prefix != "00000000000" */ ))
- item.Name = prefix + AString('/') + item.Name;
if (item.LinkFlag == NFileHeader::NLinkFlag::kHardLink)
{
@@ -353,12 +364,11 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro
if (item.PackSize > (1 << 14))
return S_OK;
unsigned packSize = (unsigned)item.GetPackSizeAligned();
- char *buf = name->GetBuffer(packSize);
+ char *buf = name->GetBuf(packSize);
size_t processedSize = packSize;
HRESULT res = ReadStream(stream, buf, &processedSize);
item.HeaderSize += (unsigned)processedSize;
- buf[(size_t)item.PackSize] = 0;
- name->ReleaseBuffer();
+ name->ReleaseBuf_CalcLen((unsigned)item.PackSize);
RINOK(res);
if (processedSize != packSize)
{
@@ -392,8 +402,18 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro
return S_OK;
}
- if (flagL) item.Name = nameL;
- if (flagK) item.LinkName = nameK;
+ if (flagL)
+ {
+ item.Name = nameL;
+ item.NameCouldBeReduced = false;
+ }
+
+ if (flagK)
+ {
+ item.LinkName = nameK;
+ item.LinkNameCouldBeReduced = false;
+ }
+
error = k_ErrorType_OK;
return S_OK;
}
diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h
index 805a2e7c..5245aaa4 100644
--- a/CPP/7zip/Archive/Tar/TarItem.h
+++ b/CPP/7zip/Archive/Tar/TarItem.h
@@ -86,6 +86,8 @@ struct CItemEx: public CItem
{
UInt64 HeaderPos;
unsigned HeaderSize;
+ bool NameCouldBeReduced;
+ bool LinkNameCouldBeReduced;
UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; }
UInt64 GetFullSize() const { return HeaderSize + PackSize; }
diff --git a/CPP/7zip/Archive/Tar/TarRegister.cpp b/CPP/7zip/Archive/Tar/TarRegister.cpp
index 9e0f6f21..f7b256df 100644
--- a/CPP/7zip/Archive/Tar/TarRegister.cpp
+++ b/CPP/7zip/Archive/Tar/TarRegister.cpp
@@ -9,18 +9,15 @@
namespace NArchive {
namespace NTar {
-IMP_CreateArcIn
-IMP_CreateArcOut
+static const Byte k_Signature[] = { 'u', 's', 't', 'a', 'r' };
-static CArcInfo g_ArcInfo =
- { "tar", "tar", 0, 0xEE,
- 5, { 'u', 's', 't', 'a', 'r' },
+REGISTER_ARC_IO(
+ "tar", "tar", 0, 0xEE,
+ k_Signature,
NFileHeader::kUstarMagic_Offset,
NArcInfoFlags::kStartOpen |
NArcInfoFlags::kSymLinks |
NArcInfoFlags::kHardLinks,
- REF_CreateArc_Pair, IsArc_Tar };
-
-REGISTER_ARC(Tar)
-
+ IsArc_Tar)
+
}}
diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp
index fdbce395..3adbdee9 100644
--- a/CPP/7zip/Archive/Tar/TarUpdate.cpp
+++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp
@@ -31,6 +31,9 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
CMyComPtr<IOutStream> outSeekStream;
outStream->QueryInterface(IID_IOutStream, (void **)&outSeekStream);
+ CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
+ updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
+
UInt64 complexity = 0;
unsigned i;
@@ -224,6 +227,13 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
}
streamSpec->Init(size);
+ if (opCallback)
+ {
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArchive,
+ NUpdateNotifyOp::kReplicate))
+ }
+
RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize != size)
return E_FAIL;
diff --git a/CPP/7zip/Archive/Udf/UdfHandler.cpp b/CPP/7zip/Archive/Udf/UdfHandler.cpp
index 6aa53ea9..d35db9fb 100644
--- a/CPP/7zip/Archive/Udf/UdfHandler.cpp
+++ b/CPP/7zip/Archive/Udf/UdfHandler.cpp
@@ -26,7 +26,7 @@ static void UdfTimeToFileTime(const CTime &t, NWindows::NCOM::CPropVariant &prop
if (!NWindows::NTime::GetSecondsSince1601(t.GetYear(), d[4], d[5], d[6], d[7], d[8], numSecs))
return;
if (t.IsLocal())
- numSecs -= t.GetMinutesOffset() * 60;
+ numSecs -= (Int64)((Int32)t.GetMinutesOffset() * 60);
FILETIME ft;
UInt64 v = (((numSecs * 100 + d[9]) * 100 + d[10]) * 100 + d[11]) * 10;
ft.dwLowDateTime = (UInt32)v;
@@ -227,13 +227,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
if (item.IsInline)
{
- CBufInStream *inStreamSpec = new CBufInStream;
- CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
- CReferenceBuf *referenceBuf = new CReferenceBuf;
- CMyComPtr<IUnknown> ref = referenceBuf;
- referenceBuf->Buf = item.InlineData;
- inStreamSpec->Init(referenceBuf);
- *stream = inStream.Detach();
+ Create_BufInStream_WithNewBuffer(item.InlineData, stream);
return S_OK;
}
@@ -366,18 +360,16 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
COM_TRY_END
}
-IMP_CreateArcIn
-
static const UInt32 kIsoStartPos = 0x8000;
-static CArcInfo g_ArcInfo =
- { "Udf", "udf iso img", 0, 0xE0,
- // 5, { 0, 'N', 'S', 'R', '0' },
- 6, { 1, 'C', 'D', '0', '0', '1' },
+// 5, { 0, 'N', 'S', 'R', '0' },
+static const Byte k_Signature[] = { 1, 'C', 'D', '0', '0', '1' };
+
+REGISTER_ARC_I(
+ "Udf", "udf iso img", 0, 0xE0,
+ k_Signature,
kIsoStartPos,
NArcInfoFlags::kStartOpen,
- CreateArc, NULL, IsArc_Udf };
-
-REGISTER_ARC(Udf)
+ IsArc_Udf)
}}
diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp
index 3053a0c1..62df64dc 100644
--- a/CPP/7zip/Archive/Udf/UdfIn.cpp
+++ b/CPP/7zip/Archive/Udf/UdfIn.cpp
@@ -82,13 +82,13 @@ void CDString::Parse(const Byte *p, unsigned size)
static UString ParseDString(const Byte *data, unsigned size)
{
UString res;
- wchar_t *p;
if (size > 0)
{
+ wchar_t *p;
Byte type = data[0];
if (type == 8)
{
- p = res.GetBuffer(size);
+ p = res.GetBuf(size);
for (unsigned i = 1; i < size; i++)
{
wchar_t c = data[i];
@@ -99,7 +99,7 @@ static UString ParseDString(const Byte *data, unsigned size)
}
else if (type == 16)
{
- p = res.GetBuffer(size / 2);
+ p = res.GetBuf(size / 2);
for (unsigned i = 1; i + 2 <= size; i += 2)
{
wchar_t c = GetBe16(data + i);
@@ -110,8 +110,8 @@ static UString ParseDString(const Byte *data, unsigned size)
}
else
return L"[unknow]";
- *p++ = 0;
- res.ReleaseBuffer();
+ *p = 0;
+ res.ReleaseBuf_SetLen((unsigned)(p - (const wchar_t *)res));
}
return res;
}
@@ -432,6 +432,8 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la
CTag tag;
const Byte *p = buf;
RINOK(tag.Parse(p, size));
+ if (size < 176)
+ return S_FALSE;
if (tag.Id != DESC_TYPE_File)
return S_FALSE;
@@ -449,7 +451,7 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la
if ((extendedAttrLen & 3) != 0)
return S_FALSE;
- int pos = 176;
+ size_t pos = 176;
if (extendedAttrLen > size - pos)
return S_FALSE;
/*
@@ -595,7 +597,7 @@ API_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size)
if (SecLogSize < 8)
return res;
UInt32 offset = (UInt32)256 << SecLogSize;
- size_t bufSize = 1 << SecLogSize;
+ size_t bufSize = (UInt32)1 << SecLogSize;
if (offset + bufSize > size)
res = k_IsArc_Res_NEED_MORE;
else
@@ -652,7 +654,7 @@ HRESULT CInArchive::Open2()
if (offset >= fileSize)
continue;
RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));
- size_t bufSize = 1 << SecLogSize;
+ size_t bufSize = (UInt32)1 << SecLogSize;
size_t readSize = bufSize;
RINOK(ReadStream(_stream, buf, &readSize));
if (readSize == bufSize)
@@ -677,7 +679,7 @@ HRESULT CInArchive::Open2()
for (UInt32 location = 0; ; location++)
{
- size_t bufSize = 1 << SecLogSize;
+ size_t bufSize = (UInt32)1 << SecLogSize;
size_t pos = 0;
if (((UInt64)(location + 1) << SecLogSize) > extentVDS.Len)
return S_FALSE;
@@ -950,7 +952,7 @@ HRESULT CInArchive::Open2()
if (PhySize < fileSize)
{
RINOK(_stream->Seek(PhySize, STREAM_SEEK_SET, NULL));
- size_t bufSize = 1 << SecLogSize;
+ size_t bufSize = (UInt32)1 << SecLogSize;
size_t readSize = bufSize;
RINOK(ReadStream(_stream, buf, &readSize));
if (readSize == bufSize)
@@ -1018,8 +1020,8 @@ UString CInArchive::GetComment() const
UString res;
FOR_VECTOR (i, LogVols)
{
- if (i > 0)
- res += L" ";
+ if (i != 0)
+ res.Add_Space();
res += LogVols[i].GetName();
}
return res;
diff --git a/CPP/7zip/Archive/Udf/UdfRegister.cpp b/CPP/7zip/Archive/Udf/UdfRegister.cpp
deleted file mode 100644
index ed32f12e..00000000
--- a/CPP/7zip/Archive/Udf/UdfRegister.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-// UdfRegister.cpp
-
-#include "StdAfx.h"
-
-#include "../../Common/RegisterArc.h"
-
-#include "UdfHandler.h"
diff --git a/CPP/7zip/Archive/UefiHandler.cpp b/CPP/7zip/Archive/UefiHandler.cpp
index a6760b36..3de6351a 100644
--- a/CPP/7zip/Archive/UefiHandler.cpp
+++ b/CPP/7zip/Archive/UefiHandler.cpp
@@ -26,6 +26,7 @@
#include "../Common/StreamUtils.h"
#include "../Compress/CopyCoder.h"
+#include "../Compress/LzhDecoder.h"
#ifdef SHOW_DEBUG_INFO
#define PRF(x) x
@@ -41,22 +42,18 @@
namespace NArchive {
namespace NUefi {
-static const UInt32 kBufTotalSizeMax = (1 << 29);
-static const UInt32 kNumFilesMax = (1 << 18);
-static const int kLevelMax = 64;
+static const size_t kBufTotalSizeMax = (1 << 29);
+static const unsigned kNumFilesMax = (1 << 18);
+static const unsigned kLevelMax = 64;
-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
-static void SzFree(void *p, void *address) { p = p; MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
+static const unsigned kFvHeaderSize = 0x38;
-static const UInt32 kFvHeaderSize = 0x38;
-static const UInt32 kGuidSize = 16;
-static const UInt32 kCapsuleSigSize = kGuidSize;
+static const unsigned kGuidSize = 16;
#define CAPSULE_SIGNATURE \
{ 0xBD,0x86,0x66,0x3B,0x76,0x0D,0x30,0x40,0xB7,0x0E,0xB5,0x51,0x9E,0x2F,0xC5,0xA0 }
-static const Byte kCapsuleSig[kCapsuleSigSize] = CAPSULE_SIGNATURE;
+static const Byte kCapsuleSig[kGuidSize] = CAPSULE_SIGNATURE;
-static const UInt32 kFfsGuidOffset = 16;
+static const unsigned kFfsGuidOffset = 16;
#define FFS_SIGNATURE \
{ 0xD9,0x54,0x93,0x7A,0x68,0x04,0x4A,0x44,0x81,0xCE,0x0B,0xF6,0x17,0xD8,0x90,0xDF }
static const Byte k_FFS_Guid[kGuidSize] = FFS_SIGNATURE;
@@ -84,7 +81,7 @@ static const Byte kGuids[][kGuidSize] =
};
-static const char *kGuidNames[] =
+static const char * const kGuidNames[] =
{
"CRC"
, "VolumeTopFile"
@@ -175,7 +172,7 @@ static bool AreGuidsEq(const Byte *p1, const Byte *p2)
static int FindGuid(const Byte *p)
{
- for (int i = 0; i < ARRAY_SIZE(kGuids); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(kGuids); i++)
if (AreGuidsEq(p, kGuids[i]))
return i;
return -1;
@@ -325,7 +322,7 @@ static const CUInt32PCharPair g_SECTION_TYPE[] =
#define COMPRESSION_TYPE_LZH 1
#define COMPRESSION_TYPE_LZMA 2
-static const char *g_Methods[] =
+static const char * const g_Methods[] =
{
"COPY"
, "LZH"
@@ -367,7 +364,7 @@ static AString GuidToString(const Byte *p, bool full)
return s;
}
-static const char *kExpressionCommands[] =
+static const char * const kExpressionCommands[] =
{
"BEFORE", "AFTER", "PUSH", "AND", "OR", "NOT", "TRUE", "FALSE", "END", "SOR"
};
@@ -385,7 +382,7 @@ static bool ParseDepedencyExpression(const Byte *p, UInt32 size, AString &res)
{
if (i + kGuidSize > size)
return false;
- res += " ";
+ res.Add_Space();
res += GuidToString(p + i, false);
i += kGuidSize;
}
@@ -427,9 +424,11 @@ static const UInt32 kFileHeaderSize = 24;
static void AddSpaceAndString(AString &res, const AString &newString)
{
- if (!res.IsEmpty() && !newString.IsEmpty())
- res += ' ';
- res += newString;
+ if (!newString.IsEmpty())
+ {
+ res.Add_Space_if_NotEmpty();
+ res += newString;
+ }
}
class CFfsFileHeader
@@ -604,7 +603,7 @@ void CItem::SetGuid(const Byte *guidName, bool full)
ThereIsUniqueName = true;
int index = FindGuid(guidName);
if (index >= 0)
- Name = kGuidNames[index];
+ Name = kGuidNames[(unsigned)index];
else
Name = GuidToString(guidName, full);
}
@@ -617,9 +616,9 @@ AString CItem::GetName(int numChildsInParent) const
char sz2[32];
ConvertUInt32ToString(NameIndex, sz);
ConvertUInt32ToString(numChildsInParent - 1, sz2);
- int numZeros = (int)strlen(sz2) - (int)strlen(sz);
+ unsigned numZeros = (unsigned)strlen(sz2) - (unsigned)strlen(sz);
AString res;
- for (int i = 0; i < numZeros; i++)
+ for (unsigned i = 0; i < numZeros; i++)
res += '0';
return res + (AString)sz + '.' + Name;
}
@@ -646,7 +645,7 @@ class CHandler:
UInt32 _methodsMask;
bool _capsuleMode;
- UInt32 _totalBufsSize;
+ size_t _totalBufsSize;
CCapsuleHeader _h;
UInt64 _phySize;
@@ -654,9 +653,9 @@ class CHandler:
int AddItem(const CItem &item);
int AddFileItemWithIndex(CItem &item);
int AddDirItem(CItem &item);
- int AddBuf(UInt32 size);
+ unsigned AddBuf(size_t size);
- HRESULT ParseSections(int bufIndex, UInt32 pos, UInt32 size, int parent, int method, int level);
+ HRESULT ParseSections(int bufIndex, UInt32 pos, UInt32 size, int parent, int method, unsigned level);
HRESULT ParseVolume(int bufIndex, UInt32 posBase,
UInt32 exactSize, UInt32 limitSize,
int parent, int method, int level);
@@ -711,7 +710,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
break;
}
case kpidIsDir: prop = item.IsDir; break;
- case kpidMethod: if (item.Method >= 0) prop = g_Methods[item.Method]; break;
+ case kpidMethod: if (item.Method >= 0) prop = g_Methods[(unsigned)item.Method]; break;
case kpidCharacts: if (!item2.Characts.IsEmpty()) prop = item2.Characts; break;
case kpidSize: if (!item.IsDir) prop = (UInt64)item.Size; break;
}
@@ -739,15 +738,15 @@ void CHandler::AddCommentString(const wchar_t *name, UInt32 pos)
c = Get16(buf + i);
if (c == 0)
break;
- s += L'\n';
+ s.Add_LF();
}
s += c;
}
if (s.IsEmpty())
return;
- _comment += L'\n';
+ _comment.Add_LF();
_comment += name;
- _comment += L": ";
+ _comment.AddAscii(": ");
_comment += s;
}
@@ -760,7 +759,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidMethod:
{
AString s;
- for (int i = 0; i < 32; i++)
+ for (unsigned i = 0; i < 32; i++)
if ((_methodsMask & ((UInt32)1 << i)) != 0)
AddSpaceAndString(s, g_Methods[i]);
if (!s.IsEmpty())
@@ -792,341 +791,7 @@ static void MyPrint(UInt32 posBase, UInt32 size, int level, const char *name)
#define MyPrint(posBase, size, level, name)
#endif
-static const unsigned kNumBigValueBits = 8 * 4;
-static const unsigned kNumValueBytes = 3;
-static const unsigned kNumValueBits = 8 * kNumValueBytes;
-static const UInt32 kMask = (1 << kNumValueBits) - 1;
-
-class CBitmMemDecoder
-{
- unsigned _bitPos;
- UInt32 _value;
- const Byte *_buf;
- size_t _pos;
- size_t _size;
- size_t _extra;
-public:
- void Init(const Byte *buf, size_t size)
- {
- _buf = buf;
- _size = size;
- _pos = 0;
- _extra = 0;
- _bitPos = kNumBigValueBits;
- Normalize();
- }
-
- bool IsFullFinished() const { return (_extra * 8) == (kNumBigValueBits - _bitPos); }
-
- void Normalize()
- {
- for (; _bitPos >= 8; _bitPos -= 8)
- {
- Byte b;
- if (_pos < _size)
- b = _buf[_pos++];
- else
- {
- b = 0;
- _extra++;
- }
- _value = (_value << 8) | b;
- }
- }
-
- UInt32 GetValue(unsigned numBits) const
- {
- return ((_value >> (8 - _bitPos)) & kMask) >> (kNumValueBits - numBits);
- }
-
- void MovePos(unsigned numBits)
- {
- _bitPos += numBits;
- Normalize();
- }
-
- UInt32 ReadBitsFast(unsigned numBits)
- {
- UInt32 res = GetValue(numBits);
- MovePos(numBits);
- return res;
- }
-
- UInt32 ReadBits(unsigned numBits);
- UInt32 ReadAlignBits() { return ReadBits((32 - _bitPos) & 7); }
-};
-
-UInt32 CBitmMemDecoder::ReadBits(unsigned numBits)
-{
- UInt32 res = GetValue(numBits);
- MovePos(numBits);
- return res;
-}
-
-namespace NHuffman {
-
-static const int kNumTableBits = 9;
-static const int kNumBitsMax = 16;
-
-class CDecoder
-{
- UInt32 m_Limits[kNumBitsMax + 1];
- UInt32 m_Positions[kNumBitsMax + 1];
- Byte m_Lengths[1 << kNumTableBits];
- Int32 m_MainSymbol;
-
-public:
- UInt32 *m_Symbols;
- UInt32 m_NumSymbols;
-
- void SetSingleSymbolMode(UInt32 symbol) { m_MainSymbol = symbol; }
- bool SetCodeLengths(const Byte *codeLengths);
- UInt32 DecodeSymbol(CBitmMemDecoder *bitStream)
- {
- if (m_MainSymbol != -1)
- return (UInt32)m_MainSymbol;
- int numBits;
- UInt32 value = bitStream->GetValue(kNumBitsMax);
- if (value < m_Limits[kNumTableBits])
- numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)];
- else
- for (numBits = kNumTableBits + 1; value >= m_Limits[numBits]; numBits++);
- bitStream->MovePos(numBits);
- return m_Symbols[m_Positions[numBits] + ((value - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits))];
- }
-};
-
-bool CDecoder::SetCodeLengths(const Byte *codeLengths)
-{
- m_MainSymbol = -1;
- int lenCounts[kNumBitsMax + 1];
- UInt32 tmpPositions[kNumBitsMax + 1];
- int i;
- for (i = 1; i <= kNumBitsMax; i++)
- lenCounts[i] = 0;
- UInt32 symbol;
- for (symbol = 0; symbol < m_NumSymbols; symbol++)
- {
- int len = codeLengths[symbol];
- if (len > kNumBitsMax)
- return false;
- lenCounts[len]++;
- m_Symbols[symbol] = 0xFFFFFFFF;
- }
- lenCounts[0] = 0;
- m_Positions[0] = m_Limits[0] = 0;
- UInt32 startPos = 0;
- UInt32 index = 0;
- const UInt32 kMaxValue = (1 << kNumBitsMax);
- for (i = 1; i <= kNumBitsMax; i++)
- {
- startPos += lenCounts[i] << (kNumBitsMax - i);
- if (startPos > kMaxValue)
- return false;
- m_Limits[i] = (i == kNumBitsMax) ? kMaxValue : startPos;
- m_Positions[i] = m_Positions[i - 1] + lenCounts[i - 1];
- tmpPositions[i] = m_Positions[i];
- if (i <= kNumTableBits)
- {
- UInt32 limit = (m_Limits[i] >> (kNumBitsMax - kNumTableBits));
- for (; index < limit; index++)
- m_Lengths[index] = (Byte)i;
- }
- }
- if (startPos != kMaxValue)
- return false;
- for (symbol = 0; symbol < m_NumSymbols; symbol++)
- {
- int len = codeLengths[symbol];
- if (len != 0)
- m_Symbols[tmpPositions[len]++] = symbol;
- }
- return true;
-}
-
-}
-
-static const int kMaxHuffmanLen = 16;
-static const int kExtraSize = kMaxHuffmanLen + 3;
-static const int kMinMatchLen = 3;
-static const int kMaxMatchLen = 256;
-static const int kNumAlphaSymsMax = 256 + kMaxMatchLen - kMinMatchLen + 1;
-static const int kNumDistSymsMax = 24 + 2; // it's limited by bit decoder.
-
-#define HUFF_START_CODE(huff, numSymsMax, numSymBits) \
- UInt32 numSyms = bitDec.ReadBits(numSymBits); \
- Byte lens[numSymsMax]; memset(lens, 0, sizeof(lens)); \
- if (numSyms > (numSymsMax)) return S_FALSE; \
- huff.m_NumSymbols = numSyms; \
- if (numSyms == 0) { \
- numSyms = bitDec.ReadBits(numSymBits); \
- if (numSyms >= (numSymsMax)) return S_FALSE; \
- huff.SetSingleSymbolMode(numSyms); } \
-
-static HRESULT LzhDecode(Byte *dest, UInt32 destSize, const Byte *src, UInt32 srcSize)
-{
- if (srcSize < 8)
- return S_FALSE;
- {
- UInt32 packSize = Get32(src);
- UInt32 unpackSize = Get32(src + 4);
- src += 8;
- srcSize -= 8;
- if (destSize != unpackSize || srcSize != packSize)
- return S_FALSE;
- }
-
- CBitmMemDecoder bitDec;
- bitDec.Init(src, srcSize);
- UInt32 pos = 0;
- for (;;)
- {
- UInt32 blockSize = bitDec.ReadBits(16);
- UInt32 symbols[kExtraSize + kNumAlphaSymsMax + kNumDistSymsMax];
-
- NHuffman::CDecoder extraHuff;
- extraHuff.m_Symbols = symbols;
- {
- HUFF_START_CODE(extraHuff, kExtraSize, 5)
- else
- {
- for (UInt32 i = 0; i < numSyms; i++)
- {
- if (i == 3)
- {
- UInt32 numZeros = bitDec.ReadBits(2);
- if (i + numZeros > numSyms)
- return S_FALSE;
- for (UInt32 j = 0; j < numZeros; j++, i++)
- lens[i] = (Byte)0;
- if (i == numSyms)
- break;
- }
-
- UInt32 len = bitDec.ReadBits(3);
- if (len == 7)
- {
- for(;; len++)
- {
- if (len > kMaxHuffmanLen)
- return S_FALSE;
- if (bitDec.ReadBits(1) == 0)
- break;
- }
- }
- lens[i] = (Byte)len;
- }
- if (!extraHuff.SetCodeLengths(lens))
- return S_FALSE;
- }
- }
-
- NHuffman::CDecoder symHuff;
- symHuff.m_Symbols = symbols + kExtraSize;
- {
- HUFF_START_CODE(symHuff, kNumAlphaSymsMax, 9)
- else
- {
- for (UInt32 i = 0; i < numSyms;)
- {
- UInt32 c = extraHuff.DecodeSymbol(&bitDec);
- if (c > 2)
- lens[i++] = (Byte)(c - 2);
- else
- {
- UInt32 numZeros;
- if (c == 0)
- numZeros = 1;
- else if (c == 1)
- numZeros = bitDec.ReadBits(4) + 3;
- else
- numZeros = bitDec.ReadBits(9) + 20;
- if (i + numZeros > numSyms)
- return S_FALSE;
- for (UInt32 j = 0; j < numZeros; j++, i++)
- lens[i] = (Byte)0;
- }
- }
- if (!symHuff.SetCodeLengths(lens))
- return S_FALSE;
- }
- }
-
- NHuffman::CDecoder distHuff;
- distHuff.m_Symbols = symbols + kExtraSize + kNumAlphaSymsMax;
- {
- const UInt32 version = 1;
- const UInt32 numDistBits = version + 4;
- HUFF_START_CODE(distHuff, kNumDistSymsMax, numDistBits)
- else
- {
- for (UInt32 i = 0; i < numSyms; i++)
- {
- UInt32 len = bitDec.ReadBits(3);
- if (len == 7)
- {
- for(;; len++)
- {
- if (len > kMaxHuffmanLen)
- return S_FALSE;
- if (bitDec.ReadBits(1) == 0)
- break;
- }
- }
- lens[i] = (Byte)len;
- }
- if (!distHuff.SetCodeLengths(lens))
- return S_FALSE;
- }
- }
-
- while (blockSize)
- {
- blockSize--;
- UInt32 c = symHuff.DecodeSymbol(&bitDec);
- if (c < 256)
- {
- if (destSize == 0)
- return S_FALSE;
- *dest++ = (Byte)c;
- destSize--;
- pos++;
- continue;
- }
- c = c - 256 + kMinMatchLen;
- if (destSize < c)
- return S_FALSE;
- UInt32 dist = distHuff.DecodeSymbol(&bitDec);
- if (dist > 1)
- dist = ((UInt32)1 << (dist - 1)) + bitDec.ReadBits(dist - 1);
- dist++;
- if (dist > pos)
- return S_FALSE;
- pos += c;
- destSize -= c;
- do
- {
- *dest = dest[0 - (Int32)dist];
- dest++;
- }
- while (--c);
- }
-
- // PRF(printf("\ndestSize = %6d", destSize));
- if (destSize == 0)
- {
- if (bitDec.ReadAlignBits() != 0)
- return S_FALSE;
- if (bitDec.ReadBits(8) != 0)
- return S_FALSE;
- if (!bitDec.IsFullFinished())
- return S_FALSE;
- break;
- }
- }
- return S_OK;
-}
int CHandler::AddItem(const CItem &item)
{
@@ -1153,17 +818,17 @@ int CHandler::AddDirItem(CItem &item)
return AddItem(item);
}
-int CHandler::AddBuf(UInt32 size)
+unsigned CHandler::AddBuf(size_t size)
{
if (size > kBufTotalSizeMax - _totalBufsSize)
throw 1;
_totalBufsSize += size;
- int index = _bufs.Size();
+ unsigned index = _bufs.Size();
_bufs.AddNew().Alloc(size);
return index;
}
-HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, int level)
+HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, unsigned level)
{
if (level > kLevelMax)
return S_FALSE;
@@ -1229,9 +894,55 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
}
else if (compressionType == COMPRESSION_TYPE_LZH)
{
- int newBufIndex = AddBuf(uncompressedSize);
+ unsigned newBufIndex = AddBuf(uncompressedSize);
CByteBuffer &buf = _bufs[newBufIndex];
- RINOK(LzhDecode(buf, uncompressedSize, pStart, newSectSize));
+
+ NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0;
+ CMyComPtr<ICompressCoder> lzhDecoder;
+
+ lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder;
+ lzhDecoder = lzhDecoderSpec;
+
+ {
+ const Byte *src = pStart;
+ if (newSectSize < 8)
+ return S_FALSE;
+ UInt32 packSize = Get32(src);
+ UInt32 unpackSize = Get32(src + 4);
+ if (uncompressedSize != unpackSize || newSectSize - 8 != packSize)
+ return S_FALSE;
+ if (packSize < 1)
+ return S_FALSE;
+ packSize--;
+ src += 8;
+ if (src[packSize] != 0)
+ return S_FALSE;
+
+ CBufInStream *inStreamSpec = new CBufInStream;
+ CMyComPtr<IInStream> inStream = inStreamSpec;
+ inStreamSpec->Init(src, packSize);
+
+ CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;
+ CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
+ outStreamSpec->Init(buf, uncompressedSize);
+
+ UInt64 uncompressedSize64 = uncompressedSize;
+ lzhDecoderSpec->FinishMode = true;
+ /*
+ EFI 1.1 probably used small dictionary and (pbit = 4) in LZH. We don't support such archives.
+ New version of compression code (named Tiano) uses LZH with (1 << 19) dictionary.
+ But maybe LZH decoder in UEFI decoder supports larger than (1 << 19) dictionary.
+ */
+ lzhDecoderSpec->SetDictSize(1 << 19);
+
+ HRESULT res = lzhDecoder->Code(inStream, outStream, NULL, &uncompressedSize64, NULL);
+ if (res != S_OK)
+ return res;
+
+ if (lzhDecoderSpec->GetInputProcessedSize() != packSize)
+ return S_FALSE;
+ }
+
RINOK(ParseSections(newBufIndex, 0, uncompressedSize, parent, compressionType, level));
}
else
@@ -1258,7 +969,7 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
if (lzmaUncompressedSize < uncompressedSize)
return S_FALSE;
SizeT destLen = (SizeT)lzmaUncompressedSize;
- int newBufIndex = AddBuf((UInt32)lzmaUncompressedSize);
+ unsigned newBufIndex = AddBuf((size_t)lzmaUncompressedSize);
CByteBuffer &buf = _bufs[newBufIndex];
ELzmaStatus status;
SizeT srcLen = newSectSize - (addSize + 5 + 8);
@@ -1278,7 +989,7 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
}
else if (type == SECTION_GUID_DEFINED)
{
- const UInt32 kHeaderSize = 4 + kGuidSize + 4;
+ const unsigned kHeaderSize = 4 + kGuidSize + 4;
if (sectSize < kHeaderSize)
return S_FALSE;
item.SetGuid(p + 4);
@@ -1373,7 +1084,8 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
{
item.BufIndex = AddBuf(s.Len());
CByteBuffer &buf0 = _bufs[item.BufIndex];
- memcpy(buf0, s, s.Len());
+ if (s.Len() != 0)
+ memcpy(buf0, s, s.Len());
item.Offset = 0;
item.Size = s.Len();
}
@@ -1389,7 +1101,7 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
{
AString s2 = "ver:";
s2 += UInt32ToString(Get16(p + 4));
- s2 += ' ';
+ s2.Add_Space();
s2 += s;
AddSpaceAndString(_items[item.Parent].Characts, s2);
needAdd = false;
@@ -1617,7 +1329,7 @@ HRESULT CHandler::ParseVolume(
HRESULT CHandler::OpenCapsule(IInStream *stream)
{
- const UInt32 kHeaderSize = 80;
+ const unsigned kHeaderSize = 80;
Byte buf[kHeaderSize];
RINOK(ReadStream_FALSE(stream, buf, kHeaderSize));
_h.Parse(buf);
@@ -1632,7 +1344,7 @@ HRESULT CHandler::OpenCapsule(IInStream *stream)
_h.OffsetToSplitInformation != 0 )
return E_NOTIMPL;
- int bufIndex = AddBuf(_h.CapsuleImageSize);
+ unsigned bufIndex = AddBuf(_h.CapsuleImageSize);
CByteBuffer &buf0 = _bufs[bufIndex];
memcpy(buf0, buf, kHeaderSize);
ReadStream_FALSE(stream, buf0 + kHeaderSize, _h.CapsuleImageSize - kHeaderSize);
@@ -1662,7 +1374,7 @@ HRESULT CHandler::OpenFv(IInStream *stream, const UInt64 * /* maxCheckStartPosit
_phySize = ffsHeader.VolSize;
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
UInt32 fvSize32 = (UInt32)ffsHeader.VolSize;
- int bufIndex = AddBuf(fvSize32);
+ unsigned bufIndex = AddBuf(fvSize32);
RINOK(ReadStream_FALSE(stream, _bufs[bufIndex], fvSize32));
return ParseVolume(bufIndex, 0, fvSize32, fvSize32, -1, -1, 0);
}
@@ -1680,14 +1392,17 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition,
unsigned num = _items.Size();
CIntArr numChilds(num);
+
unsigned i;
+
for (i = 0; i < num; i++)
numChilds[i] = 0;
+
for (i = 0; i < num; i++)
{
int parent = _items[i].Parent;
if (parent >= 0)
- numChilds[parent]++;
+ numChilds[(unsigned)parent]++;
}
for (i = 0; i < num; i++)
@@ -1696,14 +1411,15 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition,
int parent = item.Parent;
if (parent >= 0)
{
- CItem &parentItem = _items[parent];
- if (numChilds[parent] == 1)
+ CItem &parentItem = _items[(unsigned)parent];
+ if (numChilds[(unsigned)parent] == 1)
if (!item.ThereIsUniqueName || !parentItem.ThereIsUniqueName || !parentItem.ThereAreSubDirs)
parentItem.Skip = true;
}
}
CUIntVector mainToReduced;
+
for (i = 0; i < _items.Size(); i++)
{
mainToReduced.Add(_items2.Size());
@@ -1714,14 +1430,15 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition,
int numItems = -1;
int parent = item.Parent;
if (parent >= 0)
- numItems = numChilds[parent];
+ numItems = numChilds[(unsigned)parent];
AString name2 = item.GetName(numItems);
AString characts2 = item.Characts;
if (item.KeepName)
name = name2;
+
while (parent >= 0)
{
- const CItem &item3 = _items[parent];
+ const CItem &item3 = _items[(unsigned)parent];
if (!item3.Skip)
break;
if (item3.KeepName)
@@ -1735,6 +1452,7 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition,
AddSpaceAndString(characts2, item3.Characts);
parent = item3.Parent;
}
+
if (name.IsEmpty())
name = name2;
@@ -1743,7 +1461,7 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition,
item2.Name = name;
item2.Characts = characts2;
if (parent >= 0)
- item2.Parent = mainToReduced[parent];
+ item2.Parent = mainToReduced[(unsigned)parent];
_items2.Add(item2);
/*
CItem2 item2;
@@ -1753,6 +1471,7 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition,
_items2.Add(item2);
*/
}
+
return S_OK;
}
@@ -1873,30 +1592,26 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
namespace UEFIc {
-IMP_CreateArcIn_2(CHandler(true))
-
-static CArcInfo g_ArcInfo =
- { "UEFIc", "scap", 0, 0xD0,
- kCapsuleSigSize, CAPSULE_SIGNATURE,
+REGISTER_ARC_I_CLS(
+ CHandler(true),
+ "UEFIc", "scap", 0, 0xD0,
+ kCapsuleSig,
0,
NArcInfoFlags::kFindSignature,
- CreateArc };
+ NULL)
-REGISTER_ARC(UEFIc)
}
namespace UEFIf {
-IMP_CreateArcIn_2(CHandler(false))
-
-static CArcInfo g_ArcInfo =
- { "UEFIf", "uefif", 0, 0xD1,
- kGuidSize, FFS_SIGNATURE,
+REGISTER_ARC_I_CLS(
+ CHandler(false),
+ "UEFIf", "uefif", 0, 0xD1,
+ k_FFS_Guid,
kFfsGuidOffset,
NArcInfoFlags::kFindSignature,
- CreateArc };
-
-REGISTER_ARC(UEFIf)
+ NULL)
+
}
}}
diff --git a/CPP/7zip/Archive/VhdHandler.cpp b/CPP/7zip/Archive/VhdHandler.cpp
index a2126811..7508adfa 100644
--- a/CPP/7zip/Archive/VhdHandler.cpp
+++ b/CPP/7zip/Archive/VhdHandler.cpp
@@ -6,8 +6,6 @@
#include "../../Common/ComTry.h"
#include "../../Common/IntToString.h"
-#include "../../Common/MyBuffer.h"
-#include "../../Common/MyString.h"
#include "../../Windows/PropVariant.h"
@@ -41,7 +39,7 @@ static const UInt32 kDiskType_Fixed = 2;
static const UInt32 kDiskType_Dynamic = 3;
static const UInt32 kDiskType_Diff = 4;
-static const char *kDiskTypes[] =
+static const char * const kDiskTypes[] =
{
"0"
, "1"
@@ -201,11 +199,17 @@ bool CDynHeader::Parse(const Byte *p)
memcpy(ParentId, p + 0x28, 16);
{
const unsigned kNameLen = 256;
- wchar_t *s = ParentName.GetBuffer(kNameLen);
- for (unsigned i = 0; i < kNameLen; i++)
- s[i] = Get16(p + 0x40 + i * 2);
- s[kNameLen] = 0;
- ParentName.ReleaseBuffer();
+ wchar_t *s = ParentName.GetBuf(kNameLen);
+ unsigned i;
+ for (i = 0; i < kNameLen; i++)
+ {
+ wchar_t c = Get16(p + 0x40 + i * 2);
+ if (c == 0)
+ break;
+ s[i] = c;
+ }
+ s[i] = 0;
+ ParentName.ReleaseBuf_SetLen(i);
}
for (unsigned i = 0; i < 8; i++)
if (!ParentLocators[i].Parse(p + 0x240 + i * 24))
@@ -240,7 +244,7 @@ class CHandler:
void AddErrorMessage(const wchar_t *s)
{
if (!_errorMessage.IsEmpty())
- _errorMessage += L'\n';
+ _errorMessage.Add_LF();
_errorMessage += s;
}
void UpdatePhySize(UInt64 value)
@@ -265,7 +269,7 @@ class CHandler:
while (p && p->NeedParent())
{
if (!res.IsEmpty())
- res += L" -> ";
+ res.AddAscii(" -> ");
UString mainName;
UString anotherName;
if (Dyn.RelativeNameWasUsed)
@@ -281,7 +285,7 @@ class CHandler:
res += mainName;
if (mainName != anotherName && !anotherName.IsEmpty())
{
- res += L' ';
+ res.Add_Space();
res += L'(';
res += anotherName;
res += L')';
@@ -425,12 +429,20 @@ HRESULT CHandler::Open3()
Byte nameBuf[kNameBufSizeMax];
UString tempString;
unsigned len = (locator.DataLen >> 1);
- wchar_t *s = tempString.GetBuffer(len);
- RINOK(ReadPhy(locator.DataOffset, nameBuf, locator.DataLen));
- for (unsigned j = 0; j < len; j++)
- s[j] = GetUi16(nameBuf + j * 2);
- s[len] = 0;
- tempString.ReleaseBuffer();
+ {
+ wchar_t *s = tempString.GetBuf(len);
+ RINOK(ReadPhy(locator.DataOffset, nameBuf, locator.DataLen));
+ unsigned j;
+ for (j = 0; j < len; j++)
+ {
+ wchar_t c = GetUi16(nameBuf + j * 2);
+ if (c == 0)
+ break;
+ s[j] = c;
+ }
+ s[j] = 0;
+ tempString.ReleaseBuf_SetLen(j);
+ }
if (tempString[0] == L'.' && tempString[1] == L'\\')
tempString.DeleteFrontal(2);
Dyn.RelativeParentNameFromLocator = tempString;
@@ -518,10 +530,10 @@ HRESULT CHandler::Open3()
STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = 0;
if (_virtPos >= Footer.CurrentSize)
- return (Footer.CurrentSize == _virtPos) ? S_OK: E_FAIL;
+ return S_OK;
UInt64 rem = Footer.CurrentSize - _virtPos;
if (size > rem)
size = (UInt32)rem;
@@ -576,7 +588,7 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
cur += rem;
}
}
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = size;
_virtPos += size;
return res;
@@ -705,7 +717,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
AString res = s;
res.Trim();
ConvertUInt32ToString(Footer.CreatorVersion >> 16, s);
- res += ' ';
+ res.Add_Space();
res += s;
res += '.';
ConvertUInt32ToString(Footer.CreatorVersion & 0xFFFF, s);
@@ -971,15 +983,11 @@ STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "VHD", "vhd", ".mbr", 0xDC,
- kSignatureSize, SIGNATURE,
+REGISTER_ARC_I(
+ "VHD", "vhd", ".mbr", 0xDC,
+ kSignature,
0,
NArcInfoFlags::kUseGlobalOffset,
- CreateArc };
-
-REGISTER_ARC(Vhd)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp
index 886d8d77..bca551a6 100644
--- a/CPP/7zip/Archive/Wim/WimHandler.cpp
+++ b/CPP/7zip/Archive/Wim/WimHandler.cpp
@@ -37,7 +37,9 @@ static const Byte kProps[] =
kpidMethod,
kpidShortName,
kpidINode,
- kpidLinks
+ kpidLinks,
+ kpidIsAltStream,
+ kpidNumAltStreams,
#ifdef WIM_DETAILS
, kpidVolume
@@ -269,14 +271,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
res = kMethodLZX;
if (xpress)
{
- if (!res.IsEmpty())
- res += ' ';
+ res.Add_Space_if_NotEmpty();
res += kMethodXpress;
}
if (copy)
{
- if (!res.IsEmpty())
- res += ' ';
+ res.Add_Space_if_NotEmpty();
res += kMethodCopy;
}
prop = res;
@@ -308,6 +308,26 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
AddErrorMessage(s, "Some files have incorrect reference count");
if (!s.IsEmpty())
prop = s;
+ break;
+ }
+
+ case kpidReadOnly:
+ {
+ bool readOnly = false;
+ if (ThereIsError())
+ readOnly = true;
+ else if (_volumes.Size() != 0)
+ {
+ if (_version != kWimVersion
+ || _volumes.Size() != 2
+ || _volumes[0].Stream
+ // || _db.Images.Size() > kNumImagesMax
+ )
+ readOnly = true;
+ }
+ if (readOnly)
+ prop = readOnly;
+ break;
}
}
prop.Detach(value);
@@ -397,6 +417,22 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidSize: prop = (UInt64)(si ? si->Resource.UnpackSize : 0); break;
case kpidIsDir: prop = item.IsDir; break;
case kpidIsAltStream: prop = item.IsAltStream; break;
+ case kpidNumAltStreams:
+ {
+ if (!item.IsAltStream && mainItem->HasMetadata())
+ {
+ UInt32 dirRecordSize = _db.IsOldVersion ? kDirRecordSizeOld : kDirRecordSize;
+ UInt32 numAltStreams = Get16(metadata + dirRecordSize - 6);
+ if (numAltStreams != 0)
+ {
+ if (!item.IsDir)
+ numAltStreams--;
+ prop = numAltStreams;
+ }
+ }
+ break;
+ }
+
case kpidAttrib:
if (!item.IsAltStream && mainItem->ImageIndex >= 0)
{
@@ -481,7 +517,7 @@ STDMETHODIMP CHandler::GetRootProp(PROPID propID, PROPVARIANT *value)
{
// COM_TRY_BEGIN
NCOM::CPropVariant prop;
- if (_db.Images.Size() != 0 && _db.NumExludededItems != 0)
+ if (_db.Images.Size() != 0 && _db.NumExcludededItems != 0)
{
const CImage &image = _db.Images[_db.IndexOfUserImage];
const CItem &item = _db.Items[image.StartItem];
@@ -532,7 +568,7 @@ STDMETHODIMP CHandler::GetRootRawProp(PROPID propID, const void **data, UInt32 *
*data = 0;
*dataSize = 0;
*propType = 0;
- if (propID == kpidNtSecure && _db.Images.Size() != 0 && _db.NumExludededItems != 0)
+ if (propID == kpidNtSecure && _db.Images.Size() != 0 && _db.NumExcludededItems != 0)
{
const CImage &image = _db.Images[_db.IndexOfUserImage];
const CItem &item = _db.Items[image.StartItem];
@@ -705,7 +741,7 @@ class CVolumeName
public:
void InitName(const UString &name)
{
- int dotPos = name.ReverseFind('.');
+ int dotPos = name.ReverseFind_Dot();
if (dotPos < 0)
dotPos = name.Len();
_before = name.Left(dotPos);
@@ -798,11 +834,11 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal
if (_xmls.IsEmpty() || xml.Data != _xmls[0].Data)
{
- wchar_t sz[16];
+ char sz[16];
ConvertUInt32ToString(xml.VolIndex, sz);
xml.FileName = L'[';
- xml.FileName += sz;
- xml.FileName += L"].xml";
+ xml.FileName.AddAscii(sz);
+ xml.FileName.AddAscii("].xml");
_xmls.Add(xml);
}
@@ -957,11 +993,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
int streamIndex = item.StreamIndex;
if (streamIndex < 0)
{
- if (!testMode && !realOutStream)
- continue;
+ if (!item.IsDir)
+ if (!testMode && !realOutStream)
+ continue;
RINOK(extractCallback->PrepareOperation(askMode));
realOutStream.Release();
- RINOK(extractCallback->SetOperationResult(_db.ItemHasStream(item) ?
+ RINOK(extractCallback->SetOperationResult(!item.IsDir && _db.ItemHasStream(item) ?
NExtract::NOperationResult::kDataError :
NExtract::NOperationResult::kOK));
continue;
@@ -1016,7 +1053,7 @@ CHandler::CHandler()
_xmlError = false;
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
InitDefaults();
diff --git a/CPP/7zip/Archive/Wim/WimHandler.h b/CPP/7zip/Archive/Wim/WimHandler.h
index 416e11ca..00de1b87 100644
--- a/CPP/7zip/Archive/Wim/WimHandler.h
+++ b/CPP/7zip/Archive/Wim/WimHandler.h
@@ -70,7 +70,7 @@ public:
INTERFACE_IInArchive(;)
INTERFACE_IArchiveGetRawProps(;)
INTERFACE_IArchiveGetRootProps(;)
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
STDMETHOD(KeepModeForNextOpen)();
INTERFACE_IOutArchive(;)
};
diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
index 149989d1..145ede42 100644
--- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
+++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
@@ -21,7 +21,7 @@
#include "../../Common/UniqBlocks.h"
#include "../../Crypto/RandGen.h"
-#include "../../Crypto/Sha1.h"
+#include "../../Crypto/Sha1Cls.h"
#include "WimHandler.h"
@@ -676,6 +676,8 @@ static void AddTrees(CObjectVector<CDir> &trees, CObjectVector<CMetaItem> &metaI
trees.AddNew().Dirs.AddNew().MetaIndex = metaItems.Add(ri);
}
+#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
+
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 numItems, IArchiveUpdateCallback *callback)
{
COM_TRY_BEGIN
@@ -789,7 +791,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
unsigned imageIndex = (unsigned)val - 1;
if (imageIndex < _db.Images.Size())
isChangedImage[imageIndex] = true;
- if (_defaultImageNumber > 0 && val != _defaultImageNumber)
+ if (_defaultImageNumber > 0 && val != (unsigned)_defaultImageNumber)
return E_INVALIDARG;
}
}
@@ -1065,9 +1067,16 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
int colonPos = fileName.Find(L':');
if (colonPos < 0)
return E_INVALIDARG;
+
+ // we want to support cases of c::substream, where c: is drive name
+ if (colonPos == 1 && fileName[2] == L':' && IS_LETTER_CHAR(fileName[0]))
+ colonPos = 2;
const UString mainName = fileName.Left(colonPos);
unsigned indexOfDir;
- if (curItem->FindDir(db.MetaItems, mainName, indexOfDir))
+
+ if (mainName.IsEmpty())
+ ui.MetaIndex = curItem->MetaIndex;
+ else if (curItem->FindDir(db.MetaItems, mainName, indexOfDir))
ui.MetaIndex = curItem->Dirs[indexOfDir].MetaIndex;
else
{
@@ -1082,6 +1091,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
}
}
}
+
if (ui.MetaIndex >= 0)
{
CAltStream ss;
@@ -1126,7 +1136,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
NCOM::CPropVariant prop;
RINOK(GetOutProperty(callback, i, arcIndex, kpidShortName, &prop));
if (prop.vt == VT_BSTR)
- mi.ShortName = prop.bstrVal;
+ mi.ShortName.SetFromBstr(prop.bstrVal);
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
}
@@ -1235,7 +1245,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
{
const CItem &item = _db.Items[k];
if (item.StreamIndex >= 0)
- streamsRefs[item.StreamIndex]++;
+ streamsRefs[(unsigned)item.StreamIndex]++;
}
}
@@ -1250,7 +1260,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
continue;
const CItem &item = _db.Items[_db.SortedItems[ui.InArcIndex]];
if (item.StreamIndex >= 0)
- streamsRefs[item.StreamIndex]++;
+ streamsRefs[(unsigned)item.StreamIndex]++;
}
else
{
@@ -1614,7 +1624,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
db.DefaultDirItem = ri;
pos += db.WriteTree_Dummy(tree);
- CByteBuffer meta(pos);
+ CByteArr meta(pos);
Set32((Byte *)meta + 4, secBufs.Size()); // num security entries
pos = kSecuritySize;
@@ -1637,8 +1647,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
{
const CByteBuffer &buf = secBufs[i];
size_t size = buf.Size();
- memcpy(meta + pos, buf, size);
- pos += size;
+ if (size != 0)
+ {
+ memcpy(meta + pos, buf, size);
+ pos += size;
+ }
}
while ((pos & 7) != 0)
meta[pos++] = 0;
@@ -1740,15 +1753,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
size_t xmlSize;
{
- UString utf16String;
- if (!ConvertUTF8ToUnicode(xml, utf16String))
+ UString utf16;
+ if (!ConvertUTF8ToUnicode(xml, utf16))
return S_FALSE;
- xmlSize = (utf16String.Len() + 1) * 2;
+ xmlSize = (utf16.Len() + 1) * 2;
- CByteBuffer xmlBuf(xmlSize);
+ CByteArr xmlBuf(xmlSize);
Set16((Byte *)xmlBuf, 0xFEFF);
- for (i = 0; i < (unsigned)utf16String.Len(); i++)
- Set16((Byte *)xmlBuf + 2 + i * 2, utf16String[i]);
+ for (i = 0; i < (unsigned)utf16.Len(); i++)
+ Set16((Byte *)xmlBuf + 2 + i * 2, utf16[i]);
RINOK(WriteStream(outStream, (const Byte *)xmlBuf, xmlSize));
}
diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp
index cec037cc..12b8525c 100644
--- a/CPP/7zip/Archive/Wim/WimIn.cpp
+++ b/CPP/7zip/Archive/Wim/WimIn.cpp
@@ -325,10 +325,13 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
{
unsigned size = 0;
int index = index1;
- unsigned newLevel;
int imageIndex = Items[index].ImageIndex;
const CImage &image = Images[imageIndex];
- for (newLevel = 0;;)
+
+ unsigned newLevel = 0;
+ bool needColon = false;
+
+ for (;;)
{
const CItem &item = Items[index];
index = item.Parent;
@@ -338,10 +341,11 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
meta += item.IsAltStream ?
(IsOldVersion ? 0x10 : 0x24) :
(IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2);
+ needColon = item.IsAltStream;
size += Get16(meta) / 2;
size += newLevel;
newLevel = 1;
- if ((UInt32)size >= ((UInt32)1 << 15))
+ if (size >= ((UInt32)1 << 15))
{
path = kLongPath;
return;
@@ -356,7 +360,9 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
size += image.RootName.Len();
size += newLevel;
}
-
+ else if (needColon)
+ size++;
+
wchar_t *s = path.AllocBstr(size);
s[size] = 0;
@@ -364,28 +370,31 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
{
MyStringCopy(s, (const wchar_t *)image.RootName);
if (newLevel)
- s[image.RootName.Len()] = WCHAR_PATH_SEPARATOR;
+ s[image.RootName.Len()] = (wchar_t)(needColon ? L':' : WCHAR_PATH_SEPARATOR);
}
+ else if (needColon)
+ s[0] = L':';
index = index1;
wchar_t separator = 0;
+
for (;;)
{
const CItem &item = Items[index];
index = item.Parent;
if (index >= 0 || image.NumEmptyRootItems == 0)
{
- if (separator)
+ if (separator != 0)
s[--size] = separator;
const Byte *meta = image.Meta + item.Offset;
meta += (item.IsAltStream) ?
(IsOldVersion ? 0x10: 0x24) :
(IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2);
- UInt32 len = Get16(meta) / 2;
+ unsigned len = Get16(meta) / 2;
size -= len;
wchar_t *dest = s + size;
meta += 2;
- for (UInt32 i = 0; i < len; i++)
+ for (unsigned i = 0; i < len; i++)
dest[i] = Get16(meta + i * 2);
}
if (index < 0)
@@ -394,6 +403,14 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
}
}
+static bool IsEmptySha(const Byte *data)
+{
+ for (unsigned i = 0; i < kHashSize; i++)
+ if (data[i] != 0)
+ return false;
+ return true;
+}
+
// Root folders in OLD archives (ver = 1.10) conatin real items.
// Root folders in NEW archives (ver > 1.11) contain only one folder with empty name.
@@ -472,6 +489,8 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
pos += (size_t)len;
+ unsigned numItems2 = Items.Size();
+
for (UInt32 i = 0; i < numAltStreams; i++)
{
size_t rem = DirSize - pos;
@@ -522,7 +541,13 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
return S_FALSE;
}
- if (fileNameLen == 0)
+
+ /* wim uses alt sreams list, if there is at least one alt stream.
+ And alt stream without name is main stream. */
+
+ if (fileNameLen == 0 &&
+ (attrib & FILE_ATTRIBUTE_REPARSE_POINT
+ || !item.IsDir /* && (IsOldVersion || IsEmptySha(prevMeta + 0x40)) */ ))
{
Byte *prevMeta = DirData + item.Offset;
if (IsOldVersion)
@@ -546,7 +571,7 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
if (parent < 0 && numItems == 0 && shortNameLen == 0 && fileNameLen == 0 && item.IsDir)
{
CImage &image = Images.Back();
- image.NumEmptyRootItems = Items.Size() - image.StartItem;
+ image.NumEmptyRootItems = numItems2 - image.StartItem; // Items.Size()
}
if (item.IsDir && subdirOffset != 0)
@@ -732,14 +757,6 @@ static HRESULT ReadStreams(IInStream *inStream, const CHeader &h, CDatabase &db)
return (i == offsetBuf.Size()) ? S_OK : S_FALSE;
}
-static bool IsEmptySha(const Byte *data)
-{
- for (unsigned i = 0; i < kHashSize; i++)
- if (data[i] != 0)
- return false;
- return true;
-}
-
HRESULT CDatabase::OpenXml(IInStream *inStream, const CHeader &h, CByteBuffer &xml)
{
return UnpackData(inStream, h.XmlResource, h.IsLzxMode(), xml, NULL);
@@ -1046,7 +1063,7 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber)
SortedItems.Clear();
VirtualRoots.Clear();
IndexOfUserImage = imageIndex;
- NumExludededItems = 0;
+ NumExcludededItems = 0;
ExludedItem = -1;
if (Images.Size() != 1 && imageIndex < 0)
@@ -1054,6 +1071,7 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber)
unsigned startItem = 0;
unsigned endItem = 0;
+
if (imageIndex < 0)
{
endItem = Items.Size();
@@ -1062,7 +1080,7 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber)
IndexOfUserImage = 0;
const CImage &image = Images[0];
if (!showImageNumber)
- NumExludededItems = image.NumEmptyRootItems;
+ NumExcludededItems = image.NumEmptyRootItems;
}
}
else if ((unsigned)imageIndex < Images.Size())
@@ -1071,12 +1089,13 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber)
startItem = image.StartItem;
endItem = startItem + image.NumItems;
if (!showImageNumber)
- NumExludededItems = image.NumEmptyRootItems;
+ NumExcludededItems = image.NumEmptyRootItems;
}
- if (NumExludededItems != 0)
+
+ if (NumExcludededItems != 0)
{
ExludedItem = startItem;
- startItem += NumExludededItems;
+ startItem += NumExcludededItems;
}
unsigned num = endItem - startItem;
@@ -1205,7 +1224,8 @@ HRESULT CDatabase::ExtractReparseStreams(const CObjectVector<CVolume> &volumes,
Byte *dest = (Byte *)reparse;
SetUi32(dest, tag);
SetUi32(dest + 4, (UInt32)buf.Size());
- memcpy(dest + 8, buf, buf.Size());
+ if (buf.Size() != 0)
+ memcpy(dest + 8, buf, buf.Size());
ItemToReparse[i] = ReparseItems.Size() - 1;
}
@@ -1278,20 +1298,28 @@ void CWimXml::ToUnicode(UString &s)
const Byte *p = Data;
if (Get16(p) != 0xFEFF)
return;
- wchar_t *chars = s.GetBuffer((unsigned)size / 2);
+ wchar_t *chars = s.GetBuf((unsigned)(size / 2));
for (size_t i = 2; i < size; i += 2)
- *chars++ = (wchar_t)Get16(p + i);
+ {
+ wchar_t c = Get16(p + i);
+ if (c == 0)
+ break;
+ *chars++ = c;
+ }
*chars = 0;
- s.ReleaseBuffer();
+ s.ReleaseBuf_SetLen((unsigned)(chars - (const wchar_t *)s));
}
bool CWimXml::Parse()
{
- UString s;
- ToUnicode(s);
AString utf;
- if (!ConvertUnicodeToUTF8(s, utf))
- return false;
+ {
+ UString s;
+ ToUnicode(s);
+ // if (!ConvertUnicodeToUTF8(s, utf)) return false;
+ ConvertUnicodeToUTF8(s, utf);
+ }
+
if (!Xml.Parse(utf))
return false;
if (Xml.Root.Name != "WIM")
diff --git a/CPP/7zip/Archive/Wim/WimIn.h b/CPP/7zip/Archive/Wim/WimIn.h
index 4b7c6d95..c3b93a8d 100644
--- a/CPP/7zip/Archive/Wim/WimIn.h
+++ b/CPP/7zip/Archive/Wim/WimIn.h
@@ -406,7 +406,7 @@ public:
CUIntVector SortedItems;
int IndexOfUserImage; // -1 : if more than one images was filled to Sorted Items
- unsigned NumExludededItems;
+ unsigned NumExcludededItems;
int ExludedItem; // -1 : if there are no exclude items
CUIntVector VirtualRoots; // we use them for old 1.10 WIM archives
@@ -418,7 +418,7 @@ public:
return 0;
if (imageIndex >= Images.Size())
return 0;
- return Images[imageIndex].NumItems - NumExludededItems;
+ return Images[imageIndex].NumItems - NumExcludededItems;
}
bool ItemHasStream(const CItem &item) const;
diff --git a/CPP/7zip/Archive/Wim/WimRegister.cpp b/CPP/7zip/Archive/Wim/WimRegister.cpp
index 35d78314..3063dec4 100644
--- a/CPP/7zip/Archive/Wim/WimRegister.cpp
+++ b/CPP/7zip/Archive/Wim/WimRegister.cpp
@@ -9,19 +9,14 @@
namespace NArchive {
namespace NWim {
-IMP_CreateArcIn
-IMP_CreateArcOut
-
-static CArcInfo g_ArcInfo =
- { "wim", "wim swm", 0, 0xE6,
- 8, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 },
+REGISTER_ARC_IO(
+ "wim", "wim swm", 0, 0xE6,
+ kSignature,
0,
NArcInfoFlags::kAltStreams |
NArcInfoFlags::kNtSecure |
NArcInfoFlags::kSymLinks |
NArcInfoFlags::kHardLinks
- , REF_CreateArc_Pair };
-
-REGISTER_ARC(Wim)
+ , NULL)
}}
diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp
index 918ef736..7e89bf48 100644
--- a/CPP/7zip/Archive/XarHandler.cpp
+++ b/CPP/7zip/Archive/XarHandler.cpp
@@ -35,15 +35,15 @@ using namespace NWindows;
namespace NArchive {
namespace NXar {
-static const UInt32 kXmlSizeMax = ((UInt32)1 << 30) - (1 << 14);
-static const UInt32 kXmlPackSizeMax = kXmlSizeMax;
+static const size_t kXmlSizeMax = ((size_t )1 << 30) - (1 << 14);
+static const size_t kXmlPackSizeMax = kXmlSizeMax;
/*
#define XAR_CKSUM_NONE 0
#define XAR_CKSUM_SHA1 1
#define XAR_CKSUM_MD5 2
-static const char *k_ChecksumAlgos[] =
+static const char * const k_ChecksumAlgos[] =
{
"None"
, "SHA-1"
@@ -76,8 +76,8 @@ struct CFile
bool Sha1IsDefined;
// bool packSha1IsDefined;
- Byte Sha1[NCrypto::NSha1::kDigestSize];
- // Byte packSha1[NCrypto::NSha1::kDigestSize];
+ Byte Sha1[SHA1_DIGEST_SIZE];
+ // Byte packSha1[SHA1_DIGEST_SIZE];
int Parent;
@@ -107,7 +107,8 @@ class CHandler:
{
UInt64 _dataStartPos;
CMyComPtr<IInStream> _inStream;
- AString _xml;
+ CByteArr _xml;
+ size_t _xmlLen;
CObjectVector<CFile> _files;
// UInt32 _checkSumAlgo;
UInt64 _phySize;
@@ -182,7 +183,7 @@ static UInt64 ParseTime(const CXmlItem &item, const char *name)
return numSecs * 10000000;
}
-static int HexToByte(char c)
+static int HexToByte(unsigned char c)
{
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
@@ -200,7 +201,7 @@ static bool ParseSha1(const CXmlItem &item, const char *name, Byte *digest)
if (style == "SHA1")
{
const AString s = checkItem.GetSubString();
- if (s.Len() != NCrypto::NSha1::kDigestSize * 2)
+ if (s.Len() != SHA1_DIGEST_SIZE * 2)
return false;
for (unsigned i = 0; i < s.Len(); i += 2)
{
@@ -321,8 +322,9 @@ HRESULT CHandler::Open2(IInStream *stream)
_dataStartPos = kHeaderSize + packSize;
_phySize = _dataStartPos;
- char *ss = _xml.GetBuffer((unsigned)unpackSize);
-
+ _xml.Alloc((size_t)unpackSize + 1);
+ _xmlLen = (size_t)unpackSize;
+
NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder();
CMyComPtr<ICompressCoder> zlibCoder = zlibCoderSpec;
@@ -333,18 +335,18 @@ HRESULT CHandler::Open2(IInStream *stream)
CBufPtrSeqOutStream *outStreamLimSpec = new CBufPtrSeqOutStream;
CMyComPtr<ISequentialOutStream> outStreamLim(outStreamLimSpec);
- outStreamLimSpec->Init((Byte *)ss, (size_t)unpackSize);
+ outStreamLimSpec->Init(_xml, (size_t)unpackSize);
RINOK(zlibCoder->Code(inStreamLim, outStreamLim, NULL, NULL, NULL));
if (outStreamLimSpec->GetPos() != (size_t)unpackSize)
return S_FALSE;
- ss[(size_t)unpackSize] = 0;
- _xml.ReleaseBuffer();
+ _xml[(size_t)unpackSize] = 0;
+ if (strlen((const char *)(const Byte *)_xml) != unpackSize) return S_FALSE;
CXml xml;
- if (!xml.Parse(_xml))
+ if (!xml.Parse((const char *)(const Byte *)_xml))
return S_FALSE;
if (!xml.Root.IsTagged("xar") || xml.Root.SubItems.Size() != 1)
@@ -390,7 +392,8 @@ STDMETHODIMP CHandler::Close()
_phySize = 0;
_inStream.Release();
_files.Clear();
- _xml.Empty();
+ _xmlLen = 0;
+ _xml.Free();
_mainSubfile = -1;
_is_pkg = false;
return S_OK;
@@ -456,7 +459,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
case kpidPath: prop = "[TOC].xml"; break;
case kpidSize:
- case kpidPackSize: prop = (UInt64)_xml.Len(); break;
+ case kpidPackSize: prop = (UInt64)_xmlLen; break;
}
}
else
@@ -531,7 +534,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt32 index = (allFilesMode ? i : indices[i]);
#ifdef XAR_SHOW_RAW
if (index == _files.Size())
- totalSize += _xml.Len();
+ totalSize += _xmlLen;
else
#endif
totalSize += _files[index].Size;
@@ -614,9 +617,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (index == _files.Size())
{
outStreamSha1Spec->Init(false);
- outStreamLimSpec->Init(_xml.Len());
- RINOK(WriteStream(outStream, (const char *)_xml, _xml.Len()));
- currentPackSize = currentUnpSize = _xml.Len();
+ outStreamLimSpec->Init(_xmlLen);
+ RINOK(WriteStream(outStream, _xml, _xmlLen));
+ currentPackSize = currentUnpSize = _xmlLen;
}
else
#endif
@@ -670,9 +673,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
else if (item.Sha1IsDefined)
{
- Byte digest[NCrypto::NSha1::kDigestSize];
+ Byte digest[SHA1_DIGEST_SIZE];
outStreamSha1Spec->Final(digest);
- if (memcmp(digest, item.Sha1, NCrypto::NSha1::kDigestSize) != 0)
+ if (memcmp(digest, item.Sha1, SHA1_DIGEST_SIZE) != 0)
opRes = NExtract::NOperationResult::kCRCError;
}
}
@@ -695,7 +698,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
#ifdef XAR_SHOW_RAW
if (index == _files.Size())
{
- Create_BufInStream_WithNewBuf((const void *)(const char *)_xml, _xml.Len(), stream);
+ Create_BufInStream_WithNewBuffer(_xml, _xmlLen, stream);
return S_OK;
}
else
@@ -709,15 +712,13 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 'x', 'a', 'r', '!', 0, 0x1C };
-static CArcInfo g_ArcInfo =
- { "Xar", "xar pkg", 0, 0xE1,
- 6, { 'x', 'a', 'r', '!', 0, 0x1C },
+REGISTER_ARC_I(
+ "Xar", "xar pkg", 0, 0xE1,
+ k_Signature,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Xar)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp
index 0de58a44..ada14fbf 100644
--- a/CPP/7zip/Archive/XzHandler.cpp
+++ b/CPP/7zip/Archive/XzHandler.cpp
@@ -23,6 +23,8 @@
#include "Common/HandlerOut.h"
+#include "XzHandler.h"
+
using namespace NWindows;
namespace NCompress {
@@ -32,92 +34,36 @@ 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";
-struct CStatInfo
+void CStatInfo::Clear()
{
- UInt64 InSize;
- UInt64 OutSize;
- UInt64 PhySize;
-
- UInt64 NumStreams;
- UInt64 NumBlocks;
-
- bool UnpackSize_Defined;
-
- bool NumStreams_Defined;
- bool NumBlocks_Defined;
-
- bool IsArc;
- bool UnexpectedEnd;
- bool DataAfterEnd;
- bool Unsupported;
- bool HeadersError;
- bool DataError;
- bool CrcError;
-
- CStatInfo() { Clear(); }
-
- void Clear()
- {
- InSize = 0;
- OutSize = 0;
- PhySize = 0;
-
- NumStreams = 0;
- NumBlocks = 0;
-
- UnpackSize_Defined = false;
+ InSize = 0;
+ OutSize = 0;
+ PhySize = 0;
- NumStreams_Defined = false;
- NumBlocks_Defined = false;
-
- UnexpectedEnd = false;
- DataAfterEnd = false;
- Unsupported = false;
- HeadersError = false;
- DataError = false;
- CrcError = false;
- IsArc = false;
- }
-
-};
-
-struct IDecodeState: public CStatInfo
-{
- SRes DecodeRes;
-
- IDecodeState(): DecodeRes(SZ_OK) {}
- virtual HRESULT Progress() = 0;
-
- HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream);
-};
-
-struct CVirtProgress_To_LocalProgress: public IDecodeState
-{
- CLocalProgress *lps;
- CMyComPtr<ICompressProgressInfo> progress;
-
- HRESULT Progress();
-};
-
-HRESULT CVirtProgress_To_LocalProgress::Progress()
-{
- lps->InSize = InSize;
- lps->OutSize = OutSize;
- return lps->SetCur();
+ 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,
public IArchiveOpenSeq,
@@ -148,10 +94,11 @@ class CHandler:
HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback);
- HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, IDecodeState &progress)
+ HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,
+ CDecoder &decoder, ICompressProgressInfo *progress)
{
- RINOK(progress.Decode(seqInStream, outStream));
- _stat = progress;
+ RINOK(decoder.Decode(seqInStream, outStream, progress));
+ _stat = decoder;
_phySize_Defined = true;
return S_OK;
}
@@ -171,7 +118,7 @@ public:
#ifndef EXTRACT_ONLY
INTERFACE_IOutArchive(;)
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
#endif
CHandler();
@@ -295,12 +242,11 @@ 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[] =
+static const char * const kChecks[] =
{
"NoCheck"
, "CRC32"
@@ -423,26 +369,6 @@ struct CXzsCPP
~CXzsCPP() { Xzs_Free(&p, &g_Alloc); }
};
-
-struct CVirtProgress_To_OpenProgress: public IDecodeState
-{
- IArchiveOpenCallback *Callback;
- UInt64 Offset;
-
- HRESULT Progress();
-};
-
-HRESULT CVirtProgress_To_OpenProgress::Progress()
-{
- if (Callback)
- {
- UInt64 files = 0;
- UInt64 value = Offset + InSize;
- return Callback->SetCompleted(&files, &value);
- }
- return S_OK;
-}
-
static HRESULT SRes_to_Open_HRESULT(SRes res)
{
switch (res)
@@ -527,6 +453,7 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
{
res = SZ_OK;
}
+
RINOK(SRes_to_Open_HRESULT(res));
_stream = inStream;
_seqStream = inStream;
@@ -587,38 +514,32 @@ 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);
+}
+
+CXzUnpackerCPP::~CXzUnpackerCPP()
+{
+ XzUnpacker_Free(&p);
+ MyFree(InBuf);
+ MyFree(OutBuf);
+}
-HRESULT IDecodeState::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream)
+HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
{
const size_t kInBufSize = 1 << 15;
const size_t kOutBufSize = 1 << 21;
+ Clear();
DecodeRes = SZ_OK;
- CXzUnpackerCPP xzu;
XzUnpacker_Init(&xzu.p);
- xzu.InBuf = (Byte *)MyAlloc(kInBufSize);
- xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);
- if (!xzu.InBuf || !xzu.OutBuf)
- return E_OUTOFMEMORY;
-
+ if (!xzu.InBuf)
+ xzu.InBuf = (Byte *)MyAlloc(kInBufSize);
+ if (!xzu.OutBuf)
+ xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);
+
UInt32 inSize = 0;
SizeT inPos = 0;
SizeT outPos = 0;
@@ -664,7 +585,10 @@ HRESULT IDecodeState::Decode(ISequentialInStream *seqInStream, ISequentialOutStr
else
outPos = 0;
- RINOK(Progress());
+ if (progress)
+ {
+ RINOK(progress->SetRatioInfo(&InSize, &OutSize));
+ }
if (finished)
{
@@ -730,6 +654,30 @@ HRESULT IDecodeState::Decode(ISequentialInStream *seqInStream, ISequentialOutStr
return S_OK;
}
+Int32 CDecoder::Get_Extract_OperationResult() const
+{
+ Int32 opRes;
+ 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)
{
@@ -739,7 +687,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG;
- extractCallback->SetTotal(_stat.PhySize);
+ if (_phySize_Defined)
+ extractCallback->SetTotal(_stat.PhySize);
+
UInt64 currentTotalPacked = 0;
RINOK(extractCallback->SetCompleted(&currentTotalPacked));
CMyComPtr<ISequentialOutStream> realOutStream;
@@ -754,11 +704,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
extractCallback->PrepareOperation(askMode);
- CVirtProgress_To_LocalProgress vp;
- vp.lps = new CLocalProgress;
- vp.progress = vp.lps;
- vp.lps->Init(extractCallback, true);
-
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> lpsRef = lps;
+ lps->Init(extractCallback, true);
if (_needSeekToStart)
{
@@ -769,28 +717,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
else
_needSeekToStart = true;
- RINOK(Decode2(_seqStream, realOutStream, vp));
-
- Int32 opRes;
-
- if (!vp.IsArc)
- opRes = NExtract::NOperationResult::kIsNotArc;
- else if (vp.UnexpectedEnd)
- opRes = NExtract::NOperationResult::kUnexpectedEnd;
- else if (vp.DataAfterEnd)
- opRes = NExtract::NOperationResult::kDataAfterEnd;
- else if (vp.CrcError)
- opRes = NExtract::NOperationResult::kCRCError;
- else if (vp.Unsupported)
- opRes = NExtract::NOperationResult::kUnsupportedMethod;
- else if (vp.HeadersError)
- opRes = NExtract::NOperationResult::kDataError;
- else if (vp.DataError)
- opRes = NExtract::NOperationResult::kDataError;
- else if (vp.DecodeRes != SZ_OK)
- opRes = NExtract::NOperationResult::kDataError;
- else
- opRes = NExtract::NOperationResult::kOK;
+ CDecoder decoder;
+ RINOK(Decode2(_seqStream, realOutStream, decoder, lpsRef));
+ Int32 opRes = decoder.Get_Extract_OperationResult();
realOutStream.Release();
return extractCallback->SetOperationResult(opRes);
@@ -808,6 +737,8 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *updateCallback)
{
+ COM_TRY_BEGIN
+
CSeqOutStreamWrap seqOutStream(outStream);
if (numItems == 0)
@@ -927,16 +858,37 @@ 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)
+ {
+ if (_phySize_Defined)
+ RINOK(updateCallback->SetTotal(_stat.PhySize));
RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
- return NCompress::CopyStream(_stream, outStream, NULL);
+ }
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(updateCallback, true);
+
+ return NCompress::CopyStream(_stream, outStream, progress);
+
+ COM_TRY_END
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
COM_TRY_BEGIN
+
Init();
for (UInt32 i = 0; i < numProps; i++)
{
@@ -964,28 +916,25 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
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.IsEqualToNoCase(k_LZMA2_Name))
+ else if (!methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name))
return E_INVALIDARG;
}
+
return S_OK;
+
COM_TRY_END
}
#endif
-IMP_CreateArcIn
-IMP_CreateArcOut
-
-static CArcInfo g_ArcInfo =
- { "xz", "xz txz", "* .tar", 0xC,
- 6, { 0xFD, '7' , 'z', 'X', 'Z', 0 },
+REGISTER_ARC_IO(
+ "xz", "xz txz", "* .tar", 0xC,
+ XZ_SIG,
0,
NArcInfoFlags::kKeepName,
- REF_CreateArc_Pair };
-
-REGISTER_ARC(xz)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/XzHandler.h b/CPP/7zip/Archive/XzHandler.h
new file mode 100644
index 00000000..4a59e356
--- /dev/null
+++ b/CPP/7zip/Archive/XzHandler.h
@@ -0,0 +1,65 @@
+// XzHandler.h
+
+#ifndef __XZ_HANDLER_H
+#define __XZ_HANDLER_H
+
+#include "../../../C/Xz.h"
+
+#include "../ICoder.h"
+
+namespace NArchive {
+namespace NXz {
+
+struct CXzUnpackerCPP
+{
+ Byte *InBuf;
+ Byte *OutBuf;
+ CXzUnpacker p;
+
+ CXzUnpackerCPP();
+ ~CXzUnpackerCPP();
+};
+
+struct CStatInfo
+{
+ UInt64 InSize;
+ UInt64 OutSize;
+ UInt64 PhySize;
+
+ UInt64 NumStreams;
+ UInt64 NumBlocks;
+
+ bool UnpackSize_Defined;
+
+ bool NumStreams_Defined;
+ bool NumBlocks_Defined;
+
+ bool IsArc;
+ bool UnexpectedEnd;
+ bool DataAfterEnd;
+ bool Unsupported;
+ bool HeadersError;
+ bool DataError;
+ bool CrcError;
+
+ CStatInfo() { Clear(); }
+
+ void Clear();
+};
+
+struct CDecoder: public CStatInfo
+{
+ CXzUnpackerCPP xzu;
+ SRes DecodeRes; // it's not HRESULT
+
+ CDecoder(): DecodeRes(SZ_OK) {}
+
+ /* Decode() can return ERROR code only if there is progress or stream error.
+ Decode() returns S_OK in case of xz decoding error, but DecodeRes and CStatInfo contain error information */
+ HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress);
+ Int32 Get_Extract_OperationResult() const;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/ZHandler.cpp b/CPP/7zip/Archive/ZHandler.cpp
index 7635f22d..29934367 100644
--- a/CPP/7zip/Archive/ZHandler.cpp
+++ b/CPP/7zip/Archive/ZHandler.cpp
@@ -224,15 +224,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 0x1F, 0x9D };
-static CArcInfo g_ArcInfo =
- { "Z", "z taz", "* .tar", 5,
- 2, { 0x1F, 0x9D },
+REGISTER_ARC_I(
+ "Z", "z taz", "* .tar", 5,
+ k_Signature,
0,
0,
- CreateArc, NULL, IsArc_Z };
-
-REGISTER_ARC(Z)
+ IsArc_Z)
}}
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
index 9a0d7515..c9c290aa 100644
--- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
+++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
@@ -3,6 +3,7 @@
#include "StdAfx.h"
#include "../../../../C/7zCrc.h"
+#include "../../../../C/Alloc.h"
#include "../../../Windows/PropVariant.h"
@@ -77,32 +78,46 @@ STDMETHODIMP CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStr
CAddCommon::CAddCommon(const CCompressionMethodMode &options):
- _options(options),
- _copyCoderSpec(NULL),
- _cryptoStreamSpec(0)
- {}
+ _options(options),
+ _copyCoderSpec(NULL),
+ _cryptoStreamSpec(NULL),
+ _buf(NULL)
+ {}
-static HRESULT GetStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)
+CAddCommon::~CAddCommon()
{
+ MidFree(_buf);
+}
+
+static const UInt32 kBufSize = ((UInt32)1 << 16);
+
+HRESULT CAddCommon::CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)
+{
+ if (!_buf)
+ {
+ _buf = (Byte *)MidAlloc(kBufSize);
+ if (!_buf)
+ return E_OUTOFMEMORY;
+ }
+
UInt32 crc = CRC_INIT_VAL;
- const UInt32 kBufSize = (1 << 14);
- Byte buf[kBufSize];
for (;;)
{
UInt32 processed;
- RINOK(inStream->Read(buf, kBufSize, &processed));
+ RINOK(inStream->Read(_buf, kBufSize, &processed));
if (processed == 0)
{
resultCRC = CRC_GET_DIGEST(crc);
return S_OK;
}
- crc = CrcUpdate(crc, buf, (size_t)processed);
+ crc = CrcUpdate(crc, _buf, (size_t)processed);
}
}
HRESULT CAddCommon::Compress(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream, IOutStream *outStream,
+ UInt32 /* fileTime */,
ICompressProgressInfo *progress, CCompressingResult &opRes)
{
if (!inStream)
@@ -111,13 +126,14 @@ HRESULT CAddCommon::Compress(
return E_INVALIDARG;
}
- CSequentialInStreamWithCRC *inSecCrcStreamSpec = NULL;
+ // CSequentialInStreamWithCRC *inSecCrcStreamSpec = NULL;
CInStreamWithCRC *inCrcStreamSpec = NULL;
CMyComPtr<ISequentialInStream> inCrcStream;
{
CMyComPtr<IInStream> inStream2;
- // we don't support stdin, since stream from stdin can require 64-bit size header
- RINOK(inStream->QueryInterface(IID_IInStream, (void **)&inStream2));
+
+ inStream->QueryInterface(IID_IInStream, (void **)&inStream2);
+
if (inStream2)
{
inCrcStreamSpec = new CInStreamWithCRC;
@@ -127,28 +143,29 @@ HRESULT CAddCommon::Compress(
}
else
{
+ // we don't support stdin, since stream from stdin can require 64-bit size header
+ return E_NOTIMPL;
+ /*
inSecCrcStreamSpec = new CSequentialInStreamWithCRC;
inCrcStream = inSecCrcStreamSpec;
inSecCrcStreamSpec->SetStream(inStream);
inSecCrcStreamSpec->Init();
+ */
}
}
unsigned numTestMethods = _options.MethodSequence.Size();
- if (numTestMethods > 1 || _options.PasswordIsDefined)
- {
- if (!inCrcStreamSpec)
- {
- if (_options.PasswordIsDefined)
- return E_NOTIMPL;
- numTestMethods = 1;
- }
- }
+ if (numTestMethods > 1 && !inCrcStreamSpec)
+ numTestMethods = 1;
+
+ UInt32 crc = 0;
+ bool crc_IsCalculated = false;
Byte method = 0;
- COutStreamReleaser outStreamReleaser;
+ CFilterCoder::C_OutStream_Releaser outStreamReleaser;
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;
+ opRes.FileTimeWasUsed = false;
for (unsigned i = 0; i < numTestMethods; i++)
{
@@ -164,7 +181,7 @@ HRESULT CAddCommon::Compress(
if (!_cryptoStream)
{
- _cryptoStreamSpec = new CFilterCoder;
+ _cryptoStreamSpec = new CFilterCoder(true);
_cryptoStream = _cryptoStreamSpec;
}
@@ -186,13 +203,32 @@ HRESULT CAddCommon::Compress(
_cryptoStreamSpec->Filter = _filterSpec = new NCrypto::NZip::CEncoder;
_filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len());
}
- UInt32 crc = 0;
- RINOK(GetStreamCRC(inStream, crc));
- RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
- RINOK(_filterSpec->WriteHeader(outStream, crc));
+
+ UInt32 check;
+
+ // if (inCrcStreamSpec)
+ {
+ if (!crc_IsCalculated)
+ {
+ RINOK(CalcStreamCRC(inStream, crc));
+ crc_IsCalculated = true;
+ RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
+ }
+ check = (crc >> 16);
+ }
+ /*
+ else
+ {
+ opRes.FileTimeWasUsed = true;
+ check = (fileTime & 0xFFFF);
+ }
+ */
+
+ RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check));
}
RINOK(_cryptoStreamSpec->SetOutStream(outStream));
+ RINOK(_cryptoStreamSpec->InitEncoder());
outStreamReleaser.FilterCoder = _cryptoStreamSpec;
}
@@ -250,7 +286,7 @@ HRESULT CAddCommon::Compress(
}
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
- methodId, _compressEncoder, true));
+ methodId, true, _compressEncoder));
if (!_compressEncoder)
return E_NOTIMPL;
@@ -284,34 +320,42 @@ HRESULT CAddCommon::Compress(
}
}
+ if (_options.PasswordIsDefined)
+ {
+ RINOK(_cryptoStreamSpec->OutStreamFinish());
+
+ if (_options.IsAesMode)
+ {
+ RINOK(_filterAesSpec->WriteFooter(outStream));
+ }
+ }
+
RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize));
- if (inCrcStreamSpec)
+ // if (inCrcStreamSpec)
{
opRes.CRC = inCrcStreamSpec->GetCRC();
opRes.UnpackSize = inCrcStreamSpec->GetSize();
}
+ /*
else
{
opRes.CRC = inSecCrcStreamSpec->GetCRC();
opRes.UnpackSize = inSecCrcStreamSpec->GetSize();
}
+ */
if (_options.PasswordIsDefined)
{
if (opRes.PackSize < opRes.UnpackSize +
- (_options.IsAesMode ? _filterAesSpec->GetHeaderSize() : NCrypto::NZip::kHeaderSize))
+ (_options.IsAesMode ? _filterAesSpec->GetAddPackSize() : NCrypto::NZip::kHeaderSize))
break;
}
else if (opRes.PackSize < opRes.UnpackSize)
break;
}
-
- if (_options.PasswordIsDefined && _options.IsAesMode)
- {
- RINOK(_filterAesSpec->WriteFooter(outStream));
- RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize));
- }
+
+
opRes.Method = method;
return S_OK;
}
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.h b/CPP/7zip/Archive/Zip/ZipAddCommon.h
index e4c02db3..1e0c3bfa 100644
--- a/CPP/7zip/Archive/Zip/ZipAddCommon.h
+++ b/CPP/7zip/Archive/Zip/ZipAddCommon.h
@@ -26,6 +26,7 @@ struct CCompressingResult
UInt32 CRC;
UInt16 Method;
Byte ExtractVersion;
+ bool FileTimeWasUsed;
};
class CAddCommon
@@ -43,11 +44,16 @@ class CAddCommon
NCrypto::NZip::CEncoder *_filterSpec;
NCrypto::NWzAes::CEncoder *_filterAesSpec;
+ Byte *_buf;
+
+ HRESULT CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC);
public:
CAddCommon(const CCompressionMethodMode &options);
+ ~CAddCommon();
HRESULT Compress(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream, IOutStream *outStream,
+ UInt32 fileTime,
ICompressProgressInfo *progress, CCompressingResult &operationResult);
};
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp
index f556068c..3e29a880 100644
--- a/CPP/7zip/Archive/Zip/ZipHandler.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp
@@ -28,6 +28,8 @@
#include "../Common/ItemNameUtils.h"
#include "../Common/OutStreamWithCRC.h"
+#include "../XzHandler.h"
+
#include "ZipHandler.h"
using namespace NWindows;
@@ -38,7 +40,7 @@ namespace NZip {
static const CMethodId kMethodId_ZipBase = 0x040100;
static const CMethodId kMethodId_BZip2 = 0x040202;
-static const char *kHostOS[] =
+static const char * const kHostOS[] =
{
"FAT"
, "AMIGA"
@@ -62,7 +64,7 @@ static const char *kHostOS[] =
, "OS/X"
};
-static const char *kMethods[] =
+static const char * const kMethods[] =
{
"Store"
, "Shrink"
@@ -91,6 +93,7 @@ static const CIdToNamePair k_MethodIdNamePairs[] =
{
{ NFileHeader::NCompressionMethod::kBZip2, "BZip2" },
{ NFileHeader::NCompressionMethod::kLZMA, "LZMA" },
+ { NFileHeader::NCompressionMethod::kXz, "xz" },
{ NFileHeader::NCompressionMethod::kJpeg, "Jpeg" },
{ NFileHeader::NCompressionMethod::kWavPack, "WavPack" },
{ NFileHeader::NCompressionMethod::kPPMd, "PPMd" }
@@ -156,14 +159,7 @@ CHandler::CHandler()
static AString BytesToString(const CByteBuffer &data)
{
AString s;
- unsigned size = (unsigned)data.Size();
- if (size > 0)
- {
- char *p = s.GetBuffer(size);
- memcpy(p, (const Byte *)data, size);
- p[size] = 0;
- s.ReleaseBuffer();
- }
+ s.SetFrom_CalcLen((const char *)(const Byte *)data, (unsigned)data.Size());
return s;
}
@@ -220,6 +216,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
prop = v;
break;
}
+
+ case kpidReadOnly:
+ {
+ if (m_Archive.IsOpen())
+ if (!m_Archive.CanUpdate())
+ prop = true;
+ break;
+ }
}
prop.Detach(value);
COM_TRY_END
@@ -334,12 +338,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidMethod:
{
- UInt16 methodId = item.Method;
+ unsigned id = item.Method;
AString m;
if (item.IsEncrypted())
{
- if (methodId == NFileHeader::NCompressionMethod::kWzAES)
+ if (id == NFileHeader::NCompressionMethod::kWzAES)
{
m += kMethod_AES;
CWzAesExtra aesField;
@@ -349,7 +353,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
s[0] = '-';
ConvertUInt32ToString(((unsigned)aesField.Strength + 1) * 64 , s + 1);
m += s;
- methodId = aesField.Method;
+ id = aesField.Method;
}
}
else if (item.IsStrongEncrypted())
@@ -381,19 +385,19 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
char temp[16];
const char *s = NULL;
- if (methodId < ARRAY_SIZE(kMethods))
- s = kMethods[methodId];
+ if (id < ARRAY_SIZE(kMethods))
+ s = kMethods[id];
else
{
- s = FindNameForId(k_MethodIdNamePairs, ARRAY_SIZE(k_MethodIdNamePairs), methodId);
+ s = FindNameForId(k_MethodIdNamePairs, ARRAY_SIZE(k_MethodIdNamePairs), id);
if (!s)
{
- ConvertUInt32ToString(methodId, temp);
+ ConvertUInt32ToString(id, temp);
s = temp;
}
}
m += s;
- if (methodId == NFileHeader::NCompressionMethod::kLZMA && item.IsLzmaEOS())
+ if (id == NFileHeader::NCompressionMethod::kLZMA && item.IsLzmaEOS())
m += ":EOS";
}
@@ -507,9 +511,36 @@ HRESULT CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *
return Decoder->Code(inStream, outStream, NULL, outSize, progress);
}
+
+class CXzDecoder:
+ public ICompressCoder,
+ public CMyUnknownImp
+{
+ NArchive::NXz::CDecoder _decoder;
+public:
+
+ STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+
+ MY_UNKNOWN_IMP
+};
+
+HRESULT CXzDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
+{
+ RINOK(_decoder.Decode(inStream, outStream, progress));
+ Int32 opRes = _decoder.Get_Extract_OperationResult();
+ if (opRes == NExtract::NOperationResult::kUnsupportedMethod)
+ return E_NOTIMPL;
+ if (opRes != NExtract::NOperationResult::kOK)
+ return S_FALSE;
+ return S_OK;
+}
+
+
struct CMethodItem
{
- UInt16 ZipMethod;
+ unsigned ZipMethod;
CMyComPtr<ICompressCoder> Coder;
};
@@ -559,12 +590,13 @@ HRESULT CZipDecoder::Decode(
Int32 &res)
{
res = NExtract::NOperationResult::kDataError;
- CInStreamReleaser inStreamReleaser;
+ CFilterCoder::C_InStream_Releaser inStreamReleaser;
bool needCRC = true;
bool wzAesMode = false;
bool pkAesMode = false;
- UInt16 methodId = item.Method;
+ unsigned id = item.Method;
+
if (item.IsEncrypted())
{
if (item.IsStrongEncrypted())
@@ -580,7 +612,7 @@ HRESULT CZipDecoder::Decode(
return S_OK;
}
}
- if (!pkAesMode && methodId == NFileHeader::NCompressionMethod::kWzAES)
+ if (!pkAesMode && id == NFileHeader::NCompressionMethod::kWzAES)
{
CWzAesExtra aesField;
if (item.CentralExtra.GetWzAes(aesField))
@@ -613,6 +645,7 @@ HRESULT CZipDecoder::Decode(
}
CMyComPtr<ICompressFilter> cryptoFilter;
+
if (item.IsEncrypted())
{
if (wzAesMode)
@@ -620,15 +653,18 @@ HRESULT CZipDecoder::Decode(
CWzAesExtra aesField;
if (!item.CentralExtra.GetWzAes(aesField))
return S_OK;
- methodId = aesField.Method;
+ id = aesField.Method;
if (!_wzAesDecoder)
{
_wzAesDecoderSpec = new NCrypto::NWzAes::CDecoder;
_wzAesDecoder = _wzAesDecoderSpec;
}
cryptoFilter = _wzAesDecoder;
- Byte properties = aesField.Strength;
- RINOK(_wzAesDecoderSpec->SetDecoderProperties2(&properties, 1));
+ if (!_wzAesDecoderSpec->SetKeyMode(aesField.Strength))
+ {
+ res = NExtract::NOperationResult::kUnsupportedMethod;
+ return S_OK;
+ }
}
else if (pkAesMode)
{
@@ -648,6 +684,7 @@ HRESULT CZipDecoder::Decode(
}
cryptoFilter = _zipCryptoDecoder;
}
+
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
RINOK(cryptoFilter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
@@ -699,39 +736,41 @@ HRESULT CZipDecoder::Decode(
unsigned m;
for (m = 0; m < methodItems.Size(); m++)
- if (methodItems[m].ZipMethod == methodId)
+ if (methodItems[m].ZipMethod == id)
break;
if (m == methodItems.Size())
{
CMethodItem mi;
- mi.ZipMethod = methodId;
- if (methodId == NFileHeader::NCompressionMethod::kStored)
+ mi.ZipMethod = id;
+ if (id == NFileHeader::NCompressionMethod::kStored)
mi.Coder = new NCompress::CCopyCoder;
- else if (methodId == NFileHeader::NCompressionMethod::kShrunk)
+ else if (id == NFileHeader::NCompressionMethod::kShrunk)
mi.Coder = new NCompress::NShrink::CDecoder;
- else if (methodId == NFileHeader::NCompressionMethod::kImploded)
+ else if (id == NFileHeader::NCompressionMethod::kImploded)
mi.Coder = new NCompress::NImplode::NDecoder::CCoder;
- else if (methodId == NFileHeader::NCompressionMethod::kLZMA)
+ else if (id == NFileHeader::NCompressionMethod::kLZMA)
mi.Coder = new CLzmaDecoder;
- else if (methodId == NFileHeader::NCompressionMethod::kPPMd)
+ else if (id == NFileHeader::NCompressionMethod::kXz)
+ mi.Coder = new CXzDecoder;
+ else if (id == NFileHeader::NCompressionMethod::kPPMd)
mi.Coder = new NCompress::NPpmdZip::CDecoder(true);
else
{
CMethodId szMethodID;
- if (methodId == NFileHeader::NCompressionMethod::kBZip2)
+ if (id == NFileHeader::NCompressionMethod::kBZip2)
szMethodID = kMethodId_BZip2;
else
{
- if (methodId > 0xFF)
+ if (id > 0xFF)
{
res = NExtract::NOperationResult::kUnsupportedMethod;
return S_OK;
}
- szMethodID = kMethodId_ZipBase + (Byte)methodId;
+ szMethodID = kMethodId_ZipBase + (Byte)id;
}
- RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS szMethodID, mi.Coder, false));
+ RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS szMethodID, false, mi.Coder));
if (mi.Coder == 0)
{
@@ -741,6 +780,7 @@ HRESULT CZipDecoder::Decode(
}
m = methodItems.Add(mi);
}
+
ICompressCoder *coder = methodItems[m].Coder;
{
@@ -771,13 +811,23 @@ HRESULT CZipDecoder::Decode(
{
if (!filterStream)
{
- filterStreamSpec = new CFilterCoder;
+ filterStreamSpec = new CFilterCoder(false);
filterStream = filterStreamSpec;
}
+
filterStreamSpec->Filter = cryptoFilter;
+
if (wzAesMode)
{
result = _wzAesDecoderSpec->ReadHeader(inStream);
+ if (result == S_OK)
+ {
+ if (!_wzAesDecoderSpec->Init_and_CheckPassword())
+ {
+ res = NExtract::NOperationResult::kWrongPassword;
+ return S_OK;
+ }
+ }
}
else if (pkAesMode)
{
@@ -785,43 +835,64 @@ HRESULT CZipDecoder::Decode(
if (result == S_OK)
{
bool passwOK;
- result = _pkAesDecoderSpec->CheckPassword(passwOK);
+ result = _pkAesDecoderSpec->Init_and_CheckPassword(passwOK);
if (result == S_OK && !passwOK)
- result = S_FALSE;
+ {
+ res = NExtract::NOperationResult::kWrongPassword;
+ return S_OK;
+ }
}
}
else
{
result = _zipCryptoDecoderSpec->ReadHeader(inStream);
+ if (result == S_OK)
+ {
+ _zipCryptoDecoderSpec->Init_BeforeDecode();
+
+ /* Info-ZIP modification to ZipCrypto format:
+ if bit 3 of the general purpose bit flag is set,
+ it uses high byte of 16-bit File Time.
+ Info-ZIP code probably writes 2 bytes of File Time.
+ We check only 1 byte. */
+
+ // UInt32 v1 = GetUi16(_zipCryptoDecoderSpec->_header + NCrypto::NZip::kHeaderSize - 2);
+ // UInt32 v2 = (item.HasDescriptor() ? (item.Time & 0xFFFF) : (item.Crc >> 16));
+
+ Byte v1 = _zipCryptoDecoderSpec->_header[NCrypto::NZip::kHeaderSize - 1];
+ Byte v2 = (Byte)(item.HasDescriptor() ? (item.Time >> 8) : (item.Crc >> 24));
+
+ if (v1 != v2)
+ {
+ res = NExtract::NOperationResult::kWrongPassword;
+ return S_OK;
+ }
+ }
}
if (result == S_OK)
{
- if (pkAesMode)
- {
- /* 9.31: The BUG in 9.24-9.30 was fixed. pkAes archives didn't work.
- We don't need to call CAesCbcCoder::Init() to reset IV for data. */
- filterStreamSpec->SetInStream_NoSubFilterInit(inStream);
- }
- else
- {
- RINOK(filterStreamSpec->SetInStream(inStream));
- }
inStreamReleaser.FilterCoder = filterStreamSpec;
+ RINOK(filterStreamSpec->SetInStream(inStream));
+
+ /* IFilter::Init() does nothing in all zip crypto filters.
+ So we can call any Initialize function in CFilterCoder. */
+
+ RINOK(filterStreamSpec->Init_NoSubFilterInit());
+ // RINOK(filterStreamSpec->SetOutStreamSize(NULL));
+
inStreamNew = filterStream;
- if (wzAesMode)
- {
- if (!_wzAesDecoderSpec->CheckPasswordVerifyCode())
- result = S_FALSE;
- }
}
}
else
inStreamNew = inStream;
+
if (result == S_OK)
result = coder->Code(inStreamNew, outStream, NULL, &item.Size, compressProgress);
+
if (result == S_FALSE)
return S_OK;
+
if (result == E_NOTIMPL)
{
res = NExtract::NOperationResult::kUnsupportedMethod;
@@ -830,6 +901,7 @@ HRESULT CZipDecoder::Decode(
RINOK(result);
}
+
bool crcOK = true;
bool authOk = true;
if (needCRC)
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h
index 7f1d2eba..c2a362a7 100644
--- a/CPP/7zip/Archive/Zip/ZipHandler.h
+++ b/CPP/7zip/Archive/Zip/ZipHandler.h
@@ -33,7 +33,7 @@ public:
INTERFACE_IInArchive(;)
INTERFACE_IOutArchive(;)
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
DECL_ISetCompressCodecsInfo
diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
index ae58cbe2..f1c8b227 100644
--- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
@@ -34,15 +34,16 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
return S_OK;
}
-static bool IsAsciiString(const UString &s)
+static bool IsSimpleAsciiString(const wchar_t *s)
{
- for (unsigned i = 0; i < s.Len(); i++)
+ for (;;)
{
- wchar_t c = s[i];
+ wchar_t c = *s++;
+ if (c == 0)
+ return true;
if (c < 0x20 || c > 0x7F)
return false;
}
- return true;
}
#define COM_TRY_BEGIN2 try {
@@ -180,11 +181,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (tryUtf8)
{
- unsigned i;
- for (i = 0; i < name.Len() && (unsigned)name[i] < 0x80; i++);
- ui.IsUtf8 = (i != name.Len());
- if (!ConvertUnicodeToUTF8(name, ui.Name))
- return E_INVALIDARG;
+ ui.IsUtf8 = !name.IsAscii();
+ ConvertUnicodeToUTF8(name, ui.Name);
}
if (ui.Name.Len() >= (1 << 16))
@@ -249,10 +247,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (!m_ForceAesMode)
options.IsAesMode = thereAreAesUpdates;
- if (!IsAsciiString((BSTR)password))
+ if (!IsSimpleAsciiString(password))
return E_INVALIDARG;
if (password)
- options.Password = UnicodeStringToMultiByte((BSTR)password, CP_OEMCP);
+ options.Password = UnicodeStringToMultiByte((LPCOLESTR)password, CP_OEMCP);
if (options.IsAesMode)
{
if (options.Password.Len() > NCrypto::NWzAes::kPasswordSizeMax)
@@ -297,7 +295,7 @@ static const CMethodIndexToName k_SupportedMethods[] =
{ NFileHeader::NCompressionMethod::kPPMd, "ppmd" }
};
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
InitMethodProps();
#ifndef _7ZIP_ST
@@ -318,7 +316,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
UInt32 level = 9;
RINOK(ParsePropToUInt32(name.Ptr(1), prop, level));
_props.Level = level;
- _props.MethodInfo.AddLevelProp(level);
+ _props.MethodInfo.AddProp_Level(level);
}
else if (name == L"m")
{
diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h
index 1391cdf4..c109992c 100644
--- a/CPP/7zip/Archive/Zip/ZipHeader.h
+++ b/CPP/7zip/Archive/Zip/ZipHeader.h
@@ -54,6 +54,8 @@ namespace NFileHeader
kLZMA = 14,
kTerse = 18,
kLz77 = 19,
+
+ kXz = 0x5F,
kJpeg = 0x60,
kWavPack = 0x61,
kPPMd = 0x62,
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp
index 345fbf56..6f495305 100644
--- a/CPP/7zip/Archive/Zip/ZipIn.cpp
+++ b/CPP/7zip/Archive/Zip/ZipIn.cpp
@@ -348,7 +348,7 @@ HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchLim
return S_FALSE;
}
-HRESULT CInArchive::IncreaseRealPosition(UInt64 addValue)
+HRESULT CInArchive::IncreaseRealPosition(Int64 addValue)
{
return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position);
}
@@ -439,10 +439,9 @@ void CInArchive::ReadFileName(unsigned size, AString &s)
s.Empty();
return;
}
- char *p = s.GetBuffer(size);
+ char *p = s.GetBuf(size);
SafeReadBytes(p, size);
- p[size] = 0;
- s.ReleaseBuffer();
+ s.ReleaseBuf_CalcLen(size);
}
bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extraBlock,
@@ -556,7 +555,12 @@ bool CInArchive::ReadLocalItem(CItemEx &item)
UInt32 diskStartNumber = 0;
if (!ReadExtra(extraSize, item.LocalExtra, item.Size, item.PackSize,
localHeaderOffset, diskStartNumber))
- return false;
+ {
+ /* Most of archives are OK for Extra. But there are some rare cases
+ that have error. And if error in first item, it can't open archive.
+ So we ignore that error */
+ // return false;
+ }
}
if (!CheckDosTime(item.Time))
{
@@ -650,6 +654,7 @@ HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item)
numBytesInBuffer += processedSize;
if (numBytesInBuffer < kDataDescriptorSize)
return S_FALSE;
+
UInt32 i;
for (i = 0; i <= numBytesInBuffer - kDataDescriptorSize; i++)
{
@@ -666,10 +671,11 @@ HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item)
item.Crc = Get32(buf + i + 4);
item.PackSize = descriptorPackSize;
item.Size = Get32(buf + i + 12);
- return IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i - kDataDescriptorSize))));
+ return IncreaseRealPosition((Int64)(Int32)(0 - (numBytesInBuffer - i - kDataDescriptorSize)));
}
}
}
+
packedSize += i;
unsigned j;
for (j = 0; i < numBytesInBuffer; i++, j++)
@@ -1262,7 +1268,10 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p
(UInt32)ecd64.cdSize != (UInt32)cdSize ||
((UInt32)(ecd64.cdStartOffset) != (UInt32)cdRelatOffset &&
(!items.IsEmpty())))
- return S_FALSE;
+ {
+ // return S_FALSE;
+ HeadersError = true;
+ }
// printf("\nOpen OK");
return S_OK;
diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h
index f6b349b1..734d3bcb 100644
--- a/CPP/7zip/Archive/Zip/ZipIn.h
+++ b/CPP/7zip/Archive/Zip/ZipIn.h
@@ -25,7 +25,7 @@ public:
UInt64 GetLocalFullSize() const
{ return LocalFullHeaderSize + PackSize + (HasDescriptor() ? kDataDescriptorSize : 0); }
UInt64 GetDataPosition() const
- { return LocalHeaderPos + LocalFullHeaderSize; };
+ { return LocalHeaderPos + LocalFullHeaderSize; }
};
struct CInArchiveInfo
@@ -107,7 +107,7 @@ class CInArchive
HRESULT Seek(UInt64 offset);
HRESULT FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
- HRESULT IncreaseRealPosition(UInt64 addValue);
+ HRESULT IncreaseRealPosition(Int64 addValue);
HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize);
void SafeReadBytes(void *data, unsigned size);
diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp
index ae88944d..f2ccc814 100644
--- a/CPP/7zip/Archive/Zip/ZipItem.cpp
+++ b/CPP/7zip/Archive/Zip/ZipItem.cpp
@@ -114,7 +114,7 @@ bool CItem::IsDir() const
case NHostOS::kMVS:
return false; // change it throw kUnknownAttributes;
case NHostOS::kUnix:
- return (highAttrib & NUnixAttrib::kIFDIR) != 0;
+ return ((highAttrib & NUnixAttrib::kIFMT) == NUnixAttrib::kIFDIR);
default:
return false;
}
@@ -130,6 +130,11 @@ UInt32 CItem::GetWinAttrib() const
if (FromCentral)
winAttrib = ExternalAttrib;
break;
+ case NHostOS::kUnix:
+ // do we need to clear 16 low bits in this case?
+ if (FromCentral)
+ winAttrib = ExternalAttrib & 0xFFFF0000;
+ break;
}
if (IsDir()) // test it;
winAttrib |= FILE_ATTRIBUTE_DIRECTORY;
diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h
index d50c3ae9..98afdf1d 100644
--- a/CPP/7zip/Archive/Zip/ZipItem.h
+++ b/CPP/7zip/Archive/Zip/ZipItem.h
@@ -179,9 +179,12 @@ struct CExtraBlock
void RemoveUnknownSubBlocks()
{
- for (int i = SubBlocks.Size() - 1; i >= 0; i--)
+ for (unsigned i = SubBlocks.Size(); i != 0;)
+ {
+ i--;
if (SubBlocks[i].ID != NFileHeader::NExtraID::kWzAES)
SubBlocks.Delete(i);
+ }
}
};
@@ -204,8 +207,8 @@ public:
bool IsUtf8() const { return (Flags & NFileHeader::NFlags::kUtf8) != 0; }
bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kEncrypted) != 0; }
- bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; };
- bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); };
+ bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; }
+ bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); }
bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; }
bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
@@ -237,6 +240,7 @@ public:
void ClearFlags() { Flags = 0; }
void SetEncrypted(bool encrypted) { SetFlag(NFileHeader::NFlags::kEncrypted, encrypted); }
void SetUtf8(bool isUtf8) { SetFlag(NFileHeader::NFlags::kUtf8, isUtf8); }
+ void SetDescriptorMode(bool useDescriptor) { SetFlag(NFileHeader::NFlags::kDescriptorUsedMask, useDescriptor); }
UINT GetCodePage() const { return CP_OEMCP; }
};
@@ -277,6 +281,7 @@ public:
void GetUnicodeString(const AString &s, UString &res, bool useSpecifiedCodePage, UINT codePage) const
{
bool isUtf8 = IsUtf8();
+ bool ignore_Utf8_Errors = true;
#ifdef _WIN32
if (!isUtf8)
@@ -287,14 +292,15 @@ public:
{
/* Some ZIP archives in Unix use UTF-8 encoding without Utf8 flag in header.
We try to get name as UTF-8.
- Do we need to do it in POSIX version also? */
+ Do we need to do it in POSIX version also? */
isUtf8 = true;
+ ignore_Utf8_Errors = false;
}
}
#endif
if (isUtf8)
- if (ConvertUTF8ToUnicode(s, res))
+ if (ConvertUTF8ToUnicode(s, res) || ignore_Utf8_Errors)
return;
MultiByteToUnicodeString2(res, s, useSpecifiedCodePage ? codePage : GetCodePage());
}
diff --git a/CPP/7zip/Archive/Zip/ZipOut.h b/CPP/7zip/Archive/Zip/ZipOut.h
index eaaa0320..056d0d09 100644
--- a/CPP/7zip/Archive/Zip/ZipOut.h
+++ b/CPP/7zip/Archive/Zip/ZipOut.h
@@ -63,7 +63,7 @@ public:
HRESULT Create(IOutStream *outStream);
void MoveCurPos(UInt64 distanceToMove);
- UInt64 GetCurPos() const { return m_CurPos; };
+ UInt64 GetCurPos() const { return m_CurPos; }
void SeekToCurPos();
diff --git a/CPP/7zip/Archive/Zip/ZipRegister.cpp b/CPP/7zip/Archive/Zip/ZipRegister.cpp
index 545e76c6..2be783e6 100644
--- a/CPP/7zip/Archive/Zip/ZipRegister.cpp
+++ b/CPP/7zip/Archive/Zip/ZipRegister.cpp
@@ -9,23 +9,18 @@
namespace NArchive {
namespace NZip {
-IMP_CreateArcIn
-IMP_CreateArcOut
-
-static CArcInfo g_ArcInfo =
- { "zip", "zip zipx jar xpi odt ods docx xlsx epub", 0, 1,
- 3 + 4 + 4 + 6,
- {
+static const Byte k_Signature[] = {
4, 0x50, 0x4B, 0x03, 0x04,
4, 0x50, 0x4B, 0x05, 0x06,
- 6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B,
- },
+ 6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B };
+
+REGISTER_ARC_IO(
+ "zip", "zip zipx jar xpi odt ods docx xlsx epub", 0, 1,
+ k_Signature,
0,
NArcInfoFlags::kFindSignature |
NArcInfoFlags::kMultiSignature |
NArcInfoFlags::kUseGlobalOffset,
- REF_CreateArc_Pair, IsArc_Zip };
-
-REGISTER_ARC(Zip)
-
+ IsArc_Zip)
+
}}
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
index 97cce5ac..9a9526cc 100644
--- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
@@ -65,6 +65,7 @@ static void SetFileHeader(
COutArchive &archive,
const CCompressionMethodMode &options,
const CUpdateItem &ui,
+ // bool isSeqMode,
CItemOut &item)
{
item.Size = ui.Size;
@@ -95,6 +96,8 @@ static void SetFileHeader(
item.InternalAttrib = 0; // test it
item.SetEncrypted(!isDir && options.PasswordIsDefined);
+ // item.SetDescriptorMode(isSeqMode);
+
if (isDir)
{
item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir;
@@ -156,12 +159,14 @@ struct CThreadInfo
bool IsFree;
UInt32 UpdateIndex;
+ UInt32 FileTime;
CThreadInfo(const CCompressionMethodMode &options):
ExitThread(false),
ProgressSpec(0),
OutStreamSpec(0),
- Coder(options)
+ Coder(options),
+ FileTime(0)
{}
HRESULT CreateEvents()
@@ -192,9 +197,11 @@ void CThreadInfo::WaitAndCode()
CompressEvent.Lock();
if (ExitThread)
return;
+
Result = Coder.Compress(
EXTERNAL_CODECS_LOC_VARS
- InStream, OutStream, Progress, CompressingResult);
+ InStream, OutStream, FileTime, Progress, CompressingResult);
+
if (Result == S_OK && Progress)
Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize);
CompressionCompletedEvent.Set();
@@ -254,7 +261,7 @@ public:
MY_UNKNOWN_IMP
void Create(IProgress *progress, bool inSizeIsMain);
void SetProgressOffset(UInt64 progressOffset);
- HRESULT SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize);
+ HRESULT SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize);
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};
@@ -274,16 +281,16 @@ void CMtProgressMixer2::SetProgressOffset(UInt64 progressOffset)
CriticalSection.Leave();
}
-HRESULT CMtProgressMixer2::SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize)
+HRESULT CMtProgressMixer2::SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize)
{
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
if (index == 0 && RatioProgress)
{
RINOK(RatioProgress->SetRatioInfo(inSize, outSize));
}
- if (inSize != 0)
+ if (inSize)
InSizes[index] = *inSize;
- if (outSize != 0)
+ if (outSize)
OutSizes[index] = *outSize;
UInt64 v = ProgressOffset + (_inSizeIsMain ?
(InSizes[0] + InSizes[1]) :
@@ -332,8 +339,16 @@ static HRESULT UpdateItemOldData(
CItemOut &item,
/* bool izZip64, */
ICompressProgressInfo *progress,
+ IArchiveUpdateCallbackFile *opCallback,
UInt64 &complexity)
{
+ if (opCallback)
+ {
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArc,
+ NUpdateNotifyOp::kReplicate))
+ }
+
if (ui.NewProps)
{
if (item.HasDescriptor())
@@ -396,7 +411,8 @@ static HRESULT Update2St(
const CObjectVector<CUpdateItem> &updateItems,
const CCompressionMethodMode *options,
const CByteBuffer *comment,
- IArchiveUpdateCallback *updateCallback)
+ IArchiveUpdateCallback *updateCallback,
+ IArchiveUpdateCallbackFile *opCallback)
{
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
@@ -445,15 +461,37 @@ static HRESULT Update2St(
if (!fileInStream)
return E_INVALIDARG;
+ // bool isSeqMode = false;
+ /*
+ {
+ CMyComPtr<IInStream> inStream2;
+ fileInStream->QueryInterface(IID_IInStream, (void **)&inStream2);
+ isSeqMode = (inStream2 == NULL);
+ }
+ */
+
// file Size can be 64-bit !!!
SetFileHeader(archive, *options, ui, item);
archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, options->IsRealAesMode());
CCompressingResult compressingResult;
CMyComPtr<IOutStream> outStream;
archive.CreateStreamForCompressing(&outStream);
+
RINOK(compressor.Compress(
EXTERNAL_CODECS_LOC_VARS
- fileInStream, outStream, progress, compressingResult));
+ fileInStream, outStream,
+ ui.Time,
+ progress, compressingResult));
+
+ if (compressingResult.FileTimeWasUsed)
+ {
+ /*
+ if (!item.HasDescriptor())
+ return E_FAIL;
+ */
+ item.SetDescriptorMode(true);
+ }
+
SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item);
archive.WriteLocalHeader_And_SeekToNextFile(item);
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
@@ -465,13 +503,14 @@ static HRESULT Update2St(
{
UInt64 complexity = 0;
lps->SendRatio = false;
- RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, complexity));
+ RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, opCallback, complexity));
lps->SendRatio = true;
lps->ProgressOffset += complexity;
}
items.Add(item);
lps->ProgressOffset += kLocalHeaderSize;
}
+
lps->InSize = unpackSizeTotal;
lps->OutSize = packSizeTotal;
RINOK(lps->SetCur());
@@ -489,6 +528,9 @@ static HRESULT Update2(
const CByteBuffer *comment,
IArchiveUpdateCallback *updateCallback)
{
+ CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
+ updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
+
UInt64 complexity = 0;
UInt64 numFilesToCompress = 0;
UInt64 numBytesToCompress = 0;
@@ -542,6 +584,7 @@ static HRESULT Update2(
numThreads = MAXIMUM_WAIT_OBJECTS;
if (numThreads < 1)
numThreads = 1;
+
const size_t kMemPerThread = (1 << 25);
const size_t kBlockSize = 1 << 16;
@@ -558,7 +601,7 @@ static HRESULT Update2(
{
// fixed for 9.31. bzip2 default is just one thread.
if (options2.NumThreadsWasChanged || method == NFileHeader::NCompressionMethod::kBZip2)
- options2.MethodInfo.AddNumThreadsProp(numThreads);
+ options2.MethodInfo.AddProp_NumThreads(numThreads);
}
}
else
@@ -577,7 +620,7 @@ static HRESULT Update2(
numBZip2Threads = 32;
if (averageNumberOfBlocks < numBZip2Threads)
numBZip2Threads = (UInt32)averageNumberOfBlocks;
- options2.MethodInfo.AddNumThreadsProp(numBZip2Threads);
+ options2.MethodInfo.AddProp_NumThreads(numBZip2Threads);
}
numThreads /= numBZip2Threads;
}
@@ -599,7 +642,7 @@ static HRESULT Update2(
return Update2St(
EXTERNAL_CODECS_LOC_VARS
archive, inArchive,
- inputItems, updateItems, &options2, comment, updateCallback);
+ inputItems, updateItems, &options2, comment, updateCallback, opCallback);
#ifndef _7ZIP_ST
@@ -643,6 +686,7 @@ static HRESULT Update2(
threadInfo.ProgressSpec = new CMtCompressProgress();
threadInfo.Progress = threadInfo.ProgressSpec;
threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, (int)i);
+ threadInfo.FileTime = 0; // fix it !
RINOK(threadInfo.CreateThread());
}
}
@@ -784,7 +828,15 @@ static HRESULT Update2(
DWORD result = ::WaitForMultipleObjects(compressingCompletedEvents.Size(),
&compressingCompletedEvents.Front(), FALSE, INFINITE);
- int t = (int)(result - WAIT_OBJECT_0);
+ if (result == WAIT_FAILED)
+ {
+ DWORD lastError = GetLastError();
+ return lastError != 0 ? lastError : E_FAIL;
+ }
+ unsigned t = (unsigned)(result - WAIT_OBJECT_0);
+ if (t >= compressingCompletedEvents.Size())
+ return E_FAIL;
+
CThreadInfo &threadInfo = threads.Threads[threadIndices[t]];
threadInfo.InStream.Release();
threadInfo.IsFree = true;
@@ -813,7 +865,7 @@ static HRESULT Update2(
}
else
{
- RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, complexity));
+ RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, opCallback, complexity));
}
items.Add(item);
complexity += kLocalHeaderSize;