mirror of
https://github.com/ip7z/7zip.git
synced 2026-04-21 06:03:40 +00:00
Merge 6128789b97 into 839151eaaa
This commit is contained in:
commit
61048d143e
30 changed files with 530 additions and 34 deletions
|
|
@ -896,6 +896,8 @@ $O/DefaultName.o: ../../UI/Common/DefaultName.cpp
|
|||
$(CXX) $(CXXFLAGS) $<
|
||||
$O/EnumDirItems.o: ../../UI/Common/EnumDirItems.cpp
|
||||
$(CXX) $(CXXFLAGS) $<
|
||||
$O/ChainedExtract.o: ../../UI/Common/ChainedExtract.cpp
|
||||
$(CXX) $(CXXFLAGS) $<
|
||||
$O/Extract.o: ../../UI/Common/Extract.cpp
|
||||
$(CXX) $(CXXFLAGS) $<
|
||||
$O/ExtractingFilePath.o: ../../UI/Common/ExtractingFilePath.cpp
|
||||
|
|
|
|||
|
|
@ -730,15 +730,18 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
|||
stream = _stream;
|
||||
|
||||
const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
if (allFilesMode && !seqMode)
|
||||
numItems = _items.Size();
|
||||
if (_stream && numItems == 0)
|
||||
return S_OK;
|
||||
UInt64 totalSize = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < numItems; i++)
|
||||
totalSize += _items[allFilesMode ? i : indices[i]].Get_UnpackSize();
|
||||
RINOK(extractCallback->SetTotal(totalSize))
|
||||
if (!(seqMode && allFilesMode))
|
||||
{
|
||||
for (i = 0; i < numItems; i++)
|
||||
totalSize += _items[allFilesMode ? i : indices[i]].Get_UnpackSize();
|
||||
RINOK(extractCallback->SetTotal(totalSize))
|
||||
}
|
||||
|
||||
UInt64 totalPackSize;
|
||||
totalSize = totalPackSize = 0;
|
||||
|
|
|
|||
|
|
@ -186,6 +186,7 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item)
|
|||
filled = false;
|
||||
|
||||
bool thereAreEmptyRecords = false;
|
||||
unsigned numEmptyRecords = 0;
|
||||
for (;;)
|
||||
{
|
||||
size_t processedSize = NFileHeader::kRecordSize;
|
||||
|
|
@ -219,6 +220,9 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item)
|
|||
break;
|
||||
item.HeaderSize += NFileHeader::kRecordSize;
|
||||
thereAreEmptyRecords = true;
|
||||
numEmptyRecords++;
|
||||
if (!InStream && numEmptyRecords >= 2)
|
||||
return S_OK;
|
||||
RINOK(Progress(item, 0))
|
||||
}
|
||||
if (thereAreEmptyRecords)
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ UI_COMMON_OBJS = \
|
|||
$O/Bench.o \
|
||||
$O/DefaultName.o \
|
||||
$O/EnumDirItems.o \
|
||||
$O/ChainedExtract.o \
|
||||
$O/Extract.o \
|
||||
$O/ExtractingFilePath.o \
|
||||
$O/HashCalc.o \
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ UI_COMMON_OBJS = \
|
|||
$O/Bench.o \
|
||||
$O/DefaultName.o \
|
||||
$O/EnumDirItems.o \
|
||||
$O/ChainedExtract.o \
|
||||
$O/Extract.o \
|
||||
$O/ExtractingFilePath.o \
|
||||
$O/HashCalc.o \
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ UI_COMMON_OBJS = \
|
|||
$O\CompressCall2.obj \
|
||||
$O\DefaultName.obj \
|
||||
$O\EnumDirItems.obj \
|
||||
$O\ChainedExtract.obj \
|
||||
$O\Extract.obj \
|
||||
$O\ExtractingFilePath.obj \
|
||||
$O\HashCalc.obj \
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ UI_COMMON_OBJS = \
|
|||
$O\ArchiveExtractCallback.obj \
|
||||
$O\ArchiveOpenCallback.obj \
|
||||
$O\DefaultName.obj \
|
||||
$O\ChainedExtract.obj \
|
||||
$O\Extract.obj \
|
||||
$O\ExtractingFilePath.obj \
|
||||
$O\LoadCodecs.obj \
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ UI_COMMON_OBJS = \
|
|||
$O/ArchiveExtractCallback.o \
|
||||
$O/ArchiveOpenCallback.o \
|
||||
$O/DefaultName.o \
|
||||
$O/ChainedExtract.o \
|
||||
$O/Extract.o \
|
||||
$O/ExtractingFilePath.o \
|
||||
$O/LoadCodecs.o \
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ UI_COMMON_OBJS = \
|
|||
$O\ArchiveExtractCallback.obj \
|
||||
$O\ArchiveOpenCallback.obj \
|
||||
$O\DefaultName.obj \
|
||||
$O\ChainedExtract.obj \
|
||||
$O\Extract.obj \
|
||||
$O\ExtractingFilePath.obj \
|
||||
$O\LoadCodecs.obj \
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#ifndef ZIP7_INC_STREAM_BINDER_H
|
||||
#define ZIP7_INC_STREAM_BINDER_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Windows/Synchronization.h"
|
||||
|
||||
#include "../IStream.h"
|
||||
|
|
|
|||
|
|
@ -187,6 +187,7 @@ enum Enum
|
|||
kUseSlashMark,
|
||||
kDisableWildcardParsing,
|
||||
kElimDup,
|
||||
kChainedExtract,
|
||||
kFullPathMode,
|
||||
|
||||
kHardLinks,
|
||||
|
|
@ -338,6 +339,7 @@ static const CSwitchForm kSwitchForms[] =
|
|||
{ "spm", SWFRM_STRING_SINGL(0) },
|
||||
{ "spd", SWFRM_SIMPLE },
|
||||
{ "spe", SWFRM_MINUS },
|
||||
{ "sce", SWFRM_MINUS },
|
||||
{ "spf", SWFRM_STRING_SINGL(0) },
|
||||
|
||||
{ "snh", SWFRM_MINUS },
|
||||
|
|
@ -1358,6 +1360,9 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
|
|||
options.ExtractOptions.ElimDup.Def = true;
|
||||
options.ExtractOptions.ElimDup.Val = !parser[NKey::kElimDup].WithMinus;
|
||||
}
|
||||
|
||||
if (parser[NKey::kChainedExtract].ThereIs)
|
||||
options.ExtractOptions.EnableChainedExtract = !parser[NKey::kChainedExtract].WithMinus;
|
||||
|
||||
NWildcard::ECensorPathMode censorPathMode = NWildcard::k_RelatPath;
|
||||
bool fullPathMode = parser[NKey::kFullPathMode].ThereIs;
|
||||
|
|
|
|||
|
|
@ -301,7 +301,8 @@ CArchiveExtractCallback::CArchiveExtractCallback():
|
|||
// Write_MTime(true),
|
||||
Is_elimPrefix_Mode(false),
|
||||
_arc(NULL),
|
||||
_multiArchives(false)
|
||||
_multiArchives(false),
|
||||
_disableProgress(false)
|
||||
{
|
||||
#ifdef Z7_USE_SECURITY_CODE
|
||||
_saclEnabled = InitLocalPrivileges();
|
||||
|
|
@ -311,6 +312,7 @@ CArchiveExtractCallback::CArchiveExtractCallback():
|
|||
|
||||
void CArchiveExtractCallback::InitBeforeNewArchive()
|
||||
{
|
||||
_disableProgress = false;
|
||||
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
|
||||
ZoneBuf.Free();
|
||||
#endif
|
||||
|
|
@ -403,6 +405,8 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetTotal(UInt64 size))
|
|||
COM_TRY_BEGIN
|
||||
_progressTotal = size;
|
||||
// _progressTotal_Defined = true;
|
||||
if (_disableProgress)
|
||||
return S_OK;
|
||||
if (!_multiArchives && _extractCallback2)
|
||||
return _extractCallback2->SetTotal(size);
|
||||
return S_OK;
|
||||
|
|
@ -438,6 +442,9 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue))
|
|||
if (!_extractCallback2)
|
||||
return S_OK;
|
||||
|
||||
if (_disableProgress)
|
||||
return S_OK;
|
||||
|
||||
UInt64 packCur;
|
||||
if (_multiArchives)
|
||||
{
|
||||
|
|
@ -455,6 +462,8 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue))
|
|||
Z7_COM7F_IMF(CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (_disableProgress)
|
||||
return S_OK;
|
||||
return LocalProgressSpec.Interface()->SetRatioInfo(inSize, outSize);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
|
|
|||
|
|
@ -391,6 +391,7 @@ private:
|
|||
bool _some_pathParts_wereRemoved;
|
||||
|
||||
bool _multiArchives;
|
||||
bool _disableProgress;
|
||||
bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_";
|
||||
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
|
||||
bool _saclEnabled;
|
||||
|
|
@ -529,6 +530,11 @@ public:
|
|||
|
||||
void InitBeforeNewArchive();
|
||||
|
||||
void DisableProgress()
|
||||
{
|
||||
_disableProgress = true;
|
||||
}
|
||||
|
||||
void Init(
|
||||
const CExtractNtOptions &ntOptions,
|
||||
const NWildcard::CCensorNode *wildcardCensor,
|
||||
|
|
|
|||
294
CPP/7zip/UI/Common/ChainedExtract.cpp
Normal file
294
CPP/7zip/UI/Common/ChainedExtract.cpp
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
// ChainedExtract.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/StreamBinder.h"
|
||||
#include "../../Common/VirtThread.h"
|
||||
|
||||
#include "ChainedExtract.h"
|
||||
|
||||
|
||||
static void SetExtractOpResMessage(Int32 opRes, UString &message)
|
||||
{
|
||||
message.Empty();
|
||||
|
||||
switch (opRes)
|
||||
{
|
||||
case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
|
||||
message = "Unsupported Method";
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kDataError:
|
||||
message = "Data Error";
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kCRCError:
|
||||
message = "CRC Failed";
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kUnavailable:
|
||||
message = "Unavailable data";
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kUnexpectedEnd:
|
||||
message = "Unexpected end of data";
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kDataAfterEnd:
|
||||
message = "There are some data after the end of the payload data";
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kIsNotArc:
|
||||
message = "Is not archive";
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kHeadersError:
|
||||
message = "Headers Error";
|
||||
break;
|
||||
case NArchive::NExtract::NOperationResult::kWrongPassword:
|
||||
message = "Wrong password";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static HRESULT CheckOuterStreamResult(Int32 opRes, UString &errorMessage)
|
||||
{
|
||||
if (opRes == NArchive::NExtract::NOperationResult::kOK)
|
||||
return S_OK;
|
||||
|
||||
SetExtractOpResMessage(opRes, errorMessage);
|
||||
if (errorMessage.IsEmpty())
|
||||
errorMessage = "Error";
|
||||
errorMessage = UString("Outer stream: ") + errorMessage;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
static HRESULT DrainChainedStream(ISequentialInStream *stream)
|
||||
{
|
||||
Byte buf[1 << 15];
|
||||
|
||||
for (;;)
|
||||
{
|
||||
UInt32 processed = 0;
|
||||
RINOK(stream->Read(buf, (UInt32)sizeof(buf), &processed))
|
||||
if (processed == 0)
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CChainedStreamExtractCallback
|
||||
, IArchiveExtractCallback
|
||||
)
|
||||
Z7_IFACE_COM7_IMP(IProgress)
|
||||
public:
|
||||
CMyComPtr<IFolderArchiveExtractCallback> Progress;
|
||||
CMyComPtr<ISequentialOutStream> Stream;
|
||||
Int32 OperationResult;
|
||||
bool MultiMode;
|
||||
UInt64 CompletedBeforeArc;
|
||||
|
||||
void Init(IFolderArchiveExtractCallback *progress, ISequentialOutStream *stream,
|
||||
bool multiMode, UInt64 completedBeforeArc)
|
||||
{
|
||||
Progress = progress;
|
||||
Stream = stream;
|
||||
OperationResult = NArchive::NExtract::NOperationResult::kOK;
|
||||
MultiMode = multiMode;
|
||||
CompletedBeforeArc = completedBeforeArc;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CChainedStreamExtractCallback::SetTotal(UInt64 size))
|
||||
{
|
||||
if (MultiMode)
|
||||
return S_OK;
|
||||
return Progress ? Progress->SetTotal(size) : S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CChainedStreamExtractCallback::SetCompleted(const UInt64 *completeValue))
|
||||
{
|
||||
if (MultiMode)
|
||||
{
|
||||
if (!Progress || !completeValue)
|
||||
return S_OK;
|
||||
const UInt64 completed = CompletedBeforeArc + *completeValue;
|
||||
return Progress->SetCompleted(&completed);
|
||||
}
|
||||
return Progress ? Progress->SetCompleted(completeValue) : S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CChainedStreamExtractCallback::GetStream(
|
||||
UInt32 index, ISequentialOutStream **outStream, Int32 /* askExtractMode */))
|
||||
{
|
||||
*outStream = NULL;
|
||||
if (index != 0 || !Stream)
|
||||
return E_FAIL;
|
||||
*outStream = Stream.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CChainedStreamExtractCallback::PrepareOperation(Int32 /* askExtractMode */))
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CChainedStreamExtractCallback::SetOperationResult(Int32 opRes))
|
||||
{
|
||||
OperationResult = opRes;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
struct CChainedStreamExtractThread Z7_final:
|
||||
public CVirtThread
|
||||
{
|
||||
const CArc *Arc;
|
||||
CMyComPtr<IArchiveExtractCallback> Callback;
|
||||
HRESULT Result;
|
||||
|
||||
CChainedStreamExtractThread():
|
||||
Arc(NULL),
|
||||
Result(S_OK)
|
||||
{}
|
||||
|
||||
void Execute() Z7_override
|
||||
{
|
||||
Result = Arc->Archive->Extract(NULL, (UInt32)(Int32)-1, 0, Callback);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static int FindChainedFormatIndex(
|
||||
const CCodecs *codecs,
|
||||
const CArc &arc,
|
||||
const CExtractOptions &options)
|
||||
{
|
||||
if (!options.EnableChainedExtract)
|
||||
return -1;
|
||||
if (options.StdInMode || options.StdOutMode)
|
||||
return -1;
|
||||
if (arc.FormatIndex < 0)
|
||||
return -1;
|
||||
const CArcInfoEx &ai = codecs->Formats[(unsigned)arc.FormatIndex];
|
||||
const UString wrappedExt = ai.GetWrappedExt();
|
||||
if (wrappedExt.IsEmpty())
|
||||
return -1;
|
||||
UInt32 numItems = 0;
|
||||
if (arc.Archive->GetNumberOfItems(&numItems) != S_OK || numItems != 1)
|
||||
return -1;
|
||||
UString ext(wrappedExt);
|
||||
if (ext.IsPrefixedBy(L"."))
|
||||
ext.DeleteFrontal(1);
|
||||
|
||||
const int dotPos = arc.DefaultName.ReverseFind_Dot();
|
||||
if (dotPos < 0)
|
||||
return -1;
|
||||
if (!ext.IsEqualTo_NoCase(arc.DefaultName.Ptr((unsigned)(dotPos + 1))))
|
||||
return -1;
|
||||
FOR_VECTOR (i, codecs->Formats)
|
||||
if (codecs->Formats[i].FindExtension(ext) >= 0)
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
HRESULT TryChainedExtract(
|
||||
CCodecs *codecs,
|
||||
const CArchiveLink &arcLink,
|
||||
UInt64 packSize,
|
||||
UInt64 completedBeforeArc,
|
||||
bool multi,
|
||||
const NWildcard::CCensorNode &wildcardCensor,
|
||||
const CExtractOptions &options,
|
||||
bool calcCrc,
|
||||
IExtractCallbackUI *callback,
|
||||
IFolderArchiveExtractCallback *callbackFAE,
|
||||
CArchiveExtractCallback *ecs,
|
||||
UString &errorMessage)
|
||||
{
|
||||
const CArc &arc = arcLink.Arcs.Back();
|
||||
const int innerFormatIndex = FindChainedFormatIndex(codecs, arc, options);
|
||||
if (innerFormatIndex < 0)
|
||||
return S_FALSE;
|
||||
|
||||
CStreamBinder binder;
|
||||
RINOK(binder.Create_ReInit())
|
||||
|
||||
CMyComPtr<ISequentialInStream> binderInStream;
|
||||
CMyComPtr<ISequentialOutStream> binderOutStream;
|
||||
binder.CreateStreams2(binderInStream, binderOutStream);
|
||||
|
||||
CMyComPtr2_Create<IArchiveExtractCallback, CChainedStreamExtractCallback> outerExtractCallback;
|
||||
outerExtractCallback->Init(callbackFAE, binderOutStream, multi, completedBeforeArc);
|
||||
binderOutStream.Release();
|
||||
|
||||
CChainedStreamExtractThread outerExtractThread;
|
||||
outerExtractThread.Arc = &arc;
|
||||
outerExtractThread.Callback = outerExtractCallback;
|
||||
RINOK(HRESULT_FROM_WIN32(outerExtractThread.Create()))
|
||||
RINOK(HRESULT_FROM_WIN32(outerExtractThread.Start()))
|
||||
|
||||
HRESULT result = S_OK;
|
||||
|
||||
{
|
||||
CArchiveLink innerArcLink;
|
||||
CObjectVector<COpenType> innerTypes;
|
||||
COpenType innerType;
|
||||
innerType.FormatIndex = innerFormatIndex;
|
||||
innerTypes.Add(innerType);
|
||||
CIntVector excludedFormats;
|
||||
|
||||
COpenOptions op;
|
||||
#ifndef Z7_SFX
|
||||
op.props = &options.Properties;
|
||||
#endif
|
||||
op.codecs = codecs;
|
||||
op.types = &innerTypes;
|
||||
op.excludedFormats = &excludedFormats;
|
||||
op.seqStream = binderInStream;
|
||||
op.filePath = arc.DefaultName;
|
||||
|
||||
result = innerArcLink.Open(op);
|
||||
if (result == S_OK)
|
||||
{
|
||||
UInt64 innerProcessed = 0;
|
||||
ecs->DisableProgress();
|
||||
result = DecompressArchive(
|
||||
codecs,
|
||||
innerArcLink,
|
||||
packSize,
|
||||
wildcardCensor,
|
||||
options,
|
||||
calcCrc,
|
||||
callback,
|
||||
callbackFAE,
|
||||
ecs,
|
||||
errorMessage,
|
||||
innerProcessed,
|
||||
true);
|
||||
}
|
||||
innerArcLink.Release();
|
||||
}
|
||||
|
||||
if (result == S_OK)
|
||||
{
|
||||
const HRESULT drainResult = DrainChainedStream(binderInStream);
|
||||
if (drainResult != S_OK)
|
||||
result = drainResult;
|
||||
}
|
||||
|
||||
binderInStream.Release();
|
||||
|
||||
RINOK(HRESULT_FROM_WIN32(outerExtractThread.WaitExecuteFinish()))
|
||||
|
||||
const HRESULT outerResult = outerExtractThread.Result;
|
||||
|
||||
if (outerResult != S_OK && outerResult != k_My_HRESULT_WritingWasCut)
|
||||
return outerResult;
|
||||
if (result != S_OK)
|
||||
return result;
|
||||
|
||||
return CheckOuterStreamResult(outerExtractCallback->OperationResult, errorMessage);
|
||||
}
|
||||
22
CPP/7zip/UI/Common/ChainedExtract.h
Normal file
22
CPP/7zip/UI/Common/ChainedExtract.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// ChainedExtract.h
|
||||
|
||||
#ifndef ZIP7_INC_CHAINED_EXTRACT_H
|
||||
#define ZIP7_INC_CHAINED_EXTRACT_H
|
||||
|
||||
#include "Extract.h"
|
||||
|
||||
HRESULT TryChainedExtract(
|
||||
CCodecs *codecs,
|
||||
const CArchiveLink &arcLink,
|
||||
UInt64 packSize,
|
||||
UInt64 completedBeforeArc,
|
||||
bool multi,
|
||||
const NWildcard::CCensorNode &wildcardCensor,
|
||||
const CExtractOptions &options,
|
||||
bool calcCrc,
|
||||
IExtractCallbackUI *callback,
|
||||
IFolderArchiveExtractCallback *callbackFAE,
|
||||
CArchiveExtractCallback *ecs,
|
||||
UString &errorMessage);
|
||||
|
||||
#endif
|
||||
|
|
@ -44,6 +44,7 @@ using namespace NWindows;
|
|||
#define kArcIncludeSwitches " -an -ai" ISWITCH_NO_WILDCARD_POSTFIX
|
||||
#define kHashIncludeSwitches kIncludeSwitch
|
||||
#define kStopSwitchParsing " --"
|
||||
#define kChainedExtractSwitch " -sce"
|
||||
|
||||
extern HWND g_HWND;
|
||||
|
||||
|
|
@ -252,7 +253,7 @@ static void ExtractGroupCommand(const UStringVector &arcPaths, UString ¶ms,
|
|||
ErrorMessageHRESULT(result);
|
||||
}
|
||||
|
||||
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup, UInt32 writeZone)
|
||||
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup, UInt32 writeZone, bool enableChainedExtract)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
UString params ('x');
|
||||
|
|
@ -268,6 +269,8 @@ void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bo
|
|||
params += " -snz";
|
||||
params.Add_UInt32(writeZone);
|
||||
}
|
||||
if (enableChainedExtract)
|
||||
params += kChainedExtractSwitch;
|
||||
if (showDialog)
|
||||
params += kShowDialogSwitch;
|
||||
ExtractGroupCommand(arcPaths, params, false);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ HRESULT CompressFiles(
|
|||
const UStringVector &names,
|
||||
bool email, bool showDialog, bool waitFinish);
|
||||
|
||||
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup, UInt32 writeZone);
|
||||
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup, UInt32 writeZone, bool enableChainedExtract);
|
||||
void TestArchives(const UStringVector &arcPaths, bool hashMode = false);
|
||||
|
||||
void CalcChecksum(const UStringVector &paths,
|
||||
|
|
|
|||
|
|
@ -224,11 +224,12 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths,
|
|||
}
|
||||
|
||||
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder,
|
||||
bool showDialog, bool elimDup, UInt32 writeZone)
|
||||
bool showDialog, bool elimDup, UInt32 writeZone, bool enableChainedExtract)
|
||||
{
|
||||
CExtractOptions eo;
|
||||
eo.OutputDir = us2fs(outFolder);
|
||||
eo.TestMode = false;
|
||||
eo.EnableChainedExtract = enableChainedExtract;
|
||||
eo.ElimDup.Val = elimDup;
|
||||
eo.ElimDup.Def = elimDup;
|
||||
if (writeZone != (UInt32)(Int32)-1)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "../Common/ExtractingFilePath.h"
|
||||
#include "../Common/HashCalc.h"
|
||||
|
||||
#include "ChainedExtract.h"
|
||||
#include "Extract.h"
|
||||
#include "SetProperties.h"
|
||||
|
||||
|
|
@ -33,7 +34,7 @@ static void SetErrorMessage(const char *message,
|
|||
}
|
||||
|
||||
|
||||
static HRESULT DecompressArchive(
|
||||
HRESULT DecompressArchive(
|
||||
CCodecs *codecs,
|
||||
const CArchiveLink &arcLink,
|
||||
UInt64 packSize,
|
||||
|
|
@ -44,12 +45,14 @@ static HRESULT DecompressArchive(
|
|||
IFolderArchiveExtractCallback *callbackFAE,
|
||||
CArchiveExtractCallback *ecs,
|
||||
UString &errorMessage,
|
||||
UInt64 &stdInProcessed)
|
||||
UInt64 &stdInProcessed,
|
||||
bool chainedMode)
|
||||
{
|
||||
const CArc &arc = arcLink.Arcs.Back();
|
||||
stdInProcessed = 0;
|
||||
IInArchive *archive = arc.Archive;
|
||||
CRecordVector<UInt32> realIndices;
|
||||
const bool singlePassMode = (options.StdInMode || chainedMode);
|
||||
|
||||
UStringVector removePathParts;
|
||||
|
||||
|
|
@ -90,7 +93,7 @@ static HRESULT DecompressArchive(
|
|||
|
||||
const bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();
|
||||
|
||||
if (!options.StdInMode)
|
||||
if (!singlePassMode)
|
||||
{
|
||||
UInt32 numItems;
|
||||
RINOK(archive->GetNumberOfItems(&numItems))
|
||||
|
|
@ -163,7 +166,7 @@ static HRESULT DecompressArchive(
|
|||
}
|
||||
}
|
||||
|
||||
if (elimIsPossible)
|
||||
if (elimIsPossible && !singlePassMode)
|
||||
{
|
||||
removePathParts.Add(elimPrefix);
|
||||
// outDir = outDirReduced;
|
||||
|
|
@ -191,7 +194,7 @@ static HRESULT DecompressArchive(
|
|||
|
||||
ecs->Init(
|
||||
options.NtOptions,
|
||||
options.StdInMode ? &wildcardCensor : NULL,
|
||||
singlePassMode ? &wildcardCensor : NULL,
|
||||
&arc,
|
||||
callbackFAE,
|
||||
options.StdOutMode, options.TestMode,
|
||||
|
|
@ -199,12 +202,12 @@ static HRESULT DecompressArchive(
|
|||
removePathParts, false,
|
||||
packSize);
|
||||
|
||||
ecs->Is_elimPrefix_Mode = elimIsPossible;
|
||||
ecs->Is_elimPrefix_Mode = (elimIsPossible && !singlePassMode);
|
||||
|
||||
|
||||
#ifdef SUPPORT_LINKS
|
||||
|
||||
if (!options.StdInMode &&
|
||||
if (!singlePassMode &&
|
||||
!options.TestMode &&
|
||||
options.NtOptions.HardLinks.Val)
|
||||
{
|
||||
|
|
@ -219,12 +222,15 @@ static HRESULT DecompressArchive(
|
|||
|
||||
CArchiveExtractCallback_Closer ecsCloser(ecs);
|
||||
|
||||
if (options.StdInMode)
|
||||
if (singlePassMode)
|
||||
{
|
||||
result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs);
|
||||
NCOM::CPropVariant prop;
|
||||
if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK)
|
||||
ConvertPropVariantToUInt64(prop, stdInProcessed);
|
||||
if (options.StdInMode)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK)
|
||||
ConvertPropVariantToUInt64(prop, stdInProcessed);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -242,6 +248,7 @@ static HRESULT DecompressArchive(
|
|||
return callback->ExtractResult(result);
|
||||
}
|
||||
|
||||
|
||||
/* v9.31: BUG was fixed:
|
||||
Sorted list for file paths was sorted with case insensitive compare function.
|
||||
But FindInSorted function did binary search via case sensitive compare function */
|
||||
|
|
@ -539,15 +546,41 @@ HRESULT Extract(
|
|||
false;
|
||||
#endif
|
||||
|
||||
RINOK(DecompressArchive(
|
||||
codecs,
|
||||
arcLink,
|
||||
fi.Size + arcLink.VolumesSize,
|
||||
wildcardCensor,
|
||||
options,
|
||||
calcCrc,
|
||||
extractCallback, faeCallback, ecs,
|
||||
errorMessage, packProcessed))
|
||||
HRESULT chainRes = S_FALSE;
|
||||
|
||||
chainRes = TryChainedExtract(
|
||||
codecs,
|
||||
arcLink,
|
||||
fi.Size + arcLink.VolumesSize,
|
||||
totalPackProcessed,
|
||||
multi,
|
||||
wildcardCensor,
|
||||
options,
|
||||
calcCrc,
|
||||
extractCallback,
|
||||
faeCallback,
|
||||
ecs,
|
||||
errorMessage);
|
||||
|
||||
if (chainRes != S_FALSE)
|
||||
{
|
||||
RINOK(chainRes)
|
||||
packProcessed = fi.Size + arcLink.VolumesSize;
|
||||
}
|
||||
else
|
||||
RINOK(DecompressArchive(
|
||||
codecs,
|
||||
arcLink,
|
||||
fi.Size + arcLink.VolumesSize,
|
||||
wildcardCensor,
|
||||
options,
|
||||
calcCrc,
|
||||
extractCallback,
|
||||
faeCallback,
|
||||
ecs,
|
||||
errorMessage,
|
||||
packProcessed,
|
||||
false))
|
||||
|
||||
if (!options.StdInMode)
|
||||
packProcessed = fi.Size + arcLink.VolumesSize;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
struct CExtractOptionsBase
|
||||
{
|
||||
CBoolPair ElimDup;
|
||||
bool EnableChainedExtract;
|
||||
|
||||
bool ExcludeDirItems;
|
||||
bool ExcludeFileItems;
|
||||
|
|
@ -33,6 +34,7 @@ struct CExtractOptionsBase
|
|||
UString HashDir;
|
||||
|
||||
CExtractOptionsBase():
|
||||
EnableChainedExtract(false),
|
||||
ExcludeDirItems(false),
|
||||
ExcludeFileItems(false),
|
||||
PathMode_Force(false),
|
||||
|
|
@ -87,6 +89,20 @@ struct CDecompressStat
|
|||
}
|
||||
};
|
||||
|
||||
HRESULT DecompressArchive(
|
||||
CCodecs *codecs,
|
||||
const CArchiveLink &arcLink,
|
||||
UInt64 packSize,
|
||||
const NWildcard::CCensorNode &wildcardCensor,
|
||||
const CExtractOptions &options,
|
||||
bool calcCrc,
|
||||
IExtractCallbackUI *callback,
|
||||
IFolderArchiveExtractCallback *callbackFAE,
|
||||
CArchiveExtractCallback *ecs,
|
||||
UString &errorMessage,
|
||||
UInt64 &stdInProcessed,
|
||||
bool chainedMode);
|
||||
|
||||
HRESULT Extract(
|
||||
// DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CCodecs *codecs,
|
||||
|
|
|
|||
|
|
@ -184,6 +184,16 @@ struct CArcInfoEx
|
|||
return UString();
|
||||
return Exts[0].Ext;
|
||||
}
|
||||
|
||||
UString GetWrappedExt() const
|
||||
{
|
||||
if (Flags_KeepName())
|
||||
FOR_VECTOR (i, Exts)
|
||||
if (!Exts[i].AddExt.IsEmpty())
|
||||
return Exts[i].AddExt;
|
||||
return UString();
|
||||
}
|
||||
|
||||
int FindExtension(const UString &ext) const;
|
||||
|
||||
bool Is_7z() const { return Name.IsEqualTo_Ascii_NoCase("7z"); }
|
||||
|
|
|
|||
|
|
@ -3094,11 +3094,10 @@ HRESULT CArc::OpenStreamOrFile(COpenOptions &op)
|
|||
#endif
|
||||
op.seqStream = seqStream;
|
||||
}
|
||||
else if (!op.stream)
|
||||
else if (!op.stream && !op.seqStream)
|
||||
{
|
||||
fileStreamSpec = new CInFileStream;
|
||||
fileStream = fileStreamSpec;
|
||||
Path = filePath;
|
||||
if (!fileStreamSpec->Open(us2fs(Path)))
|
||||
return GetLastError_noZero_HRESULT();
|
||||
op.stream = fileStream;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ UI_COMMON_OBJS = \
|
|||
$O\Bench.obj \
|
||||
$O\DefaultName.obj \
|
||||
$O\EnumDirItems.obj \
|
||||
$O\ChainedExtract.obj \
|
||||
$O\Extract.obj \
|
||||
$O\ExtractingFilePath.obj \
|
||||
$O\HashCalc.obj \
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ static const char * const kHelpString =
|
|||
" -p{Password} : set Password\n"
|
||||
#endif
|
||||
" -r[-|0] : Recurse subdirectories for name search\n"
|
||||
" -sce : chained extract archives with tar wrapper in a single operation\n"
|
||||
" -sa{a|e|s} : set Archive name mode\n"
|
||||
" -scc{UTF-8|WIN|DOS} : set charset for console input/output\n"
|
||||
" -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files\n"
|
||||
|
|
|
|||
|
|
@ -45,9 +45,11 @@ WIN_OBJS = \
|
|||
$O\MultiOutStream.obj \
|
||||
$O\ProgressUtils.obj \
|
||||
$O\PropId.obj \
|
||||
$O\StreamBinder.obj \
|
||||
$O\StreamObjects.obj \
|
||||
$O\StreamUtils.obj \
|
||||
$O\UniqBlocks.obj \
|
||||
$O\VirtThread.obj \
|
||||
|
||||
AR_COMMON_OBJS = \
|
||||
$O\ItemNameUtils.obj \
|
||||
|
|
|
|||
|
|
@ -444,6 +444,56 @@ static bool IsItArcExt(const UString &ext)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool IsTarCompoundExtension(const UString &ext)
|
||||
{
|
||||
return ext.IsEqualTo_Ascii_NoCase("gz")
|
||||
|| ext.IsEqualTo_Ascii_NoCase("gzip")
|
||||
|| ext.IsEqualTo_Ascii_NoCase("bz2")
|
||||
|| ext.IsEqualTo_Ascii_NoCase("bzip2")
|
||||
|| ext.IsEqualTo_Ascii_NoCase("xz")
|
||||
|| ext.IsEqualTo_Ascii_NoCase("zst")
|
||||
|| ext.IsEqualTo_Ascii_NoCase("zstd")
|
||||
|| ext.IsEqualTo_Ascii_NoCase("z");
|
||||
}
|
||||
|
||||
static bool GetChainedExtractFolderName(const UString &arcName, UString &folderName)
|
||||
{
|
||||
int dotPos = arcName.ReverseFind_Dot();
|
||||
if (dotPos < 0)
|
||||
return false;
|
||||
|
||||
const UString ext = arcName.Ptr(dotPos + 1);
|
||||
UString base = arcName.Left(dotPos);
|
||||
|
||||
if (ext.IsEqualTo_Ascii_NoCase("tgz")
|
||||
|| ext.IsEqualTo_Ascii_NoCase("tpz")
|
||||
|| ext.IsEqualTo_Ascii_NoCase("tbz")
|
||||
|| ext.IsEqualTo_Ascii_NoCase("tbz2")
|
||||
|| ext.IsEqualTo_Ascii_NoCase("txz")
|
||||
|| ext.IsEqualTo_Ascii_NoCase("tzst")
|
||||
|| ext.IsEqualTo_Ascii_NoCase("taz"))
|
||||
{
|
||||
base.TrimRight();
|
||||
folderName = Get_Correct_FsFile_Name(base);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IsTarCompoundExtension(ext))
|
||||
return false;
|
||||
|
||||
dotPos = base.ReverseFind_Dot();
|
||||
if (dotPos < 0)
|
||||
return false;
|
||||
|
||||
if (!StringsAreEqualNoCase_Ascii(base.Ptr((unsigned)(dotPos + 1)), "tar"))
|
||||
return false;
|
||||
|
||||
base.DeleteFrom((unsigned)dotPos);
|
||||
base.TrimRight();
|
||||
folderName = Get_Correct_FsFile_Name(base);
|
||||
return true;
|
||||
}
|
||||
|
||||
UString GetSubFolderNameForExtract(const UString &arcName);
|
||||
UString GetSubFolderNameForExtract(const UString &arcName)
|
||||
{
|
||||
|
|
@ -831,9 +881,14 @@ Z7_COMWF_B CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
|
|||
if (_dropMode)
|
||||
baseFolder = _dropPath;
|
||||
|
||||
UString specFolder ('*');
|
||||
UString specFolderName ('*');
|
||||
if (_fileNames.Size() == 1)
|
||||
specFolder = GetSubFolderNameForExtract(fs2us(fi0.Name));
|
||||
{
|
||||
const UString arcName = fs2us(fi0.Name);
|
||||
if (!GetChainedExtractFolderName(arcName, specFolderName))
|
||||
specFolderName = GetSubFolderNameForExtract(arcName);
|
||||
}
|
||||
UString specFolder = specFolderName;
|
||||
specFolder.Add_PathSepar();
|
||||
|
||||
if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0)
|
||||
|
|
@ -861,7 +916,7 @@ Z7_COMWF_B CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
|
|||
UString s;
|
||||
cmi.Folder = baseFolder + specFolder;
|
||||
AddCommand(kExtractTo, s, cmi);
|
||||
MyFormatNew_ReducedName(s, specFolder);
|
||||
MyFormatNew_ReducedName(s, specFolderName);
|
||||
Set_UserString_in_LastCommand(s);
|
||||
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap);
|
||||
}
|
||||
|
|
@ -1285,7 +1340,8 @@ HRESULT CZipContextMenu::InvokeCommandCommon(const CCommandMapItem &cmi)
|
|||
ExtractArchives(_fileNames, cmi.Folder,
|
||||
(cmdID == kExtract), // showDialog
|
||||
(cmdID == kExtractTo) && _elimDup.Val, // elimDup
|
||||
_writeZone
|
||||
_writeZone,
|
||||
true
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1035,6 +1035,7 @@ void CPanel::ExtractArchives()
|
|||
, true // showDialog
|
||||
, false // elimDup
|
||||
, ci.WriteZone
|
||||
, false // enableChainedExtract
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -282,6 +282,12 @@ static int Main2()
|
|||
}
|
||||
#endif
|
||||
|
||||
if (options.StdInMode)
|
||||
{
|
||||
ArchivePathsSorted.Add(options.ArcName_for_StdInMode);
|
||||
ArchivePathsFullSorted.Add(options.ArcName_for_StdInMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
CDirItemsStat st;
|
||||
HRESULT hresultMain = EnumerateDirItemsAndSort(
|
||||
|
|
|
|||
|
|
@ -693,6 +693,10 @@ SOURCE=..\..\Common\PropId.cpp
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamBinder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamObjects.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
@ -715,6 +719,14 @@ SOURCE=..\..\Common\UniqBlocks.cpp
|
|||
|
||||
SOURCE=..\..\Common\UniqBlocks.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\VirtThread.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\VirtThread.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Compress"
|
||||
|
||||
|
|
|
|||
|
|
@ -76,9 +76,11 @@ WIN_CTRL_OBJS = \
|
|||
$O\MultiOutStream.obj \
|
||||
$O\ProgressUtils.obj \
|
||||
$O\PropId.obj \
|
||||
$O\StreamBinder.obj \
|
||||
$O\StreamObjects.obj \
|
||||
$O\StreamUtils.obj \
|
||||
$O\UniqBlocks.obj \
|
||||
$O\VirtThread.obj \
|
||||
|
||||
UI_COMMON_OBJS = \
|
||||
$O\ArchiveCommandLine.obj \
|
||||
|
|
@ -87,6 +89,7 @@ UI_COMMON_OBJS = \
|
|||
$O\Bench.obj \
|
||||
$O\DefaultName.obj \
|
||||
$O\EnumDirItems.obj \
|
||||
$O\ChainedExtract.obj \
|
||||
$O\Extract.obj \
|
||||
$O\ExtractingFilePath.obj \
|
||||
$O\HashCalc.obj \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue