Update to 7-Zip Version 21.04

- first test... no release!!!
This commit is contained in:
Tino Reichardt
2021-11-06 22:17:34 +01:00
parent 0f6bcfd2ed
commit 09497b7ba0
152 changed files with 6166 additions and 1341 deletions

View File

@@ -133,6 +133,8 @@ enum Enum
kSfx,
kEmail,
kHash,
// kHashGenFile,
kHashDir,
kStdIn,
kStdOut,
@@ -141,6 +143,7 @@ enum Enum
kListfileCharSet,
kConsoleCharSet,
kTechMode,
kListFields,
kPreserveATime,
kShareForWrite,
@@ -273,6 +276,8 @@ static const CSwitchForm kSwitchForms[] =
{ "sfx", SWFRM_STRING },
{ "seml", SWFRM_STRING_SINGL(0) },
{ "scrc", SWFRM_STRING_MULT(0) },
// { "scrf", SWFRM_STRING_SINGL(1) },
{ "shd", SWFRM_STRING_SINGL(1) },
{ "si", SWFRM_STRING },
{ "so", SWFRM_SIMPLE },
@@ -281,6 +286,7 @@ static const CSwitchForm kSwitchForms[] =
{ "scs", SWFRM_STRING },
{ "scc", SWFRM_STRING },
{ "slt", SWFRM_SIMPLE },
{ "slf", SWFRM_STRING_SINGL(1) },
{ "ssp", SWFRM_SIMPLE },
{ "ssw", SWFRM_SIMPLE },
@@ -626,7 +632,21 @@ static void AddSwitchWildcardsToCensor(
errorMessage = "Too short switch";
break;
}
if (!include)
{
if (name.IsEqualTo_Ascii_NoCase("td"))
{
censor.ExcludeDirItems = true;
continue;
}
if (name.IsEqualTo_Ascii_NoCase("tf"))
{
censor.ExcludeFileItems = true;
continue;
}
}
if (::MyCharLower_Ascii(name[pos]) == kRecursedIDChar)
{
pos++;
@@ -875,6 +895,11 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
options.StdInMode = parser[NKey::kStdIn].ThereIs;
options.StdOutMode = parser[NKey::kStdOut].ThereIs;
options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs;
if (parser[NKey::kListFields].ThereIs)
{
const UString &s = parser[NKey::kListFields].PostStrings[0];
options.ListFields = GetAnsiString(s);
}
options.TechMode = parser[NKey::kTechMode].ThereIs;
options.ShowTime = parser[NKey::kShowTime].ThereIs;
@@ -1094,6 +1119,27 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
if (parser[NKey::kHash].ThereIs)
options.HashMethods = parser[NKey::kHash].PostStrings;
/*
if (parser[NKey::kHashGenFile].ThereIs)
{
const UString &s = parser[NKey::kHashGenFile].PostStrings[0];
for (unsigned i = 0 ; i < s.Len();)
{
const wchar_t c = s[i++];
if (!options.HashOptions.ParseFlagCharOption(c, true))
{
if (c != '=')
throw CArcCmdLineException("Unsupported hash mode switch:", s);
options.HashOptions.HashFilePath = s.Ptr(i);
break;
}
}
}
*/
if (parser[NKey::kHashDir].ThereIs)
options.ExtractOptions.HashDir = parser[NKey::kHashDir].PostStrings[0];
if (parser[NKey::kElimDup].ThereIs)
{
@@ -1232,6 +1278,9 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
{
CExtractOptionsBase &eo = options.ExtractOptions;
eo.ExcludeDirItems = options.Censor.ExcludeDirItems;
eo.ExcludeFileItems = options.Censor.ExcludeFileItems;
{
CExtractNtOptions &nt = eo.NtOptions;
nt.NtSecurity = options.NtSecurity;
@@ -1252,6 +1301,11 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs;
nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs;
if (parser[NKey::kPreserveATime].ThereIs)
nt.PreserveATime = true;
if (parser[NKey::kShareForWrite].ThereIs)
nt.OpenShareForWrite = true;
}
options.Censor.AddPathsToCensor(NWildcard::k_AbsPath);
@@ -1422,6 +1476,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
CHashOptions &hashOptions = options.HashOptions;
hashOptions.PathMode = censorPathMode;
hashOptions.Methods = options.HashMethods;
// hashOptions.HashFilePath = options.HashFilePath;
if (parser[NKey::kPreserveATime].ThereIs)
hashOptions.PreserveATime = true;
if (parser[NKey::kShareForWrite].ThereIs)

View File

@@ -66,6 +66,8 @@ struct CArcCmdLineOptions
bool TechMode;
bool ShowTime;
AString ListFields;
int ConsoleCodePage;
NWildcard::CCensor Censor;
@@ -79,6 +81,7 @@ struct CArcCmdLineOptions
#endif
UStringVector HashMethods;
// UString HashFilePath;
bool AppendName;
// UStringVector ArchivePathsSorted;

View File

@@ -47,6 +47,7 @@ static const char * const kCantRenameFile = "Cannot rename existing file";
static const char * const kCantDeleteOutputFile = "Cannot delete output file";
static const char * const kCantDeleteOutputDir = "Cannot delete output folder";
static const char * const kCantOpenOutFile = "Cannot open output file";
static const char * const kCantOpenInFile = "Cannot open input file";
static const char * const kCantSetFileLen = "Cannot set length for output file";
#ifdef SUPPORT_LINKS
static const char * const kCantCreateHardLink = "Cannot create hard link";
@@ -889,7 +890,8 @@ void CArchiveExtractCallback::CorrectPathParts()
void CArchiveExtractCallback::CreateFolders()
{
UStringVector &pathParts = _item.PathParts;
// 21.04 : we don't change original (_item.PathParts) here
UStringVector pathParts = _item.PathParts;
if (!_item.IsDir)
{
@@ -1078,18 +1080,19 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
IInArchive *archive = _arc->Archive;
#endif
const UStringVector &pathParts = _item.PathParts;
const UInt32 index = _index;
bool isAnti = false;
RINOK(_arc->IsItemAnti(index, isAnti));
CorrectPathParts();
UString processedPath (MakePathFromParts(pathParts));
UString processedPath (MakePathFromParts(_item.PathParts));
if (!isAnti)
{
// 21.04: CreateFolders doesn't change (_item.PathParts)
CreateFolders();
}
FString fullProcessedPath (us2fs(processedPath));
if (_pathMode != NExtract::NPathMode::kAbsPaths
@@ -1295,7 +1298,25 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
HRESULT CArchiveExtractCallback::GetItem(UInt32 index)
{
#ifndef _SFX
_item._use_baseParentFolder_mode = _use_baseParentFolder_mode;
if (_use_baseParentFolder_mode)
{
_item._baseParentFolder = (int)_baseParentFolder;
if (_pathMode == NExtract::NPathMode::kFullPaths ||
_pathMode == NExtract::NPathMode::kAbsPaths)
_item._baseParentFolder = -1;
}
#endif // _SFX
#ifdef SUPPORT_ALT_STREAMS
_item.WriteToAltStreamIfColon = _ntOptions.WriteToAltStreamIfColon;
#endif
return _arc->GetItem(index, _item);
}
STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)
@@ -1339,22 +1360,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
IInArchive *archive = _arc->Archive;
#ifndef _SFX
_item._use_baseParentFolder_mode = _use_baseParentFolder_mode;
if (_use_baseParentFolder_mode)
{
_item._baseParentFolder = (int)_baseParentFolder;
if (_pathMode == NExtract::NPathMode::kFullPaths ||
_pathMode == NExtract::NPathMode::kAbsPaths)
_item._baseParentFolder = -1;
}
#endif // _SFX
#ifdef SUPPORT_ALT_STREAMS
_item.WriteToAltStreamIfColon = _ntOptions.WriteToAltStreamIfColon;
#endif
RINOK(_arc->GetItem(index, _item));
RINOK(GetItem(index));
{
NCOM::CPropVariant prop;
@@ -1382,6 +1388,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
return S_OK;
#endif // SUPPORT_ALT_STREAMS
// we can change (_item.PathParts) in this function
UStringVector &pathParts = _item.PathParts;
if (_wildcardCensor)
@@ -1974,7 +1981,10 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
#ifndef _SFX
if (ExtractToStreamCallback)
return ExtractToStreamCallback->SetOperationResult7(opRes, BoolToInt(_encrypted));
{
GetUnpackSize();
return ExtractToStreamCallback->SetOperationResult8(opRes, BoolToInt(_encrypted), _curSize);
}
#endif
#ifndef _SFX
@@ -2103,6 +2113,82 @@ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
}
// ---------- HASH functions ----------
FString CArchiveExtractCallback::Hash_GetFullFilePath()
{
// this function changes _item.PathParts.
CorrectPathParts();
const UStringVector &pathParts = _item.PathParts;
const UString processedPath (MakePathFromParts(pathParts));
FString fullProcessedPath (us2fs(processedPath));
if (_pathMode != NExtract::NPathMode::kAbsPaths
|| !NName::IsAbsolutePath(processedPath))
{
fullProcessedPath = MakePath_from_2_Parts(
DirPathPrefix_for_HashFiles,
// _dirPathPrefix,
fullProcessedPath);
}
return fullProcessedPath;
}
STDMETHODIMP CArchiveExtractCallback::GetDiskProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NCOM::CPropVariant prop;
if (propID == kpidSize)
{
RINOK(GetItem(index));
const FString fullProcessedPath = Hash_GetFullFilePath();
NFile::NFind::CFileInfo fi;
if (fi.Find_FollowLink(fullProcessedPath))
if (!fi.IsDir())
prop = (UInt64)fi.Size;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
STDMETHODIMP CArchiveExtractCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode)
{
COM_TRY_BEGIN
*inStream = NULL;
// if (index != _index) return E_FAIL;
if (mode != NUpdateNotifyOp::kHashRead)
return E_FAIL;
RINOK(GetItem(index));
const FString fullProcessedPath = Hash_GetFullFilePath();
CInFileStream *inStreamSpec = new CInFileStream;
CMyComPtr<ISequentialInStream> inStreamRef = inStreamSpec;
inStreamSpec->File.PreserveATime = _ntOptions.PreserveATime;
if (!inStreamSpec->OpenShared(fullProcessedPath, _ntOptions.OpenShareForWrite))
{
RINOK(SendMessageError_with_LastError(kCantOpenInFile, fullProcessedPath));
return S_OK;
}
*inStream = inStreamRef.Detach();
return S_OK;
COM_TRY_END
}
STDMETHODIMP CArchiveExtractCallback::ReportOperation(
UInt32 /* indexType */, UInt32 /* index */, UInt32 /* op */)
{
// COM_TRY_BEGIN
return S_OK;
// COM_TRY_END
}
// ------------ After Extracting functions ------------
void CDirPathSortPair::SetNumSlashes(const FChar *s)
{
for (unsigned numSlashes = 0;;)

View File

@@ -62,9 +62,15 @@ struct CExtractNtOptions
bool PreAllocateOutFile;
// used for hash arcs only, when we open external files
bool PreserveATime;
bool OpenShareForWrite;
CExtractNtOptions():
ReplaceColonForAltStream(false),
WriteToAltStreamIfColon(false)
WriteToAltStreamIfColon(false),
PreserveATime(false),
OpenShareForWrite(false)
{
SymLinks.Val = true;
SymLinks_AllowDangerous.Val = false;
@@ -205,6 +211,8 @@ class CArchiveExtractCallback:
public IArchiveExtractCallbackMessage,
public ICryptoGetTextPassword,
public ICompressProgressInfo,
public IArchiveUpdateCallbackFile,
public IArchiveGetDiskProperty,
public CMyUnknownImp
{
const CArc *_arc;
@@ -342,6 +350,9 @@ class CArchiveExtractCallback:
HRESULT GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
HRESULT GetUnpackSize();
FString Hash_GetFullFilePath();
public:
HRESULT SendMessageError(const char *message, const FString &path);
HRESULT SendMessageError_with_LastError(const char *message, const FString &path);
HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2);
@@ -356,10 +367,20 @@ public:
UInt64 UnpackSize;
UInt64 AltStreams_UnpackSize;
MY_UNKNOWN_IMP3(IArchiveExtractCallbackMessage, ICryptoGetTextPassword, ICompressProgressInfo)
FString DirPathPrefix_for_HashFiles;
MY_UNKNOWN_IMP5(
IArchiveExtractCallbackMessage,
ICryptoGetTextPassword,
ICompressProgressInfo,
IArchiveUpdateCallbackFile,
IArchiveGetDiskProperty
)
INTERFACE_IArchiveExtractCallback(;)
INTERFACE_IArchiveExtractCallbackMessage(;)
INTERFACE_IArchiveUpdateCallbackFile(;)
INTERFACE_IArchiveGetDiskProperty(;)
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
@@ -453,6 +474,7 @@ private:
bool _isRenamed;
HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit);
HRESULT GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit);
HRESULT GetItem(UInt32 index);
HRESULT CloseFile();
HRESULT CloseReparseAndFile();

View File

@@ -639,15 +639,22 @@ STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64
static const unsigned kSubBits = 8;
static UInt32 GetLogSize(UInt64 size)
static unsigned GetLogSize(UInt64 size)
{
unsigned i = 0;
for (;;)
{
i++; size >>= 1; if (size == 0) break;
}
return i;
}
static UInt32 GetLogSize_Sub(UInt64 size)
{
if (size <= 1)
return 0;
unsigned i;
for (i = 2; i < 64; i++)
if (size < ((UInt64)1 << i))
break;
i--;
const unsigned i = GetLogSize(size) - 1;
UInt32 v;
if (i <= kSubBits)
v = (UInt32)(size) << (kSubBits - i);
@@ -656,60 +663,101 @@ static UInt32 GetLogSize(UInt64 size)
return ((UInt32)i << kSubBits) + (v & (((UInt32)1 << kSubBits) - 1));
}
static void NormalizeVals(UInt64 &v1, UInt64 &v2)
static UInt64 Get_UInt64_from_double(double v)
{
while (v1 >= ((UInt32)1 << ((64 - kBenchmarkUsageMultBits) / 2)))
{
v1 >>= 1;
v2 >>= 1;
}
const UInt64 kMaxVal = (UInt64)1 << 62;
if (v > (double)(Int64)kMaxVal)
return kMaxVal;
return (UInt64)v;
}
static UInt64 MyMultDiv64(UInt64 m1, UInt64 m2, UInt64 d)
{
if (d == 0)
d = 1;
const double v =
(double)(Int64)m1 *
(double)(Int64)m2 /
(double)(Int64)d;
return Get_UInt64_from_double(v);
/*
unsigned n1 = GetLogSize(m1);
unsigned n2 = GetLogSize(m2);
while (n1 + n2 > 64)
{
if (n1 >= n2)
{
m1 >>= 1;
n1--;
}
else
{
m2 >>= 1;
n2--;
}
d >>= 1;
}
if (d == 0)
d = 1;
return m1 * m2 / d;
*/
}
UInt64 CBenchInfo::GetUsage() const
{
UInt64 userTime = UserTime;
UInt64 userFreq = UserFreq;
UInt64 globalTime = GlobalTime;
UInt64 globalFreq = GlobalFreq;
NormalizeVals(userTime, userFreq);
NormalizeVals(globalFreq, globalTime);
if (userFreq == 0)
userFreq = 1;
if (globalTime == 0)
globalTime = 1;
return userTime * globalFreq * kBenchmarkUsageMult / userFreq / globalTime;
const double v =
((double)(Int64)userTime / (double)(Int64)userFreq)
* ((double)(Int64)globalFreq / (double)(Int64)globalTime)
* (double)(Int64)kBenchmarkUsageMult;
return Get_UInt64_from_double(v);
/*
return MyMultDiv64(
MyMultDiv64(kBenchmarkUsageMult, userTime, userFreq),
globalFreq, globalTime);
*/
}
UInt64 CBenchInfo::GetRatingPerUsage(UInt64 rating) const
{
UInt64 userTime = UserTime;
UInt64 userFreq = UserFreq;
UInt64 globalTime = GlobalTime;
UInt64 globalFreq = GlobalFreq;
NormalizeVals(userFreq, userTime);
NormalizeVals(globalTime, globalFreq);
if (globalFreq == 0)
globalFreq = 1;
if (userTime == 0)
if (UserTime == 0)
{
return 0;
// userTime = 1;
}
return userFreq * globalTime / globalFreq * rating / userTime;
UInt64 globalFreq = GlobalFreq;
if (globalFreq == 0)
globalFreq = 1;
const double v =
((double)(Int64)GlobalTime / (double)(Int64)globalFreq)
* ((double)(Int64)UserFreq / (double)(Int64)UserTime)
* (double)(Int64)rating;
return Get_UInt64_from_double(v);
/*
return MyMultDiv64(
MyMultDiv64(rating, UserFreq, UserTime),
GlobalTime, globalFreq);
*/
}
static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)
{
UInt64 elTime = elapsedTime;
NormalizeVals(freq, elTime);
if (elTime == 0)
elTime = 1;
return value * freq / elTime;
}
UInt64 CBenchInfo::GetSpeed(UInt64 numUnits) const
{
return MyMultDiv64(numUnits, GlobalTime, GlobalFreq);
return MyMultDiv64(numUnits, GlobalFreq, GlobalTime);
}
struct CBenchProps
@@ -764,24 +812,24 @@ UInt64 CBenchProps::GetCompressRating(UInt64 dictSize, UInt64 elapsedTime, UInt6
/*
for (UInt64 uu = 0; uu < (UInt64)0xf << 60;)
{
unsigned rr = GetLogSize(uu);
unsigned rr = GetLogSize_Sub(uu);
printf("\n%16I64x , log = %4x", uu, rr);
uu += 1;
uu += uu / 50;
}
*/
// throw 1;
const UInt32 t = GetLogSize(dictSize) - (kBenchMinDicLogSize << kSubBits);
const UInt32 t = GetLogSize_Sub(dictSize) - (kBenchMinDicLogSize << kSubBits);
encComplex = 870 + ((t * t * 5) >> (2 * kSubBits));
}
const UInt64 numCommands = (UInt64)size * encComplex;
return MyMultDiv64(numCommands, elapsedTime, freq);
return MyMultDiv64(numCommands, freq, elapsedTime);
}
UInt64 CBenchProps::GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations)
{
const UInt64 numCommands = (inSize * DecComplexCompr + outSize * DecComplexUnc) * numIterations;
return MyMultDiv64(numCommands, elapsedTime, freq);
return MyMultDiv64(numCommands, freq, elapsedTime);
}
@@ -2675,8 +2723,8 @@ void CTotalBenchRes::Mult_For_Weight(unsigned weight)
NumIterations2 *= weight;
RPU *= weight;
Rating *= weight;
Usage += weight;
Speed += weight;
Usage *= weight;
Speed *= weight;
}
void CTotalBenchRes::Update_With_Res(const CTotalBenchRes &r)
@@ -3712,7 +3760,7 @@ HRESULT Bench(
start = 1;
const UInt64 freq = GetFreq();
// mips is constant in some compilers
const UInt64 hz = MyMultDiv64(numMilCommands * 1000000, start, freq);
const UInt64 hz = MyMultDiv64(numMilCommands * 1000000, freq, start);
const UInt64 mipsVal = numMilCommands * freq / start;
if (printCallback)
{

View File

@@ -347,22 +347,56 @@ void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bo
MY_TRY_FINISH_VOID
}
void TestArchives(const UStringVector &arcPaths)
void TestArchives(const UStringVector &arcPaths, bool hashMode)
{
MY_TRY_BEGIN
UString params ('t');
if (hashMode)
{
params += kArchiveTypeSwitch;
params += "hash";
}
ExtractGroupCommand(arcPaths, params, false);
MY_TRY_FINISH_VOID
}
void CalcChecksum(const UStringVector &paths, const UString &methodName)
void CalcChecksum(const UStringVector &paths,
const UString &methodName,
const UString &arcPathPrefix,
const UString &arcFileName)
{
MY_TRY_BEGIN
if (!arcFileName.IsEmpty())
{
CompressFiles(
arcPathPrefix,
arcFileName,
UString("hash"),
false, // addExtension,
paths,
false, // email,
false, // showDialog,
false // waitFinish
);
return;
}
UString params ('h');
if (!methodName.IsEmpty())
{
params += " -scrc";
params += methodName;
/*
if (!arcFileName.IsEmpty())
{
// not used alternate method of generating file
params += " -scrf=";
params += GetQuotedString(arcPathPrefix + arcFileName);
}
*/
}
ExtractGroupCommand(paths, params, true);
MY_TRY_FINISH_VOID

View File

@@ -16,8 +16,13 @@ HRESULT CompressFiles(
bool email, bool showDialog, bool waitFinish);
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup);
void TestArchives(const UStringVector &arcPaths);
void CalcChecksum(const UStringVector &paths, const UString &methodName);
void TestArchives(const UStringVector &arcPaths, bool hashMode = false);
void CalcChecksum(const UStringVector &paths,
const UString &methodName,
const UString &arcPathPrefix,
const UString &arcFileName);
void Benchmark(bool totalMode);
#endif

View File

@@ -38,7 +38,8 @@ static void ThrowException_if_Error(HRESULT res)
#define CREATE_CODECS \
CCodecs *codecs = new CCodecs; \
CMyComPtr<ICompressCodecsInfo> compressCodecsInfo = codecs; \
ThrowException_if_Error(codecs->Load());
ThrowException_if_Error(codecs->Load()); \
Codecs_AddHashArcHandler(codecs);
#define LOAD_EXTERNAL_CODECS \
CExternalCodecs __externalCodecs; \
@@ -51,7 +52,8 @@ static void ThrowException_if_Error(HRESULT res)
#define CREATE_CODECS \
CCodecs *codecs = new CCodecs; \
CMyComPtr<IUnknown> compressCodecsInfo = codecs; \
ThrowException_if_Error(codecs->Load());
ThrowException_if_Error(codecs->Load()); \
Codecs_AddHashArcHandler(codecs);
#define LOAD_EXTERNAL_CODECS
@@ -150,7 +152,8 @@ HRESULT CompressFiles(
static HRESULT ExtractGroupCommand(const UStringVector &arcPaths,
bool showDialog, const UString &outFolder, bool testMode, bool elimDup = false)
bool showDialog, const UString &outFolder, bool testMode, bool elimDup = false,
const char *kType = NULL)
{
MY_TRY_BEGIN
@@ -187,6 +190,15 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths,
}
CObjectVector<COpenType> formatIndices;
if (kType)
{
if (!ParseOpenTypes(*codecs, UString(kType), formatIndices))
{
throw CSystemException(E_INVALIDARG);
// ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE);
// return E_INVALIDARG;
}
}
NWildcard::CCensor censor;
{
@@ -221,14 +233,34 @@ void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bo
ExtractGroupCommand(arcPaths, showDialog, outFolder, false, elimDup);
}
void TestArchives(const UStringVector &arcPaths)
void TestArchives(const UStringVector &arcPaths, bool hashMode)
{
ExtractGroupCommand(arcPaths, true, UString(), true);
ExtractGroupCommand(arcPaths, true, UString(), true,
false, // elimDup
hashMode ? "hash" : NULL);
}
void CalcChecksum(const UStringVector &paths, const UString &methodName)
void CalcChecksum(const UStringVector &paths,
const UString &methodName,
const UString &arcPathPrefix,
const UString &arcFileName)
{
MY_TRY_BEGIN
if (!arcFileName.IsEmpty())
{
CompressFiles(
arcPathPrefix,
arcFileName,
UString("hash"),
false, // addExtension,
paths,
false, // email,
false, // showDialog,
false // waitFinish
);
return;
}
CREATE_CODECS
LOAD_EXTERNAL_CODECS
@@ -245,6 +277,11 @@ void CalcChecksum(const UStringVector &paths, const UString &methodName)
CHashOptions options;
options.Methods.Add(methodName);
/*
if (!arcFileName.IsEmpty())
options.HashFilePath = arcPathPrefix + arcFileName;
*/
result = HashCalcGUI(EXTERNAL_CODECS_VARS_L censor, options, messageWasDisplayed);
if (result != S_OK)
{

View File

@@ -141,7 +141,16 @@ public:
bool SymLinks;
bool ScanAltStreams;
bool ExcludeDirItems;
bool ExcludeFileItems;
/* it must be called after anotrher checks */
bool CanIncludeItem(bool isDir) const
{
return isDir ? !ExcludeDirItems : !ExcludeFileItems;
}
CDirItemsStat Stat;
#if !defined(UNDER_CE)

View File

@@ -146,6 +146,8 @@ bool InitLocalPrivileges();
CDirItems::CDirItems():
SymLinks(false),
ScanAltStreams(false)
, ExcludeDirItems(false)
, ExcludeFileItems(false)
#ifdef _USE_SECURITY_CODE
, ReadSecure(false)
#endif
@@ -318,6 +320,8 @@ HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phy
*/
#endif
if (CanIncludeItem(fi.IsDir()))
{
int secureIndex = -1;
#ifdef _USE_SECURITY_CODE
if (ReadSecure)
@@ -325,8 +329,8 @@ HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phy
RINOK(AddSecurityItem(phyPrefix + fi.Name, secureIndex));
}
#endif
AddDirFileInfo(phyParent, logParent, secureIndex, fi);
}
if (Callback && (i & kScanProgressStepMask) == kScanProgressStepMask)
{
@@ -392,6 +396,8 @@ HRESULT CDirItems::EnumerateItems2(
phyParentCur = (int)AddPrefix(phyParent, logParent, fs2us(phyPrefixCur));
}
if (CanIncludeItem(fi.IsDir()))
{
int secureIndex = -1;
#ifdef _USE_SECURITY_CODE
if (ReadSecure)
@@ -399,8 +405,8 @@ HRESULT CDirItems::EnumerateItems2(
RINOK(AddSecurityItem(phyPath, secureIndex));
}
#endif
AddDirFileInfo(phyParentCur, logParent, secureIndex, fi);
}
if (fi.IsDir())
{
@@ -470,6 +476,9 @@ static HRESULT EnumerateAltStreams(
bool addAllSubStreams,
CDirItems &dirItems)
{
// we don't use (ExcludeFileItems) rules for AltStreams
// if (dirItems.ExcludeFileItems) return S_OK;
NFind::CStreamEnumerator enumerator(phyPath);
for (;;)
{
@@ -560,29 +569,42 @@ static HRESULT EnumerateForItem(
int dirItemIndex = -1;
#if defined(_WIN32)
bool addAllSubStreams = false;
bool needAltStreams = true;
#endif // _WIN32
#endif // !defined(UNDER_CE)
// check the path in inlcude rules
if (curNode.CheckPathToRoot(true, newParts, !fi.IsDir()))
{
int secureIndex = -1;
#ifdef _USE_SECURITY_CODE
if (dirItems.ReadSecure)
{
RINOK(dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex));
}
#endif
#if !defined(UNDER_CE)
dirItemIndex = (int)dirItems.Items.Size();
// dirItemIndex = (int)dirItems.Items.Size();
#if defined(_WIN32)
// we will not check include rules for substreams.
addAllSubStreams = true;
#endif // _WIN32
#endif // !defined(UNDER_CE)
dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi);
if (dirItems.CanIncludeItem(fi.IsDir()))
{
int secureIndex = -1;
#ifdef _USE_SECURITY_CODE
if (dirItems.ReadSecure)
{
RINOK(dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex));
}
#endif
#if !defined(UNDER_CE)
dirItemIndex = (int)dirItems.Items.Size();
#endif // !defined(UNDER_CE)
dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi);
}
else
{
#if defined(_WIN32) && !defined(UNDER_CE)
needAltStreams = false;
#endif
}
if (fi.IsDir())
enterToSubFolders = true;
}
@@ -600,7 +622,7 @@ static HRESULT EnumerateForItem(
}
#if defined(_WIN32)
if (dirItems.ScanAltStreams)
if (needAltStreams && dirItems.ScanAltStreams)
{
RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent,
phyPrefix + fi.Name, // with (fi.Name)
@@ -814,6 +836,9 @@ static HRESULT EnumerateDirItems(
continue;
}
if (dirItems.CanIncludeItem(fi.IsDir()))
{
int secureIndex = -1;
#ifdef _USE_SECURITY_CODE
if (needSecurity && dirItems.ReadSecure)
@@ -848,6 +873,7 @@ static HRESULT EnumerateDirItems(
#endif // defined(_WIN32)
#endif // !defined(UNDER_CE)
}
#ifndef _WIN32

View File

@@ -7,11 +7,13 @@
#include "../../../Common/StringConvert.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/ErrorMsg.h"
#include "../../../Windows/PropVariant.h"
#include "../../../Windows/PropVariantConv.h"
#include "../Common/ExtractingFilePath.h"
#include "../Common/HashCalc.h"
#include "Extract.h"
#include "SetProperties.h"
@@ -87,7 +89,7 @@ static HRESULT DecompressArchive(
}
}
bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();
const bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();
if (!options.StdInMode)
{
@@ -98,9 +100,14 @@ static HRESULT DecompressArchive(
for (UInt32 i = 0; i < numItems; i++)
{
if (elimIsPossible || !allFilesAreAllowed)
if (elimIsPossible
|| !allFilesAreAllowed
|| options.ExcludeDirItems
|| options.ExcludeFileItems)
{
RINOK(arc.GetItem(i, item));
if (item.IsDir ? options.ExcludeDirItems : options.ExcludeFileItems)
continue;
}
else
{
@@ -254,6 +261,7 @@ int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &n
HRESULT Extract(
// DECL_EXTERNAL_CODECS_LOC_VARS
CCodecs *codecs,
const CObjectVector<COpenType> &types,
const CIntVector &excludedFormats,
@@ -409,6 +417,31 @@ HRESULT Extract(
continue;
}
if (arcLink.Arcs.Size() != 0)
{
if (arcLink.GetArc()->IsHashHandler(op))
{
if (!options.TestMode)
{
/* real Extracting to files is possible.
But user can think that hash archive contains real files.
So we block extracting here. */
return E_NOTIMPL;
}
FString dirPrefix = us2fs(options.HashDir);
if (dirPrefix.IsEmpty())
{
if (!NFile::NDir::GetOnlyDirPrefix(us2fs(arcPath), dirPrefix))
{
// return GetLastError_noZero_HRESULT();
}
}
if (!dirPrefix.IsEmpty())
NName::NormalizeDirPathPrefix(dirPrefix);
ecs->DirPathPrefix_for_HashFiles = dirPrefix;
}
}
if (!options.StdInMode)
{
// numVolumes += arcLink.VolumePaths.Size();

View File

@@ -17,7 +17,10 @@
struct CExtractOptionsBase
{
CBoolPair ElimDup;
bool ExcludeDirItems;
bool ExcludeFileItems;
bool PathMode_Force;
bool OverwriteMode_Force;
NExtract::NPathMode::EEnum PathMode;
@@ -25,8 +28,11 @@ struct CExtractOptionsBase
FString OutputDir;
CExtractNtOptions NtOptions;
UString HashDir;
CExtractOptionsBase():
ExcludeDirItems(false),
ExcludeFileItems(false),
PathMode_Force(false),
OverwriteMode_Force(false),
PathMode(NExtract::NPathMode::kFullPaths),
@@ -48,9 +54,11 @@ struct CExtractOptions: public CExtractOptionsBase
CObjectVector<CProperty> Properties;
#endif
/*
#ifdef EXTERNAL_CODECS
CCodecs *Codecs;
#endif
*/
CExtractOptions():
StdInMode(false),
@@ -77,6 +85,7 @@ struct CDecompressStat
};
HRESULT Extract(
// DECL_EXTERNAL_CODECS_LOC_VARS
CCodecs *codecs,
const CObjectVector<COpenType> &types,
const CIntVector &excludedFormats,

View File

File diff suppressed because it is too large Load Diff

View File

@@ -3,15 +3,17 @@
#ifndef __HASH_CALC_H
#define __HASH_CALC_H
#include "../../../Common/UTFConvert.h"
#include "../../../Common/Wildcard.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/MethodProps.h"
#include "DirItem.h"
#include "IFileExtractCallback.h"
const unsigned k_HashCalc_DigestSize_Max = 64;
const unsigned k_HashCalc_ExtraSize = 8;
const unsigned k_HashCalc_NumGroups = 4;
enum
@@ -27,9 +29,37 @@ struct CHasherState
CMyComPtr<IHasher> Hasher;
AString Name;
UInt32 DigestSize;
Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max];
UInt64 NumSums[k_HashCalc_NumGroups];
Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max + k_HashCalc_ExtraSize];
void InitDigestGroup(unsigned groupIndex)
{
NumSums[groupIndex] = 0;
memset(Digests[groupIndex], 0, sizeof(Digests[groupIndex]));
}
const Byte *GetExtraData_for_Group(unsigned groupIndex) const
{
return Digests[groupIndex] + k_HashCalc_DigestSize_Max;
}
unsigned GetNumExtraBytes_for_Group(unsigned groupIndex) const
{
const Byte *p = GetExtraData_for_Group(groupIndex);
// we use little-endian to read extra bytes
for (unsigned i = k_HashCalc_ExtraSize; i != 0; i--)
if (p[i - 1] != 0)
return i;
return 0;
}
void AddDigest(unsigned groupIndex, const Byte *data);
void WriteToString(unsigned digestIndex, char *s) const;
};
struct IHashCalc
{
virtual void InitForNewFile() = 0;
@@ -89,9 +119,68 @@ struct IHashCallbackUI: public IDirItemsCallback
INTERFACE_IHashCallbackUI(=0)
};
struct CHashOptionsLocal
{
CBoolPair HashMode_Zero;
CBoolPair HashMode_Tag;
CBoolPair HashMode_Dirs;
CBoolPair HashMode_OnlyHash;
void Init_HashOptionsLocal()
{
HashMode_Zero.Init();
HashMode_Tag.Init();
HashMode_Dirs.Init();
HashMode_OnlyHash.Init();
// HashMode_Dirs = true; // for debug
}
CHashOptionsLocal()
{
Init_HashOptionsLocal();
}
bool ParseFlagCharOption(wchar_t c, bool val)
{
c = MyCharLower_Ascii(c);
if (c == 'z') HashMode_Zero.SetVal_as_Defined(val);
else if (c == 't') HashMode_Tag.SetVal_as_Defined(val);
else if (c == 'd') HashMode_Dirs.SetVal_as_Defined(val);
else if (c == 'h') HashMode_OnlyHash.SetVal_as_Defined(val);
else return false;
return true;
}
bool ParseString(const UString &s)
{
for (unsigned i = 0; i < s.Len();)
{
const wchar_t c = s[i++];
bool val = true;
if (i < s.Len())
{
const wchar_t next = s[i];
if (next == '-')
{
val = false;
i++;
}
}
if (!ParseFlagCharOption(c, val))
return false;
}
return true;
}
};
struct CHashOptions
// : public CHashOptionsLocal
{
UStringVector Methods;
// UString HashFilePath;
bool PreserveATime;
bool OpenShareForWrite;
bool StdInMode;
@@ -99,7 +188,7 @@ struct CHashOptions
CBoolPair SymLinks;
NWildcard::ECensorPathMode PathMode;
CHashOptions():
PreserveATime(false),
OpenShareForWrite(false),
@@ -108,6 +197,7 @@ struct CHashOptions
PathMode(NWildcard::k_RelatPath) {};
};
HRESULT HashCalc(
DECL_EXTERNAL_CODECS_LOC_VARS
const NWildcard::CCensor &censor,
@@ -115,6 +205,130 @@ HRESULT HashCalc(
AString &errorInfo,
IHashCallbackUI *callback);
void AddHashHexToString(char *dest, const Byte *data, UInt32 size);
#ifndef _SFX
namespace NHash {
struct CHashPair
{
CByteBuffer Hash;
char Mode;
bool IsBSD;
bool Size_from_Arc_Defined;
bool Size_from_Disk_Defined;
AString Method;
AString Name;
AString FullLine;
AString HashString;
// unsigned HashLengthInBits;
// AString MethodName;
UInt64 Size_from_Arc;
UInt64 Size_from_Disk;
bool IsDir() const;
void Get_UString_Path(UString &path) const
{
path.Empty();
if (!ConvertUTF8ToUnicode(Name, path))
return;
}
bool ParseCksum(const char *s);
bool Parse(const char *s);
bool IsSupportedMode() const
{
return Mode != 'U' && Mode != '^';
}
CHashPair():
Mode(0)
, IsBSD(false)
, Size_from_Arc_Defined(false)
, Size_from_Disk_Defined(false)
// , HashLengthInBits(0)
, Size_from_Arc(0)
, Size_from_Disk(0)
{}
};
class CHandler:
public IInArchive,
public IArchiveGetRawProps,
// public IGetArchiveHashHandler,
public IOutArchive,
public ISetProperties,
public CMyUnknownImp
{
bool _isArc;
UInt64 _phySize;
CObjectVector<CHashPair> HashPairs;
UString _nameExtenstion;
// UString _method_fromName;
AString _pgpMethod;
bool _is_CksumMode;
bool _is_PgpMethod;
bool _is_ZeroMode;
bool _are_there_Tags;
bool _are_there_Dirs;
bool _hashSize_Defined;
unsigned _hashSize;
bool _crcSize_WasSet;
UInt32 _crcSize;
UStringVector _methods;
void ClearVars();
void InitProps()
{
_crcSize_WasSet = false;
_crcSize = 4;
_methods.Clear();
_options.Init_HashOptionsLocal();
}
CHashOptionsLocal _options;
bool CanUpdate() const
{
if (!_isArc || _is_PgpMethod || _is_CksumMode)
return false;
return true;
}
HRESULT SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value);
public:
CHandler();
MY_UNKNOWN_IMP4(
IInArchive,
IArchiveGetRawProps,
IOutArchive,
ISetProperties
/*, IGetArchiveHashHandler */
)
INTERFACE_IInArchive(;)
INTERFACE_IOutArchive(;)
INTERFACE_IArchiveGetRawProps(;)
// STDMETHOD(GetArchiveHashHandler)(CHandler **handler);
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
};
}
void Codecs_AddHashArcHandler(CCodecs *codecs);
#endif
#endif

View File

@@ -103,9 +103,9 @@ DECL_INTERFACE_SUB(IGetProp, IUnknown, 0x01, 0x20)
STDMETHOD(UseExtractToStream)(Int32 *res) x; \
STDMETHOD(GetStream7)(const wchar_t *name, Int32 isDir, ISequentialOutStream **outStream, Int32 askExtractMode, IGetProp *getProp) x; \
STDMETHOD(PrepareOperation7)(Int32 askExtractMode) x; \
STDMETHOD(SetOperationResult7)(Int32 resultEOperationResult, Int32 encrypted) x; \
STDMETHOD(SetOperationResult8)(Int32 resultEOperationResult, Int32 encrypted, UInt64 size) x; \
DECL_INTERFACE_SUB(IFolderExtractToStreamCallback, IUnknown, 0x01, 0x30)
DECL_INTERFACE_SUB(IFolderExtractToStreamCallback, IUnknown, 0x01, 0x31)
{
INTERFACE_IFolderExtractToStreamCallback(PURE)
};

View File

@@ -53,6 +53,7 @@ using namespace NWindows;
#include "../../ICoder.h"
#include "../../Common/RegisterArc.h"
#include "../../Common/RegisterCodec.h"
#ifdef EXTERNAL_CODECS
@@ -193,9 +194,9 @@ void CArcInfoEx::AddExts(const UString &ext, const UString &addExt)
static bool ParseSignatures(const Byte *data, unsigned size, CObjectVector<CByteBuffer> &signatures)
{
signatures.Clear();
while (size > 0)
while (size != 0)
{
unsigned len = *data++;
const unsigned len = *data++;
size--;
if (len > size)
return false;
@@ -252,6 +253,25 @@ static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 in
return S_OK;
}
static HRESULT GetMethodBoolProp(Func_GetMethodProperty getMethodProperty, UInt32 index,
PROPID propId, bool &resVal, bool &isAssigned)
{
NCOM::CPropVariant prop;
resVal = false;
isAssigned = false;
RINOK(getMethodProperty(index, propId, &prop));
if (prop.vt == VT_BOOL)
{
isAssigned = true;
resVal = VARIANT_BOOLToBool(prop.boolVal);
}
else if (prop.vt != VT_EMPTY)
return E_FAIL;
return S_OK;
}
#define MY_GET_FUNC(dest, type, func) *(void **)(&dest) = (func);
// #define MY_GET_FUNC(dest, type, func) dest = (type)(func);
@@ -279,6 +299,7 @@ HRESULT CCodecs::LoadCodecs()
info.CodecIndex = i;
RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned));
RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned));
RINOK(GetMethodBoolProp(lib.GetMethodProperty, i, NMethodPropID::kIsFilter, info.IsFilter, info.IsFilter_Assigned));
Codecs.Add(info);
}
}
@@ -647,8 +668,14 @@ HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPath)
}
if (!found)
break;
#ifdef _WIN32
if (fi.IsDir())
continue;
#else
if (enumerator.DirEntry_IsDir(fi, true)) // followLink
continue;
#endif
RINOK(LoadDll(folderPrefix + fi.Name, true));
}
return S_OK;
@@ -725,7 +752,10 @@ HRESULT CCodecs::Load()
if (arc.IsMultiSignature())
ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures);
else
item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize);
{
if (arc.SignatureSize != 0) // 21.04
item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize);
}
#endif
@@ -776,6 +806,8 @@ HRESULT CCodecs::Load()
#endif
// we sort Formats to get fixed order of Formats after compilation.
Formats.Sort();
return S_OK;
}
@@ -952,6 +984,15 @@ STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *valu
prop.Detach(value);
return S_OK;
}
if (propID == NMethodPropID::kIsFilter && ci.IsFilter_Assigned)
{
NCOM::CPropVariant prop;
prop = (bool)ci.IsFilter;
prop.Detach(value);
return S_OK;
}
const CCodecLib &lib = Libs[ci.LibIndex];
return lib.GetMethodProperty(ci.CodecIndex, propID, value);
#else
@@ -1096,6 +1137,7 @@ bool CCodecs::GetCodec_DecoderIsAssigned(UInt32 index) const
#endif
}
bool CCodecs::GetCodec_EncoderIsAssigned(UInt32 index) const
{
#ifdef EXPORT_CODECS
@@ -1118,6 +1160,38 @@ bool CCodecs::GetCodec_EncoderIsAssigned(UInt32 index) const
#endif
}
bool CCodecs::GetCodec_IsFilter(UInt32 index, bool &isAssigned) const
{
isAssigned = false;
#ifdef EXPORT_CODECS
if (index < g_NumCodecs)
{
NCOM::CPropVariant prop;
if (GetProperty(index, NMethodPropID::kIsFilter, &prop) == S_OK)
{
if (prop.vt == VT_BOOL)
{
isAssigned = true;
return VARIANT_BOOLToBool(prop.boolVal);
}
}
return false;
}
#endif
#ifdef EXTERNAL_CODECS
{
const CDllCodecInfo &c = Codecs[index - NUM_EXPORT_CODECS];
isAssigned = c.IsFilter_Assigned;
return c.IsFilter;
}
#else
return false;
#endif
}
UInt32 CCodecs::GetCodec_NumStreams(UInt32 index)
{
NCOM::CPropVariant prop;
@@ -1203,3 +1277,45 @@ void CCodecs::GetCodecsErrorMessage(UString &s)
}
#endif // EXTERNAL_CODECS
#ifndef _SFX
extern unsigned g_NumCodecs;
extern const CCodecInfo *g_Codecs[];
void CCodecs::Get_CodecsInfoUser_Vector(CObjectVector<CCodecInfoUser> &v)
{
v.Clear();
{
for (unsigned i = 0; i < g_NumCodecs; i++)
{
const CCodecInfo &cod = *g_Codecs[i];
CCodecInfoUser &u = v.AddNew();
u.EncoderIsAssigned = (cod.CreateEncoder != NULL);
u.DecoderIsAssigned = (cod.CreateDecoder != NULL);
u.IsFilter_Assigned = true;
u.IsFilter = cod.IsFilter;
u.NumStreams = cod.NumStreams;
u.Name = cod.Name;
}
}
#ifdef EXTERNAL_CODECS
{
UInt32 numMethods;
if (GetNumMethods(&numMethods) == S_OK)
for (UInt32 j = 0; j < numMethods; j++)
{
CCodecInfoUser &u = v.AddNew();
u.EncoderIsAssigned = GetCodec_EncoderIsAssigned(j);
u.DecoderIsAssigned = GetCodec_DecoderIsAssigned(j);
u.IsFilter = GetCodec_IsFilter(j, u.IsFilter_Assigned);
u.NumStreams = GetCodec_NumStreams(j);
u.Name = GetCodec_Name(j);
}
}
#endif
}
#endif

View File

@@ -68,6 +68,8 @@ struct CDllCodecInfo
UInt32 CodecIndex;
bool EncoderIsAssigned;
bool DecoderIsAssigned;
bool IsFilter;
bool IsFilter_Assigned;
CLSID Encoder;
CLSID Decoder;
};
@@ -119,6 +121,23 @@ struct CArcInfoEx
CLSID ClassID;
#endif
int Compare(const CArcInfoEx &a) const
{
int res = Name.Compare(a.Name);
if (res != 0)
return res;
#ifdef EXTERNAL_CODECS
return MyCompare(LibIndex, a.LibIndex);
#else
return 0;
#endif
/*
if (LibIndex < a.LibIndex) return -1;
if (LibIndex > a.LibIndex) return 1;
return 0;
*/
}
bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; }
bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; }
@@ -133,6 +152,7 @@ struct CArcInfoEx
bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; }
bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; }
bool Flags_ByExtOnlyOpen() const { return (Flags & NArcInfoFlags::kByExtOnlyOpen) != 0; }
bool Flags_HashHandler() const { return (Flags & NArcInfoFlags::kHashHandler) != 0; }
UString GetMainExt() const
{
@@ -236,6 +256,21 @@ struct CCodecError
CCodecError(): ErrorCode(0) {}
};
struct CCodecInfoUser
{
// unsigned LibIndex;
// UInt32 CodecIndex;
// UInt64 id;
bool EncoderIsAssigned;
bool DecoderIsAssigned;
bool IsFilter;
bool IsFilter_Assigned;
UInt32 NumStreams;
AString Name;
};
class CCodecs:
#ifdef EXTERNAL_CODECS
public ICompressCodecsInfo,
@@ -353,6 +388,7 @@ public:
int GetCodec_LibIndex(UInt32 index) const;
bool GetCodec_DecoderIsAssigned(UInt32 index) const;
bool GetCodec_EncoderIsAssigned(UInt32 index) const;
bool GetCodec_IsFilter(UInt32 index, bool &isAssigned) const;
UInt32 GetCodec_NumStreams(UInt32 index);
HRESULT GetCodec_Id(UInt32 index, UInt64 &id);
AString GetCodec_Name(UInt32 index);
@@ -416,6 +452,8 @@ public:
return -1;
}
void Get_CodecsInfoUser_Vector(CObjectVector<CCodecInfoUser> &v);
#endif // _SFX
};
@@ -432,5 +470,5 @@ public:
CCodecs *codecs = new CCodecs; \
CMyComPtr<IUnknown> __codecsRef = codecs;
#endif
#endif

View File

@@ -1026,30 +1026,33 @@ static void MakeCheckOrder(CCodecs *codecs,
{
for (unsigned i = 0; i < numTypes; i++)
{
int index = orderIndices[i];
const int index = orderIndices[i];
if (index < 0)
continue;
const CArcInfoEx &ai = codecs->Formats[(unsigned)index];
if (ai.SignatureOffset != 0)
if (ai.SignatureOffset == 0)
{
orderIndices2.Add(index);
orderIndices[i] = -1;
continue;
}
const CObjectVector<CByteBuffer> &sigs = ai.Signatures;
FOR_VECTOR (k, sigs)
{
const CByteBuffer &sig = sigs[k];
if ((sig.Size() == 0 && dataSize == 0)
|| (sig.Size() != 0 && sig.Size() <= dataSize
&& TestSignature(data, sig, sig.Size())))
if (ai.Signatures.IsEmpty())
{
orderIndices2.Add(index);
orderIndices[i] = -1;
break;
if (dataSize != 0) // 21.04: no Sinature means Empty Signature
continue;
}
else
{
unsigned k;
const CObjectVector<CByteBuffer> &sigs = ai.Signatures;
for (k = 0; k < sigs.Size(); k++)
{
const CByteBuffer &sig = sigs[k];
if (sig.Size() <= dataSize && TestSignature(data, sig, sig.Size()))
break;
}
if (k == sigs.Size())
continue;
}
}
orderIndices2.Add(index);
orderIndices[i] = -1;
}
}
@@ -2144,7 +2147,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
continue;
}
bool isNewStyleSignature = IsNewStyleSignature(ai);
const bool isNewStyleSignature = IsNewStyleSignature(ai);
bool needCheck = !isNewStyleSignature
|| ai.Signatures.IsEmpty()
|| ai.Flags_PureStartOpen()
@@ -2157,13 +2160,12 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
for (k = 0; k < ai.Signatures.Size(); k++)
{
const CByteBuffer &sig = ai.Signatures[k];
UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size();
if (processedSize < signatureEnd)
if (processedSize < ai.SignatureOffset + sig.Size())
{
if (!endOfFile)
needCheck = true;
}
else if (memcmp(sig, byteBuffer + ai.SignatureOffset, sig.Size()) == 0)
else if (TestSignature(sig, byteBuffer + ai.SignatureOffset, sig.Size()))
break;
}
if (k != ai.Signatures.Size())
@@ -3391,7 +3393,7 @@ HRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI)
return S_OK;
}
HRESULT CArc::ReOpen(const COpenOptions &op)
HRESULT CArc::ReOpen(const COpenOptions &op, IArchiveOpenCallback *openCallback_Additional)
{
ErrorInfo.ClearErrors();
ErrorInfo.ErrorFormatIndex = -1;
@@ -3421,7 +3423,10 @@ HRESULT CArc::ReOpen(const COpenOptions &op)
// There are archives with embedded STUBs (like ZIP), so we must support signature scanning
// But for another archives we can use 0 here. So the code can be fixed !!!
UInt64 maxStartPosition = kMaxCheckStartPosition;
HRESULT res = Archive->Open(stream2, &maxStartPosition, op.callback);
IArchiveOpenCallback *openCallback = openCallback_Additional;
if (!openCallback)
openCallback = op.callback;
HRESULT res = Archive->Open(stream2, &maxStartPosition, openCallback);
if (res == S_OK)
{
@@ -3477,7 +3482,7 @@ HRESULT CArchiveLink::ReOpen(COpenOptions &op)
op.stream = stream;
CArc &arc = Arcs[0];
HRESULT res = arc.ReOpen(op);
HRESULT res = arc.ReOpen(op, openCallbackNew);
PasswordWasAsked = openCallbackSpec->PasswordWasAsked;
// Password = openCallbackSpec->Password;
@@ -3580,6 +3585,12 @@ static bool ParseType(CCodecs &codecs, const UString &s, COpenType &type)
type.CanReturnArc = false;
type.CanReturnParser = true;
}
else if (name.IsEqualTo_Ascii_NoCase("hash"))
{
// type.CanReturnArc = false;
// type.CanReturnParser = false;
type.IsHashType = true;
}
else
return false;
}
@@ -3607,6 +3618,7 @@ static bool ParseType(CCodecs &codecs, const UString &s, COpenType &type)
bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types)
{
types.Clear();
bool isHashType = false;
for (unsigned pos = 0; pos < s.Len();)
{
int pos2 = s.Find(L'.', pos);
@@ -3618,10 +3630,24 @@ bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType>
COpenType type;
if (!ParseType(codecs, name, type))
return false;
if (isHashType)
return false;
if (type.IsHashType)
isHashType = true;
types.Add(type);
pos = (unsigned)pos2 + 1;
}
return true;
}
/*
bool IsHashType(const CObjectVector<COpenType> &types)
{
if (types.Size() != 1)
return false;
return types[0].IsHashType;
}
*/
#endif

View File

@@ -70,6 +70,7 @@ struct COpenType
bool CanReturnArc;
bool CanReturnParser;
bool IsHashType;
bool EachPos;
// bool SkipSfxStub;
@@ -90,6 +91,7 @@ struct COpenType
Recursive(true),
CanReturnArc(true),
CanReturnParser(false),
IsHashType(false),
EachPos(false),
// SkipSfxStub(true),
// ExeAsUnknown(true),
@@ -285,7 +287,7 @@ public:
UString Path;
UString filePath;
UString DefaultName;
int FormatIndex; // - 1 means Parser.
int FormatIndex; // -1 means Parser
UInt32 SubfileIndex; // (UInt32)(Int32)-1; means no subfile
FILETIME MTime;
bool MTimeDefined;
@@ -358,9 +360,16 @@ public:
HRESULT OpenStream(const COpenOptions &options);
HRESULT OpenStreamOrFile(COpenOptions &options);
HRESULT ReOpen(const COpenOptions &options);
HRESULT ReOpen(const COpenOptions &options, IArchiveOpenCallback *openCallback_Additional);
HRESULT CreateNewTailStream(CMyComPtr<IInStream> &stream);
bool IsHashHandler(const COpenOptions &options) const
{
if (FormatIndex < 0)
return false;
return options.codecs->Formats[(unsigned)FormatIndex].Flags_HashHandler();
}
};
struct CArchiveLink
@@ -421,6 +430,8 @@ struct CArchiveLink
bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
// bool IsHashType(const CObjectVector<COpenType> &types);
struct CDirPathSortPair
{

View File

@@ -542,9 +542,9 @@ static HRESULT Compress(
#endif
}
if (outArchive == 0)
if (!outArchive)
throw kUpdateIsNotSupoorted;
NFileTimeType::EEnum fileTimeType;
{
UInt32 value;
@@ -568,6 +568,8 @@ static HRESULT Compress(
return E_NOTIMPL;
if (options.NtSecurity.Val && !arcInfo.Flags_NtSecure())
return E_NOTIMPL;
if (options.DeleteAfterCompressing && arcInfo.Flags_HashHandler())
return E_NOTIMPL;
}
CRecordVector<CUpdatePair2> updatePairs2;
@@ -745,6 +747,11 @@ static HRESULT Compress(
updateCallbackSpec->ProcessedItemsStatuses = processedItemsStatuses;
{
const UString arcPath = archivePath.GetFinalPath();
updateCallbackSpec->ArcFileName = ExtractFileNameFromPath(arcPath);
}
if (options.RenamePairs.Size() != 0)
updateCallbackSpec->NewNames = &newNames;
@@ -907,7 +914,7 @@ static HRESULT Compress(
ft.dwHighDateTime = 0;
FOR_VECTOR (i, updatePairs2)
{
CUpdatePair2 &pair2 = updatePairs2[i];
const CUpdatePair2 &pair2 = updatePairs2[i];
const FILETIME *ft2 = NULL;
if (pair2.NewProps && pair2.DirIndex >= 0)
ft2 = &dirItems.Items[(unsigned)pair2.DirIndex].MTime;
@@ -945,9 +952,28 @@ static HRESULT Compress(
result = outStreamSpec->Close();
else if (volStreamSpec)
result = volStreamSpec->Close();
RINOK(result)
if (processedItemsStatuses)
{
FOR_VECTOR (i, updatePairs2)
{
const CUpdatePair2 &up = updatePairs2[i];
if (up.NewData && up.DirIndex >= 0)
{
const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex];
if (di.AreReparseData() || (!di.IsDir() && di.Size == 0))
processedItemsStatuses[(unsigned)up.DirIndex] = 1;
}
}
}
return result;
}
bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include);
static bool Censor_CheckPath(const NWildcard::CCensor &censor, const CReadArcItem &item)
@@ -1288,6 +1314,8 @@ HRESULT UpdateArchive(
#endif
dirItems.ScanAltStreams = options.AltStreams.Val;
dirItems.ExcludeDirItems = censor.ExcludeDirItems;
dirItems.ExcludeFileItems = censor.ExcludeFileItems;
HRESULT res = EnumerateItems(censor,
options.PathMode,
@@ -1440,7 +1468,7 @@ HRESULT UpdateArchive(
CByteBuffer processedItems;
if (options.DeleteAfterCompressing)
{
unsigned num = dirItems.Items.Size();
const unsigned num = dirItems.Items.Size();
processedItems.Alloc(num);
for (unsigned i = 0; i < num; i++)
processedItems[i] = 0;
@@ -1654,17 +1682,27 @@ HRESULT UpdateArchive(
}
else
{
if (processedItems[i] != 0 || dirItem.Size == 0)
// 21.04: we have set processedItems[*] before for all required items
if (processedItems[i] != 0
// || dirItem.Size == 0
// || dirItem.AreReparseData()
)
{
NFind::CFileInfo fileInfo;
/* here we compare Raw FileInfo that can be link with actual file info that was processed.
we can fix it. */
if (fileInfo.Find(phyPath))
/* if (!SymLinks), we follow link here, similar to (dirItem) filling */
if (fileInfo.Find(phyPath, !options.SymLinks.Val))
{
// FIXME: here we can check Find_FollowLink() also;
bool is_SameSize = false;
if (options.SymLinks.Val && dirItem.AreReparseData())
{
/* (dirItem.Size = dirItem.ReparseData.Size()) was set before.
So we don't compare sizes for that case here */
is_SameSize = fileInfo.IsOsSymLink();
}
else
is_SameSize = (fileInfo.Size == dirItem.Size);
// maybe we must exclude also files with archive name: "a a.7z * -sdel"
if (fileInfo.Size == dirItem.Size
if (is_SameSize
&& CompareFileTime(&fileInfo.MTime, &dirItem.MTime) == 0
&& CompareFileTime(&fileInfo.CTime, &dirItem.CTime) == 0)
{
@@ -1675,11 +1713,11 @@ HRESULT UpdateArchive(
}
else
{
// file was skipped
// file was skipped by some reason. We can throw error for debug:
/*
errorInfo.SystemError = 0;
errorInfo.Message = "file was not processed";
errorInfo.FileName = phyPath;
errorInfo.FileNames.Add(phyPath);
return E_FAIL;
*/
}

View File

@@ -144,6 +144,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *val
case kpidCTime: if (ParentDirItem) prop = ParentDirItem->CTime; break;
case kpidATime: if (ParentDirItem) prop = ParentDirItem->ATime; break;
case kpidMTime: if (ParentDirItem) prop = ParentDirItem->MTime; break;
case kpidArcFileName: if (!ArcFileName.IsEmpty()) prop = ArcFileName; break;
}
prop.Detach(value);
return S_OK;
@@ -475,6 +476,17 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
static NSynchronization::CCriticalSection CS;
#endif
void CArchiveUpdateCallback::UpdateProcessedItemStatus(unsigned dirIndex)
{
if (ProcessedItemsStatuses)
{
#ifndef _7ZIP_ST
NSynchronization::CCriticalSectionLock lock(CS);
#endif
ProcessedItemsStatuses[dirIndex] = 1;
}
}
STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode)
{
COM_TRY_BEGIN
@@ -544,6 +556,8 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea
CMyComPtr<ISequentialInStream> inStreamLoc = inStreamSpec;
inStreamSpec->Init(di.ReparseData, di.ReparseData.Size());
*inStream = inStreamLoc.Detach();
UpdateProcessedItemStatus((unsigned)up.DirIndex);
return S_OK;
}
#endif // !defined(UNDER_CE)
@@ -600,13 +614,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea
}
// #endif
if (ProcessedItemsStatuses)
{
#ifndef _7ZIP_ST
NSynchronization::CCriticalSectionLock lock(CS);
#endif
ProcessedItemsStatuses[(unsigned)up.DirIndex] = 1;
}
UpdateProcessedItemStatus((unsigned)up.DirIndex);
*inStream = inStreamLoc.Detach();
}
@@ -649,7 +657,7 @@ STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 in
isDir = DirItems->Items[(unsigned)up.DirIndex].IsDir();
}
}
return Callback->ReportUpdateOpeartion(op, name.IsEmpty() ? NULL : name.Ptr(), isDir);
return Callback->ReportUpdateOperation(op, name.IsEmpty() ? NULL : name.Ptr(), isDir);
}
wchar_t temp[16];
@@ -684,7 +692,7 @@ STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 in
if (!s)
s = L"";
return Callback->ReportUpdateOpeartion(op, s, isDir);
return Callback->ReportUpdateOperation(op, s, isDir);
COM_TRY_END
}

View File

@@ -40,7 +40,7 @@ struct CArcToDoStat
virtual HRESULT ReadingFileError(const FString &path, DWORD systemError) x; \
virtual HRESULT SetOperationResult(Int32 opRes) x; \
virtual HRESULT ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) x; \
virtual HRESULT ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool isDir) x; \
virtual HRESULT ReportUpdateOperation(UInt32 op, const wchar_t *name, bool isDir) x; \
/* virtual HRESULT SetPassword(const UString &password) x; */ \
virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \
virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \
@@ -87,6 +87,8 @@ class CArchiveUpdateCallback:
UInt32 _hardIndex_From;
UInt32 _hardIndex_To;
void UpdateProcessedItemStatus(unsigned dirIndex);
public:
MY_QUERYINTERFACE_BEGIN2(IArchiveUpdateCallback2)
MY_QUERYINTERFACE_ENTRY(IArchiveUpdateCallbackFile)
@@ -121,6 +123,7 @@ public:
CRecordVector<UInt64> VolumesSizes;
FString VolName;
FString VolExt;
UString ArcFileName; // without path prefix
IUpdateCallbackUI *Callback;
@@ -147,7 +150,6 @@ public:
Byte *ProcessedItemsStatuses;
CArchiveUpdateCallback();
bool IsDir(const CUpdatePair2 &up) const