1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// Extract.cpp
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StdAfx.h"
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include <stdio.h>
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Windows/FileDir.h"
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Windows/PropVariant.h"
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Windows/PropVariantConversions.h"
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../Common/ExtractingFilePath.h"
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Extract.h"
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "SetProperties.h"
15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
16baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NWindows;
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
18baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic HRESULT DecompressArchive(
19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CArc &arc,
20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt64 packSize,
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const NWildcard::CCensorNode &wildcardCensor,
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CExtractOptions &options,
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IExtractCallbackUI *callback,
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CArchiveExtractCallback *extractCallbackSpec,
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UString &errorMessage,
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt64 &stdInProcessed)
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  stdInProcessed = 0;
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  IInArchive *archive = arc.Archive;
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CRecordVector<UInt32> realIndices;
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!options.StdInMode)
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 numItems;
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(archive->GetNumberOfItems(&numItems));
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (UInt32 i = 0; i < numItems; i++)
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UString filePath;
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(arc.GetItemPath(i, filePath));
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      bool isFolder;
41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(IsArchiveItemFolder(archive, i, isFolder));
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!wildcardCensor.CheckPath(filePath, !isFolder))
43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        continue;
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      realIndices.Add(i);
45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (realIndices.Size() == 0)
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      callback->ThereAreNoFiles();
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return S_OK;
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UStringVector removePathParts;
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UString outDir = options.OutputDir;
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  outDir.Replace(L"*", GetCorrectFsPath(arc.DefaultName));
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef _WIN32
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  // GetCorrectFullFsPath doesn't like "..".
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  // outDir.TrimRight();
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  // outDir = GetCorrectFullFsPath(outDir);
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!outDir.IsEmpty())
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!NFile::NDirectory::CreateComplexDirectory(outDir))
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      HRESULT res = ::GetLastError();
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (res == S_OK)
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        res = E_FAIL;
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorMessage = ((UString)L"Can not create output directory ") + outDir;
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return res;
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  extractCallbackSpec->Init(
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      options.StdInMode ? &wildcardCensor : NULL,
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      &arc,
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      callback,
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      options.StdOutMode, options.TestMode, options.CalcCrc,
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      outDir,
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      removePathParts,
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      packSize);
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #if !defined(_7ZIP_ST) && !defined(_SFX)
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(SetProperties(archive, options.Properties));
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT result;
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Int32 testMode = (options.TestMode && !options.CalcCrc) ? 1: 0;
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (options.StdInMode)
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, extractCallbackSpec);
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NCOM::CPropVariant prop;
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK)
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (prop.vt == VT_UI8 || prop.vt == VT_UI4)
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        stdInProcessed = ConvertPropVariantToUInt64(prop);
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallbackSpec);
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return callback->ExtractResult(result);
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
102baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT DecompressArchives(
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CCodecs *codecs, const CIntVector &formatIndices,
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UStringVector &arcPaths, UStringVector &arcPathsFull,
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const NWildcard::CCensorNode &wildcardCensor,
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CExtractOptions &options,
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IOpenCallbackUI *openCallback,
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IExtractCallbackUI *extractCallback,
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UString &errorMessage,
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CDecompressStat &stat)
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  stat.Clear();
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int i;
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 totalPackSize = 0;
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CRecordVector<UInt64> archiveSizes;
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int numArcs = options.StdInMode ? 1 : arcPaths.Size();
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < numArcs; i++)
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NFile::NFind::CFileInfoW fi;
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    fi.Size = 0;
123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!options.StdInMode)
124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      const UString &arcPath = arcPaths[i];
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!fi.Find(arcPath))
127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        throw "there is no such archive";
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (fi.IsDir())
129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        throw "can't decompress folder";
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    archiveSizes.Add(fi.Size);
132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    totalPackSize += fi.Size;
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec);
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bool multi = (numArcs > 1);
137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode);
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (multi)
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(extractCallback->SetTotal(totalPackSize));
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < numArcs; i++)
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UString &arcPath = arcPaths[i];
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NFile::NFind::CFileInfoW fi;
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (options.StdInMode)
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      fi.Size = 0;
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      fi.Attrib = 0;
150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!fi.Find(arcPath) || fi.IsDir())
154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        throw "there is no such archive";
155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifndef _NO_CRYPTO
158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    openCallback->Open_ClearPasswordWasAskedFlag();
159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(extractCallback->BeforeOpen(arcPath));
162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CArchiveLink archiveLink;
163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CIntVector formatIndices2 = formatIndices;
165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifndef _SFX
166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (formatIndices.IsEmpty())
167baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
168baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      int pos = arcPath.ReverseFind(L'.');
169baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (pos >= 0)
170baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        UString s = arcPath.Mid(pos + 1);
172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        int index = codecs->FindFormatForExtension(s);
173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (index >= 0 && s == L"001")
174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          s = arcPath.Left(pos);
176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          pos = s.ReverseFind(L'.');
177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          if (pos >= 0)
178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          {
179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1));
180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            if (index2 >= 0 && s.CompareNoCase(L"rar") != 0)
181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            {
182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync              formatIndices2.Add(index2);
183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync              formatIndices2.Add(index);
184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            }
185baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          }
186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    HRESULT result = archiveLink.Open2(codecs, formatIndices2, options.StdInMode, NULL, arcPath, openCallback);
191baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (result == E_ABORT)
192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return result;
193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
194baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool crypted = false;
195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifndef _NO_CRYPTO
196baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    crypted = openCallback->Open_WasPasswordAsked();
197baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
198baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(extractCallback->OpenResult(arcPath, result, crypted));
200baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (result != S_OK)
201baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      continue;
202baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
203baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!options.StdInMode)
204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
205baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]);
207baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (index >= 0 && index > i)
208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
209baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        arcPaths.Delete(index);
210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        arcPathsFull.Delete(index);
211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        totalPackSize -= archiveSizes[index];
212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        archiveSizes.Delete(index);
213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        numArcs = arcPaths.Size();
214baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
215baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (archiveLink.VolumePaths.Size() != 0)
217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      totalPackSize += archiveLink.VolumesSize;
219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(extractCallback->SetTotal(totalPackSize));
220baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
222baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifndef _NO_CRYPTO
223baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UString password;
224baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(openCallback->Open_GetPasswordIfAny(password));
225baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!password.IsEmpty())
226baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
227baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(extractCallback->SetPassword(password));
228baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
229baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
230baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
231baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (int v = 0; v < archiveLink.Arcs.Size(); v++)
232baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
233baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      const UString &s = archiveLink.Arcs[v].ErrorMessage;
234baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!s.IsEmpty())
235baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
236baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        RINOK(extractCallback->MessageError(s));
237baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
238baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
239baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
240baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CArc &arc = archiveLink.Arcs.Back();
241baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice);
242baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    arc.MTime = fi.MTime;
243baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
244baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt64 packProcessed;
245baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(DecompressArchive(arc,
246baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        fi.Size + archiveLink.VolumesSize,
247baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage, packProcessed));
248baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!options.StdInMode)
249baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      packProcessed = fi.Size + archiveLink.VolumesSize;
250baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    extractCallbackSpec->LocalProgressSpec->InSize += packProcessed;
251baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize;
252baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!errorMessage.IsEmpty())
253baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_FAIL;
254baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
255baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  stat.NumFolders = extractCallbackSpec->NumFolders;
256baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  stat.NumFiles = extractCallbackSpec->NumFiles;
257baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  stat.UnpackSize = extractCallbackSpec->UnpackSize;
258baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  stat.CrcSum = extractCallbackSpec->CrcSum;
259baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
260baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  stat.NumArchives = arcPaths.Size();
261baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize;
262baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
263baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
264