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>2011-04-11 04:00:00 +0400
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:16:05 +0300
commit35596517f203f1c4970413b3b5b2e216b849e462 (patch)
tree93240df3eb4ddbd8eebbe6a5fc65e93f2ccb6495 /CPP/7zip/Archive
parentde4f8c22fe4b9e59b60495b84db2e81de50999a9 (diff)
9.219.21
Diffstat (limited to 'CPP/7zip/Archive')
-rwxr-xr-xCPP/7zip/Archive/7z/7zCompressionMode.h9
-rwxr-xr-xCPP/7zip/Archive/7z/7zEncode.cpp12
-rwxr-xr-xCPP/7zip/Archive/7z/7zHandler.cpp52
-rwxr-xr-xCPP/7zip/Archive/7z/7zHandler.h63
-rwxr-xr-xCPP/7zip/Archive/7z/7zHandlerOut.cpp393
-rwxr-xr-xCPP/7zip/Archive/7z/7zIn.cpp33
-rwxr-xr-xCPP/7zip/Archive/7z/7zIn.h1
-rwxr-xr-xCPP/7zip/Archive/7z/7zUpdate.cpp192
-rwxr-xr-xCPP/7zip/Archive/Bz2Handler.cpp143
-rwxr-xr-xCPP/7zip/Archive/Cab/CabHandler.cpp33
-rwxr-xr-xCPP/7zip/Archive/Chm/ChmIn.h2
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixer2MT.cpp2
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixer2MT.h1
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixer2ST.cpp14
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixer2ST.h8
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixerMT.cpp2
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixerMT.h1
-rwxr-xr-xCPP/7zip/Archive/Common/HandlerOut.cpp606
-rwxr-xr-xCPP/7zip/Archive/Common/HandlerOut.h80
-rwxr-xr-xCPP/7zip/Archive/Common/ItemNameUtils.cpp4
-rwxr-xr-xCPP/7zip/Archive/Common/ParseProperties.cpp174
-rwxr-xr-xCPP/7zip/Archive/Common/ParseProperties.h16
-rwxr-xr-xCPP/7zip/Archive/DeflateProps.cpp115
-rwxr-xr-xCPP/7zip/Archive/DeflateProps.h29
-rwxr-xr-xCPP/7zip/Archive/GzHandler.cpp21
-rwxr-xr-xCPP/7zip/Archive/Icons/bz2.icobin3638 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Icons/cab.icobin3638 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Icons/fat.icobin3638 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Icons/gz.icobin3638 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Icons/hfs.icobin3638 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Icons/iso.icobin3638 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Icons/split.icobin3638 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Icons/squashfs.icobin3638 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Icons/xz.icobin3638 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Iso/IsoHandler.cpp13
-rwxr-xr-xCPP/7zip/Archive/LzhHandler.cpp144
-rwxr-xr-xCPP/7zip/Archive/LzmaHandler.cpp3
-rwxr-xr-xCPP/7zip/Archive/MubHandler.cpp24
-rwxr-xr-xCPP/7zip/Archive/Nsis/NsisIn.h2
-rwxr-xr-xCPP/7zip/Archive/PeHandler.cpp337
-rwxr-xr-xCPP/7zip/Archive/Rar/RarIn.cpp2
-rwxr-xr-xCPP/7zip/Archive/SquashfsHandler.cpp104
-rwxr-xr-xCPP/7zip/Archive/SwfHandler.cpp13
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHandler.cpp47
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHandler.h1
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHandlerOut.cpp8
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHeader.h1
-rwxr-xr-xCPP/7zip/Archive/Tar/TarIn.cpp102
-rwxr-xr-xCPP/7zip/Archive/Tar/TarItem.h17
-rwxr-xr-xCPP/7zip/Archive/Tar/TarOut.cpp26
-rwxr-xr-xCPP/7zip/Archive/Tar/TarUpdate.cpp24
-rwxr-xr-xCPP/7zip/Archive/Tar/TarUpdate.h10
-rwxr-xr-xCPP/7zip/Archive/Udf/UdfIn.cpp35
-rwxr-xr-xCPP/7zip/Archive/UefiHandler.cpp1935
-rwxr-xr-xCPP/7zip/Archive/Wim/WimHandlerOut.cpp3
-rwxr-xr-xCPP/7zip/Archive/XzHandler.cpp115
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipAddCommon.cpp101
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipCompressionMode.h56
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandler.cpp44
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandler.h41
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandlerOut.cpp298
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipIn.cpp4
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipItem.cpp62
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipItem.h13
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipUpdate.cpp69
65 files changed, 3599 insertions, 2061 deletions
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h
index 55bbc68e..5cde97c3 100755
--- a/CPP/7zip/Archive/7z/7zCompressionMode.h
+++ b/CPP/7zip/Archive/7z/7zCompressionMode.h
@@ -3,19 +3,18 @@
#ifndef __7Z_COMPRESSION_MODE_H
#define __7Z_COMPRESSION_MODE_H
-#include "../../../Common/MyString.h"
-
-#include "../../../Windows/PropVariant.h"
-
+#include "../../Common/MethodId.h"
#include "../../Common/MethodProps.h"
namespace NArchive {
namespace N7z {
-struct CMethodFull: public CMethod
+struct CMethodFull: public CProps
{
+ CMethodId Id;
UInt32 NumInStreams;
UInt32 NumOutStreams;
+
bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
};
diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp
index 87996bc0..614f9913 100755
--- a/CPP/7zip/Archive/7z/7zEncode.cpp
+++ b/CPP/7zip/Archive/7z/7zEncode.cpp
@@ -49,6 +49,15 @@ static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindIn
folder.PackStreams.Add(bindInfo.InStreams[i]);
}
+static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)
+{
+ CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
+ coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);
+ if (setCoderProperties)
+ return props.SetCoderProps(setCoderProperties, dataSizeReduce);
+ return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;
+}
+
HRESULT CEncoder::CreateMixerCoder(
DECL_EXTERNAL_CODECS_LOC_VARS
const UInt64 *inSizeForReduce)
@@ -86,8 +95,7 @@ HRESULT CEncoder::CreateMixerCoder(
}
#endif
-
- RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon));
+ RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon));
/*
CMyComPtr<ICryptoResetSalt> resetSalt;
diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp
index 4ab7afa8..93d4f51e 100755
--- a/CPP/7zip/Archive/7z/7zHandler.cpp
+++ b/CPP/7zip/Archive/7z/7zHandler.cpp
@@ -24,25 +24,20 @@
using namespace NWindows;
-extern UString ConvertMethodIdToString(UInt64 id);
-
namespace NArchive {
namespace N7z {
CHandler::CHandler()
{
- _crcSize = 4;
-
#ifndef _NO_CRYPTO
_passwordIsDefined = false;
#endif
#ifdef EXTRACT_ONLY
+ _crcSize = 4;
#ifdef __7Z_SET_PROPERTIES
_numThreads = NSystem::GetNumberOfProcessors();
#endif
- #else
- Init();
#endif
}
@@ -70,7 +65,7 @@ STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
#else
-STATPROPSTG kArcProps[] =
+static const STATPROPSTG kArcProps[] =
{
{ NULL, kpidMethod, VT_BSTR},
{ NULL, kpidSolid, VT_BOOL},
@@ -80,6 +75,25 @@ STATPROPSTG kArcProps[] =
{ NULL, kpidOffset, VT_UI8}
};
+static inline wchar_t GetHex(Byte value)
+{
+ return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+}
+
+static UString ConvertMethodIdToString(UInt64 id)
+{
+ wchar_t s[32];
+ int len = 32;
+ s[--len] = 0;
+ do
+ {
+ s[--len] = GetHex((Byte)id & 0xF); id >>= 4;
+ s[--len] = GetHex((Byte)id & 0xF); id >>= 4;
+ }
+ while (id != 0);
+ return s + len;
+}
+
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
@@ -172,22 +186,18 @@ static UString GetStringForSizeValue(UInt32 value)
return result;
}
-static const UInt64 k_Copy = 0x0;
-static const UInt64 k_Delta = 3;
-static const UInt64 k_LZMA2 = 0x21;
-static const UInt64 k_LZMA = 0x030101;
-static const UInt64 k_PPMD = 0x030401;
-
-static wchar_t GetHex(Byte value)
-{
- return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));
-}
static inline void AddHexToString(UString &res, Byte value)
{
res += GetHex((Byte)(value >> 4));
res += GetHex((Byte)(value & 0xF));
}
+static void AddProp32(UString &s, const wchar_t *name, UInt32 v)
+{
+ s += name;
+ s += ConvertUInt32ToString(v);
+}
+
#endif
bool CHandler::IsEncrypted(UInt32 index2) const
@@ -283,6 +293,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
{
UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);
propsString = GetStringForSizeValue(dicSize);
+ UInt32 d = coder.Props[0];
+ UInt32 lc = d % 9;
+ d /= 9;
+ UInt32 pb = d / 5;
+ UInt32 lp = d % 5;
+ if (lc != 3) AddProp32(propsString, L":lc", lc);
+ if (lp != 0) AddProp32(propsString, L":lp", lp);
+ if (pb != 2) AddProp32(propsString, L":pb", pb);
}
else if (coder.MethodID == k_LZMA2 && coder.Props.GetCapacity() == 1)
{
diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h
index 56062d46..247b55f7 100755
--- a/CPP/7zip/Archive/7z/7zHandler.h
+++ b/CPP/7zip/Archive/7z/7zHandler.h
@@ -18,6 +18,16 @@
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
@@ -31,9 +41,52 @@ namespace N7z {
#endif
+#ifndef EXTRACT_ONLY
+
+class COutHandler: public CMultiMethodProps
+{
+ HRESULT SetSolidFromString(const UString &s);
+ HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value);
+public:
+ bool _removeSfxBlock;
+
+ UInt64 _numSolidFiles;
+ UInt64 _numSolidBytes;
+ bool _numSolidBytesDefined;
+ bool _solidExtension;
+
+ bool _compressHeaders;
+ bool _encryptHeadersSpecified;
+ bool _encryptHeaders;
+
+ bool WriteCTime;
+ bool WriteATime;
+ bool WriteMTime;
+
+ bool _volumeMode;
+
+ void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
+ void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
+ void InitSolid()
+ {
+ InitSolidFiles();
+ InitSolidSize();
+ _solidExtension = false;
+ _numSolidBytesDefined = false;
+ }
+
+ void InitProps();
+
+ COutHandler() { InitProps(); }
+
+ HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
+};
+
+#endif
+
class CHandler:
#ifndef EXTRACT_ONLY
- public NArchive::COutHandler,
+ public COutHandler,
#endif
public IInArchive,
#ifdef __7Z_SET_PROPERTIES
@@ -90,16 +143,16 @@ private:
CRecordVector<CBind> _binds;
- HRESULT SetCompressionMethod(CCompressionMethodMode &method,
+ HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m);
+ HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod);
+ void AddDefaultMethod();
+ HRESULT SetMainMethod(CCompressionMethodMode &method,
CObjectVector<COneMethodInfo> &methodsInfo
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
);
- HRESULT SetCompressionMethod(
- CCompressionMethodMode &method,
- CCompressionMethodMode &headerMethod);
#endif
diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
index a8ccab6d..dd73ee84 100755
--- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp
+++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -2,13 +2,9 @@
#include "StdAfx.h"
-#include "../../../Windows/PropVariant.h"
-
#include "../../../Common/ComTry.h"
#include "../../../Common/StringToInt.h"
-#include "../../ICoder.h"
-
#include "../Common/ItemNameUtils.h"
#include "../Common/ParseProperties.h"
@@ -21,24 +17,19 @@ using namespace NWindows;
namespace NArchive {
namespace N7z {
-static const wchar_t *kLZMAMethodName = L"LZMA";
-static const wchar_t *kCopyMethod = L"Copy";
-static const wchar_t *kDefaultMethodName = kLZMAMethodName;
+static const wchar_t *k_LZMA_Name = L"LZMA";
+static const wchar_t *kDefaultMethodName = k_LZMA_Name;
+static const wchar_t *k_Copy_Name = L"Copy";
-static const UInt32 kLzmaAlgorithmX5 = 1;
-static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";
-static const UInt32 kDictionaryForHeaders =
+static const wchar_t *k_MatchFinder_ForHeaders = L"BT2";
+static const UInt32 k_NumFastBytes_ForHeaders = 273;
+static const UInt32 k_Level_ForHeaders = 5;
+static const UInt32 k_Dictionary_ForHeaders =
#ifdef UNDER_CE
- 1 << 18
+ 1 << 18;
#else
- 1 << 20
+ 1 << 20;
#endif
-;
-static const UInt32 kNumFastBytesForHeaders = 273;
-static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5;
-
-static inline bool IsCopyMethod(const UString &methodName)
- { return (methodName.CompareNoCase(kCopyMethod) == 0); }
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
{
@@ -46,123 +37,105 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
return S_OK;
}
-HRESULT CHandler::SetCompressionMethod(
- CCompressionMethodMode &methodMode,
- CCompressionMethodMode &headerMethod)
+HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m)
{
- HRESULT res = SetCompressionMethod(methodMode, _methods
- #ifndef _7ZIP_ST
- , _numThreads
- #endif
- );
- RINOK(res);
- methodMode.Binds = _binds;
+ if (!FindMethod(
+ EXTERNAL_CODECS_VARS
+ m.MethodName, dest.Id, dest.NumInStreams, dest.NumOutStreams))
+ return E_INVALIDARG;
+ (CProps &)dest = (CProps &)m;
+ return S_OK;
+}
- if (_compressHeaders)
- {
- // headerMethod.Methods.Add(methodMode.Methods.Back());
+HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod)
+{
+ if (!_compressHeaders)
+ 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.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders);
+ m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders);
+ m.AddNumThreadsProp(1);
+
+ CMethodFull methodFull;
+ RINOK(PropsMethod_To_FullMethod(methodFull, m));
+ headerMethod.Methods.Add(methodFull);
+ return S_OK;
+}
- CObjectVector<COneMethodInfo> headerMethodInfoVector;
- COneMethodInfo oneMethodInfo;
- oneMethodInfo.MethodName = kLZMAMethodName;
- {
- CProp prop;
- prop.Id = NCoderPropID::kMatchFinder;
- prop.Value = kLzmaMatchFinderForHeaders;
- oneMethodInfo.Props.Add(prop);
- }
- {
- CProp prop;
- prop.Id = NCoderPropID::kAlgorithm;
- prop.Value = kAlgorithmForHeaders;
- oneMethodInfo.Props.Add(prop);
- }
- {
- CProp prop;
- prop.Id = NCoderPropID::kNumFastBytes;
- prop.Value = (UInt32)kNumFastBytesForHeaders;
- oneMethodInfo.Props.Add(prop);
- }
- {
- CProp prop;
- prop.Id = NCoderPropID::kDictionarySize;
- prop.Value = (UInt32)kDictionaryForHeaders;
- oneMethodInfo.Props.Add(prop);
- }
- headerMethodInfoVector.Add(oneMethodInfo);
- HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector
- #ifndef _7ZIP_ST
- , 1
- #endif
- );
- RINOK(res);
+void CHandler::AddDefaultMethod()
+{
+ for (int i = 0; i < _methods.Size(); i++)
+ {
+ UString &methodName = _methods[0].MethodName;
+ if (methodName.IsEmpty())
+ methodName = kDefaultMethodName;
+ }
+ if (_methods.IsEmpty())
+ {
+ COneMethodInfo m;
+ m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);
+ _methods.Add(m);
}
- return S_OK;
}
-HRESULT CHandler::SetCompressionMethod(
+HRESULT CHandler::SetMainMethod(
CCompressionMethodMode &methodMode,
- CObjectVector<COneMethodInfo> &methodsInfo
+ CObjectVector<COneMethodInfo> &methods
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
)
{
- UInt32 level = _level;
-
- if (methodsInfo.IsEmpty())
- {
- COneMethodInfo oneMethodInfo;
- oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName);
- methodsInfo.Add(oneMethodInfo);
- }
+ AddDefaultMethod();
+
+ const UInt64 kSolidBytes_Min = (1 << 24);
+ const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1;
bool needSolid = false;
- for(int i = 0; i < methodsInfo.Size(); i++)
+ for (int i = 0; i < methods.Size(); i++)
{
- COneMethodInfo &oneMethodInfo = methodsInfo[i];
- SetCompressionMethod2(oneMethodInfo
+ COneMethodInfo &oneMethodInfo = methods[i];
+ SetGlobalLevelAndThreads(oneMethodInfo
#ifndef _7ZIP_ST
, numThreads
#endif
);
- if (!IsCopyMethod(oneMethodInfo.MethodName))
- needSolid = true;
-
CMethodFull methodFull;
-
- if (!FindMethod(
- EXTERNAL_CODECS_VARS
- oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams))
- return E_INVALIDARG;
- methodFull.Props = oneMethodInfo.Props;
+ RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo));
methodMode.Methods.Add(methodFull);
- if (!_numSolidBytesDefined)
+ if (methodFull.Id != k_Copy)
+ needSolid = true;
+
+ if (_numSolidBytesDefined)
+ continue;
+
+ UInt32 dicSize;
+ switch (methodFull.Id)
{
- for (int j = 0; j < methodFull.Props.Size(); j++)
- {
- const CProp &prop = methodFull.Props[j];
- if ((prop.Id == NCoderPropID::kDictionarySize ||
- prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4)
- {
- _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7;
- const UInt64 kMinSize = (1 << 24);
- if (_numSolidBytes < kMinSize)
- _numSolidBytes = kMinSize;
- _numSolidBytesDefined = true;
- break;
- }
- }
+ case k_LZMA:
+ case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break;
+ case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break;
+ case k_Deflate: dicSize = (UInt32)1 << 15; break;
+ case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break;
+ default: continue;
}
- }
-
- if (!needSolid && !_numSolidBytesDefined)
- {
+ _numSolidBytes = (UInt64)dicSize << 7;
+ if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min;
+ if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max;
_numSolidBytesDefined = true;
- _numSolidBytes = 0;
}
+
+ if (!_numSolidBytesDefined)
+ if (needSolid)
+ _numSolidBytes = kSolidBytes_Max;
+ else
+ _numSolidBytes = 0;
+ _numSolidBytesDefined = true;
return S_OK;
}
@@ -326,7 +299,16 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
}
CCompressionMethodMode methodMode, headerMethod;
- RINOK(SetCompressionMethod(methodMode, headerMethod));
+
+ HRESULT res = SetMainMethod(methodMode, _methods
+ #ifndef _7ZIP_ST
+ , _numThreads
+ #endif
+ );
+ RINOK(res);
+ methodMode.Binds = _binds;
+
+ RINOK(SetHeaderMethod(headerMethod));
#ifndef _7ZIP_ST
methodMode.NumThreads = _numThreads;
headerMethod.NumThreads = 1;
@@ -373,8 +355,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
CUpdateOptions options;
options.Method = &methodMode;
options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0;
- options.UseFilters = _level != 0 && _autoFilter;
- options.MaxFilter = _level >= 8;
+ int level = GetLevel();
+ options.UseFilters = level != 0 && _autoFilter;
+ options.MaxFilter = level >= 8;
options.HeaderOptions.CompressMainHeader = compressMainHeader;
options.HeaderOptions.WriteCTime = WriteCTime;
@@ -393,7 +376,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
CMyComPtr<ICryptoGetTextPassword> getPassword;
updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword);
- HRESULT res = Update(
+ res = Update(
EXTERNAL_CODECS_VARS
#ifdef _7Z_VOL
volume ? volume->Stream: 0,
@@ -437,25 +420,138 @@ static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream
return S_OK;
}
-static HRESULT GetBindInfo(UString &srcString, CBind &bind)
+void COutHandler::InitProps()
{
- RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream));
- if (srcString[0] != ':')
- return E_INVALIDARG;
- srcString.Delete(0);
- RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream));
- if (!srcString.IsEmpty())
- return E_INVALIDARG;
+ CMultiMethodProps::Init();
+
+ _removeSfxBlock = false;
+ _compressHeaders = true;
+ _encryptHeadersSpecified = false;
+ _encryptHeaders = false;
+
+ WriteCTime = false;
+ WriteATime = false;
+ WriteMTime = true;
+
+ _volumeMode = false;
+ InitSolid();
+}
+
+HRESULT COutHandler::SetSolidFromString(const UString &s)
+{
+ UString s2 = s;
+ s2.MakeUpper();
+ for (int i = 0; i < s2.Length();)
+ {
+ const wchar_t *start = ((const wchar_t *)s2) + i;
+ const wchar_t *end;
+ UInt64 v = ConvertStringToUInt64(start, &end);
+ if (start == end)
+ {
+ if (s2[i++] != 'E')
+ return E_INVALIDARG;
+ _solidExtension = true;
+ continue;
+ }
+ i += (int)(end - start);
+ if (i == s2.Length())
+ return E_INVALIDARG;
+ wchar_t c = s2[i++];
+ if (c == 'F')
+ {
+ if (v < 1)
+ v = 1;
+ _numSolidFiles = v;
+ }
+ else
+ {
+ unsigned numBits;
+ switch (c)
+ {
+ case 'B': numBits = 0; break;
+ case 'K': numBits = 10; break;
+ case 'M': numBits = 20; break;
+ case 'G': numBits = 30; break;
+ default: return E_INVALIDARG;
+ }
+ _numSolidBytes = (v << numBits);
+ _numSolidBytesDefined = true;
+ }
+ }
+ return S_OK;
+}
+
+HRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value)
+{
+ bool isSolid;
+ switch (value.vt)
+ {
+ case VT_EMPTY: isSolid = true; break;
+ case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break;
+ case VT_BSTR:
+ if (StringToBool(value.bstrVal, isSolid))
+ break;
+ return SetSolidFromString(value.bstrVal);
+ default: return E_INVALIDARG;
+ }
+ if (isSolid)
+ InitSolid();
+ else
+ _numSolidFiles = 1;
return S_OK;
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
+HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
+{
+ UString name = nameSpec;
+ name.MakeUpper();
+ if (name.IsEmpty())
+ return E_INVALIDARG;
+
+ if (name[0] == L'S')
+ {
+ name.Delete(0);
+ if (name.IsEmpty())
+ return SetSolidFromPROPVARIANT(value);
+ if (value.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ return SetSolidFromString(name);
+ }
+
+ UInt32 number;
+ int index = ParseStringToUInt32(name, number);
+ UString realName = name.Mid(index);
+ if (index == 0)
+ {
+ if (name.CompareNoCase(L"RSFX") == 0) return PROPVARIANT_to_bool(value, _removeSfxBlock);
+ if (name.CompareNoCase(L"HC") == 0) return PROPVARIANT_to_bool(value, _compressHeaders);
+ if (name.CompareNoCase(L"HCF") == 0)
+ {
+ bool compressHeadersFull = true;
+ RINOK(PROPVARIANT_to_bool(value, compressHeadersFull));
+ return compressHeadersFull ? S_OK: E_INVALIDARG;
+ }
+ if (name.CompareNoCase(L"HE") == 0)
+ {
+ RINOK(PROPVARIANT_to_bool(value, _encryptHeaders));
+ _encryptHeadersSpecified = true;
+ return S_OK;
+ }
+ if (name.CompareNoCase(L"TC") == 0) return PROPVARIANT_to_bool(value, WriteCTime);
+ if (name.CompareNoCase(L"TA") == 0) return PROPVARIANT_to_bool(value, WriteATime);
+ if (name.CompareNoCase(L"TM") == 0) return PROPVARIANT_to_bool(value, WriteMTime);
+ if (name.CompareNoCase(L"V") == 0) return PROPVARIANT_to_bool(value, _volumeMode);
+ }
+ return CMultiMethodProps::SetProperty(name, value);
+}
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
COM_TRY_BEGIN
_binds.Clear();
- BeforeSetProperty();
+ InitProps();
- for (int i = 0; i < numProperties; i++)
+ for (int i = 0; i < numProps; i++)
{
UString name = names[i];
name.MakeUpper();
@@ -466,9 +562,17 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
if (name[0] == 'B')
{
+ if (value.vt != VT_EMPTY)
+ return E_INVALIDARG;
name.Delete(0);
CBind bind;
- RINOK(GetBindInfo(name, bind));
+ RINOK(GetBindInfoPart(name, bind.OutCoder, bind.OutStream));
+ if (name[0] != ':')
+ return E_INVALIDARG;
+ name.Delete(0);
+ RINOK(GetBindInfoPart(name, bind.InCoder, bind.InStream));
+ if (!name.IsEmpty())
+ return E_INVALIDARG;
_binds.Add(bind);
continue;
}
@@ -476,6 +580,47 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
RINOK(SetProperty(name, value));
}
+ int numEmptyMethods = GetNumEmptyMethods();
+ if (numEmptyMethods > 0)
+ {
+ int k;
+ for (k = 0; k < _binds.Size(); k++)
+ {
+ const CBind &bind = _binds[k];
+ if (bind.InCoder < (UInt32)numEmptyMethods ||
+ bind.OutCoder < (UInt32)numEmptyMethods)
+ return E_INVALIDARG;
+ }
+ for (k = 0; k < _binds.Size(); k++)
+ {
+ CBind &bind = _binds[k];
+ bind.InCoder -= (UInt32)numEmptyMethods;
+ bind.OutCoder -= (UInt32)numEmptyMethods;
+ }
+ _methods.Delete(0, numEmptyMethods);
+ }
+
+ AddDefaultMethod();
+
+ if (!_filterMethod.MethodName.IsEmpty())
+ {
+ for (int k = 0; k < _binds.Size(); k++)
+ {
+ CBind &bind = _binds[k];
+ bind.InCoder++;
+ bind.OutCoder++;
+ }
+ _methods.Insert(0, _filterMethod);
+ }
+
+ for (int k = 0; k < _binds.Size(); k++)
+ {
+ const CBind &bind = _binds[k];
+ if (bind.InCoder >= (UInt32)_methods.Size() ||
+ bind.OutCoder >= (UInt32)_methods.Size())
+ return E_INVALIDARG;
+ }
+
return S_OK;
COM_TRY_END
}
diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp
index 0feb81d2..fd751a74 100755
--- a/CPP/7zip/Archive/7z/7zIn.cpp
+++ b/CPP/7zip/Archive/7z/7zIn.cpp
@@ -317,7 +317,6 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
const UInt32 kBufferSize = (1 << 16);
byteBuffer.SetCapacity(kBufferSize);
Byte *buffer = byteBuffer;
- UInt32 numPrevBytes = kHeaderSize;
memcpy(buffer, _header, kHeaderSize);
UInt64 curTestPos = _arhiveBeginStreamPosition;
for (;;)
@@ -325,21 +324,14 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
if (searchHeaderSizeLimit != NULL)
if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit)
break;
- do
- {
- UInt32 numReadBytes = kBufferSize - numPrevBytes;
- UInt32 processedSize;
- RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize));
- numPrevBytes += processedSize;
- if (processedSize == 0)
- return S_FALSE;
- }
- while (numPrevBytes <= kHeaderSize);
- UInt32 numTests = numPrevBytes - kHeaderSize;
- for (UInt32 pos = 0; pos < numTests; pos++)
+ UInt32 processedSize;
+ RINOK(stream->Read(buffer + kHeaderSize, kBufferSize - kHeaderSize, &processedSize));
+ if (processedSize == 0)
+ return S_FALSE;
+ for (UInt32 pos = 1; pos <= processedSize; pos++)
{
- for (; buffer[pos] != '7' && pos < numTests; pos++);
- if (pos == numTests)
+ for (; buffer[pos] != '7' && pos <= processedSize; pos++);
+ if (pos > processedSize)
break;
if (TestSignature(buffer + pos))
{
@@ -349,9 +341,8 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL);
}
}
- curTestPos += numTests;
- numPrevBytes -= numTests;
- memmove(buffer, buffer + numTests, numPrevBytes);
+ curTestPos += processedSize;
+ memmove(buffer, buffer + processedSize, kHeaderSize);
}
return S_FALSE;
}
@@ -362,6 +353,8 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
HeadersSize = 0;
Close();
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition))
+ RINOK(stream->Seek(0, STREAM_SEEK_END, &_fileEndPosition))
+ RINOK(stream->Seek(_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL))
RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit));
_stream = stream;
return S_OK;
@@ -1194,12 +1187,14 @@ HRESULT CInArchive::ReadDatabase2(
if (nextHeaderSize == 0)
return S_OK;
- if (nextHeaderSize > (UInt64)0xFFFFFFFF)
+ if (nextHeaderSize > (UInt64)(UInt32)0xFFFFFFFF)
return S_FALSE;
if ((Int64)nextHeaderOffset < 0)
return S_FALSE;
+ if (db.ArchiveInfo.StartPositionAfterHeader + nextHeaderOffset > _fileEndPosition)
+ return S_FALSE;
RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL));
CByteBuffer buffer2;
diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h
index 971f27b2..4305a8c5 100755
--- a/CPP/7zip/Archive/7z/7zIn.h
+++ b/CPP/7zip/Archive/7z/7zIn.h
@@ -133,6 +133,7 @@ class CInArchive
CInByte2 *_inByteBack;
UInt64 _arhiveBeginStreamPosition;
+ UInt64 _fileEndPosition;
Byte _header[kHeaderSize];
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
index ee7f55c0..e63b09d2 100755
--- a/CPP/7zip/Archive/7z/7zUpdate.cpp
+++ b/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -24,15 +24,6 @@
namespace NArchive {
namespace N7z {
-static const UInt64 k_LZMA = 0x030101;
-static const UInt64 k_BCJ = 0x03030103;
-static const UInt64 k_BCJ2 = 0x0303011B;
-
-static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2";
-static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20;
-static const UInt32 kAlgorithmForBCJ2_LZMA = 1;
-static const UInt32 kNumFastBytesForBCJ2_LZMA = 64;
-
#ifdef MY_CPU_X86_OR_AMD64
#define USE_86_FILTER
#endif
@@ -339,90 +330,74 @@ static bool IsExeExt(const UString &ext)
return false;
}
-#ifdef USE_86_FILTER
-static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult)
+static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &m)
{
- methodResult.Id = methodID;
- methodResult.NumInStreams = numInStreams;
- methodResult.NumOutStreams = 1;
+ m.Id = methodID;
+ m.NumInStreams = numInStreams;
+ m.NumOutStreams = 1;
+}
+
+static void AddBcj2Methods(CCompressionMethodMode &mode)
+{
+ CMethodFull m;
+ GetMethodFull(k_LZMA, 1, m);
+
+ m.AddProp32(NCoderPropID::kDictionarySize, 1 << 20);
+ m.AddProp32(NCoderPropID::kNumFastBytes, 128);
+ m.AddProp32(NCoderPropID::kNumThreads, 1);
+ m.AddProp32(NCoderPropID::kLitPosBits, 2);
+ m.AddProp32(NCoderPropID::kLitContextBits, 0);
+ // m.AddPropString(NCoderPropID::kMatchFinder, L"BT2");
+
+ 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);
}
-static void MakeExeMethod(const CCompressionMethodMode &method,
- bool bcj2Filter, CCompressionMethodMode &exeMethod)
+static void MakeExeMethod(CCompressionMethodMode &mode,
+ bool useFilters, bool addFilter, bool bcj2Filter)
{
- exeMethod = method;
+ if (!mode.Binds.IsEmpty() || !useFilters || mode.Methods.Size() > 2)
+ return;
+ if (mode.Methods.Size() == 2)
+ {
+ if (mode.Methods[0].Id == k_BCJ2)
+ AddBcj2Methods(mode);
+ return;
+ }
+ if (!addFilter)
+ return;
+ bcj2Filter = bcj2Filter;
+ #ifdef USE_86_FILTER
if (bcj2Filter)
{
- CMethodFull methodFull;
- GetMethodFull(k_BCJ2, 4, methodFull);
- exeMethod.Methods.Insert(0, methodFull);
- GetMethodFull(k_LZMA, 1, methodFull);
- {
- CProp prop;
- prop.Id = NCoderPropID::kAlgorithm;
- prop.Value = kAlgorithmForBCJ2_LZMA;
- methodFull.Props.Add(prop);
- }
- {
- CProp prop;
- prop.Id = NCoderPropID::kMatchFinder;
- prop.Value = kMatchFinderForBCJ2_LZMA;
- methodFull.Props.Add(prop);
- }
- {
- CProp prop;
- prop.Id = NCoderPropID::kDictionarySize;
- prop.Value = kDictionaryForBCJ2_LZMA;
- methodFull.Props.Add(prop);
- }
- {
- CProp prop;
- prop.Id = NCoderPropID::kNumFastBytes;
- prop.Value = kNumFastBytesForBCJ2_LZMA;
- methodFull.Props.Add(prop);
- }
- {
- CProp prop;
- prop.Id = NCoderPropID::kNumThreads;
- prop.Value = (UInt32)1;
- methodFull.Props.Add(prop);
- }
-
- exeMethod.Methods.Add(methodFull);
- exeMethod.Methods.Add(methodFull);
- CBind bind;
-
- bind.OutCoder = 0;
- bind.InStream = 0;
-
- bind.InCoder = 1;
- bind.OutStream = 0;
- exeMethod.Binds.Add(bind);
-
- bind.InCoder = 2;
- bind.OutStream = 1;
- exeMethod.Binds.Add(bind);
-
- bind.InCoder = 3;
- bind.OutStream = 2;
- exeMethod.Binds.Add(bind);
+ CMethodFull m;
+ GetMethodFull(k_BCJ2, 4, m);
+ mode.Methods.Insert(0, m);
+ AddBcj2Methods(mode);
}
else
{
- CMethodFull methodFull;
- GetMethodFull(k_BCJ, 1, methodFull);
- exeMethod.Methods.Insert(0, methodFull);
+ 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;
- exeMethod.Binds.Add(bind);
+ mode.Binds.Add(bind);
}
+ #endif
}
-#endif
static void FromUpdateItemToFileItem(const CUpdateItem &ui,
CFileItem &file, CFileItem2 &file2)
@@ -601,6 +576,7 @@ public:
Fos = FosSpec;
Result = E_FAIL;
}
+ ~CThreadDecoder() { CVirtThread::WaitThreadFinish(); }
virtual void Execute();
};
@@ -669,9 +645,7 @@ STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password)
static const int kNumGroupsMax = 4;
-#ifdef USE_86_FILTER
static bool Is86Group(int group) { return (group & 1) != 0; }
-#endif
static bool IsEncryptedGroup(int group) { return (group & 2) != 0; }
static int GetGroupIndex(bool encrypted, int bcjFiltered)
{ return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); }
@@ -789,16 +763,15 @@ HRESULT Update(
if (inSizeForReduce2 > inSizeForReduce)
inSizeForReduce = inSizeForReduce2;
- const UInt32 kMinReduceSize = (1 << 16);
- if (inSizeForReduce < kMinReduceSize)
- inSizeForReduce = kMinReduceSize;
-
RINOK(updateCallback->SetTotal(complexity));
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(updateCallback, true);
+ CStreamBinder sb;
+ RINOK(sb.CreateEvents());
+
CThreadDecoder threadDecoder;
if (!folderRefs.IsEmpty())
{
@@ -870,13 +843,8 @@ HRESULT Update(
{
const CSolidGroup &group = groups[groupIndex];
- CCompressionMethodMode method;
- #ifdef USE_86_FILTER
- if (Is86Group(groupIndex))
- MakeExeMethod(*options.Method, options.MaxFilter, method);
- else
- #endif
- method = *options.Method;
+ CCompressionMethodMode method = *options.Method;
+ MakeExeMethod(method, options.UseFilters, Is86Group(groupIndex), options.MaxFilter);
if (IsEncryptedGroup(groupIndex))
{
@@ -923,11 +891,6 @@ HRESULT Update(
}
else
{
- CStreamBinder sb;
- RINOK(sb.CreateEvents());
- CMyComPtr<ISequentialOutStream> sbOutStream;
- CMyComPtr<ISequentialInStream> sbInStream;
- sb.CreateStreams(&sbInStream, &sbOutStream);
CBoolVector extractStatuses;
CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
@@ -946,24 +909,31 @@ HRESULT Update(
extractStatuses.Add(needExtract);
}
- RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream));
- sbOutStream.Release();
-
- threadDecoder.InStream = inStream;
- threadDecoder.Folder = &db->Folders[folderIndex];
- threadDecoder.StartPos = db->GetFolderStreamPos(folderIndex, 0);
- threadDecoder.PackSizes = &db->PackSizes[db->FolderStartPackStreamIndex[folderIndex]];
-
- threadDecoder.Start();
-
int startPackIndex = newDatabase.PackSizes.Size();
CFolder newFolder;
- RINOK(encoder.Encode(
- EXTERNAL_CODECS_LOC_VARS
- sbInStream, NULL, &inSizeForReduce, newFolder,
- archive.SeqStream, newDatabase.PackSizes, progress));
-
- threadDecoder.WaitFinish();
+ {
+ CMyComPtr<ISequentialInStream> sbInStream;
+ {
+ CMyComPtr<ISequentialOutStream> sbOutStream;
+ sb.CreateStreams(&sbInStream, &sbOutStream);
+ sb.ReInit();
+ RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream));
+ }
+
+ threadDecoder.InStream = inStream;
+ threadDecoder.Folder = &db->Folders[folderIndex];
+ threadDecoder.StartPos = db->GetFolderStreamPos(folderIndex, 0);
+ threadDecoder.PackSizes = &db->PackSizes[db->FolderStartPackStreamIndex[folderIndex]];
+
+ threadDecoder.Start();
+
+ RINOK(encoder.Encode(
+ EXTERNAL_CODECS_LOC_VARS
+ sbInStream, NULL, &inSizeForReduce, newFolder,
+ archive.SeqStream, newDatabase.PackSizes, progress));
+
+ threadDecoder.WaitExecuteFinish();
+ }
RINOK(threadDecoder.Result);
@@ -1134,6 +1104,8 @@ HRESULT Update(
if (folderRefIndex != folderRefs.Size())
return E_FAIL;
+ RINOK(lps->SetCur());
+
/*
folderRefs.ClearAndFree();
fileIndexToUpdateIndexMap.ClearAndFree();
@@ -1169,7 +1141,7 @@ HRESULT Update(
newDatabase.AddFile(file, file2);
}
}
-
+
newDatabase.ReserveDown();
return S_OK;
}
diff --git a/CPP/7zip/Archive/Bz2Handler.cpp b/CPP/7zip/Archive/Bz2Handler.cpp
index 98cbcc18..49ae8c79 100755
--- a/CPP/7zip/Archive/Bz2Handler.cpp
+++ b/CPP/7zip/Archive/Bz2Handler.cpp
@@ -4,13 +4,6 @@
#include "Common/ComTry.h"
-#include "Windows/PropVariant.h"
-
-#ifndef _7ZIP_ST
-#include "../../Windows/System.h"
-#endif
-
-#include "../Common/CreateCoder.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"
@@ -20,21 +13,13 @@
#include "../Compress/CopyCoder.h"
#include "Common/DummyOutStream.h"
-#include "Common/ParseProperties.h"
+#include "Common/HandlerOut.h"
using namespace NWindows;
namespace NArchive {
namespace NBz2 {
-static const UInt32 kNumPassesX1 = 1;
-static const UInt32 kNumPassesX7 = 2;
-static const UInt32 kNumPassesX9 = 7;
-
-static const UInt32 kDicSizeX1 = 100000;
-static const UInt32 kDicSizeX3 = 500000;
-static const UInt32 kDicSizeX5 = 900000;
-
class CHandler:
public IInArchive,
public IArchiveOpenSeq,
@@ -48,22 +33,7 @@ class CHandler:
UInt64 _startPosition;
bool _packSizeDefined;
- UInt32 _level;
- UInt32 _dicSize;
- UInt32 _numPasses;
- #ifndef _7ZIP_ST
- UInt32 _numThreads;
- #endif
-
- void InitMethodProperties()
- {
- _level = 5;
- _dicSize =
- _numPasses = 0xFFFFFFFF;
- #ifndef _7ZIP_ST
- _numThreads = NWindows::NSystem::GetNumberOfProcessors();;
- #endif
- }
+ CSingleMethodProps _props;
public:
MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)
@@ -73,10 +43,10 @@ public:
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
- CHandler() { InitMethodProperties(); }
+ CHandler() { }
};
-STATPROPSTG kProps[] =
+static const STATPROPSTG kProps[] =
{
{ NULL, kpidPackSize, VT_UI8}
};
@@ -87,7 +57,7 @@ IMP_IInArchive_ArcProps_NO_Table
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
- switch(propID)
+ switch (propID)
{
case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;
}
@@ -104,7 +74,7 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
{
NWindows::NCOM::CPropVariant prop;
- switch(propID)
+ switch (propID)
{
case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;
}
@@ -188,7 +158,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
decoderSpec->SetInStream(_seqStream);
#ifndef _7ZIP_ST
- RINOK(decoderSpec->SetNumberOfThreads(_numThreads));
+ RINOK(decoderSpec->SetNumberOfThreads(_props._numThreads));
#endif
CDummyOutStream *outStreamSpec = new CDummyOutStream;
@@ -246,50 +216,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
static HRESULT UpdateArchive(
UInt64 unpackSize,
ISequentialOutStream *outStream,
- int indexInClient,
- UInt32 dictionary,
- UInt32 numPasses,
- #ifndef _7ZIP_ST
- UInt32 numThreads,
- #endif
+ const CProps &props,
IArchiveUpdateCallback *updateCallback)
{
RINOK(updateCallback->SetTotal(unpackSize));
- UInt64 complexity = 0;
- RINOK(updateCallback->SetCompleted(&complexity));
-
CMyComPtr<ISequentialInStream> fileInStream;
-
- RINOK(updateCallback->GetStream(indexInClient, &fileInStream));
-
+ RINOK(updateCallback->GetStream(0, &fileInStream));
CLocalProgress *localProgressSpec = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
localProgressSpec->Init(updateCallback, true);
-
NCompress::NBZip2::CEncoder *encoderSpec = new NCompress::NBZip2::CEncoder;
CMyComPtr<ICompressCoder> encoder = encoderSpec;
- {
- NWindows::NCOM::CPropVariant properties[] =
- {
- dictionary,
- numPasses
- #ifndef _7ZIP_ST
- , numThreads
- #endif
- };
- PROPID propIDs[] =
- {
- NCoderPropID::kDictionarySize,
- NCoderPropID::kNumPasses
- #ifndef _7ZIP_ST
- , NCoderPropID::kNumThreads
- #endif
- };
- RINOK(encoderSpec->SetCoderProperties(propIDs, properties, sizeof(propIDs) / sizeof(propIDs[0])));
- }
-
+ RINOK(props.SetCoderProps(encoderSpec, NULL));
RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress));
-
return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
}
@@ -336,25 +275,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return E_INVALIDARG;
size = prop.uhVal.QuadPart;
}
-
- UInt32 dicSize = _dicSize;
- if (dicSize == 0xFFFFFFFF)
- dicSize = (_level >= 5 ? kDicSizeX5 :
- (_level >= 3 ? kDicSizeX3 :
- kDicSizeX1));
-
- UInt32 numPasses = _numPasses;
- if (numPasses == 0xFFFFFFFF)
- numPasses = (_level >= 9 ? kNumPassesX9 :
- (_level >= 7 ? kNumPassesX7 :
- kNumPassesX1));
-
- return UpdateArchive(
- size, outStream, 0, dicSize, numPasses,
- #ifndef _7ZIP_ST
- _numThreads,
- #endif
- updateCallback);
+ return UpdateArchive(size, outStream, _props, updateCallback);
}
if (indexInArchive != 0)
return E_INVALIDARG;
@@ -365,47 +286,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
- InitMethodProperties();
- #ifndef _7ZIP_ST
- const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
- _numThreads = numProcessors;
- #endif
-
- for (int i = 0; i < numProps; i++)
- {
- UString name = names[i];
- name.MakeUpper();
- if (name.IsEmpty())
- return E_INVALIDARG;
- const PROPVARIANT &prop = values[i];
- if (name[0] == L'X')
- {
- UInt32 level = 9;
- RINOK(ParsePropValue(name.Mid(1), prop, level));
- _level = level;
- }
- else if (name[0] == L'D')
- {
- UInt32 dicSize = kDicSizeX5;
- RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize));
- _dicSize = dicSize;
- }
- else if (name.Left(4) == L"PASS")
- {
- UInt32 num = kNumPassesX9;
- RINOK(ParsePropValue(name.Mid(4), prop, num));
- _numPasses = num;
- }
- else if (name.Left(2) == L"MT")
- {
- #ifndef _7ZIP_ST
- RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads));
- #endif
- }
- else
- return E_INVALIDARG;
- }
- return S_OK;
+ return _props.SetProperties(names, values, numProps);
}
static IInArchive *CreateArc() { return new CHandler; }
diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp
index 20f670d3..fd707fe5 100755
--- a/CPP/7zip/Archive/Cab/CabHandler.cpp
+++ b/CPP/7zip/Archive/Cab/CabHandler.cpp
@@ -4,9 +4,7 @@
#include "../../../../C/Alloc.h"
-#include "Common/Buffer.h"
#include "Common/ComTry.h"
-#include "Common/Defs.h"
#include "Common/IntToString.h"
#include "Common/StringConvert.h"
#include "Common/UTFConvert.h"
@@ -654,7 +652,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode)
numItems = m_Database.Items.Size();
- if(numItems == 0)
+ if (numItems == 0)
return S_OK;
bool testMode = (testModeSpec != 0);
UInt64 totalUnPacked = 0;
@@ -780,12 +778,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
curUnpack, extractCallback, testMode);
cabBlockInStreamSpec->MsZip = false;
+ HRESULT res = S_OK;
switch(folder.GetCompressionMethod())
{
case NHeader::NCompressionMethodMajor::kNone:
break;
case NHeader::NCompressionMethodMajor::kMSZip:
- if(deflateDecoderSpec == NULL)
+ if (!deflateDecoder)
{
deflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder;
deflateDecoder = deflateDecoderSpec;
@@ -793,33 +792,35 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
cabBlockInStreamSpec->MsZip = true;
break;
case NHeader::NCompressionMethodMajor::kLZX:
- if(lzxDecoderSpec == NULL)
+ if (!lzxDecoder)
{
lzxDecoderSpec = new NCompress::NLzx::CDecoder;
lzxDecoder = lzxDecoderSpec;
}
- RINOK(lzxDecoderSpec->SetParams(folder.CompressionTypeMinor));
+ res = lzxDecoderSpec->SetParams(folder.CompressionTypeMinor);
break;
case NHeader::NCompressionMethodMajor::kQuantum:
- if(quantumDecoderSpec == NULL)
+ if (!quantumDecoder)
{
quantumDecoderSpec = new NCompress::NQuantum::CDecoder;
quantumDecoder = quantumDecoderSpec;
}
- quantumDecoderSpec->SetParams(folder.CompressionTypeMinor);
+ res = quantumDecoderSpec->SetParams(folder.CompressionTypeMinor);
break;
default:
- {
- RINOK(cabFolderOutStream->Unsupported());
- totalUnPacked += curUnpack;
- continue;
- }
+ res = E_INVALIDARG;
+ break;
}
- cabBlockInStreamSpec->InitForNewFolder();
-
- HRESULT res = S_OK;
+ if (res == E_INVALIDARG)
+ {
+ RINOK(cabFolderOutStream->Unsupported());
+ totalUnPacked += curUnpack;
+ continue;
+ }
+ RINOK(res);
+ cabBlockInStreamSpec->InitForNewFolder();
{
int volIndex = mvItem.VolumeIndex;
int locFolderIndex = item.GetFolderIndex(db.Folders.Size());
diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h
index 4719a484..4b1ac7a6 100755
--- a/CPP/7zip/Archive/Chm/ChmIn.h
+++ b/CPP/7zip/Archive/Chm/ChmIn.h
@@ -39,7 +39,7 @@ struct CItem
{
if (Name.Length() == 0)
return false;
- return (Name[Name.Length() - 1] == '/');
+ return (Name.Back() == '/');
}
};
diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
index d76450bd..87686e85 100755
--- a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
@@ -214,7 +214,7 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
for (i = 0; i < _coders.Size(); i++)
if (i != _progressCoderIndex)
- _coders[i].WaitFinish();
+ _coders[i].WaitExecuteFinish();
RINOK(ReturnIfError(E_ABORT));
RINOK(ReturnIfError(E_OUTOFMEMORY));
diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h
index d1c7f4d0..81bb3f0b 100755
--- a/CPP/7zip/Archive/Common/CoderMixer2MT.h
+++ b/CPP/7zip/Archive/Common/CoderMixer2MT.h
@@ -19,6 +19,7 @@ struct CCoder2: public CCoderInfo2, public CVirtThread
CRecordVector<ISequentialOutStream*> OutStreamPointers;
CCoder2(UInt32 numInStreams, UInt32 numOutStreams);
+ ~CCoder2() { CVirtThread::WaitThreadFinish(); }
void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
virtual void Execute();
void Code(ICompressProgressInfo *progress);
diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
index a59ce5fc..a21ca0c0 100755
--- a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
@@ -4,7 +4,7 @@
#include "CoderMixer2ST.h"
-namespace NCoderMixer2 {
+namespace NCoderMixer {
CCoderMixer2ST::CCoderMixer2ST() {}
@@ -42,7 +42,7 @@ HRESULT CCoderMixer2ST::GetInStream(
{
CMyComPtr<ISequentialInStream> seqInStream;
int i;
- for(i = 0; i < _bindInfo.InStreams.Size(); i++)
+ for (i = 0; i < _bindInfo.InStreams.Size(); i++)
if (_bindInfo.InStreams[i] == streamIndex)
{
seqInStream = inStreams[i];
@@ -57,7 +57,7 @@ HRESULT CCoderMixer2ST::GetInStream(
_bindInfo.FindOutStream(_bindInfo.BindPairs[binderIndex].OutIndex,
coderIndex, coderStreamIndex);
- CCoderInfo &coder = _coders[coderIndex];
+ CCoderInfo2 &coder = _coders[coderIndex];
if (!coder.Coder)
return E_NOTIMPL;
coder.Coder.QueryInterface(IID_ISequentialInStream, &seqInStream);
@@ -91,7 +91,7 @@ HRESULT CCoderMixer2ST::GetOutStream(
{
CMyComPtr<ISequentialOutStream> seqOutStream;
int i;
- for(i = 0; i < _bindInfo.OutStreams.Size(); i++)
+ for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
if (_bindInfo.OutStreams[i] == streamIndex)
{
seqOutStream = outStreams[i];
@@ -106,7 +106,7 @@ HRESULT CCoderMixer2ST::GetOutStream(
_bindInfo.FindInStream(_bindInfo.BindPairs[binderIndex].InIndex,
coderIndex, coderStreamIndex);
- CCoderInfo &coder = _coders[coderIndex];
+ CCoderInfo2 &coder = _coders[coderIndex];
if (!coder.Coder)
return E_NOTIMPL;
coder.Coder.QueryInterface(IID_ISequentialOutStream, &seqOutStream);
@@ -169,7 +169,7 @@ STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams,
// _mainCoderIndex = 0;
// _mainCoderIndex = _coders.Size() - 1;
- CCoderInfo &mainCoder = _coders[_mainCoderIndex];
+ CCoderInfo2 &mainCoder = _coders[_mainCoderIndex];
CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
@@ -198,7 +198,7 @@ STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams,
{
if (i == _mainCoderIndex)
continue;
- CCoderInfo &coder = _coders[i];
+ CCoderInfo2 &coder = _coders[i];
CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
coder.Coder.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
if (setOutStreamSize)
diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.h b/CPP/7zip/Archive/Common/CoderMixer2ST.h
index a4ea7e80..d35655ba 100755
--- a/CPP/7zip/Archive/Common/CoderMixer2ST.h
+++ b/CPP/7zip/Archive/Common/CoderMixer2ST.h
@@ -7,7 +7,7 @@
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
-namespace NCoderMixer2 {
+namespace NCoderMixer {
// SetBindInfo()
// for each coder
@@ -26,11 +26,11 @@ namespace NCoderMixer2 {
// Code
// }
-struct CSTCoderInfo: public CCoderInfo
+struct CSTCoderInfo: public CCoderInfo2
{
bool IsMain;
CSTCoderInfo(UInt32 numInStreams, UInt32 numOutStreams, bool isMain):
- CCoderInfo(numInStreams, numOutStreams),IsMain(isMain) {}
+ CCoderInfo2(numInStreams, numOutStreams), IsMain(isMain) {}
};
class CCoderMixer2ST:
@@ -84,5 +84,5 @@ public:
};
}
-#endif
+#endif
diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.cpp b/CPP/7zip/Archive/Common/CoderMixerMT.cpp
index f43d1612..96ea76a3 100755
--- a/CPP/7zip/Archive/Common/CoderMixerMT.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixerMT.cpp
@@ -73,7 +73,7 @@ STDMETHODIMP CCoderMixerMT::Code(ISequentialInStream *inStream,
for (i = 0; i < _coders.Size(); i++)
if (i != _progressCoderIndex)
- _coders[i].WaitFinish();
+ _coders[i].WaitExecuteFinish();
RINOK(ReturnIfError(E_ABORT));
RINOK(ReturnIfError(E_OUTOFMEMORY));
diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.h b/CPP/7zip/Archive/Common/CoderMixerMT.h
index c70e1829..9491a965 100755
--- a/CPP/7zip/Archive/Common/CoderMixerMT.h
+++ b/CPP/7zip/Archive/Common/CoderMixerMT.h
@@ -18,6 +18,7 @@ struct CCoder: public CCoderInfo, public CVirtThread
virtual void Execute();
void Code(ICompressProgressInfo *progress);
+ ~CCoder() { CVirtThread::WaitThreadFinish(); }
};
/*
diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp
index 70ad47aa..7e6f4602 100755
--- a/CPP/7zip/Archive/Common/HandlerOut.cpp
+++ b/CPP/7zip/Archive/Common/HandlerOut.cpp
@@ -2,16 +2,10 @@
#include "StdAfx.h"
-#include "../../../Common/StringToInt.h"
-
-#include "../../../Windows/PropVariant.h"
-
#ifndef _7ZIP_ST
#include "../../../Windows/System.h"
#endif
-#include "../../ICoder.h"
-
#include "../Common/ParseProperties.h"
#include "HandlerOut.h"
@@ -20,487 +14,40 @@ using namespace NWindows;
namespace NArchive {
-static const wchar_t *kCopyMethod = L"Copy";
-static const wchar_t *kLZMAMethodName = L"LZMA";
-static const wchar_t *kLZMA2MethodName = L"LZMA2";
-static const wchar_t *kBZip2MethodName = L"BZip2";
-static const wchar_t *kPpmdMethodName = L"PPMd";
-static const wchar_t *kDeflateMethodName = L"Deflate";
-static const wchar_t *kDeflate64MethodName = L"Deflate64";
-
-static const wchar_t *kLzmaMatchFinderX1 = L"HC4";
-static const wchar_t *kLzmaMatchFinderX5 = L"BT4";
-
-static const UInt32 kLzmaAlgoX1 = 0;
-static const UInt32 kLzmaAlgoX5 = 1;
-
-static const UInt32 kLzmaDicSizeX1 = 1 << 16;
-static const UInt32 kLzmaDicSizeX3 = 1 << 20;
-static const UInt32 kLzmaDicSizeX5 = 1 << 24;
-static const UInt32 kLzmaDicSizeX7 = 1 << 25;
-static const UInt32 kLzmaDicSizeX9 = 1 << 26;
-
-static const UInt32 kLzmaFastBytesX1 = 32;
-static const UInt32 kLzmaFastBytesX7 = 64;
-
-static const UInt32 kPpmdMemSizeX1 = (1 << 22);
-static const UInt32 kPpmdMemSizeX5 = (1 << 24);
-static const UInt32 kPpmdMemSizeX7 = (1 << 26);
-static const UInt32 kPpmdMemSizeX9 = (192 << 20);
-
-static const UInt32 kPpmdOrderX1 = 4;
-static const UInt32 kPpmdOrderX5 = 6;
-static const UInt32 kPpmdOrderX7 = 16;
-static const UInt32 kPpmdOrderX9 = 32;
-
-static const UInt32 kDeflateAlgoX1 = 0;
-static const UInt32 kDeflateAlgoX5 = 1;
-
-static const UInt32 kDeflateFastBytesX1 = 32;
-static const UInt32 kDeflateFastBytesX7 = 64;
-static const UInt32 kDeflateFastBytesX9 = 128;
-
-static const UInt32 kDeflatePassesX1 = 1;
-static const UInt32 kDeflatePassesX7 = 3;
-static const UInt32 kDeflatePassesX9 = 10;
-
-static const UInt32 kBZip2NumPassesX1 = 1;
-static const UInt32 kBZip2NumPassesX7 = 2;
-static const UInt32 kBZip2NumPassesX9 = 7;
-
-static const UInt32 kBZip2DicSizeX1 = 100000;
-static const UInt32 kBZip2DicSizeX3 = 500000;
-static const UInt32 kBZip2DicSizeX5 = 900000;
-
-static const wchar_t *kDefaultMethodName = kLZMAMethodName;
-
-static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";
-static const UInt32 kDictionaryForHeaders = 1 << 20;
-static const UInt32 kNumFastBytesForHeaders = 273;
-static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5;
-
-static bool AreEqual(const UString &methodName, const wchar_t *s)
- { return (methodName.CompareNoCase(s) == 0); }
-
-bool COneMethodInfo::IsLzma() const
-{
- return
- AreEqual(MethodName, kLZMAMethodName) ||
- AreEqual(MethodName, kLZMA2MethodName);
-}
-
-static inline bool IsBZip2Method(const UString &methodName)
- { return AreEqual(methodName, kBZip2MethodName); }
-
-static inline bool IsPpmdMethod(const UString &methodName)
- { return AreEqual(methodName, kPpmdMethodName); }
-
-static inline bool IsDeflateMethod(const UString &methodName)
-{
- return
- AreEqual(methodName, kDeflateMethodName) ||
- AreEqual(methodName, kDeflate64MethodName);
-}
-
-struct CNameToPropID
-{
- PROPID PropID;
- VARTYPE VarType;
- const wchar_t *Name;
-};
-
-static CNameToPropID g_NameToPropID[] =
-{
- { NCoderPropID::kBlockSize, VT_UI4, L"C" },
- { NCoderPropID::kDictionarySize, VT_UI4, L"D" },
- { NCoderPropID::kUsedMemorySize, VT_UI4, L"MEM" },
-
- { NCoderPropID::kOrder, VT_UI4, L"O" },
- { NCoderPropID::kPosStateBits, VT_UI4, L"PB" },
- { NCoderPropID::kLitContextBits, VT_UI4, L"LC" },
- { NCoderPropID::kLitPosBits, VT_UI4, L"LP" },
- { NCoderPropID::kEndMarker, VT_BOOL, L"eos" },
-
- { NCoderPropID::kNumPasses, VT_UI4, L"Pass" },
- { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" },
- { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" },
- { NCoderPropID::kAlgorithm, VT_UI4, L"a" },
- { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" },
- { NCoderPropID::kNumThreads, VT_UI4, L"mt" },
- { NCoderPropID::kDefaultProp, VT_UI4, L"" }
-};
-
-static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)
-{
- if (varType == srcProp.vt)
- {
- destProp = srcProp;
- return true;
- }
- if (varType == VT_UI1)
- {
- if (srcProp.vt == VT_UI4)
- {
- UInt32 value = srcProp.ulVal;
- if (value > 0xFF)
- return false;
- destProp = (Byte)value;
- return true;
- }
- }
- else if (varType == VT_BOOL)
- {
- bool res;
- if (SetBoolProperty(res, srcProp) != S_OK)
- return false;
- destProp = res;
- return true;
- }
- return false;
-}
-
-static int FindPropIdExact(const UString &name)
-{
- for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)
- if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)
- return i;
- return -1;
-}
-
-static int FindPropIdStart(const UString &name)
+static void SetMethodProp32(COneMethodInfo &m, PROPID propID, UInt32 value)
{
- for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)
- {
- UString t = g_NameToPropID[i].Name;
- if (t.CompareNoCase(name.Left(t.Length())) == 0)
- return i;
- }
- return -1;
+ if (m.FindProp(propID) < 0)
+ m.AddProp32(propID, value);
}
-static void SetMethodProp(COneMethodInfo &m, PROPID propID, const NCOM::CPropVariant &value)
-{
- for (int j = 0; j < m.Props.Size(); j++)
- if (m.Props[j].Id == propID)
- return;
- CProp prop;
- prop.Id = propID;
- prop.Value = value;
- m.Props.Add(prop);
-}
-
-void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
+void CMultiMethodProps::SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
)
{
UInt32 level = _level;
- if (oneMethodInfo.MethodName.IsEmpty())
- oneMethodInfo.MethodName = kDefaultMethodName;
-
- if (oneMethodInfo.IsLzma())
- {
- UInt32 dicSize =
- (level >= 9 ? kLzmaDicSizeX9 :
- (level >= 7 ? kLzmaDicSizeX7 :
- (level >= 5 ? kLzmaDicSizeX5 :
- (level >= 3 ? kLzmaDicSizeX3 :
- kLzmaDicSizeX1))));
-
- UInt32 algo =
- (level >= 5 ? kLzmaAlgoX5 :
- kLzmaAlgoX1);
-
- UInt32 fastBytes =
- (level >= 7 ? kLzmaFastBytesX7 :
- kLzmaFastBytesX1);
-
- const wchar_t *matchFinder =
- (level >= 5 ? kLzmaMatchFinderX5 :
- kLzmaMatchFinderX1);
-
- SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
- SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
- SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
- SetMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);
- #ifndef _7ZIP_ST
- SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
- #endif
- }
- else if (IsDeflateMethod(oneMethodInfo.MethodName))
- {
- UInt32 fastBytes =
- (level >= 9 ? kDeflateFastBytesX9 :
- (level >= 7 ? kDeflateFastBytesX7 :
- kDeflateFastBytesX1));
-
- UInt32 numPasses =
- (level >= 9 ? kDeflatePassesX9 :
- (level >= 7 ? kDeflatePassesX7 :
- kDeflatePassesX1));
-
- UInt32 algo =
- (level >= 5 ? kDeflateAlgoX5 :
- kDeflateAlgoX1);
-
- SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
- SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
- SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
- }
- else if (IsBZip2Method(oneMethodInfo.MethodName))
- {
- UInt32 numPasses =
- (level >= 9 ? kBZip2NumPassesX9 :
- (level >= 7 ? kBZip2NumPassesX7 :
- kBZip2NumPassesX1));
-
- UInt32 dicSize =
- (level >= 5 ? kBZip2DicSizeX5 :
- (level >= 3 ? kBZip2DicSizeX3 :
- kBZip2DicSizeX1));
-
- SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
- SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
- #ifndef _7ZIP_ST
- SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
- #endif
- }
- else if (IsPpmdMethod(oneMethodInfo.MethodName))
- {
- UInt32 useMemSize =
- (level >= 9 ? kPpmdMemSizeX9 :
- (level >= 7 ? kPpmdMemSizeX7 :
- (level >= 5 ? kPpmdMemSizeX5 :
- kPpmdMemSizeX1)));
-
- UInt32 order =
- (level >= 9 ? kPpmdOrderX9 :
- (level >= 7 ? kPpmdOrderX7 :
- (level >= 5 ? kPpmdOrderX5 :
- kPpmdOrderX1)));
-
- SetMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);
- SetMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);
- }
-}
-
-static void SplitParams(const UString &srcString, UStringVector &subStrings)
-{
- subStrings.Clear();
- UString name;
- int len = srcString.Length();
- if (len == 0)
- return;
- for (int i = 0; i < len; i++)
- {
- wchar_t c = srcString[i];
- if (c == L':')
- {
- subStrings.Add(name);
- name.Empty();
- }
- else
- name += c;
- }
- subStrings.Add(name);
-}
-
-static void SplitParam(const UString &param, UString &name, UString &value)
-{
- int eqPos = param.Find(L'=');
- if (eqPos >= 0)
- {
- name = param.Left(eqPos);
- value = param.Mid(eqPos + 1);
- return;
- }
- for(int i = 0; i < param.Length(); i++)
- {
- wchar_t c = param[i];
- if (c >= L'0' && c <= L'9')
- {
- name = param.Left(i);
- value = param.Mid(i);
- return;
- }
- }
- name = param;
-}
-
-HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)
-{
- CProp prop;
- int index = FindPropIdExact(name);
- if (index < 0)
- return E_INVALIDARG;
- const CNameToPropID &nameToPropID = g_NameToPropID[index];
- prop.Id = nameToPropID.PropID;
-
- if (prop.Id == NCoderPropID::kBlockSize ||
- prop.Id == NCoderPropID::kDictionarySize ||
- prop.Id == NCoderPropID::kUsedMemorySize)
- {
- UInt32 dicSize;
- RINOK(ParsePropDictionaryValue(value, dicSize));
- prop.Value = dicSize;
- }
- else
- {
- NCOM::CPropVariant propValue;
-
- if (nameToPropID.VarType == VT_BSTR)
- propValue = value;
- else if (nameToPropID.VarType == VT_BOOL)
- {
- bool res;
- if (!StringToBool(value, res))
- return E_INVALIDARG;
- propValue = res;
- }
- else
- {
- UInt32 number;
- if (ParseStringToUInt32(value, number) == value.Length())
- propValue = number;
- else
- propValue = value;
- }
-
- if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value))
- return E_INVALIDARG;
- }
- oneMethodInfo.Props.Add(prop);
- return S_OK;
-}
-
-HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString)
-{
- UStringVector params;
- SplitParams(srcString, params);
- if (params.Size() > 0)
- oneMethodInfo.MethodName = params[0];
- for (int i = 1; i < params.Size(); i++)
- {
- const UString &param = params[i];
- UString name, value;
- SplitParam(param, name, value);
- RINOK(SetParam(oneMethodInfo, name, value));
- }
- return S_OK;
-}
-
-HRESULT COutHandler::SetSolidSettings(const UString &s)
-{
- UString s2 = s;
- s2.MakeUpper();
- for (int i = 0; i < s2.Length();)
- {
- const wchar_t *start = ((const wchar_t *)s2) + i;
- const wchar_t *end;
- UInt64 v = ConvertStringToUInt64(start, &end);
- if (start == end)
- {
- if (s2[i++] != 'E')
- return E_INVALIDARG;
- _solidExtension = true;
- continue;
- }
- i += (int)(end - start);
- if (i == s2.Length())
- return E_INVALIDARG;
- wchar_t c = s2[i++];
- switch(c)
- {
- case 'F':
- if (v < 1)
- v = 1;
- _numSolidFiles = v;
- break;
- case 'B':
- _numSolidBytes = v;
- _numSolidBytesDefined = true;
- break;
- case 'K':
- _numSolidBytes = (v << 10);
- _numSolidBytesDefined = true;
- break;
- case 'M':
- _numSolidBytes = (v << 20);
- _numSolidBytesDefined = true;
- break;
- case 'G':
- _numSolidBytes = (v << 30);
- _numSolidBytesDefined = true;
- break;
- default:
- return E_INVALIDARG;
- }
- }
- return S_OK;
-}
-
-HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value)
-{
- bool isSolid;
- switch(value.vt)
- {
- case VT_EMPTY:
- isSolid = true;
- break;
- case VT_BOOL:
- isSolid = (value.boolVal != VARIANT_FALSE);
- break;
- case VT_BSTR:
- if (StringToBool(value.bstrVal, isSolid))
- break;
- return SetSolidSettings(value.bstrVal);
- default:
- return E_INVALIDARG;
- }
- if (isSolid)
- InitSolid();
- else
- _numSolidFiles = 1;
- return S_OK;
-}
-
-void COutHandler::Init()
-{
- _removeSfxBlock = false;
- _compressHeaders = true;
- _encryptHeadersSpecified = false;
- _encryptHeaders = false;
-
- WriteCTime = false;
- WriteATime = false;
- WriteMTime = true;
-
+ if (level != (UInt32)(UInt32)-1)
+ SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);
#ifndef _7ZIP_ST
- _numThreads = NSystem::GetNumberOfProcessors();
+ SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
#endif
-
- _level = 5;
- _autoFilter = true;
- _volumeMode = false;
- _crcSize = 4;
- InitSolid();
}
-void COutHandler::BeforeSetProperty()
+void CMultiMethodProps::Init()
{
- Init();
#ifndef _7ZIP_ST
- numProcessors = NSystem::GetNumberOfProcessors();
+ _numProcessors = _numThreads = NSystem::GetNumberOfProcessors();
#endif
-
- mainDicSize = 0xFFFFFFFF;
- mainDicMethodIndex = 0xFFFFFFFF;
- minNumber = 0;
+
+ _level = (UInt32)(UInt32)-1;
+ _autoFilter = true;
_crcSize = 4;
+ _filterMethod.Clear();
+ _methods.Clear();
}
-HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
+HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
{
UString name = nameSpec;
name.MakeUpper();
@@ -511,24 +58,14 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
{
name.Delete(0);
_level = 9;
- return ParsePropValue(name, value, _level);
- }
-
- if (name[0] == L'S')
- {
- name.Delete(0);
- if (name.IsEmpty())
- return SetSolidSettings(value);
- if (value.vt != VT_EMPTY)
- return E_INVALIDARG;
- return SetSolidSettings(name);
+ return ParsePropToUInt32(name, value, _level);
}
if (name == L"CRC")
{
- _crcSize = 4;
name.Delete(0, 3);
- return ParsePropValue(name, value, _crcSize);
+ _crcSize = 4;
+ return ParsePropToUInt32(name, value, _crcSize);
}
UInt32 number;
@@ -536,86 +73,67 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
UString realName = name.Mid(index);
if (index == 0)
{
- if(name.Left(2).CompareNoCase(L"MT") == 0)
+ if (name.Left(2).CompareNoCase(L"MT") == 0)
{
#ifndef _7ZIP_ST
- RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
+ RINOK(ParseMtProp(name.Mid(2), value, _numProcessors, _numThreads));
#endif
return S_OK;
}
- if (name.CompareNoCase(L"RSFX") == 0) return SetBoolProperty(_removeSfxBlock, value);
- if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value);
- if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value);
- if (name.CompareNoCase(L"HCF") == 0)
+ if (name.CompareNoCase(L"F") == 0)
{
- bool compressHeadersFull = true;
- RINOK(SetBoolProperty(compressHeadersFull, value));
- if (!compressHeadersFull)
+ HRESULT res = PROPVARIANT_to_bool(value, _autoFilter);
+ if (res == S_OK)
+ return res;
+ if (value.vt != VT_BSTR)
return E_INVALIDARG;
- return S_OK;
+ return _filterMethod.ParseMethodFromPROPVARIANT(L"", value);
}
- if (name.CompareNoCase(L"HE") == 0)
- {
- RINOK(SetBoolProperty(_encryptHeaders, value));
- _encryptHeadersSpecified = true;
- return S_OK;
- }
- if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCTime, value);
- if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteATime, value);
- if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteMTime, value);
- if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value);
number = 0;
}
- if (number > 10000)
+ if (number > 64)
return E_FAIL;
- if (number < minNumber)
- return E_INVALIDARG;
- number -= minNumber;
- for(int j = _methods.Size(); j <= (int)number; j++)
- {
- COneMethodInfo oneMethodInfo;
- _methods.Add(oneMethodInfo);
- }
-
- COneMethodInfo &oneMethodInfo = _methods[number];
-
- if (realName.Length() == 0)
- {
- if (value.vt != VT_BSTR)
- return E_INVALIDARG;
-
- RINOK(SetParams(oneMethodInfo, value.bstrVal));
- }
- else
+ for (int j = _methods.Size(); j <= (int)number; j++)
+ _methods.Add(COneMethodInfo());
+ return _methods[number].ParseMethodFromPROPVARIANT(realName, value);
+}
+
+void CSingleMethodProps::Init()
+{
+ Clear();
+ #ifndef _7ZIP_ST
+ _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors();
+ AddNumThreadsProp(_numThreads);
+ #endif
+ _level = (UInt32)(UInt32)-1;
+}
+
+HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
+{
+ Init();
+ for (int i = 0; i < numProps; i++)
{
- int index = FindPropIdStart(realName);
- if (index < 0)
+ UString name = names[i];
+ name.MakeUpper();
+ if (name.IsEmpty())
return E_INVALIDARG;
- const CNameToPropID &nameToPropID = g_NameToPropID[index];
- CProp prop;
- prop.Id = nameToPropID.PropID;
-
- if (prop.Id == NCoderPropID::kBlockSize ||
- prop.Id == NCoderPropID::kDictionarySize ||
- prop.Id == NCoderPropID::kUsedMemorySize)
+ const PROPVARIANT &value = values[i];
+ if (name[0] == L'X')
{
- UInt32 dicSize;
- RINOK(ParsePropDictionaryValue(realName.Mid(MyStringLen(nameToPropID.Name)), value, dicSize));
- prop.Value = dicSize;
- if (number <= mainDicMethodIndex)
- mainDicSize = dicSize;
+ UInt32 a = 9;
+ RINOK(ParsePropToUInt32(name.Mid(1), value, a));
+ _level = a;
+ AddLevelProp(a);
}
- else
+ else if (name.Left(2).CompareNoCase(L"MT") == 0)
{
- int index = FindPropIdExact(realName);
- if (index < 0)
- return E_INVALIDARG;
- const CNameToPropID &nameToPropID = g_NameToPropID[index];
- prop.Id = nameToPropID.PropID;
- if (!ConvertProperty(value, nameToPropID.VarType, prop.Value))
- return E_INVALIDARG;
+ #ifndef _7ZIP_ST
+ RINOK(ParseMtProp(name.Mid(2), value, _numProcessors, _numThreads));
+ AddNumThreadsProp(_numThreads);
+ #endif
}
- oneMethodInfo.Props.Add(prop);
+ else
+ return ParseParamsFromPROPVARIANT(name, value);
}
return S_OK;
}
diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h
index 72ea4032..d3c9a237 100755
--- a/CPP/7zip/Archive/Common/HandlerOut.h
+++ b/CPP/7zip/Archive/Common/HandlerOut.h
@@ -3,83 +3,61 @@
#ifndef __HANDLER_OUT_H
#define __HANDLER_OUT_H
-#include "../../../Common/MyString.h"
#include "../../Common/MethodProps.h"
namespace NArchive {
-struct COneMethodInfo
-{
- CObjectVector<CProp> Props;
- UString MethodName;
-
- bool IsLzma() const;
-};
-
-class COutHandler
+class CMultiMethodProps
{
+ UInt32 _level;
public:
- HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
-
- HRESULT SetSolidSettings(const UString &s);
- HRESULT SetSolidSettings(const PROPVARIANT &value);
-
#ifndef _7ZIP_ST
UInt32 _numThreads;
+ UInt32 _numProcessors;
#endif
UInt32 _crcSize;
-
CObjectVector<COneMethodInfo> _methods;
- bool _removeSfxBlock;
-
- UInt64 _numSolidFiles;
- UInt64 _numSolidBytes;
- bool _numSolidBytesDefined;
- bool _solidExtension;
-
- bool _compressHeaders;
- bool _encryptHeadersSpecified;
- bool _encryptHeaders;
-
- bool WriteCTime;
- bool WriteATime;
- bool WriteMTime;
-
+ COneMethodInfo _filterMethod;
bool _autoFilter;
- UInt32 _level;
- bool _volumeMode;
-
- HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value);
- HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString);
-
- void SetCompressionMethod2(COneMethodInfo &oneMethodInfo
+ void SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
);
- void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
- void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
- void InitSolid()
+ int GetNumEmptyMethods() const
{
- InitSolidFiles();
- InitSolidSize();
- _solidExtension = false;
- _numSolidBytesDefined = false;
+ int i;
+ for (i = 0; i < _methods.Size(); i++)
+ if (!_methods[i].IsEmpty())
+ break;
+ return i;
}
+ int GetLevel() const { return _level == (UInt32)(UInt32)-1 ? 5 : (int)_level; }
+
void Init();
- COutHandler() { Init(); }
+ CMultiMethodProps() { Init(); }
+ HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
+};
- void BeforeSetProperty();
+class CSingleMethodProps: public CMethodProps
+{
+ UInt32 _level;
+
+ void Init();
+public:
+ #ifndef _7ZIP_ST
+ UInt32 _numThreads;
+ UInt32 _numProcessors;
+ #endif
- UInt32 minNumber;
- UInt32 numProcessors;
- UInt32 mainDicSize;
- UInt32 mainDicMethodIndex;
+ CSingleMethodProps() { Init(); }
+ int GetLevel() const { return _level == (UInt32)(UInt32)-1 ? 5 : (int)_level; }
+ HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
};
}
diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp
index a5e0dc0b..cc476fad 100755
--- a/CPP/7zip/Archive/Common/ItemNameUtils.cpp
+++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp
@@ -31,8 +31,8 @@ UString GetOSName2(const UString &name)
if (name.IsEmpty())
return UString();
UString newName = GetOSName(name);
- if (newName[newName.Length() - 1] == kOSDirDelimiter)
- newName.Delete(newName.Length() - 1);
+ if (newName.Back() == kOSDirDelimiter)
+ newName.DeleteBack();
return newName;
}
diff --git a/CPP/7zip/Archive/Common/ParseProperties.cpp b/CPP/7zip/Archive/Common/ParseProperties.cpp
index 5cd849e2..63e4f3ef 100755
--- a/CPP/7zip/Archive/Common/ParseProperties.cpp
+++ b/CPP/7zip/Archive/Common/ParseProperties.cpp
@@ -1,177 +1,3 @@
// ParseProperties.cpp
#include "StdAfx.h"
-
-#include "ParseProperties.h"
-
-#include "Common/StringToInt.h"
-#include "Common/MyCom.h"
-
-HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
-{
- if (prop.vt == VT_UI4)
- {
- if (!name.IsEmpty())
- return E_INVALIDARG;
- resValue = prop.ulVal;
- }
- else if (prop.vt == VT_EMPTY)
- {
- if(!name.IsEmpty())
- {
- const wchar_t *start = name;
- const wchar_t *end;
- UInt64 v = ConvertStringToUInt64(start, &end);
- if (end - start != name.Length())
- return E_INVALIDARG;
- resValue = (UInt32)v;
- }
- }
- else
- return E_INVALIDARG;
- return S_OK;
-}
-
-static const int kLogarithmicSizeLimit = 32;
-static const wchar_t kByteSymbol = L'B';
-static const wchar_t kKiloByteSymbol = L'K';
-static const wchar_t kMegaByteSymbol = L'M';
-
-HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize)
-{
- UString srcString = srcStringSpec;
- srcString.MakeUpper();
-
- const wchar_t *start = srcString;
- const wchar_t *end;
- UInt64 number = ConvertStringToUInt64(start, &end);
- int numDigits = (int)(end - start);
- if (numDigits == 0 || srcString.Length() > numDigits + 1)
- return E_INVALIDARG;
- if (srcString.Length() == numDigits)
- {
- if (number >= kLogarithmicSizeLimit)
- return E_INVALIDARG;
- dicSize = (UInt32)1 << (int)number;
- return S_OK;
- }
- switch (srcString[numDigits])
- {
- case kByteSymbol:
- if (number >= ((UInt64)1 << kLogarithmicSizeLimit))
- return E_INVALIDARG;
- dicSize = (UInt32)number;
- break;
- case kKiloByteSymbol:
- if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10)))
- return E_INVALIDARG;
- dicSize = (UInt32)(number << 10);
- break;
- case kMegaByteSymbol:
- if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20)))
- return E_INVALIDARG;
- dicSize = (UInt32)(number << 20);
- break;
- default:
- return E_INVALIDARG;
- }
- return S_OK;
-}
-
-HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
-{
- if (name.IsEmpty())
- {
- if (prop.vt == VT_UI4)
- {
- UInt32 logDicSize = prop.ulVal;
- if (logDicSize >= 32)
- return E_INVALIDARG;
- resValue = (UInt32)1 << logDicSize;
- return S_OK;
- }
- if (prop.vt == VT_BSTR)
- return ParsePropDictionaryValue(prop.bstrVal, resValue);
- return E_INVALIDARG;
- }
- return ParsePropDictionaryValue(name, resValue);
-}
-
-bool StringToBool(const UString &s, bool &res)
-{
- if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0)
- {
- res = true;
- return true;
- }
- if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0)
- {
- res = false;
- return true;
- }
- return false;
-}
-
-HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value)
-{
- switch(value.vt)
- {
- case VT_EMPTY:
- dest = true;
- return S_OK;
- case VT_BOOL:
- dest = (value.boolVal != VARIANT_FALSE);
- return S_OK;
- /*
- case VT_UI4:
- dest = (value.ulVal != 0);
- break;
- */
- case VT_BSTR:
- return StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG;
- }
- return E_INVALIDARG;
-}
-
-int ParseStringToUInt32(const UString &srcString, UInt32 &number)
-{
- const wchar_t *start = srcString;
- const wchar_t *end;
- UInt64 number64 = ConvertStringToUInt64(start, &end);
- if (number64 > 0xFFFFFFFF)
- {
- number = 0;
- return 0;
- }
- number = (UInt32)number64;
- return (int)(end - start);
-}
-
-HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)
-{
- if (name.IsEmpty())
- {
- switch(prop.vt)
- {
- case VT_UI4:
- numThreads = prop.ulVal;
- break;
- default:
- {
- bool val;
- RINOK(SetBoolProperty(val, prop));
- numThreads = (val ? defaultNumThreads : 1);
- break;
- }
- }
- }
- else
- {
- UInt32 number;
- int index = ParseStringToUInt32(name, number);
- if (index != name.Length())
- return E_INVALIDARG;
- numThreads = number;
- }
- return S_OK;
-}
diff --git a/CPP/7zip/Archive/Common/ParseProperties.h b/CPP/7zip/Archive/Common/ParseProperties.h
index 6f80f634..1038a8c0 100755
--- a/CPP/7zip/Archive/Common/ParseProperties.h
+++ b/CPP/7zip/Archive/Common/ParseProperties.h
@@ -1,18 +1,6 @@
// ParseProperties.h
-#ifndef __PARSEPROPERTIES_H
-#define __PARSEPROPERTIES_H
-
-#include "Common/MyString.h"
-#include "Common/Types.h"
-
-HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
-HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize);
-HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
-
-bool StringToBool(const UString &s, bool &res);
-HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value);
-int ParseStringToUInt32(const UString &srcString, UInt32 &number);
-HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);
+#ifndef __PARSE_PROPERTIES_H
+#define __PARSE_PROPERTIES_H
#endif
diff --git a/CPP/7zip/Archive/DeflateProps.cpp b/CPP/7zip/Archive/DeflateProps.cpp
index 8498e056..ca3dc6f5 100755
--- a/CPP/7zip/Archive/DeflateProps.cpp
+++ b/CPP/7zip/Archive/DeflateProps.cpp
@@ -1,118 +1,3 @@
// DeflateProps.cpp
#include "StdAfx.h"
-
-#include "Windows/PropVariant.h"
-
-#include "Common/ParseProperties.h"
-
-#include "DeflateProps.h"
-
-namespace NArchive {
-
-static const UInt32 kAlgo1 = 0;
-static const UInt32 kAlgo5 = 1;
-
-static const UInt32 kPasses1 = 1;
-static const UInt32 kPasses7 = 3;
-static const UInt32 kPasses9 = 10;
-
-static const UInt32 kFb1 = 32;
-static const UInt32 kFb7 = 64;
-static const UInt32 kFb9 = 128;
-
-void CDeflateProps::Normalize()
-{
- UInt32 level = Level;
- if (level == 0xFFFFFFFF)
- level = 5;
-
- if (Algo == 0xFFFFFFFF)
- Algo = (level >= 5 ?
- kAlgo5 :
- kAlgo1);
-
- if (NumPasses == 0xFFFFFFFF)
- NumPasses =
- (level >= 9 ? kPasses9 :
- (level >= 7 ? kPasses7 :
- kPasses1));
- if (Fb == 0xFFFFFFFF)
- Fb =
- (level >= 9 ? kFb9 :
- (level >= 7 ? kFb7 :
- kFb1));
-}
-
-HRESULT CDeflateProps::SetCoderProperties(ICompressSetCoderProperties *setCoderProperties)
-{
- Normalize();
-
- NWindows::NCOM::CPropVariant props[] =
- {
- Algo,
- NumPasses,
- Fb,
- Mc
- };
- PROPID propIDs[] =
- {
- NCoderPropID::kAlgorithm,
- NCoderPropID::kNumPasses,
- NCoderPropID::kNumFastBytes,
- NCoderPropID::kMatchFinderCycles
- };
- int numProps = sizeof(propIDs) / sizeof(propIDs[0]);
- if (!McDefined)
- numProps--;
- return setCoderProperties->SetCoderProperties(propIDs, props, numProps);
-}
-
-HRESULT CDeflateProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
-{
- Init();
- for (int i = 0; i < numProps; i++)
- {
- UString name = names[i];
- name.MakeUpper();
- if (name.IsEmpty())
- return E_INVALIDARG;
- const PROPVARIANT &prop = values[i];
- if (name[0] == L'X')
- {
- UInt32 a = 9;
- RINOK(ParsePropValue(name.Mid(1), prop, a));
- Level = a;
- }
- else if (name.Left(1) == L"A")
- {
- UInt32 a = kAlgo5;
- RINOK(ParsePropValue(name.Mid(1), prop, a));
- Algo = a;
- }
- else if (name.Left(4) == L"PASS")
- {
- UInt32 a = kPasses9;
- RINOK(ParsePropValue(name.Mid(4), prop, a));
- NumPasses = a;
- }
- else if (name.Left(2) == L"FB")
- {
- UInt32 a = kFb9;
- RINOK(ParsePropValue(name.Mid(2), prop, a));
- Fb = a;
- }
- else if (name.Left(2) == L"MC")
- {
- UInt32 a = 0xFFFFFFFF;
- RINOK(ParsePropValue(name.Mid(2), prop, a));
- Mc = a;
- McDefined = true;
- }
- else
- return E_INVALIDARG;
- }
- return S_OK;
-}
-
-}
diff --git a/CPP/7zip/Archive/DeflateProps.h b/CPP/7zip/Archive/DeflateProps.h
index e05a9d4a..9fd2c2e9 100755
--- a/CPP/7zip/Archive/DeflateProps.h
+++ b/CPP/7zip/Archive/DeflateProps.h
@@ -3,33 +3,4 @@
#ifndef __DEFLATE_PROPS_H
#define __DEFLATE_PROPS_H
-#include "../ICoder.h"
-
-namespace NArchive {
-
-class CDeflateProps
-{
- UInt32 Level;
- UInt32 NumPasses;
- UInt32 Fb;
- UInt32 Algo;
- UInt32 Mc;
- bool McDefined;
-
- void Init()
- {
- Level = NumPasses = Fb = Algo = Mc = 0xFFFFFFFF;
- McDefined = false;
- }
- void Normalize();
-public:
- CDeflateProps() { Init(); }
- bool IsMaximum() const { return Algo > 0; }
-
- HRESULT SetCoderProperties(ICompressSetCoderProperties *setCoderProperties);
- HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
-};
-
-}
-
#endif
diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp
index 7b73bddc..ede6b01b 100755
--- a/CPP/7zip/Archive/GzHandler.cpp
+++ b/CPP/7zip/Archive/GzHandler.cpp
@@ -18,11 +18,10 @@
#include "../Compress/DeflateDecoder.h"
#include "../Compress/DeflateEncoder.h"
+#include "Common/HandlerOut.h"
#include "Common/InStreamWithCRC.h"
#include "Common/OutStreamWithCRC.h"
-#include "DeflateProps.h"
-
#define Get32(p) GetUi32(p)
using namespace NWindows;
@@ -305,7 +304,7 @@ class CHandler:
CMyComPtr<ICompressCoder> _decoder;
NCompress::NDeflate::NDecoder::CCOMCoder *_decoderSpec;
- CDeflateProps _method;
+ CSingleMethodProps _props;
public:
MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)
@@ -321,7 +320,7 @@ public:
}
};
-STATPROPSTG kProps[] =
+static STATPROPSTG const kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidSize, VT_UI8},
@@ -545,7 +544,7 @@ static HRESULT UpdateArchive(
ISequentialOutStream *outStream,
UInt64 unpackSize,
const CItem &newItem,
- CDeflateProps &deflateProps,
+ const CSingleMethodProps &props,
IArchiveUpdateCallback *updateCallback)
{
UInt64 complexity = 0;
@@ -567,7 +566,7 @@ static HRESULT UpdateArchive(
CItem item = newItem;
item.Method = NHeader::NCompressionMethod::kDeflate;
- item.ExtraFlags = deflateProps.IsMaximum() ?
+ item.ExtraFlags = props.GetLevel() >= 7 ?
NHeader::NExtraFlags::kMaximum :
NHeader::NExtraFlags::kFastest;
@@ -577,7 +576,7 @@ static HRESULT UpdateArchive(
NCompress::NDeflate::NEncoder::CCOMCoder *deflateEncoderSpec = new NCompress::NDeflate::NEncoder::CCOMCoder;
CMyComPtr<ICompressCoder> deflateEncoder = deflateEncoderSpec;
- RINOK(deflateProps.SetCoderProperties(deflateEncoderSpec));
+ RINOK(props.SetCoderProps(deflateEncoderSpec, NULL));
RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress));
item.Crc = inStreamSpec->GetCRC();
@@ -616,8 +615,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (prop.vt != VT_FILETIME)
return E_INVALIDARG;
utcTime = prop.filetime;
- if (!NTime::FileTimeToUnixTime(utcTime, newItem.Time))
- return E_INVALIDARG;
+ NTime::FileTimeToUnixTime(utcTime, newItem.Time);
}
{
NCOM::CPropVariant prop;
@@ -658,8 +656,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return E_INVALIDARG;
size = prop.uhVal.QuadPart;
}
-
- return UpdateArchive(outStream, size, newItem, _method, updateCallback);
+ return UpdateArchive(outStream, size, newItem, _props, updateCallback);
}
if (indexInArchive != 0)
@@ -680,7 +677,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
- return _method.SetProperties(names, values, numProps);
+ return _props.SetProperties(names, values, numProps);
}
static IInArchive *CreateArc() { return new CHandler; }
diff --git a/CPP/7zip/Archive/Icons/bz2.ico b/CPP/7zip/Archive/Icons/bz2.ico
index 614e3540..f22abebc 100755
--- a/CPP/7zip/Archive/Icons/bz2.ico
+++ b/CPP/7zip/Archive/Icons/bz2.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/cab.ico b/CPP/7zip/Archive/Icons/cab.ico
index cc2007fc..c96c0f01 100755
--- a/CPP/7zip/Archive/Icons/cab.ico
+++ b/CPP/7zip/Archive/Icons/cab.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/fat.ico b/CPP/7zip/Archive/Icons/fat.ico
index 882753ac..7503d933 100755
--- a/CPP/7zip/Archive/Icons/fat.ico
+++ b/CPP/7zip/Archive/Icons/fat.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/gz.ico b/CPP/7zip/Archive/Icons/gz.ico
index f50d8c08..d402a698 100755
--- a/CPP/7zip/Archive/Icons/gz.ico
+++ b/CPP/7zip/Archive/Icons/gz.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/hfs.ico b/CPP/7zip/Archive/Icons/hfs.ico
index 92a46b81..bf2c1986 100755
--- a/CPP/7zip/Archive/Icons/hfs.ico
+++ b/CPP/7zip/Archive/Icons/hfs.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/iso.ico b/CPP/7zip/Archive/Icons/iso.ico
index 2538e408..b3e3ac2f 100755
--- a/CPP/7zip/Archive/Icons/iso.ico
+++ b/CPP/7zip/Archive/Icons/iso.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/split.ico b/CPP/7zip/Archive/Icons/split.ico
index 79cb089b..65723ff3 100755
--- a/CPP/7zip/Archive/Icons/split.ico
+++ b/CPP/7zip/Archive/Icons/split.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/squashfs.ico b/CPP/7zip/Archive/Icons/squashfs.ico
index 551a7439..b802d942 100755
--- a/CPP/7zip/Archive/Icons/squashfs.ico
+++ b/CPP/7zip/Archive/Icons/squashfs.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Icons/xz.ico b/CPP/7zip/Archive/Icons/xz.ico
index 02707351..bc07a7eb 100755
--- a/CPP/7zip/Archive/Icons/xz.ico
+++ b/CPP/7zip/Archive/Icons/xz.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp
index 4bfb7dc6..f040b033 100755
--- a/CPP/7zip/Archive/Iso/IsoHandler.cpp
+++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp
@@ -172,11 +172,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
int pos = s.ReverseFind(L';');
if (pos >= 0 && pos == s.Length() - 2)
- if (s[s.Length() - 1] == L'1')
+ if (s.Back() == L'1')
s = s.Left(pos);
if (!s.IsEmpty())
- if (s[s.Length() - 1] == L'.')
- s = s.Left(s.Length() - 1);
+ if (s.Back() == L'.')
+ s.DeleteBack();
prop = (const wchar_t *)NItemName::GetOSName2(s);
}
break;
@@ -211,19 +211,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
return S_OK;
UInt64 totalSize = 0;
UInt32 i;
- for(i = 0; i < numItems; i++)
+ for (i = 0; i < numItems; i++)
{
UInt32 index = (allFilesMode ? i : indices[i]);
if (index < (UInt32)_archive.Refs.Size())
{
const CRef &ref = _archive.Refs[index];
const CDir &item = ref.Dir->_subItems[ref.Index];
- totalSize += item.DataLength;
+ if (!item.IsDir())
+ totalSize += item.DataLength;
}
else
- {
totalSize += _archive.GetBootItemSize(index - _archive.Refs.Size());
- }
}
extractCallback->SetTotal(totalSize);
diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp
index 95efc501..194de47e 100755
--- a/CPP/7zip/Archive/LzhHandler.cpp
+++ b/CPP/7zip/Archive/LzhHandler.cpp
@@ -177,47 +177,6 @@ struct CItem
}
};
-struct CItemEx: public CItem
-{
- UInt64 DataPosition;
-};
-
-class CInArchive
-{
- CMyComPtr<IInStream> m_Stream;
- UInt64 m_Position;
-
- HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize);
- HRESULT CheckReadBytes(void *data, UInt32 size);
-public:
- HRESULT Open(IInStream *inStream);
- HRESULT GetNextItem(bool &filled, CItemEx &itemInfo);
- HRESULT Skip(UInt64 numBytes);
-};
-
-HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
-{
- size_t realProcessedSize = size;
- RINOK(ReadStream(m_Stream, data, &realProcessedSize));
- processedSize = (UInt32)realProcessedSize;
- m_Position += processedSize;
- return S_OK;
-}
-
-HRESULT CInArchive::CheckReadBytes(void *data, UInt32 size)
-{
- UInt32 processedSize;
- RINOK(ReadBytes(data, size, processedSize));
- return (processedSize == size) ? S_OK: S_FALSE;
-}
-
-HRESULT CInArchive::Open(IInStream *inStream)
-{
- RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));
- m_Stream = inStream;
- return S_OK;
-}
-
static const Byte *ReadUInt16(const Byte *p, UInt16 &v)
{
v = Get16(p);
@@ -245,13 +204,13 @@ static Byte CalcSum(const Byte *data, size_t size)
return sum;
}
-HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
+static HRESULT GetNextItem(ISequentialInStream *stream, bool &filled, CItem &item)
{
filled = false;
- UInt32 processedSize;
+ size_t processedSize = 2;
Byte startHeader[2];
- RINOK(ReadBytes(startHeader, 2, processedSize))
+ RINOK(ReadStream(stream, startHeader, &processedSize))
if (processedSize == 0)
return S_OK;
if (processedSize == 1)
@@ -261,7 +220,8 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
Byte header[256];
const UInt32 kBasicPartSize = 22;
- RINOK(ReadBytes(header, kBasicPartSize, processedSize));
+ processedSize = kBasicPartSize;
+ RINOK(ReadStream(stream, header, &processedSize));
if (processedSize != kBasicPartSize)
return (startHeader[0] == 0) ? S_OK: S_FALSE;
@@ -284,8 +244,7 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
headerSize = startHeader[0];
if (headerSize < kBasicPartSize)
return S_FALSE;
- UInt32 remain = headerSize - kBasicPartSize;
- RINOK(CheckReadBytes(header + kBasicPartSize, remain));
+ RINOK(ReadStream_FALSE(stream, header + kBasicPartSize, headerSize - kBasicPartSize));
if (startHeader[1] != CalcSum(header, headerSize))
return S_FALSE;
size_t nameLength = *p++;
@@ -294,13 +253,13 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
p = ReadString(p, nameLength, item.Name);
}
else
- headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8);
+ headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8);
p = ReadUInt16(p, item.CRC);
if (item.Level != 0)
{
if (item.Level == 2)
{
- RINOK(CheckReadBytes(header + kBasicPartSize, 2));
+ RINOK(ReadStream_FALSE(stream, header + kBasicPartSize, 2));
}
if ((size_t)(p - header) + 3 > headerSize)
return S_FALSE;
@@ -317,39 +276,30 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
return S_FALSE;
item.PackSize -= nextSize;
}
+ if (item.Extensions.Size() >= (1 << 8))
+ return S_FALSE;
CExtension ext;
- RINOK(CheckReadBytes(&ext.Type, 1))
+ RINOK(ReadStream_FALSE(stream, &ext.Type, 1))
nextSize -= 3;
ext.Data.SetCapacity(nextSize);
- RINOK(CheckReadBytes((Byte *)ext.Data, nextSize))
+ RINOK(ReadStream_FALSE(stream, (Byte *)ext.Data, nextSize))
item.Extensions.Add(ext);
Byte hdr2[2];
- RINOK(CheckReadBytes(hdr2, 2));
+ RINOK(ReadStream_FALSE(stream, hdr2, 2));
ReadUInt16(hdr2, nextSize);
}
}
- item.DataPosition = m_Position;
filled = true;
return S_OK;
}
-HRESULT CInArchive::Skip(UInt64 numBytes)
-{
- UInt64 newPostion;
- RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion));
- m_Position += numBytes;
- if (m_Position != newPostion)
- return E_FAIL;
- return S_OK;
-}
-
struct COsPair
{
Byte Id;
const char *Name;
};
-static COsPair g_OsPairs[] =
+static const COsPair g_OsPairs[] =
{
{ 0, "MS-DOS" },
{ 'M', "MS-DOS" },
@@ -380,7 +330,7 @@ static const char *GetOS(Byte osId)
return kUnknownOS;
}
-static STATPROPSTG kProps[] =
+static const STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL},
@@ -393,6 +343,11 @@ static STATPROPSTG kProps[] =
{ NULL, kpidHostOS, VT_BSTR}
};
+static const STATPROPSTG kArcProps[] =
+{
+ { NULL, kpidPhySize, VT_UI8}
+};
+
class CCRC
{
UInt16 _value;
@@ -479,12 +434,19 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *pro
return result;
}
+struct CItemEx: public CItem
+{
+ UInt64 DataPosition;
+};
+
class CHandler:
public IInArchive,
public CMyUnknownImp
{
CObjectVector<CItemEx> _items;
CMyComPtr<IInStream> _stream;
+ UInt64 _phySize;
+ AString _errorMessage;
public:
MY_UNKNOWN_IMP1(IInArchive)
INTERFACE_IInArchive(;)
@@ -492,7 +454,7 @@ public:
};
IMP_IInArchive_Props
-IMP_IInArchive_ArcProps_NO
+IMP_IInArchive_ArcProps
CHandler::CHandler() {}
@@ -502,6 +464,18 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK;
}
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+ NCOM::CPropVariant prop;
+ switch(propID)
+ {
+ case kpidPhySize: prop = _phySize; break;
+ case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
+ }
+ prop.Detach(value);
+ return S_OK;
+}
+
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
@@ -514,8 +488,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP));
if (!s.IsEmpty())
{
- if (s[s.Length() - 1] == WCHAR_PATH_SEPARATOR)
- s.Delete(s.Length() - 1);
+ if (s.Back() == WCHAR_PATH_SEPARATOR)
+ s.DeleteBack();
prop = s;
}
break;
@@ -567,32 +541,43 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
try
{
_items.Clear();
- CInArchive archive;
UInt64 endPos = 0;
bool needSetTotal = true;
- if (callback != NULL)
- {
- RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));
- RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
- }
+ RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));
+ RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
- RINOK(archive.Open(stream));
+ _phySize = 0;
for (;;)
{
CItemEx item;
bool filled;
- HRESULT result = archive.GetNextItem(filled, item);
+ HRESULT result = GetNextItem(stream, filled, item);
+ RINOK(stream->Seek(0, STREAM_SEEK_CUR, &item.DataPosition));
if (result == S_FALSE)
- return S_FALSE;
+ {
+ _errorMessage = "Incorrect header";
+ break;
+ }
+
if (result != S_OK)
return S_FALSE;
+ _phySize = item.DataPosition;
if (!filled)
break;
_items.Add(item);
- archive.Skip(item.PackSize);
- if (callback != NULL)
+
+ UInt64 newPostion;
+ RINOK(stream->Seek(item.PackSize, STREAM_SEEK_CUR, &newPostion));
+ if (newPostion > endPos)
+ {
+ _phySize = endPos;
+ _errorMessage = "Unexpected end of archive";
+ break;
+ }
+ _phySize = newPostion;
+ if (callback)
{
if (needSetTotal)
{
@@ -622,6 +607,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
STDMETHODIMP CHandler::Close()
{
+ _errorMessage.Empty();
_items.Clear();
_stream.Release();
return S_OK;
diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp
index a83e6a1a..778c2fd8 100755
--- a/CPP/7zip/Archive/LzmaHandler.cpp
+++ b/CPP/7zip/Archive/LzmaHandler.cpp
@@ -296,7 +296,8 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal
RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos));
_packSize = endPos - _startPosition;
_packSizeDefined = true;
-
+ if (_packSize >= 24 && _header.Size == 0 && _header.FilterID == 0 && _header.LzmaProps[0] == 0)
+ return S_FALSE;
_stream = inStream;
_seqStream = inStream;
return S_OK;
diff --git a/CPP/7zip/Archive/MubHandler.cpp b/CPP/7zip/Archive/MubHandler.cpp
index da4df24c..5ebda099 100755
--- a/CPP/7zip/Archive/MubHandler.cpp
+++ b/CPP/7zip/Archive/MubHandler.cpp
@@ -15,7 +15,7 @@
#include "../Compress/CopyCoder.h"
-#define Get32(p) GetBe32(p)
+static UInt32 Get32(const Byte *p, int be) { if (be) return GetBe32(p); return GetUi32(p); }
namespace NArchive {
namespace NMub {
@@ -116,8 +116,16 @@ HRESULT CHandler::Open2(IInStream *stream)
RINOK(ReadStream(stream, buf, &processed));
if (processed < kHeaderSize)
return S_FALSE;
- UInt32 num = Get32(buf + 4);
- if (Get32(buf) != 0xCAFEBABE || num > kNumFilesMax || processed < kHeaderSize + num * kRecordSize)
+
+ bool be;
+ switch (GetBe32(buf))
+ {
+ case 0xCAFEBABE: be = true; break;
+ case 0xB9FAF10E: be = false; break;
+ default: return S_FALSE;
+ }
+ UInt32 num = Get32(buf + 4, be);
+ if (num > kNumFilesMax || processed < kHeaderSize + num * kRecordSize)
return S_FALSE;
UInt64 endPosMax = kHeaderSize;
for (UInt32 i = 0; i < num; i++)
@@ -125,11 +133,11 @@ HRESULT CHandler::Open2(IInStream *stream)
const Byte *p = buf + kHeaderSize + i * kRecordSize;
CItem &sb = _items[i];
sb.IsTail = false;
- sb.Type = Get32(p);
- sb.SubType = Get32(p + 4);
- sb.Offset = Get32(p + 8);
- sb.Size = Get32(p + 12);
- sb.Align = Get32(p + 16);
+ sb.Type = Get32(p, be);
+ sb.SubType = Get32(p + 4, be);
+ sb.Offset = Get32(p + 8, be);
+ sb.Size = Get32(p + 12, be);
+ sb.Align = Get32(p + 16, be);
if ((sb.Type & ~MACH_TYPE_ABI64) >= 0x100 ||
(sb.SubType & ~MACH_SUBTYPE_ABI64) >= 0x100 ||
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h
index 87ae3f1c..7ca719e4 100755
--- a/CPP/7zip/Archive/Nsis/NsisIn.h
+++ b/CPP/7zip/Archive/Nsis/NsisIn.h
@@ -87,7 +87,7 @@ struct CItem
else
s = MultiByteToUnicodeString(PrefixA);
if (s.Length() > 0)
- if (s[s.Length() - 1] != L'\\')
+ if (s.Back() != L'\\')
s += L'\\';
if (unicode)
s += NameU;
diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp
index c64067aa..e5946969 100755
--- a/CPP/7zip/Archive/PeHandler.cpp
+++ b/CPP/7zip/Archive/PeHandler.cpp
@@ -631,7 +631,7 @@ enum
// kpidBaseOfData32,
};
-STATPROPSTG kArcProps[] =
+static const STATPROPSTG kArcProps[] =
{
{ NULL, kpidCpu, VT_BSTR},
{ NULL, kpidBit64, VT_BOOL},
@@ -662,7 +662,7 @@ STATPROPSTG kArcProps[] =
// { L"Base Of Data", kpidBaseOfData32, VT_UI8},
};
-STATPROPSTG kProps[] =
+static const STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidSize, VT_UI8},
@@ -1749,4 +1749,335 @@ static CArcInfo g_ArcInfo =
REGISTER_ARC(Pe)
-}}
+}
+
+
+
+
+namespace NTe {
+
+// Terse Executable (TE) image
+
+/*
+struct CDataDir
+{
+ UInt32 Va;
+ UInt32 Size;
+};
+*/
+
+static const UInt32 kHeaderSize = 40;
+
+static bool FindValue(const CUInt32PCharPair *pairs, unsigned num, UInt32 value)
+{
+ for (unsigned i = 0; i < num; i++)
+ if (pairs[i].Value == value)
+ return true;
+ return false;
+}
+
+#define MY_FIND_VALUE(pairs, value) FindValue(pairs, sizeof(pairs) / sizeof(pairs[0]), value)
+
+struct CHeader
+{
+ UInt16 Machine;
+ Byte NumSections;
+ Byte SubSystem;
+ UInt16 StrippedSize;
+ /*
+ UInt32 AddressOfEntryPoint;
+ UInt32 BaseOfCode;
+ UInt64 ImageBase;
+ CDataDir DataDir[2]; // base relocation and debug directory
+ */
+
+ UInt32 ConvertPa(UInt32 pa) const { return pa - StrippedSize + kHeaderSize; }
+
+ bool Parse(const Byte *p)
+ {
+ if (p[0] != 'V' || p[1] != 'Z')
+ return false;
+ Machine = Get16(p + 2);
+ NumSections = p[4];
+ SubSystem = p[5];
+ StrippedSize = Get16(p + 6);
+ /*
+ AddressOfEntryPoint = Get32(p + 8);
+ BaseOfCode = Get32(p + 12);
+ ImageBase = Get64(p + 16);
+ for (int i = 0; i < 2; i++)
+ {
+ const Byte *p2 = p + 24 + i * 8;
+ DataDir[i].Va = Get32(p2);
+ DataDir[i].Size = Get32(p2 + 4);
+ }
+ */
+ return NumSections <= 64 &&
+ MY_FIND_VALUE(NPe::g_MachinePairs, Machine) &&
+ MY_FIND_VALUE(NPe::g_SubSystems, SubSystem);
+ }
+};
+
+struct CSection
+{
+ Byte Name[8];
+
+ // UInt32 VSize;
+ UInt32 Va;
+ UInt32 PSize;
+ UInt32 Pa;
+ UInt32 Flags;
+ // UInt16 NumRelocs;
+
+ void Parse(const Byte *p)
+ {
+ memcpy(Name, p, 8);
+ // VSize = Get32(p + 8);
+ Va = Get32(p + 12);
+ PSize = Get32(p + 16);
+ Pa = Get32(p + 20);
+ // NumRelocs = Get16(p + 32);
+ Flags = Get32(p + 36);
+ }
+
+ bool Check() const { return (PSize + Pa > Pa); }
+
+ void UpdateTotalSize(UInt32 &totalSize)
+ {
+ UInt32 t = Pa + PSize;
+ if (t > totalSize)
+ totalSize = t;
+ }
+};
+
+class CHandler:
+ public IInArchive,
+ public IInArchiveGetStream,
+ public CMyUnknownImp
+{
+ UInt32 _totalSize;
+ CMyComPtr<IInStream> _stream;
+ CObjectVector<CSection> _items;
+ CHeader _h;
+ UInt64 _fileSize;
+
+ HRESULT Open2(IInStream *stream);
+public:
+ MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+ INTERFACE_IInArchive(;)
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+};
+
+static const STATPROPSTG kProps[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ { NULL, kpidSize, VT_UI4},
+ { NULL, kpidPackSize, VT_UI4},
+ { NULL, kpidCharacts, VT_BSTR},
+ { NULL, kpidOffset, VT_UI4},
+ { NULL, kpidVa, VT_UI8}
+};
+
+enum
+{
+ kpidSubSystem
+ // , kpidImageBase
+};
+
+static const STATPROPSTG kArcProps[] =
+{
+ { NULL, kpidPhySize, VT_UI4},
+ // { NULL, kpidHeadersSize, VT_UI4},
+ { NULL, kpidCpu, VT_BSTR},
+ { L"Subsystem", kpidSubSystem, VT_BSTR},
+ // { L"Image Base", kpidImageBase, VT_UI8}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_WITH_NAME
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NCOM::CPropVariant prop;
+ switch(propID)
+ {
+ case kpidPhySize: prop = _totalSize; break;
+ case kpidCpu: PAIR_TO_PROP(NPe::g_MachinePairs, _h.Machine, prop); break;
+ case kpidSubSystem: PAIR_TO_PROP(NPe::g_SubSystems, _h.SubSystem, prop); break;
+ /*
+ case kpidImageBase: prop = _h.ImageBase; break;
+ case kpidAddressOfEntryPoint: prop = _h.AddressOfEntryPoint; break;
+ case kpidBaseOfCode: prop = _h.BaseOfCode; break;
+ */
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NCOM::CPropVariant prop;
+ {
+ const CSection &item = _items[index];
+ switch(propID)
+ {
+ case kpidPath: StringToProp(NPe::GetName(item.Name), prop); break;
+ case kpidSize:
+ case kpidPackSize: prop = (UInt64)item.PSize; break;
+ case kpidOffset: prop = item.Pa; break;
+ case kpidVa: prop = item.Va; break;
+ case kpidCharacts: FLAGS_TO_PROP(NPe::g_SectFlags, item.Flags, prop); break;
+ }
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+HRESULT CHandler::Open2(IInStream *stream)
+{
+ Byte h[kHeaderSize];
+ RINOK(ReadStream_FALSE(stream, h, kHeaderSize));
+ if (!_h.Parse(h))
+ return S_FALSE;
+
+ CByteBuffer buf;
+ UInt32 headerSize = NPe::kSectionSize * _h.NumSections;
+ buf.SetCapacity(headerSize);
+ RINOK(ReadStream_FALSE(stream, buf, headerSize));
+
+ _totalSize = kHeaderSize + headerSize;
+
+ for (UInt32 i = 0; i < headerSize; i += NPe::kSectionSize)
+ {
+ CSection sect;
+ sect.Parse(buf + i);
+ sect.Pa = _h.ConvertPa(sect.Pa);
+ _items.Add(sect);
+ sect.UpdateTotalSize(_totalSize);
+ if (!sect.Check())
+ return S_FALSE;
+ }
+
+ return stream->Seek(0, STREAM_SEEK_END, &_fileSize);
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream,
+ const UInt64 * /* maxCheckStartPosition */,
+ IArchiveOpenCallback * /* openArchiveCallback */)
+{
+ COM_TRY_BEGIN
+ Close();
+ try
+ {
+ if (Open2(inStream) != S_OK)
+ return S_FALSE;
+ _stream = inStream;
+ }
+ catch(...) { return S_FALSE; }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ _stream.Release();
+ _items.Clear();
+ _totalSize = 0;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = _items.Size();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool allFilesMode = (numItems == (UInt32)-1);
+ if (allFilesMode)
+ numItems = _items.Size();
+ if (numItems == 0)
+ return S_OK;
+ UInt64 totalSize = 0;
+ UInt32 i;
+ for (i = 0; i < numItems; i++)
+ totalSize += _items[allFilesMode ? i : indices[i]].PSize;
+ extractCallback->SetTotal(totalSize);
+
+ UInt64 currentTotalSize = 0;
+
+ NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+ CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(extractCallback, false);
+
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream(streamSpec);
+ streamSpec->SetStream(_stream);
+
+ for (i = 0; i < numItems; i++)
+ {
+ lps->InSize = lps->OutSize = currentTotalSize;
+ RINOK(lps->SetCur());
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode = testMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract;
+ UInt32 index = allFilesMode ? i : indices[i];
+ const CSection &item = _items[index];
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+ currentTotalSize += item.PSize;
+
+ if (!testMode && !realOutStream)
+ continue;
+ RINOK(extractCallback->PrepareOperation(askMode));
+ int res = NExtract::NOperationResult::kDataError;
+ if (item.Pa <= _fileSize)
+ {
+ if (testMode)
+ {
+ if (item.Pa + item.PSize <= _fileSize)
+ res = NExtract::NOperationResult::kOK;
+ }
+ else
+ {
+ RINOK(_stream->Seek(item.Pa, STREAM_SEEK_SET, NULL));
+ streamSpec->Init(item.PSize);
+ RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
+ if (copyCoderSpec->TotalSize == item.PSize)
+ res = NExtract::NOperationResult::kOK;
+ }
+ }
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(res));
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+ COM_TRY_BEGIN
+ const CSection &item = _items[index];
+ return CreateLimitedInStream(_stream, item.Pa, item.PSize, stream);
+ COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+ { L"TE", L"te", 0, 0xCF, { 'V', 'Z' }, 2, false, CreateArc, 0 };
+
+REGISTER_ARC(TE)
+
+}
+}
diff --git a/CPP/7zip/Archive/Rar/RarIn.cpp b/CPP/7zip/Archive/Rar/RarIn.cpp
index e4c23752..a7d018ff 100755
--- a/CPP/7zip/Archive/Rar/RarIn.cpp
+++ b/CPP/7zip/Archive/Rar/RarIn.cpp
@@ -112,7 +112,7 @@ HRESULT CInArchive::Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit
(UInt32)Get16(buf) != (CrcCalc(buf + 2, headerSize - 2) & 0xFFFF))
return S_FALSE;
- size_t commentSize = blockSize - headerSize;
+ size_t commentSize = blockSize - headerSize;
_comment.SetCapacity(commentSize);
RINOK(ReadStream_FALSE(stream, _comment, commentSize));
AddToSeekValue(commentSize);
diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp
index 2cc1219a..efaffed1 100755
--- a/CPP/7zip/Archive/SquashfsHandler.cpp
+++ b/CPP/7zip/Archive/SquashfsHandler.cpp
@@ -5,6 +5,7 @@
#include "../../../C/7zCrc.h"
#include "../../../C/Alloc.h"
#include "../../../C/CpuArch.h"
+#include "../../../C/Xz.h"
#include "Common/ComTry.h"
#include "Common/IntToString.h"
@@ -13,6 +14,7 @@
#include "Windows/PropVariantUtils.h"
#include "Windows/Time.h"
+#include "../Common/CWrappers.h"
#include "../Common/LimitedStreams.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
@@ -26,6 +28,10 @@
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);
@@ -62,13 +68,15 @@ static const UInt32 kSignature32_LZ = 0x71736873;
#define kMethod_ZLIB 1
#define kMethod_LZMA 2
#define kMethod_LZO 3
+#define kMethod_XZ 4
static const char *k_Methods[] =
{
"Unknown",
"ZLIB",
"LZMA",
- "LZO"
+ "LZO",
+ "XZ"
};
static const UInt32 kMetadataBlockSizeLog = 13;
@@ -860,6 +868,8 @@ class CHandler:
NCompress::NZlib::CDecoder *_zlibDecoderSpec;
CMyComPtr<ICompressCoder> _zlibDecoder;
+ CXzUnpacker _xz;
+
CByteBuffer _inputBuffer;
CDynBufSeqOutStream *_dynOutStreamSpec;
@@ -886,6 +896,11 @@ class CHandler:
public:
CHandler();
+ ~CHandler()
+ {
+ XzUnpacker_Free(&_xz);
+ }
+
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
@@ -895,6 +910,8 @@ public:
CHandler::CHandler()
{
+ XzUnpacker_Construct(&_xz, &g_Alloc);
+
_limitedInStreamSpec = new CLimitedSequentialInStream;
_limitedInStream = _limitedInStreamSpec;
@@ -1104,33 +1121,16 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
RINOK(_stream->Seek(-1, STREAM_SEEK_CUR, NULL));
}
- if (method == kMethod_LZO)
+ if (method == kMethod_ZLIB)
{
- if (_inputBuffer.GetCapacity() < inSize)
- {
- _inputBuffer.Free();
- _inputBuffer.SetCapacity(inSize);
- }
- RINOK(ReadStream_FALSE(_stream, _inputBuffer, inSize));
-
- Byte *dest = outBuf;
- if (!outBuf)
+ if (!_zlibDecoder)
{
- dest = _dynOutStreamSpec->GetBufPtrForWriting(outSizeMax);
- if (!dest)
- return E_OUTOFMEMORY;
+ _zlibDecoderSpec = new NCompress::NZlib::CDecoder();
+ _zlibDecoder = _zlibDecoderSpec;
}
- SizeT destLen = outSizeMax, srcLen = inSize;
- RINOK(LzoDecode(dest, &destLen, _inputBuffer, &srcLen));
- if (inSize != srcLen)
+ RINOK(_zlibDecoder->Code(_limitedInStream, outStream, NULL, NULL, NULL));
+ if (inSize != _zlibDecoderSpec->GetInputProcessedSize())
return S_FALSE;
- if (outBuf)
- {
- *outBufWasWritten = true;
- *outBufWasWrittenSize = (UInt32)destLen;
- }
- else
- _dynOutStreamSpec->UpdateSize(destLen);
}
else if (method == kMethod_LZMA)
{
@@ -1153,14 +1153,44 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
}
else
{
- if (!_zlibDecoder)
+ if (_inputBuffer.GetCapacity() < inSize)
{
- _zlibDecoderSpec = new NCompress::NZlib::CDecoder();
- _zlibDecoder = _zlibDecoderSpec;
+ _inputBuffer.Free();
+ _inputBuffer.SetCapacity(inSize);
}
- RINOK(_zlibDecoder->Code(_limitedInStream, outStream, NULL, NULL, NULL));
- if (inSize != _zlibDecoderSpec->GetInputProcessedSize())
+ RINOK(ReadStream_FALSE(_stream, _inputBuffer, inSize));
+
+ Byte *dest = outBuf;
+ if (!outBuf)
+ {
+ dest = _dynOutStreamSpec->GetBufPtrForWriting(outSizeMax);
+ if (!dest)
+ return E_OUTOFMEMORY;
+ }
+ SizeT destLen = outSizeMax, srcLen = inSize;
+ if (method == kMethod_LZO)
+ {
+ RINOK(LzoDecode(dest, &destLen, _inputBuffer, &srcLen));
+ }
+ else
+ {
+ ECoderStatus status;
+ XzUnpacker_Init(&_xz);
+ SRes res = XzUnpacker_Code(&_xz, dest, &destLen, _inputBuffer, &srcLen, LZMA_FINISH_END, &status);
+ if (res != 0)
+ return SResToHRESULT(res);
+ if (status != CODER_STATUS_NEEDS_MORE_INPUT || !XzUnpacker_IsStreamWasFinished(&_xz))
+ return S_FALSE;
+ }
+ if (inSize != srcLen)
return S_FALSE;
+ if (outBuf)
+ {
+ *outBufWasWritten = true;
+ *outBufWasWrittenSize = (UInt32)destLen;
+ }
+ else
+ _dynOutStreamSpec->UpdateSize(destLen);
}
return S_OK;
}
@@ -1418,6 +1448,7 @@ HRESULT CHandler::Open2(IInStream *inStream)
case kMethod_ZLIB:
case kMethod_LZMA:
case kMethod_LZO:
+ case kMethod_XZ:
break;
default:
return E_NOTIMPL;
@@ -2072,15 +2103,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (inStream)
{
HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
- if (hres != S_OK && hres != S_FALSE)
+ if (hres == S_OK)
{
- RINOK(hres);
+ if (copyCoderSpec->TotalSize == unpackSize)
+ res = NExtract::NOperationResult::kOK;
+ }
+ else if (hres == E_NOTIMPL)
+ {
+ res = NExtract::NOperationResult::kUnSupportedMethod;
}
- if (copyCoderSpec->TotalSize == unpackSize && hres == S_OK)
- res = NExtract::NOperationResult::kOK;
- else
+ else if(hres != S_FALSE)
{
- res = res;
+ RINOK(hres);
}
}
}
diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp
index dfc0326d..d7d9537e 100755
--- a/CPP/7zip/Archive/SwfHandler.cpp
+++ b/CPP/7zip/Archive/SwfHandler.cpp
@@ -21,8 +21,7 @@
#include "../Compress/ZlibEncoder.h"
#include "Common/DummyOutStream.h"
-
-#include "DeflateProps.h"
+#include "Common/HandlerOut.h"
using namespace NWindows;
@@ -69,7 +68,7 @@ class CHandler:
CMyComPtr<ISequentialInStream> _seqStream;
CMyComPtr<IInStream> _stream;
- CDeflateProps _method;
+ CSingleMethodProps _props;
public:
MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)
@@ -206,7 +205,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
static HRESULT UpdateArchive(ISequentialOutStream *outStream,
- UInt64 size, CDeflateProps &deflateProps,
+ UInt64 size, const CSingleMethodProps &props,
IArchiveUpdateCallback *updateCallback)
{
UInt64 complexity = 0;
@@ -234,7 +233,7 @@ static HRESULT UpdateArchive(ISequentialOutStream *outStream,
NCompress::NZlib::CEncoder *encoderSpec = new NCompress::NZlib::CEncoder;
CMyComPtr<ICompressCoder> encoder = encoderSpec;
encoderSpec->Create();
- RINOK(deflateProps.SetCoderProperties(encoderSpec->DeflateEncoderSpec));
+ RINOK(props.SetCoderProps(encoderSpec->DeflateEncoderSpec, NULL));
RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, progress));
if (encoderSpec->GetInputProcessedSize() + kHeaderSize != size)
return E_INVALIDARG;
@@ -284,7 +283,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return E_INVALIDARG;
size = prop.uhVal.QuadPart;
}
- return UpdateArchive(outStream, size, _method, updateCallback);
+ return UpdateArchive(outStream, size, _props, updateCallback);
}
if (indexInArchive != 0)
@@ -304,7 +303,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
- return _method.SetProperties(names, values, numProps);
+ return _props.SetProperties(names, values, numProps);
}
static IInArchive *CreateArc() { return new CHandler; }
diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp
index 4db0cae8..251afdb7 100755
--- a/CPP/7zip/Archive/Tar/TarHandler.cpp
+++ b/CPP/7zip/Archive/Tar/TarHandler.cpp
@@ -64,6 +64,8 @@ HRESULT CHandler::ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &
{
item.HeaderPos = _phySize;
RINOK(ReadItem(stream, filled, item, _errorMessage));
+ if (filled && item.IsSparse())
+ _isSparse = true;
_phySize += item.HeaderSize;
_headersSize += item.HeaderSize;
return S_OK;
@@ -87,7 +89,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
break;
_items.Add(item);
- RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &_phySize));
+ RINOK(stream->Seek(item.GetPackSizeAligned(), STREAM_SEEK_CUR, &_phySize));
if (_phySize > endPos)
{
_errorMessage = kUnexpectedEnd;
@@ -162,6 +164,7 @@ STDMETHODIMP CHandler::Close()
_headersSize = 0;
_curIndex = 0;
_latestIsRead = false;
+ _isSparse = false;
_items.Clear();
_seqStream.Release();
_stream.Release();
@@ -186,7 +189,7 @@ HRESULT CHandler::SkipTo(UInt32 index)
{
if (_latestIsRead)
{
- UInt64 packSize = _latestItem.GetPackSize();
+ UInt64 packSize = _latestItem.GetPackSizeAligned();
RINOK(copyCoderSpec->Code(_seqStream, NULL, &packSize, &packSize, NULL));
_phySize += copyCoderSpec->TotalSize;
if (copyCoderSpec->TotalSize != packSize)
@@ -241,13 +244,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidPath: prop = NItemName::GetOSName2(TarStringToUnicode(item->Name)); break;
case kpidIsDir: prop = item->IsDir(); break;
case kpidSize: prop = item->GetUnpackSize(); break;
- case kpidPackSize: prop = item->GetPackSize(); break;
+ case kpidPackSize: prop = item->GetPackSizeAligned(); break;
case kpidMTime:
if (item->MTime != 0)
{
FILETIME ft;
- NTime::UnixTimeToFileTime(item->MTime, ft);
- prop = ft;
+ if (NTime::UnixTime64ToFileTime(item->MTime, ft))
+ prop = ft;
}
break;
case kpidPosixAttrib: prop = item->Mode; break;
@@ -319,7 +322,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
UInt64 unpackSize = item->GetUnpackSize();
totalSize += unpackSize;
- totalPackSize += item->GetPackSize();
+ totalPackSize += item->GetPackSizeAligned();
if (item->IsDir())
{
RINOK(extractCallback->PrepareOperation(askMode));
@@ -340,18 +343,26 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
realOutStream.Release();
outStreamSpec->Init(skipMode ? 0 : unpackSize, true);
- if (item->IsLink())
- {
- RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Length()));
- }
+ Int32 opRes = NExtract::NOperationResult::kOK;
+ if (item->IsSparse())
+ opRes = NExtract::NOperationResult::kUnSupportedMethod;
else
{
- if (!seqMode)
+ if (item->IsLink())
+ {
+ RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Length()));
+ }
+ else
{
- RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL));
+ if (!seqMode)
+ {
+ RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL));
+ }
+ streamSpec->Init(item->GetPackSizeAligned());
+ RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
}
- streamSpec->Init(item->GetPackSize());
- RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+ if (outStreamSpec->GetRem() != 0)
+ opRes = NExtract::NOperationResult::kDataError;
}
if (seqMode)
{
@@ -359,9 +370,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
_curIndex++;
}
outStreamSpec->ReleaseStream();
- RINOK(extractCallback->SetOperationResult(outStreamSpec->GetRem() == 0 ?
- NExtract::NOperationResult::kOK:
- NExtract::NOperationResult::kDataError));
+ RINOK(extractCallback->SetOperationResult(opRes));
}
return S_OK;
COM_TRY_END
@@ -371,6 +380,8 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{
COM_TRY_BEGIN
const CItemEx &item = _items[index];
+ if (item.IsSparse())
+ return E_NOTIMPL;
if (item.IsLink())
{
CBufInStream *streamSpec = new CBufInStream;
@@ -379,7 +390,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
*stream = streamTemp.Detach();
return S_OK;
}
- return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream);
+ return CreateLimitedInStream(_stream, item.GetDataPosition(), item.PackSize, stream);
COM_TRY_END
}
diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h
index b1967061..9251edf6 100755
--- a/CPP/7zip/Archive/Tar/TarHandler.h
+++ b/CPP/7zip/Archive/Tar/TarHandler.h
@@ -32,6 +32,7 @@ class CHandler:
UInt64 _headersSize;
bool _phySizeDefined;
AString _errorMessage;
+ bool _isSparse;
NCompress::CCopyCoder *copyCoderSpec;
CMyComPtr<ICompressCoder> copyCoder;
diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
index ffdf2b13..b0ec63d1 100755
--- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
+++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
@@ -37,7 +37,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
IArchiveUpdateCallback *callback)
{
COM_TRY_BEGIN
- if ((_stream && !_errorMessage.IsEmpty()) || _seqStream)
+ if ((_stream && (!_errorMessage.IsEmpty() || _isSparse)) || _seqStream)
return E_NOTIMPL;
CObjectVector<CUpdateItem> updateItems;
for (UInt32 i = 0; i < numItems; i++)
@@ -81,11 +81,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidMTime, &prop));
if (prop.vt == VT_EMPTY)
- ui.Time = 0;
+ ui.MTime = 0;
else if (prop.vt != VT_FILETIME)
return E_INVALIDARG;
- else if (!NTime::FileTimeToUnixTime(prop.filetime, ui.Time))
- ui.Time = 0;
+ else
+ ui.MTime = NTime::FileTimeToUnixTime64(prop.filetime);
}
{
NCOM::CPropVariant prop;
diff --git a/CPP/7zip/Archive/Tar/TarHeader.h b/CPP/7zip/Archive/Tar/TarHeader.h
index 0b78bdc2..a212ae03 100755
--- a/CPP/7zip/Archive/Tar/TarHeader.h
+++ b/CPP/7zip/Archive/Tar/TarHeader.h
@@ -84,6 +84,7 @@ namespace NFileHeader
Each file name is terminated by a null + an additional null after
the last file name. */
+ const char kSparse = 'S';
}
// Further link types may be defined later.
diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp
index 5ceaa509..b6e5e0f5 100755
--- a/CPP/7zip/Archive/Tar/TarIn.cpp
+++ b/CPP/7zip/Archive/Tar/TarIn.cpp
@@ -63,6 +63,31 @@ static void ReadString(const char *s, int size, AString &result)
result = temp;
}
+static bool ParseInt64(const char *p, Int64 &val)
+{
+ UInt32 h = GetBe32(p);
+ val = GetBe64(p + 4);
+ if (h == (UInt32)1 << 31)
+ return ((val >> 63) & 1) == 0;
+ if (h == (UInt32)(Int32)-1)
+ return ((val >> 63) & 1) != 0;
+ UInt64 uv;
+ bool res = OctalToNumber(p, 12, uv);
+ val = uv;
+ return res;
+}
+
+static bool ParseSize(const char *p, UInt64 &val)
+{
+ if (GetBe32(p) == (UInt32)1 << 31)
+ {
+ // GNU extension
+ val = GetBe64(p + 4);
+ return ((val >> 63) & 1) == 0;
+ }
+ return OctalToNumber(p, 12, val);
+}
+
static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error)
{
char buf[NFileHeader::kRecordSize];
@@ -105,17 +130,10 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8;
if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8;
- if (GetBe32(p) == (UInt32)1 << 31)
- {
- // GNU extension
- item.Size = GetBe64(p + 4);
- }
- else
- {
- RIF(OctalToNumber(p, 12, item.Size));
- }
+ RIF(ParseSize(p, item.PackSize));
+ item.Size = item.PackSize;
p += 12;
- RIF(OctalToNumber32(p, 12, item.MTime)); p += 12;
+ RIF(ParseInt64(p, item.MTime)); p += 12;
UInt32 checkSum;
RIF(OctalToNumber32(p, 8, checkSum));
@@ -141,7 +159,36 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
item.Name = prefix + AString('/') + item.Name;
if (item.LinkFlag == NFileHeader::NLinkFlag::kLink)
+ {
+ item.PackSize = 0;
item.Size = 0;
+ }
+ else if (item.LinkFlag == NFileHeader::NLinkFlag::kSparse)
+ {
+ if (buf[482] != 0)
+ return S_FALSE;
+ RIF(ParseSize(buf + 483, item.Size));
+ p = buf + 386;
+ UInt64 min = 0;
+ for (int i = 0; i < 4; i++, p += 24)
+ {
+ if (GetBe32(p) == 0)
+ break;
+ CSparseBlock sb;
+ RIF(ParseSize(p, sb.Offset));
+ RIF(ParseSize(p + 12, sb.Size));
+ item.SparseBlocks.Add(sb);
+ if (sb.Offset < min || sb.Offset > item.Size)
+ return S_FALSE;
+ if ((sb.Offset & 0x1FF) != 0 || (sb.Size & 0x1FF) != 0)
+ return S_FALSE;
+ min = sb.Offset + sb.Size;
+ if (min < sb.Offset)
+ return S_FALSE;
+ }
+ if (min > item.Size)
+ return S_FALSE;
+ }
UInt32 checkSumReal = 0;
for (int i = 0; i < NFileHeader::kRecordSize; i++)
@@ -178,26 +225,39 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, AStri
if (item.Name.Compare(NFileHeader::kLongLink) != 0 &&
item.Name.Compare(NFileHeader::kLongLink2) != 0)
return S_FALSE;
- if (item.Size > (1 << 14))
+ if (item.PackSize > (1 << 14))
return S_FALSE;
- int packSize = (int)item.GetPackSize();
+ int packSize = (int)item.GetPackSizeAligned();
char *buf = name->GetBuffer(packSize);
RINOK(ReadStream_FALSE(stream, buf, packSize));
item.HeaderSize += packSize;
- buf[(size_t)item.Size] = '\0';
+ buf[(size_t)item.PackSize] = '\0';
name->ReleaseBuffer();
continue;
}
- if (item.LinkFlag == 'g' || item.LinkFlag == 'x' || item.LinkFlag == 'X')
+ switch (item.LinkFlag)
{
- // pax Extended Header
+ case 'g':
+ case 'x':
+ case 'X':
+ {
+ // pax Extended Header
+ break;
+ }
+ case NFileHeader::NLinkFlag::kDumpDir:
+ {
+ break;
+ // GNU Extensions to the Archive Format
+ }
+ case NFileHeader::NLinkFlag::kSparse:
+ {
+ break;
+ // GNU Extensions to the Archive Format
+ }
+ default:
+ if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0))
+ return S_FALSE;
}
- else if (item.LinkFlag == NFileHeader::NLinkFlag::kDumpDir)
- {
- // GNU Extensions to the Archive Format
- }
- else if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0))
- return S_FALSE;
if (flagL) item.Name = nameL;
if (flagK) item.LinkName = nameK;
return S_OK;
diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h
index 859e66dd..3584a7ce 100755
--- a/CPP/7zip/Archive/Tar/TarItem.h
+++ b/CPP/7zip/Archive/Tar/TarItem.h
@@ -10,15 +10,22 @@
namespace NArchive {
namespace NTar {
+struct CSparseBlock
+{
+ UInt64 Offset;
+ UInt64 Size;
+};
+
struct CItem
{
AString Name;
+ UInt64 PackSize;
UInt64 Size;
+ Int64 MTime;
UInt32 Mode;
UInt32 UID;
UInt32 GID;
- UInt32 MTime;
UInt32 DeviceMajor;
UInt32 DeviceMinor;
@@ -31,7 +38,10 @@ struct CItem
bool DeviceMajorDefined;
bool DeviceMinorDefined;
+ CRecordVector<CSparseBlock> SparseBlocks;
+
bool IsLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymbolicLink && (Size == 0); }
+ bool IsSparse() const { return LinkFlag == NFileHeader::NLinkFlag::kSparse; }
UInt64 GetUnpackSize() const { return IsLink() ? LinkName.Length() : Size; }
bool IsDir() const
@@ -56,15 +66,16 @@ struct CItem
return true;
}
- UInt64 GetPackSize() const { return (Size + 0x1FF) & (~((UInt64)0x1FF)); }
+ UInt64 GetPackSizeAligned() const { return (PackSize + 0x1FF) & (~((UInt64)0x1FF)); }
};
struct CItemEx: public CItem
{
UInt64 HeaderPos;
unsigned HeaderSize;
+
UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; }
- UInt64 GetFullSize() const { return HeaderSize + Size; }
+ UInt64 GetFullSize() const { return HeaderSize + PackSize; }
};
}}
diff --git a/CPP/7zip/Archive/Tar/TarOut.cpp b/CPP/7zip/Archive/Tar/TarOut.cpp
index e542a3b2..6e699e28 100755
--- a/CPP/7zip/Archive/Tar/TarOut.cpp
+++ b/CPP/7zip/Archive/Tar/TarOut.cpp
@@ -47,7 +47,7 @@ static bool MakeOctalString8(char *s, UInt32 value)
if (tempString.Length() >= kMaxSize)
return false;
int numSpaces = kMaxSize - (tempString.Length() + 1);
- for(int i = 0; i < numSpaces; i++)
+ for (int i = 0; i < numSpaces; i++)
s[i] = ' ';
MyStringCopy(s + numSpaces, (const char *)tempString);
return true;
@@ -55,7 +55,7 @@ static bool MakeOctalString8(char *s, UInt32 value)
static void MakeOctalString12(char *s, UInt64 value)
{
- AString tempString = MakeOctalString(value);
+ AString tempString = MakeOctalString(value);
const int kMaxSize = 12;
if (tempString.Length() > kMaxSize)
{
@@ -67,11 +67,23 @@ static void MakeOctalString12(char *s, UInt64 value)
return;
}
int numSpaces = kMaxSize - tempString.Length();
- for(int i = 0; i < numSpaces; i++)
+ for (int i = 0; i < numSpaces; i++)
s[i] = ' ';
memmove(s + numSpaces, (const char *)tempString, tempString.Length());
}
+static void MakeOctalString12_From_Int64(char *s, Int64 value)
+{
+ if (value >= 0)
+ {
+ MakeOctalString12(s, value);
+ return;
+ }
+ s[0] = s[1] = s[2] = s[3] = (char)(Byte)0xFF;
+ for (int i = 0; i < 8; i++, value <<= 8)
+ s[4 + i] = (char)(value >> 56);
+}
+
static bool CopyString(char *dest, const AString &src, int maxSize)
{
if (src.Length() >= maxSize)
@@ -100,8 +112,8 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item)
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID)); cur += 8;
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID)); cur += 8;
- MakeOctalString12(cur, item.Size); cur += 12;
- MakeOctalString12(cur, item.MTime); cur += 12;
+ MakeOctalString12(cur, item.PackSize); cur += 12;
+ MakeOctalString12_From_Int64(cur, item.MTime); cur += 12;
memmove(cur, NFileHeader::kCheckSumBlanks, 8);
cur += 8;
@@ -130,7 +142,7 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item)
UInt32 checkSumReal = 0;
- for(i = 0; i < NFileHeader::kRecordSize; i++)
+ for (i = 0; i < NFileHeader::kRecordSize; i++)
checkSumReal += Byte(record[i]);
RETURN_IF_NOT_TRUE(MakeOctalString8(record + 148, checkSumReal));
@@ -146,7 +158,7 @@ HRESULT COutArchive::WriteHeader(const CItem &item)
CItem modifiedItem = item;
int nameStreamSize = nameSize + 1;
- modifiedItem.Size = nameStreamSize;
+ modifiedItem.PackSize = nameStreamSize;
modifiedItem.LinkFlag = 'L';
modifiedItem.Name = NFileHeader::kLongLink;
modifiedItem.LinkName.Empty();
diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp
index c1633218..fb123169 100755
--- a/CPP/7zip/Archive/Tar/TarUpdate.cpp
+++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp
@@ -48,7 +48,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
complexity = 0;
- for(i = 0; i < updateItems.Size(); i++)
+ for (i = 0; i < updateItems.Size(); i++)
{
lps->InSize = lps->OutSize = complexity;
RINOK(lps->SetCur());
@@ -64,14 +64,14 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
if (ui.IsDir)
{
item.LinkFlag = NFileHeader::NLinkFlag::kDirectory;
- item.Size = 0;
+ item.PackSize = 0;
}
else
{
item.LinkFlag = NFileHeader::NLinkFlag::kNormal;
- item.Size = ui.Size;
+ item.PackSize = ui.Size;
}
- item.MTime = ui.Time;
+ item.MTime = ui.MTime;
item.DeviceMajorDefined = false;
item.DeviceMinorDefined = false;
item.UID = 0;
@@ -83,12 +83,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
if (ui.NewData)
{
- item.Size = ui.Size;
- if (item.Size == (UInt64)(Int64)-1)
+ item.PackSize = ui.Size;
+ if (ui.Size == (UInt64)(Int64)-1)
return E_INVALIDARG;
}
else
- item.Size = inputItems[ui.IndexInArchive].Size;
+ item.PackSize = inputItems[ui.IndexInArchive].PackSize;
if (ui.NewData)
{
@@ -101,9 +101,9 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
if (!ui.IsDir)
{
RINOK(copyCoder->Code(fileInStream, outStream, NULL, NULL, progress));
- if (copyCoderSpec->TotalSize != item.Size)
+ if (copyCoderSpec->TotalSize != item.PackSize)
return E_FAIL;
- RINOK(outArchive.FillDataResidual(item.Size));
+ RINOK(outArchive.FillDataResidual(item.PackSize));
}
}
complexity += ui.Size;
@@ -117,7 +117,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
{
RINOK(outArchive.WriteHeader(item));
RINOK(inStream->Seek(existItem.GetDataPosition(), STREAM_SEEK_SET, NULL));
- size = existItem.Size;
+ size = existItem.PackSize;
}
else
{
@@ -129,10 +129,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize != size)
return E_FAIL;
- RINOK(outArchive.FillDataResidual(existItem.Size));
+ RINOK(outArchive.FillDataResidual(existItem.PackSize));
complexity += size;
}
}
+ lps->InSize = lps->OutSize = complexity;
+ RINOK(lps->SetCur());
return outArchive.WriteFinishHeader();
}
diff --git a/CPP/7zip/Archive/Tar/TarUpdate.h b/CPP/7zip/Archive/Tar/TarUpdate.h
index fb217d19..3f889739 100755
--- a/CPP/7zip/Archive/Tar/TarUpdate.h
+++ b/CPP/7zip/Archive/Tar/TarUpdate.h
@@ -13,15 +13,15 @@ struct CUpdateItem
{
int IndexInArchive;
int IndexInClient;
- UInt32 Time;
- UInt32 Mode;
+ Int64 MTime;
UInt64 Size;
- AString Name;
- AString User;
- AString Group;
+ UInt32 Mode;
bool NewData;
bool NewProps;
bool IsDir;
+ AString Name;
+ AString User;
+ AString Group;
};
HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp
index 60d5fc2a..d2a2884f 100755
--- a/CPP/7zip/Archive/Udf/UdfIn.cpp
+++ b/CPP/7zip/Archive/Udf/UdfIn.cpp
@@ -574,34 +574,33 @@ HRESULT CInArchive::Open2()
{
Clear();
+ // Some UDFs contain additional pad zeros (2 KB).
+ // Seek to STREAM_SEEK_END for direct DVD reading can return 8 KB more, so we check last 16 KB.
+ // And when we read last block, result read size can be smaller than required size.
+
UInt64 fileSize;
RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize));
-
- // Some UDFs contain additional 2 KB of zeros, so we also check 12, corrected to 11.
- const int kSecLogSizeMax = 12;
- Byte buf[1 << kSecLogSizeMax];
- Byte kSizesLog[] = { 11, 8, 12 };
-
- for (int i = 0;; i++)
+ const size_t kBufSize = 1 << 14;
+ Byte buf[kBufSize];
+ size_t readSize = (fileSize < kBufSize) ? (size_t)fileSize : kBufSize;
+ RINOK(_stream->Seek(fileSize - readSize, STREAM_SEEK_SET, NULL));
+ RINOK(ReadStream(_stream, buf, &readSize));
+ size_t i = readSize;
+ for (;;)
{
- if (i == sizeof(kSizesLog) / sizeof(kSizesLog[0]))
- return S_FALSE;
- SecLogSize = kSizesLog[i];
- Int32 bufSize = 1 << SecLogSize;
- if (bufSize > fileSize)
+ const size_t kSecSizeMin = 1 << 8;
+ if (i < kSecSizeMin)
return S_FALSE;
- RINOK(_stream->Seek(-bufSize, STREAM_SEEK_END, NULL));
- RINOK(ReadStream_FALSE(_stream, buf, bufSize));
+ i -= kSecSizeMin;
+ SecLogSize = (readSize - i < ((size_t)1 << 11)) ? 8 : 11;
CTag tag;
- if (tag.Parse(buf, bufSize) == S_OK)
+ if (tag.Parse(buf + i, (1 << SecLogSize)) == S_OK)
if (tag.Id == DESC_TYPE_AnchorVolPtr)
break;
}
- if (SecLogSize == 12)
- SecLogSize = 11;
CExtent extentVDS;
- extentVDS.Parse(buf + 16);
+ extentVDS.Parse(buf + i + 16);
for (UInt32 location = extentVDS.Pos; ; location++)
{
diff --git a/CPP/7zip/Archive/UefiHandler.cpp b/CPP/7zip/Archive/UefiHandler.cpp
new file mode 100755
index 00000000..88739d8f
--- /dev/null
+++ b/CPP/7zip/Archive/UefiHandler.cpp
@@ -0,0 +1,1935 @@
+// UefiHandler.cpp
+
+#include "StdAfx.h"
+
+// #define SHOW_DEBUG_INFO
+
+// #include <stdio.h>
+
+#ifdef SHOW_DEBUG_INFO
+#include <stdio.h>
+#endif
+
+#include "../../../C/7zCrc.h"
+#include "../../../C/Alloc.h"
+#include "../../../C/CpuArch.h"
+#include "../../../C/LzmaDec.h"
+
+#include "Common/Buffer.h"
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/PropVariantUtils.h"
+
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamObjects.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+
+#include "./Common/FindSignature.h"
+
+#ifdef SHOW_DEBUG_INFO
+#define PRF(x) x
+#else
+#define PRF(x)
+#endif
+
+#define Get16(p) GetUi16(p)
+#define Get32(p) GetUi32(p)
+#define Get64(p) GetUi64(p)
+#define Get24(p) (Get32(p) & 0xFFFFFF)
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+namespace NArchive {
+namespace NUefi {
+
+static const UInt32 kBufTotalSizeMax = (1 << 29);
+static const UInt32 kNumFilesMax = (1 << 18);
+static const int 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 UInt32 kFvHeaderSize = 0x38;
+static const UInt32 kGuidSize = 16;
+static const UInt32 kCapsuleSigSize = kGuidSize;
+#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 UInt32 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;
+
+static const Byte k_MacFS_Guid[kGuidSize] =
+ { 0xAD,0xEE,0xAD,0x04,0xFF,0x61,0x31,0x4D,0xB6,0xBA,0x64,0xF8,0xBF,0x90,0x1F,0x5A };
+
+static const UInt32 kFvSignature = 0x4856465F;
+
+static const Byte kGuids[][kGuidSize] =
+{
+ { 0xB0,0xCD,0x1B,0xFC,0x31,0x7D,0xAA,0x49,0x93,0x6A,0xA4,0x60,0x0D,0x9D,0xD0,0x83 },
+ { 0x2E,0x06,0xA0,0x1B,0x79,0xC7,0x82,0x45,0x85,0x66,0x33,0x6A,0xE8,0xF7,0x8F,0x09 },
+ { 0x25,0x4E,0x37,0x7E,0x01,0x8E,0xEE,0x4F,0x87,0xf2,0x39,0x0C,0x23,0xC6,0x06,0xCD },
+ { 0x97,0xE5,0x1B,0x16,0xC5,0xE9,0xDB,0x49,0xAE,0x50,0xC4,0x62,0xAB,0x54,0xEE,0xDA },
+ { 0xDB,0x7F,0xAD,0x77,0x2A,0xDF,0x02,0x43,0x88,0x98,0xC7,0x2E,0x4C,0xDB,0xD0,0xF4 },
+ { 0xAB,0x71,0xCF,0xF5,0x4B,0xB0,0x7E,0x4B,0x98,0x8A,0xD8,0xA0,0xD4,0x98,0xE6,0x92 },
+ { 0x91,0x45,0x53,0x7A,0xCE,0x37,0x81,0x48,0xB3,0xC9,0x71,0x38,0x14,0xF4,0x5D,0x6B },
+ { 0x84,0xE6,0x7A,0x36,0x5D,0x33,0x71,0x46,0xA1,0x6D,0x89,0x9D,0xBF,0xEA,0x6B,0x88 },
+ { 0x98,0x07,0x40,0x24,0x07,0x38,0x42,0x4A,0xB4,0x13,0xA1,0xEC,0xEE,0x20,0x5D,0xD8 },
+ { 0xEE,0xA2,0x3F,0x28,0x2C,0x53,0x4D,0x48,0x93,0x83,0x9F,0x93,0xB3,0x6F,0x0B,0x7E },
+ { 0x9B,0xD5,0xB8,0x98,0xBA,0xE8,0xEE,0x48,0x98,0xDD,0xC2,0x95,0x39,0x2F,0x1E,0xDB },
+ { 0x09,0x6D,0xE3,0xC3,0x94,0x82,0x97,0x4B,0xA8,0x57,0xD5,0x28,0x8F,0xE3,0x3E,0x28 },
+ { 0x18,0x88,0x53,0x4A,0xE0,0x5A,0xB2,0x4E,0xB2,0xEB,0x48,0x8B,0x23,0x65,0x70,0x22 }
+};
+
+
+static const char *kGuidNames[] =
+{
+ "CRC",
+ "VolumeTopFile",
+ "ACPI",
+ "ACPI2",
+ "Main",
+ "Intel32",
+ "Intel64",
+ "Intel32c",
+ "Intel64c",
+ "MacVolume",
+ "MacUpdate.txt",
+ "MacName",
+ "Insyde"
+};
+
+enum
+{
+ kGuidIndex_CRC = 0
+};
+
+struct CSigExtPair
+{
+ const char *ext;
+ unsigned sigSize;
+ Byte sig[16];
+};
+
+static const CSigExtPair g_Sigs[] =
+{
+ { "bmp", 2, { 'B','M' } },
+ { "riff", 4, { 'R','I','F','F' } },
+ { "pe", 2, { 'M','Z'} },
+ { "gif", 6, { 'G','I','F','8','9', 'a' } },
+ { "png", 8, { 0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A } },
+ { "jpg", 10, { 0xFF,0xD8,0xFF,0xE0,0x00,0x10,0x4A,0x46,0x49,0x46 } },
+ { "rom", 2, { 0x55,0xAA } }
+};
+
+enum
+{
+ kSig_BMP,
+ kSig_RIFF,
+ kSig_PE
+};
+
+static const char *FindExt(const Byte *p, size_t size)
+{
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE(g_Sigs); i++)
+ {
+ const CSigExtPair &pair = g_Sigs[i];
+ if (size >= pair.sigSize)
+ if (memcmp(p, pair.sig, pair.sigSize) == 0)
+ break;
+ }
+ if (i == ARRAY_SIZE(g_Sigs))
+ return NULL;
+ switch (i)
+ {
+ case kSig_BMP:
+ if (GetUi32(p + 2) > size || GetUi32(p + 0xA) > size)
+ return NULL;
+ break;
+ case kSig_RIFF:
+ if (GetUi32(p + 8) == 0x45564157 || GetUi32(p + 0xC) == 0x20746D66 )
+ return "wav";
+ break;
+ case kSig_PE:
+ {
+ if (size < 512)
+ return NULL;
+ UInt32 peOffset = GetUi32(p + 0x3C);
+ if (peOffset >= 0x1000 || peOffset + 512 > size || (peOffset & 7) != 0)
+ return NULL;
+ if (GetUi32(p + peOffset) != 0x00004550)
+ return NULL;
+ break;
+ }
+ }
+ return g_Sigs[i].ext;
+}
+
+static bool AreGuidsEq(const Byte *p1, const Byte *p2)
+{
+ return memcmp(p1, p2, kGuidSize) == 0;
+}
+
+static int FindGuid(const Byte *p)
+{
+ for (int i = 0; i < ARRAY_SIZE(kGuids); i++)
+ if (AreGuidsEq(p, kGuids[i]))
+ return i;
+ return -1;
+}
+
+static bool IsFfs(const Byte *p)
+{
+ return (Get32(p + 0x28) == kFvSignature && AreGuidsEq(p + kFfsGuidOffset, k_FFS_Guid));
+}
+
+#define FVB_ERASE_POLARITY (1 << 11)
+
+/*
+static const CUInt32PCharPair g_FV_Attribs[] =
+{
+ { 0, "ReadDisabledCap" },
+ { 1, "ReadEnabledCap" },
+ { 2, "ReadEnabled" },
+ { 3, "WriteDisabledCap" },
+ { 4, "WriteEnabledCap" },
+ { 5, "WriteEnabled" },
+ { 6, "LockCap" },
+ { 7, "Locked" },
+
+ { 9, "StickyWrite" },
+ { 10, "MemoryMapped" },
+ { 11, "ErasePolarity" },
+
+ { 12, "ReadLockCap" },
+ { 13, "WriteLockCap" },
+ { 14, "WriteLockCap" }
+};
+*/
+
+enum
+{
+ FV_FILETYPE_ALL,
+ FV_FILETYPE_RAW,
+ FV_FILETYPE_FREEFORM,
+ FV_FILETYPE_SECURITY_CORE,
+ FV_FILETYPE_PEI_CORE,
+ FV_FILETYPE_DXE_CORE,
+ FV_FILETYPE_PEIM,
+ FV_FILETYPE_DRIVER,
+ FV_FILETYPE_COMBINED_PEIM_DRIVER,
+ FV_FILETYPE_APPLICATION,
+ // The value 0x0A is reserved and should not be used
+ FV_FILETYPE_FIRMWARE_VOLUME_IMAGE = 0x0B,
+ // types 0xF0 - 0xFF are FFS file types
+ FV_FILETYPE_FFS_PAD = 0xF0
+};
+
+static const char *g_FileTypes[] =
+{
+ "ALL",
+ "RAW",
+ "FREEFORM",
+ "SECURITY_CORE",
+ "PEI_CORE",
+ "DXE_CORE",
+ "PEIM",
+ "DRIVER",
+ "COMBINED_PEIM_DRIVER",
+ "APPLICATION",
+ "0xA",
+ "VOLUME"
+};
+
+// typedef Byte FFS_FILE_ATTRIBUTES;
+// FFS File Attributes
+#define FFS_ATTRIB_TAIL_PRESENT 0x01
+// #define FFS_ATTRIB_RECOVERY 0x02
+// #define FFS_ATTRIB_HEADER_EXTENSION 0x04
+// #define FFS_ATTRIB_DATA_ALIGNMENT 0x38
+#define FFS_ATTRIB_CHECKSUM 0x40
+
+static const CUInt32PCharPair g_FFS_FILE_ATTRIBUTES[] =
+{
+ { 0, "" /* "TAIL" */ },
+ { 1, "RECOVERY" },
+ // { 2, "HEADER_EXTENSION" }, // reserved for future
+ { 6, "" /* "CHECKSUM" */ }
+};
+
+// static const Byte g_Allignment[8] = { 3, 4, 7, 9, 10, 12, 15, 16 };
+
+// typedef Byte FFS_FILE_STATE;
+
+// Look also FVB_ERASE_POLARITY.
+// Lower-order State bits are superceded by higher-order State bits.
+
+// #define FILE_HEADER_CONSTRUCTION 0x01
+// #define FILE_HEADER_VALID 0x02
+#define FILE_DATA_VALID 0x04
+// #define FILE_MARKED_FOR_UPDATE 0x08
+// #define FILE_DELETED 0x10
+// #define FILE_HEADER_INVALID 0x20
+
+// SECTION_TYPE
+
+#define SECTION_ALL 0x00
+
+#define SECTION_COMPRESSION 0x01
+#define SECTION_GUID_DEFINED 0x02
+
+// Leaf section Type values
+#define SECTION_PE32 0x10
+#define SECTION_PIC 0x11
+#define SECTION_TE 0x12
+#define SECTION_DXE_DEPEX 0x13
+#define SECTION_VERSION 0x14
+#define SECTION_USER_INTERFACE 0x15
+#define SECTION_COMPATIBILITY16 0x16
+#define SECTION_FIRMWARE_VOLUME_IMAGE 0x17
+#define SECTION_FREEFORM_SUBTYPE_GUID 0x18
+#define SECTION_RAW 0x19
+#define SECTION_PEI_DEPEX 0x1B
+
+
+// #define GUIDED_SECTION_PROCESSING_REQUIRED 0x01
+// #define GUIDED_SECTION_AUTH_STATUS_VALID 0x02
+
+static const CUInt32PCharPair g_GUIDED_SECTION_ATTRIBUTES[] =
+{
+ { 0, "PROCESSING_REQUIRED" },
+ { 1, "AUTH" }
+};
+
+static const CUInt32PCharPair g_SECTION_TYPE[] =
+{
+ { 0x01, "COMPRESSION" },
+ { 0x02, "GUID" },
+ { 0x10, "efi" },
+ { 0x11, "PIC" },
+ { 0x12, "te" },
+ { 0x13, "DXE_DEPEX" },
+ { 0x14, "VERSION" },
+ { 0x15, "USER_INTERFACE" },
+ { 0x16, "COMPATIBILITY16" },
+ { 0x17, "VOLUME" },
+ { 0x18, "FREEFORM_SUBTYPE_GUID" },
+ { 0x19, "raw" },
+ { 0x1B, "PEI_DEPEX" }
+};
+
+#define COMPRESSION_TYPE_NONE 0
+#define COMPRESSION_TYPE_LZH 1
+#define COMPRESSION_TYPE_LZMA 2
+
+static const char *g_Methods[] =
+{
+ "COPY",
+ "LZH",
+ "LZMA"
+};
+
+static AString UInt32ToString(UInt32 val)
+{
+ char sz[16];
+ ConvertUInt32ToString(val, sz);
+ return sz;
+}
+
+static void ConvertByteToHex(unsigned value, char *s)
+{
+ for (int i = 0; i < 2; i++)
+ {
+ unsigned t = value & 0xF;
+ value >>= 4;
+ s[1 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
+ }
+}
+
+static AString GuidToString(const Byte *p, bool full)
+{
+ char s[16 * 2 + 8];
+ int i;
+ for (i = 0; i < 4; i++)
+ ConvertByteToHex(p[3 - i], s + i * 2);
+ s[8] = 0;
+
+ if (full)
+ {
+ s[8] = '-';
+ for (i = 4; i < kGuidSize; i++)
+ ConvertByteToHex(p[i], s + 1 + i * 2);
+ s[32 + 1] = 0;
+ }
+ return s;
+}
+
+static const char *kExpressionCommands[] =
+{
+ "BEFORE", "AFTER", "PUSH", "AND", "OR", "NOT", "TRUE", "FALSE", "END", "SOR"
+};
+
+static bool ParseDepedencyExpression(const Byte *p, UInt32 size, AString &res)
+{
+ res.Empty();
+ for (UInt32 i = 0; i < size;)
+ {
+ unsigned command = p[i++];
+ if (command > ARRAY_SIZE(kExpressionCommands))
+ return false;
+ res += kExpressionCommands[command];
+ if (command < 3)
+ {
+ if (i + kGuidSize > size)
+ return false;
+ res += " ";
+ res += GuidToString(p + i, false);
+ i += kGuidSize;
+ }
+ res += "; ";
+ }
+ return true;
+}
+
+static bool ParseUtf16zString(const Byte *p, UInt32 size, UString &res)
+{
+ if ((size & 1) != 0)
+ return false;
+ res.Empty();
+ UInt32 i;
+ for (i = 0; i < size; i += 2)
+ {
+ wchar_t c = Get16(p + i);
+ if (c == 0)
+ break;
+ res += c;
+ }
+ return (i == size - 2);
+}
+
+static bool ParseUtf16zString2(const Byte *p, UInt32 size, AString &res)
+{
+ UString s;
+ if (!ParseUtf16zString(p, size, s))
+ return false;
+ res = UnicodeStringToMultiByte(s);
+ return true;
+}
+
+#define FLAGS_TO_STRING(pairs, value) FlagsToString(pairs, ARRAY_SIZE(pairs), value)
+#define TYPE_TO_STRING(table, value) TypeToString(table, ARRAY_SIZE(table), value)
+#define TYPE_PAIR_TO_STRING(table, value) TypePairToString(table, ARRAY_SIZE(table), value)
+
+static const UInt32 kFileHeaderSize = 24;
+
+static void AddSpaceAndString(AString &res, const AString &newString)
+{
+ if (!res.IsEmpty() && !newString.IsEmpty())
+ res += ' ';
+ res += newString;
+}
+
+class CFfsFileHeader
+{
+ Byte CheckHeader;
+ Byte CheckFile;
+ Byte Attrib;
+ Byte State;
+
+ UInt16 GetTailReference() const { return CheckHeader | ((UInt16)CheckFile << 8); }
+ UInt32 GetTailSize() const { return IsThereTail() ? 2 : 0; }
+ bool IsThereFileChecksum() const { return (Attrib & FFS_ATTRIB_CHECKSUM) != 0; }
+ bool IsThereTail() const { return (Attrib & FFS_ATTRIB_TAIL_PRESENT) != 0; }
+public:
+ Byte GuidName[kGuidSize];
+ Byte Type;
+ UInt32 Size;
+
+ bool Parse(const Byte *p)
+ {
+ int i;
+ for (i = 0; i < kFileHeaderSize; i++)
+ if (p[i] != 0xFF)
+ break;
+ if (i == kFileHeaderSize)
+ return false;
+ memcpy(GuidName, p, kGuidSize);
+ CheckHeader = p[0x10];
+ CheckFile = p[0x11];
+ Type = p[0x12];
+ Attrib = p[0x13];
+ Size = Get24(p + 0x14);
+ State = p[0x17];
+ return true;
+ }
+
+ UInt32 GetDataSize() const { return Size - kFileHeaderSize - GetTailSize(); }
+
+ bool Check(const Byte *p, UInt32 size)
+ {
+ if (Size > size)
+ return false;
+ UInt32 tailSize = GetTailSize();
+ if (Size < kFileHeaderSize + tailSize)
+ return false;
+
+ {
+ unsigned checkSum = 0;
+ for (UInt32 i = 0; i < kFileHeaderSize; i++)
+ checkSum += p[i];
+ checkSum -= p[0x17];
+ checkSum -= p[0x11];
+ if ((Byte)checkSum != 0)
+ return false;
+ }
+
+ if (IsThereFileChecksum())
+ {
+ unsigned checkSum = 0;
+ UInt32 checkSize = Size - tailSize;
+ for (UInt32 i = 0; i < checkSize; i++)
+ checkSum += p[i];
+ checkSum -= p[0x17];
+ if ((Byte)checkSum != 0)
+ return false;
+ }
+
+ if (IsThereTail())
+ if (GetTailReference() != (UInt16)~Get16(p + Size - 2))
+ return false;
+
+ int polarity = 0;
+ int i;
+ for (i = 5; i >= 0; i--)
+ if (((State >> i) & 1) == polarity)
+ {
+ // AddSpaceAndString(s, g_FFS_FILE_STATE_Flags[i]);
+ if ((1 << i) != FILE_DATA_VALID)
+ return false;
+ break;
+ }
+ if (i < 0)
+ return false;
+
+ return true;
+ }
+
+ AString GetCharacts() const
+ {
+ AString s;
+ if (Type == FV_FILETYPE_FFS_PAD)
+ s += "PAD";
+ else
+ s += TYPE_TO_STRING(g_FileTypes, Type);
+ AddSpaceAndString(s, FLAGS_TO_STRING(g_FFS_FILE_ATTRIBUTES, Attrib & 0xC7));
+ /*
+ int align = (Attrib >> 3) & 7;
+ if (align != 0)
+ {
+ s += " Align:";
+ s += UInt32ToString((UInt32)1 << g_Allignment[align]);
+ }
+ */
+ return s;
+ }
+};
+
+#define GET_32(offs, dest) dest = Get32(p + (offs));
+#define GET_64(offs, dest) dest = Get64(p + (offs));
+
+struct CCapsuleHeader
+{
+ UInt32 HeaderSize;
+ UInt32 Flags;
+ UInt32 CapsuleImageSize;
+ UInt32 SequenceNumber;
+ // Guid InstanceId;
+ UInt32 OffsetToSplitInformation;
+ UInt32 OffsetToCapsuleBody;
+ UInt32 OffsetToOemDefinedHeader;
+ UInt32 OffsetToAuthorInformation;
+ UInt32 OffsetToRevisionInformation;
+ UInt32 OffsetToShortDescription;
+ UInt32 OffsetToLongDescription;
+ UInt32 OffsetToApplicableDevices;
+
+ void Clear() { memset(this, 0, sizeof(this)); }
+
+ void Parse(const Byte *p)
+ {
+ GET_32(0x10, HeaderSize);
+ GET_32(0x14, Flags);
+ GET_32(0x18, CapsuleImageSize);
+ GET_32(0x1C, SequenceNumber);
+ GET_32(0x30, OffsetToSplitInformation);
+ GET_32(0x34, OffsetToCapsuleBody);
+ GET_32(0x38, OffsetToOemDefinedHeader);
+ GET_32(0x3C, OffsetToAuthorInformation);
+ GET_32(0x40, OffsetToRevisionInformation);
+ GET_32(0x44, OffsetToShortDescription);
+ GET_32(0x48, OffsetToLongDescription);
+ GET_32(0x4C, OffsetToApplicableDevices);
+ }
+};
+
+struct CItem
+{
+ AString Name;
+ AString Characts;
+ int Parent;
+ int Method;
+ int NameIndex;
+ int NumChilds;
+ bool IsDir;
+ bool Skip;
+ bool ThereAreSubDirs;
+ bool ThereIsUniqueName;
+ bool KeepName;
+
+ int BufIndex;
+ UInt32 Offset;
+ UInt32 Size;
+
+ CItem(): Parent(-1), Method(-1), NameIndex(-1), NumChilds(0),
+ IsDir(false), Skip(false), ThereAreSubDirs(false), ThereIsUniqueName(false), KeepName(true) {}
+ void SetGuid(const Byte *guidName, bool full = false);
+ AString GetName(int numChildsInParent) const;
+};
+
+void CItem::SetGuid(const Byte *guidName, bool full)
+{
+ ThereIsUniqueName = true;
+ int index = FindGuid(guidName);
+ if (index >= 0)
+ Name = kGuidNames[index];
+ else
+ Name = GuidToString(guidName, full);
+}
+
+AString CItem::GetName(int numChildsInParent) const
+{
+ if (numChildsInParent <= 1 || NameIndex < 0)
+ return Name;
+ char sz[32];
+ char sz2[32];
+ ConvertUInt32ToString(NameIndex, sz);
+ ConvertUInt32ToString(numChildsInParent - 1, sz2);
+ int numZeros = (int)strlen(sz2) - (int)strlen(sz);
+ AString res;
+ for (int i = 0; i < numZeros; i++)
+ res += '0';
+ return res + (AString)sz + '.' + Name;
+}
+
+struct CItem2
+{
+ AString Name;
+ AString Characts;
+ int MainIndex;
+ int Parent;
+
+ CItem2(): Parent(-1) {}
+};
+
+class CHandler:
+ public IInArchive,
+ public IInArchiveGetStream,
+ public CMyUnknownImp
+{
+ CObjectVector<CItem> _items;
+ CObjectVector<CItem2> _items2;
+ CObjectVector<CByteBuffer> _bufs;
+ UString _comment;
+ UInt32 _methodsMask;
+ bool _capsuleMode;
+
+ UInt32 _totalBufsSize;
+ CCapsuleHeader _h;
+
+ void AddCommentString(const wchar_t *name, UInt32 pos);
+ int AddItem(const CItem &item);
+ int AddFileItemWithIndex(CItem &item);
+ int AddDirItem(CItem &item);
+ int AddBuf(UInt32 size);
+
+ HRESULT ParseSections(int bufIndex, UInt32 pos, UInt32 size, int parent, int method, int level);
+ HRESULT ParseVolume(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, int level);
+ HRESULT OpenCapsule(IInStream *stream);
+ HRESULT OpenFv(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback);
+ HRESULT Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback);
+public:
+ CHandler(bool capsuleMode): _capsuleMode(capsuleMode) {}
+ MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+ INTERFACE_IInArchive(;)
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+};
+
+static const STATPROPSTG kProps[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ { NULL, kpidIsDir, VT_BOOL},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidMethod, VT_BSTR},
+ { NULL, kpidCharacts, VT_BSTR}
+};
+
+static const STATPROPSTG kArcProps[] =
+{
+ { NULL, kpidComment, VT_BSTR},
+ { NULL, kpidMethod, VT_BSTR},
+ { NULL, kpidPhySize, VT_UI8},
+ { NULL, kpidCharacts, VT_BSTR}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant prop;
+ const CItem2 &item2 = _items2[index];
+ const CItem &item = _items[item2.MainIndex];
+ switch(propID)
+ {
+ case kpidPath:
+ {
+ AString path = item2.Name;
+ int cur = item2.Parent;
+ while (cur >= 0)
+ {
+ const CItem2 &item2 = _items2[cur];
+ path = item2.Name + CHAR_PATH_SEPARATOR + path;
+ cur = item2.Parent;
+ }
+ prop = path;
+ break;
+ }
+ case kpidIsDir: prop = item.IsDir; break;
+ case kpidMethod: if (item.Method >= 0) prop = g_Methods[item.Method]; break;
+ case kpidCharacts: if (!item2.Characts.IsEmpty()) prop = item2.Characts; break;
+ case kpidSize: if (!item.IsDir) prop = (UInt64)item.Size; break;
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+void CHandler::AddCommentString(const wchar_t *name, UInt32 pos)
+{
+ UString s;
+ const Byte *buf = _bufs[0];
+ if (pos < _h.HeaderSize)
+ return;
+ for (UInt32 i = pos;; i += 2)
+ {
+ if (s.Length() > (1 << 16) || i >= _h.OffsetToCapsuleBody)
+ return;
+ wchar_t c = Get16(buf + i);
+ if (c == 0)
+ {
+ i += 2;
+ if (i >= _h.OffsetToCapsuleBody)
+ return;
+ c = Get16(buf + i);
+ if (c == 0)
+ break;
+ s += L'\n';
+ }
+ s += c;
+ }
+ if (s.IsEmpty())
+ return;
+ _comment += L'\n';
+ _comment += name;
+ _comment += L": ";
+ _comment += s;
+}
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant prop;
+ switch(propID)
+ {
+ case kpidMethod:
+ {
+ AString s;
+ for (int i = 0; i < 32; i++)
+ if ((_methodsMask & ((UInt32)1 << i)) != 0)
+ AddSpaceAndString(s, g_Methods[i]);
+ if (!s.IsEmpty())
+ prop = s;
+ break;
+ }
+ case kpidComment: if (!_comment.IsEmpty()) prop = _comment; break;
+ case kpidPhySize: prop = (UInt64)_h.CapsuleImageSize; break;
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+#ifdef SHOW_DEBUG_INFO
+static void PrintLevel(int level)
+{
+ PRF(printf("\n"));
+ for (int i = 0; i < level; i++)
+ PRF(printf(" "));
+}
+static void MyPrint(UInt32 posBase, UInt32 size, int level, const char *name)
+{
+ PrintLevel(level);
+ PRF(printf("%s, pos = %6x, size = %6d", name, posBase, size));
+}
+#else
+#define PrintLevel(level)
+#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)
+{
+ if (_items.Size() >= kNumFilesMax)
+ throw 2;
+ return _items.Add(item);
+}
+
+int CHandler::AddFileItemWithIndex(CItem &item)
+{
+ int nameIndex = _items.Size();
+ if (item.Parent >= 0)
+ nameIndex = _items[item.Parent].NumChilds++;
+ item.NameIndex = nameIndex;
+ return AddItem(item);
+}
+
+int CHandler::AddDirItem(CItem &item)
+{
+ if (item.Parent >= 0)
+ _items[item.Parent].ThereAreSubDirs = true;
+ item.IsDir = true;
+ item.Size = 0;
+ return AddItem(item);
+}
+
+int CHandler::AddBuf(UInt32 size)
+{
+ if (size > kBufTotalSizeMax - _totalBufsSize)
+ throw 1;
+ _totalBufsSize += size;
+ int index = _bufs.Add(CByteBuffer());
+ _bufs[index].SetCapacity(size);
+ return index;
+}
+
+HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, int level)
+{
+ if (level > kLevelMax)
+ return S_FALSE;
+ MyPrint(posBase, size, level, "Sections");
+ level++;
+ const Byte *bufData = _bufs[bufIndex];
+ UInt32 pos = 0;
+ for (;;)
+ {
+ if (size == pos)
+ return S_OK;
+ PrintLevel(level);
+ PRF(printf("%s, pos = %6x", "Sect", pos));
+ pos = (pos + 3) & ~(UInt32)3;
+ if (pos > size)
+ return S_FALSE;
+ UInt32 rem = size - pos;
+ if (rem == 0)
+ return S_OK;
+ if (rem < 4)
+ return S_FALSE;
+ const Byte *p = bufData + posBase + pos;
+ UInt32 sectSize = Get24(p);
+ if (sectSize > rem || sectSize < 4)
+ return S_FALSE;
+
+ Byte type = p[3];
+ PrintLevel(level);
+ PRF(printf("%s, type = %2x, pos = %6x, size = %6d", "Sect", type, pos, sectSize));
+ CItem item;
+ item.Method = method;
+ item.BufIndex = bufIndex;
+ item.Parent = parent;
+ item.Offset = posBase + pos + 4;
+ UInt32 sectDataSize = sectSize - 4;
+ item.Size = sectDataSize;
+ item.Name = TYPE_PAIR_TO_STRING(g_SECTION_TYPE, type);
+
+ if (type == SECTION_COMPRESSION)
+ {
+ if (sectSize < 4 + 5)
+ return S_FALSE;
+ UInt32 uncompressedSize = Get32(p + 4);
+ Byte compressionType = p[8];
+
+ UInt32 newSectSize = sectSize - 9;
+ UInt32 newOffset = posBase + pos + 9;
+ const Byte *pStart = p + 9;
+
+ item.KeepName = false;
+ if (compressionType > 2)
+ {
+ // AddFileItemWithIndex(item);
+ return S_FALSE;
+ }
+ else
+ {
+ item.Name = g_Methods[compressionType];
+ // int parent = AddDirItem(item);
+ if (compressionType == COMPRESSION_TYPE_NONE)
+ {
+ RINOK(ParseSections(bufIndex, newOffset, newSectSize, parent, method, level));
+ }
+ else if (compressionType == COMPRESSION_TYPE_LZH)
+ {
+ int newBufIndex = AddBuf(uncompressedSize);
+ CByteBuffer &buf = _bufs[newBufIndex];
+ RINOK(LzhDecode(buf, uncompressedSize, pStart, newSectSize));
+ RINOK(ParseSections(newBufIndex, 0, uncompressedSize, parent, compressionType, level));
+ }
+ else
+ {
+ if (newSectSize < 4 + 5 + 8)
+ return S_FALSE;
+ unsigned addSize = 4;
+ if (pStart[0] == 0x5d && pStart[1] == 0 && pStart[2] == 0 && pStart[3] == 0x80 && pStart[4] == 0)
+ {
+ addSize = 0;
+ // some archives have such header
+ }
+ else
+ {
+ // normal BIOS contains uncompressed size here
+ // UInt32 uncompressedSize2 = Get24(pStart);
+ // Byte firstSectType = p[9 + 3];
+ // firstSectType can be 0 in some archives
+ }
+ pStart += addSize;
+ UInt64 lzmaUncompressedSize = Get64(pStart + 5);
+ if (lzmaUncompressedSize > (1 << 30))
+ return S_FALSE;
+ if (lzmaUncompressedSize < uncompressedSize)
+ return S_FALSE;
+ SizeT destLen = (SizeT)lzmaUncompressedSize;
+ int newBufIndex = AddBuf((UInt32)lzmaUncompressedSize);
+ CByteBuffer &buf = _bufs[newBufIndex];
+ ELzmaStatus status;
+ SizeT srcLen = newSectSize - (addSize + 5 + 8);
+ SizeT srcLen2 = srcLen;
+ SRes res = LzmaDecode(buf, &destLen, pStart + 13, &srcLen,
+ pStart, 5, LZMA_FINISH_END, &status, &g_Alloc);
+ if (res != 0)
+ return S_FALSE;
+ if (srcLen != srcLen2 || destLen != lzmaUncompressedSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
+ return S_FALSE;
+ RINOK(ParseSections(newBufIndex, 0, (UInt32)lzmaUncompressedSize, parent, compressionType, level));
+ }
+ _methodsMask |= (1 << compressionType);
+ }
+ }
+ else if (type == SECTION_GUID_DEFINED)
+ {
+ const UInt32 kHeaderSize = 4 + kGuidSize + 4;
+ if (sectSize < kHeaderSize)
+ return S_FALSE;
+ item.SetGuid(p + 4);
+ UInt32 dataOffset = Get16(p + 4 + kGuidSize);
+ UInt32 attrib = Get16(p + 4 + kGuidSize + 2);
+ if (dataOffset > sectSize || dataOffset < kHeaderSize)
+ return S_FALSE;
+ UInt32 newSectSize = sectSize - dataOffset;
+ item.Size = newSectSize;
+ UInt32 newOffset = posBase + pos + dataOffset;
+ item.Offset = newOffset;
+ UInt32 propsSize = dataOffset - kHeaderSize;
+ bool needDir = true;
+ AddSpaceAndString(item.Characts, FLAGS_TO_STRING(g_GUIDED_SECTION_ATTRIBUTES, attrib));
+ if (AreGuidsEq(p + 0x4, kGuids[kGuidIndex_CRC]) && propsSize == 4)
+ {
+ needDir = false;
+ item.KeepName = false;
+ if (CrcCalc(bufData + newOffset, newSectSize) != Get32(p + kHeaderSize))
+ return S_FALSE;
+ }
+ else
+ {
+ if (propsSize != 0)
+ {
+ CItem item2 = item;
+ item2.Name += ".prop";
+ item2.Size = propsSize;
+ item2.Offset = posBase + pos + kHeaderSize;
+ AddItem(item2);
+ }
+ }
+ int newParent = parent;
+ if (needDir)
+ newParent = AddDirItem(item);
+ RINOK(ParseSections(bufIndex, newOffset, newSectSize, newParent, method, level));
+ }
+ else if (type == SECTION_FIRMWARE_VOLUME_IMAGE)
+ {
+ item.KeepName = false;
+ int newParent = AddDirItem(item);
+ RINOK(ParseVolume(bufIndex, posBase + pos + 4, sectSize - 4, newParent, method, level));
+ }
+ else
+ {
+ bool needAdd = true;
+ switch(type)
+ {
+ case SECTION_RAW:
+ {
+ const UInt32 kInsydeOffset = 12;
+ if (sectDataSize >= kFvHeaderSize + kInsydeOffset)
+ {
+ if (IsFfs(p + 4 + kInsydeOffset) &&
+ sectDataSize - kInsydeOffset == Get64(p + 4 + kInsydeOffset + 0x20))
+ {
+ needAdd = false;
+ item.Name = "vol";
+ int newParent = AddDirItem(item);
+ RINOK(ParseVolume(bufIndex, posBase + pos + 4 + kInsydeOffset, sectDataSize - kInsydeOffset, newParent, method, level));
+ }
+
+ if (needAdd)
+ {
+ const char *ext = FindExt(p + 4, sectDataSize);
+ if (ext)
+ item.Name = ext;
+ }
+ }
+ break;
+ }
+ case SECTION_DXE_DEPEX:
+ case SECTION_PEI_DEPEX:
+ {
+ AString s;
+ if (ParseDepedencyExpression(p + 4, sectDataSize, s))
+ {
+ if (s.Length() < (1 << 9))
+ {
+ s = '[' + s + ']';
+ AddSpaceAndString(_items[item.Parent].Characts, s);
+ needAdd = false;
+ }
+ else
+ {
+ item.BufIndex = AddBuf(s.Length());
+ CByteBuffer &buf0 = _bufs[item.BufIndex];
+ memcpy(buf0, s, s.Length());
+ item.Offset = 0;
+ item.Size = s.Length();
+ }
+ }
+ break;
+ }
+ case SECTION_VERSION:
+ {
+ if (sectDataSize > 2)
+ {
+ AString s;
+ if (ParseUtf16zString2(p + 6, sectDataSize - 2, s))
+ {
+ AddSpaceAndString(_items[item.Parent].Characts, (AString)"ver:" + UInt32ToString(Get16(p + 4)) + ' ' + s);
+ needAdd = false;
+ }
+ }
+ break;
+ }
+ case SECTION_USER_INTERFACE:
+ {
+ AString s;
+ if (ParseUtf16zString2(p + 4, sectDataSize, s))
+ {
+ _items[parent].Name = s;
+ needAdd = false;
+ }
+ break;
+ }
+ case SECTION_FREEFORM_SUBTYPE_GUID:
+ {
+ if (sectDataSize >= kGuidSize)
+ {
+ item.SetGuid(p + 4);
+ item.Size = sectDataSize - kGuidSize;
+ item.Offset = posBase + pos + 4 + kGuidSize;
+ }
+ break;
+ }
+ }
+
+ if (needAdd)
+ AddFileItemWithIndex(item);
+ }
+ pos += sectSize;
+ }
+}
+
+static UInt32 Count_FF_Bytes(const Byte *p, UInt32 size)
+{
+ UInt32 i;
+ for (i = 0; i < size && p[i] == 0xFF; i++);
+ return i;
+}
+
+static bool Is_FF_Stream(const Byte *p, UInt32 size)
+{
+ return (Count_FF_Bytes(p, size) == size);
+}
+
+HRESULT CHandler::ParseVolume(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, int level)
+{
+ if (level > kLevelMax)
+ return S_FALSE;
+ MyPrint(posBase, size, level, "Volume");
+ level++;
+ if (size < kFvHeaderSize)
+ return S_FALSE;
+ const Byte *p = _bufs[bufIndex] + posBase;
+ // first 16 bytes must be zeros, but they are not zeros sometimes.
+ if (!AreGuidsEq(p + kFfsGuidOffset, k_FFS_Guid) &&
+ !AreGuidsEq(p + kFfsGuidOffset, k_MacFS_Guid))
+ {
+ CItem item;
+ item.Method = method;
+ item.BufIndex = bufIndex;
+ item.Parent = parent;
+ item.Offset = posBase;
+ item.Size = size;
+ item.SetGuid(p + kFfsGuidOffset);
+ item.Name += " [VOLUME]";
+ AddItem(item);
+ return S_OK;
+ }
+
+ if (Get32(p + 0x28) != kFvSignature)
+ return S_FALSE;
+ UInt32 attribs = Get32(p + 0x2C);
+ if ((attribs & FVB_ERASE_POLARITY) == 0)
+ return S_FALSE;
+ // if (parent >= 0) AddSpaceAndString(_items[parent].Characts, FLAGS_TO_STRING(g_FV_Attribs, attribs));
+ UInt64 fvLen = Get64(p + 0x20);
+ UInt32 headerLen = Get16(p + 0x30);
+ if (headerLen > size || headerLen < kFvHeaderSize || (headerLen & 0x7) != 0 ||
+ fvLen > size || fvLen < headerLen)
+ return S_FALSE;
+
+ {
+ UInt32 checkCalc = 0;
+ for (UInt32 i = 0; i < headerLen; i += 2)
+ checkCalc += Get16(p + i);
+ if ((checkCalc & 0xFFFF) != 0)
+ return S_FALSE;
+ }
+
+ // 3 reserved bytes are not zeros sometimes.
+ // UInt16 ExtHeaderOffset; // in new SPECIFICATION?
+ // Byte revision = p[0x37];
+
+ UInt32 pos = kFvHeaderSize;
+ for (;;)
+ {
+ if (pos >= headerLen)
+ return S_FALSE;
+ UInt32 numBlocks = Get32(p + pos);
+ UInt32 length = Get32(p + pos + 4);
+ pos += 8;
+ if (numBlocks == 0 && length == 0)
+ break;
+ }
+ if (pos != headerLen)
+ return S_FALSE;
+
+ CRecordVector<UInt32> guidsVector;
+
+ for (;;)
+ {
+ UInt32 rem = (UInt32)fvLen - pos;
+ if (rem < kFileHeaderSize)
+ break;
+ pos = (pos + 7) & ~7;
+ rem = (UInt32)fvLen - pos;
+ if (rem < kFileHeaderSize)
+ break;
+
+ CItem item;
+ item.Method = method;
+ item.BufIndex = bufIndex;
+ item.Parent = parent;
+
+ const Byte *pFile = p + pos;
+ CFfsFileHeader fh;
+ if (!fh.Parse(pFile))
+ {
+ UInt32 num_FF_bytes = Count_FF_Bytes(pFile, rem);
+ if (num_FF_bytes != rem)
+ {
+ item.Name = "[junk]";
+ item.Offset = posBase + pos + num_FF_bytes;
+ item.Size = rem - num_FF_bytes;
+ AddItem(item);
+ }
+ break;
+ }
+ PrintLevel(level); PRF(printf("%s, pos = %6x, size = %6d", "FILE", posBase + pos, fh.Size));
+ if (!fh.Check(pFile, rem))
+ return S_FALSE;
+
+ UInt32 offset = posBase + pos + kFileHeaderSize;
+ UInt32 sectSize = fh.GetDataSize();
+ item.Offset = offset;
+ item.Size = sectSize;
+
+ pos += fh.Size;
+
+ if (fh.Type == FV_FILETYPE_FFS_PAD)
+ if (Is_FF_Stream(pFile + kFileHeaderSize, sectSize))
+ continue;
+
+ UInt32 guid32 = Get32(fh.GuidName);
+ bool full = true;
+ if (guidsVector.FindInSorted(guid32) < 0)
+ {
+ guidsVector.AddToUniqueSorted(guid32);
+ full = false;
+ }
+ item.SetGuid(fh.GuidName, full);
+
+ item.Characts = fh.GetCharacts();
+ PrintLevel(level);
+ PRF(printf("%s", item.Characts));
+
+ if (fh.Type == FV_FILETYPE_FFS_PAD ||
+ fh.Type == FV_FILETYPE_RAW)
+ {
+ bool isVolume = false;
+ if (fh.Type == FV_FILETYPE_RAW)
+ {
+ if (sectSize >= kFvHeaderSize)
+ if (IsFfs(pFile + kFileHeaderSize))
+ isVolume = true;
+ }
+ if (isVolume)
+ {
+ int newParent = AddDirItem(item);
+ RINOK(ParseVolume(bufIndex, offset, sectSize, newParent, method, level));
+ }
+ else
+ AddItem(item);
+ }
+ else
+ {
+ int newParent = AddDirItem(item);
+ RINOK(ParseSections(bufIndex, offset, sectSize, newParent, method, level));
+ }
+ }
+ return S_OK;
+}
+
+HRESULT CHandler::OpenCapsule(IInStream *stream)
+{
+ const UInt32 kHeaderSize = 80;
+ Byte buf[kHeaderSize];
+ RINOK(ReadStream_FALSE(stream, buf, kHeaderSize));
+ _h.Parse(buf);
+ if (_h.HeaderSize != kHeaderSize ||
+ _h.CapsuleImageSize < kHeaderSize ||
+ _h.OffsetToCapsuleBody < kHeaderSize ||
+ _h.OffsetToCapsuleBody > _h.CapsuleImageSize)
+ return S_FALSE;
+
+ if (_h.SequenceNumber != 0 ||
+ _h.OffsetToSplitInformation != 0 )
+ return E_NOTIMPL;
+
+ int bufIndex = AddBuf(_h.CapsuleImageSize);
+ CByteBuffer &buf0 = _bufs[bufIndex];
+ memcpy(buf0, buf, kHeaderSize);
+ ReadStream_FALSE(stream, buf0 + kHeaderSize, _h.CapsuleImageSize - kHeaderSize);
+
+ AddCommentString(L"Author", _h.OffsetToAuthorInformation);
+ AddCommentString(L"Revision", _h.OffsetToRevisionInformation);
+ AddCommentString(L"Short Description", _h.OffsetToShortDescription);
+ AddCommentString(L"Long Description", _h.OffsetToLongDescription);
+
+ return ParseVolume(bufIndex, _h.OffsetToCapsuleBody, _h.CapsuleImageSize - _h.OffsetToCapsuleBody, -1, -1, 0);
+}
+
+HRESULT CHandler::OpenFv(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)
+{
+ UInt64 fileSize;
+ RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));
+ if (fileSize > (1 << 27))
+ return S_FALSE;
+
+ UInt32 volIndex = 0;
+ UInt32 pos = 0, prevEnd = 0;
+ if (callback)
+ {
+ RINOK(callback->SetTotal(NULL, &fileSize));
+ }
+
+ for (;;)
+ {
+ UInt64 limit = 0;
+ UInt64 *limitPtr = NULL;
+ if (maxCheckStartPosition)
+ {
+ UInt32 directSize = pos - prevEnd;
+ if (directSize >= *maxCheckStartPosition)
+ break;
+ limit = *maxCheckStartPosition - directSize;
+ limitPtr = &limit;
+ }
+
+ UInt64 resPos;
+ RINOK(stream->Seek(pos + kFfsGuidOffset, STREAM_SEEK_SET, NULL));
+ if (FindSignatureInStream(stream, k_FFS_Guid, kGuidSize, limitPtr, resPos) == S_FALSE)
+ break;
+
+ pos += (UInt32)resPos;
+ UInt64 fvSize;
+ {
+ UInt32 rem = (UInt32)fileSize - pos;
+ if (rem < kFvHeaderSize)
+ break;
+ RINOK(stream->Seek(pos, STREAM_SEEK_SET, NULL));
+ Byte buf[kFvHeaderSize];
+ RINOK(ReadStream_FALSE(stream, buf, kFvHeaderSize));
+ fvSize = Get64(buf + 0x20);
+ if (!IsFfs(buf) || fvSize > rem)
+ {
+ pos++;
+ continue;
+ }
+ }
+
+ RINOK(stream->Seek(prevEnd, STREAM_SEEK_SET, NULL));
+
+ if (pos != prevEnd)
+ {
+ CItem item;
+ item.Offset = 0;
+ item.Size = pos - prevEnd;
+ item.BufIndex = AddBuf(item.Size);
+ CByteBuffer &buf0 = _bufs[item.BufIndex];
+ RINOK(ReadStream_FALSE(stream, buf0, item.Size));
+ item.Name = UInt32ToString(volIndex++);
+ AddItem(item);
+ }
+
+ prevEnd = pos;
+ RINOK(stream->Seek(pos, STREAM_SEEK_SET, NULL));
+ UInt32 fvSize32 = (UInt32)fvSize;
+ CItem item;
+ item.BufIndex = AddBuf(fvSize32);
+ CByteBuffer &buf0 = _bufs[item.BufIndex];
+ item.Name = UInt32ToString(volIndex++);
+ int parent = AddDirItem(item);
+ ReadStream_FALSE(stream, buf0, fvSize32);
+ RINOK(ParseVolume(item.BufIndex, 0, fvSize32, parent, -1, 0));
+ pos += fvSize32;
+ prevEnd = pos;
+
+ if (callback)
+ {
+ UInt64 pos64 = pos;
+ RINOK(callback->SetCompleted(NULL, &pos64));
+ }
+ }
+ if (_items.Size() == 0)
+ return S_FALSE;
+
+ if (pos <= fileSize)
+ {
+ pos = (UInt32)fileSize;
+ if (prevEnd < pos)
+ {
+ CItem item;
+ item.Offset = 0;
+ item.Size = pos - prevEnd;
+ item.BufIndex = AddBuf(item.Size);
+ CByteBuffer &buf0 = _bufs[item.BufIndex];
+ RINOK(stream->Seek(prevEnd, STREAM_SEEK_SET, NULL));
+ RINOK(ReadStream_FALSE(stream, buf0, item.Size));
+ item.Name = UInt32ToString(volIndex++);
+ AddItem(item);
+ }
+ }
+ _h.CapsuleImageSize = pos;
+ return S_OK;
+}
+
+HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)
+{
+ if (_capsuleMode)
+ {
+ RINOK(OpenCapsule(stream));
+ }
+ else
+ {
+ RINOK(OpenFv(stream, maxCheckStartPosition, callback));
+ }
+
+ CIntVector numChilds;
+ numChilds.Reserve(_items.Size());
+ int i;
+ for (i = 0; i < _items.Size(); i++)
+ {
+ numChilds.Add(0);
+ int parent = _items[i].Parent;
+ if (parent >= 0)
+ numChilds[parent]++;
+ }
+
+ for (i = 0; i < _items.Size(); i++)
+ {
+ CItem &item = _items[i];
+ int parent = item.Parent;
+ if (parent >= 0)
+ {
+ CItem &parentItem = _items[parent];
+ if (numChilds[parent] == 1)
+ if (!item.ThereIsUniqueName || !parentItem.ThereIsUniqueName || !parentItem.ThereAreSubDirs)
+ parentItem.Skip = true;
+ }
+ }
+
+ CIntVector mainToReduced;
+ for (i = 0; i < _items.Size(); i++)
+ {
+ mainToReduced.Add(_items2.Size());
+ const CItem &item = _items[i];
+ if (item.Skip)
+ continue;
+ AString name;
+ int numItems = -1;
+ int parent = item.Parent;
+ if (parent >= 0)
+ numItems = numChilds[parent];
+ AString name2 = item.GetName(numItems);
+ AString characts2 = item.Characts;
+ if (item.KeepName)
+ name = name2;
+ while (parent >= 0)
+ {
+ const CItem &item3 = _items[parent];
+ if (!item3.Skip)
+ break;
+ if (item3.KeepName)
+ {
+ AString name3 = item3.GetName(-1);
+ if (name.IsEmpty())
+ name = name3;
+ else
+ name = name3 + '.' + name;
+ }
+ AddSpaceAndString(characts2, item3.Characts);
+ parent = item3.Parent;
+ }
+ if (name.IsEmpty())
+ name = name2;
+
+ CItem2 item2;
+ item2.MainIndex = i;
+ item2.Name = name;
+ item2.Characts = characts2;
+ if (parent >= 0)
+ item2.Parent = mainToReduced[parent];
+ _items2.Add(item2);
+ /*
+ CItem2 item2;
+ item2.MainIndex = i;
+ item2.Name = item.Name;
+ item2.Parent = item.Parent;
+ _items2.Add(item2);
+ */
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *callback)
+{
+ COM_TRY_BEGIN
+ Close();
+ try
+ {
+ if (Open2(inStream, maxCheckStartPosition, callback) != S_OK)
+ return S_FALSE;
+ }
+ catch(...) { return S_FALSE; }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ _totalBufsSize = 0;
+ _methodsMask = 0;
+ _items.Clear();
+ _items2.Clear();
+ _bufs.Clear();
+ _comment.Empty();
+ _h.Clear();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = _items2.Size();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool allFilesMode = (numItems == (UInt32)-1);
+ if (allFilesMode)
+ numItems = _items2.Size();
+ if (numItems == 0)
+ return S_OK;
+ UInt64 totalSize = 0;
+ UInt32 i;
+ for (i = 0; i < numItems; i++)
+ totalSize += _items[_items2[allFilesMode ? i : indices[i]].MainIndex].Size;
+ extractCallback->SetTotal(totalSize);
+
+ UInt64 currentTotalSize = 0;
+
+ NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+ CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(extractCallback, false);
+
+ for (i = 0; i < numItems; i++)
+ {
+ lps->InSize = lps->OutSize = currentTotalSize;
+ RINOK(lps->SetCur());
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode = testMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract;
+ UInt32 index = allFilesMode ? i : indices[i];
+ const CItem &item = _items[_items2[index].MainIndex];
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+ currentTotalSize += item.Size;
+
+ if (!testMode && !realOutStream)
+ continue;
+ RINOK(extractCallback->PrepareOperation(askMode));
+ if (testMode || item.IsDir)
+ {
+ RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+ continue;
+ }
+ int res = NExtract::NOperationResult::kDataError;
+ CMyComPtr<ISequentialInStream> inStream;
+ GetStream(index, &inStream);
+ if (inStream)
+ {
+ RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
+ if (copyCoderSpec->TotalSize == item.Size)
+ res = NExtract::NOperationResult::kOK;
+ }
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(res));
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+ COM_TRY_BEGIN
+ const CItem &item = _items[_items2[index].MainIndex];
+ if (item.IsDir)
+ return S_FALSE;
+ CBufInStream *streamSpec = new CBufInStream;
+ CMyComPtr<IInStream> streamTemp = streamSpec;
+ const CByteBuffer &buf = _bufs[item.BufIndex];
+ /*
+ if (item.Offset + item.Size > buf.GetCapacity())
+ return S_FALSE;
+ */
+ streamSpec->Init(buf + item.Offset, item.Size, (IInArchive *)this);
+ *stream = streamTemp.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+
+namespace UEFIc
+{
+ static IInArchive *CreateArc() { return new CHandler(true); }
+ static CArcInfo g_ArcInfo =
+ { L"UEFIc", L"scap", 0, 0xD0, CAPSULE_SIGNATURE, kCapsuleSigSize, false, CreateArc, 0 };
+ REGISTER_ARC(UEFIc)
+}
+
+namespace UEFIs
+{
+ static IInArchive *CreateArc() { return new CHandler(false); }
+ static CArcInfo g_ArcInfo =
+ { L"UEFIs", L"", 0, 0xD1, FFS_SIGNATURE, kGuidSize, false, CreateArc, 0 };
+ REGISTER_ARC(UEFIs)
+}
+
+}}
diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
index 50b879e7..85f0771c 100755
--- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
+++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
@@ -465,7 +465,8 @@ static HRESULT UpdateArchive(ISequentialOutStream *seqOutStream,
RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
}
}
-
+ lps->InSize = lps->OutSize = complexity;
+ RINOK(lps->SetCur());
CUpdateItem ri;
FILETIME ft;
diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp
index 64b7a586..8383488b 100755
--- a/CPP/7zip/Archive/XzHandler.cpp
+++ b/CPP/7zip/Archive/XzHandler.cpp
@@ -8,6 +8,7 @@
#include "../../Common/ComTry.h"
#include "../../Common/IntToString.h"
+#include "../../Common/StringConvert.h"
#include "../ICoder.h"
@@ -40,13 +41,15 @@ namespace NXz {
struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit;
+static const wchar_t *k_LZMA2_Name = L"LZMA2";
+
class CHandler:
public IInArchive,
public IArchiveOpenSeq,
#ifndef EXTRACT_ONLY
public IOutArchive,
public ISetProperties,
- public COutHandler,
+ public CMultiMethodProps,
#endif
public CMyUnknownImp
{
@@ -62,12 +65,12 @@ class CHandler:
CMyComPtr<IInStream> _stream;
CMyComPtr<ISequentialInStream> _seqStream;
- UInt32 _crcSize;
+ UInt32 _filterId;
void Init()
{
- _crcSize = 4;
- COutHandler::Init();
+ _filterId = 0;
+ CMultiMethodProps::Init();
}
HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback);
@@ -98,14 +101,14 @@ CHandler::CHandler()
Init();
}
-STATPROPSTG kProps[] =
+static STATPROPSTG const kProps[] =
{
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidPackSize, VT_UI8},
{ NULL, kpidMethod, VT_BSTR}
};
-STATPROPSTG kArcProps[] =
+static STATPROPSTG const kArcProps[] =
{
{ NULL, kpidMethod, VT_BSTR},
{ NULL, kpidNumBlocks, VT_UI4}
@@ -160,11 +163,11 @@ struct CMethodNamePair
const char *Name;
};
-static CMethodNamePair g_NamePairs[] =
+static const CMethodNamePair g_NamePairs[] =
{
{ XZ_ID_Subblock, "SB" },
{ XZ_ID_Delta, "Delta" },
- { XZ_ID_X86, "x86" },
+ { XZ_ID_X86, "BCJ" },
{ XZ_ID_PPC, "PPC" },
{ XZ_ID_IA64, "IA64" },
{ XZ_ID_ARM, "ARM" },
@@ -439,7 +442,10 @@ struct CXzUnpackerCPP
Byte *InBuf;
Byte *OutBuf;
CXzUnpacker p;
- CXzUnpackerCPP(): InBuf(0), OutBuf(0) {}
+ CXzUnpackerCPP(): InBuf(0), OutBuf(0)
+ {
+ XzUnpacker_Construct(&p, &g_Alloc);
+ }
~CXzUnpackerCPP()
{
XzUnpacker_Free(&p);
@@ -483,7 +489,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CCompressProgressWrap progressWrap(progress);
- SRes res;
+ SRes res = S_OK;
const UInt32 kInBufSize = 1 << 15;
const UInt32 kOutBufSize = 1 << 21;
@@ -492,8 +498,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt32 inSize = 0;
UInt32 outPos = 0;
CXzUnpackerCPP xzu;
- res = XzUnpacker_Create(&xzu.p, &g_Alloc);
- if (res == SZ_OK)
+ XzUnpacker_Init(&xzu.p);
{
xzu.InBuf = (Byte *)MyAlloc(kInBufSize);
xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);
@@ -534,6 +539,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
outPos = 0;
}
+ RINOK(lps->SetCur());
if (finished)
{
_packSize = lps->InSize;
@@ -553,7 +559,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
break;
}
- RINOK(lps->SetCur());
}
Int32 opRes;
@@ -573,8 +578,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
return SResToHRESULT(res);
}
realOutStream.Release();
- RINOK(extractCallback->SetOperationResult(opRes));
- return S_OK;
+ return extractCallback->SetOperationResult(opRes);
COM_TRY_END
}
@@ -619,8 +623,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (IntToBool(newData))
{
+ UInt64 size;
{
- UInt64 size;
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
if (prop.vt != VT_UI8)
@@ -632,22 +636,26 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
CLzma2EncProps lzma2Props;
Lzma2EncProps_Init(&lzma2Props);
- lzma2Props.lzmaProps.level = _level;
+ lzma2Props.lzmaProps.level = GetLevel();
CMyComPtr<ISequentialInStream> fileInStream;
RINOK(updateCallback->GetStream(0, &fileInStream));
CSeqInStreamWrap seqInStream(fileInStream);
+ {
+ NCOM::CPropVariant prop = (UInt64)size;
+ RINOK(NCompress::NLzma2::SetLzma2Prop(NCoderPropID::kReduceSize, prop, lzma2Props));
+ }
+
for (int i = 0; i < _methods.Size(); i++)
{
COneMethodInfo &m = _methods[i];
- SetCompressionMethod2(m
+ SetGlobalLevelAndThreads(m
#ifndef _7ZIP_ST
, _numThreads
#endif
);
- if (m.IsLzma())
{
for (int j = 0; j < m.Props.Size(); j++)
{
@@ -666,7 +674,40 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
lps->Init(updateCallback, true);
CCompressProgressWrap progressWrap(progress);
- SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &lzma2Props, False, &progressWrap.p);
+ CXzProps xzProps;
+ CXzFilterProps filter;
+ XzProps_Init(&xzProps);
+ XzFilterProps_Init(&filter);
+ xzProps.lzma2Props = &lzma2Props;
+ xzProps.filterProps = (_filterId != 0 ? &filter : NULL);
+ switch (_crcSize)
+ {
+ case 0: xzProps.checkId = XZ_CHECK_NO; break;
+ case 4: xzProps.checkId = XZ_CHECK_CRC32; break;
+ case 8: xzProps.checkId = XZ_CHECK_CRC64; break;
+ case 32: xzProps.checkId = XZ_CHECK_SHA256; break;
+ default: return E_INVALIDARG;
+ }
+ filter.id = _filterId;
+ if (_filterId == XZ_ID_Delta)
+ {
+ bool deltaDefined = false;
+ for (int j = 0; j < _filterMethod.Props.Size(); j++)
+ {
+ const CProp &prop = _filterMethod.Props[j];
+ if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4)
+ {
+ UInt32 delta = (UInt32)prop.Value.ulVal;
+ if (delta < 1 || delta > 256)
+ return E_INVALIDARG;
+ filter.delta = delta;
+ deltaDefined = true;
+ }
+ }
+ if (!deltaDefined)
+ return E_INVALIDARG;
+ }
+ SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &xzProps, &progressWrap.p);
if (res == SZ_OK)
return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
return SResToHRESULT(res);
@@ -678,14 +719,46 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return NCompress::CopyStream(_stream, outStream, 0);
}
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
COM_TRY_BEGIN
- BeforeSetProperty();
+ Init();
for (int i = 0; i < numProps; i++)
{
RINOK(SetProperty(names[i], values[i]));
}
+
+ if (!_filterMethod.MethodName.IsEmpty())
+ {
+ int k;
+ for (k = 0; k < ARRAY_SIZE(g_NamePairs); k++)
+ {
+ const CMethodNamePair &pair = g_NamePairs[k];
+ UString m = GetUnicodeString(pair.Name);
+ if (_filterMethod.MethodName.CompareNoCase(m) == 0)
+ {
+ _filterId = pair.Id;
+ break;
+ }
+ }
+ if (k == ARRAY_SIZE(g_NamePairs))
+ return E_INVALIDARG;
+ }
+
+ int numEmptyMethods = GetNumEmptyMethods();
+ _methods.Delete(0, numEmptyMethods);
+ if (_methods.Size() > 1)
+ return E_INVALIDARG;
+ if (_methods.Size() == 1)
+ {
+ UString &methodName = _methods[0].MethodName;
+ if (methodName.IsEmpty())
+ methodName = k_LZMA2_Name;
+ else if (methodName.CompareNoCase(k_LZMA2_Name) != 0)
+ return E_INVALIDARG;
+ }
return S_OK;
COM_TRY_END
}
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
index 4c5fd38d..da42f3bd 100755
--- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
+++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
@@ -33,6 +33,7 @@ static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize;
class CLzmaEncoder:
public ICompressCoder,
+ public ICompressSetCoderProperties,
public CMyUnknownImp
{
NCompress::NLzma::CEncoder *EncoderSpec;
@@ -41,12 +42,12 @@ class CLzmaEncoder:
public:
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
- HRESULT SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
+ STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
- MY_UNKNOWN_IMP
+ MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
};
-HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
+STDMETHODIMP CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
{
if (!Encoder)
{
@@ -67,7 +68,7 @@ HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIAN
return S_OK;
}
-HRESULT CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+STDMETHODIMP CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
{
RINOK(WriteStream(outStream, Header, kLzmaHeaderSize));
@@ -210,52 +211,12 @@ HRESULT CAddCommon::Compress(
_compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_LZMA;
CLzmaEncoder *_lzmaEncoder = new CLzmaEncoder();
_compressEncoder = _lzmaEncoder;
- NWindows::NCOM::CPropVariant props[] =
- {
- #ifndef _7ZIP_ST
- _options.NumThreads,
- #endif
- _options.Algo,
- _options.DicSize,
- _options.NumFastBytes,
- const_cast<BSTR>((const wchar_t *)_options.MatchFinder),
- _options.NumMatchFinderCycles
- };
- PROPID propIDs[] =
- {
- #ifndef _7ZIP_ST
- NCoderPropID::kNumThreads,
- #endif
- NCoderPropID::kAlgorithm,
- NCoderPropID::kDictionarySize,
- NCoderPropID::kNumFastBytes,
- NCoderPropID::kMatchFinder,
- NCoderPropID::kMatchFinderCycles
- };
- int numProps = sizeof(propIDs) / sizeof(propIDs[0]);
- if (!_options.NumMatchFinderCyclesDefined)
- numProps--;
- RINOK(_lzmaEncoder->SetCoderProperties(propIDs, props, numProps));
}
else if (method == NFileHeader::NCompressionMethod::kPPMd)
{
_compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_PPMd;
NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder();
_compressEncoder = encoder;
- NWindows::NCOM::CPropVariant props[] =
- {
- _options.Algo,
- _options.MemSize,
- _options.Order
-
- };
- PROPID propIDs[] =
- {
- NCoderPropID::kAlgorithm,
- NCoderPropID::kUsedMemorySize,
- NCoderPropID::kOrder
- };
- RINOK(encoder->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0])));
}
else
{
@@ -282,56 +243,20 @@ HRESULT CAddCommon::Compress(
if (method == NFileHeader::NCompressionMethod::kDeflated ||
method == NFileHeader::NCompressionMethod::kDeflated64)
{
- NWindows::NCOM::CPropVariant props[] =
- {
- _options.Algo,
- _options.NumPasses,
- _options.NumFastBytes,
- _options.NumMatchFinderCycles
- };
- PROPID propIDs[] =
- {
- NCoderPropID::kAlgorithm,
- NCoderPropID::kNumPasses,
- NCoderPropID::kNumFastBytes,
- NCoderPropID::kMatchFinderCycles
- };
- int numProps = sizeof(propIDs) / sizeof(propIDs[0]);
- if (!_options.NumMatchFinderCyclesDefined)
- numProps--;
- CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
- _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties);
- if (setCoderProperties)
- {
- RINOK(setCoderProperties->SetCoderProperties(propIDs, props, numProps));
- }
}
else if (method == NFileHeader::NCompressionMethod::kBZip2)
{
- NWindows::NCOM::CPropVariant props[] =
- {
- _options.DicSize,
- _options.NumPasses
- #ifndef _7ZIP_ST
- , _options.NumThreads
- #endif
- };
- PROPID propIDs[] =
- {
- NCoderPropID::kDictionarySize,
- NCoderPropID::kNumPasses
- #ifndef _7ZIP_ST
- , NCoderPropID::kNumThreads
- #endif
- };
- CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
- _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties);
- if (setCoderProperties)
+ }
+ }
+ {
+ CMyComPtr<ICompressSetCoderProperties> setCoderProps;
+ _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProps);
+ if (setCoderProps)
{
- RINOK(setCoderProperties->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0])));
+ RINOK(_options.MethodInfo.SetCoderProps(setCoderProps,
+ _options._dataSizeReduceDefined ? &_options._dataSizeReduce : NULL));
}
}
- }
}
CMyComPtr<ISequentialOutStream> outStreamNew;
if (_options.PasswordIsDefined)
diff --git a/CPP/7zip/Archive/Zip/ZipCompressionMode.h b/CPP/7zip/Archive/Zip/ZipCompressionMode.h
index 7ef7cfb2..5be33166 100755
--- a/CPP/7zip/Archive/Zip/ZipCompressionMode.h
+++ b/CPP/7zip/Archive/Zip/ZipCompressionMode.h
@@ -5,36 +5,54 @@
#include "Common/MyString.h"
+#ifndef _7ZIP_ST
+#include "../../../Windows/System.h"
+#endif
+
+#include "../Common/HandlerOut.h"
+
namespace NArchive {
namespace NZip {
-struct CCompressionMethodMode
+struct CBaseProps
{
- CRecordVector<Byte> MethodSequence;
- UString MatchFinder;
- UInt32 Algo;
- UInt32 NumPasses;
- UInt32 NumFastBytes;
- bool NumMatchFinderCyclesDefined;
- UInt32 NumMatchFinderCycles;
- UInt32 DicSize;
- UInt32 MemSize;
- UInt32 Order;
+ CMethodProps MethodInfo;
+ Int32 Level;
#ifndef _7ZIP_ST
UInt32 NumThreads;
+ bool NumThreadsWasChanged;
#endif
- bool PasswordIsDefined;
- AString Password;
bool IsAesMode;
Byte AesKeyMode;
+
+ void Init()
+ {
+ MethodInfo.Clear();
+ Level = -1;
+ #ifndef _7ZIP_ST
+ NumThreads = NWindows::NSystem::GetNumberOfProcessors();;
+ NumThreadsWasChanged = false;
+ #endif
+ IsAesMode = false;
+ AesKeyMode = 3;
+ }
+};
+
+struct CCompressionMethodMode: public CBaseProps
+{
+ CRecordVector<Byte> MethodSequence;
+ bool PasswordIsDefined;
+ AString Password;
+
+ UInt64 _dataSizeReduce;
+ bool _dataSizeReduceDefined;
- CCompressionMethodMode():
- NumMatchFinderCyclesDefined(false),
- PasswordIsDefined(false),
- IsAesMode(false),
- AesKeyMode(3)
- {}
+ CCompressionMethodMode(): PasswordIsDefined(false)
+ {
+ _dataSizeReduceDefined = false;
+ _dataSizeReduce = 0;
+ }
};
}}
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp
index bd156322..2281ed5b 100755
--- a/CPP/7zip/Archive/Zip/ZipHandler.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp
@@ -107,7 +107,7 @@ static struct CStrongCryptoPair
{ NStrongCryptoFlags::kRC4, "RC4" }
};
-static STATPROPSTG kProps[] =
+static const STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL},
@@ -117,6 +117,7 @@ static STATPROPSTG kProps[] =
{ NULL, kpidCTime, VT_FILETIME},
{ NULL, kpidATime, VT_FILETIME},
{ NULL, kpidAttrib, VT_UI4},
+ // { NULL, kpidPosixAttrib, VT_UI4},
{ NULL, kpidEncrypted, VT_BOOL},
{ NULL, kpidComment, VT_BSTR},
{ NULL, kpidCRC, VT_UI4},
@@ -125,7 +126,7 @@ static STATPROPSTG kProps[] =
{ NULL, kpidUnpackVer, VT_UI4}
};
-static STATPROPSTG kArcProps[] =
+static const STATPROPSTG kArcProps[] =
{
{ NULL, kpidBit64, VT_BOOL},
{ NULL, kpidComment, VT_BSTR},
@@ -135,7 +136,7 @@ static STATPROPSTG kArcProps[] =
CHandler::CHandler()
{
- InitMethodProperties();
+ InitMethodProps();
}
static AString BytesToString(const CByteBuffer &data)
@@ -165,6 +166,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidComment: prop = MultiByteToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); break;
case kpidPhySize: prop = m_Archive.ArcInfo.GetPhySize(); break;
case kpidOffset: if (m_Archive.ArcInfo.StartPosition != 0) prop = m_Archive.ArcInfo.StartPosition; break;
+ case kpidError: if (!m_Archive.IsOkHeaders) prop = "Incorrect headers"; break;
}
prop.Detach(value);
COM_TRY_END
@@ -194,7 +196,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
UInt32 unixTime;
if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft))
prop = (UInt32)NFileTimeType::kWindows;
- else if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime))
+ else if (item.CentralExtra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime))
prop = (UInt32)NFileTimeType::kUnix;
else
prop = (UInt32)NFileTimeType::kDOS;
@@ -220,7 +222,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utc))
{
UInt32 unixTime;
- if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime))
+ if (item.CentralExtra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime))
NTime::UnixTimeToFileTime(unixTime, utc);
else
{
@@ -233,7 +235,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = utc;
break;
}
- case kpidAttrib: prop = item.GetWinAttributes(); break;
+ case kpidAttrib: prop = item.GetWinAttrib(); break;
+ case kpidPosixAttrib:
+ {
+ UInt32 attrib;
+ if (item.GetPosixAttrib(attrib))
+ prop = attrib;
+ break;
+ }
case kpidEncrypted: prop = item.IsEncrypted(); break;
case kpidComment: prop = item.GetUnicodeString(BytesToString(item.Comment)); break;
case kpidCRC: if (item.IsThereCrc()) prop = item.FileCRC; break;
@@ -435,7 +444,10 @@ public:
ISequentialOutStream *realOutStream,
IArchiveExtractCallback *extractCallback,
ICompressProgressInfo *compressProgress,
- UInt32 numThreads, Int32 &res);
+ #ifndef _7ZIP_ST
+ UInt32 numThreads,
+ #endif
+ Int32 &res);
};
HRESULT CZipDecoder::Decode(
@@ -444,7 +456,10 @@ HRESULT CZipDecoder::Decode(
ISequentialOutStream *realOutStream,
IArchiveExtractCallback *extractCallback,
ICompressProgressInfo *compressProgress,
- UInt32 numThreads, Int32 &res)
+ #ifndef _7ZIP_ST
+ UInt32 numThreads,
+ #endif
+ Int32 &res)
{
res = NExtract::NOperationResult::kDataError;
CInStreamReleaser inStreamReleaser;
@@ -805,15 +820,22 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->PrepareOperation(askMode));
Int32 res;
- RINOK(myDecoder.Decode(
+ HRESULT hres = myDecoder.Decode(
EXTERNAL_CODECS_VARS
m_Archive, item, realOutStream, extractCallback,
- progress, _numThreads, res));
+ progress,
+ #ifndef _7ZIP_ST
+ _props.NumThreads,
+ #endif
+ res);
+ RINOK(hres);
realOutStream.Release();
RINOK(extractCallback->SetOperationResult(res))
}
- return S_OK;
+ lps->InSize = currentTotalPacked;
+ lps->OutSize = currentTotalUnPacked;
+ return lps->SetCur();
COM_TRY_END
}
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h
index fdb60aaf..33cf6fdc 100755
--- a/CPP/7zip/Archive/Zip/ZipHandler.h
+++ b/CPP/7zip/Archive/Zip/ZipHandler.h
@@ -12,10 +12,6 @@
#include "ZipIn.h"
#include "ZipCompressionMode.h"
-#ifndef _7ZIP_ST
-#include "../../../Windows/System.h"
-#endif
-
namespace NArchive {
namespace NZip {
@@ -46,53 +42,24 @@ private:
CObjectVector<CItemEx> m_Items;
CInArchive m_Archive;
- int m_Level;
- int m_MainMethod;
- UInt32 m_DicSize;
- UInt32 m_Algo;
- UInt32 m_NumPasses;
- UInt32 m_NumFastBytes;
- UInt32 m_NumMatchFinderCycles;
- UInt32 m_MemSize;
- UInt32 m_Order;
-
- bool m_NumMatchFinderCyclesDefined;
+ CBaseProps _props;
+ int m_MainMethod;
bool m_ForceAesMode;
- bool m_IsAesMode;
- Byte m_AesKeyMode;
-
bool m_WriteNtfsTimeExtra;
bool m_ForceLocal;
bool m_ForceUtf8;
- #ifndef _7ZIP_ST
- UInt32 _numThreads;
- #endif
-
DECL_EXTERNAL_CODECS_VARS
- void InitMethodProperties()
+ void InitMethodProps()
{
- m_Level = -1;
+ _props.Init();
m_MainMethod = -1;
- m_Algo =
- m_DicSize =
- m_NumPasses =
- m_NumFastBytes =
- m_Order =
- m_MemSize =
- m_NumMatchFinderCycles = 0xFFFFFFFF;
- m_NumMatchFinderCyclesDefined = false;
m_ForceAesMode = false;
- m_IsAesMode = false;
- m_AesKeyMode = 3; // aes-256
m_WriteNtfsTimeExtra = true;
m_ForceLocal = false;
m_ForceUtf8 = false;
- #ifndef _7ZIP_ST
- _numThreads = NWindows::NSystem::GetNumberOfProcessors();;
- #endif
}
};
diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
index a5e0f59d..427b0c31 100755
--- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
@@ -28,37 +28,6 @@ using namespace NTime;
namespace NArchive {
namespace NZip {
-static const UInt32 kLzAlgoX1 = 0;
-static const UInt32 kLzAlgoX5 = 1;
-
-static const UInt32 kDeflateNumPassesX1 = 1;
-static const UInt32 kDeflateNumPassesX7 = 3;
-static const UInt32 kDeflateNumPassesX9 = 10;
-
-static const UInt32 kDeflateNumFastBytesX1 = 32;
-static const UInt32 kDeflateNumFastBytesX7 = 64;
-static const UInt32 kDeflateNumFastBytesX9 = 128;
-
-static const wchar_t *kLzmaMatchFinderX1 = L"HC4";
-static const wchar_t *kLzmaMatchFinderX5 = L"BT4";
-
-static const UInt32 kLzmaNumFastBytesX1 = 32;
-static const UInt32 kLzmaNumFastBytesX7 = 64;
-
-static const UInt32 kLzmaDicSizeX1 = 1 << 16;
-static const UInt32 kLzmaDicSizeX3 = 1 << 20;
-static const UInt32 kLzmaDicSizeX5 = 1 << 24;
-static const UInt32 kLzmaDicSizeX7 = 1 << 25;
-static const UInt32 kLzmaDicSizeX9 = 1 << 26;
-
-static const UInt32 kBZip2NumPassesX1 = 1;
-static const UInt32 kBZip2NumPassesX7 = 2;
-static const UInt32 kBZip2NumPassesX9 = 7;
-
-static const UInt32 kBZip2DicSizeX1 = 100000;
-static const UInt32 kBZip2DicSizeX3 = 500000;
-static const UInt32 kBZip2DicSizeX5 = 900000;
-
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
{
*timeType = NFileTimeType::kDOS;
@@ -99,6 +68,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
COM_TRY_BEGIN2
CObjectVector<CUpdateItem> updateItems;
bool thereAreAesUpdates = false;
+ UInt64 largestSize = 0;
+ bool largestSizeDefined = false;
for (UInt32 i = 0; i < numItems; i++)
{
CUpdateItem ui;
@@ -178,7 +149,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
const wchar_t kSlash = L'/';
if (!name.IsEmpty())
{
- if (name[name.Length() - 1] == kSlash)
+ if (name.Back() == kSlash)
{
if (!ui.IsDir)
return E_INVALIDARG;
@@ -235,6 +206,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (prop.vt != VT_UI8)
return E_INVALIDARG;
size = prop.uhVal.QuadPart;
+ if (largestSize < size)
+ largestSize = size;
+ largestSizeDefined = true;
}
ui.Size = size;
}
@@ -247,6 +221,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
udateCallBack2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);
}
CCompressionMethodMode options;
+ (CBaseProps &)options = _props;
+ options._dataSizeReduce = largestSize;
+ options._dataSizeReduceDefined = largestSizeDefined;
if (getTextPassword)
{
@@ -256,8 +233,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options.PasswordIsDefined = IntToBool(passwordIsDefined);
if (options.PasswordIsDefined)
{
- options.IsAesMode = (m_ForceAesMode ? m_IsAesMode : thereAreAesUpdates);
- options.AesKeyMode = m_AesKeyMode;
+ if (!m_ForceAesMode)
+ options.IsAesMode = thereAreAesUpdates;
if (!IsAsciiString((const wchar_t *)password))
return E_INVALIDARG;
@@ -272,13 +249,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
else
options.PasswordIsDefined = false;
- int level = m_Level;
- if (level < 0)
- level = 5;
-
Byte mainMethod;
if (m_MainMethod < 0)
- mainMethod = (Byte)(((level == 0) ?
+ mainMethod = (Byte)(((_props.Level == 0) ?
NFileHeader::NCompressionMethod::kStored :
NFileHeader::NCompressionMethod::kDeflated));
else
@@ -286,83 +259,6 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options.MethodSequence.Add(mainMethod);
if (mainMethod != NFileHeader::NCompressionMethod::kStored)
options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored);
- bool isDeflate = (mainMethod == NFileHeader::NCompressionMethod::kDeflated) ||
- (mainMethod == NFileHeader::NCompressionMethod::kDeflated64);
- bool isLZMA = (mainMethod == NFileHeader::NCompressionMethod::kLZMA);
- bool isLz = (isLZMA || isDeflate);
- options.NumPasses = m_NumPasses;
- options.DicSize = m_DicSize;
- options.NumFastBytes = m_NumFastBytes;
- options.NumMatchFinderCycles = m_NumMatchFinderCycles;
- options.NumMatchFinderCyclesDefined = m_NumMatchFinderCyclesDefined;
- options.Algo = m_Algo;
- options.MemSize = m_MemSize;
- options.Order = m_Order;
- #ifndef _7ZIP_ST
- options.NumThreads = _numThreads;
- #endif
- if (isLz)
- {
- if (isDeflate)
- {
- if (options.NumPasses == 0xFFFFFFFF)
- options.NumPasses = (level >= 9 ? kDeflateNumPassesX9 :
- (level >= 7 ? kDeflateNumPassesX7 :
- kDeflateNumPassesX1));
- if (options.NumFastBytes == 0xFFFFFFFF)
- options.NumFastBytes = (level >= 9 ? kDeflateNumFastBytesX9 :
- (level >= 7 ? kDeflateNumFastBytesX7 :
- kDeflateNumFastBytesX1));
- }
- else if (isLZMA)
- {
- if (options.DicSize == 0xFFFFFFFF)
- options.DicSize =
- (level >= 9 ? kLzmaDicSizeX9 :
- (level >= 7 ? kLzmaDicSizeX7 :
- (level >= 5 ? kLzmaDicSizeX5 :
- (level >= 3 ? kLzmaDicSizeX3 :
- kLzmaDicSizeX1))));
-
- if (options.NumFastBytes == 0xFFFFFFFF)
- options.NumFastBytes = (level >= 7 ? kLzmaNumFastBytesX7 :
- kLzmaNumFastBytesX1);
-
- options.MatchFinder =
- (level >= 5 ? kLzmaMatchFinderX5 :
- kLzmaMatchFinderX1);
- }
-
- if (options.Algo == 0xFFFFFFFF)
- options.Algo = (level >= 5 ? kLzAlgoX5 :
- kLzAlgoX1);
- }
- if (mainMethod == NFileHeader::NCompressionMethod::kBZip2)
- {
- if (options.NumPasses == 0xFFFFFFFF)
- options.NumPasses = (level >= 9 ? kBZip2NumPassesX9 :
- (level >= 7 ? kBZip2NumPassesX7 :
- kBZip2NumPassesX1));
- if (options.DicSize == 0xFFFFFFFF)
- options.DicSize = (level >= 5 ? kBZip2DicSizeX5 :
- (level >= 3 ? kBZip2DicSizeX3 :
- kBZip2DicSizeX1));
- }
- if (mainMethod == NFileHeader::NCompressionMethod::kPPMd)
- {
- int level2 = level;
- if (level2 < 1) level2 = 1;
- if (level2 > 9) level2 = 9;
-
- if (options.MemSize == 0xFFFFFFFF)
- options.MemSize = (1 << (19 + (level2 > 8 ? 8 : level2)));
-
- if (options.Order == 0xFFFFFFFF)
- options.Order = 3 + level2;
-
- if (options.Algo == 0xFFFFFFFF)
- options.Algo = (level2 >= 7 ? 1 : 0);
- }
return Update(
EXTERNAL_CODECS_VARS
@@ -371,16 +267,34 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
COM_TRY_END2
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
+struct CMethodIndexToName
+{
+ unsigned Method;
+ const wchar_t *Name;
+};
+
+static const CMethodIndexToName k_SupportedMethods[] =
{
+ { NFileHeader::NCompressionMethod::kStored, L"COPY" },
+ { NFileHeader::NCompressionMethod::kDeflated, L"DEFLATE" },
+ { NFileHeader::NCompressionMethod::kDeflated64, L"DEFLATE64" },
+ { NFileHeader::NCompressionMethod::kBZip2, L"BZIP2" },
+ { NFileHeader::NCompressionMethod::kLZMA, L"LZMA" },
+ { NFileHeader::NCompressionMethod::kPPMd, L"PPMD" }
+};
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
+{
+ InitMethodProps();
#ifndef _7ZIP_ST
- const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
- _numThreads = numProcessors;
+ const UInt32 numProcessors = _props.NumThreads;
#endif
- InitMethodProperties();
- for (int i = 0; i < numProperties; i++)
+
+ for (int i = 0; i < numProps; i++)
{
- UString name = UString(names[i]);
+ UString name = names[i];
name.MakeUpper();
if (name.IsEmpty())
return E_INVALIDARG;
@@ -390,140 +304,112 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
if (name[0] == L'X')
{
UInt32 level = 9;
- RINOK(ParsePropValue(name.Mid(1), prop, level));
- m_Level = level;
- continue;
+ RINOK(ParsePropToUInt32(name.Mid(1), prop, level));
+ _props.Level = level;
+ _props.MethodInfo.AddLevelProp(level);
}
else if (name == L"M")
{
if (prop.vt == VT_BSTR)
{
- UString m = prop.bstrVal;
+ UString m = prop.bstrVal, m2;
m.MakeUpper();
- if (m == L"COPY") m_MainMethod = NFileHeader::NCompressionMethod::kStored;
- else if (m == L"DEFLATE") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated;
- else if (m == L"DEFLATE64") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated64;
- else if (m == L"BZIP2") m_MainMethod = NFileHeader::NCompressionMethod::kBZip2;
- else if (m == L"LZMA") m_MainMethod = NFileHeader::NCompressionMethod::kLZMA;
- else if (m == L"PPMD") m_MainMethod = NFileHeader::NCompressionMethod::kPPMd;
- else return E_INVALIDARG;
+ int colonPos = m.Find(L':');
+ if (colonPos >= 0)
+ {
+ m2 = m.Mid(colonPos + 1);
+ m = m.Left(colonPos);
+ }
+ int k;
+ for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++)
+ {
+ const CMethodIndexToName &pair = k_SupportedMethods[k];
+ if (m == pair.Name)
+ {
+ if (!m2.IsEmpty())
+ {
+ RINOK(_props.MethodInfo.ParseParamsFromString(m2));
+ }
+ m_MainMethod = pair.Method;
+ break;
+ }
+ }
+ if (k == ARRAY_SIZE(k_SupportedMethods))
+ return E_INVALIDARG;
}
else if (prop.vt == VT_UI4)
{
- switch(prop.ulVal)
+ int k;
+ for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++)
{
- case NFileHeader::NCompressionMethod::kStored:
- case NFileHeader::NCompressionMethod::kDeflated:
- case NFileHeader::NCompressionMethod::kDeflated64:
- case NFileHeader::NCompressionMethod::kBZip2:
- case NFileHeader::NCompressionMethod::kLZMA:
- m_MainMethod = (Byte)prop.ulVal;
+ unsigned method = k_SupportedMethods[k].Method;
+ if (prop.ulVal == method)
+ {
+ m_MainMethod = method;
break;
- default:
- return E_INVALIDARG;
+ }
}
+ if (k == ARRAY_SIZE(k_SupportedMethods))
+ return E_INVALIDARG;
}
else
return E_INVALIDARG;
}
else if (name.Left(2) == L"EM")
{
- if (prop.vt == VT_BSTR)
+ if (prop.vt != VT_BSTR)
+ return E_INVALIDARG;
{
- UString valueString = prop.bstrVal;
- valueString.MakeUpper();
- if (valueString.Left(3) == L"AES")
+ UString m = prop.bstrVal;
+ m.MakeUpper();
+ if (m.Left(3) == L"AES")
{
- valueString = valueString.Mid(3);
- if (valueString == L"128")
- m_AesKeyMode = 1;
- else if (valueString == L"192")
- m_AesKeyMode = 2;
- else if (valueString == L"256" || valueString.IsEmpty())
- m_AesKeyMode = 3;
+ m = m.Mid(3);
+ if (m == L"128")
+ _props.AesKeyMode = 1;
+ else if (m == L"192")
+ _props.AesKeyMode = 2;
+ else if (m == L"256" || m.IsEmpty())
+ _props.AesKeyMode = 3;
else
return E_INVALIDARG;
- m_IsAesMode = true;
+ _props.IsAesMode = true;
m_ForceAesMode = true;
}
- else if (valueString == L"ZIPCRYPTO")
+ else if (m == L"ZIPCRYPTO")
{
- m_IsAesMode = false;
+ _props.IsAesMode = false;
m_ForceAesMode = true;
}
else
return E_INVALIDARG;
}
- else
- return E_INVALIDARG;
- }
- else if (name[0] == L'D')
- {
- UInt32 dicSize = kBZip2DicSizeX5;
- RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize));
- m_DicSize = dicSize;
- }
- else if (name.Left(3) == L"MEM")
- {
- UInt32 memSize = 1 << 24;
- RINOK(ParsePropDictionaryValue(name.Mid(3), prop, memSize));
- m_MemSize = memSize;
- }
- else if (name[0] == L'O')
- {
- UInt32 order = 8;
- RINOK(ParsePropValue(name.Mid(1), prop, order));
- m_Order = order;
- }
- else if (name.Left(4) == L"PASS")
- {
- UInt32 num = kDeflateNumPassesX9;
- RINOK(ParsePropValue(name.Mid(4), prop, num));
- m_NumPasses = num;
- }
- else if (name.Left(2) == L"FB")
- {
- UInt32 num = kDeflateNumFastBytesX9;
- RINOK(ParsePropValue(name.Mid(2), prop, num));
- m_NumFastBytes = num;
- }
- else if (name.Left(2) == L"MC")
- {
- UInt32 num = 0xFFFFFFFF;
- RINOK(ParsePropValue(name.Mid(2), prop, num));
- m_NumMatchFinderCycles = num;
- m_NumMatchFinderCyclesDefined = true;
}
else if (name.Left(2) == L"MT")
{
#ifndef _7ZIP_ST
- RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads));
+ RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _props.NumThreads));
+ _props.NumThreadsWasChanged = true;
#endif
}
- else if (name.Left(1) == L"A")
- {
- UInt32 num = kLzAlgoX5;
- RINOK(ParsePropValue(name.Mid(1), prop, num));
- m_Algo = num;
- }
else if (name.CompareNoCase(L"TC") == 0)
{
- RINOK(SetBoolProperty(m_WriteNtfsTimeExtra, prop));
+ RINOK(PROPVARIANT_to_bool(prop, m_WriteNtfsTimeExtra));
}
else if (name.CompareNoCase(L"CL") == 0)
{
- RINOK(SetBoolProperty(m_ForceLocal, prop));
+ RINOK(PROPVARIANT_to_bool(prop, m_ForceLocal));
if (m_ForceLocal)
m_ForceUtf8 = false;
}
else if (name.CompareNoCase(L"CU") == 0)
{
- RINOK(SetBoolProperty(m_ForceUtf8, prop));
+ RINOK(PROPVARIANT_to_bool(prop, m_ForceUtf8));
if (m_ForceUtf8)
m_ForceLocal = false;
}
else
- return E_INVALIDARG;
+ return _props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop);
}
return S_OK;
}
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp
index b36b61be..e930488f 100755
--- a/CPP/7zip/Archive/Zip/ZipIn.cpp
+++ b/CPP/7zip/Archive/Zip/ZipIn.cpp
@@ -756,6 +756,7 @@ void CEcd64::Parse(const Byte *p)
HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress)
{
+ IsOkHeaders = true;
// m_Signature must be kLocalFileHeaderSignature or
// kEndOfCentralDirSignature
// m_Position points to next byte after signature
@@ -852,6 +853,8 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0)
throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
+ if (numCdItems != items.Size())
+ IsOkHeaders = false;
if ((UInt16)ecd64.numEntriesInCDOnThisDisk != ((UInt16)numCdItems) ||
(UInt16)ecd64.numEntriesInCD != ((UInt16)numCdItems) ||
(UInt32)ecd64.cdSize != (UInt32)cdSize ||
@@ -861,7 +864,6 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
_inBufMode = false;
_inBuffer.Free();
- IsOkHeaders = (numCdItems == items.Size());
ArcInfo.FinishPosition = m_Position;
return S_OK;
}
diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp
index 139b0129..ad89f558 100755
--- a/CPP/7zip/Archive/Zip/ZipItem.cpp
+++ b/CPP/7zip/Archive/Zip/ZipItem.cpp
@@ -51,7 +51,7 @@ bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const
return false;
}
-bool CExtraSubBlock::ExtractUnixTime(int index, UInt32 &res) const
+bool CExtraSubBlock::ExtractUnixTime(bool isCentral, int index, UInt32 &res) const
{
res = 0;
UInt32 size = (UInt32)Data.GetCapacity();
@@ -60,6 +60,15 @@ bool CExtraSubBlock::ExtractUnixTime(int index, UInt32 &res) const
const Byte *p = (const Byte *)Data;
Byte flags = *p++;
size--;
+ if (isCentral)
+ {
+ if (index != NFileHeader::NUnixTime::kMTime ||
+ (flags & (1 << NFileHeader::NUnixTime::kMTime)) == 0 ||
+ size < 4)
+ return false;
+ res = GetUi32(p);
+ return true;
+ }
for (int i = 0; i < 3; i++)
if ((flags & (1 << i)) != 0)
{
@@ -88,7 +97,7 @@ bool CItem::IsDir() const
if (!FromCentral)
return false;
WORD highAttributes = WORD((ExternalAttributes >> 16 ) & 0xFFFF);
- switch(MadeByVersion.HostOS)
+ switch (MadeByVersion.HostOS)
{
case NFileHeader::NHostOS::kAMIGA:
switch (highAttributes & NFileHeader::NAmigaAttribute::kIFMT)
@@ -109,44 +118,41 @@ bool CItem::IsDir() const
case NFileHeader::NHostOS::kAcorn:
case NFileHeader::NHostOS::kMVS:
return false; // change it throw kUnknownAttributes;
+ case NFileHeader::NHostOS::kUnix:
+ return (highAttributes & NFileHeader::NUnixAttribute::kIFDIR) != 0;
default:
- /*
- switch (highAttributes & NFileHeader::NUnixAttribute::kIFMT)
- {
- case NFileHeader::NUnixAttribute::kIFDIR:
- return true;
- default:
- return false;
- }
- */
return false;
}
}
-UInt32 CLocalItem::GetWinAttributes() const
-{
- DWORD winAttributes = 0;
- if (IsDir())
- winAttributes |= FILE_ATTRIBUTE_DIRECTORY;
- return winAttributes;
-}
-
-UInt32 CItem::GetWinAttributes() const
+UInt32 CItem::GetWinAttrib() const
{
- DWORD winAttributes = 0;
- switch(MadeByVersion.HostOS)
+ DWORD winAttrib = 0;
+ switch (MadeByVersion.HostOS)
{
case NFileHeader::NHostOS::kFAT:
case NFileHeader::NHostOS::kNTFS:
if (FromCentral)
- winAttributes = ExternalAttributes;
+ winAttrib = ExternalAttributes;
break;
- default:
- winAttributes = 0; // must be converted from unix value;
}
- if (IsDir()) // test it;
- winAttributes |= FILE_ATTRIBUTE_DIRECTORY;
- return winAttributes;
+ if (IsDir()) // test it;
+ winAttrib |= FILE_ATTRIBUTE_DIRECTORY;
+ return winAttrib;
+}
+
+bool CItem::GetPosixAttrib(UInt32 &attrib) const
+{
+ // some archivers can store PosixAttrib in high 16 bits even with HostOS=FAT.
+ if (FromCentral && MadeByVersion.HostOS == NFileHeader::NHostOS::kUnix)
+ {
+ attrib = ExternalAttributes >> 16;
+ return (attrib != 0);
+ }
+ attrib = 0;
+ if (IsDir())
+ attrib = NFileHeader::NUnixAttribute::kIFDIR;
+ return false;
}
void CLocalItem::SetFlagBits(int startBitNumber, int numBits, int value)
diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h
index 31f2de73..5efd433a 100755
--- a/CPP/7zip/Archive/Zip/ZipItem.h
+++ b/CPP/7zip/Archive/Zip/ZipItem.h
@@ -3,7 +3,6 @@
#ifndef __ARCHIVE_ZIP_ITEM_H
#define __ARCHIVE_ZIP_ITEM_H
-#include "Common/Types.h"
#include "Common/MyString.h"
#include "Common/Buffer.h"
#include "Common/UTFConvert.h"
@@ -28,7 +27,7 @@ struct CExtraSubBlock
UInt16 ID;
CByteBuffer Data;
bool ExtractNtfsTime(int index, FILETIME &ft) const;
- bool ExtractUnixTime(int index, UInt32 &res) const;
+ bool ExtractUnixTime(bool isCentral, int index, UInt32 &res) const;
};
struct CWzAesExtraField
@@ -152,13 +151,13 @@ struct CExtraBlock
return false;
}
- bool GetUnixTime(int index, UInt32 &res) const
+ bool GetUnixTime(bool isCentral, int index, UInt32 &res) const
{
for (int i = 0; i < SubBlocks.Size(); i++)
{
const CExtraSubBlock &sb = SubBlocks[i];
if (sb.ID == NFileHeader::NExtraID::kUnixTime)
- return sb.ExtractUnixTime(index, res);
+ return sb.ExtractUnixTime(isCentral, index, res);
}
return false;
}
@@ -205,7 +204,6 @@ public:
bool IsDir() const;
bool IgnoreItem() const { return false; }
- UInt32 GetWinAttributes() const;
bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
@@ -252,7 +250,8 @@ public:
bool NtfsTimeIsDefined;
bool IsDir() const;
- UInt32 GetWinAttributes() const;
+ UInt32 GetWinAttrib() const;
+ bool GetPosixAttrib(UInt32 &attrib) const;
bool IsThereCrc() const
{
@@ -277,5 +276,3 @@ public:
}}
#endif
-
-
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
index d4fdee3d..490d9e26 100755
--- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
@@ -473,6 +473,9 @@ static HRESULT Update2St(
items.Add(item);
lps->ProgressOffset += NFileHeader::kLocalBlockSize;
}
+ lps->InSize = unpackSizeTotal;
+ lps->OutSize = packSizeTotal;
+ RINOK(lps->SetCur());
archive.WriteCentralDir(items, comment);
return S_OK;
}
@@ -493,7 +496,7 @@ static HRESULT Update2(
UInt64 numBytesToCompress = 0;
int i;
- for(i = 0; i < updateItems.Size(); i++)
+ for (i = 0; i < updateItems.Size(); i++)
{
const CUpdateItem &ui = updateItems[i];
if (ui.NewData)
@@ -527,6 +530,10 @@ static HRESULT Update2(
complexity = 0;
+ CCompressionMethodMode options2;
+ if (options != 0)
+ options2 = *options;
+
#ifndef _7ZIP_ST
const size_t kNumMaxThreads = (1 << 10);
@@ -537,53 +544,58 @@ static HRESULT Update2(
const size_t kMemPerThread = (1 << 25);
const size_t kBlockSize = 1 << 16;
- CCompressionMethodMode options2;
- if (options != 0)
- options2 = *options;
-
bool mtMode = ((options != 0) && (numThreads > 1));
if (numFilesToCompress <= 1)
mtMode = false;
- if (mtMode)
+ if (!mtMode)
+ {
+ if (numThreads < 2)
+ if (options2.MethodInfo.FindProp(NCoderPropID::kNumThreads) < 0 &&
+ options2.NumThreadsWasChanged)
+ options2.MethodInfo.AddNumThreadsProp(1);
+ }
+ else
{
Byte method = options->MethodSequence.Front();
if (method == NFileHeader::NCompressionMethod::kStored && !options->PasswordIsDefined)
- mtMode = false;
+ numThreads = 1;
if (method == NFileHeader::NCompressionMethod::kBZip2)
{
- UInt64 averageSize = numBytesToCompress / numFilesToCompress;
- UInt32 blockSize = options->DicSize;
- if (blockSize == 0)
- blockSize = 1;
- UInt64 averageNumberOfBlocks = averageSize / blockSize;
- UInt32 numBZip2Threads = 32;
- if (averageNumberOfBlocks < numBZip2Threads)
- numBZip2Threads = (UInt32)averageNumberOfBlocks;
- if (numBZip2Threads < 1)
- numBZip2Threads = 1;
- numThreads = numThreads / numBZip2Threads;
- options2.NumThreads = numBZip2Threads;
- if (numThreads <= 1)
- mtMode = false;
+ bool fixedNumber;
+ UInt32 numBZip2Threads = options2.MethodInfo.Get_BZip2_NumThreads(fixedNumber);
+ if (!fixedNumber)
+ {
+ UInt64 averageSize = numBytesToCompress / numFilesToCompress;
+ UInt32 blockSize = options2.MethodInfo.Get_BZip2_BlockSize();
+ UInt64 averageNumberOfBlocks = averageSize / blockSize + 1;
+ numBZip2Threads = 32;
+ if (averageNumberOfBlocks < numBZip2Threads)
+ numBZip2Threads = (UInt32)averageNumberOfBlocks;
+ options2.MethodInfo.AddNumThreadsProp(numBZip2Threads);
+ }
+ numThreads /= numBZip2Threads;
}
if (method == NFileHeader::NCompressionMethod::kLZMA)
{
- UInt32 numLZMAThreads = (options->Algo > 0 ? 2 : 1);
+ bool fixedNumber;
+ // we suppose that default LZMA is 2 thread. So we don't change it
+ UInt32 numLZMAThreads = options2.MethodInfo.Get_Lzma_NumThreads(fixedNumber);
numThreads /= numLZMAThreads;
- options2.NumThreads = numLZMAThreads;
- if (numThreads <= 1)
- mtMode = false;
}
+ if (numThreads > numFilesToCompress)
+ numThreads = (UInt32)numFilesToCompress;
+ if (numThreads <= 1)
+ mtMode = false;
}
if (!mtMode)
#endif
return Update2St(
EXTERNAL_CODECS_LOC_VARS
- archive, inArchive,inStream,
- inputItems, updateItems, options, comment, updateCallback);
+ archive, inArchive, inStream,
+ inputItems, updateItems, &options2, comment, updateCallback);
#ifndef _7ZIP_ST
@@ -606,7 +618,7 @@ static HRESULT Update2(
{
RINOK(memManager.AllocateSpaceAlways((size_t)numThreads * (kMemPerThread / kBlockSize)));
- for(i = 0; i < updateItems.Size(); i++)
+ for (i = 0; i < updateItems.Size(); i++)
refs.Refs.Add(CMemBlocks2());
UInt32 i;
@@ -796,6 +808,7 @@ static HRESULT Update2(
mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);
itemIndex++;
}
+ RINOK(mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL));
archive.WriteCentralDir(items, comment);
return S_OK;
#endif