1*f6dc9357SAndroid Build Coastguard Worker // Extract.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringConvert.h"
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileDir.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileName.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/ErrorMsg.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariant.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariantConv.h"
12*f6dc9357SAndroid Build Coastguard Worker
13*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ExtractingFilePath.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../Common/HashCalc.h"
15*f6dc9357SAndroid Build Coastguard Worker
16*f6dc9357SAndroid Build Coastguard Worker #include "Extract.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "SetProperties.h"
18*f6dc9357SAndroid Build Coastguard Worker
19*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
20*f6dc9357SAndroid Build Coastguard Worker using namespace NFile;
21*f6dc9357SAndroid Build Coastguard Worker using namespace NDir;
22*f6dc9357SAndroid Build Coastguard Worker
23*f6dc9357SAndroid Build Coastguard Worker
SetErrorMessage(const char * message,const FString & path,HRESULT errorCode,UString & s)24*f6dc9357SAndroid Build Coastguard Worker static void SetErrorMessage(const char *message,
25*f6dc9357SAndroid Build Coastguard Worker const FString &path, HRESULT errorCode,
26*f6dc9357SAndroid Build Coastguard Worker UString &s)
27*f6dc9357SAndroid Build Coastguard Worker {
28*f6dc9357SAndroid Build Coastguard Worker s = message;
29*f6dc9357SAndroid Build Coastguard Worker s += " : ";
30*f6dc9357SAndroid Build Coastguard Worker s += NError::MyFormatMessage(errorCode);
31*f6dc9357SAndroid Build Coastguard Worker s += " : ";
32*f6dc9357SAndroid Build Coastguard Worker s += fs2us(path);
33*f6dc9357SAndroid Build Coastguard Worker }
34*f6dc9357SAndroid Build Coastguard Worker
35*f6dc9357SAndroid Build Coastguard Worker
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)36*f6dc9357SAndroid Build Coastguard Worker static HRESULT DecompressArchive(
37*f6dc9357SAndroid Build Coastguard Worker CCodecs *codecs,
38*f6dc9357SAndroid Build Coastguard Worker const CArchiveLink &arcLink,
39*f6dc9357SAndroid Build Coastguard Worker UInt64 packSize,
40*f6dc9357SAndroid Build Coastguard Worker const NWildcard::CCensorNode &wildcardCensor,
41*f6dc9357SAndroid Build Coastguard Worker const CExtractOptions &options,
42*f6dc9357SAndroid Build Coastguard Worker bool calcCrc,
43*f6dc9357SAndroid Build Coastguard Worker IExtractCallbackUI *callback,
44*f6dc9357SAndroid Build Coastguard Worker IFolderArchiveExtractCallback *callbackFAE,
45*f6dc9357SAndroid Build Coastguard Worker CArchiveExtractCallback *ecs,
46*f6dc9357SAndroid Build Coastguard Worker UString &errorMessage,
47*f6dc9357SAndroid Build Coastguard Worker UInt64 &stdInProcessed)
48*f6dc9357SAndroid Build Coastguard Worker {
49*f6dc9357SAndroid Build Coastguard Worker const CArc &arc = arcLink.Arcs.Back();
50*f6dc9357SAndroid Build Coastguard Worker stdInProcessed = 0;
51*f6dc9357SAndroid Build Coastguard Worker IInArchive *archive = arc.Archive;
52*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt32> realIndices;
53*f6dc9357SAndroid Build Coastguard Worker
54*f6dc9357SAndroid Build Coastguard Worker UStringVector removePathParts;
55*f6dc9357SAndroid Build Coastguard Worker
56*f6dc9357SAndroid Build Coastguard Worker FString outDir = options.OutputDir;
57*f6dc9357SAndroid Build Coastguard Worker UString replaceName = arc.DefaultName;
58*f6dc9357SAndroid Build Coastguard Worker
59*f6dc9357SAndroid Build Coastguard Worker if (arcLink.Arcs.Size() > 1)
60*f6dc9357SAndroid Build Coastguard Worker {
61*f6dc9357SAndroid Build Coastguard Worker // Most "pe" archives have same name of archive subfile "[0]" or ".rsrc_1".
62*f6dc9357SAndroid Build Coastguard Worker // So it extracts different archives to one folder.
63*f6dc9357SAndroid Build Coastguard Worker // We will use top level archive name
64*f6dc9357SAndroid Build Coastguard Worker const CArc &arc0 = arcLink.Arcs[0];
65*f6dc9357SAndroid Build Coastguard Worker if (arc0.FormatIndex >= 0 && StringsAreEqualNoCase_Ascii(codecs->Formats[(unsigned)arc0.FormatIndex].Name, "pe"))
66*f6dc9357SAndroid Build Coastguard Worker replaceName = arc0.DefaultName;
67*f6dc9357SAndroid Build Coastguard Worker }
68*f6dc9357SAndroid Build Coastguard Worker
69*f6dc9357SAndroid Build Coastguard Worker outDir.Replace(FString("*"), us2fs(Get_Correct_FsFile_Name(replaceName)));
70*f6dc9357SAndroid Build Coastguard Worker
71*f6dc9357SAndroid Build Coastguard Worker bool elimIsPossible = false;
72*f6dc9357SAndroid Build Coastguard Worker UString elimPrefix; // only pure name without dir delimiter
73*f6dc9357SAndroid Build Coastguard Worker FString outDirReduced = outDir;
74*f6dc9357SAndroid Build Coastguard Worker
75*f6dc9357SAndroid Build Coastguard Worker if (options.ElimDup.Val && options.PathMode != NExtract::NPathMode::kAbsPaths)
76*f6dc9357SAndroid Build Coastguard Worker {
77*f6dc9357SAndroid Build Coastguard Worker UString dirPrefix;
78*f6dc9357SAndroid Build Coastguard Worker SplitPathToParts_Smart(fs2us(outDir), dirPrefix, elimPrefix);
79*f6dc9357SAndroid Build Coastguard Worker if (!elimPrefix.IsEmpty())
80*f6dc9357SAndroid Build Coastguard Worker {
81*f6dc9357SAndroid Build Coastguard Worker if (IsPathSepar(elimPrefix.Back()))
82*f6dc9357SAndroid Build Coastguard Worker elimPrefix.DeleteBack();
83*f6dc9357SAndroid Build Coastguard Worker if (!elimPrefix.IsEmpty())
84*f6dc9357SAndroid Build Coastguard Worker {
85*f6dc9357SAndroid Build Coastguard Worker outDirReduced = us2fs(dirPrefix);
86*f6dc9357SAndroid Build Coastguard Worker elimIsPossible = true;
87*f6dc9357SAndroid Build Coastguard Worker }
88*f6dc9357SAndroid Build Coastguard Worker }
89*f6dc9357SAndroid Build Coastguard Worker }
90*f6dc9357SAndroid Build Coastguard Worker
91*f6dc9357SAndroid Build Coastguard Worker const bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();
92*f6dc9357SAndroid Build Coastguard Worker
93*f6dc9357SAndroid Build Coastguard Worker if (!options.StdInMode)
94*f6dc9357SAndroid Build Coastguard Worker {
95*f6dc9357SAndroid Build Coastguard Worker UInt32 numItems;
96*f6dc9357SAndroid Build Coastguard Worker RINOK(archive->GetNumberOfItems(&numItems))
97*f6dc9357SAndroid Build Coastguard Worker
98*f6dc9357SAndroid Build Coastguard Worker CReadArcItem item;
99*f6dc9357SAndroid Build Coastguard Worker
100*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numItems; i++)
101*f6dc9357SAndroid Build Coastguard Worker {
102*f6dc9357SAndroid Build Coastguard Worker if (elimIsPossible
103*f6dc9357SAndroid Build Coastguard Worker || !allFilesAreAllowed
104*f6dc9357SAndroid Build Coastguard Worker || options.ExcludeDirItems
105*f6dc9357SAndroid Build Coastguard Worker || options.ExcludeFileItems)
106*f6dc9357SAndroid Build Coastguard Worker {
107*f6dc9357SAndroid Build Coastguard Worker RINOK(arc.GetItem(i, item))
108*f6dc9357SAndroid Build Coastguard Worker if (item.IsDir ? options.ExcludeDirItems : options.ExcludeFileItems)
109*f6dc9357SAndroid Build Coastguard Worker continue;
110*f6dc9357SAndroid Build Coastguard Worker }
111*f6dc9357SAndroid Build Coastguard Worker else
112*f6dc9357SAndroid Build Coastguard Worker {
113*f6dc9357SAndroid Build Coastguard Worker #ifdef SUPPORT_ALT_STREAMS
114*f6dc9357SAndroid Build Coastguard Worker item.IsAltStream = false;
115*f6dc9357SAndroid Build Coastguard Worker if (!options.NtOptions.AltStreams.Val && arc.Ask_AltStream)
116*f6dc9357SAndroid Build Coastguard Worker {
117*f6dc9357SAndroid Build Coastguard Worker RINOK(Archive_IsItem_AltStream(arc.Archive, i, item.IsAltStream))
118*f6dc9357SAndroid Build Coastguard Worker }
119*f6dc9357SAndroid Build Coastguard Worker #endif
120*f6dc9357SAndroid Build Coastguard Worker }
121*f6dc9357SAndroid Build Coastguard Worker
122*f6dc9357SAndroid Build Coastguard Worker #ifdef SUPPORT_ALT_STREAMS
123*f6dc9357SAndroid Build Coastguard Worker if (!options.NtOptions.AltStreams.Val && item.IsAltStream)
124*f6dc9357SAndroid Build Coastguard Worker continue;
125*f6dc9357SAndroid Build Coastguard Worker #endif
126*f6dc9357SAndroid Build Coastguard Worker
127*f6dc9357SAndroid Build Coastguard Worker if (elimIsPossible)
128*f6dc9357SAndroid Build Coastguard Worker {
129*f6dc9357SAndroid Build Coastguard Worker const UString &s =
130*f6dc9357SAndroid Build Coastguard Worker #ifdef SUPPORT_ALT_STREAMS
131*f6dc9357SAndroid Build Coastguard Worker item.MainPath;
132*f6dc9357SAndroid Build Coastguard Worker #else
133*f6dc9357SAndroid Build Coastguard Worker item.Path;
134*f6dc9357SAndroid Build Coastguard Worker #endif
135*f6dc9357SAndroid Build Coastguard Worker if (!IsPath1PrefixedByPath2(s, elimPrefix))
136*f6dc9357SAndroid Build Coastguard Worker elimIsPossible = false;
137*f6dc9357SAndroid Build Coastguard Worker else
138*f6dc9357SAndroid Build Coastguard Worker {
139*f6dc9357SAndroid Build Coastguard Worker wchar_t c = s[elimPrefix.Len()];
140*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
141*f6dc9357SAndroid Build Coastguard Worker {
142*f6dc9357SAndroid Build Coastguard Worker if (!item.MainIsDir)
143*f6dc9357SAndroid Build Coastguard Worker elimIsPossible = false;
144*f6dc9357SAndroid Build Coastguard Worker }
145*f6dc9357SAndroid Build Coastguard Worker else if (!IsPathSepar(c))
146*f6dc9357SAndroid Build Coastguard Worker elimIsPossible = false;
147*f6dc9357SAndroid Build Coastguard Worker }
148*f6dc9357SAndroid Build Coastguard Worker }
149*f6dc9357SAndroid Build Coastguard Worker
150*f6dc9357SAndroid Build Coastguard Worker if (!allFilesAreAllowed)
151*f6dc9357SAndroid Build Coastguard Worker {
152*f6dc9357SAndroid Build Coastguard Worker if (!CensorNode_CheckPath(wildcardCensor, item))
153*f6dc9357SAndroid Build Coastguard Worker continue;
154*f6dc9357SAndroid Build Coastguard Worker }
155*f6dc9357SAndroid Build Coastguard Worker
156*f6dc9357SAndroid Build Coastguard Worker realIndices.Add(i);
157*f6dc9357SAndroid Build Coastguard Worker }
158*f6dc9357SAndroid Build Coastguard Worker
159*f6dc9357SAndroid Build Coastguard Worker if (realIndices.Size() == 0)
160*f6dc9357SAndroid Build Coastguard Worker {
161*f6dc9357SAndroid Build Coastguard Worker callback->ThereAreNoFiles();
162*f6dc9357SAndroid Build Coastguard Worker return callback->ExtractResult(S_OK);
163*f6dc9357SAndroid Build Coastguard Worker }
164*f6dc9357SAndroid Build Coastguard Worker }
165*f6dc9357SAndroid Build Coastguard Worker
166*f6dc9357SAndroid Build Coastguard Worker if (elimIsPossible)
167*f6dc9357SAndroid Build Coastguard Worker {
168*f6dc9357SAndroid Build Coastguard Worker removePathParts.Add(elimPrefix);
169*f6dc9357SAndroid Build Coastguard Worker // outDir = outDirReduced;
170*f6dc9357SAndroid Build Coastguard Worker }
171*f6dc9357SAndroid Build Coastguard Worker
172*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
173*f6dc9357SAndroid Build Coastguard Worker // GetCorrectFullFsPath doesn't like "..".
174*f6dc9357SAndroid Build Coastguard Worker // outDir.TrimRight();
175*f6dc9357SAndroid Build Coastguard Worker // outDir = GetCorrectFullFsPath(outDir);
176*f6dc9357SAndroid Build Coastguard Worker #endif
177*f6dc9357SAndroid Build Coastguard Worker
178*f6dc9357SAndroid Build Coastguard Worker if (outDir.IsEmpty())
179*f6dc9357SAndroid Build Coastguard Worker outDir = "." STRING_PATH_SEPARATOR;
180*f6dc9357SAndroid Build Coastguard Worker /*
181*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
182*f6dc9357SAndroid Build Coastguard Worker else if (NName::IsAltPathPrefix(outDir)) {}
183*f6dc9357SAndroid Build Coastguard Worker #endif
184*f6dc9357SAndroid Build Coastguard Worker */
185*f6dc9357SAndroid Build Coastguard Worker else if (!CreateComplexDir(outDir))
186*f6dc9357SAndroid Build Coastguard Worker {
187*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = GetLastError_noZero_HRESULT();
188*f6dc9357SAndroid Build Coastguard Worker SetErrorMessage("Cannot create output directory", outDir, res, errorMessage);
189*f6dc9357SAndroid Build Coastguard Worker return res;
190*f6dc9357SAndroid Build Coastguard Worker }
191*f6dc9357SAndroid Build Coastguard Worker
192*f6dc9357SAndroid Build Coastguard Worker ecs->Init(
193*f6dc9357SAndroid Build Coastguard Worker options.NtOptions,
194*f6dc9357SAndroid Build Coastguard Worker options.StdInMode ? &wildcardCensor : NULL,
195*f6dc9357SAndroid Build Coastguard Worker &arc,
196*f6dc9357SAndroid Build Coastguard Worker callbackFAE,
197*f6dc9357SAndroid Build Coastguard Worker options.StdOutMode, options.TestMode,
198*f6dc9357SAndroid Build Coastguard Worker outDir,
199*f6dc9357SAndroid Build Coastguard Worker removePathParts, false,
200*f6dc9357SAndroid Build Coastguard Worker packSize);
201*f6dc9357SAndroid Build Coastguard Worker
202*f6dc9357SAndroid Build Coastguard Worker ecs->Is_elimPrefix_Mode = elimIsPossible;
203*f6dc9357SAndroid Build Coastguard Worker
204*f6dc9357SAndroid Build Coastguard Worker
205*f6dc9357SAndroid Build Coastguard Worker #ifdef SUPPORT_LINKS
206*f6dc9357SAndroid Build Coastguard Worker
207*f6dc9357SAndroid Build Coastguard Worker if (!options.StdInMode &&
208*f6dc9357SAndroid Build Coastguard Worker !options.TestMode &&
209*f6dc9357SAndroid Build Coastguard Worker options.NtOptions.HardLinks.Val)
210*f6dc9357SAndroid Build Coastguard Worker {
211*f6dc9357SAndroid Build Coastguard Worker RINOK(ecs->PrepareHardLinks(&realIndices))
212*f6dc9357SAndroid Build Coastguard Worker }
213*f6dc9357SAndroid Build Coastguard Worker
214*f6dc9357SAndroid Build Coastguard Worker #endif
215*f6dc9357SAndroid Build Coastguard Worker
216*f6dc9357SAndroid Build Coastguard Worker
217*f6dc9357SAndroid Build Coastguard Worker HRESULT result;
218*f6dc9357SAndroid Build Coastguard Worker const Int32 testMode = (options.TestMode && !calcCrc) ? 1: 0;
219*f6dc9357SAndroid Build Coastguard Worker
220*f6dc9357SAndroid Build Coastguard Worker CArchiveExtractCallback_Closer ecsCloser(ecs);
221*f6dc9357SAndroid Build Coastguard Worker
222*f6dc9357SAndroid Build Coastguard Worker if (options.StdInMode)
223*f6dc9357SAndroid Build Coastguard Worker {
224*f6dc9357SAndroid Build Coastguard Worker result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs);
225*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
226*f6dc9357SAndroid Build Coastguard Worker if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK)
227*f6dc9357SAndroid Build Coastguard Worker ConvertPropVariantToUInt64(prop, stdInProcessed);
228*f6dc9357SAndroid Build Coastguard Worker }
229*f6dc9357SAndroid Build Coastguard Worker else
230*f6dc9357SAndroid Build Coastguard Worker {
231*f6dc9357SAndroid Build Coastguard Worker // v23.02: we reset completed value that could be set by Open() operation
232*f6dc9357SAndroid Build Coastguard Worker IArchiveExtractCallback *aec = ecs;
233*f6dc9357SAndroid Build Coastguard Worker const UInt64 val = 0;
234*f6dc9357SAndroid Build Coastguard Worker RINOK(aec->SetCompleted(&val))
235*f6dc9357SAndroid Build Coastguard Worker result = archive->Extract(realIndices.ConstData(), realIndices.Size(), testMode, aec);
236*f6dc9357SAndroid Build Coastguard Worker }
237*f6dc9357SAndroid Build Coastguard Worker
238*f6dc9357SAndroid Build Coastguard Worker const HRESULT res2 = ecsCloser.Close();
239*f6dc9357SAndroid Build Coastguard Worker if (result == S_OK)
240*f6dc9357SAndroid Build Coastguard Worker result = res2;
241*f6dc9357SAndroid Build Coastguard Worker
242*f6dc9357SAndroid Build Coastguard Worker return callback->ExtractResult(result);
243*f6dc9357SAndroid Build Coastguard Worker }
244*f6dc9357SAndroid Build Coastguard Worker
245*f6dc9357SAndroid Build Coastguard Worker /* v9.31: BUG was fixed:
246*f6dc9357SAndroid Build Coastguard Worker Sorted list for file paths was sorted with case insensitive compare function.
247*f6dc9357SAndroid Build Coastguard Worker But FindInSorted function did binary search via case sensitive compare function */
248*f6dc9357SAndroid Build Coastguard Worker
249*f6dc9357SAndroid Build Coastguard Worker int Find_FileName_InSortedVector(const UStringVector &fileNames, const UString &name);
Find_FileName_InSortedVector(const UStringVector & fileNames,const UString & name)250*f6dc9357SAndroid Build Coastguard Worker int Find_FileName_InSortedVector(const UStringVector &fileNames, const UString &name)
251*f6dc9357SAndroid Build Coastguard Worker {
252*f6dc9357SAndroid Build Coastguard Worker unsigned left = 0, right = fileNames.Size();
253*f6dc9357SAndroid Build Coastguard Worker while (left != right)
254*f6dc9357SAndroid Build Coastguard Worker {
255*f6dc9357SAndroid Build Coastguard Worker const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
256*f6dc9357SAndroid Build Coastguard Worker const UString &midVal = fileNames[mid];
257*f6dc9357SAndroid Build Coastguard Worker const int comp = CompareFileNames(name, midVal);
258*f6dc9357SAndroid Build Coastguard Worker if (comp == 0)
259*f6dc9357SAndroid Build Coastguard Worker return (int)mid;
260*f6dc9357SAndroid Build Coastguard Worker if (comp < 0)
261*f6dc9357SAndroid Build Coastguard Worker right = mid;
262*f6dc9357SAndroid Build Coastguard Worker else
263*f6dc9357SAndroid Build Coastguard Worker left = mid + 1;
264*f6dc9357SAndroid Build Coastguard Worker }
265*f6dc9357SAndroid Build Coastguard Worker return -1;
266*f6dc9357SAndroid Build Coastguard Worker }
267*f6dc9357SAndroid Build Coastguard Worker
268*f6dc9357SAndroid Build Coastguard Worker
269*f6dc9357SAndroid Build Coastguard Worker
Extract(CCodecs * codecs,const CObjectVector<COpenType> & types,const CIntVector & excludedFormats,UStringVector & arcPaths,UStringVector & arcPathsFull,const NWildcard::CCensorNode & wildcardCensor,const CExtractOptions & options,IOpenCallbackUI * openCallback,IExtractCallbackUI * extractCallback,IFolderArchiveExtractCallback * faeCallback,IHashCalc * hash,UString & errorMessage,CDecompressStat & st)270*f6dc9357SAndroid Build Coastguard Worker HRESULT Extract(
271*f6dc9357SAndroid Build Coastguard Worker // DECL_EXTERNAL_CODECS_LOC_VARS
272*f6dc9357SAndroid Build Coastguard Worker CCodecs *codecs,
273*f6dc9357SAndroid Build Coastguard Worker const CObjectVector<COpenType> &types,
274*f6dc9357SAndroid Build Coastguard Worker const CIntVector &excludedFormats,
275*f6dc9357SAndroid Build Coastguard Worker UStringVector &arcPaths, UStringVector &arcPathsFull,
276*f6dc9357SAndroid Build Coastguard Worker const NWildcard::CCensorNode &wildcardCensor,
277*f6dc9357SAndroid Build Coastguard Worker const CExtractOptions &options,
278*f6dc9357SAndroid Build Coastguard Worker IOpenCallbackUI *openCallback,
279*f6dc9357SAndroid Build Coastguard Worker IExtractCallbackUI *extractCallback,
280*f6dc9357SAndroid Build Coastguard Worker IFolderArchiveExtractCallback *faeCallback,
281*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_SFX
282*f6dc9357SAndroid Build Coastguard Worker IHashCalc *hash,
283*f6dc9357SAndroid Build Coastguard Worker #endif
284*f6dc9357SAndroid Build Coastguard Worker UString &errorMessage,
285*f6dc9357SAndroid Build Coastguard Worker CDecompressStat &st)
286*f6dc9357SAndroid Build Coastguard Worker {
287*f6dc9357SAndroid Build Coastguard Worker st.Clear();
288*f6dc9357SAndroid Build Coastguard Worker UInt64 totalPackSize = 0;
289*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt64> arcSizes;
290*f6dc9357SAndroid Build Coastguard Worker
291*f6dc9357SAndroid Build Coastguard Worker unsigned numArcs = options.StdInMode ? 1 : arcPaths.Size();
292*f6dc9357SAndroid Build Coastguard Worker
293*f6dc9357SAndroid Build Coastguard Worker unsigned i;
294*f6dc9357SAndroid Build Coastguard Worker
295*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numArcs; i++)
296*f6dc9357SAndroid Build Coastguard Worker {
297*f6dc9357SAndroid Build Coastguard Worker NFind::CFileInfo fi;
298*f6dc9357SAndroid Build Coastguard Worker fi.Size = 0;
299*f6dc9357SAndroid Build Coastguard Worker if (!options.StdInMode)
300*f6dc9357SAndroid Build Coastguard Worker {
301*f6dc9357SAndroid Build Coastguard Worker const FString arcPath = us2fs(arcPaths[i]);
302*f6dc9357SAndroid Build Coastguard Worker if (!fi.Find_FollowLink(arcPath))
303*f6dc9357SAndroid Build Coastguard Worker {
304*f6dc9357SAndroid Build Coastguard Worker const HRESULT errorCode = GetLastError_noZero_HRESULT();
305*f6dc9357SAndroid Build Coastguard Worker SetErrorMessage("Cannot find archive file", arcPath, errorCode, errorMessage);
306*f6dc9357SAndroid Build Coastguard Worker return errorCode;
307*f6dc9357SAndroid Build Coastguard Worker }
308*f6dc9357SAndroid Build Coastguard Worker if (fi.IsDir())
309*f6dc9357SAndroid Build Coastguard Worker {
310*f6dc9357SAndroid Build Coastguard Worker HRESULT errorCode = E_FAIL;
311*f6dc9357SAndroid Build Coastguard Worker SetErrorMessage("The item is a directory", arcPath, errorCode, errorMessage);
312*f6dc9357SAndroid Build Coastguard Worker return errorCode;
313*f6dc9357SAndroid Build Coastguard Worker }
314*f6dc9357SAndroid Build Coastguard Worker }
315*f6dc9357SAndroid Build Coastguard Worker arcSizes.Add(fi.Size);
316*f6dc9357SAndroid Build Coastguard Worker totalPackSize += fi.Size;
317*f6dc9357SAndroid Build Coastguard Worker }
318*f6dc9357SAndroid Build Coastguard Worker
319*f6dc9357SAndroid Build Coastguard Worker CBoolArr skipArcs(numArcs);
320*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numArcs; i++)
321*f6dc9357SAndroid Build Coastguard Worker skipArcs[i] = false;
322*f6dc9357SAndroid Build Coastguard Worker
323*f6dc9357SAndroid Build Coastguard Worker CArchiveExtractCallback *ecs = new CArchiveExtractCallback;
324*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IArchiveExtractCallback> ec(ecs);
325*f6dc9357SAndroid Build Coastguard Worker
326*f6dc9357SAndroid Build Coastguard Worker const bool multi = (numArcs > 1);
327*f6dc9357SAndroid Build Coastguard Worker
328*f6dc9357SAndroid Build Coastguard Worker ecs->InitForMulti(multi,
329*f6dc9357SAndroid Build Coastguard Worker options.PathMode,
330*f6dc9357SAndroid Build Coastguard Worker options.OverwriteMode,
331*f6dc9357SAndroid Build Coastguard Worker options.ZoneMode,
332*f6dc9357SAndroid Build Coastguard Worker false // keepEmptyDirParts
333*f6dc9357SAndroid Build Coastguard Worker );
334*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_SFX
335*f6dc9357SAndroid Build Coastguard Worker ecs->SetHashMethods(hash);
336*f6dc9357SAndroid Build Coastguard Worker #endif
337*f6dc9357SAndroid Build Coastguard Worker
338*f6dc9357SAndroid Build Coastguard Worker if (multi)
339*f6dc9357SAndroid Build Coastguard Worker {
340*f6dc9357SAndroid Build Coastguard Worker RINOK(faeCallback->SetTotal(totalPackSize))
341*f6dc9357SAndroid Build Coastguard Worker }
342*f6dc9357SAndroid Build Coastguard Worker
343*f6dc9357SAndroid Build Coastguard Worker UInt64 totalPackProcessed = 0;
344*f6dc9357SAndroid Build Coastguard Worker bool thereAreNotOpenArcs = false;
345*f6dc9357SAndroid Build Coastguard Worker
346*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numArcs; i++)
347*f6dc9357SAndroid Build Coastguard Worker {
348*f6dc9357SAndroid Build Coastguard Worker if (skipArcs[i])
349*f6dc9357SAndroid Build Coastguard Worker continue;
350*f6dc9357SAndroid Build Coastguard Worker
351*f6dc9357SAndroid Build Coastguard Worker ecs->InitBeforeNewArchive();
352*f6dc9357SAndroid Build Coastguard Worker
353*f6dc9357SAndroid Build Coastguard Worker const UString &arcPath = arcPaths[i];
354*f6dc9357SAndroid Build Coastguard Worker NFind::CFileInfo fi;
355*f6dc9357SAndroid Build Coastguard Worker if (options.StdInMode)
356*f6dc9357SAndroid Build Coastguard Worker {
357*f6dc9357SAndroid Build Coastguard Worker // do we need ctime and mtime?
358*f6dc9357SAndroid Build Coastguard Worker // fi.ClearBase();
359*f6dc9357SAndroid Build Coastguard Worker // fi.Size = 0; // (UInt64)(Int64)-1;
360*f6dc9357SAndroid Build Coastguard Worker if (!fi.SetAs_StdInFile())
361*f6dc9357SAndroid Build Coastguard Worker return GetLastError_noZero_HRESULT();
362*f6dc9357SAndroid Build Coastguard Worker }
363*f6dc9357SAndroid Build Coastguard Worker else
364*f6dc9357SAndroid Build Coastguard Worker {
365*f6dc9357SAndroid Build Coastguard Worker if (!fi.Find_FollowLink(us2fs(arcPath)) || fi.IsDir())
366*f6dc9357SAndroid Build Coastguard Worker {
367*f6dc9357SAndroid Build Coastguard Worker const HRESULT errorCode = GetLastError_noZero_HRESULT();
368*f6dc9357SAndroid Build Coastguard Worker SetErrorMessage("Cannot find archive file", us2fs(arcPath), errorCode, errorMessage);
369*f6dc9357SAndroid Build Coastguard Worker return errorCode;
370*f6dc9357SAndroid Build Coastguard Worker }
371*f6dc9357SAndroid Build Coastguard Worker }
372*f6dc9357SAndroid Build Coastguard Worker
373*f6dc9357SAndroid Build Coastguard Worker /*
374*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_NO_CRYPTO
375*f6dc9357SAndroid Build Coastguard Worker openCallback->Open_Clear_PasswordWasAsked_Flag();
376*f6dc9357SAndroid Build Coastguard Worker #endif
377*f6dc9357SAndroid Build Coastguard Worker */
378*f6dc9357SAndroid Build Coastguard Worker
379*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->BeforeOpen(arcPath, options.TestMode))
380*f6dc9357SAndroid Build Coastguard Worker CArchiveLink arcLink;
381*f6dc9357SAndroid Build Coastguard Worker
382*f6dc9357SAndroid Build Coastguard Worker CObjectVector<COpenType> types2 = types;
383*f6dc9357SAndroid Build Coastguard Worker /*
384*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_SFX
385*f6dc9357SAndroid Build Coastguard Worker if (types.IsEmpty())
386*f6dc9357SAndroid Build Coastguard Worker {
387*f6dc9357SAndroid Build Coastguard Worker int pos = arcPath.ReverseFind(L'.');
388*f6dc9357SAndroid Build Coastguard Worker if (pos >= 0)
389*f6dc9357SAndroid Build Coastguard Worker {
390*f6dc9357SAndroid Build Coastguard Worker UString s = arcPath.Ptr(pos + 1);
391*f6dc9357SAndroid Build Coastguard Worker int index = codecs->FindFormatForExtension(s);
392*f6dc9357SAndroid Build Coastguard Worker if (index >= 0 && s == L"001")
393*f6dc9357SAndroid Build Coastguard Worker {
394*f6dc9357SAndroid Build Coastguard Worker s = arcPath.Left(pos);
395*f6dc9357SAndroid Build Coastguard Worker pos = s.ReverseFind(L'.');
396*f6dc9357SAndroid Build Coastguard Worker if (pos >= 0)
397*f6dc9357SAndroid Build Coastguard Worker {
398*f6dc9357SAndroid Build Coastguard Worker int index2 = codecs->FindFormatForExtension(s.Ptr(pos + 1));
399*f6dc9357SAndroid Build Coastguard Worker if (index2 >= 0) // && s.CompareNoCase(L"rar") != 0
400*f6dc9357SAndroid Build Coastguard Worker {
401*f6dc9357SAndroid Build Coastguard Worker types2.Add(index2);
402*f6dc9357SAndroid Build Coastguard Worker types2.Add(index);
403*f6dc9357SAndroid Build Coastguard Worker }
404*f6dc9357SAndroid Build Coastguard Worker }
405*f6dc9357SAndroid Build Coastguard Worker }
406*f6dc9357SAndroid Build Coastguard Worker }
407*f6dc9357SAndroid Build Coastguard Worker }
408*f6dc9357SAndroid Build Coastguard Worker #endif
409*f6dc9357SAndroid Build Coastguard Worker */
410*f6dc9357SAndroid Build Coastguard Worker
411*f6dc9357SAndroid Build Coastguard Worker COpenOptions op;
412*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_SFX
413*f6dc9357SAndroid Build Coastguard Worker op.props = &options.Properties;
414*f6dc9357SAndroid Build Coastguard Worker #endif
415*f6dc9357SAndroid Build Coastguard Worker op.codecs = codecs;
416*f6dc9357SAndroid Build Coastguard Worker op.types = &types2;
417*f6dc9357SAndroid Build Coastguard Worker op.excludedFormats = &excludedFormats;
418*f6dc9357SAndroid Build Coastguard Worker op.stdInMode = options.StdInMode;
419*f6dc9357SAndroid Build Coastguard Worker op.stream = NULL;
420*f6dc9357SAndroid Build Coastguard Worker op.filePath = arcPath;
421*f6dc9357SAndroid Build Coastguard Worker
422*f6dc9357SAndroid Build Coastguard Worker HRESULT result = arcLink.Open_Strict(op, openCallback);
423*f6dc9357SAndroid Build Coastguard Worker
424*f6dc9357SAndroid Build Coastguard Worker if (result == E_ABORT)
425*f6dc9357SAndroid Build Coastguard Worker return result;
426*f6dc9357SAndroid Build Coastguard Worker
427*f6dc9357SAndroid Build Coastguard Worker // arcLink.Set_ErrorsText();
428*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->OpenResult(codecs, arcLink, arcPath, result))
429*f6dc9357SAndroid Build Coastguard Worker
430*f6dc9357SAndroid Build Coastguard Worker if (result != S_OK)
431*f6dc9357SAndroid Build Coastguard Worker {
432*f6dc9357SAndroid Build Coastguard Worker thereAreNotOpenArcs = true;
433*f6dc9357SAndroid Build Coastguard Worker if (!options.StdInMode)
434*f6dc9357SAndroid Build Coastguard Worker totalPackProcessed += fi.Size;
435*f6dc9357SAndroid Build Coastguard Worker continue;
436*f6dc9357SAndroid Build Coastguard Worker }
437*f6dc9357SAndroid Build Coastguard Worker
438*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
439*f6dc9357SAndroid Build Coastguard Worker if (options.ZoneMode != NExtract::NZoneIdMode::kNone
440*f6dc9357SAndroid Build Coastguard Worker && !options.StdInMode)
441*f6dc9357SAndroid Build Coastguard Worker {
442*f6dc9357SAndroid Build Coastguard Worker ReadZoneFile_Of_BaseFile(us2fs(arcPath), ecs->ZoneBuf);
443*f6dc9357SAndroid Build Coastguard Worker }
444*f6dc9357SAndroid Build Coastguard Worker #endif
445*f6dc9357SAndroid Build Coastguard Worker
446*f6dc9357SAndroid Build Coastguard Worker
447*f6dc9357SAndroid Build Coastguard Worker if (arcLink.Arcs.Size() != 0)
448*f6dc9357SAndroid Build Coastguard Worker {
449*f6dc9357SAndroid Build Coastguard Worker if (arcLink.GetArc()->IsHashHandler(op))
450*f6dc9357SAndroid Build Coastguard Worker {
451*f6dc9357SAndroid Build Coastguard Worker if (!options.TestMode)
452*f6dc9357SAndroid Build Coastguard Worker {
453*f6dc9357SAndroid Build Coastguard Worker /* real Extracting to files is possible.
454*f6dc9357SAndroid Build Coastguard Worker But user can think that hash archive contains real files.
455*f6dc9357SAndroid Build Coastguard Worker So we block extracting here. */
456*f6dc9357SAndroid Build Coastguard Worker // v23.00 : we don't break process.
457*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->OpenResult(codecs, arcLink, arcPath, E_NOTIMPL))
458*f6dc9357SAndroid Build Coastguard Worker thereAreNotOpenArcs = true;
459*f6dc9357SAndroid Build Coastguard Worker if (!options.StdInMode)
460*f6dc9357SAndroid Build Coastguard Worker totalPackProcessed += fi.Size;
461*f6dc9357SAndroid Build Coastguard Worker continue;
462*f6dc9357SAndroid Build Coastguard Worker // return E_NOTIMPL; // before v23
463*f6dc9357SAndroid Build Coastguard Worker }
464*f6dc9357SAndroid Build Coastguard Worker FString dirPrefix = us2fs(options.HashDir);
465*f6dc9357SAndroid Build Coastguard Worker if (dirPrefix.IsEmpty())
466*f6dc9357SAndroid Build Coastguard Worker {
467*f6dc9357SAndroid Build Coastguard Worker if (!NFile::NDir::GetOnlyDirPrefix(us2fs(arcPath), dirPrefix))
468*f6dc9357SAndroid Build Coastguard Worker {
469*f6dc9357SAndroid Build Coastguard Worker // return GetLastError_noZero_HRESULT();
470*f6dc9357SAndroid Build Coastguard Worker }
471*f6dc9357SAndroid Build Coastguard Worker }
472*f6dc9357SAndroid Build Coastguard Worker if (!dirPrefix.IsEmpty())
473*f6dc9357SAndroid Build Coastguard Worker NName::NormalizeDirPathPrefix(dirPrefix);
474*f6dc9357SAndroid Build Coastguard Worker ecs->DirPathPrefix_for_HashFiles = dirPrefix;
475*f6dc9357SAndroid Build Coastguard Worker }
476*f6dc9357SAndroid Build Coastguard Worker }
477*f6dc9357SAndroid Build Coastguard Worker
478*f6dc9357SAndroid Build Coastguard Worker if (!options.StdInMode)
479*f6dc9357SAndroid Build Coastguard Worker {
480*f6dc9357SAndroid Build Coastguard Worker // numVolumes += arcLink.VolumePaths.Size();
481*f6dc9357SAndroid Build Coastguard Worker // arcLink.VolumesSize;
482*f6dc9357SAndroid Build Coastguard Worker
483*f6dc9357SAndroid Build Coastguard Worker // totalPackSize -= DeleteUsedFileNamesFromList(arcLink, i + 1, arcPaths, arcPathsFull, &arcSizes);
484*f6dc9357SAndroid Build Coastguard Worker // numArcs = arcPaths.Size();
485*f6dc9357SAndroid Build Coastguard Worker if (arcLink.VolumePaths.Size() != 0)
486*f6dc9357SAndroid Build Coastguard Worker {
487*f6dc9357SAndroid Build Coastguard Worker Int64 correctionSize = (Int64)arcLink.VolumesSize;
488*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (v, arcLink.VolumePaths)
489*f6dc9357SAndroid Build Coastguard Worker {
490*f6dc9357SAndroid Build Coastguard Worker int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]);
491*f6dc9357SAndroid Build Coastguard Worker if (index >= 0)
492*f6dc9357SAndroid Build Coastguard Worker {
493*f6dc9357SAndroid Build Coastguard Worker if ((unsigned)index > i)
494*f6dc9357SAndroid Build Coastguard Worker {
495*f6dc9357SAndroid Build Coastguard Worker skipArcs[(unsigned)index] = true;
496*f6dc9357SAndroid Build Coastguard Worker correctionSize -= arcSizes[(unsigned)index];
497*f6dc9357SAndroid Build Coastguard Worker }
498*f6dc9357SAndroid Build Coastguard Worker }
499*f6dc9357SAndroid Build Coastguard Worker }
500*f6dc9357SAndroid Build Coastguard Worker if (correctionSize != 0)
501*f6dc9357SAndroid Build Coastguard Worker {
502*f6dc9357SAndroid Build Coastguard Worker Int64 newPackSize = (Int64)totalPackSize + correctionSize;
503*f6dc9357SAndroid Build Coastguard Worker if (newPackSize < 0)
504*f6dc9357SAndroid Build Coastguard Worker newPackSize = 0;
505*f6dc9357SAndroid Build Coastguard Worker totalPackSize = (UInt64)newPackSize;
506*f6dc9357SAndroid Build Coastguard Worker RINOK(faeCallback->SetTotal(totalPackSize))
507*f6dc9357SAndroid Build Coastguard Worker }
508*f6dc9357SAndroid Build Coastguard Worker }
509*f6dc9357SAndroid Build Coastguard Worker }
510*f6dc9357SAndroid Build Coastguard Worker
511*f6dc9357SAndroid Build Coastguard Worker /*
512*f6dc9357SAndroid Build Coastguard Worker // Now openCallback and extractCallback use same object. So we don't need to send password.
513*f6dc9357SAndroid Build Coastguard Worker
514*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_NO_CRYPTO
515*f6dc9357SAndroid Build Coastguard Worker bool passwordIsDefined;
516*f6dc9357SAndroid Build Coastguard Worker UString password;
517*f6dc9357SAndroid Build Coastguard Worker RINOK(openCallback->Open_GetPasswordIfAny(passwordIsDefined, password))
518*f6dc9357SAndroid Build Coastguard Worker if (passwordIsDefined)
519*f6dc9357SAndroid Build Coastguard Worker {
520*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetPassword(password))
521*f6dc9357SAndroid Build Coastguard Worker }
522*f6dc9357SAndroid Build Coastguard Worker #endif
523*f6dc9357SAndroid Build Coastguard Worker */
524*f6dc9357SAndroid Build Coastguard Worker
525*f6dc9357SAndroid Build Coastguard Worker CArc &arc = arcLink.Arcs.Back();
526*f6dc9357SAndroid Build Coastguard Worker arc.MTime.Def = !options.StdInMode
527*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
528*f6dc9357SAndroid Build Coastguard Worker && !fi.IsDevice
529*f6dc9357SAndroid Build Coastguard Worker #endif
530*f6dc9357SAndroid Build Coastguard Worker ;
531*f6dc9357SAndroid Build Coastguard Worker if (arc.MTime.Def)
532*f6dc9357SAndroid Build Coastguard Worker arc.MTime.Set_From_FiTime(fi.MTime);
533*f6dc9357SAndroid Build Coastguard Worker
534*f6dc9357SAndroid Build Coastguard Worker UInt64 packProcessed;
535*f6dc9357SAndroid Build Coastguard Worker const bool calcCrc =
536*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_SFX
537*f6dc9357SAndroid Build Coastguard Worker (hash != NULL);
538*f6dc9357SAndroid Build Coastguard Worker #else
539*f6dc9357SAndroid Build Coastguard Worker false;
540*f6dc9357SAndroid Build Coastguard Worker #endif
541*f6dc9357SAndroid Build Coastguard Worker
542*f6dc9357SAndroid Build Coastguard Worker RINOK(DecompressArchive(
543*f6dc9357SAndroid Build Coastguard Worker codecs,
544*f6dc9357SAndroid Build Coastguard Worker arcLink,
545*f6dc9357SAndroid Build Coastguard Worker fi.Size + arcLink.VolumesSize,
546*f6dc9357SAndroid Build Coastguard Worker wildcardCensor,
547*f6dc9357SAndroid Build Coastguard Worker options,
548*f6dc9357SAndroid Build Coastguard Worker calcCrc,
549*f6dc9357SAndroid Build Coastguard Worker extractCallback, faeCallback, ecs,
550*f6dc9357SAndroid Build Coastguard Worker errorMessage, packProcessed))
551*f6dc9357SAndroid Build Coastguard Worker
552*f6dc9357SAndroid Build Coastguard Worker if (!options.StdInMode)
553*f6dc9357SAndroid Build Coastguard Worker packProcessed = fi.Size + arcLink.VolumesSize;
554*f6dc9357SAndroid Build Coastguard Worker totalPackProcessed += packProcessed;
555*f6dc9357SAndroid Build Coastguard Worker ecs->LocalProgressSpec->InSize += packProcessed;
556*f6dc9357SAndroid Build Coastguard Worker ecs->LocalProgressSpec->OutSize = ecs->UnpackSize;
557*f6dc9357SAndroid Build Coastguard Worker if (!errorMessage.IsEmpty())
558*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
559*f6dc9357SAndroid Build Coastguard Worker }
560*f6dc9357SAndroid Build Coastguard Worker
561*f6dc9357SAndroid Build Coastguard Worker if (multi || thereAreNotOpenArcs)
562*f6dc9357SAndroid Build Coastguard Worker {
563*f6dc9357SAndroid Build Coastguard Worker RINOK(faeCallback->SetTotal(totalPackSize))
564*f6dc9357SAndroid Build Coastguard Worker RINOK(faeCallback->SetCompleted(&totalPackProcessed))
565*f6dc9357SAndroid Build Coastguard Worker }
566*f6dc9357SAndroid Build Coastguard Worker
567*f6dc9357SAndroid Build Coastguard Worker st.NumFolders = ecs->NumFolders;
568*f6dc9357SAndroid Build Coastguard Worker st.NumFiles = ecs->NumFiles;
569*f6dc9357SAndroid Build Coastguard Worker st.NumAltStreams = ecs->NumAltStreams;
570*f6dc9357SAndroid Build Coastguard Worker st.UnpackSize = ecs->UnpackSize;
571*f6dc9357SAndroid Build Coastguard Worker st.AltStreams_UnpackSize = ecs->AltStreams_UnpackSize;
572*f6dc9357SAndroid Build Coastguard Worker st.NumArchives = arcPaths.Size();
573*f6dc9357SAndroid Build Coastguard Worker st.PackSize = ecs->LocalProgressSpec->InSize;
574*f6dc9357SAndroid Build Coastguard Worker return S_OK;
575*f6dc9357SAndroid Build Coastguard Worker }
576