xref: /third_party/lzma/CPP/7zip/UI/Common/Update.cpp (revision 370b324c)
1370b324cSopenharmony_ci// Update.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci// #include  <stdio.h>
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#include "Update.h"
8370b324cSopenharmony_ci
9370b324cSopenharmony_ci#include "../../../Common/StringConvert.h"
10370b324cSopenharmony_ci
11370b324cSopenharmony_ci#include "../../../Windows/DLL.h"
12370b324cSopenharmony_ci#include "../../../Windows/FileDir.h"
13370b324cSopenharmony_ci#include "../../../Windows/FileFind.h"
14370b324cSopenharmony_ci#include "../../../Windows/FileName.h"
15370b324cSopenharmony_ci#include "../../../Windows/PropVariant.h"
16370b324cSopenharmony_ci#include "../../../Windows/PropVariantConv.h"
17370b324cSopenharmony_ci#include "../../../Windows/TimeUtils.h"
18370b324cSopenharmony_ci
19370b324cSopenharmony_ci#include "../../Common/FileStreams.h"
20370b324cSopenharmony_ci#include "../../Common/LimitedStreams.h"
21370b324cSopenharmony_ci#include "../../Common/MultiOutStream.h"
22370b324cSopenharmony_ci#include "../../Common/StreamUtils.h"
23370b324cSopenharmony_ci
24370b324cSopenharmony_ci#include "../../Compress/CopyCoder.h"
25370b324cSopenharmony_ci
26370b324cSopenharmony_ci#include "../Common/DirItem.h"
27370b324cSopenharmony_ci#include "../Common/EnumDirItems.h"
28370b324cSopenharmony_ci#include "../Common/OpenArchive.h"
29370b324cSopenharmony_ci#include "../Common/UpdateProduce.h"
30370b324cSopenharmony_ci
31370b324cSopenharmony_ci#include "EnumDirItems.h"
32370b324cSopenharmony_ci#include "SetProperties.h"
33370b324cSopenharmony_ci#include "TempFiles.h"
34370b324cSopenharmony_ci#include "UpdateCallback.h"
35370b324cSopenharmony_ci
36370b324cSopenharmony_cistatic const char * const kUpdateIsNotSupoorted =
37370b324cSopenharmony_ci  "update operations are not supported for this archive";
38370b324cSopenharmony_ci
39370b324cSopenharmony_cistatic const char * const kUpdateIsNotSupported_MultiVol =
40370b324cSopenharmony_ci  "Updating for multivolume archives is not implemented";
41370b324cSopenharmony_ci
42370b324cSopenharmony_ciusing namespace NWindows;
43370b324cSopenharmony_ciusing namespace NCOM;
44370b324cSopenharmony_ciusing namespace NFile;
45370b324cSopenharmony_ciusing namespace NDir;
46370b324cSopenharmony_ciusing namespace NName;
47370b324cSopenharmony_ci
48370b324cSopenharmony_ci#ifdef _WIN32
49370b324cSopenharmony_cistatic CFSTR const kTempFolderPrefix = FTEXT("7zE");
50370b324cSopenharmony_ci#endif
51370b324cSopenharmony_ci
52370b324cSopenharmony_civoid CUpdateErrorInfo::SetFromLastError(const char *message)
53370b324cSopenharmony_ci{
54370b324cSopenharmony_ci  SystemError = ::GetLastError();
55370b324cSopenharmony_ci  Message = message;
56370b324cSopenharmony_ci}
57370b324cSopenharmony_ci
58370b324cSopenharmony_ciHRESULT CUpdateErrorInfo::SetFromLastError(const char *message, const FString &fileName)
59370b324cSopenharmony_ci{
60370b324cSopenharmony_ci  SetFromLastError(message);
61370b324cSopenharmony_ci  FileNames.Add(fileName);
62370b324cSopenharmony_ci  return Get_HRESULT_Error();
63370b324cSopenharmony_ci}
64370b324cSopenharmony_ci
65370b324cSopenharmony_ciHRESULT CUpdateErrorInfo::SetFromError_DWORD(const char *message, const FString &fileName, DWORD error)
66370b324cSopenharmony_ci{
67370b324cSopenharmony_ci  Message = message;
68370b324cSopenharmony_ci  FileNames.Add(fileName);
69370b324cSopenharmony_ci  SystemError = error;
70370b324cSopenharmony_ci  return Get_HRESULT_Error();
71370b324cSopenharmony_ci}
72370b324cSopenharmony_ci
73370b324cSopenharmony_ci
74370b324cSopenharmony_ciusing namespace NUpdateArchive;
75370b324cSopenharmony_ci
76370b324cSopenharmony_cistruct CMultiOutStream_Rec
77370b324cSopenharmony_ci{
78370b324cSopenharmony_ci  CMultiOutStream *Spec;
79370b324cSopenharmony_ci  CMyComPtr<IOutStream> Ref;
80370b324cSopenharmony_ci};
81370b324cSopenharmony_ci
82370b324cSopenharmony_cistruct CMultiOutStream_Bunch
83370b324cSopenharmony_ci{
84370b324cSopenharmony_ci  CObjectVector<CMultiOutStream_Rec> Items;
85370b324cSopenharmony_ci
86370b324cSopenharmony_ci  HRESULT Destruct()
87370b324cSopenharmony_ci  {
88370b324cSopenharmony_ci    HRESULT hres = S_OK;
89370b324cSopenharmony_ci    FOR_VECTOR (i, Items)
90370b324cSopenharmony_ci    {
91370b324cSopenharmony_ci      CMultiOutStream_Rec &rec = Items[i];
92370b324cSopenharmony_ci      if (rec.Ref)
93370b324cSopenharmony_ci      {
94370b324cSopenharmony_ci        const HRESULT hres2 = rec.Spec->Destruct();
95370b324cSopenharmony_ci        if (hres == S_OK)
96370b324cSopenharmony_ci          hres = hres2;
97370b324cSopenharmony_ci      }
98370b324cSopenharmony_ci    }
99370b324cSopenharmony_ci    Items.Clear();
100370b324cSopenharmony_ci    return hres;
101370b324cSopenharmony_ci  }
102370b324cSopenharmony_ci
103370b324cSopenharmony_ci  void DisableDeletion()
104370b324cSopenharmony_ci  {
105370b324cSopenharmony_ci    FOR_VECTOR (i, Items)
106370b324cSopenharmony_ci    {
107370b324cSopenharmony_ci      CMultiOutStream_Rec &rec = Items[i];
108370b324cSopenharmony_ci      if (rec.Ref)
109370b324cSopenharmony_ci        rec.Spec->NeedDelete = false;
110370b324cSopenharmony_ci    }
111370b324cSopenharmony_ci  }
112370b324cSopenharmony_ci};
113370b324cSopenharmony_ci
114370b324cSopenharmony_ci
115370b324cSopenharmony_civoid CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode)
116370b324cSopenharmony_ci{
117370b324cSopenharmony_ci  OriginalPath = path;
118370b324cSopenharmony_ci
119370b324cSopenharmony_ci  SplitPathToParts_2(path, Prefix, Name);
120370b324cSopenharmony_ci
121370b324cSopenharmony_ci  if (mode == k_ArcNameMode_Add)
122370b324cSopenharmony_ci    return;
123370b324cSopenharmony_ci
124370b324cSopenharmony_ci  if (mode != k_ArcNameMode_Exact)
125370b324cSopenharmony_ci  {
126370b324cSopenharmony_ci    int dotPos = Name.ReverseFind_Dot();
127370b324cSopenharmony_ci    if (dotPos < 0)
128370b324cSopenharmony_ci      return;
129370b324cSopenharmony_ci    if ((unsigned)dotPos == Name.Len() - 1)
130370b324cSopenharmony_ci      Name.DeleteBack();
131370b324cSopenharmony_ci    else
132370b324cSopenharmony_ci    {
133370b324cSopenharmony_ci      const UString ext = Name.Ptr((unsigned)(dotPos + 1));
134370b324cSopenharmony_ci      if (BaseExtension.IsEqualTo_NoCase(ext))
135370b324cSopenharmony_ci      {
136370b324cSopenharmony_ci        BaseExtension = ext;
137370b324cSopenharmony_ci        Name.DeleteFrom((unsigned)dotPos);
138370b324cSopenharmony_ci        return;
139370b324cSopenharmony_ci      }
140370b324cSopenharmony_ci    }
141370b324cSopenharmony_ci  }
142370b324cSopenharmony_ci
143370b324cSopenharmony_ci  BaseExtension.Empty();
144370b324cSopenharmony_ci}
145370b324cSopenharmony_ci
146370b324cSopenharmony_ciUString CArchivePath::GetFinalPath() const
147370b324cSopenharmony_ci{
148370b324cSopenharmony_ci  UString path = GetPathWithoutExt();
149370b324cSopenharmony_ci  if (!BaseExtension.IsEmpty())
150370b324cSopenharmony_ci  {
151370b324cSopenharmony_ci    path.Add_Dot();
152370b324cSopenharmony_ci    path += BaseExtension;
153370b324cSopenharmony_ci  }
154370b324cSopenharmony_ci  return path;
155370b324cSopenharmony_ci}
156370b324cSopenharmony_ci
157370b324cSopenharmony_ciUString CArchivePath::GetFinalVolPath() const
158370b324cSopenharmony_ci{
159370b324cSopenharmony_ci  UString path = GetPathWithoutExt();
160370b324cSopenharmony_ci  // if BaseExtension is empty, we must ignore VolExtension also.
161370b324cSopenharmony_ci  if (!BaseExtension.IsEmpty())
162370b324cSopenharmony_ci  {
163370b324cSopenharmony_ci    path.Add_Dot();
164370b324cSopenharmony_ci    path += VolExtension;
165370b324cSopenharmony_ci  }
166370b324cSopenharmony_ci  return path;
167370b324cSopenharmony_ci}
168370b324cSopenharmony_ci
169370b324cSopenharmony_ciFString CArchivePath::GetTempPath() const
170370b324cSopenharmony_ci{
171370b324cSopenharmony_ci  FString path = TempPrefix;
172370b324cSopenharmony_ci  path += us2fs(Name);
173370b324cSopenharmony_ci  if (!BaseExtension.IsEmpty())
174370b324cSopenharmony_ci  {
175370b324cSopenharmony_ci    path.Add_Dot();
176370b324cSopenharmony_ci    path += us2fs(BaseExtension);
177370b324cSopenharmony_ci  }
178370b324cSopenharmony_ci  path += ".tmp";
179370b324cSopenharmony_ci  path += TempPostfix;
180370b324cSopenharmony_ci  return path;
181370b324cSopenharmony_ci}
182370b324cSopenharmony_ci
183370b324cSopenharmony_cistatic const char * const kDefaultArcType = "7z";
184370b324cSopenharmony_cistatic const char * const kDefaultArcExt = "7z";
185370b324cSopenharmony_cistatic const char * const kSFXExtension =
186370b324cSopenharmony_ci  #ifdef _WIN32
187370b324cSopenharmony_ci    "exe";
188370b324cSopenharmony_ci  #else
189370b324cSopenharmony_ci    "";
190370b324cSopenharmony_ci  #endif
191370b324cSopenharmony_ci
192370b324cSopenharmony_cibool CUpdateOptions::InitFormatIndex(const CCodecs *codecs,
193370b324cSopenharmony_ci    const CObjectVector<COpenType> &types, const UString &arcPath)
194370b324cSopenharmony_ci{
195370b324cSopenharmony_ci  if (types.Size() > 1)
196370b324cSopenharmony_ci    return false;
197370b324cSopenharmony_ci  // int arcTypeIndex = -1;
198370b324cSopenharmony_ci  if (types.Size() != 0)
199370b324cSopenharmony_ci  {
200370b324cSopenharmony_ci    MethodMode.Type = types[0];
201370b324cSopenharmony_ci    MethodMode.Type_Defined = true;
202370b324cSopenharmony_ci  }
203370b324cSopenharmony_ci  if (MethodMode.Type.FormatIndex < 0)
204370b324cSopenharmony_ci  {
205370b324cSopenharmony_ci    // MethodMode.Type = -1;
206370b324cSopenharmony_ci    MethodMode.Type = COpenType();
207370b324cSopenharmony_ci    if (ArcNameMode != k_ArcNameMode_Add)
208370b324cSopenharmony_ci    {
209370b324cSopenharmony_ci      MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveName(arcPath);
210370b324cSopenharmony_ci      if (MethodMode.Type.FormatIndex >= 0)
211370b324cSopenharmony_ci        MethodMode.Type_Defined = true;
212370b324cSopenharmony_ci    }
213370b324cSopenharmony_ci  }
214370b324cSopenharmony_ci  return true;
215370b324cSopenharmony_ci}
216370b324cSopenharmony_ci
217370b324cSopenharmony_cibool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath)
218370b324cSopenharmony_ci{
219370b324cSopenharmony_ci  UString typeExt;
220370b324cSopenharmony_ci  int formatIndex = MethodMode.Type.FormatIndex;
221370b324cSopenharmony_ci  if (formatIndex < 0)
222370b324cSopenharmony_ci  {
223370b324cSopenharmony_ci    typeExt = kDefaultArcExt;
224370b324cSopenharmony_ci  }
225370b324cSopenharmony_ci  else
226370b324cSopenharmony_ci  {
227370b324cSopenharmony_ci    const CArcInfoEx &arcInfo = codecs->Formats[(unsigned)formatIndex];
228370b324cSopenharmony_ci    if (!arcInfo.UpdateEnabled)
229370b324cSopenharmony_ci      return false;
230370b324cSopenharmony_ci    typeExt = arcInfo.GetMainExt();
231370b324cSopenharmony_ci  }
232370b324cSopenharmony_ci  UString ext = typeExt;
233370b324cSopenharmony_ci  if (SfxMode)
234370b324cSopenharmony_ci    ext = kSFXExtension;
235370b324cSopenharmony_ci  ArchivePath.BaseExtension = ext;
236370b324cSopenharmony_ci  ArchivePath.VolExtension = typeExt;
237370b324cSopenharmony_ci  ArchivePath.ParseFromPath(arcPath, ArcNameMode);
238370b324cSopenharmony_ci  FOR_VECTOR (i, Commands)
239370b324cSopenharmony_ci  {
240370b324cSopenharmony_ci    CUpdateArchiveCommand &uc = Commands[i];
241370b324cSopenharmony_ci    uc.ArchivePath.BaseExtension = ext;
242370b324cSopenharmony_ci    uc.ArchivePath.VolExtension = typeExt;
243370b324cSopenharmony_ci    uc.ArchivePath.ParseFromPath(uc.UserArchivePath, ArcNameMode);
244370b324cSopenharmony_ci  }
245370b324cSopenharmony_ci  return true;
246370b324cSopenharmony_ci}
247370b324cSopenharmony_ci
248370b324cSopenharmony_ci
249370b324cSopenharmony_cistruct CUpdateProduceCallbackImp Z7_final: public IUpdateProduceCallback
250370b324cSopenharmony_ci{
251370b324cSopenharmony_ci  const CObjectVector<CArcItem> *_arcItems;
252370b324cSopenharmony_ci  CDirItemsStat *_stat;
253370b324cSopenharmony_ci  IUpdateCallbackUI *_callback;
254370b324cSopenharmony_ci
255370b324cSopenharmony_ci  CUpdateProduceCallbackImp(
256370b324cSopenharmony_ci      const CObjectVector<CArcItem> *a,
257370b324cSopenharmony_ci      CDirItemsStat *stat,
258370b324cSopenharmony_ci      IUpdateCallbackUI *callback):
259370b324cSopenharmony_ci    _arcItems(a),
260370b324cSopenharmony_ci    _stat(stat),
261370b324cSopenharmony_ci    _callback(callback) {}
262370b324cSopenharmony_ci
263370b324cSopenharmony_ci  virtual HRESULT ShowDeleteFile(unsigned arcIndex) Z7_override;
264370b324cSopenharmony_ci};
265370b324cSopenharmony_ci
266370b324cSopenharmony_ci
267370b324cSopenharmony_ciHRESULT CUpdateProduceCallbackImp::ShowDeleteFile(unsigned arcIndex)
268370b324cSopenharmony_ci{
269370b324cSopenharmony_ci  const CArcItem &ai = (*_arcItems)[arcIndex];
270370b324cSopenharmony_ci  {
271370b324cSopenharmony_ci    CDirItemsStat &stat = *_stat;
272370b324cSopenharmony_ci    if (ai.IsDir)
273370b324cSopenharmony_ci      stat.NumDirs++;
274370b324cSopenharmony_ci    else if (ai.IsAltStream)
275370b324cSopenharmony_ci    {
276370b324cSopenharmony_ci      stat.NumAltStreams++;
277370b324cSopenharmony_ci      stat.AltStreamsSize += ai.Size;
278370b324cSopenharmony_ci    }
279370b324cSopenharmony_ci    else
280370b324cSopenharmony_ci    {
281370b324cSopenharmony_ci      stat.NumFiles++;
282370b324cSopenharmony_ci      stat.FilesSize += ai.Size;
283370b324cSopenharmony_ci    }
284370b324cSopenharmony_ci  }
285370b324cSopenharmony_ci  return _callback->ShowDeleteFile(ai.Name, ai.IsDir);
286370b324cSopenharmony_ci}
287370b324cSopenharmony_ci
288370b324cSopenharmony_cibool CRenamePair::Prepare()
289370b324cSopenharmony_ci{
290370b324cSopenharmony_ci  if (RecursedType != NRecursedType::kNonRecursed)
291370b324cSopenharmony_ci    return false;
292370b324cSopenharmony_ci  if (!WildcardParsing)
293370b324cSopenharmony_ci    return true;
294370b324cSopenharmony_ci  return !DoesNameContainWildcard(OldName);
295370b324cSopenharmony_ci}
296370b324cSopenharmony_ci
297370b324cSopenharmony_ciextern bool g_CaseSensitive;
298370b324cSopenharmony_ci
299370b324cSopenharmony_cistatic unsigned CompareTwoNames(const wchar_t *s1, const wchar_t *s2)
300370b324cSopenharmony_ci{
301370b324cSopenharmony_ci  for (unsigned i = 0;; i++)
302370b324cSopenharmony_ci  {
303370b324cSopenharmony_ci    wchar_t c1 = s1[i];
304370b324cSopenharmony_ci    wchar_t c2 = s2[i];
305370b324cSopenharmony_ci    if (c1 == 0 || c2 == 0)
306370b324cSopenharmony_ci      return i;
307370b324cSopenharmony_ci    if (c1 == c2)
308370b324cSopenharmony_ci      continue;
309370b324cSopenharmony_ci    if (!g_CaseSensitive && (MyCharUpper(c1) == MyCharUpper(c2)))
310370b324cSopenharmony_ci      continue;
311370b324cSopenharmony_ci    if (IsPathSepar(c1) && IsPathSepar(c2))
312370b324cSopenharmony_ci      continue;
313370b324cSopenharmony_ci    return i;
314370b324cSopenharmony_ci  }
315370b324cSopenharmony_ci}
316370b324cSopenharmony_ci
317370b324cSopenharmony_cibool CRenamePair::GetNewPath(bool isFolder, const UString &src, UString &dest) const
318370b324cSopenharmony_ci{
319370b324cSopenharmony_ci  unsigned num = CompareTwoNames(OldName, src);
320370b324cSopenharmony_ci  if (OldName[num] == 0)
321370b324cSopenharmony_ci  {
322370b324cSopenharmony_ci    if (src[num] != 0 && !IsPathSepar(src[num]) && num != 0 && !IsPathSepar(src[num - 1]))
323370b324cSopenharmony_ci      return false;
324370b324cSopenharmony_ci  }
325370b324cSopenharmony_ci  else
326370b324cSopenharmony_ci  {
327370b324cSopenharmony_ci    // OldName[num] != 0
328370b324cSopenharmony_ci    // OldName = "1\1a.txt"
329370b324cSopenharmony_ci    // src = "1"
330370b324cSopenharmony_ci
331370b324cSopenharmony_ci    if (!isFolder
332370b324cSopenharmony_ci        || src[num] != 0
333370b324cSopenharmony_ci        || !IsPathSepar(OldName[num])
334370b324cSopenharmony_ci        || OldName[num + 1] != 0)
335370b324cSopenharmony_ci      return false;
336370b324cSopenharmony_ci  }
337370b324cSopenharmony_ci  dest = NewName + src.Ptr(num);
338370b324cSopenharmony_ci  return true;
339370b324cSopenharmony_ci}
340370b324cSopenharmony_ci
341370b324cSopenharmony_ci#ifdef SUPPORT_ALT_STREAMS
342370b324cSopenharmony_ciint FindAltStreamColon_in_Path(const wchar_t *path);
343370b324cSopenharmony_ci#endif
344370b324cSopenharmony_ci
345370b324cSopenharmony_ci
346370b324cSopenharmony_ci
347370b324cSopenharmony_cistatic HRESULT Compress(
348370b324cSopenharmony_ci    const CUpdateOptions &options,
349370b324cSopenharmony_ci    bool isUpdatingItself,
350370b324cSopenharmony_ci    CCodecs *codecs,
351370b324cSopenharmony_ci    const CActionSet &actionSet,
352370b324cSopenharmony_ci    const CArc *arc,
353370b324cSopenharmony_ci    CArchivePath &archivePath,
354370b324cSopenharmony_ci    const CObjectVector<CArcItem> &arcItems,
355370b324cSopenharmony_ci    Byte *processedItemsStatuses,
356370b324cSopenharmony_ci    const CDirItems &dirItems,
357370b324cSopenharmony_ci    const CDirItem *parentDirItem,
358370b324cSopenharmony_ci    CTempFiles &tempFiles,
359370b324cSopenharmony_ci    CMultiOutStream_Bunch &multiStreams,
360370b324cSopenharmony_ci    CUpdateErrorInfo &errorInfo,
361370b324cSopenharmony_ci    IUpdateCallbackUI *callback,
362370b324cSopenharmony_ci    CFinishArchiveStat &st)
363370b324cSopenharmony_ci{
364370b324cSopenharmony_ci  CMyComPtr<IOutArchive> outArchive;
365370b324cSopenharmony_ci  int formatIndex = options.MethodMode.Type.FormatIndex;
366370b324cSopenharmony_ci
367370b324cSopenharmony_ci  if (arc)
368370b324cSopenharmony_ci  {
369370b324cSopenharmony_ci    formatIndex = arc->FormatIndex;
370370b324cSopenharmony_ci    if (formatIndex < 0)
371370b324cSopenharmony_ci      return E_NOTIMPL;
372370b324cSopenharmony_ci    CMyComPtr<IInArchive> archive2 = arc->Archive;
373370b324cSopenharmony_ci    HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);
374370b324cSopenharmony_ci    if (result != S_OK)
375370b324cSopenharmony_ci      throw kUpdateIsNotSupoorted;
376370b324cSopenharmony_ci  }
377370b324cSopenharmony_ci  else
378370b324cSopenharmony_ci  {
379370b324cSopenharmony_ci    RINOK(codecs->CreateOutArchive((unsigned)formatIndex, outArchive))
380370b324cSopenharmony_ci
381370b324cSopenharmony_ci    #ifdef Z7_EXTERNAL_CODECS
382370b324cSopenharmony_ci    {
383370b324cSopenharmony_ci      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
384370b324cSopenharmony_ci      outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
385370b324cSopenharmony_ci      if (setCompressCodecsInfo)
386370b324cSopenharmony_ci      {
387370b324cSopenharmony_ci        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs))
388370b324cSopenharmony_ci      }
389370b324cSopenharmony_ci    }
390370b324cSopenharmony_ci    #endif
391370b324cSopenharmony_ci  }
392370b324cSopenharmony_ci
393370b324cSopenharmony_ci  if (!outArchive)
394370b324cSopenharmony_ci    throw kUpdateIsNotSupoorted;
395370b324cSopenharmony_ci
396370b324cSopenharmony_ci  // we need to set properties to get fileTimeType.
397370b324cSopenharmony_ci  RINOK(SetProperties(outArchive, options.MethodMode.Properties))
398370b324cSopenharmony_ci
399370b324cSopenharmony_ci  NFileTimeType::EEnum fileTimeType;
400370b324cSopenharmony_ci  {
401370b324cSopenharmony_ci    /*
402370b324cSopenharmony_ci    how we compare file_in_archive::MTime with dirItem.MTime
403370b324cSopenharmony_ci    for GetUpdatePairInfoList():
404370b324cSopenharmony_ci
405370b324cSopenharmony_ci    if (kpidMTime is not defined), external MTime of archive is used.
406370b324cSopenharmony_ci
407370b324cSopenharmony_ci    before 22.00:
408370b324cSopenharmony_ci      if (kpidTimeType is defined)
409370b324cSopenharmony_ci      {
410370b324cSopenharmony_ci        kpidTimeType is used as precision.
411370b324cSopenharmony_ci        (kpidTimeType > kDOS) is not allowed.
412370b324cSopenharmony_ci      }
413370b324cSopenharmony_ci      else GetFileTimeType() value is used as precision.
414370b324cSopenharmony_ci
415370b324cSopenharmony_ci    22.00:
416370b324cSopenharmony_ci      if (kpidMTime is defined)
417370b324cSopenharmony_ci      {
418370b324cSopenharmony_ci        if (kpidMTime::precision != 0), then kpidMTime::precision is used as precision.
419370b324cSopenharmony_ci        else
420370b324cSopenharmony_ci        {
421370b324cSopenharmony_ci          if (kpidTimeType is defined), kpidTimeType is used as precision.
422370b324cSopenharmony_ci          else GetFileTimeType() value is used as precision.
423370b324cSopenharmony_ci        }
424370b324cSopenharmony_ci      }
425370b324cSopenharmony_ci      else external MTime of archive is used as precision.
426370b324cSopenharmony_ci    */
427370b324cSopenharmony_ci
428370b324cSopenharmony_ci    UInt32 value;
429370b324cSopenharmony_ci    RINOK(outArchive->GetFileTimeType(&value))
430370b324cSopenharmony_ci
431370b324cSopenharmony_ci    // we support any future fileType here.
432370b324cSopenharmony_ci    fileTimeType = (NFileTimeType::EEnum)value;
433370b324cSopenharmony_ci
434370b324cSopenharmony_ci    /*
435370b324cSopenharmony_ci    old 21.07 code:
436370b324cSopenharmony_ci    switch (value)
437370b324cSopenharmony_ci    {
438370b324cSopenharmony_ci      case NFileTimeType::kWindows:
439370b324cSopenharmony_ci      case NFileTimeType::kUnix:
440370b324cSopenharmony_ci      case NFileTimeType::kDOS:
441370b324cSopenharmony_ci        fileTimeType = (NFileTimeType::EEnum)value;
442370b324cSopenharmony_ci        break;
443370b324cSopenharmony_ci      default:
444370b324cSopenharmony_ci        return E_FAIL;
445370b324cSopenharmony_ci    }
446370b324cSopenharmony_ci    */
447370b324cSopenharmony_ci  }
448370b324cSopenharmony_ci
449370b324cSopenharmony_ci  // bool noTimestampExpected = false;
450370b324cSopenharmony_ci  {
451370b324cSopenharmony_ci    const CArcInfoEx &arcInfo = codecs->Formats[(unsigned)formatIndex];
452370b324cSopenharmony_ci
453370b324cSopenharmony_ci    // if (arcInfo.Flags_KeepName()) noTimestampExpected = true;
454370b324cSopenharmony_ci    if (arcInfo.Is_Xz() ||
455370b324cSopenharmony_ci        arcInfo.Is_BZip2())
456370b324cSopenharmony_ci    {
457370b324cSopenharmony_ci      /* 7-zip before 22.00 returns NFileTimeType::kUnix for xz and bzip2,
458370b324cSopenharmony_ci         but we want to set timestamp without reduction to unix. */
459370b324cSopenharmony_ci      // noTimestampExpected = true;
460370b324cSopenharmony_ci      fileTimeType = NFileTimeType::kNotDefined; // it means not defined
461370b324cSopenharmony_ci    }
462370b324cSopenharmony_ci
463370b324cSopenharmony_ci    if (options.AltStreams.Val && !arcInfo.Flags_AltStreams())
464370b324cSopenharmony_ci      return E_NOTIMPL;
465370b324cSopenharmony_ci    if (options.NtSecurity.Val && !arcInfo.Flags_NtSecurity())
466370b324cSopenharmony_ci      return E_NOTIMPL;
467370b324cSopenharmony_ci    if (options.DeleteAfterCompressing && arcInfo.Flags_HashHandler())
468370b324cSopenharmony_ci      return E_NOTIMPL;
469370b324cSopenharmony_ci  }
470370b324cSopenharmony_ci
471370b324cSopenharmony_ci  CRecordVector<CUpdatePair2> updatePairs2;
472370b324cSopenharmony_ci
473370b324cSopenharmony_ci  UStringVector newNames;
474370b324cSopenharmony_ci
475370b324cSopenharmony_ci  CArcToDoStat stat2;
476370b324cSopenharmony_ci
477370b324cSopenharmony_ci  if (options.RenamePairs.Size() != 0)
478370b324cSopenharmony_ci  {
479370b324cSopenharmony_ci    FOR_VECTOR (i, arcItems)
480370b324cSopenharmony_ci    {
481370b324cSopenharmony_ci      const CArcItem &ai = arcItems[i];
482370b324cSopenharmony_ci      bool needRename = false;
483370b324cSopenharmony_ci      UString dest;
484370b324cSopenharmony_ci
485370b324cSopenharmony_ci      if (ai.Censored)
486370b324cSopenharmony_ci      {
487370b324cSopenharmony_ci        FOR_VECTOR (j, options.RenamePairs)
488370b324cSopenharmony_ci        {
489370b324cSopenharmony_ci          const CRenamePair &rp = options.RenamePairs[j];
490370b324cSopenharmony_ci          if (rp.GetNewPath(ai.IsDir, ai.Name, dest))
491370b324cSopenharmony_ci          {
492370b324cSopenharmony_ci            needRename = true;
493370b324cSopenharmony_ci            break;
494370b324cSopenharmony_ci          }
495370b324cSopenharmony_ci
496370b324cSopenharmony_ci          #ifdef SUPPORT_ALT_STREAMS
497370b324cSopenharmony_ci          if (ai.IsAltStream)
498370b324cSopenharmony_ci          {
499370b324cSopenharmony_ci            int colonPos = FindAltStreamColon_in_Path(ai.Name);
500370b324cSopenharmony_ci            if (colonPos >= 0)
501370b324cSopenharmony_ci            {
502370b324cSopenharmony_ci              UString mainName = ai.Name.Left((unsigned)colonPos);
503370b324cSopenharmony_ci              /*
504370b324cSopenharmony_ci              actually we must improve that code to support cases
505370b324cSopenharmony_ci              with folder renaming like: rn arc dir1\ dir2\
506370b324cSopenharmony_ci              */
507370b324cSopenharmony_ci              if (rp.GetNewPath(false, mainName, dest))
508370b324cSopenharmony_ci              {
509370b324cSopenharmony_ci                needRename = true;
510370b324cSopenharmony_ci                dest += ':';
511370b324cSopenharmony_ci                dest += ai.Name.Ptr((unsigned)(colonPos + 1));
512370b324cSopenharmony_ci                break;
513370b324cSopenharmony_ci              }
514370b324cSopenharmony_ci            }
515370b324cSopenharmony_ci          }
516370b324cSopenharmony_ci          #endif
517370b324cSopenharmony_ci        }
518370b324cSopenharmony_ci      }
519370b324cSopenharmony_ci
520370b324cSopenharmony_ci      CUpdatePair2 up2;
521370b324cSopenharmony_ci      up2.SetAs_NoChangeArcItem(ai.IndexInServer);
522370b324cSopenharmony_ci      if (needRename)
523370b324cSopenharmony_ci      {
524370b324cSopenharmony_ci        up2.NewProps = true;
525370b324cSopenharmony_ci        RINOK(arc->IsItem_Anti(i, up2.IsAnti))
526370b324cSopenharmony_ci        up2.NewNameIndex = (int)newNames.Add(dest);
527370b324cSopenharmony_ci      }
528370b324cSopenharmony_ci      updatePairs2.Add(up2);
529370b324cSopenharmony_ci    }
530370b324cSopenharmony_ci  }
531370b324cSopenharmony_ci  else
532370b324cSopenharmony_ci  {
533370b324cSopenharmony_ci    CRecordVector<CUpdatePair> updatePairs;
534370b324cSopenharmony_ci    GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!!
535370b324cSopenharmony_ci    CUpdateProduceCallbackImp upCallback(&arcItems, &stat2.DeleteData, callback);
536370b324cSopenharmony_ci
537370b324cSopenharmony_ci    UpdateProduce(updatePairs, actionSet, updatePairs2, isUpdatingItself ? &upCallback : NULL);
538370b324cSopenharmony_ci  }
539370b324cSopenharmony_ci
540370b324cSopenharmony_ci  {
541370b324cSopenharmony_ci    FOR_VECTOR (i, updatePairs2)
542370b324cSopenharmony_ci    {
543370b324cSopenharmony_ci      const CUpdatePair2 &up = updatePairs2[i];
544370b324cSopenharmony_ci
545370b324cSopenharmony_ci      // 17.01: anti-item is (up.NewData && (p.UseArcProps in most cases))
546370b324cSopenharmony_ci
547370b324cSopenharmony_ci      if (up.NewData && !up.UseArcProps)
548370b324cSopenharmony_ci      {
549370b324cSopenharmony_ci        if (up.ExistOnDisk())
550370b324cSopenharmony_ci        {
551370b324cSopenharmony_ci          CDirItemsStat2 &stat = stat2.NewData;
552370b324cSopenharmony_ci          const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex];
553370b324cSopenharmony_ci          if (di.IsDir())
554370b324cSopenharmony_ci          {
555370b324cSopenharmony_ci            if (up.IsAnti)
556370b324cSopenharmony_ci              stat.Anti_NumDirs++;
557370b324cSopenharmony_ci            else
558370b324cSopenharmony_ci              stat.NumDirs++;
559370b324cSopenharmony_ci          }
560370b324cSopenharmony_ci         #ifdef _WIN32
561370b324cSopenharmony_ci          else if (di.IsAltStream)
562370b324cSopenharmony_ci          {
563370b324cSopenharmony_ci            if (up.IsAnti)
564370b324cSopenharmony_ci              stat.Anti_NumAltStreams++;
565370b324cSopenharmony_ci            else
566370b324cSopenharmony_ci            {
567370b324cSopenharmony_ci              stat.NumAltStreams++;
568370b324cSopenharmony_ci              stat.AltStreamsSize += di.Size;
569370b324cSopenharmony_ci            }
570370b324cSopenharmony_ci          }
571370b324cSopenharmony_ci         #endif
572370b324cSopenharmony_ci          else
573370b324cSopenharmony_ci          {
574370b324cSopenharmony_ci            if (up.IsAnti)
575370b324cSopenharmony_ci              stat.Anti_NumFiles++;
576370b324cSopenharmony_ci            else
577370b324cSopenharmony_ci            {
578370b324cSopenharmony_ci              stat.NumFiles++;
579370b324cSopenharmony_ci              stat.FilesSize += di.Size;
580370b324cSopenharmony_ci            }
581370b324cSopenharmony_ci          }
582370b324cSopenharmony_ci        }
583370b324cSopenharmony_ci      }
584370b324cSopenharmony_ci      else if (up.ArcIndex >= 0)
585370b324cSopenharmony_ci      {
586370b324cSopenharmony_ci        CDirItemsStat2 &stat = *(up.NewData ? &stat2.NewData : &stat2.OldData);
587370b324cSopenharmony_ci        const CArcItem &ai = arcItems[(unsigned)up.ArcIndex];
588370b324cSopenharmony_ci        if (ai.IsDir)
589370b324cSopenharmony_ci        {
590370b324cSopenharmony_ci          if (up.IsAnti)
591370b324cSopenharmony_ci            stat.Anti_NumDirs++;
592370b324cSopenharmony_ci          else
593370b324cSopenharmony_ci            stat.NumDirs++;
594370b324cSopenharmony_ci        }
595370b324cSopenharmony_ci        else if (ai.IsAltStream)
596370b324cSopenharmony_ci        {
597370b324cSopenharmony_ci          if (up.IsAnti)
598370b324cSopenharmony_ci            stat.Anti_NumAltStreams++;
599370b324cSopenharmony_ci          else
600370b324cSopenharmony_ci          {
601370b324cSopenharmony_ci            stat.NumAltStreams++;
602370b324cSopenharmony_ci            stat.AltStreamsSize += ai.Size;
603370b324cSopenharmony_ci          }
604370b324cSopenharmony_ci        }
605370b324cSopenharmony_ci        else
606370b324cSopenharmony_ci        {
607370b324cSopenharmony_ci          if (up.IsAnti)
608370b324cSopenharmony_ci            stat.Anti_NumFiles++;
609370b324cSopenharmony_ci          else
610370b324cSopenharmony_ci          {
611370b324cSopenharmony_ci            stat.NumFiles++;
612370b324cSopenharmony_ci            stat.FilesSize += ai.Size;
613370b324cSopenharmony_ci          }
614370b324cSopenharmony_ci        }
615370b324cSopenharmony_ci      }
616370b324cSopenharmony_ci    }
617370b324cSopenharmony_ci    RINOK(callback->SetNumItems(stat2))
618370b324cSopenharmony_ci  }
619370b324cSopenharmony_ci
620370b324cSopenharmony_ci  CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
621370b324cSopenharmony_ci  CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
622370b324cSopenharmony_ci
623370b324cSopenharmony_ci  updateCallbackSpec->PreserveATime = options.PreserveATime;
624370b324cSopenharmony_ci  updateCallbackSpec->ShareForWrite = options.OpenShareForWrite;
625370b324cSopenharmony_ci  updateCallbackSpec->StopAfterOpenError = options.StopAfterOpenError;
626370b324cSopenharmony_ci  updateCallbackSpec->StdInMode = options.StdInMode;
627370b324cSopenharmony_ci  updateCallbackSpec->Callback = callback;
628370b324cSopenharmony_ci
629370b324cSopenharmony_ci  if (arc)
630370b324cSopenharmony_ci  {
631370b324cSopenharmony_ci    // we set Archive to allow to transfer GetProperty requests back to DLL.
632370b324cSopenharmony_ci    updateCallbackSpec->Archive = arc->Archive;
633370b324cSopenharmony_ci  }
634370b324cSopenharmony_ci
635370b324cSopenharmony_ci  updateCallbackSpec->DirItems = &dirItems;
636370b324cSopenharmony_ci  updateCallbackSpec->ParentDirItem = parentDirItem;
637370b324cSopenharmony_ci
638370b324cSopenharmony_ci  updateCallbackSpec->StoreNtSecurity = options.NtSecurity.Val;
639370b324cSopenharmony_ci  updateCallbackSpec->StoreHardLinks = options.HardLinks.Val;
640370b324cSopenharmony_ci  updateCallbackSpec->StoreSymLinks = options.SymLinks.Val;
641370b324cSopenharmony_ci  updateCallbackSpec->StoreOwnerName = options.StoreOwnerName.Val;
642370b324cSopenharmony_ci  updateCallbackSpec->StoreOwnerId = options.StoreOwnerId.Val;
643370b324cSopenharmony_ci
644370b324cSopenharmony_ci  updateCallbackSpec->Arc = arc;
645370b324cSopenharmony_ci  updateCallbackSpec->ArcItems = &arcItems;
646370b324cSopenharmony_ci  updateCallbackSpec->UpdatePairs = &updatePairs2;
647370b324cSopenharmony_ci
648370b324cSopenharmony_ci  updateCallbackSpec->ProcessedItemsStatuses = processedItemsStatuses;
649370b324cSopenharmony_ci
650370b324cSopenharmony_ci  {
651370b324cSopenharmony_ci    const UString arcPath = archivePath.GetFinalPath();
652370b324cSopenharmony_ci    updateCallbackSpec->ArcFileName = ExtractFileNameFromPath(arcPath);
653370b324cSopenharmony_ci  }
654370b324cSopenharmony_ci
655370b324cSopenharmony_ci  if (options.RenamePairs.Size() != 0)
656370b324cSopenharmony_ci    updateCallbackSpec->NewNames = &newNames;
657370b324cSopenharmony_ci
658370b324cSopenharmony_ci  if (options.SetArcMTime)
659370b324cSopenharmony_ci  {
660370b324cSopenharmony_ci    // updateCallbackSpec->Need_ArcMTime_Report = true;
661370b324cSopenharmony_ci    updateCallbackSpec->Need_LatestMTime = true;
662370b324cSopenharmony_ci  }
663370b324cSopenharmony_ci
664370b324cSopenharmony_ci  CMyComPtr<IOutStream> outSeekStream;
665370b324cSopenharmony_ci  CMyComPtr<ISequentialOutStream> outStream;
666370b324cSopenharmony_ci
667370b324cSopenharmony_ci  if (!options.StdOutMode)
668370b324cSopenharmony_ci  {
669370b324cSopenharmony_ci    FString dirPrefix;
670370b324cSopenharmony_ci    if (!GetOnlyDirPrefix(us2fs(archivePath.GetFinalPath()), dirPrefix))
671370b324cSopenharmony_ci      throw 1417161;
672370b324cSopenharmony_ci    CreateComplexDir(dirPrefix);
673370b324cSopenharmony_ci  }
674370b324cSopenharmony_ci
675370b324cSopenharmony_ci  COutFileStream *outStreamSpec = NULL;
676370b324cSopenharmony_ci  CStdOutFileStream *stdOutFileStreamSpec = NULL;
677370b324cSopenharmony_ci  CMultiOutStream *volStreamSpec = NULL;
678370b324cSopenharmony_ci
679370b324cSopenharmony_ci  if (options.VolumesSizes.Size() == 0)
680370b324cSopenharmony_ci  {
681370b324cSopenharmony_ci    if (options.StdOutMode)
682370b324cSopenharmony_ci    {
683370b324cSopenharmony_ci      stdOutFileStreamSpec = new CStdOutFileStream;
684370b324cSopenharmony_ci      outStream = stdOutFileStreamSpec;
685370b324cSopenharmony_ci    }
686370b324cSopenharmony_ci    else
687370b324cSopenharmony_ci    {
688370b324cSopenharmony_ci      outStreamSpec = new COutFileStream;
689370b324cSopenharmony_ci      outSeekStream = outStreamSpec;
690370b324cSopenharmony_ci      outStream = outSeekStream;
691370b324cSopenharmony_ci      bool isOK = false;
692370b324cSopenharmony_ci      FString realPath;
693370b324cSopenharmony_ci
694370b324cSopenharmony_ci      for (unsigned i = 0; i < (1 << 16); i++)
695370b324cSopenharmony_ci      {
696370b324cSopenharmony_ci        if (archivePath.Temp)
697370b324cSopenharmony_ci        {
698370b324cSopenharmony_ci          if (i > 0)
699370b324cSopenharmony_ci          {
700370b324cSopenharmony_ci            archivePath.TempPostfix.Empty();
701370b324cSopenharmony_ci            archivePath.TempPostfix.Add_UInt32(i);
702370b324cSopenharmony_ci          }
703370b324cSopenharmony_ci          realPath = archivePath.GetTempPath();
704370b324cSopenharmony_ci        }
705370b324cSopenharmony_ci        else
706370b324cSopenharmony_ci          realPath = us2fs(archivePath.GetFinalPath());
707370b324cSopenharmony_ci        if (outStreamSpec->Create(realPath, false))
708370b324cSopenharmony_ci        {
709370b324cSopenharmony_ci          tempFiles.Paths.Add(realPath);
710370b324cSopenharmony_ci          isOK = true;
711370b324cSopenharmony_ci          break;
712370b324cSopenharmony_ci        }
713370b324cSopenharmony_ci        if (::GetLastError() != ERROR_FILE_EXISTS)
714370b324cSopenharmony_ci          break;
715370b324cSopenharmony_ci        if (!archivePath.Temp)
716370b324cSopenharmony_ci          break;
717370b324cSopenharmony_ci      }
718370b324cSopenharmony_ci
719370b324cSopenharmony_ci      if (!isOK)
720370b324cSopenharmony_ci        return errorInfo.SetFromLastError("cannot open file", realPath);
721370b324cSopenharmony_ci    }
722370b324cSopenharmony_ci  }
723370b324cSopenharmony_ci  else
724370b324cSopenharmony_ci  {
725370b324cSopenharmony_ci    if (options.StdOutMode)
726370b324cSopenharmony_ci      return E_FAIL;
727370b324cSopenharmony_ci    if (arc && arc->GetGlobalOffset() > 0)
728370b324cSopenharmony_ci      return E_NOTIMPL;
729370b324cSopenharmony_ci
730370b324cSopenharmony_ci    volStreamSpec = new CMultiOutStream();
731370b324cSopenharmony_ci    outSeekStream = volStreamSpec;
732370b324cSopenharmony_ci    outStream = outSeekStream;
733370b324cSopenharmony_ci    volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath());
734370b324cSopenharmony_ci    volStreamSpec->Prefix.Add_Dot();
735370b324cSopenharmony_ci    volStreamSpec->Init(options.VolumesSizes);
736370b324cSopenharmony_ci    {
737370b324cSopenharmony_ci      CMultiOutStream_Rec &rec = multiStreams.Items.AddNew();
738370b324cSopenharmony_ci      rec.Spec = volStreamSpec;
739370b324cSopenharmony_ci      rec.Ref = rec.Spec;
740370b324cSopenharmony_ci    }
741370b324cSopenharmony_ci
742370b324cSopenharmony_ci    /*
743370b324cSopenharmony_ci    updateCallbackSpec->VolumesSizes = volumesSizes;
744370b324cSopenharmony_ci    updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name;
745370b324cSopenharmony_ci    if (!archivePath.VolExtension.IsEmpty())
746370b324cSopenharmony_ci      updateCallbackSpec->VolExt = UString('.') + archivePath.VolExtension;
747370b324cSopenharmony_ci    */
748370b324cSopenharmony_ci  }
749370b324cSopenharmony_ci
750370b324cSopenharmony_ci  if (options.SfxMode)
751370b324cSopenharmony_ci  {
752370b324cSopenharmony_ci    CInFileStream *sfxStreamSpec = new CInFileStream;
753370b324cSopenharmony_ci    CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
754370b324cSopenharmony_ci    if (!sfxStreamSpec->Open(options.SfxModule))
755370b324cSopenharmony_ci      return errorInfo.SetFromLastError("cannot open SFX module", options.SfxModule);
756370b324cSopenharmony_ci
757370b324cSopenharmony_ci    CMyComPtr<ISequentialOutStream> sfxOutStream;
758370b324cSopenharmony_ci    COutFileStream *outStreamSpec2 = NULL;
759370b324cSopenharmony_ci    if (options.VolumesSizes.Size() == 0)
760370b324cSopenharmony_ci      sfxOutStream = outStream;
761370b324cSopenharmony_ci    else
762370b324cSopenharmony_ci    {
763370b324cSopenharmony_ci      outStreamSpec2 = new COutFileStream;
764370b324cSopenharmony_ci      sfxOutStream = outStreamSpec2;
765370b324cSopenharmony_ci      const FString realPath = us2fs(archivePath.GetFinalPath());
766370b324cSopenharmony_ci      if (!outStreamSpec2->Create(realPath, false))
767370b324cSopenharmony_ci        return errorInfo.SetFromLastError("cannot open file", realPath);
768370b324cSopenharmony_ci    }
769370b324cSopenharmony_ci
770370b324cSopenharmony_ci    {
771370b324cSopenharmony_ci      UInt64 sfxSize;
772370b324cSopenharmony_ci      RINOK(sfxStreamSpec->GetSize(&sfxSize))
773370b324cSopenharmony_ci      RINOK(callback->WriteSfx(fs2us(options.SfxModule), sfxSize))
774370b324cSopenharmony_ci    }
775370b324cSopenharmony_ci
776370b324cSopenharmony_ci    RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL))
777370b324cSopenharmony_ci
778370b324cSopenharmony_ci    if (outStreamSpec2)
779370b324cSopenharmony_ci    {
780370b324cSopenharmony_ci      RINOK(outStreamSpec2->Close())
781370b324cSopenharmony_ci    }
782370b324cSopenharmony_ci  }
783370b324cSopenharmony_ci
784370b324cSopenharmony_ci  CMyComPtr<ISequentialOutStream> tailStream;
785370b324cSopenharmony_ci
786370b324cSopenharmony_ci  if (options.SfxMode || !arc || arc->ArcStreamOffset == 0)
787370b324cSopenharmony_ci    tailStream = outStream;
788370b324cSopenharmony_ci  else
789370b324cSopenharmony_ci  {
790370b324cSopenharmony_ci    // Int64 globalOffset = arc->GetGlobalOffset();
791370b324cSopenharmony_ci    RINOK(InStream_SeekToBegin(arc->InStream))
792370b324cSopenharmony_ci    RINOK(NCompress::CopyStream_ExactSize(arc->InStream, outStream, arc->ArcStreamOffset, NULL))
793370b324cSopenharmony_ci    if (options.StdOutMode)
794370b324cSopenharmony_ci      tailStream = outStream;
795370b324cSopenharmony_ci    else
796370b324cSopenharmony_ci    {
797370b324cSopenharmony_ci      CTailOutStream *tailStreamSpec = new CTailOutStream;
798370b324cSopenharmony_ci      tailStream = tailStreamSpec;
799370b324cSopenharmony_ci      tailStreamSpec->Stream = outSeekStream;
800370b324cSopenharmony_ci      tailStreamSpec->Offset = arc->ArcStreamOffset;
801370b324cSopenharmony_ci      tailStreamSpec->Init();
802370b324cSopenharmony_ci    }
803370b324cSopenharmony_ci  }
804370b324cSopenharmony_ci
805370b324cSopenharmony_ci  CFiTime ft;
806370b324cSopenharmony_ci  FiTime_Clear(ft);
807370b324cSopenharmony_ci  bool ft_Defined = false;
808370b324cSopenharmony_ci  {
809370b324cSopenharmony_ci    FOR_VECTOR (i, updatePairs2)
810370b324cSopenharmony_ci    {
811370b324cSopenharmony_ci      const CUpdatePair2 &pair2 = updatePairs2[i];
812370b324cSopenharmony_ci      CFiTime ft2;
813370b324cSopenharmony_ci      FiTime_Clear(ft2);
814370b324cSopenharmony_ci      bool ft2_Defined = false;
815370b324cSopenharmony_ci      /* we use full precision of dirItem, if dirItem is defined
816370b324cSopenharmony_ci         and (dirItem will be used or dirItem is sameTime in dir and arc */
817370b324cSopenharmony_ci      if (pair2.DirIndex >= 0 &&
818370b324cSopenharmony_ci          (pair2.NewProps || pair2.IsSameTime))
819370b324cSopenharmony_ci      {
820370b324cSopenharmony_ci        ft2 = dirItems.Items[(unsigned)pair2.DirIndex].MTime;
821370b324cSopenharmony_ci        ft2_Defined = true;
822370b324cSopenharmony_ci      }
823370b324cSopenharmony_ci      else if (pair2.UseArcProps && pair2.ArcIndex >= 0)
824370b324cSopenharmony_ci      {
825370b324cSopenharmony_ci        const CArcItem &arcItem = arcItems[(unsigned)pair2.ArcIndex];
826370b324cSopenharmony_ci        if (arcItem.MTime.Def)
827370b324cSopenharmony_ci        {
828370b324cSopenharmony_ci          arcItem.MTime.Write_To_FiTime(ft2);
829370b324cSopenharmony_ci          ft2_Defined = true;
830370b324cSopenharmony_ci        }
831370b324cSopenharmony_ci      }
832370b324cSopenharmony_ci      if (ft2_Defined)
833370b324cSopenharmony_ci      {
834370b324cSopenharmony_ci        if (!ft_Defined || Compare_FiTime(&ft, &ft2) < 0)
835370b324cSopenharmony_ci        {
836370b324cSopenharmony_ci          ft = ft2;
837370b324cSopenharmony_ci          ft_Defined = true;
838370b324cSopenharmony_ci        }
839370b324cSopenharmony_ci      }
840370b324cSopenharmony_ci    }
841370b324cSopenharmony_ci    /*
842370b324cSopenharmony_ci    if (fileTimeType != NFileTimeType::kNotDefined)
843370b324cSopenharmony_ci    FiTime_Normalize_With_Prec(ft, fileTimeType);
844370b324cSopenharmony_ci    */
845370b324cSopenharmony_ci  }
846370b324cSopenharmony_ci
847370b324cSopenharmony_ci  if (volStreamSpec && options.SetArcMTime && ft_Defined)
848370b324cSopenharmony_ci  {
849370b324cSopenharmony_ci    volStreamSpec->MTime = ft;
850370b324cSopenharmony_ci    volStreamSpec->MTime_Defined = true;
851370b324cSopenharmony_ci  }
852370b324cSopenharmony_ci
853370b324cSopenharmony_ci  HRESULT result = outArchive->UpdateItems(tailStream, updatePairs2.Size(), updateCallback);
854370b324cSopenharmony_ci  // callback->Finalize();
855370b324cSopenharmony_ci  RINOK(result)
856370b324cSopenharmony_ci
857370b324cSopenharmony_ci  if (!updateCallbackSpec->AreAllFilesClosed())
858370b324cSopenharmony_ci  {
859370b324cSopenharmony_ci    errorInfo.Message = "There are unclosed input file:";
860370b324cSopenharmony_ci    errorInfo.FileNames = updateCallbackSpec->_openFiles_Paths;
861370b324cSopenharmony_ci    return E_FAIL;
862370b324cSopenharmony_ci  }
863370b324cSopenharmony_ci
864370b324cSopenharmony_ci  if (options.SetArcMTime)
865370b324cSopenharmony_ci  {
866370b324cSopenharmony_ci    // bool needNormalizeAfterStream;
867370b324cSopenharmony_ci    // needParse;
868370b324cSopenharmony_ci    /*
869370b324cSopenharmony_ci    if (updateCallbackSpec->ArcMTime_WasReported)
870370b324cSopenharmony_ci    {
871370b324cSopenharmony_ci      isDefined = updateCallbackSpec->Reported_ArcMTime.Def;
872370b324cSopenharmony_ci      if (isDefined)
873370b324cSopenharmony_ci        updateCallbackSpec->Reported_ArcMTime.Write_To_FiTime(ft);
874370b324cSopenharmony_ci      else
875370b324cSopenharmony_ci        fileTimeType = NFileTimeType::kNotDefined;
876370b324cSopenharmony_ci    }
877370b324cSopenharmony_ci    if (!isDefined)
878370b324cSopenharmony_ci    */
879370b324cSopenharmony_ci    {
880370b324cSopenharmony_ci      if (updateCallbackSpec->LatestMTime_Defined)
881370b324cSopenharmony_ci      {
882370b324cSopenharmony_ci        // CArcTime at = StreamCallback_ArcMTime;
883370b324cSopenharmony_ci        // updateCallbackSpec->StreamCallback_ArcMTime.Write_To_FiTime(ft);
884370b324cSopenharmony_ci        // we must normalize with precision from archive;
885370b324cSopenharmony_ci        if (!ft_Defined || Compare_FiTime(&ft, &updateCallbackSpec->LatestMTime) < 0)
886370b324cSopenharmony_ci          ft = updateCallbackSpec->LatestMTime;
887370b324cSopenharmony_ci        ft_Defined = true;
888370b324cSopenharmony_ci      }
889370b324cSopenharmony_ci      /*
890370b324cSopenharmony_ci      if (fileTimeType != NFileTimeType::kNotDefined)
891370b324cSopenharmony_ci        FiTime_Normalize_With_Prec(ft, fileTimeType);
892370b324cSopenharmony_ci      */
893370b324cSopenharmony_ci    }
894370b324cSopenharmony_ci    // if (ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0)
895370b324cSopenharmony_ci    if (ft_Defined)
896370b324cSopenharmony_ci    {
897370b324cSopenharmony_ci      // we ignore set time errors here.
898370b324cSopenharmony_ci      // note that user could move some finished volumes to another folder.
899370b324cSopenharmony_ci      if (outStreamSpec)
900370b324cSopenharmony_ci        outStreamSpec->SetMTime(&ft);
901370b324cSopenharmony_ci      else if (volStreamSpec)
902370b324cSopenharmony_ci        volStreamSpec->SetMTime_Final(ft);
903370b324cSopenharmony_ci    }
904370b324cSopenharmony_ci  }
905370b324cSopenharmony_ci
906370b324cSopenharmony_ci  if (callback)
907370b324cSopenharmony_ci  {
908370b324cSopenharmony_ci    UInt64 size = 0;
909370b324cSopenharmony_ci    if (outStreamSpec)
910370b324cSopenharmony_ci      outStreamSpec->GetSize(&size);
911370b324cSopenharmony_ci    else if (stdOutFileStreamSpec)
912370b324cSopenharmony_ci      size = stdOutFileStreamSpec->GetSize();
913370b324cSopenharmony_ci    else
914370b324cSopenharmony_ci      size = volStreamSpec->GetSize();
915370b324cSopenharmony_ci
916370b324cSopenharmony_ci    st.OutArcFileSize = size;
917370b324cSopenharmony_ci  }
918370b324cSopenharmony_ci
919370b324cSopenharmony_ci  if (outStreamSpec)
920370b324cSopenharmony_ci    result = outStreamSpec->Close();
921370b324cSopenharmony_ci  else if (volStreamSpec)
922370b324cSopenharmony_ci  {
923370b324cSopenharmony_ci    result = volStreamSpec->FinalFlush_and_CloseFiles(st.NumVolumes);
924370b324cSopenharmony_ci    st.IsMultiVolMode = true;
925370b324cSopenharmony_ci  }
926370b324cSopenharmony_ci
927370b324cSopenharmony_ci  RINOK(result)
928370b324cSopenharmony_ci
929370b324cSopenharmony_ci  if (processedItemsStatuses)
930370b324cSopenharmony_ci  {
931370b324cSopenharmony_ci    FOR_VECTOR (i, updatePairs2)
932370b324cSopenharmony_ci    {
933370b324cSopenharmony_ci      const CUpdatePair2 &up = updatePairs2[i];
934370b324cSopenharmony_ci      if (up.NewData && up.DirIndex >= 0)
935370b324cSopenharmony_ci      {
936370b324cSopenharmony_ci        const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex];
937370b324cSopenharmony_ci        if (di.AreReparseData() || (!di.IsDir() && di.Size == 0))
938370b324cSopenharmony_ci          processedItemsStatuses[(unsigned)up.DirIndex] = 1;
939370b324cSopenharmony_ci      }
940370b324cSopenharmony_ci    }
941370b324cSopenharmony_ci  }
942370b324cSopenharmony_ci
943370b324cSopenharmony_ci  return result;
944370b324cSopenharmony_ci}
945370b324cSopenharmony_ci
946370b324cSopenharmony_ci
947370b324cSopenharmony_ci
948370b324cSopenharmony_cistatic bool Censor_AreAllAllowed(const NWildcard::CCensor &censor)
949370b324cSopenharmony_ci{
950370b324cSopenharmony_ci  if (censor.Pairs.Size() != 1)
951370b324cSopenharmony_ci    return false;
952370b324cSopenharmony_ci  const NWildcard::CPair &pair = censor.Pairs[0];
953370b324cSopenharmony_ci  /* Censor_CheckPath() ignores (CPair::Prefix).
954370b324cSopenharmony_ci     So we also ignore (CPair::Prefix) here */
955370b324cSopenharmony_ci  // if (!pair.Prefix.IsEmpty()) return false;
956370b324cSopenharmony_ci  return pair.Head.AreAllAllowed();
957370b324cSopenharmony_ci}
958370b324cSopenharmony_ci
959370b324cSopenharmony_cibool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include);
960370b324cSopenharmony_ci
961370b324cSopenharmony_cistatic bool Censor_CheckPath(const NWildcard::CCensor &censor, const CReadArcItem &item)
962370b324cSopenharmony_ci{
963370b324cSopenharmony_ci  bool finded = false;
964370b324cSopenharmony_ci  FOR_VECTOR (i, censor.Pairs)
965370b324cSopenharmony_ci  {
966370b324cSopenharmony_ci    /* (CPair::Prefix) in not used for matching items in archive.
967370b324cSopenharmony_ci       So we ignore (CPair::Prefix) here */
968370b324cSopenharmony_ci    bool include;
969370b324cSopenharmony_ci    if (CensorNode_CheckPath2(censor.Pairs[i].Head, item, include))
970370b324cSopenharmony_ci    {
971370b324cSopenharmony_ci      // Check it and FIXME !!!!
972370b324cSopenharmony_ci      // here we can exclude item via some Pair, that is still allowed by another Pair
973370b324cSopenharmony_ci      if (!include)
974370b324cSopenharmony_ci        return false;
975370b324cSopenharmony_ci      finded = true;
976370b324cSopenharmony_ci    }
977370b324cSopenharmony_ci  }
978370b324cSopenharmony_ci  return finded;
979370b324cSopenharmony_ci}
980370b324cSopenharmony_ci
981370b324cSopenharmony_cistatic HRESULT EnumerateInArchiveItems(
982370b324cSopenharmony_ci    // bool storeStreamsMode,
983370b324cSopenharmony_ci    const NWildcard::CCensor &censor,
984370b324cSopenharmony_ci    const CArc &arc,
985370b324cSopenharmony_ci    CObjectVector<CArcItem> &arcItems)
986370b324cSopenharmony_ci{
987370b324cSopenharmony_ci  arcItems.Clear();
988370b324cSopenharmony_ci  UInt32 numItems;
989370b324cSopenharmony_ci  IInArchive *archive = arc.Archive;
990370b324cSopenharmony_ci  RINOK(archive->GetNumberOfItems(&numItems))
991370b324cSopenharmony_ci  arcItems.ClearAndReserve(numItems);
992370b324cSopenharmony_ci
993370b324cSopenharmony_ci  CReadArcItem item;
994370b324cSopenharmony_ci
995370b324cSopenharmony_ci  const bool allFilesAreAllowed = Censor_AreAllAllowed(censor);
996370b324cSopenharmony_ci
997370b324cSopenharmony_ci  for (UInt32 i = 0; i < numItems; i++)
998370b324cSopenharmony_ci  {
999370b324cSopenharmony_ci    CArcItem ai;
1000370b324cSopenharmony_ci
1001370b324cSopenharmony_ci    RINOK(arc.GetItem(i, item))
1002370b324cSopenharmony_ci    ai.Name = item.Path;
1003370b324cSopenharmony_ci    ai.IsDir = item.IsDir;
1004370b324cSopenharmony_ci    ai.IsAltStream =
1005370b324cSopenharmony_ci        #ifdef SUPPORT_ALT_STREAMS
1006370b324cSopenharmony_ci          item.IsAltStream;
1007370b324cSopenharmony_ci        #else
1008370b324cSopenharmony_ci          false;
1009370b324cSopenharmony_ci        #endif
1010370b324cSopenharmony_ci
1011370b324cSopenharmony_ci    /*
1012370b324cSopenharmony_ci    if (!storeStreamsMode && ai.IsAltStream)
1013370b324cSopenharmony_ci      continue;
1014370b324cSopenharmony_ci    */
1015370b324cSopenharmony_ci    if (allFilesAreAllowed)
1016370b324cSopenharmony_ci      ai.Censored = true;
1017370b324cSopenharmony_ci    else
1018370b324cSopenharmony_ci      ai.Censored = Censor_CheckPath(censor, item);
1019370b324cSopenharmony_ci
1020370b324cSopenharmony_ci    // ai.MTime will be set to archive MTime, if not present in archive item
1021370b324cSopenharmony_ci    RINOK(arc.GetItem_MTime(i, ai.MTime))
1022370b324cSopenharmony_ci    RINOK(arc.GetItem_Size(i, ai.Size, ai.Size_Defined))
1023370b324cSopenharmony_ci
1024370b324cSopenharmony_ci    ai.IndexInServer = i;
1025370b324cSopenharmony_ci    arcItems.AddInReserved(ai);
1026370b324cSopenharmony_ci  }
1027370b324cSopenharmony_ci  return S_OK;
1028370b324cSopenharmony_ci}
1029370b324cSopenharmony_ci
1030370b324cSopenharmony_ci#if defined(_WIN32) && !defined(UNDER_CE)
1031370b324cSopenharmony_ci
1032370b324cSopenharmony_ci#if defined(__MINGW32__) || defined(__MINGW64__)
1033370b324cSopenharmony_ci#include <mapi.h>
1034370b324cSopenharmony_ci#else
1035370b324cSopenharmony_ci#include <MAPI.h>
1036370b324cSopenharmony_ci#endif
1037370b324cSopenharmony_ci
1038370b324cSopenharmony_ciextern "C" {
1039370b324cSopenharmony_ci
1040370b324cSopenharmony_ci#ifdef MAPI_FORCE_UNICODE
1041370b324cSopenharmony_ci
1042370b324cSopenharmony_ci#define Z7_WIN_LPMAPISENDMAILW  LPMAPISENDMAILW
1043370b324cSopenharmony_ci#define Z7_WIN_MapiFileDescW    MapiFileDescW
1044370b324cSopenharmony_ci#define Z7_WIN_MapiMessageW     MapiMessageW
1045370b324cSopenharmony_ci#define Z7_WIN_MapiRecipDescW   MapiRecipDescW
1046370b324cSopenharmony_ci
1047370b324cSopenharmony_ci#else
1048370b324cSopenharmony_ci
1049370b324cSopenharmony_citypedef struct
1050370b324cSopenharmony_ci{
1051370b324cSopenharmony_ci    ULONG ulReserved;
1052370b324cSopenharmony_ci    ULONG ulRecipClass;
1053370b324cSopenharmony_ci    PWSTR lpszName;
1054370b324cSopenharmony_ci    PWSTR lpszAddress;
1055370b324cSopenharmony_ci    ULONG ulEIDSize;
1056370b324cSopenharmony_ci    PVOID lpEntryID;
1057370b324cSopenharmony_ci} Z7_WIN_MapiRecipDescW, *Z7_WIN_lpMapiRecipDescW;
1058370b324cSopenharmony_ci
1059370b324cSopenharmony_citypedef struct
1060370b324cSopenharmony_ci{
1061370b324cSopenharmony_ci    ULONG ulReserved;
1062370b324cSopenharmony_ci    ULONG flFlags;
1063370b324cSopenharmony_ci    ULONG nPosition;
1064370b324cSopenharmony_ci    PWSTR lpszPathName;
1065370b324cSopenharmony_ci    PWSTR lpszFileName;
1066370b324cSopenharmony_ci    PVOID lpFileType;
1067370b324cSopenharmony_ci} Z7_WIN_MapiFileDescW, *Z7_WIN_lpMapiFileDescW;
1068370b324cSopenharmony_ci
1069370b324cSopenharmony_citypedef struct
1070370b324cSopenharmony_ci{
1071370b324cSopenharmony_ci  ULONG ulReserved;
1072370b324cSopenharmony_ci  PWSTR lpszSubject;
1073370b324cSopenharmony_ci  PWSTR lpszNoteText;
1074370b324cSopenharmony_ci  PWSTR lpszMessageType;
1075370b324cSopenharmony_ci  PWSTR lpszDateReceived;
1076370b324cSopenharmony_ci  PWSTR lpszConversationID;
1077370b324cSopenharmony_ci  FLAGS flFlags;
1078370b324cSopenharmony_ci  Z7_WIN_lpMapiRecipDescW lpOriginator;
1079370b324cSopenharmony_ci  ULONG nRecipCount;
1080370b324cSopenharmony_ci  Z7_WIN_lpMapiRecipDescW lpRecips;
1081370b324cSopenharmony_ci  ULONG nFileCount;
1082370b324cSopenharmony_ci  Z7_WIN_lpMapiFileDescW lpFiles;
1083370b324cSopenharmony_ci} Z7_WIN_MapiMessageW, *Z7_WIN_lpMapiMessageW;
1084370b324cSopenharmony_ci
1085370b324cSopenharmony_citypedef ULONG (FAR PASCAL Z7_WIN_MAPISENDMAILW)(
1086370b324cSopenharmony_ci  LHANDLE lhSession,
1087370b324cSopenharmony_ci  ULONG_PTR ulUIParam,
1088370b324cSopenharmony_ci  Z7_WIN_lpMapiMessageW lpMessage,
1089370b324cSopenharmony_ci  FLAGS flFlags,
1090370b324cSopenharmony_ci  ULONG ulReserved
1091370b324cSopenharmony_ci);
1092370b324cSopenharmony_citypedef Z7_WIN_MAPISENDMAILW FAR *Z7_WIN_LPMAPISENDMAILW;
1093370b324cSopenharmony_ci
1094370b324cSopenharmony_ci#endif // MAPI_FORCE_UNICODE
1095370b324cSopenharmony_ci}
1096370b324cSopenharmony_ci#endif // _WIN32
1097370b324cSopenharmony_ci
1098370b324cSopenharmony_ci
1099370b324cSopenharmony_ciHRESULT UpdateArchive(
1100370b324cSopenharmony_ci    CCodecs *codecs,
1101370b324cSopenharmony_ci    const CObjectVector<COpenType> &types,
1102370b324cSopenharmony_ci    const UString &cmdArcPath2,
1103370b324cSopenharmony_ci    NWildcard::CCensor &censor,
1104370b324cSopenharmony_ci    CUpdateOptions &options,
1105370b324cSopenharmony_ci    CUpdateErrorInfo &errorInfo,
1106370b324cSopenharmony_ci    IOpenCallbackUI *openCallback,
1107370b324cSopenharmony_ci    IUpdateCallbackUI2 *callback,
1108370b324cSopenharmony_ci    bool needSetPath)
1109370b324cSopenharmony_ci{
1110370b324cSopenharmony_ci  if (options.StdOutMode && options.EMailMode)
1111370b324cSopenharmony_ci    return E_FAIL;
1112370b324cSopenharmony_ci
1113370b324cSopenharmony_ci  if (types.Size() > 1)
1114370b324cSopenharmony_ci    return E_NOTIMPL;
1115370b324cSopenharmony_ci
1116370b324cSopenharmony_ci  bool renameMode = !options.RenamePairs.IsEmpty();
1117370b324cSopenharmony_ci  if (renameMode)
1118370b324cSopenharmony_ci  {
1119370b324cSopenharmony_ci    if (options.Commands.Size() != 1)
1120370b324cSopenharmony_ci      return E_FAIL;
1121370b324cSopenharmony_ci  }
1122370b324cSopenharmony_ci
1123370b324cSopenharmony_ci  if (options.DeleteAfterCompressing)
1124370b324cSopenharmony_ci  {
1125370b324cSopenharmony_ci    if (options.Commands.Size() != 1)
1126370b324cSopenharmony_ci      return E_NOTIMPL;
1127370b324cSopenharmony_ci    const CActionSet &as = options.Commands[0].ActionSet;
1128370b324cSopenharmony_ci    for (unsigned i = 2; i < NPairState::kNumValues; i++)
1129370b324cSopenharmony_ci      if (as.StateActions[i] != NPairAction::kCompress)
1130370b324cSopenharmony_ci        return E_NOTIMPL;
1131370b324cSopenharmony_ci  }
1132370b324cSopenharmony_ci
1133370b324cSopenharmony_ci  censor.AddPathsToCensor(options.PathMode);
1134370b324cSopenharmony_ci  #ifdef _WIN32
1135370b324cSopenharmony_ci  ConvertToLongNames(censor);
1136370b324cSopenharmony_ci  #endif
1137370b324cSopenharmony_ci  censor.ExtendExclude();
1138370b324cSopenharmony_ci
1139370b324cSopenharmony_ci
1140370b324cSopenharmony_ci  if (options.VolumesSizes.Size() > 0 && (options.EMailMode /* || options.SfxMode */))
1141370b324cSopenharmony_ci    return E_NOTIMPL;
1142370b324cSopenharmony_ci
1143370b324cSopenharmony_ci  if (options.SfxMode)
1144370b324cSopenharmony_ci  {
1145370b324cSopenharmony_ci    CProperty property;
1146370b324cSopenharmony_ci    property.Name = "rsfx";
1147370b324cSopenharmony_ci    options.MethodMode.Properties.Add(property);
1148370b324cSopenharmony_ci    if (options.SfxModule.IsEmpty())
1149370b324cSopenharmony_ci    {
1150370b324cSopenharmony_ci      errorInfo.Message = "SFX file is not specified";
1151370b324cSopenharmony_ci      return E_FAIL;
1152370b324cSopenharmony_ci    }
1153370b324cSopenharmony_ci    bool found = false;
1154370b324cSopenharmony_ci    if (options.SfxModule.Find(FCHAR_PATH_SEPARATOR) < 0)
1155370b324cSopenharmony_ci    {
1156370b324cSopenharmony_ci      const FString fullName = NDLL::GetModuleDirPrefix() + options.SfxModule;
1157370b324cSopenharmony_ci      if (NFind::DoesFileExist_FollowLink(fullName))
1158370b324cSopenharmony_ci      {
1159370b324cSopenharmony_ci        options.SfxModule = fullName;
1160370b324cSopenharmony_ci        found = true;
1161370b324cSopenharmony_ci      }
1162370b324cSopenharmony_ci    }
1163370b324cSopenharmony_ci    if (!found)
1164370b324cSopenharmony_ci    {
1165370b324cSopenharmony_ci      if (!NFind::DoesFileExist_FollowLink(options.SfxModule))
1166370b324cSopenharmony_ci        return errorInfo.SetFromLastError("cannot find specified SFX module", options.SfxModule);
1167370b324cSopenharmony_ci    }
1168370b324cSopenharmony_ci  }
1169370b324cSopenharmony_ci
1170370b324cSopenharmony_ci  CArchiveLink arcLink;
1171370b324cSopenharmony_ci
1172370b324cSopenharmony_ci
1173370b324cSopenharmony_ci  if (needSetPath)
1174370b324cSopenharmony_ci  {
1175370b324cSopenharmony_ci    if (!options.InitFormatIndex(codecs, types, cmdArcPath2) ||
1176370b324cSopenharmony_ci        !options.SetArcPath(codecs, cmdArcPath2))
1177370b324cSopenharmony_ci      return E_NOTIMPL;
1178370b324cSopenharmony_ci  }
1179370b324cSopenharmony_ci
1180370b324cSopenharmony_ci  UString arcPath = options.ArchivePath.GetFinalPath();
1181370b324cSopenharmony_ci
1182370b324cSopenharmony_ci  if (!options.VolumesSizes.IsEmpty())
1183370b324cSopenharmony_ci  {
1184370b324cSopenharmony_ci    arcPath = options.ArchivePath.GetFinalVolPath();
1185370b324cSopenharmony_ci    arcPath += ".001";
1186370b324cSopenharmony_ci  }
1187370b324cSopenharmony_ci
1188370b324cSopenharmony_ci  if (cmdArcPath2.IsEmpty())
1189370b324cSopenharmony_ci  {
1190370b324cSopenharmony_ci    if (options.MethodMode.Type.FormatIndex < 0)
1191370b324cSopenharmony_ci      throw "type of archive is not specified";
1192370b324cSopenharmony_ci  }
1193370b324cSopenharmony_ci  else
1194370b324cSopenharmony_ci  {
1195370b324cSopenharmony_ci    NFind::CFileInfo fi;
1196370b324cSopenharmony_ci    if (!fi.Find_FollowLink(us2fs(arcPath)))
1197370b324cSopenharmony_ci    {
1198370b324cSopenharmony_ci      if (renameMode)
1199370b324cSopenharmony_ci        throw "can't find archive";
1200370b324cSopenharmony_ci      if (options.MethodMode.Type.FormatIndex < 0)
1201370b324cSopenharmony_ci      {
1202370b324cSopenharmony_ci        if (!options.SetArcPath(codecs, cmdArcPath2))
1203370b324cSopenharmony_ci          return E_NOTIMPL;
1204370b324cSopenharmony_ci      }
1205370b324cSopenharmony_ci    }
1206370b324cSopenharmony_ci    else
1207370b324cSopenharmony_ci    {
1208370b324cSopenharmony_ci      if (fi.IsDir())
1209370b324cSopenharmony_ci        return errorInfo.SetFromError_DWORD("There is a folder with the name of archive",
1210370b324cSopenharmony_ci            us2fs(arcPath),
1211370b324cSopenharmony_ci            #ifdef _WIN32
1212370b324cSopenharmony_ci              ERROR_ACCESS_DENIED
1213370b324cSopenharmony_ci            #else
1214370b324cSopenharmony_ci              EISDIR
1215370b324cSopenharmony_ci            #endif
1216370b324cSopenharmony_ci            );
1217370b324cSopenharmony_ci     #ifdef _WIN32
1218370b324cSopenharmony_ci      if (fi.IsDevice)
1219370b324cSopenharmony_ci        return E_NOTIMPL;
1220370b324cSopenharmony_ci     #endif
1221370b324cSopenharmony_ci
1222370b324cSopenharmony_ci      if (!options.StdOutMode && options.UpdateArchiveItself)
1223370b324cSopenharmony_ci        if (fi.IsReadOnly())
1224370b324cSopenharmony_ci        {
1225370b324cSopenharmony_ci          return errorInfo.SetFromError_DWORD("The file is read-only",
1226370b324cSopenharmony_ci              us2fs(arcPath),
1227370b324cSopenharmony_ci              #ifdef _WIN32
1228370b324cSopenharmony_ci                ERROR_ACCESS_DENIED
1229370b324cSopenharmony_ci              #else
1230370b324cSopenharmony_ci                EACCES
1231370b324cSopenharmony_ci              #endif
1232370b324cSopenharmony_ci              );
1233370b324cSopenharmony_ci        }
1234370b324cSopenharmony_ci
1235370b324cSopenharmony_ci      if (options.VolumesSizes.Size() > 0)
1236370b324cSopenharmony_ci      {
1237370b324cSopenharmony_ci        errorInfo.FileNames.Add(us2fs(arcPath));
1238370b324cSopenharmony_ci        // errorInfo.SystemError = (DWORD)E_NOTIMPL;
1239370b324cSopenharmony_ci        errorInfo.Message = kUpdateIsNotSupported_MultiVol;
1240370b324cSopenharmony_ci        return E_NOTIMPL;
1241370b324cSopenharmony_ci      }
1242370b324cSopenharmony_ci      CObjectVector<COpenType> types2;
1243370b324cSopenharmony_ci      // change it.
1244370b324cSopenharmony_ci      if (options.MethodMode.Type_Defined)
1245370b324cSopenharmony_ci        types2.Add(options.MethodMode.Type);
1246370b324cSopenharmony_ci      // We need to set Properties to open archive only in some cases (WIM archives).
1247370b324cSopenharmony_ci
1248370b324cSopenharmony_ci      CIntVector excl;
1249370b324cSopenharmony_ci      COpenOptions op;
1250370b324cSopenharmony_ci      #ifndef Z7_SFX
1251370b324cSopenharmony_ci      op.props = &options.MethodMode.Properties;
1252370b324cSopenharmony_ci      #endif
1253370b324cSopenharmony_ci      op.codecs = codecs;
1254370b324cSopenharmony_ci      op.types = &types2;
1255370b324cSopenharmony_ci      op.excludedFormats = &excl;
1256370b324cSopenharmony_ci      op.stdInMode = false;
1257370b324cSopenharmony_ci      op.stream = NULL;
1258370b324cSopenharmony_ci      op.filePath = arcPath;
1259370b324cSopenharmony_ci
1260370b324cSopenharmony_ci      RINOK(callback->StartOpenArchive(arcPath))
1261370b324cSopenharmony_ci
1262370b324cSopenharmony_ci      HRESULT result = arcLink.Open_Strict(op, openCallback);
1263370b324cSopenharmony_ci
1264370b324cSopenharmony_ci      if (result == E_ABORT)
1265370b324cSopenharmony_ci        return result;
1266370b324cSopenharmony_ci
1267370b324cSopenharmony_ci      HRESULT res2 = callback->OpenResult(codecs, arcLink, arcPath, result);
1268370b324cSopenharmony_ci      /*
1269370b324cSopenharmony_ci      if (result == S_FALSE)
1270370b324cSopenharmony_ci        return E_FAIL;
1271370b324cSopenharmony_ci      */
1272370b324cSopenharmony_ci      RINOK(res2)
1273370b324cSopenharmony_ci      RINOK(result)
1274370b324cSopenharmony_ci
1275370b324cSopenharmony_ci      if (arcLink.VolumePaths.Size() > 1)
1276370b324cSopenharmony_ci      {
1277370b324cSopenharmony_ci        // errorInfo.SystemError = (DWORD)E_NOTIMPL;
1278370b324cSopenharmony_ci        errorInfo.Message = kUpdateIsNotSupported_MultiVol;
1279370b324cSopenharmony_ci        return E_NOTIMPL;
1280370b324cSopenharmony_ci      }
1281370b324cSopenharmony_ci
1282370b324cSopenharmony_ci      CArc &arc = arcLink.Arcs.Back();
1283370b324cSopenharmony_ci      arc.MTime.Def =
1284370b324cSopenharmony_ci        #ifdef _WIN32
1285370b324cSopenharmony_ci          !fi.IsDevice;
1286370b324cSopenharmony_ci        #else
1287370b324cSopenharmony_ci          true;
1288370b324cSopenharmony_ci        #endif
1289370b324cSopenharmony_ci      if (arc.MTime.Def)
1290370b324cSopenharmony_ci        arc.MTime.Set_From_FiTime(fi.MTime);
1291370b324cSopenharmony_ci
1292370b324cSopenharmony_ci      if (arc.ErrorInfo.ThereIsTail)
1293370b324cSopenharmony_ci      {
1294370b324cSopenharmony_ci        // errorInfo.SystemError = (DWORD)E_NOTIMPL;
1295370b324cSopenharmony_ci        errorInfo.Message = "There is some data block after the end of the archive";
1296370b324cSopenharmony_ci        return E_NOTIMPL;
1297370b324cSopenharmony_ci      }
1298370b324cSopenharmony_ci      if (options.MethodMode.Type.FormatIndex < 0)
1299370b324cSopenharmony_ci      {
1300370b324cSopenharmony_ci        options.MethodMode.Type.FormatIndex = arcLink.GetArc()->FormatIndex;
1301370b324cSopenharmony_ci        if (!options.SetArcPath(codecs, cmdArcPath2))
1302370b324cSopenharmony_ci          return E_NOTIMPL;
1303370b324cSopenharmony_ci      }
1304370b324cSopenharmony_ci    }
1305370b324cSopenharmony_ci  }
1306370b324cSopenharmony_ci
1307370b324cSopenharmony_ci  if (options.MethodMode.Type.FormatIndex < 0)
1308370b324cSopenharmony_ci  {
1309370b324cSopenharmony_ci    options.MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveType((UString)kDefaultArcType);
1310370b324cSopenharmony_ci    if (options.MethodMode.Type.FormatIndex < 0)
1311370b324cSopenharmony_ci      return E_NOTIMPL;
1312370b324cSopenharmony_ci  }
1313370b324cSopenharmony_ci
1314370b324cSopenharmony_ci  bool thereIsInArchive = arcLink.IsOpen;
1315370b324cSopenharmony_ci  if (!thereIsInArchive && renameMode)
1316370b324cSopenharmony_ci    return E_FAIL;
1317370b324cSopenharmony_ci
1318370b324cSopenharmony_ci  CDirItems dirItems;
1319370b324cSopenharmony_ci  dirItems.Callback = callback;
1320370b324cSopenharmony_ci
1321370b324cSopenharmony_ci  CDirItem parentDirItem;
1322370b324cSopenharmony_ci  CDirItem *parentDirItem_Ptr = NULL;
1323370b324cSopenharmony_ci
1324370b324cSopenharmony_ci  /*
1325370b324cSopenharmony_ci  FStringVector requestedPaths;
1326370b324cSopenharmony_ci  FStringVector *requestedPaths_Ptr = NULL;
1327370b324cSopenharmony_ci  if (options.DeleteAfterCompressing)
1328370b324cSopenharmony_ci    requestedPaths_Ptr = &requestedPaths;
1329370b324cSopenharmony_ci  */
1330370b324cSopenharmony_ci
1331370b324cSopenharmony_ci  if (options.StdInMode)
1332370b324cSopenharmony_ci  {
1333370b324cSopenharmony_ci    CDirItem di;
1334370b324cSopenharmony_ci    di.ClearBase();
1335370b324cSopenharmony_ci    di.Name = options.StdInFileName;
1336370b324cSopenharmony_ci    di.Size = (UInt64)(Int64)-1;
1337370b324cSopenharmony_ci    di.SetAsFile();
1338370b324cSopenharmony_ci    NTime::GetCurUtc_FiTime(di.MTime);
1339370b324cSopenharmony_ci    di.CTime = di.ATime = di.MTime;
1340370b324cSopenharmony_ci    dirItems.Items.Add(di);
1341370b324cSopenharmony_ci  }
1342370b324cSopenharmony_ci  else
1343370b324cSopenharmony_ci  {
1344370b324cSopenharmony_ci    bool needScanning = false;
1345370b324cSopenharmony_ci
1346370b324cSopenharmony_ci    if (!renameMode)
1347370b324cSopenharmony_ci    FOR_VECTOR (i, options.Commands)
1348370b324cSopenharmony_ci      if (options.Commands[i].ActionSet.NeedScanning())
1349370b324cSopenharmony_ci        needScanning = true;
1350370b324cSopenharmony_ci
1351370b324cSopenharmony_ci    if (needScanning)
1352370b324cSopenharmony_ci    {
1353370b324cSopenharmony_ci      RINOK(callback->StartScanning())
1354370b324cSopenharmony_ci
1355370b324cSopenharmony_ci      dirItems.SymLinks = options.SymLinks.Val;
1356370b324cSopenharmony_ci
1357370b324cSopenharmony_ci      #if defined(_WIN32) && !defined(UNDER_CE)
1358370b324cSopenharmony_ci      dirItems.ReadSecure = options.NtSecurity.Val;
1359370b324cSopenharmony_ci      #endif
1360370b324cSopenharmony_ci
1361370b324cSopenharmony_ci      dirItems.ScanAltStreams = options.AltStreams.Val;
1362370b324cSopenharmony_ci      dirItems.ExcludeDirItems = censor.ExcludeDirItems;
1363370b324cSopenharmony_ci      dirItems.ExcludeFileItems = censor.ExcludeFileItems;
1364370b324cSopenharmony_ci
1365370b324cSopenharmony_ci      dirItems.ShareForWrite = options.OpenShareForWrite;
1366370b324cSopenharmony_ci
1367370b324cSopenharmony_ci     #ifndef _WIN32
1368370b324cSopenharmony_ci      dirItems.StoreOwnerName = options.StoreOwnerName.Val;
1369370b324cSopenharmony_ci     #endif
1370370b324cSopenharmony_ci
1371370b324cSopenharmony_ci      const HRESULT res = EnumerateItems(censor,
1372370b324cSopenharmony_ci          options.PathMode,
1373370b324cSopenharmony_ci          UString(), // options.AddPathPrefix,
1374370b324cSopenharmony_ci          dirItems);
1375370b324cSopenharmony_ci
1376370b324cSopenharmony_ci      if (res != S_OK)
1377370b324cSopenharmony_ci      {
1378370b324cSopenharmony_ci        if (res != E_ABORT)
1379370b324cSopenharmony_ci          errorInfo.Message = "Scanning error";
1380370b324cSopenharmony_ci        return res;
1381370b324cSopenharmony_ci      }
1382370b324cSopenharmony_ci
1383370b324cSopenharmony_ci      RINOK(callback->FinishScanning(dirItems.Stat))
1384370b324cSopenharmony_ci
1385370b324cSopenharmony_ci      // 22.00: we don't need parent folder, if absolute path mode
1386370b324cSopenharmony_ci      if (options.PathMode != NWildcard::k_AbsPath)
1387370b324cSopenharmony_ci      if (censor.Pairs.Size() == 1)
1388370b324cSopenharmony_ci      {
1389370b324cSopenharmony_ci        NFind::CFileInfo fi;
1390370b324cSopenharmony_ci        FString prefix = us2fs(censor.Pairs[0].Prefix);
1391370b324cSopenharmony_ci        prefix.Add_Dot();
1392370b324cSopenharmony_ci        // UString prefix = censor.Pairs[0].Prefix;
1393370b324cSopenharmony_ci        /*
1394370b324cSopenharmony_ci        if (prefix.Back() == WCHAR_PATH_SEPARATOR)
1395370b324cSopenharmony_ci        {
1396370b324cSopenharmony_ci          prefix.DeleteBack();
1397370b324cSopenharmony_ci        }
1398370b324cSopenharmony_ci        */
1399370b324cSopenharmony_ci        if (fi.Find(prefix))
1400370b324cSopenharmony_ci          if (fi.IsDir())
1401370b324cSopenharmony_ci          {
1402370b324cSopenharmony_ci            parentDirItem.Copy_From_FileInfoBase(fi);
1403370b324cSopenharmony_ci            parentDirItem_Ptr = &parentDirItem;
1404370b324cSopenharmony_ci
1405370b324cSopenharmony_ci            int secureIndex = -1;
1406370b324cSopenharmony_ci            #if defined(_WIN32) && !defined(UNDER_CE)
1407370b324cSopenharmony_ci            if (options.NtSecurity.Val)
1408370b324cSopenharmony_ci              dirItems.AddSecurityItem(prefix, secureIndex);
1409370b324cSopenharmony_ci            #endif
1410370b324cSopenharmony_ci            parentDirItem.SecureIndex = secureIndex;
1411370b324cSopenharmony_ci          }
1412370b324cSopenharmony_ci      }
1413370b324cSopenharmony_ci    }
1414370b324cSopenharmony_ci  }
1415370b324cSopenharmony_ci
1416370b324cSopenharmony_ci  FString tempDirPrefix;
1417370b324cSopenharmony_ci  bool usesTempDir = false;
1418370b324cSopenharmony_ci
1419370b324cSopenharmony_ci  #ifdef _WIN32
1420370b324cSopenharmony_ci  CTempDir tempDirectory;
1421370b324cSopenharmony_ci  if (options.EMailMode && options.EMailRemoveAfter)
1422370b324cSopenharmony_ci  {
1423370b324cSopenharmony_ci    tempDirectory.Create(kTempFolderPrefix);
1424370b324cSopenharmony_ci    tempDirPrefix = tempDirectory.GetPath();
1425370b324cSopenharmony_ci    NormalizeDirPathPrefix(tempDirPrefix);
1426370b324cSopenharmony_ci    usesTempDir = true;
1427370b324cSopenharmony_ci  }
1428370b324cSopenharmony_ci  #endif
1429370b324cSopenharmony_ci
1430370b324cSopenharmony_ci  CTempFiles tempFiles;
1431370b324cSopenharmony_ci
1432370b324cSopenharmony_ci  bool createTempFile = false;
1433370b324cSopenharmony_ci
1434370b324cSopenharmony_ci  if (!options.StdOutMode && options.UpdateArchiveItself)
1435370b324cSopenharmony_ci  {
1436370b324cSopenharmony_ci    CArchivePath &ap = options.Commands[0].ArchivePath;
1437370b324cSopenharmony_ci    ap = options.ArchivePath;
1438370b324cSopenharmony_ci    // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty())
1439370b324cSopenharmony_ci    if ((thereIsInArchive || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0)
1440370b324cSopenharmony_ci    {
1441370b324cSopenharmony_ci      createTempFile = true;
1442370b324cSopenharmony_ci      ap.Temp = true;
1443370b324cSopenharmony_ci      if (!options.WorkingDir.IsEmpty())
1444370b324cSopenharmony_ci        ap.TempPrefix = options.WorkingDir;
1445370b324cSopenharmony_ci      else
1446370b324cSopenharmony_ci        ap.TempPrefix = us2fs(ap.Prefix);
1447370b324cSopenharmony_ci      NormalizeDirPathPrefix(ap.TempPrefix);
1448370b324cSopenharmony_ci    }
1449370b324cSopenharmony_ci  }
1450370b324cSopenharmony_ci
1451370b324cSopenharmony_ci  unsigned ci;
1452370b324cSopenharmony_ci
1453370b324cSopenharmony_ci
1454370b324cSopenharmony_ci  // self including protection
1455370b324cSopenharmony_ci  if (options.DeleteAfterCompressing)
1456370b324cSopenharmony_ci  {
1457370b324cSopenharmony_ci    for (ci = 0; ci < options.Commands.Size(); ci++)
1458370b324cSopenharmony_ci    {
1459370b324cSopenharmony_ci      CArchivePath &ap = options.Commands[ci].ArchivePath;
1460370b324cSopenharmony_ci      const FString path = us2fs(ap.GetFinalPath());
1461370b324cSopenharmony_ci      // maybe we must compare absolute paths path here
1462370b324cSopenharmony_ci      FOR_VECTOR (i, dirItems.Items)
1463370b324cSopenharmony_ci      {
1464370b324cSopenharmony_ci        const FString phyPath = dirItems.GetPhyPath(i);
1465370b324cSopenharmony_ci        if (phyPath == path)
1466370b324cSopenharmony_ci        {
1467370b324cSopenharmony_ci          UString s;
1468370b324cSopenharmony_ci          s = "It is not allowed to include archive to itself";
1469370b324cSopenharmony_ci          s.Add_LF();
1470370b324cSopenharmony_ci          s += fs2us(path);
1471370b324cSopenharmony_ci          throw s;
1472370b324cSopenharmony_ci        }
1473370b324cSopenharmony_ci      }
1474370b324cSopenharmony_ci    }
1475370b324cSopenharmony_ci  }
1476370b324cSopenharmony_ci
1477370b324cSopenharmony_ci
1478370b324cSopenharmony_ci  for (ci = 0; ci < options.Commands.Size(); ci++)
1479370b324cSopenharmony_ci  {
1480370b324cSopenharmony_ci    CArchivePath &ap = options.Commands[ci].ArchivePath;
1481370b324cSopenharmony_ci    if (usesTempDir)
1482370b324cSopenharmony_ci    {
1483370b324cSopenharmony_ci      // Check it
1484370b324cSopenharmony_ci      ap.Prefix = fs2us(tempDirPrefix);
1485370b324cSopenharmony_ci      // ap.Temp = true;
1486370b324cSopenharmony_ci      // ap.TempPrefix = tempDirPrefix;
1487370b324cSopenharmony_ci    }
1488370b324cSopenharmony_ci    if (!options.StdOutMode &&
1489370b324cSopenharmony_ci        (ci > 0 || !createTempFile))
1490370b324cSopenharmony_ci    {
1491370b324cSopenharmony_ci      const FString path = us2fs(ap.GetFinalPath());
1492370b324cSopenharmony_ci      if (NFind::DoesFileOrDirExist(path))
1493370b324cSopenharmony_ci      {
1494370b324cSopenharmony_ci        errorInfo.SystemError = ERROR_FILE_EXISTS;
1495370b324cSopenharmony_ci        errorInfo.Message = "The file already exists";
1496370b324cSopenharmony_ci        errorInfo.FileNames.Add(path);
1497370b324cSopenharmony_ci        return errorInfo.Get_HRESULT_Error();
1498370b324cSopenharmony_ci      }
1499370b324cSopenharmony_ci    }
1500370b324cSopenharmony_ci  }
1501370b324cSopenharmony_ci
1502370b324cSopenharmony_ci  CObjectVector<CArcItem> arcItems;
1503370b324cSopenharmony_ci  if (thereIsInArchive)
1504370b324cSopenharmony_ci  {
1505370b324cSopenharmony_ci    RINOK(EnumerateInArchiveItems(
1506370b324cSopenharmony_ci      // options.StoreAltStreams,
1507370b324cSopenharmony_ci      censor, arcLink.Arcs.Back(), arcItems))
1508370b324cSopenharmony_ci  }
1509370b324cSopenharmony_ci
1510370b324cSopenharmony_ci  /*
1511370b324cSopenharmony_ci  FStringVector processedFilePaths;
1512370b324cSopenharmony_ci  FStringVector *processedFilePaths_Ptr = NULL;
1513370b324cSopenharmony_ci  if (options.DeleteAfterCompressing)
1514370b324cSopenharmony_ci    processedFilePaths_Ptr = &processedFilePaths;
1515370b324cSopenharmony_ci  */
1516370b324cSopenharmony_ci
1517370b324cSopenharmony_ci  CByteBuffer processedItems;
1518370b324cSopenharmony_ci  if (options.DeleteAfterCompressing)
1519370b324cSopenharmony_ci  {
1520370b324cSopenharmony_ci    const unsigned num = dirItems.Items.Size();
1521370b324cSopenharmony_ci    processedItems.Alloc(num);
1522370b324cSopenharmony_ci    for (unsigned i = 0; i < num; i++)
1523370b324cSopenharmony_ci      processedItems[i] = 0;
1524370b324cSopenharmony_ci  }
1525370b324cSopenharmony_ci
1526370b324cSopenharmony_ci  CMultiOutStream_Bunch multiStreams;
1527370b324cSopenharmony_ci
1528370b324cSopenharmony_ci  /*
1529370b324cSopenharmony_ci  #ifndef Z7_NO_CRYPTO
1530370b324cSopenharmony_ci  if (arcLink.PasswordWasAsked)
1531370b324cSopenharmony_ci  {
1532370b324cSopenharmony_ci    // We set password, if open have requested password
1533370b324cSopenharmony_ci    RINOK(callback->SetPassword(arcLink.Password));
1534370b324cSopenharmony_ci  }
1535370b324cSopenharmony_ci  #endif
1536370b324cSopenharmony_ci  */
1537370b324cSopenharmony_ci
1538370b324cSopenharmony_ci  for (ci = 0; ci < options.Commands.Size(); ci++)
1539370b324cSopenharmony_ci  {
1540370b324cSopenharmony_ci    const CArc *arc = thereIsInArchive ? arcLink.GetArc() : NULL;
1541370b324cSopenharmony_ci    CUpdateArchiveCommand &command = options.Commands[ci];
1542370b324cSopenharmony_ci    UString name;
1543370b324cSopenharmony_ci    bool isUpdating;
1544370b324cSopenharmony_ci
1545370b324cSopenharmony_ci    if (options.StdOutMode)
1546370b324cSopenharmony_ci    {
1547370b324cSopenharmony_ci      name = "stdout";
1548370b324cSopenharmony_ci      isUpdating = thereIsInArchive;
1549370b324cSopenharmony_ci    }
1550370b324cSopenharmony_ci    else
1551370b324cSopenharmony_ci    {
1552370b324cSopenharmony_ci      name = command.ArchivePath.GetFinalPath();
1553370b324cSopenharmony_ci      isUpdating = (ci == 0 && options.UpdateArchiveItself && thereIsInArchive);
1554370b324cSopenharmony_ci    }
1555370b324cSopenharmony_ci
1556370b324cSopenharmony_ci    RINOK(callback->StartArchive(name, isUpdating))
1557370b324cSopenharmony_ci
1558370b324cSopenharmony_ci    CFinishArchiveStat st;
1559370b324cSopenharmony_ci
1560370b324cSopenharmony_ci    RINOK(Compress(options,
1561370b324cSopenharmony_ci        isUpdating,
1562370b324cSopenharmony_ci        codecs,
1563370b324cSopenharmony_ci        command.ActionSet,
1564370b324cSopenharmony_ci        arc,
1565370b324cSopenharmony_ci        command.ArchivePath,
1566370b324cSopenharmony_ci        arcItems,
1567370b324cSopenharmony_ci        options.DeleteAfterCompressing ? (Byte *)processedItems : NULL,
1568370b324cSopenharmony_ci
1569370b324cSopenharmony_ci        dirItems,
1570370b324cSopenharmony_ci        parentDirItem_Ptr,
1571370b324cSopenharmony_ci
1572370b324cSopenharmony_ci        tempFiles,
1573370b324cSopenharmony_ci        multiStreams,
1574370b324cSopenharmony_ci        errorInfo, callback, st))
1575370b324cSopenharmony_ci
1576370b324cSopenharmony_ci    RINOK(callback->FinishArchive(st))
1577370b324cSopenharmony_ci  }
1578370b324cSopenharmony_ci
1579370b324cSopenharmony_ci
1580370b324cSopenharmony_ci  if (thereIsInArchive)
1581370b324cSopenharmony_ci  {
1582370b324cSopenharmony_ci    RINOK(arcLink.Close())
1583370b324cSopenharmony_ci    arcLink.Release();
1584370b324cSopenharmony_ci  }
1585370b324cSopenharmony_ci
1586370b324cSopenharmony_ci  multiStreams.DisableDeletion();
1587370b324cSopenharmony_ci  RINOK(multiStreams.Destruct())
1588370b324cSopenharmony_ci
1589370b324cSopenharmony_ci  tempFiles.Paths.Clear();
1590370b324cSopenharmony_ci  if (createTempFile)
1591370b324cSopenharmony_ci  {
1592370b324cSopenharmony_ci    try
1593370b324cSopenharmony_ci    {
1594370b324cSopenharmony_ci      CArchivePath &ap = options.Commands[0].ArchivePath;
1595370b324cSopenharmony_ci      const FString &tempPath = ap.GetTempPath();
1596370b324cSopenharmony_ci
1597370b324cSopenharmony_ci      // DWORD attrib = 0;
1598370b324cSopenharmony_ci      if (thereIsInArchive)
1599370b324cSopenharmony_ci      {
1600370b324cSopenharmony_ci        // attrib = NFind::GetFileAttrib(us2fs(arcPath));
1601370b324cSopenharmony_ci        if (!DeleteFileAlways(us2fs(arcPath)))
1602370b324cSopenharmony_ci          return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath));
1603370b324cSopenharmony_ci      }
1604370b324cSopenharmony_ci
1605370b324cSopenharmony_ci      if (!MyMoveFile(tempPath, us2fs(arcPath)))
1606370b324cSopenharmony_ci      {
1607370b324cSopenharmony_ci        errorInfo.SetFromLastError("cannot move the file", tempPath);
1608370b324cSopenharmony_ci        errorInfo.FileNames.Add(us2fs(arcPath));
1609370b324cSopenharmony_ci        return errorInfo.Get_HRESULT_Error();
1610370b324cSopenharmony_ci      }
1611370b324cSopenharmony_ci
1612370b324cSopenharmony_ci      /*
1613370b324cSopenharmony_ci      if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY))
1614370b324cSopenharmony_ci      {
1615370b324cSopenharmony_ci        DWORD attrib2 = NFind::GetFileAttrib(us2fs(arcPath));
1616370b324cSopenharmony_ci        if (attrib2 != INVALID_FILE_ATTRIBUTES)
1617370b324cSopenharmony_ci          NDir::SetFileAttrib(us2fs(arcPath), attrib2 | FILE_ATTRIBUTE_READONLY);
1618370b324cSopenharmony_ci      }
1619370b324cSopenharmony_ci      */
1620370b324cSopenharmony_ci    }
1621370b324cSopenharmony_ci    catch(...)
1622370b324cSopenharmony_ci    {
1623370b324cSopenharmony_ci      throw;
1624370b324cSopenharmony_ci    }
1625370b324cSopenharmony_ci  }
1626370b324cSopenharmony_ci
1627370b324cSopenharmony_ci
1628370b324cSopenharmony_ci  #if defined(_WIN32) && !defined(UNDER_CE)
1629370b324cSopenharmony_ci
1630370b324cSopenharmony_ci  if (options.EMailMode)
1631370b324cSopenharmony_ci  {
1632370b324cSopenharmony_ci    NDLL::CLibrary mapiLib;
1633370b324cSopenharmony_ci    if (!mapiLib.Load(FTEXT("Mapi32.dll")))
1634370b324cSopenharmony_ci    {
1635370b324cSopenharmony_ci      errorInfo.SetFromLastError("cannot load Mapi32.dll");
1636370b324cSopenharmony_ci      return errorInfo.Get_HRESULT_Error();
1637370b324cSopenharmony_ci    }
1638370b324cSopenharmony_ci
1639370b324cSopenharmony_ci    FStringVector fullPaths;
1640370b324cSopenharmony_ci    unsigned i;
1641370b324cSopenharmony_ci
1642370b324cSopenharmony_ci    for (i = 0; i < options.Commands.Size(); i++)
1643370b324cSopenharmony_ci    {
1644370b324cSopenharmony_ci      CArchivePath &ap = options.Commands[i].ArchivePath;
1645370b324cSopenharmony_ci      const FString finalPath = us2fs(ap.GetFinalPath());
1646370b324cSopenharmony_ci      FString arcPath2;
1647370b324cSopenharmony_ci      if (!MyGetFullPathName(finalPath, arcPath2))
1648370b324cSopenharmony_ci        return errorInfo.SetFromLastError("GetFullPathName error", finalPath);
1649370b324cSopenharmony_ci      fullPaths.Add(arcPath2);
1650370b324cSopenharmony_ci    }
1651370b324cSopenharmony_ci
1652370b324cSopenharmony_ci    /*
1653370b324cSopenharmony_ci    LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments");
1654370b324cSopenharmony_ci    if (fnSend == 0)
1655370b324cSopenharmony_ci    {
1656370b324cSopenharmony_ci      errorInfo.SetFromLastError)("7-Zip cannot find MAPISendDocuments function");
1657370b324cSopenharmony_ci      return errorInfo.Get_HRESULT_Error();
1658370b324cSopenharmony_ci    }
1659370b324cSopenharmony_ci    */
1660370b324cSopenharmony_ci    const
1661370b324cSopenharmony_ci    Z7_WIN_LPMAPISENDMAILW sendMailW = Z7_GET_PROC_ADDRESS(
1662370b324cSopenharmony_ci    Z7_WIN_LPMAPISENDMAILW, mapiLib.Get_HMODULE(),
1663370b324cSopenharmony_ci            "MAPISendMailW");
1664370b324cSopenharmony_ci   if (sendMailW)
1665370b324cSopenharmony_ci   {
1666370b324cSopenharmony_ci
1667370b324cSopenharmony_ci    CCurrentDirRestorer curDirRestorer;
1668370b324cSopenharmony_ci
1669370b324cSopenharmony_ci    UStringVector paths;
1670370b324cSopenharmony_ci    UStringVector names;
1671370b324cSopenharmony_ci
1672370b324cSopenharmony_ci    for (i = 0; i < fullPaths.Size(); i++)
1673370b324cSopenharmony_ci    {
1674370b324cSopenharmony_ci      const UString arcPath2 = fs2us(fullPaths[i]);
1675370b324cSopenharmony_ci      const UString fileName = ExtractFileNameFromPath(arcPath2);
1676370b324cSopenharmony_ci      paths.Add(arcPath2);
1677370b324cSopenharmony_ci      names.Add(fileName);
1678370b324cSopenharmony_ci      // Warning!!! MAPISendDocuments function changes Current directory
1679370b324cSopenharmony_ci      // fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
1680370b324cSopenharmony_ci    }
1681370b324cSopenharmony_ci
1682370b324cSopenharmony_ci    CRecordVector<Z7_WIN_MapiFileDescW> files;
1683370b324cSopenharmony_ci    files.ClearAndSetSize(paths.Size());
1684370b324cSopenharmony_ci
1685370b324cSopenharmony_ci    for (i = 0; i < paths.Size(); i++)
1686370b324cSopenharmony_ci    {
1687370b324cSopenharmony_ci      Z7_WIN_MapiFileDescW &f = files[i];
1688370b324cSopenharmony_ci      memset(&f, 0, sizeof(f));
1689370b324cSopenharmony_ci      f.nPosition = 0xFFFFFFFF;
1690370b324cSopenharmony_ci      f.lpszPathName = paths[i].Ptr_non_const();
1691370b324cSopenharmony_ci      f.lpszFileName = names[i].Ptr_non_const();
1692370b324cSopenharmony_ci    }
1693370b324cSopenharmony_ci
1694370b324cSopenharmony_ci    {
1695370b324cSopenharmony_ci      Z7_WIN_MapiMessageW m;
1696370b324cSopenharmony_ci      memset(&m, 0, sizeof(m));
1697370b324cSopenharmony_ci      m.nFileCount = files.Size();
1698370b324cSopenharmony_ci      m.lpFiles = &files.Front();
1699370b324cSopenharmony_ci
1700370b324cSopenharmony_ci      const UString addr (options.EMailAddress);
1701370b324cSopenharmony_ci      Z7_WIN_MapiRecipDescW rec;
1702370b324cSopenharmony_ci      if (!addr.IsEmpty())
1703370b324cSopenharmony_ci      {
1704370b324cSopenharmony_ci        memset(&rec, 0, sizeof(rec));
1705370b324cSopenharmony_ci        rec.ulRecipClass = MAPI_TO;
1706370b324cSopenharmony_ci        rec.lpszAddress = addr.Ptr_non_const();
1707370b324cSopenharmony_ci        m.nRecipCount = 1;
1708370b324cSopenharmony_ci        m.lpRecips = &rec;
1709370b324cSopenharmony_ci      }
1710370b324cSopenharmony_ci
1711370b324cSopenharmony_ci      sendMailW((LHANDLE)0, 0, &m, MAPI_DIALOG, 0);
1712370b324cSopenharmony_ci    }
1713370b324cSopenharmony_ci   }
1714370b324cSopenharmony_ci   else
1715370b324cSopenharmony_ci   {
1716370b324cSopenharmony_ci    const
1717370b324cSopenharmony_ci    LPMAPISENDMAIL sendMail = Z7_GET_PROC_ADDRESS(
1718370b324cSopenharmony_ci    LPMAPISENDMAIL, mapiLib.Get_HMODULE(),
1719370b324cSopenharmony_ci     "MAPISendMail");
1720370b324cSopenharmony_ci    if (!sendMail)
1721370b324cSopenharmony_ci    {
1722370b324cSopenharmony_ci      errorInfo.SetFromLastError("7-Zip cannot find MAPISendMail function");
1723370b324cSopenharmony_ci      return errorInfo.Get_HRESULT_Error();
1724370b324cSopenharmony_ci    }
1725370b324cSopenharmony_ci
1726370b324cSopenharmony_ci    CCurrentDirRestorer curDirRestorer;
1727370b324cSopenharmony_ci
1728370b324cSopenharmony_ci    AStringVector paths;
1729370b324cSopenharmony_ci    AStringVector names;
1730370b324cSopenharmony_ci
1731370b324cSopenharmony_ci    for (i = 0; i < fullPaths.Size(); i++)
1732370b324cSopenharmony_ci    {
1733370b324cSopenharmony_ci      const UString arcPath2 = fs2us(fullPaths[i]);
1734370b324cSopenharmony_ci      const UString fileName = ExtractFileNameFromPath(arcPath2);
1735370b324cSopenharmony_ci      paths.Add(GetAnsiString(arcPath2));
1736370b324cSopenharmony_ci      names.Add(GetAnsiString(fileName));
1737370b324cSopenharmony_ci      // const AString path (GetAnsiString(arcPath2));
1738370b324cSopenharmony_ci      // const AString name (GetAnsiString(fileName));
1739370b324cSopenharmony_ci      // Warning!!! MAPISendDocuments function changes Current directory
1740370b324cSopenharmony_ci      // fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
1741370b324cSopenharmony_ci    }
1742370b324cSopenharmony_ci
1743370b324cSopenharmony_ci    CRecordVector<MapiFileDesc> files;
1744370b324cSopenharmony_ci    files.ClearAndSetSize(paths.Size());
1745370b324cSopenharmony_ci
1746370b324cSopenharmony_ci    for (i = 0; i < paths.Size(); i++)
1747370b324cSopenharmony_ci    {
1748370b324cSopenharmony_ci      MapiFileDesc &f = files[i];
1749370b324cSopenharmony_ci      memset(&f, 0, sizeof(f));
1750370b324cSopenharmony_ci      f.nPosition = 0xFFFFFFFF;
1751370b324cSopenharmony_ci      f.lpszPathName = paths[i].Ptr_non_const();
1752370b324cSopenharmony_ci      f.lpszFileName = names[i].Ptr_non_const();
1753370b324cSopenharmony_ci    }
1754370b324cSopenharmony_ci
1755370b324cSopenharmony_ci    {
1756370b324cSopenharmony_ci      MapiMessage m;
1757370b324cSopenharmony_ci      memset(&m, 0, sizeof(m));
1758370b324cSopenharmony_ci      m.nFileCount = files.Size();
1759370b324cSopenharmony_ci      m.lpFiles = &files.Front();
1760370b324cSopenharmony_ci
1761370b324cSopenharmony_ci      const AString addr (GetAnsiString(options.EMailAddress));
1762370b324cSopenharmony_ci      MapiRecipDesc rec;
1763370b324cSopenharmony_ci      if (!addr.IsEmpty())
1764370b324cSopenharmony_ci      {
1765370b324cSopenharmony_ci        memset(&rec, 0, sizeof(rec));
1766370b324cSopenharmony_ci        rec.ulRecipClass = MAPI_TO;
1767370b324cSopenharmony_ci        rec.lpszAddress = addr.Ptr_non_const();
1768370b324cSopenharmony_ci        m.nRecipCount = 1;
1769370b324cSopenharmony_ci        m.lpRecips = &rec;
1770370b324cSopenharmony_ci      }
1771370b324cSopenharmony_ci
1772370b324cSopenharmony_ci      sendMail((LHANDLE)0, 0, &m, MAPI_DIALOG, 0);
1773370b324cSopenharmony_ci    }
1774370b324cSopenharmony_ci   }
1775370b324cSopenharmony_ci  }
1776370b324cSopenharmony_ci
1777370b324cSopenharmony_ci  #endif
1778370b324cSopenharmony_ci
1779370b324cSopenharmony_ci  if (options.DeleteAfterCompressing)
1780370b324cSopenharmony_ci  {
1781370b324cSopenharmony_ci    CRecordVector<CDirPathSortPair> pairs;
1782370b324cSopenharmony_ci    FStringVector foldersNames;
1783370b324cSopenharmony_ci
1784370b324cSopenharmony_ci    unsigned i;
1785370b324cSopenharmony_ci
1786370b324cSopenharmony_ci    for (i = 0; i < dirItems.Items.Size(); i++)
1787370b324cSopenharmony_ci    {
1788370b324cSopenharmony_ci      const CDirItem &dirItem = dirItems.Items[i];
1789370b324cSopenharmony_ci      const FString phyPath = dirItems.GetPhyPath(i);
1790370b324cSopenharmony_ci      if (dirItem.IsDir())
1791370b324cSopenharmony_ci      {
1792370b324cSopenharmony_ci        CDirPathSortPair pair;
1793370b324cSopenharmony_ci        pair.Index = i;
1794370b324cSopenharmony_ci        pair.SetNumSlashes(phyPath);
1795370b324cSopenharmony_ci        pairs.Add(pair);
1796370b324cSopenharmony_ci      }
1797370b324cSopenharmony_ci      else
1798370b324cSopenharmony_ci      {
1799370b324cSopenharmony_ci        // 21.04: we have set processedItems[*] before for all required items
1800370b324cSopenharmony_ci        if (processedItems[i] != 0
1801370b324cSopenharmony_ci            // || dirItem.Size == 0
1802370b324cSopenharmony_ci            // || dirItem.AreReparseData()
1803370b324cSopenharmony_ci            )
1804370b324cSopenharmony_ci        {
1805370b324cSopenharmony_ci          NFind::CFileInfo fileInfo;
1806370b324cSopenharmony_ci          /* if (!SymLinks), we follow link here, similar to (dirItem) filling */
1807370b324cSopenharmony_ci          if (fileInfo.Find(phyPath, !options.SymLinks.Val))
1808370b324cSopenharmony_ci          {
1809370b324cSopenharmony_ci            bool is_SameSize = false;
1810370b324cSopenharmony_ci            if (options.SymLinks.Val && dirItem.AreReparseData())
1811370b324cSopenharmony_ci            {
1812370b324cSopenharmony_ci              /* (dirItem.Size = dirItem.ReparseData.Size()) was set before.
1813370b324cSopenharmony_ci                 So we don't compare sizes for that case here */
1814370b324cSopenharmony_ci              is_SameSize = fileInfo.IsOsSymLink();
1815370b324cSopenharmony_ci            }
1816370b324cSopenharmony_ci            else
1817370b324cSopenharmony_ci              is_SameSize = (fileInfo.Size == dirItem.Size);
1818370b324cSopenharmony_ci
1819370b324cSopenharmony_ci            if (is_SameSize
1820370b324cSopenharmony_ci                && Compare_FiTime(&fileInfo.MTime, &dirItem.MTime) == 0
1821370b324cSopenharmony_ci                && Compare_FiTime(&fileInfo.CTime, &dirItem.CTime) == 0)
1822370b324cSopenharmony_ci            {
1823370b324cSopenharmony_ci              RINOK(callback->DeletingAfterArchiving(phyPath, false))
1824370b324cSopenharmony_ci              DeleteFileAlways(phyPath);
1825370b324cSopenharmony_ci            }
1826370b324cSopenharmony_ci          }
1827370b324cSopenharmony_ci        }
1828370b324cSopenharmony_ci        else
1829370b324cSopenharmony_ci        {
1830370b324cSopenharmony_ci          // file was skipped by some reason. We can throw error for debug:
1831370b324cSopenharmony_ci          /*
1832370b324cSopenharmony_ci          errorInfo.SystemError = 0;
1833370b324cSopenharmony_ci          errorInfo.Message = "file was not processed";
1834370b324cSopenharmony_ci          errorInfo.FileNames.Add(phyPath);
1835370b324cSopenharmony_ci          return E_FAIL;
1836370b324cSopenharmony_ci          */
1837370b324cSopenharmony_ci        }
1838370b324cSopenharmony_ci      }
1839370b324cSopenharmony_ci    }
1840370b324cSopenharmony_ci
1841370b324cSopenharmony_ci    pairs.Sort2();
1842370b324cSopenharmony_ci
1843370b324cSopenharmony_ci    for (i = 0; i < pairs.Size(); i++)
1844370b324cSopenharmony_ci    {
1845370b324cSopenharmony_ci      const FString phyPath = dirItems.GetPhyPath(pairs[i].Index);
1846370b324cSopenharmony_ci      if (NFind::DoesDirExist(phyPath))
1847370b324cSopenharmony_ci      {
1848370b324cSopenharmony_ci        RINOK(callback->DeletingAfterArchiving(phyPath, true))
1849370b324cSopenharmony_ci        RemoveDir(phyPath);
1850370b324cSopenharmony_ci      }
1851370b324cSopenharmony_ci    }
1852370b324cSopenharmony_ci
1853370b324cSopenharmony_ci    RINOK(callback->FinishDeletingAfterArchiving())
1854370b324cSopenharmony_ci  }
1855370b324cSopenharmony_ci
1856370b324cSopenharmony_ci  return S_OK;
1857370b324cSopenharmony_ci}
1858