This commit is contained in:
Igor Pavlov
2011-04-11 00:00:00 +00:00
committed by Kornel Lesiński
parent de4f8c22fe
commit 35596517f2
322 changed files with 9989 additions and 7759 deletions

View File

@@ -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); }
};

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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 (_compressHeaders)
{
// headerMethod.Methods.Add(methodMode.Methods.Back());
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);
}
if (!FindMethod(
EXTERNAL_CODECS_VARS
m.MethodName, dest.Id, dest.NumInStreams, dest.NumOutStreams))
return E_INVALIDARG;
(CProps &)dest = (CProps &)m;
return S_OK;
}
HRESULT CHandler::SetCompressionMethod(
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;
}
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);
}
}
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;
}
_numSolidBytes = (UInt64)dicSize << 7;
if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min;
if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max;
_numSolidBytesDefined = true;
}
if (!needSolid && !_numSolidBytesDefined)
{
_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;
}
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
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;
}
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
}

View File

@@ -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 processedSize;
RINOK(stream->Read(buffer + kHeaderSize, kBufferSize - kHeaderSize, &processedSize));
if (processedSize == 0)
return S_FALSE;
for (UInt32 pos = 1; pos <= processedSize; pos++)
{
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++)
{
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;

View File

@@ -133,6 +133,7 @@ class CInArchive
CInByte2 *_inByteBack;
UInt64 _arhiveBeginStreamPosition;
UInt64 _fileEndPosition;
Byte _header[kHeaderSize];

View File

@@ -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 MakeExeMethod(const CCompressionMethodMode &method,
bool bcj2Filter, CCompressionMethodMode &exeMethod)
static void AddBcj2Methods(CCompressionMethodMode &mode)
{
exeMethod = method;
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(CCompressionMethodMode &mode,
bool useFilters, bool addFilter, bool bcj2Filter)
{
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;
}

View File

@@ -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; }

View File

@@ -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;
}
if (res == E_INVALIDARG)
{
RINOK(cabFolderOutStream->Unsupported());
totalUnPacked += curUnpack;
continue;
}
RINOK(res);
cabBlockInStreamSpec->InitForNewFolder();
HRESULT res = S_OK;
{
int volIndex = mvItem.VolumeIndex;
int locFolderIndex = item.GetFolderIndex(db.Folders.Size());

View File

@@ -39,7 +39,7 @@ struct CItem
{
if (Name.Length() == 0)
return false;
return (Name[Name.Length() - 1] == '/');
return (Name.Back() == '/');
}
};

View File

@@ -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));

View File

@@ -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);

View File

@@ -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)

View File

@@ -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

View File

@@ -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));

View File

@@ -18,6 +18,7 @@ struct CCoder: public CCoderInfo, public CVirtThread
virtual void Execute();
void Code(ICompressProgressInfo *progress);
~CCoder() { CVirtThread::WaitThreadFinish(); }
};
/*

View File

@@ -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
static void SetMethodProp32(COneMethodInfo &m, PROPID propID, UInt32 value)
{
return
AreEqual(MethodName, kLZMAMethodName) ||
AreEqual(MethodName, kLZMA2MethodName);
if (m.FindProp(propID) < 0)
m.AddProp32(propID, value);
}
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)
{
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;
}
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
}
void CMultiMethodProps::Init()
{
#ifndef _7ZIP_ST
_numProcessors = _numThreads = NSystem::GetNumberOfProcessors();
#endif
_level = 5;
_level = (UInt32)(UInt32)-1;
_autoFilter = true;
_volumeMode = false;
_crcSize = 4;
InitSolid();
_filterMethod.Clear();
_methods.Clear();
}
void COutHandler::BeforeSetProperty()
{
Init();
#ifndef _7ZIP_ST
numProcessors = NSystem::GetNumberOfProcessors();
#endif
mainDicSize = 0xFFFFFFFF;
mainDicMethodIndex = 0xFFFFFFFF;
minNumber = 0;
_crcSize = 4;
}
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
{
int index = FindPropIdStart(realName);
if (index < 0)
return E_INVALIDARG;
const CNameToPropID &nameToPropID = g_NameToPropID[index];
CProp prop;
prop.Id = nameToPropID.PropID;
for (int j = _methods.Size(); j <= (int)number; j++)
_methods.Add(COneMethodInfo());
return _methods[number].ParseMethodFromPROPVARIANT(realName, value);
}
if (prop.Id == NCoderPropID::kBlockSize ||
prop.Id == NCoderPropID::kDictionarySize ||
prop.Id == NCoderPropID::kUsedMemorySize)
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++)
{
UString name = names[i];
name.MakeUpper();
if (name.IsEmpty())
return E_INVALIDARG;
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 if (name.Left(2).CompareNoCase(L"MT") == 0)
{
#ifndef _7ZIP_ST
RINOK(ParseMtProp(name.Mid(2), value, _numProcessors, _numThreads));
AddNumThreadsProp(_numThreads);
#endif
}
else
{
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;
}
oneMethodInfo.Props.Add(prop);
return ParseParamsFromPROPVARIANT(name, value);
}
return S_OK;
}

View File

@@ -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);
};
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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; }

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 ||

View File

@@ -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;

View File

@@ -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)
}
}

View File

@@ -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);

View File

@@ -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)
if (!_zlibDecoder)
{
_inputBuffer.Free();
_inputBuffer.SetCapacity(inSize);
_zlibDecoderSpec = new NCompress::NZlib::CDecoder();
_zlibDecoder = _zlibDecoderSpec;
}
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;
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,16 +2103,19 @@ 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)
{
if (copyCoderSpec->TotalSize == unpackSize)
res = NExtract::NOperationResult::kOK;
}
else if (hres == E_NOTIMPL)
{
res = NExtract::NOperationResult::kUnSupportedMethod;
}
else if(hres != S_FALSE)
{
RINOK(hres);
}
if (copyCoderSpec->TotalSize == unpackSize && hres == S_OK)
res = NExtract::NOperationResult::kOK;
else
{
res = res;
}
}
}
}

View File

@@ -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; }

View File

@@ -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(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL));
RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Length()));
}
streamSpec->Init(item->GetPackSize());
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
else
{
if (!seqMode)
{
RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL));
}
streamSpec->Init(item->GetPackSizeAligned());
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
}

View File

@@ -32,6 +32,7 @@ class CHandler:
UInt64 _headersSize;
bool _phySizeDefined;
AString _errorMessage;
bool _isSparse;
NCompress::CCopyCoder *copyCoderSpec;
CMyComPtr<ICompressCoder> copyCoder;

View File

@@ -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;

View File

@@ -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.

View File

@@ -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;

View File

@@ -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; }
};
}}

View File

@@ -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();

View File

@@ -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();
}

View File

@@ -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,

View File

@@ -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]))
const size_t kSecSizeMin = 1 << 8;
if (i < kSecSizeMin)
return S_FALSE;
SecLogSize = kSizesLog[i];
Int32 bufSize = 1 << SecLogSize;
if (bufSize > fileSize)
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++)
{

1935
CPP/7zip/Archive/UefiHandler.cpp Executable file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -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;

View File

@@ -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
}

View File

@@ -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)
{
RINOK(setCoderProperties->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0])));
}
}
}
{
CMyComPtr<ICompressSetCoderProperties> setCoderProps;
_compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProps);
if (setCoderProps)
{
RINOK(_options.MethodInfo.SetCoderProps(setCoderProps,
_options._dataSizeReduceDefined ? &_options._dataSizeReduce : NULL));
}
}
}
CMyComPtr<ISequentialOutStream> outStreamNew;
if (_options.PasswordIsDefined)

View File

@@ -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;
}
};
}}

View File

@@ -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
}

View File

@@ -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;
CBaseProps _props;
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;
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
}
};

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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
UInt32 CItem::GetWinAttrib() const
{
DWORD winAttributes = 0;
if (IsDir())
winAttributes |= FILE_ATTRIBUTE_DIRECTORY;
return winAttributes;
}
UInt32 CItem::GetWinAttributes() 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)

View File

@@ -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

View File

@@ -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

View File

@@ -1771,14 +1771,6 @@ SOURCE=..\..\UI\Common\UpdateProduce.cpp
SOURCE=..\..\UI\Common\UpdateProduce.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\WorkDir.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\WorkDir.h
# End Source File
# End Group
# Begin Group "Crypto"

View File

@@ -90,7 +90,6 @@ UI_COMMON_OBJS = \
$O\UpdateCallback.obj \
$O\UpdatePair.obj \
$O\UpdateProduce.obj \
$O\WorkDir.obj \
AR_OBJS = \
$O\Bz2Handler.obj \

View File

@@ -88,7 +88,6 @@ UI_COMMON_OBJS = \
$O\UpdateCallback.obj \
$O\UpdatePair.obj \
$O\UpdateProduce.obj \
$O\WorkDir.obj \
AR_OBJS = \
$O\LzmaHandler.obj \

View File

@@ -613,6 +613,14 @@ SOURCE=..\..\Common\FileStreams.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\MethodProps.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\MethodProps.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\ProgressUtils.cpp
# End Source File
# Begin Source File

View File

@@ -181,6 +181,7 @@ AR_OBJS = \
$O\SplitHandler.obj \
$O\SquashfsHandler.obj \
$O\SwfHandler.obj \
$O\UefiHandler.obj \
$O\VhdHandler.obj \
$O\XarHandler.obj \
$O\XzHandler.obj \

View File

@@ -3,5 +3,5 @@
STRINGTABLE
BEGIN
100 "7z zip bz2 bzip2 tbz2 tbz rar arj z taz lzh lha cab iso 001 rpm deb cpio tar gz gzip tgz tpz4 wim swm lzma dmg hfs xar vhd fat ntfs xz"
100 "7z zip rar 001 cab iso xz txz lzma tar cpio bz2 bzip2 tbz2 tbz gz gzip tgz tpz z taz lzh lha rpm deb arj vhd wim swm fat ntfs dmg hfs xar squashfs"
END

View File

@@ -109,7 +109,6 @@ CRYPTO_OBJS = \
$O\7zAesRegister.obj \
$O\MyAes.obj \
$O\RandGen.obj \
$O\Sha1.obj \
C_OBJS = \
$O\Alloc.obj \

View File

@@ -26,6 +26,7 @@ WIN_OBJS = \
$O\LimitedStreams.obj \
$O\LockedStream.obj \
$O\MethodId.obj \
$O\MethodProps.obj \
$O\OutBuffer.obj \
$O\ProgressUtils.obj \
$O\StreamBinder.obj \

View File

@@ -2436,6 +2436,10 @@ SOURCE=..\..\Archive\SwfHandler.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\UefiHandler.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\VhdHandler.cpp
# End Source File
# Begin Source File

View File

@@ -79,6 +79,7 @@ AR_OBJS = \
$O\SplitHandler.obj \
$O\SwfHandler.obj \
$O\SquashfsHandler.obj \
$O\UefiHandler.obj \
$O\VhdHandler.obj \
$O\XarHandler.obj \
$O\XzHandler.obj \

View File

@@ -1,6 +1,6 @@
#include "../../MyVersionInfo.rc"
MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za")
MY_VERSION_INFO_DLL("7z Plugin", "7z")
0 ICON "../../Archive/Icons/7z.ico"
@@ -33,5 +33,5 @@ MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za")
STRINGTABLE
BEGIN
100 "7z:0 zip:1 bz2:2 bzip2:2 tbz2:2 tbz:2 rar:3 arj:4 z:5 taz:5 lzh:6 lha:6 cab:7 iso:8 001:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14 wim:15 swm:15 lzma:16 dmg:17 hfs:18 xar:19 vhd:20 fat:21 ntfs:22 xz:23 txz:23 squashfs:24"
100 "7z:0 zip:1 rar:3 001:9 cab:7 iso:8 xz:23 txz:23 lzma:16 tar:13 cpio:12 bz2:2 bzip2:2 tbz2:2 tbz:2 gz:14 gzip:14 tgz:14 tpz:14 z:5 taz:5 lzh:6 lha:6 rpm:10 deb:11 arj:4 vhd:20 wim:15 swm:15 fat:21 ntfs:22 dmg:17 hfs:18 xar:19 squashfs:24"
END

View File

@@ -49,6 +49,8 @@ enum Enum
{
kHelp1 = 0,
kHelp2,
kMethod,
kLevel,
kAlgo,
kDict,
kFb,
@@ -69,6 +71,8 @@ static const CSwitchForm kSwitchForms[] =
{
{ L"?", NSwitchType::kSimple, false },
{ L"H", NSwitchType::kSimple, false },
{ L"MM", NSwitchType::kUnLimitedPostString, false, 1 },
{ L"X", NSwitchType::kUnLimitedPostString, false, 1 },
{ L"A", NSwitchType::kUnLimitedPostString, false, 1 },
{ L"D", NSwitchType::kUnLimitedPostString, false, 1 },
{ L"FB", NSwitchType::kUnLimitedPostString, false, 1 },
@@ -186,7 +190,7 @@ int main2(int numArgs, const char *args[])
IncorrectCommand();
}
if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
{
PrintHelp();
return 0;
@@ -198,21 +202,38 @@ int main2(int numArgs, const char *args[])
IncorrectCommand();
const UString &command = nonSwitchStrings[paramIndex++];
CObjectVector<CProperty> props;
bool dictDefined = false;
UInt32 dict = (UInt32)-1;
if(parser[NKey::kDict].ThereIs)
UInt32 dict = (UInt32)(Int32)-1;
if (parser[NKey::kDict].ThereIs)
{
UInt32 dicLog;
if (!GetNumber(parser[NKey::kDict].PostStrings[0], dicLog))
const UString &s = parser[NKey::kDict].PostStrings[0];
if (!GetNumber(s, dicLog))
IncorrectCommand();
dict = 1 << dicLog;
dictDefined = true;
CProperty prop;
prop.Name = L"d";
prop.Value = s;
props.Add(prop);
}
if (parser[NKey::kLevel].ThereIs)
{
UInt32 level = 5;
const UString &s = parser[NKey::kLevel].PostStrings[0];
if (!GetNumber(s, level))
IncorrectCommand();
CProperty prop;
prop.Name = L"x";
prop.Value = s;
props.Add(prop);
}
UString mf = L"BT4";
if (parser[NKey::kMatchFinder].ThereIs)
mf = parser[NKey::kMatchFinder].PostStrings[0];
UInt32 numThreads = (UInt32)-1;
UInt32 numThreads = (UInt32)(Int32)-1;
#ifndef _7ZIP_ST
if (parser[NKey::kMultiThread].ThereIs)
@@ -224,9 +245,24 @@ int main2(int numArgs, const char *args[])
else
if (!GetNumber(s, numThreads))
IncorrectCommand();
CProperty prop;
prop.Name = L"mt";
prop.Value = s;
props.Add(prop);
}
#endif
if (parser[NKey::kMethod].ThereIs)
{
UString s = parser[NKey::kMethod].PostStrings[0];
if (s.IsEmpty() || s[0] != '=')
IncorrectCommand();
CProperty prop;
prop.Name = L"m";
prop.Value = s.Mid(1);
props.Add(prop);
}
if (command.CompareNoCase(L"b") == 0)
{
const UInt32 kNumDefaultItereations = 1;
@@ -236,10 +272,19 @@ int main2(int numArgs, const char *args[])
if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations))
numIterations = kNumDefaultItereations;
}
return LzmaBenchCon(stderr, numIterations, numThreads, dict);
HRESULT res = BenchCon(props, numIterations, stderr);
if (res != S_OK)
{
if (res != E_ABORT)
{
PrintMessage("Benchmark Error");
return 1;
}
}
return 0;
}
if (numThreads == (UInt32)-1)
if (numThreads == (UInt32)(Int32)-1)
numThreads = 1;
bool encodeMode = false;
@@ -267,7 +312,7 @@ int main2(int numArgs, const char *args[])
const UString &inputName = nonSwitchStrings[paramIndex++];
inStreamSpec = new CInFileStream;
inStream = inStreamSpec;
if (!inStreamSpec->Open(GetSystemString(inputName)))
if (!inStreamSpec->Open(us2fs(inputName)))
{
fprintf(stderr, "\nError: can not open input file %s\n",
(const char *)GetOemString(inputName));
@@ -289,7 +334,7 @@ int main2(int numArgs, const char *args[])
const UString &outputName = nonSwitchStrings[paramIndex++];
outStreamSpec = new COutFileStream;
outStream = outStreamSpec;
if (!outStreamSpec->Create(GetSystemString(outputName), true))
if (!outStreamSpec->Create(us2fs(outputName), true))
{
fprintf(stderr, "\nError: can not open output file %s\n",
(const char *)GetOemString(outputName));
@@ -398,7 +443,7 @@ int main2(int numArgs, const char *args[])
if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc))
IncorrectCommand();
PROPID propIDs[] =
const PROPID propIDs[] =
{
NCoderPropID::kDictionarySize,
NCoderPropID::kPosStateBits,
@@ -512,7 +557,7 @@ int main2(int numArgs, const char *args[])
int MY_CDECL main(int numArgs, const char *args[])
{
try { return main2(numArgs, args); }
catch(const char *s)
catch (const char *s)
{
fprintf(stderr, "\nError: %s\n", s);
return 1;

View File

@@ -132,6 +132,14 @@ SOURCE=..\..\..\Windows\FileIO.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariant.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariant.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Synchronization.cpp
# End Source File
# Begin Source File
@@ -280,6 +288,14 @@ SOURCE=..\..\Common\FilterCoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\MethodProps.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\MethodProps.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamUtils.cpp
# End Source File
# Begin Source File

View File

@@ -21,6 +21,7 @@ COMMON_OBJS = \
WIN_OBJS = \
$O\FileIO.obj \
$O\PropVariant.obj \
$O\System.obj
7ZIP_COMMON_OBJS = \
@@ -28,6 +29,7 @@ WIN_OBJS = \
$O\CreateCoder.obj \
$O\FileStreams.obj \
$O\FilterCoder.obj \
$O\MethodProps.obj \
$O\OutBuffer.obj \
$O\StreamUtils.obj \

View File

@@ -30,15 +30,18 @@ OBJS = \
CWrappers.o \
FileStreams.o \
FilterCoder.o \
MethodProps.o \
StreamUtils.o \
$(FILE_IO).o \
CommandLineParser.o \
CRC.o \
IntToString.o \
MyString.o \
MyVector.o \
MyWindows.o \
StringConvert.o \
StringToInt.o \
MyVector.o \
PropVariant.o \
7zCrc.o \
7zCrcOpt.o \
Alloc.o \
@@ -89,6 +92,9 @@ FileStreams.o: ../../Common/FileStreams.cpp
FilterCoder.o: ../../Common/FilterCoder.cpp
$(CXX) $(CFLAGS) ../../Common/FilterCoder.cpp
MethodProps.o: ../../Common/MethodProps.cpp
$(CXX) $(CFLAGS) ../../Common/MethodProps.cpp
StreamUtils.o: ../../Common/StreamUtils.cpp
$(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp
@@ -102,23 +108,26 @@ CommandLineParser.o: ../../../Common/CommandLineParser.cpp
CRC.o: ../../../Common/CRC.cpp
$(CXX) $(CFLAGS) ../../../Common/CRC.cpp
MyWindows.o: ../../../Common/MyWindows.cpp
$(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp
IntToString.o: ../../../Common/IntToString.cpp
$(CXX) $(CFLAGS) ../../../Common/IntToString.cpp
MyString.o: ../../../Common/MyString.cpp
$(CXX) $(CFLAGS) ../../../Common/MyString.cpp
MyVector.o: ../../../Common/MyVector.cpp
$(CXX) $(CFLAGS) ../../../Common/MyVector.cpp
MyWindows.o: ../../../Common/MyWindows.cpp
$(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp
StringConvert.o: ../../../Common/StringConvert.cpp
$(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp
StringToInt.o: ../../../Common/StringToInt.cpp
$(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp
MyVector.o: ../../../Common/MyVector.cpp
$(CXX) $(CFLAGS) ../../../Common/MyVector.cpp
PropVariant.o: ../../../Windows/PropVariant.cpp
$(CXX) $(CFLAGS) ../../../Windows/PropVariant.cpp
7zCrc.o: ../../../../C/7zCrc.c
$(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c

View File

@@ -11,6 +11,7 @@
#include "Windows/DLL.h"
#include "Windows/FileDir.h"
#endif
#include "Windows/FileName.h"
#include "../../UI/Common/ExitCode.h"
#include "../../UI/Common/Extract.h"
@@ -25,6 +26,9 @@ using namespace NWindows;
using namespace NFile;
using namespace NCommandLineParser;
#ifdef _WIN32
HINSTANCE g_hInstance = 0;
#endif
int g_CodePage = -1;
extern CStdOutStream *g_StdStream;
@@ -261,12 +265,11 @@ int Main2(
#ifdef _WIN32
UString arcPath;
FString arcPath;
{
UString path;
NDLL::MyGetModuleFileName(NULL, path);
int fileNamePartStartIndex;
if (!NDirectory::MyGetFullPathName(path, arcPath, fileNamePartStartIndex))
FString path;
NDLL::MyGetModuleFileName(path);
if (!NDirectory::MyGetFullPathName(path, arcPath))
{
g_StdOut << "GetFullPathName Error";
return NExitCode::kFatalError;
@@ -291,7 +294,7 @@ int Main2(
PrintHelpAndExit();
}
if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
{
PrintHelp();
return 0;
@@ -330,23 +333,23 @@ int Main2(
bool passwordEnabled = parser[NKey::kPassword].ThereIs;
UString password;
if(passwordEnabled)
if (passwordEnabled)
password = parser[NKey::kPassword].PostStrings[0];
if (!NFind::DoesFileExist(arcPath))
throw kCantFindSFX;
UString outputDir;
FString outputDir;
if (parser[NKey::kOutputDir].ThereIs)
{
outputDir = parser[NKey::kOutputDir].PostStrings[0];
outputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]);
NName::NormalizeDirPathPrefix(outputDir);
}
{
UStringVector v1, v2;
v1.Add(arcPath);
v2.Add(arcPath);
v1.Add(fs2us(arcPath));
v2.Add(fs2us(arcPath));
const NWildcard::CCensorNode &wildcardCensorHead =
wildcardCensor.Pairs.Front().Head;
@@ -362,7 +365,7 @@ int Main2(
if (result != S_OK)
throw CSystemException(result);
if(command.CommandType != NCommandType::kList)
if (command.CommandType != NCommandType::kList)
{
CExtractCallbackConsole *ecs = new CExtractCallbackConsole;
CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;

View File

@@ -6,6 +6,7 @@
#include "Windows/FileDir.h"
#include "Windows/FileFind.h"
#include "Windows/FileName.h"
#include "Windows/PropVariant.h"
#include "ExtractCallback.h"
@@ -18,7 +19,7 @@ static LPCWSTR kCantOpenFile = L"Can not open output file";
static LPCWSTR kUnsupportedMethod = L"Unsupported Method";
void CExtractCallbackImp::Init(IInArchive *archiveHandler,
const UString &directoryPath,
const FString &directoryPath,
const UString &itemDefaultName,
const FILETIME &defaultMTime,
UInt32 defaultAttributes)
@@ -76,12 +77,12 @@ STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue)
void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts)
{
UString fullPath = _directoryPath;
for(int i = 0; i < dirPathParts.Size(); i++)
FString fullPath = _directoryPath;
for (int i = 0; i < dirPathParts.Size(); i++)
{
fullPath += dirPathParts[i];
fullPath += us2fs(dirPathParts[i]);
NDirectory::MyCreateDirectory(fullPath);
fullPath += NName::kDirDelimiter;
fullPath += FCHAR_PATH_SEPARATOR;
}
}
@@ -153,7 +154,7 @@ STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index,
CreateComplexDirectory(pathParts);
}
UString fullProcessedPath = _directoryPath + processedPath;
FString fullProcessedPath = _directoryPath + us2fs(processedPath);
if (_processedFileInfo.IsDir)
{
@@ -166,7 +167,7 @@ STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index,
return S_OK;
}
NFind::CFileInfoW fileInfo;
NFind::CFileInfo fileInfo;
if (fileInfo.Find(fullProcessedPath))
{
if (!NDirectory::DeleteFileAlways(fullProcessedPath))

View File

@@ -31,9 +31,9 @@ public:
private:
CMyComPtr<IInArchive> _archiveHandler;
UString _directoryPath;
FString _directoryPath;
UString _filePath;
UString _diskFilePath;
FString _diskFilePath;
bool _extractMode;
struct CProcessedFileInfo
@@ -60,7 +60,7 @@ public:
UString _message;
void Init(IInArchive *archiveHandler,
const UString &directoryPath,
const FString &directoryPath,
const UString &itemDefaultName,
const FILETIME &defaultMTime,
UInt32 defaultAttributes);

View File

@@ -3,6 +3,7 @@
#include "StdAfx.h"
#include "Windows/FileDir.h"
#include "Windows/FileName.h"
#include "Windows/Thread.h"
#include "../../UI/Common/OpenArchive.h"
@@ -20,8 +21,8 @@ static LPCWSTR kCantOpenArchive = L"Can not open the file as archive";
struct CThreadExtracting
{
CCodecs *Codecs;
UString FileName;
UString DestFolder;
FString FileName;
FString DestFolder;
CExtractCallbackImp *ExtractCallbackSpec;
CMyComPtr<IArchiveExtractCallback> ExtractCallback;
@@ -32,7 +33,7 @@ struct CThreadExtracting
void Process2()
{
NFile::NFind::CFileInfoW fi;
NFile::NFind::CFileInfo fi;
if (!fi.Find(FileName))
{
ErrorMessage = kCantFindArchive;
@@ -40,7 +41,7 @@ struct CThreadExtracting
return;
}
Result = ArchiveLink.Open2(Codecs, CIntVector(), false, NULL, FileName, ExtractCallbackSpec);
Result = ArchiveLink.Open2(Codecs, CIntVector(), false, NULL, fs2us(FileName), ExtractCallbackSpec);
if (Result != S_OK)
{
if (Result != S_OK)
@@ -48,7 +49,7 @@ struct CThreadExtracting
return;
}
UString dirPath = DestFolder;
FString dirPath = DestFolder;
NFile::NName::NormalizeDirPathPrefix(dirPath);
if (!NFile::NDirectory::CreateComplexDirectory(dirPath))
@@ -57,7 +58,7 @@ struct CThreadExtracting
#ifdef LANG
0x02000603,
#endif
dirPath);
fs2us(dirPath));
Result = E_FAIL;
return;
}
@@ -86,7 +87,7 @@ struct CThreadExtracting
}
};
HRESULT ExtractArchive(CCodecs *codecs,const UString &fileName, const UString &destFolder,
HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder,
bool showProgress, bool &isCorrupt, UString &errorMessage)
{
isCorrupt = false;

View File

@@ -1,11 +1,11 @@
// ExtractEngine.h
#ifndef __EXTRACTENGINE_H
#define __EXTRACTENGINE_H
#ifndef __EXTRACT_ENGINE_H
#define __EXTRACT_ENGINE_H
#include "../../UI/Common/LoadCodecs.h"
HRESULT ExtractArchive(CCodecs *codecs, const UString &fileName, const UString &destFolder,
bool showProgress, bool &isCorrupt, UString &errorMessage);
HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder,
bool showProgress, bool &isCorrupt, UString &errorMessage);
#endif

View File

@@ -12,6 +12,7 @@
#include "Windows/FileDir.h"
#include "Windows/FileFind.h"
#include "Windows/FileIO.h"
#include "Windows/FileName.h"
#include "Windows/NtCheck.h"
#include "Windows/ResourceString.h"
@@ -25,11 +26,11 @@ using namespace NWindows;
HINSTANCE g_hInstance;
static LPCTSTR kTempDirPrefix = TEXT("7zS");
static CFSTR kTempDirPrefix = FTEXT("7zS");
#define _SHELL_EXECUTE
static bool ReadDataString(LPCWSTR fileName, LPCSTR startID,
static bool ReadDataString(CFSTR fileName, LPCSTR startID,
LPCSTR endID, AString &stringResult)
{
stringResult.Empty();
@@ -107,11 +108,11 @@ public:
#ifndef UNDER_CE
class CCurrentDirRestorer
{
CSysString m_CurrentDirectory;
FString m_CurrentDirectory;
public:
CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); }
~CCurrentDirRestorer() { RestoreDirectory();}
bool RestoreDirectory() { return BOOLToBool(::SetCurrentDirectory(m_CurrentDirectory)); }
bool RestoreDirectory() const { return NFile::NDirectory::MySetCurrentDirectory(m_CurrentDirectory); }
};
#endif
@@ -137,8 +138,8 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
#endif
NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches);
UString fullPath;
NDLL::MyGetModuleFileName(g_hInstance, fullPath);
FString fullPath;
NDLL::MyGetModuleFileName(fullPath);
switches.Trim();
bool assumeYes = false;
@@ -191,7 +192,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
#endif
}
NFile::NDirectory::CTempDirectory tempDir;
NFile::NDirectory::CTempDir tempDir;
if (!tempDir.Create(kTempDirPrefix))
{
if (!assumeYes)
@@ -208,7 +209,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
return 1;
}
UString tempDirPath = GetUnicodeString(tempDir.GetPath());
FString tempDirPath = tempDir.GetPath();
{
bool isCorrupt = false;
UString errorMessage;
@@ -233,7 +234,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
#ifndef UNDER_CE
CCurrentDirRestorer currentDirRestorer;
if (!SetCurrentDirectory(tempDir.GetPath()))
if (!NFile::NDirectory::MySetCurrentDirectory(tempDir.GetPath()))
return 1;
#endif
@@ -281,7 +282,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
if (appLaunched.IsEmpty())
{
appLaunched = L"setup.exe";
if (!NFile::NFind::DoesFileExist(GetSystemString(appLaunched)))
if (!NFile::NFind::DoesFileExist(us2fs(appLaunched)))
{
if (!assumeYes)
ShowErrorMessage(L"Can not find setup.exe");
@@ -290,12 +291,12 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
}
{
UString s2 = tempDirPath;
FString s2 = tempDirPath;
NFile::NName::NormalizeDirPathPrefix(s2);
appLaunched.Replace(L"%%T" WSTRING_PATH_SEPARATOR, s2);
appLaunched.Replace(L"%%T" WSTRING_PATH_SEPARATOR, fs2us(s2));
}
appLaunched.Replace(L"%%T", tempDirPath);
appLaunched.Replace(L"%%T", fs2us(tempDirPath));
if (!switches.IsEmpty())
{

View File

@@ -41,7 +41,7 @@ int APIENTRY WinMain2()
UString password;
bool assumeYes = false;
bool outputFolderDefined = false;
UString outputFolder;
FString outputFolder;
UStringVector commandStrings;
NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
@@ -57,7 +57,7 @@ int APIENTRY WinMain2()
assumeYes = true;
else if (s.Left(2).CompareNoCase(L"-o") == 0)
{
outputFolder = s.Mid(2);
outputFolder = us2fs(s.Mid(2));
NWindows::NFile::NName::NormalizeDirPathPrefix(outputFolder);
outputFolderDefined = !outputFolder.IsEmpty();
}
@@ -67,12 +67,11 @@ int APIENTRY WinMain2()
}
}
UString path;
NWindows::NDLL::MyGetModuleFileName(g_hInstance, path);
FString path;
NWindows::NDLL::MyGetModuleFileName(path);
UString fullPath;
int fileNamePartStartIndex;
if (!NWindows::NFile::NDirectory::MyGetFullPathName(path, fullPath, fileNamePartStartIndex))
FString fullPath;
if (!NWindows::NFile::NDirectory::MyGetFullPathName(path, fullPath))
{
ShowErrorMessage(L"Error 1329484");
return 1;
@@ -102,8 +101,15 @@ int APIENTRY WinMain2()
#endif
CExtractOptions eo;
eo.OutputDir = outputFolderDefined ? outputFolder :
fullPath.Left(fileNamePartStartIndex);
FString dirPrefix;
if (!NWindows::NFile::NDirectory::GetOnlyDirPrefix(path, dirPrefix))
{
ShowErrorMessage(L"Error 1329485");
return 1;
}
eo.OutputDir = outputFolderDefined ? outputFolder : dirPrefix;
eo.YesToAll = assumeYes;
eo.OverwriteMode = assumeYes ?
NExtract::NOverwriteMode::kWithoutPrompt :
@@ -112,8 +118,8 @@ int APIENTRY WinMain2()
eo.TestMode = false;
UStringVector v1, v2;
v1.Add(fullPath);
v2.Add(fullPath);
v1.Add(fs2us(fullPath));
v2.Add(fs2us(fullPath));
NWildcard::CCensorNode wildcardCensor;
wildcardCensor.AddItem(true, L"*", true, true, true);
@@ -170,4 +176,3 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
return NExitCode::kFatalError;
}
}

View File

@@ -37,6 +37,7 @@ SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes)
case E_INVALIDARG: return SZ_ERROR_PARAM;
case E_ABORT: return SZ_ERROR_PROGRESS;
case S_FALSE: return SZ_ERROR_DATA;
case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED;
}
return defaultRes;
}
@@ -90,6 +91,7 @@ HRESULT SResToHRESULT(SRes res)
case SZ_ERROR_PARAM: return E_INVALIDARG;
case SZ_ERROR_PROGRESS: return E_ABORT;
case SZ_ERROR_DATA: return S_FALSE;
case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
}
return E_FAIL;
}

View File

@@ -11,10 +11,10 @@
using namespace NWindows;
static bool MakeAutoName(const UString &name,
const UString &extension, unsigned value, UString &path)
static bool MakeAutoName(const FString &name,
const FString &extension, unsigned value, FString &path)
{
wchar_t number[16];
FChar number[16];
ConvertUInt32ToString(value, number);
path = name;
path += number;
@@ -22,18 +22,18 @@ static bool MakeAutoName(const UString &name,
return NFile::NFind::DoesFileOrDirExist(path);
}
bool AutoRenamePath(UString &fullProcessedPath)
bool AutoRenamePath(FString &fullProcessedPath)
{
UString path;
int dotPos = fullProcessedPath.ReverseFind(L'.');
FString path;
int dotPos = fullProcessedPath.ReverseFind(FTEXT('.'));
int slashPos = fullProcessedPath.ReverseFind(L'/');
int slashPos = fullProcessedPath.ReverseFind(FTEXT('/'));
#ifdef _WIN32
int slash1Pos = fullProcessedPath.ReverseFind(L'\\');
int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\'));
slashPos = MyMax(slashPos, slash1Pos);
#endif
UString name, extension;
FString name, extension;
if (dotPos > slashPos && dotPos > 0)
{
name = fullProcessedPath.Left(dotPos);

View File

@@ -1,10 +1,10 @@
// Util/FilePathAutoRename.h
// FilePathAutoRename.h
#ifndef __FILEPATHAUTORENAME_H
#define __FILEPATHAUTORENAME_H
#ifndef __FILE_PATH_AUTO_RENAME_H
#define __FILE_PATH_AUTO_RENAME_H
#include "Common/MyString.h"
bool AutoRenamePath(UString &fullProcessedPath);
bool AutoRenamePath(FString &fullProcessedPath);
#endif

View File

@@ -29,34 +29,6 @@ static inline HRESULT ConvertBoolToHRESULT(bool result)
#endif
}
bool CInFileStream::Open(LPCTSTR fileName)
{
return File.Open(fileName);
}
#ifdef USE_WIN_FILE
#ifndef _UNICODE
bool CInFileStream::Open(LPCWSTR fileName)
{
return File.Open(fileName);
}
#endif
#endif
bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite)
{
return File.OpenShared(fileName, shareForWrite);
}
#ifdef USE_WIN_FILE
#ifndef _UNICODE
bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite)
{
return File.OpenShared(fileName, shareForWrite);
}
#endif
#endif
#ifdef SUPPORT_DEVICE_FILE
static const UInt32 kClusterSize = 1 << 18;
@@ -279,7 +251,7 @@ STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin,
#else
off_t res = File.Seek(offset, seekOrigin);
off_t res = File.Seek((off_t)offset, seekOrigin);
if (res == -1)
return E_FAIL;
if (newPosition != NULL)
@@ -343,7 +315,7 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo
#else
off_t res = File.Seek(offset, seekOrigin);
off_t res = File.Seek((off_t)offset, seekOrigin);
if (res == -1)
return E_FAIL;
if (newPosition != NULL)

View File

@@ -1,12 +1,14 @@
// FileStreams.h
#ifndef __FILESTREAMS_H
#define __FILESTREAMS_H
#ifndef __FILE_STREAMS_H
#define __FILE_STREAMS_H
#ifdef _WIN32
#define USE_WIN_FILE
#endif
#include "../../Common/MyString.h"
#ifdef USE_WIN_FILE
#include "../../Windows/FileIO.h"
#else
@@ -41,19 +43,15 @@ public:
CInFileStream();
#endif
bool Open(LPCTSTR fileName);
#ifdef USE_WIN_FILE
#ifndef _UNICODE
bool Open(LPCWSTR fileName);
#endif
#endif
bool OpenShared(LPCTSTR fileName, bool shareForWrite);
#ifdef USE_WIN_FILE
#ifndef _UNICODE
bool OpenShared(LPCWSTR fileName, bool shareForWrite);
#endif
#endif
bool Open(CFSTR fileName)
{
return File.Open(fileName);
}
bool OpenShared(CFSTR fileName, bool shareForWrite)
{
return File.OpenShared(fileName, shareForWrite);
}
MY_UNKNOWN_IMP2(IInStream, IStreamGetSize)
@@ -78,37 +76,23 @@ class COutFileStream:
public IOutStream,
public CMyUnknownImp
{
public:
#ifdef USE_WIN_FILE
NWindows::NFile::NIO::COutFile File;
#else
NC::NFile::NIO::COutFile File;
#endif
public:
virtual ~COutFileStream() {}
bool Create(LPCTSTR fileName, bool createAlways)
bool Create(CFSTR fileName, bool createAlways)
{
ProcessedSize = 0;
return File.Create(fileName, createAlways);
}
bool Open(LPCTSTR fileName, DWORD creationDisposition)
bool Open(CFSTR fileName, DWORD creationDisposition)
{
ProcessedSize = 0;
return File.Open(fileName, creationDisposition);
}
#ifdef USE_WIN_FILE
#ifndef _UNICODE
bool Create(LPCWSTR fileName, bool createAlways)
{
ProcessedSize = 0;
return File.Create(fileName, createAlways);
}
bool Open(LPCWSTR fileName, DWORD creationDisposition)
{
ProcessedSize = 0;
return File.Open(fileName, creationDisposition);
}
#endif
#endif
HRESULT Close();

View File

@@ -13,7 +13,7 @@ using namespace NDirectory;
static const UInt32 kTempBufSize = (1 << 20);
static LPCTSTR kTempFilePrefixString = TEXT("7zt");
static CFSTR kTempFilePrefixString = FTEXT("7zt");
CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { }
@@ -42,12 +42,7 @@ bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size)
return true;
if (!_tempFileCreated)
{
CSysString tempDirPath;
if (!MyGetTempPath(tempDirPath))
return false;
if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tempFileName) == 0)
return false;
if (!_outFile.Create(_tempFileName, true))
if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile))
return false;
_tempFileCreated = true;
}
@@ -91,7 +86,7 @@ HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream)
if (_tempFileCreated)
{
NIO::CInFile inFile;
if (!inFile.Open(_tempFileName))
if (!inFile.Open(_tempFile.GetPath()))
return E_FAIL;
while (size < _size)
{

View File

@@ -5,7 +5,6 @@
#include "../../Common/MyCom.h"
#include "../../Windows/FileDir.h"
#include "../../Windows/FileIO.h"
#include "../IStream.h"
@@ -15,7 +14,6 @@ class CInOutTempBuffer
NWindows::NFile::NIO::COutFile _outFile;
Byte *_buf;
UInt32 _bufPos;
CSysString _tempFileName;
bool _tempFileCreated;
UInt64 _size;
UInt32 _crc;

View File

@@ -1,27 +1,3 @@
// MethodId.cpp
#include "StdAfx.h"
#include "MethodId.h"
#include "../../Common/MyString.h"
static inline wchar_t GetHex(Byte value)
{
return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
}
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;
}

View File

@@ -2,98 +2,447 @@
#include "StdAfx.h"
#include "../../Common/MyCom.h"
#include "../ICoder.h"
#include "../../Common/StringToInt.h"
#include "MethodProps.h"
static const UInt64 k_LZMA = 0x030101;
static const UInt64 k_LZMA2 = 0x21;
using namespace NWindows;
HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder)
bool StringToBool(const UString &s, bool &res)
{
bool tryReduce = false;
UInt32 reducedDictionarySize = 1 << 10;
if (inSizeForReduce != 0 && (method.Id == k_LZMA || method.Id == k_LZMA2))
if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0)
{
for (;;)
{
const UInt32 step = (reducedDictionarySize >> 1);
if (reducedDictionarySize >= *inSizeForReduce)
{
tryReduce = true;
break;
}
reducedDictionarySize += step;
if (reducedDictionarySize >= *inSizeForReduce)
{
tryReduce = true;
break;
}
if (reducedDictionarySize >= ((UInt32)3 << 30))
break;
reducedDictionarySize += step;
}
res = true;
return true;
}
if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0)
{
res = false;
return true;
}
return false;
}
HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest)
{
switch (prop.vt)
{
int numProps = method.Props.Size();
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);
if (setCoderProperties == NULL)
{
if (numProps != 0)
return E_INVALIDARG;
}
else
{
CRecordVector<PROPID> propIDs;
NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProps];
HRESULT res = S_OK;
try
{
for (int i = 0; i < numProps; i++)
{
const CProp &prop = method.Props[i];
propIDs.Add(prop.Id);
NWindows::NCOM::CPropVariant &value = values[i];
value = prop.Value;
// if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal)
if (tryReduce)
if (prop.Id == NCoderPropID::kDictionarySize)
if (value.vt == VT_UI4)
if (reducedDictionarySize < value.ulVal)
value.ulVal = reducedDictionarySize;
}
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);
res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProps);
}
catch(...)
{
delete []values;
throw;
}
delete []values;
RINOK(res);
}
case VT_EMPTY: dest = true; return S_OK;
case VT_BOOL: dest = (prop.boolVal != VARIANT_FALSE); return S_OK;
case VT_BSTR: return StringToBool(prop.bstrVal, dest) ? S_OK : E_INVALIDARG;
}
/*
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
if (writeCoderProperties != NULL)
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 > (UInt32)0xFFFFFFFF)
{
CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->Init();
RINOK(writeCoderProperties->WriteCoderProperties(outStream));
size_t size = outStreamSpec->GetSize();
filterProps.SetCapacity(size);
memmove(filterProps, outStreamSpec->GetBuffer(), size);
number = 0;
return 0;
}
*/
number = (UInt32)number64;
return (int)(end - start);
}
HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
{
// =VT_UI4
// =VT_EMPTY
// {stringUInt32}=VT_EMPTY
if (prop.vt == VT_UI4)
{
if (!name.IsEmpty())
return E_INVALIDARG;
resValue = prop.ulVal;
return S_OK;
}
if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
if (name.IsEmpty())
return S_OK;
UInt32 v;
if (ParseStringToUInt32(name, v) != name.Length())
return E_INVALIDARG;
resValue = v;
return S_OK;
}
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(PROPVARIANT_to_bool(prop, val));
numThreads = (val ? defaultNumThreads : 1);
break;
}
}
return S_OK;
}
if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
return ParsePropToUInt32(name, prop, numThreads);
}
static HRESULT StringToDictSize(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;
const unsigned kLogDictSizeLimit = 32;
if (srcString.Length() == numDigits)
{
if (number >= kLogDictSizeLimit)
return E_INVALIDARG;
dicSize = (UInt32)1 << (int)number;
return S_OK;
}
unsigned numBits;
switch (srcString[numDigits])
{
case 'B': numBits = 0; break;
case 'K': numBits = 10; break;
case 'M': numBits = 20; break;
case 'G': numBits = 30; break;
default: return E_INVALIDARG;
}
if (number >= ((UInt64)1 << (kLogDictSizeLimit - numBits)))
return E_INVALIDARG;
dicSize = (UInt32)number << numBits;
return S_OK;
}
static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, UInt32 &resValue)
{
if (prop.vt == VT_UI4)
{
UInt32 v = prop.ulVal;
if (v >= 32)
return E_INVALIDARG;
resValue = (UInt32)1 << v;
return S_OK;
}
if (prop.vt == VT_BSTR)
return StringToDictSize(prop.bstrVal, resValue);
return E_INVALIDARG;
}
void CProps::AddProp32(PROPID propid, UInt32 level)
{
CProp prop;
prop.IsOptional = true;
prop.Id = propid;
prop.Value = (UInt32)level;
Props.Add(prop);
}
class CCoderProps
{
PROPID *_propIDs;
NCOM::CPropVariant *_props;
unsigned _numProps;
unsigned _numPropsMax;
public:
CCoderProps(unsigned numPropsMax)
{
_numPropsMax = numPropsMax;
_numProps = 0;
_propIDs = new PROPID[numPropsMax];
_props = new NCOM::CPropVariant[numPropsMax];
}
~CCoderProps()
{
delete []_propIDs;
delete []_props;
}
void AddProp(const CProp &prop);
HRESULT SetProps(ICompressSetCoderProperties *setCoderProperties)
{
return setCoderProperties->SetCoderProperties(_propIDs, _props, _numProps);
}
};
void CCoderProps::AddProp(const CProp &prop)
{
if (_numProps >= _numPropsMax)
throw 1;
_propIDs[_numProps] = prop.Id;
_props[_numProps] = prop.Value;
_numProps++;
}
HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const
{
CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0));
for (int i = 0; i < Props.Size(); i++)
coderProps.AddProp(Props[i]);
if (dataSizeReduce)
{
CProp prop;
prop.Id = NCoderPropID::kReduceSize;
prop.Value = *dataSizeReduce;
coderProps.AddProp(prop);
}
return coderProps.SetProps(scp);
}
int CMethodProps::FindProp(PROPID id) const
{
for (int i = Props.Size() - 1; i >= 0; i--)
if (Props[i].Id == id)
return i;
return -1;
}
int CMethodProps::GetLevel() const
{
int i = FindProp(NCoderPropID::kLevel);
if (i < 0)
return 5;
if (Props[i].Value.vt != VT_UI4)
return 9;
UInt32 level = Props[i].Value.ulVal;
return level > 9 ? 9 : (int)level;
}
struct CNameToPropID
{
VARTYPE VarType;
const wchar_t *Name;
};
static const CNameToPropID g_NameToPropID[] =
{
{ VT_UI4, L"" },
{ VT_UI4, L"d" },
{ VT_UI4, L"mem" },
{ VT_UI4, L"o" },
{ VT_UI4, L"c" },
{ VT_UI4, L"pb" },
{ VT_UI4, L"lc" },
{ VT_UI4, L"lp" },
{ VT_UI4, L"fb" },
{ VT_BSTR, L"mf" },
{ VT_UI4, L"mc" },
{ VT_UI4, L"pass" },
{ VT_UI4, L"a" },
{ VT_UI4, L"mt" },
{ VT_BOOL, L"eos" },
{ VT_UI4, L"x" },
{ VT_UI4, L"reduceSize" }
};
static int FindPropIdExact(const UString &name)
{
for (unsigned i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)
if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)
return i;
return -1;
}
static bool ConvertProperty(const PROPVARIANT &srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)
{
if (varType == srcProp.vt)
{
destProp = srcProp;
return true;
}
if (varType == VT_BOOL)
{
bool res;
if (PROPVARIANT_to_bool(srcProp, res) != S_OK)
return false;
destProp = res;
return true;
}
if (srcProp.vt == VT_EMPTY)
{
destProp = srcProp;
return true;
}
return false;
}
static void SplitParams(const UString &srcString, UStringVector &subStrings)
{
subStrings.Clear();
UString s;
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(s);
s.Empty();
}
else
s += c;
}
subStrings.Add(s);
}
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;
}
int i;
for (i = 0; i < param.Length(); i++)
{
wchar_t c = param[i];
if (c >= L'0' && c <= L'9')
break;
}
name = param.Left(i);
value = param.Mid(i);
}
static bool IsLogSizeProp(PROPID propid)
{
switch (propid)
{
case NCoderPropID::kDictionarySize:
case NCoderPropID::kUsedMemorySize:
case NCoderPropID::kBlockSize:
case NCoderPropID::kReduceSize:
return true;
}
return false;
}
HRESULT CMethodProps::SetParam(const UString &name, const UString &value)
{
int index = FindPropIdExact(name);
if (index < 0)
return E_INVALIDARG;
const CNameToPropID &nameToPropID = g_NameToPropID[index];
CProp prop;
prop.Id = index;
if (IsLogSizeProp(prop.Id))
{
UInt32 dicSize;
RINOK(StringToDictSize(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 if (!value.IsEmpty())
{
UInt32 number;
if (ParseStringToUInt32(value, number) == value.Length())
propValue = number;
else
propValue = value;
}
if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value))
return E_INVALIDARG;
}
Props.Add(prop);
return S_OK;
}
HRESULT CMethodProps::ParseParamsFromString(const UString &srcString)
{
UStringVector params;
SplitParams(srcString, params);
for (int i = 0; i < params.Size(); i++)
{
const UString &param = params[i];
UString name, value;
SplitParam(param, name, value);
RINOK(SetParam(name, value));
}
return S_OK;
}
HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)
{
if (realName.Length() == 0)
{
// [empty]=method
return E_INVALIDARG;
}
if (value.vt == VT_EMPTY)
{
// {realName}=[empty]
UString name, value;
SplitParam(realName, name, value);
return SetParam(name, value);
}
// {realName}=value
int index = FindPropIdExact(realName);
if (index < 0)
return E_INVALIDARG;
const CNameToPropID &nameToPropID = g_NameToPropID[index];
CProp prop;
prop.Id = index;
if (IsLogSizeProp(prop.Id))
{
UInt32 dicSize;
RINOK(PROPVARIANT_to_DictSize(value, dicSize));
prop.Value = dicSize;
}
else
{
if (!ConvertProperty(value, nameToPropID.VarType, prop.Value))
return E_INVALIDARG;
}
Props.Add(prop);
return S_OK;
}
HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)
{
if (!realName.IsEmpty() && realName.CompareNoCase(L"m") != 0)
return ParseParamsFromPROPVARIANT(realName, value);
// -m{N}=method
if (value.vt != VT_BSTR)
return E_INVALIDARG;
const UString s = value.bstrVal;
int splitPos = s.Find(':');
if (splitPos < 0)
{
MethodName = s;
return S_OK;
}
MethodName = s.Left(splitPos);
return ParseParamsFromString(s.Mid(splitPos + 1));
}

View File

@@ -3,39 +3,182 @@
#ifndef __7Z_METHOD_PROPS_H
#define __7Z_METHOD_PROPS_H
#include "../../Common/MyVector.h"
#include "../../Common/MyString.h"
#include "../../Windows/PropVariant.h"
#include "MethodId.h"
#include "../ICoder.h"
bool StringToBool(const UString &s, bool &res);
HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest);
int ParseStringToUInt32(const UString &srcString, UInt32 &number);
HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);
struct CProp
{
PROPID Id;
bool IsOptional;
NWindows::NCOM::CPropVariant Value;
CProp(): IsOptional(false) {}
};
struct CMethod
struct CProps
{
CMethodId Id;
CObjectVector<CProp> Props;
void Clear() { Props.Clear(); }
bool AreThereNonOptionalProps() const
{
for (int i = 0; i < Props.Size(); i++)
if (!Props[i].IsOptional)
return true;
return false;
}
void AddProp32(PROPID propid, UInt32 level);
void AddPropString(PROPID propid, const wchar_t *s)
{
CProp prop;
prop.IsOptional = true;
prop.Id = propid;
prop.Value = s;
Props.Add(prop);
}
HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const;
};
struct CMethodsMode
class CMethodProps: public CProps
{
CObjectVector<CMethod> Methods;
#ifndef _7ZIP_ST
UInt32 NumThreads;
#endif
HRESULT SetParam(const UString &name, const UString &value);
public:
int GetLevel() const;
int Get_NumThreads() const
{
int i = FindProp(NCoderPropID::kNumThreads);
if (i >= 0)
if (Props[i].Value.vt == VT_UI4)
return (int)Props[i].Value.ulVal;
return -1;
}
CMethodsMode()
#ifndef _7ZIP_ST
: NumThreads(1)
#endif
{}
bool IsEmpty() const { return Methods.IsEmpty() ; }
bool Get_DicSize(UInt32 &res) const
{
res = 0;
int i = FindProp(NCoderPropID::kDictionarySize);
if (i >= 0)
if (Props[i].Value.vt == VT_UI4)
{
res = Props[i].Value.ulVal;
return true;
}
return false;
}
int FindProp(PROPID id) const;
UInt32 Get_Lzma_Algo() const
{
int i = FindProp(NCoderPropID::kAlgorithm);
if (i >= 0)
if (Props[i].Value.vt == VT_UI4)
return Props[i].Value.ulVal;
return GetLevel() >= 5 ? 1 : 0;
}
UInt32 Get_Lzma_DicSize() const
{
int i = FindProp(NCoderPropID::kDictionarySize);
if (i >= 0)
if (Props[i].Value.vt == VT_UI4)
return Props[i].Value.ulVal;
int level = GetLevel();
return level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26));
}
UInt32 Get_Lzma_NumThreads(bool &fixedNumber) const
{
fixedNumber = false;
int numThreads = Get_NumThreads();
if (numThreads >= 0)
{
fixedNumber = true;
return numThreads < 2 ? 1 : 2;
}
return Get_Lzma_Algo() == 0 ? 1 : 2;
}
UInt32 Get_BZip2_NumThreads(bool &fixedNumber) const
{
fixedNumber = false;
int numThreads = Get_NumThreads();
if (numThreads >= 0)
{
fixedNumber = true;
if (numThreads < 1) return 1;
if (numThreads > 64) return 64;
return numThreads;
}
return 1;
}
UInt32 Get_BZip2_BlockSize() const
{
int i = FindProp(NCoderPropID::kDictionarySize);
if (i >= 0)
if (Props[i].Value.vt == VT_UI4)
{
UInt32 blockSize = Props[i].Value.ulVal;
const UInt32 kDicSizeMin = 100000;
const UInt32 kDicSizeMax = 900000;
if (blockSize < kDicSizeMin) blockSize = kDicSizeMin;
if (blockSize > kDicSizeMax) blockSize = kDicSizeMax;
return blockSize;
}
int level = GetLevel();
return 100000 * (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1));
}
UInt32 Get_Ppmd_MemSize() const
{
int i = FindProp(NCoderPropID::kUsedMemorySize);
if (i >= 0)
if (Props[i].Value.vt == VT_UI4)
return Props[i].Value.ulVal;
int level = GetLevel();
return level >= 9 ? (192 << 20) : ((UInt32)1 << (level + 19));
}
void AddLevelProp(UInt32 level)
{
AddProp32(NCoderPropID::kLevel, level);
}
void AddNumThreadsProp(UInt32 numThreads)
{
AddProp32(NCoderPropID::kNumThreads, numThreads);
}
HRESULT ParseParamsFromString(const UString &srcString);
HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);
};
HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder);
class COneMethodInfo: public CMethodProps
{
public:
UString MethodName;
void Clear()
{
CMethodProps::Clear();
MethodName.Empty();
}
bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); }
HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);
};
#endif

View File

@@ -2,149 +2,125 @@
#include "StdAfx.h"
#include "StreamBinder.h"
#include "../../Common/Defs.h"
#include "../../Common/MyCom.h"
using namespace NWindows;
using namespace NSynchronization;
#include "StreamBinder.h"
class CSequentialInStreamForBinder:
class CBinderInStream:
public ISequentialInStream,
public CMyUnknownImp
{
CStreamBinder *_binder;
public:
MY_UNKNOWN_IMP
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
private:
CStreamBinder *m_StreamBinder;
public:
~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); }
void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; }
~CBinderInStream() { _binder->CloseRead(); }
CBinderInStream(CStreamBinder *binder): _binder(binder) {}
};
STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
{ return m_StreamBinder->Read(data, size, processedSize); }
STDMETHODIMP CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{ return _binder->Read(data, size, processedSize); }
class CSequentialOutStreamForBinder:
class CBinderOutStream:
public ISequentialOutStream,
public CMyUnknownImp
{
CStreamBinder *_binder;
public:
MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
private:
CStreamBinder *m_StreamBinder;
public:
~CSequentialOutStreamForBinder() { m_StreamBinder->CloseWrite(); }
void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; }
~CBinderOutStream() { _binder->CloseWrite(); }
CBinderOutStream(CStreamBinder *binder): _binder(binder) {}
};
STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
{ return m_StreamBinder->Write(data, size, processedSize); }
STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{ return _binder->Write(data, size, processedSize); }
//////////////////////////
// CStreamBinder
// (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished.
HRes CStreamBinder::CreateEvents()
WRes CStreamBinder::CreateEvents()
{
RINOK(_allBytesAreWritenEvent.Create(true));
RINOK(_thereAreBytesToReadEvent.Create());
return _readStreamIsClosedEvent.Create();
RINOK(_canWrite_Event.Create(true));
RINOK(_canRead_Event.Create());
return _readingWasClosed_Event.Create();
}
void CStreamBinder::ReInit()
{
_thereAreBytesToReadEvent.Reset();
_readStreamIsClosedEvent.Reset();
_waitWrite = true;
_canRead_Event.Reset();
_readingWasClosed_Event.Reset();
ProcessedSize = 0;
}
void CStreamBinder::CreateStreams(ISequentialInStream **inStream,
ISequentialOutStream **outStream)
void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream)
{
CSequentialInStreamForBinder *inStreamSpec = new
CSequentialInStreamForBinder;
_waitWrite = true;
_bufSize = 0;
_buf = NULL;
ProcessedSize = 0;
CBinderInStream *inStreamSpec = new CBinderInStream(this);
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
inStreamSpec->SetBinder(this);
*inStream = inStreamLoc.Detach();
CSequentialOutStreamForBinder *outStreamSpec = new
CSequentialOutStreamForBinder;
CBinderOutStream *outStreamSpec = new CBinderOutStream(this);
CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec);
outStreamSpec->SetBinder(this);
*outStream = outStreamLoc.Detach();
_buffer = NULL;
_bufferSize= 0;
ProcessedSize = 0;
}
// (_canRead_Event && _bufSize == 0) means that stream is finished.
HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 sizeToRead = size;
if (size > 0)
if (processedSize)
*processedSize = 0;
if (size != 0)
{
RINOK(_thereAreBytesToReadEvent.Lock());
sizeToRead = MyMin(_bufferSize, size);
if (_bufferSize > 0)
if (_waitWrite)
{
memcpy(data, _buffer, sizeToRead);
_buffer = ((const Byte *)_buffer) + sizeToRead;
_bufferSize -= sizeToRead;
if (_bufferSize == 0)
RINOK(_canRead_Event.Lock());
_waitWrite = false;
}
if (size > _bufSize)
size = _bufSize;
if (size != 0)
{
memcpy(data, _buf, size);
_buf = ((const Byte *)_buf) + size;
ProcessedSize += size;
if (processedSize)
*processedSize = size;
_bufSize -= size;
if (_bufSize == 0)
{
_thereAreBytesToReadEvent.Reset();
_allBytesAreWritenEvent.Set();
_waitWrite = true;
_canRead_Event.Reset();
_canWrite_Event.Set();
}
}
}
if (processedSize != NULL)
*processedSize = sizeToRead;
ProcessedSize += sizeToRead;
return S_OK;
}
void CStreamBinder::CloseRead()
{
_readStreamIsClosedEvent.Set();
}
HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
if (size > 0)
if (processedSize)
*processedSize = 0;
if (size != 0)
{
_buffer = data;
_bufferSize = size;
_allBytesAreWritenEvent.Reset();
_thereAreBytesToReadEvent.Set();
_buf = data;
_bufSize = size;
_canWrite_Event.Reset();
_canRead_Event.Set();
HANDLE events[2];
events[0] = _allBytesAreWritenEvent;
events[1] = _readStreamIsClosedEvent;
HANDLE events[2] = { _canWrite_Event, _readingWasClosed_Event };
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
if (waitResult != WAIT_OBJECT_0 + 0)
{
// ReadingWasClosed = true;
return S_FALSE;
}
// if(!_allBytesAreWritenEvent.Lock())
// return E_FAIL;
if (processedSize)
*processedSize = size;
}
if (processedSize != NULL)
*processedSize = size;
return S_OK;
}
void CStreamBinder::CloseWrite()
{
// _bufferSize must be = 0
_thereAreBytesToReadEvent.Set();
}

View File

@@ -1,32 +1,34 @@
// StreamBinder.h
#ifndef __STREAMBINDER_H
#define __STREAMBINDER_H
#ifndef __STREAM_BINDER_H
#define __STREAM_BINDER_H
#include "../../Windows/Synchronization.h"
#include "../IStream.h"
#include "../../Windows/Synchronization.h"
class CStreamBinder
{
NWindows::NSynchronization::CManualResetEvent _allBytesAreWritenEvent;
NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent;
NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent;
UInt32 _bufferSize;
const void *_buffer;
NWindows::NSynchronization::CManualResetEvent _canWrite_Event;
NWindows::NSynchronization::CManualResetEvent _canRead_Event;
NWindows::NSynchronization::CManualResetEvent _readingWasClosed_Event;
bool _waitWrite;
UInt32 _bufSize;
const void *_buf;
public:
// bool ReadingWasClosed;
UInt64 ProcessedSize;
CStreamBinder() {}
HRes CreateEvents();
void CreateStreams(ISequentialInStream **inStream,
ISequentialOutStream **outStream);
HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);
void CloseRead();
HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize);
void CloseWrite();
WRes CreateEvents();
void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream);
void ReInit();
HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);
HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize);
void CloseRead() { _readingWasClosed_Event.Set(); }
void CloseWrite()
{
// _bufSize must be = 0
_canRead_Event.Set();
}
};
#endif

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include <stdlib.h>
#include "../../../C/Alloc.h"
#include "StreamObjects.h"
@@ -78,7 +80,7 @@ Byte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize)
void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const
{
dest.SetCapacity(_size);
memcpy(dest, _buffer, _size);
memcpy(dest, (const Byte *)_buffer, _size);
}
STDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

Some files were not shown because too many files have changed in this diff Show More