1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// Update.cpp
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StdAfx.h"
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Update.h"
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Common/IntToString.h"
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Common/StringConvert.h"
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef _WIN32
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Windows/DLL.h"
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Windows/FileDir.h"
15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Windows/FileFind.h"
16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Windows/FileName.h"
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Windows/PropVariant.h"
18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Windows/PropVariantConversions.h"
19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Windows/Time.h"
20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../Common/FileStreams.h"
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../Compress/CopyCoder.h"
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../Common/DirItem.h"
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../Common/EnumDirItems.h"
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../Common/OpenArchive.h"
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../Common/UpdateProduce.h"
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "EnumDirItems.h"
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "SetProperties.h"
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "TempFiles.h"
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "UpdateCallback.h"
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
35baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const char *kUpdateIsNotSupoorted =
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  "update operations are not supported for this archive";
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
38baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NWindows;
39baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NCOM;
40baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NFile;
41baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NName;
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
43baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const wchar_t *kTempFolderPrefix = L"7zE";
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
45baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NUpdateArchive;
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
47baa3858d3f5d128a5c8466b700098109edcad5f2repo syncclass COutMultiVolStream:
48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  public IOutStream,
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  public CMyUnknownImp
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int _streamIndex; // required stream
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 _offsetPos; // offset from start of _streamIndex index
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 _absPos;
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 _length;
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  struct CSubStreamInfo
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    COutFileStream *StreamSpec;
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<IOutStream> Stream;
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UString Name;
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt64 Pos;
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt64 RealSize;
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  };
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CObjectVector<CSubStreamInfo> Streams;
65baa3858d3f5d128a5c8466b700098109edcad5f2repo syncpublic:
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CRecordVector<UInt64> Sizes;
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UString Prefix;
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CTempFiles *TempFiles;
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  void Init()
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _streamIndex = 0;
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _offsetPos = 0;
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _absPos = 0;
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _length = 0;
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT Close();
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  MY_UNKNOWN_IMP1(IOutStream)
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  STDMETHOD(SetSize)(UInt64 newSize);
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// static NSynchronization::CCriticalSection g_TempPathsCS;
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
90baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT COutMultiVolStream::Close()
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT res = S_OK;
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (int i = 0; i < Streams.Size(); i++)
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CSubStreamInfo &s = Streams[i];
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (s.StreamSpec)
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      HRESULT res2 = s.StreamSpec->Close();
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (res2 != S_OK)
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        res = res2;
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return res;
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
106baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (processedSize != NULL)
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = 0;
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  while(size > 0)
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (_streamIndex >= Streams.Size())
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CSubStreamInfo subStream;
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      wchar_t temp[16];
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      ConvertUInt32ToString(_streamIndex + 1, temp);
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UString res = temp;
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      while (res.Length() < 3)
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        res = UString(L'0') + res;
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UString name = Prefix + res;
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      subStream.StreamSpec = new COutFileStream;
123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      subStream.Stream = subStream.StreamSpec;
124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!subStream.StreamSpec->Create(name, false))
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return ::GetLastError();
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS);
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        TempFiles->Paths.Add(name);
129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      subStream.Pos = 0;
132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      subStream.RealSize = 0;
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      subStream.Name = name;
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      Streams.Add(subStream);
135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      continue;
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CSubStreamInfo &subStream = Streams[_streamIndex];
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int index = _streamIndex;
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (index >= Sizes.Size())
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      index = Sizes.Size() - 1;
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt64 volSize = Sizes[index];
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (_offsetPos >= volSize)
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _offsetPos -= volSize;
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _streamIndex++;
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      continue;
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (_offsetPos != subStream.Pos)
151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      // CMyComPtr<IOutStream> outStream;
153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      subStream.Pos = _offsetPos;
156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos);
159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 realProcessed;
160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    data = (void *)((Byte *)data + realProcessed);
162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size -= realProcessed;
163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    subStream.Pos += realProcessed;
164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _offsetPos += realProcessed;
165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _absPos += realProcessed;
166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (_absPos > _length)
167baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _length = _absPos;
168baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (_offsetPos > subStream.RealSize)
169baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      subStream.RealSize = _offsetPos;
170baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (processedSize != NULL)
171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      *processedSize += realProcessed;
172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (subStream.Pos == volSize)
173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _streamIndex++;
175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _offsetPos = 0;
176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (realProcessed == 0 && curSize != 0)
178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_FAIL;
179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    break;
180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
184baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
185baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (seekOrigin >= 3)
187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return STG_E_INVALIDFUNCTION;
188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  switch(seekOrigin)
189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case STREAM_SEEK_SET:
191baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _absPos = offset;
192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      break;
193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case STREAM_SEEK_CUR:
194baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _absPos += offset;
195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      break;
196baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case STREAM_SEEK_END:
197baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _absPos = _length + offset;
198baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      break;
199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
200baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _offsetPos = _absPos;
201baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (newPosition != NULL)
202baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *newPosition = _absPos;
203baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _streamIndex = 0;
204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
205baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
207baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize)
208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
209baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (newSize < 0)
210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_INVALIDARG;
211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int i = 0;
212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  while (i < Streams.Size())
213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
214baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CSubStreamInfo &subStream = Streams[i++];
215baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if ((UInt64)newSize < subStream.RealSize)
216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(subStream.Stream->SetSize(newSize));
218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      subStream.RealSize = newSize;
219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      break;
220baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    newSize -= subStream.RealSize;
222baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
223baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  while (i < Streams.Size())
224baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
225baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
226baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CSubStreamInfo &subStream = Streams.Back();
227baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      subStream.Stream.Release();
228baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      NDirectory::DeleteFileAlways(subStream.Name);
229baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
230baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Streams.DeleteBack();
231baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
232baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _offsetPos = _absPos;
233baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _streamIndex = 0;
234baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _length = newSize;
235baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
236baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
237baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
238baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const wchar_t *kDefaultArchiveType = L"7z";
239baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const wchar_t *kSFXExtension =
240baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef _WIN32
241baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    L"exe";
242baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
243baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    L"";
244baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
245baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
246baa3858d3f5d128a5c8466b700098109edcad5f2repo syncbool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath)
247baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
248baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (formatIndices.Size() > 1)
249baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return false;
250baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int arcTypeIndex = -1;
251baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (formatIndices.Size() != 0)
252baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    arcTypeIndex = formatIndices[0];
253baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (arcTypeIndex >= 0)
254baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    MethodMode.FormatIndex = arcTypeIndex;
255baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else
256baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
257baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath);
258baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    // It works incorrectly for update command if archive has some non-default extension!
259baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (MethodMode.FormatIndex < 0)
260baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType);
261baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
262baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (MethodMode.FormatIndex < 0)
263baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return false;
264baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex];
265baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!arcInfo.UpdateEnabled)
266baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return false;
267baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UString typeExt = arcInfo.GetMainExt();
268baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UString ext = typeExt;
269baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (SfxMode)
270baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ext = kSFXExtension;
271baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ArchivePath.BaseExtension = ext;
272baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ArchivePath.VolExtension = typeExt;
273baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ArchivePath.ParseFromPath(arcPath);
274baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (int i = 0; i < Commands.Size(); i++)
275baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
276baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CUpdateArchiveCommand &uc = Commands[i];
277baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    uc.ArchivePath.BaseExtension = ext;
278baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    uc.ArchivePath.VolExtension = typeExt;
279baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    uc.ArchivePath.ParseFromPath(uc.UserArchivePath);
280baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
281baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return true;
282baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
283baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
284baa3858d3f5d128a5c8466b700098109edcad5f2repo sync/*
285baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstruct CUpdateProduceCallbackImp: public IUpdateProduceCallback
286baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
287baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  const CObjectVector<CArcItem> *_arcItems;
288baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  IUpdateCallbackUI *_callback;
289baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
290baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a,
291baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {}
292baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  virtual HRESULT ShowDeleteFile(int arcIndex);
293baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
294baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
295baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex)
296baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
297baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return _callback->ShowDeleteFile((*_arcItems)[arcIndex].Name);
298baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
299baa3858d3f5d128a5c8466b700098109edcad5f2repo sync*/
300baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
301baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic HRESULT Compress(
302baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CCodecs *codecs,
303baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CActionSet &actionSet,
304baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IInArchive *archive,
305baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CCompressionMethodMode &compressionMethod,
306baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CArchivePath &archivePath,
307baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CObjectVector<CArcItem> &arcItems,
308baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool shareForWrite,
309baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool stdInMode,
310baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    /* const UString & stdInFileName, */
311baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool stdOutMode,
312baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CDirItems &dirItems,
313baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool sfxMode,
314baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UString &sfxModule,
315baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CRecordVector<UInt64> &volumesSizes,
316baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CTempFiles &tempFiles,
317baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CUpdateErrorInfo &errorInfo,
318baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IUpdateCallbackUI *callback)
319baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
320baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<IOutArchive> outArchive;
321baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (archive != NULL)
322baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
323baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<IInArchive> archive2 = archive;
324baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);
325baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (result != S_OK)
326baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      throw kUpdateIsNotSupoorted;
327baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
328baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else
329baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
330baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive));
331baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
332baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifdef EXTERNAL_CODECS
333baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
334baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
335baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
336baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (setCompressCodecsInfo)
337baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
338baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));
339baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
340baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
341baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
342baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
343baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (outArchive == 0)
344baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    throw kUpdateIsNotSupoorted;
345baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
346baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NFileTimeType::EEnum fileTimeType;
347baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 value;
348baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(outArchive->GetFileTimeType(&value));
349baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
350baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  switch(value)
351baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
352baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case NFileTimeType::kWindows:
353baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case NFileTimeType::kUnix:
354baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case NFileTimeType::kDOS:
355baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      fileTimeType = (NFileTimeType::EEnum)value;
356baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      break;
357baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    default:
358baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_FAIL;
359baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
360baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
361baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CRecordVector<CUpdatePair2> updatePairs2;
362baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
363baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
364baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CRecordVector<CUpdatePair> updatePairs;
365baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!!
366baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    // CUpdateProduceCallbackImp upCallback(&arcItems, callback);
367baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UpdateProduce(updatePairs, actionSet, updatePairs2, NULL /* &upCallback */);
368baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
369baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
370baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 numFiles = 0;
371baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (int i = 0; i < updatePairs2.Size(); i++)
372baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (updatePairs2[i].NewData)
373baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      numFiles++;
374baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
375baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(callback->SetNumFiles(numFiles));
376baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
377baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
378baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
379baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
380baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
381baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  updateCallbackSpec->ShareForWrite = shareForWrite;
382baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  updateCallbackSpec->StdInMode = stdInMode;
383baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  updateCallbackSpec->Callback = callback;
384baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  updateCallbackSpec->DirItems = &dirItems;
385baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  updateCallbackSpec->ArcItems = &arcItems;
386baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  updateCallbackSpec->UpdatePairs = &updatePairs2;
387baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
388baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ISequentialOutStream> outStream;
389baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
390baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!stdOutMode)
391baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
392baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UString resultPath;
393baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int pos;
394baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!NFile::NDirectory::MyGetFullPathName(archivePath.GetFinalPath(), resultPath, pos))
395baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      throw 1417161;
396baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
397baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
398baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
399baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  COutFileStream *outStreamSpec = NULL;
400baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  COutMultiVolStream *volStreamSpec = NULL;
401baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
402baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (volumesSizes.Size() == 0)
403baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
404baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (stdOutMode)
405baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      outStream = new CStdOutFileStream;
406baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
407baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
408baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      outStreamSpec = new COutFileStream;
409baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      outStream = outStreamSpec;
410baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      bool isOK = false;
411baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UString realPath;
412baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      for (int i = 0; i < (1 << 16); i++)
413baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
414baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (archivePath.Temp)
415baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
416baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          if (i > 0)
417baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          {
418baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            wchar_t s[16];
419baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            ConvertUInt32ToString(i, s);
420baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            archivePath.TempPostfix = s;
421baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          }
422baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          realPath = archivePath.GetTempPath();
423baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
424baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        else
425baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          realPath = archivePath.GetFinalPath();
426baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (outStreamSpec->Create(realPath, false))
427baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
428baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          tempFiles.Paths.Add(realPath);
429baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          isOK = true;
430baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          break;
431baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
432baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (::GetLastError() != ERROR_FILE_EXISTS)
433baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          break;
434baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (!archivePath.Temp)
435baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          break;
436baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
437baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!isOK)
438baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
439baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.SystemError = ::GetLastError();
440baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.FileName = realPath;
441baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.Message = L"7-Zip cannot open file";
442baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return E_FAIL;
443baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
444baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
445baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
446baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else
447baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
448baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (stdOutMode)
449baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_FAIL;
450baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    volStreamSpec = new COutMultiVolStream;
451baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    outStream = volStreamSpec;
452baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    volStreamSpec->Sizes = volumesSizes;
453baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L".");
454baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    volStreamSpec->TempFiles = &tempFiles;
455baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    volStreamSpec->Init();
456baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
457baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    /*
458baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    updateCallbackSpec->VolumesSizes = volumesSizes;
459baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name;
460baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!archivePath.VolExtension.IsEmpty())
461baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension;
462baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    */
463baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
464baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
465baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(SetProperties(outArchive, compressionMethod.Properties));
466baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
467baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (sfxMode)
468baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
469baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CInFileStream *sfxStreamSpec = new CInFileStream;
470baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
471baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!sfxStreamSpec->Open(sfxModule))
472baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
473baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorInfo.SystemError = ::GetLastError();
474baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorInfo.Message = L"7-Zip cannot open SFX module";
475baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorInfo.FileName = sfxModule;
476baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_FAIL;
477baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
478baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
479baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<ISequentialOutStream> sfxOutStream;
480baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    COutFileStream *outStreamSpec = NULL;
481baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (volumesSizes.Size() == 0)
482baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      sfxOutStream = outStream;
483baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
484baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
485baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      outStreamSpec = new COutFileStream;
486baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      sfxOutStream = outStreamSpec;
487baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UString realPath = archivePath.GetFinalPath();
488baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!outStreamSpec->Create(realPath, false))
489baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
490baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.SystemError = ::GetLastError();
491baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.FileName = realPath;
492baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.Message = L"7-Zip cannot open file";
493baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return E_FAIL;
494baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
495baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
496baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL));
497baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (outStreamSpec)
498baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
499baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(outStreamSpec->Close());
500baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
501baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
502baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
503baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback);
504baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  callback->Finilize();
505baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(result);
506baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (outStreamSpec)
507baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    result = outStreamSpec->Close();
508baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else if (volStreamSpec)
509baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    result = volStreamSpec->Close();
510baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return result;
511baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
512baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
513baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,
514baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CArc &arc,
515baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CObjectVector<CArcItem> &arcItems)
516baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
517baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  arcItems.Clear();
518baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 numItems;
519baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  IInArchive *archive = arc.Archive;
520baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(archive->GetNumberOfItems(&numItems));
521baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  arcItems.Reserve(numItems);
522baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (UInt32 i = 0; i < numItems; i++)
523baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
524baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CArcItem ai;
525baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
526baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(arc.GetItemPath(i, ai.Name));
527baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(IsArchiveItemFolder(archive, i, ai.IsDir));
528baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir);
529baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined));
530baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
531baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
532baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CPropVariant prop;
533baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(archive->GetProperty(i, kpidSize, &prop));
534baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      ai.SizeDefined = (prop.vt != VT_EMPTY);
535baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (ai.SizeDefined)
536baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        ai.Size = ConvertPropVariantToUInt64(prop);
537baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
538baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
539baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
540baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CPropVariant prop;
541baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(archive->GetProperty(i, kpidTimeType, &prop));
542baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (prop.vt == VT_UI4)
543baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
544baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal;
545baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        switch(ai.TimeType)
546baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
547baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          case NFileTimeType::kWindows:
548baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          case NFileTimeType::kUnix:
549baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          case NFileTimeType::kDOS:
550baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            break;
551baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          default:
552baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            return E_FAIL;
553baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
554baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
555baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
556baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
557baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ai.IndexInServer = i;
558baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    arcItems.Add(ai);
559baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
560baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
561baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
562baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
563baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
564baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic HRESULT UpdateWithItemLists(
565baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CCodecs *codecs,
566baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CUpdateOptions &options,
567baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IInArchive *archive,
568baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CObjectVector<CArcItem> &arcItems,
569baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CDirItems &dirItems,
570baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CTempFiles &tempFiles,
571baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CUpdateErrorInfo &errorInfo,
572baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IUpdateCallbackUI2 *callback)
573baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
574baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for(int i = 0; i < options.Commands.Size(); i++)
575baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
576baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CUpdateArchiveCommand &command = options.Commands[i];
577baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (options.StdOutMode)
578baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
579baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(callback->StartArchive(L"stdout", archive != 0));
580baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
581baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
582baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
583baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(),
584baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          i == 0 && options.UpdateArchiveItself && archive != 0));
585baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
586baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
587baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(Compress(
588baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        codecs,
589baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        command.ActionSet, archive,
590baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        options.MethodMode,
591baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        command.ArchivePath,
592baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        arcItems,
593baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        options.OpenShareForWrite,
594baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        options.StdInMode,
595baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        /* options.StdInFileName, */
596baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        options.StdOutMode,
597baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        dirItems,
598baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        options.SfxMode, options.SfxModule,
599baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        options.VolumesSizes,
600baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        tempFiles,
601baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo, callback));
602baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
603baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(callback->FinishArchive());
604baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
605baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
606baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
607baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
608baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#if defined(_WIN32) && !defined(UNDER_CE)
609baa3858d3f5d128a5c8466b700098109edcad5f2repo syncclass CCurrentDirRestorer
610baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
611baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UString _path;
612baa3858d3f5d128a5c8466b700098109edcad5f2repo syncpublic:
613baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(_path); }
614baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ~CCurrentDirRestorer() { RestoreDirectory();}
615baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(_path)); }
616baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
617baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
618baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
619baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstruct CEnumDirItemUpdateCallback: public IEnumDirItemCallback
620baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
621baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  IUpdateCallbackUI2 *Callback;
622baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path)
623baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
624baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return Callback->ScanProgress(numFolders, numFiles, path);
625baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
626baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
627baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
628baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef _WIN32
629baa3858d3f5d128a5c8466b700098109edcad5f2repo synctypedef ULONG (FAR PASCAL MY_MAPISENDDOCUMENTS)(
630baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ULONG_PTR ulUIParam,
631baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LPSTR lpszDelimChar,
632baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LPSTR lpszFilePaths,
633baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LPSTR lpszFileNames,
634baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ULONG ulReserved
635baa3858d3f5d128a5c8466b700098109edcad5f2repo sync);
636baa3858d3f5d128a5c8466b700098109edcad5f2repo synctypedef MY_MAPISENDDOCUMENTS FAR *MY_LPMAPISENDDOCUMENTS;
637baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
638baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
639baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT UpdateArchive(
640baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CCodecs *codecs,
641baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const NWildcard::CCensor &censor,
642baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CUpdateOptions &options,
643baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CUpdateErrorInfo &errorInfo,
644baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IOpenCallbackUI *openCallback,
645baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IUpdateCallbackUI2 *callback)
646baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
647baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (options.StdOutMode && options.EMailMode)
648baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
649baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
650baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode))
651baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_NOTIMPL;
652baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
653baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (options.SfxMode)
654baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
655baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CProperty property;
656baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    property.Name = L"rsfx";
657baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    property.Value = L"on";
658baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    options.MethodMode.Properties.Add(property);
659baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (options.SfxModule.IsEmpty())
660baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
661baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorInfo.Message = L"SFX file is not specified";
662baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_FAIL;
663baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
664baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UString name = options.SfxModule;
665baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifdef UNDER_CE
666baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!NFind::DoesFileExist(name))
667baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #else
668baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule))
669baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
670baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
671baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorInfo.SystemError = ::GetLastError();
672baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorInfo.Message = L"7-Zip cannot find specified SFX module";
673baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorInfo.FileName = name;
674baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_FAIL;
675baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
676baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
677baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
678baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
679baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CArchiveLink arcLink;
680baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  const UString arcPath = options.ArchivePath.GetFinalPath();
681baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
682baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!options.ArchivePath.OriginalPath.IsEmpty())
683baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
684baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NFind::CFileInfoW fi;
685baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (fi.Find(arcPath))
686baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
687baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (fi.IsDir())
688baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        throw "there is no such archive";
689baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (options.VolumesSizes.Size() > 0)
690baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return E_NOTIMPL;
691baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CIntVector formatIndices;
692baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (options.MethodMode.FormatIndex >= 0)
693baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        formatIndices.Add(options.MethodMode.FormatIndex);
694baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      HRESULT result = arcLink.Open2(codecs, formatIndices, false, NULL, arcPath, openCallback);
695baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (result == E_ABORT)
696baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return result;
697baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(callback->OpenResult(arcPath, result));
698baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(result);
699baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (arcLink.VolumePaths.Size() > 1)
700baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
701baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.SystemError = (DWORD)E_NOTIMPL;
702baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.Message = L"Updating for multivolume archives is not implemented";
703baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return E_NOTIMPL;
704baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
705baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
706baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CArc &arc = arcLink.Arcs.Back();
707baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      arc.MTimeDefined = !fi.IsDevice;
708baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      arc.MTime = fi.MTime;
709baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
710baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
711baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else
712baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
713baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    /*
714baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (archiveType.IsEmpty())
715baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      throw "type of archive is not specified";
716baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    */
717baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
718baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
719baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CDirItems dirItems;
720baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (options.StdInMode)
721baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
722baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CDirItem di;
723baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    di.Name = options.StdInFileName;
724baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    di.Size = (UInt64)(Int64)-1;
725baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    di.Attrib = 0;
726baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NTime::GetCurUtcFileTime(di.MTime);
727baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    di.CTime = di.ATime = di.MTime;
728baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    dirItems.Items.Add(di);
729baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
730baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else
731baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
732baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool needScanning = false;
733baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for(int i = 0; i < options.Commands.Size(); i++)
734baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (options.Commands[i].ActionSet.NeedScanning())
735baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        needScanning = true;
736baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (needScanning)
737baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
738baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CEnumDirItemUpdateCallback enumCallback;
739baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      enumCallback.Callback = callback;
740baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(callback->StartScanning());
741baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UStringVector errorPaths;
742baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CRecordVector<DWORD> errorCodes;
743baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes);
744baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      for (int i = 0; i < errorPaths.Size(); i++)
745baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
746baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i]));
747baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
748baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (res != S_OK)
749baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
750baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (res != E_ABORT)
751baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          errorInfo.Message = L"Scanning error";
752baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return res;
753baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
754baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(callback->FinishScanning());
755baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
756baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
757baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
758baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UString tempDirPrefix;
759baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bool usesTempDir = false;
760baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
761baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef _WIN32
762baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NDirectory::CTempDirectoryW tempDirectory;
763baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (options.EMailMode && options.EMailRemoveAfter)
764baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
765baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    tempDirectory.Create(kTempFolderPrefix);
766baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    tempDirPrefix = tempDirectory.GetPath();
767baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NormalizeDirPathPrefix(tempDirPrefix);
768baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    usesTempDir = true;
769baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
770baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
771baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
772baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CTempFiles tempFiles;
773baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
774baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bool createTempFile = false;
775baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
776baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bool thereIsInArchive = arcLink.IsOpen;
777baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
778baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!options.StdOutMode && options.UpdateArchiveItself)
779baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
780baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CArchivePath &ap = options.Commands[0].ArchivePath;
781baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ap = options.ArchivePath;
782baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty())
783baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if ((thereIsInArchive || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0)
784baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
785baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      createTempFile = true;
786baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      ap.Temp = true;
787baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!options.WorkingDir.IsEmpty())
788baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
789baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        ap.TempPrefix = options.WorkingDir;
790baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        NormalizeDirPathPrefix(ap.TempPrefix);
791baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
792baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
793baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
794baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
795baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for(int i = 0; i < options.Commands.Size(); i++)
796baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
797baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CArchivePath &ap = options.Commands[i].ArchivePath;
798baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (usesTempDir)
799baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
800baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      // Check it
801baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      ap.Prefix = tempDirPrefix;
802baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      // ap.Temp = true;
803baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      // ap.TempPrefix = tempDirPrefix;
804baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
805baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!options.StdOutMode &&
806baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        (i > 0 || !createTempFile))
807baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
808baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      const UString &path = ap.GetFinalPath();
809baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (NFind::DoesFileOrDirExist(path))
810baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
811baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.SystemError = 0;
812baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.Message = L"The file already exists";
813baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.FileName = path;
814baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return E_FAIL;
815baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
816baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
817baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
818baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
819baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CObjectVector<CArcItem> arcItems;
820baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (thereIsInArchive)
821baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
822baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(EnumerateInArchiveItems(censor, arcLink.Arcs.Back(), arcItems));
823baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
824baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
825baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(UpdateWithItemLists(codecs, options,
826baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      thereIsInArchive ? arcLink.GetArchive() : 0,
827baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      arcItems, dirItems,
828baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      tempFiles, errorInfo, callback));
829baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
830baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (thereIsInArchive)
831baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
832baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(arcLink.Close());
833baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    arcLink.Release();
834baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
835baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
836baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  tempFiles.Paths.Clear();
837baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (createTempFile)
838baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
839baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    try
840baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
841baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CArchivePath &ap = options.Commands[0].ArchivePath;
842baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      const UString &tempPath = ap.GetTempPath();
843baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (thereIsInArchive)
844baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (!NDirectory::DeleteFileAlways(arcPath))
845baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
846baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          errorInfo.SystemError = ::GetLastError();
847baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          errorInfo.Message = L"7-Zip cannot delete the file";
848baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          errorInfo.FileName = arcPath;
849baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          return E_FAIL;
850baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
851baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!NDirectory::MyMoveFile(tempPath, arcPath))
852baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
853baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.SystemError = ::GetLastError();
854baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.Message = L"7-Zip cannot move the file";
855baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.FileName = tempPath;
856baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.FileName2 = arcPath;
857baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return E_FAIL;
858baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
859baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
860baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    catch(...)
861baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
862baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      throw;
863baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
864baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
865baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
866baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #if defined(_WIN32) && !defined(UNDER_CE)
867baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (options.EMailMode)
868baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
869baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NDLL::CLibrary mapiLib;
870baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!mapiLib.Load(TEXT("Mapi32.dll")))
871baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
872baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorInfo.SystemError = ::GetLastError();
873baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorInfo.Message = L"7-Zip cannot load Mapi32.dll";
874baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_FAIL;
875baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
876baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    MY_LPMAPISENDDOCUMENTS fnSend = (MY_LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments");
877baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (fnSend == 0)
878baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
879baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorInfo.SystemError = ::GetLastError();
880baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      errorInfo.Message = L"7-Zip cannot find MAPISendDocuments function";
881baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_FAIL;
882baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
883baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UStringVector fullPaths;
884baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int i;
885baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for(i = 0; i < options.Commands.Size(); i++)
886baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
887baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CArchivePath &ap = options.Commands[i].ArchivePath;
888baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UString arcPath;
889baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath))
890baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
891baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.SystemError = ::GetLastError();
892baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        errorInfo.Message = L"GetFullPathName error";
893baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return E_FAIL;
894baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
895baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      fullPaths.Add(arcPath);
896baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
897baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CCurrentDirRestorer curDirRestorer;
898baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for(i = 0; i < fullPaths.Size(); i++)
899baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
900baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UString arcPath = fullPaths[i];
901baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UString fileName = ExtractFileNameFromPath(arcPath);
902baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      AString path = GetAnsiString(arcPath);
903baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      AString name = GetAnsiString(fileName);
904baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      // Warning!!! MAPISendDocuments function changes Current directory
905baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
906baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
907baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
908baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
909baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
910baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
911