xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/Common/Extract.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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