xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/Common/Update.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // Update.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker // #include  <stdio.h>
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include "Update.h"
8*f6dc9357SAndroid Build Coastguard Worker 
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringConvert.h"
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/DLL.h"
12*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileDir.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileFind.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileName.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariant.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariantConv.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/TimeUtils.h"
18*f6dc9357SAndroid Build Coastguard Worker 
19*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/FileStreams.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/LimitedStreams.h"
21*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MultiOutStream.h"
22*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamUtils.h"
23*f6dc9357SAndroid Build Coastguard Worker 
24*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/CopyCoder.h"
25*f6dc9357SAndroid Build Coastguard Worker 
26*f6dc9357SAndroid Build Coastguard Worker #include "../Common/DirItem.h"
27*f6dc9357SAndroid Build Coastguard Worker #include "../Common/EnumDirItems.h"
28*f6dc9357SAndroid Build Coastguard Worker #include "../Common/OpenArchive.h"
29*f6dc9357SAndroid Build Coastguard Worker #include "../Common/UpdateProduce.h"
30*f6dc9357SAndroid Build Coastguard Worker 
31*f6dc9357SAndroid Build Coastguard Worker #include "EnumDirItems.h"
32*f6dc9357SAndroid Build Coastguard Worker #include "SetProperties.h"
33*f6dc9357SAndroid Build Coastguard Worker #include "TempFiles.h"
34*f6dc9357SAndroid Build Coastguard Worker #include "UpdateCallback.h"
35*f6dc9357SAndroid Build Coastguard Worker 
36*f6dc9357SAndroid Build Coastguard Worker static const char * const kUpdateIsNotSupoorted =
37*f6dc9357SAndroid Build Coastguard Worker   "update operations are not supported for this archive";
38*f6dc9357SAndroid Build Coastguard Worker 
39*f6dc9357SAndroid Build Coastguard Worker static const char * const kUpdateIsNotSupported_MultiVol =
40*f6dc9357SAndroid Build Coastguard Worker   "Updating for multivolume archives is not implemented";
41*f6dc9357SAndroid Build Coastguard Worker 
42*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
43*f6dc9357SAndroid Build Coastguard Worker using namespace NCOM;
44*f6dc9357SAndroid Build Coastguard Worker using namespace NFile;
45*f6dc9357SAndroid Build Coastguard Worker using namespace NDir;
46*f6dc9357SAndroid Build Coastguard Worker using namespace NName;
47*f6dc9357SAndroid Build Coastguard Worker 
48*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
49*f6dc9357SAndroid Build Coastguard Worker static CFSTR const kTempFolderPrefix = FTEXT("7zE");
50*f6dc9357SAndroid Build Coastguard Worker #endif
51*f6dc9357SAndroid Build Coastguard Worker 
SetFromLastError(const char * message)52*f6dc9357SAndroid Build Coastguard Worker void CUpdateErrorInfo::SetFromLastError(const char *message)
53*f6dc9357SAndroid Build Coastguard Worker {
54*f6dc9357SAndroid Build Coastguard Worker   SystemError = ::GetLastError();
55*f6dc9357SAndroid Build Coastguard Worker   Message = message;
56*f6dc9357SAndroid Build Coastguard Worker }
57*f6dc9357SAndroid Build Coastguard Worker 
SetFromLastError(const char * message,const FString & fileName)58*f6dc9357SAndroid Build Coastguard Worker HRESULT CUpdateErrorInfo::SetFromLastError(const char *message, const FString &fileName)
59*f6dc9357SAndroid Build Coastguard Worker {
60*f6dc9357SAndroid Build Coastguard Worker   SetFromLastError(message);
61*f6dc9357SAndroid Build Coastguard Worker   FileNames.Add(fileName);
62*f6dc9357SAndroid Build Coastguard Worker   return Get_HRESULT_Error();
63*f6dc9357SAndroid Build Coastguard Worker }
64*f6dc9357SAndroid Build Coastguard Worker 
SetFromError_DWORD(const char * message,const FString & fileName,DWORD error)65*f6dc9357SAndroid Build Coastguard Worker HRESULT CUpdateErrorInfo::SetFromError_DWORD(const char *message, const FString &fileName, DWORD error)
66*f6dc9357SAndroid Build Coastguard Worker {
67*f6dc9357SAndroid Build Coastguard Worker   Message = message;
68*f6dc9357SAndroid Build Coastguard Worker   FileNames.Add(fileName);
69*f6dc9357SAndroid Build Coastguard Worker   SystemError = error;
70*f6dc9357SAndroid Build Coastguard Worker   return Get_HRESULT_Error();
71*f6dc9357SAndroid Build Coastguard Worker }
72*f6dc9357SAndroid Build Coastguard Worker 
73*f6dc9357SAndroid Build Coastguard Worker 
74*f6dc9357SAndroid Build Coastguard Worker using namespace NUpdateArchive;
75*f6dc9357SAndroid Build Coastguard Worker 
76*f6dc9357SAndroid Build Coastguard Worker struct CMultiOutStream_Rec
77*f6dc9357SAndroid Build Coastguard Worker {
78*f6dc9357SAndroid Build Coastguard Worker   CMultiOutStream *Spec;
79*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IOutStream> Ref;
80*f6dc9357SAndroid Build Coastguard Worker };
81*f6dc9357SAndroid Build Coastguard Worker 
82*f6dc9357SAndroid Build Coastguard Worker struct CMultiOutStream_Bunch
83*f6dc9357SAndroid Build Coastguard Worker {
84*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CMultiOutStream_Rec> Items;
85*f6dc9357SAndroid Build Coastguard Worker 
DestructCMultiOutStream_Bunch86*f6dc9357SAndroid Build Coastguard Worker   HRESULT Destruct()
87*f6dc9357SAndroid Build Coastguard Worker   {
88*f6dc9357SAndroid Build Coastguard Worker     HRESULT hres = S_OK;
89*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, Items)
90*f6dc9357SAndroid Build Coastguard Worker     {
91*f6dc9357SAndroid Build Coastguard Worker       CMultiOutStream_Rec &rec = Items[i];
92*f6dc9357SAndroid Build Coastguard Worker       if (rec.Ref)
93*f6dc9357SAndroid Build Coastguard Worker       {
94*f6dc9357SAndroid Build Coastguard Worker         const HRESULT hres2 = rec.Spec->Destruct();
95*f6dc9357SAndroid Build Coastguard Worker         if (hres == S_OK)
96*f6dc9357SAndroid Build Coastguard Worker           hres = hres2;
97*f6dc9357SAndroid Build Coastguard Worker       }
98*f6dc9357SAndroid Build Coastguard Worker     }
99*f6dc9357SAndroid Build Coastguard Worker     Items.Clear();
100*f6dc9357SAndroid Build Coastguard Worker     return hres;
101*f6dc9357SAndroid Build Coastguard Worker   }
102*f6dc9357SAndroid Build Coastguard Worker 
DisableDeletionCMultiOutStream_Bunch103*f6dc9357SAndroid Build Coastguard Worker   void DisableDeletion()
104*f6dc9357SAndroid Build Coastguard Worker   {
105*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, Items)
106*f6dc9357SAndroid Build Coastguard Worker     {
107*f6dc9357SAndroid Build Coastguard Worker       CMultiOutStream_Rec &rec = Items[i];
108*f6dc9357SAndroid Build Coastguard Worker       if (rec.Ref)
109*f6dc9357SAndroid Build Coastguard Worker         rec.Spec->NeedDelete = false;
110*f6dc9357SAndroid Build Coastguard Worker     }
111*f6dc9357SAndroid Build Coastguard Worker   }
112*f6dc9357SAndroid Build Coastguard Worker };
113*f6dc9357SAndroid Build Coastguard Worker 
114*f6dc9357SAndroid Build Coastguard Worker 
ParseFromPath(const UString & path,EArcNameMode mode)115*f6dc9357SAndroid Build Coastguard Worker void CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode)
116*f6dc9357SAndroid Build Coastguard Worker {
117*f6dc9357SAndroid Build Coastguard Worker   OriginalPath = path;
118*f6dc9357SAndroid Build Coastguard Worker 
119*f6dc9357SAndroid Build Coastguard Worker   SplitPathToParts_2(path, Prefix, Name);
120*f6dc9357SAndroid Build Coastguard Worker 
121*f6dc9357SAndroid Build Coastguard Worker   if (mode == k_ArcNameMode_Add)
122*f6dc9357SAndroid Build Coastguard Worker     return;
123*f6dc9357SAndroid Build Coastguard Worker 
124*f6dc9357SAndroid Build Coastguard Worker   if (mode != k_ArcNameMode_Exact)
125*f6dc9357SAndroid Build Coastguard Worker   {
126*f6dc9357SAndroid Build Coastguard Worker     int dotPos = Name.ReverseFind_Dot();
127*f6dc9357SAndroid Build Coastguard Worker     if (dotPos < 0)
128*f6dc9357SAndroid Build Coastguard Worker       return;
129*f6dc9357SAndroid Build Coastguard Worker     if ((unsigned)dotPos == Name.Len() - 1)
130*f6dc9357SAndroid Build Coastguard Worker       Name.DeleteBack();
131*f6dc9357SAndroid Build Coastguard Worker     else
132*f6dc9357SAndroid Build Coastguard Worker     {
133*f6dc9357SAndroid Build Coastguard Worker       const UString ext = Name.Ptr((unsigned)(dotPos + 1));
134*f6dc9357SAndroid Build Coastguard Worker       if (BaseExtension.IsEqualTo_NoCase(ext))
135*f6dc9357SAndroid Build Coastguard Worker       {
136*f6dc9357SAndroid Build Coastguard Worker         BaseExtension = ext;
137*f6dc9357SAndroid Build Coastguard Worker         Name.DeleteFrom((unsigned)dotPos);
138*f6dc9357SAndroid Build Coastguard Worker         return;
139*f6dc9357SAndroid Build Coastguard Worker       }
140*f6dc9357SAndroid Build Coastguard Worker     }
141*f6dc9357SAndroid Build Coastguard Worker   }
142*f6dc9357SAndroid Build Coastguard Worker 
143*f6dc9357SAndroid Build Coastguard Worker   BaseExtension.Empty();
144*f6dc9357SAndroid Build Coastguard Worker }
145*f6dc9357SAndroid Build Coastguard Worker 
GetFinalPath() const146*f6dc9357SAndroid Build Coastguard Worker UString CArchivePath::GetFinalPath() const
147*f6dc9357SAndroid Build Coastguard Worker {
148*f6dc9357SAndroid Build Coastguard Worker   UString path = GetPathWithoutExt();
149*f6dc9357SAndroid Build Coastguard Worker   if (!BaseExtension.IsEmpty())
150*f6dc9357SAndroid Build Coastguard Worker   {
151*f6dc9357SAndroid Build Coastguard Worker     path.Add_Dot();
152*f6dc9357SAndroid Build Coastguard Worker     path += BaseExtension;
153*f6dc9357SAndroid Build Coastguard Worker   }
154*f6dc9357SAndroid Build Coastguard Worker   return path;
155*f6dc9357SAndroid Build Coastguard Worker }
156*f6dc9357SAndroid Build Coastguard Worker 
GetFinalVolPath() const157*f6dc9357SAndroid Build Coastguard Worker UString CArchivePath::GetFinalVolPath() const
158*f6dc9357SAndroid Build Coastguard Worker {
159*f6dc9357SAndroid Build Coastguard Worker   UString path = GetPathWithoutExt();
160*f6dc9357SAndroid Build Coastguard Worker   // if BaseExtension is empty, we must ignore VolExtension also.
161*f6dc9357SAndroid Build Coastguard Worker   if (!BaseExtension.IsEmpty())
162*f6dc9357SAndroid Build Coastguard Worker   {
163*f6dc9357SAndroid Build Coastguard Worker     path.Add_Dot();
164*f6dc9357SAndroid Build Coastguard Worker     path += VolExtension;
165*f6dc9357SAndroid Build Coastguard Worker   }
166*f6dc9357SAndroid Build Coastguard Worker   return path;
167*f6dc9357SAndroid Build Coastguard Worker }
168*f6dc9357SAndroid Build Coastguard Worker 
GetTempPath() const169*f6dc9357SAndroid Build Coastguard Worker FString CArchivePath::GetTempPath() const
170*f6dc9357SAndroid Build Coastguard Worker {
171*f6dc9357SAndroid Build Coastguard Worker   FString path = TempPrefix;
172*f6dc9357SAndroid Build Coastguard Worker   path += us2fs(Name);
173*f6dc9357SAndroid Build Coastguard Worker   if (!BaseExtension.IsEmpty())
174*f6dc9357SAndroid Build Coastguard Worker   {
175*f6dc9357SAndroid Build Coastguard Worker     path.Add_Dot();
176*f6dc9357SAndroid Build Coastguard Worker     path += us2fs(BaseExtension);
177*f6dc9357SAndroid Build Coastguard Worker   }
178*f6dc9357SAndroid Build Coastguard Worker   path += ".tmp";
179*f6dc9357SAndroid Build Coastguard Worker   path += TempPostfix;
180*f6dc9357SAndroid Build Coastguard Worker   return path;
181*f6dc9357SAndroid Build Coastguard Worker }
182*f6dc9357SAndroid Build Coastguard Worker 
183*f6dc9357SAndroid Build Coastguard Worker static const char * const kDefaultArcType = "7z";
184*f6dc9357SAndroid Build Coastguard Worker static const char * const kDefaultArcExt = "7z";
185*f6dc9357SAndroid Build Coastguard Worker static const char * const kSFXExtension =
186*f6dc9357SAndroid Build Coastguard Worker   #ifdef _WIN32
187*f6dc9357SAndroid Build Coastguard Worker     "exe";
188*f6dc9357SAndroid Build Coastguard Worker   #else
189*f6dc9357SAndroid Build Coastguard Worker     "";
190*f6dc9357SAndroid Build Coastguard Worker   #endif
191*f6dc9357SAndroid Build Coastguard Worker 
InitFormatIndex(const CCodecs * codecs,const CObjectVector<COpenType> & types,const UString & arcPath)192*f6dc9357SAndroid Build Coastguard Worker bool CUpdateOptions::InitFormatIndex(const CCodecs *codecs,
193*f6dc9357SAndroid Build Coastguard Worker     const CObjectVector<COpenType> &types, const UString &arcPath)
194*f6dc9357SAndroid Build Coastguard Worker {
195*f6dc9357SAndroid Build Coastguard Worker   if (types.Size() > 1)
196*f6dc9357SAndroid Build Coastguard Worker     return false;
197*f6dc9357SAndroid Build Coastguard Worker   // int arcTypeIndex = -1;
198*f6dc9357SAndroid Build Coastguard Worker   if (types.Size() != 0)
199*f6dc9357SAndroid Build Coastguard Worker   {
200*f6dc9357SAndroid Build Coastguard Worker     MethodMode.Type = types[0];
201*f6dc9357SAndroid Build Coastguard Worker     MethodMode.Type_Defined = true;
202*f6dc9357SAndroid Build Coastguard Worker   }
203*f6dc9357SAndroid Build Coastguard Worker   if (MethodMode.Type.FormatIndex < 0)
204*f6dc9357SAndroid Build Coastguard Worker   {
205*f6dc9357SAndroid Build Coastguard Worker     // MethodMode.Type = -1;
206*f6dc9357SAndroid Build Coastguard Worker     MethodMode.Type = COpenType();
207*f6dc9357SAndroid Build Coastguard Worker     if (ArcNameMode != k_ArcNameMode_Add)
208*f6dc9357SAndroid Build Coastguard Worker     {
209*f6dc9357SAndroid Build Coastguard Worker       MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveName(arcPath);
210*f6dc9357SAndroid Build Coastguard Worker       if (MethodMode.Type.FormatIndex >= 0)
211*f6dc9357SAndroid Build Coastguard Worker         MethodMode.Type_Defined = true;
212*f6dc9357SAndroid Build Coastguard Worker     }
213*f6dc9357SAndroid Build Coastguard Worker   }
214*f6dc9357SAndroid Build Coastguard Worker   return true;
215*f6dc9357SAndroid Build Coastguard Worker }
216*f6dc9357SAndroid Build Coastguard Worker 
SetArcPath(const CCodecs * codecs,const UString & arcPath)217*f6dc9357SAndroid Build Coastguard Worker bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath)
218*f6dc9357SAndroid Build Coastguard Worker {
219*f6dc9357SAndroid Build Coastguard Worker   UString typeExt;
220*f6dc9357SAndroid Build Coastguard Worker   int formatIndex = MethodMode.Type.FormatIndex;
221*f6dc9357SAndroid Build Coastguard Worker   if (formatIndex < 0)
222*f6dc9357SAndroid Build Coastguard Worker   {
223*f6dc9357SAndroid Build Coastguard Worker     typeExt = kDefaultArcExt;
224*f6dc9357SAndroid Build Coastguard Worker   }
225*f6dc9357SAndroid Build Coastguard Worker   else
226*f6dc9357SAndroid Build Coastguard Worker   {
227*f6dc9357SAndroid Build Coastguard Worker     const CArcInfoEx &arcInfo = codecs->Formats[(unsigned)formatIndex];
228*f6dc9357SAndroid Build Coastguard Worker     if (!arcInfo.UpdateEnabled)
229*f6dc9357SAndroid Build Coastguard Worker       return false;
230*f6dc9357SAndroid Build Coastguard Worker     typeExt = arcInfo.GetMainExt();
231*f6dc9357SAndroid Build Coastguard Worker   }
232*f6dc9357SAndroid Build Coastguard Worker   UString ext = typeExt;
233*f6dc9357SAndroid Build Coastguard Worker   if (SfxMode)
234*f6dc9357SAndroid Build Coastguard Worker     ext = kSFXExtension;
235*f6dc9357SAndroid Build Coastguard Worker   ArchivePath.BaseExtension = ext;
236*f6dc9357SAndroid Build Coastguard Worker   ArchivePath.VolExtension = typeExt;
237*f6dc9357SAndroid Build Coastguard Worker   ArchivePath.ParseFromPath(arcPath, ArcNameMode);
238*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, Commands)
239*f6dc9357SAndroid Build Coastguard Worker   {
240*f6dc9357SAndroid Build Coastguard Worker     CUpdateArchiveCommand &uc = Commands[i];
241*f6dc9357SAndroid Build Coastguard Worker     uc.ArchivePath.BaseExtension = ext;
242*f6dc9357SAndroid Build Coastguard Worker     uc.ArchivePath.VolExtension = typeExt;
243*f6dc9357SAndroid Build Coastguard Worker     uc.ArchivePath.ParseFromPath(uc.UserArchivePath, ArcNameMode);
244*f6dc9357SAndroid Build Coastguard Worker   }
245*f6dc9357SAndroid Build Coastguard Worker   return true;
246*f6dc9357SAndroid Build Coastguard Worker }
247*f6dc9357SAndroid Build Coastguard Worker 
248*f6dc9357SAndroid Build Coastguard Worker 
249*f6dc9357SAndroid Build Coastguard Worker struct CUpdateProduceCallbackImp Z7_final: public IUpdateProduceCallback
250*f6dc9357SAndroid Build Coastguard Worker {
251*f6dc9357SAndroid Build Coastguard Worker   const CObjectVector<CArcItem> *_arcItems;
252*f6dc9357SAndroid Build Coastguard Worker   CDirItemsStat *_stat;
253*f6dc9357SAndroid Build Coastguard Worker   IUpdateCallbackUI *_callback;
254*f6dc9357SAndroid Build Coastguard Worker 
CUpdateProduceCallbackImpZ7_final255*f6dc9357SAndroid Build Coastguard Worker   CUpdateProduceCallbackImp(
256*f6dc9357SAndroid Build Coastguard Worker       const CObjectVector<CArcItem> *a,
257*f6dc9357SAndroid Build Coastguard Worker       CDirItemsStat *stat,
258*f6dc9357SAndroid Build Coastguard Worker       IUpdateCallbackUI *callback):
259*f6dc9357SAndroid Build Coastguard Worker     _arcItems(a),
260*f6dc9357SAndroid Build Coastguard Worker     _stat(stat),
261*f6dc9357SAndroid Build Coastguard Worker     _callback(callback) {}
262*f6dc9357SAndroid Build Coastguard Worker 
263*f6dc9357SAndroid Build Coastguard Worker   virtual HRESULT ShowDeleteFile(unsigned arcIndex) Z7_override;
264*f6dc9357SAndroid Build Coastguard Worker };
265*f6dc9357SAndroid Build Coastguard Worker 
266*f6dc9357SAndroid Build Coastguard Worker 
ShowDeleteFile(unsigned arcIndex)267*f6dc9357SAndroid Build Coastguard Worker HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(unsigned arcIndex)
268*f6dc9357SAndroid Build Coastguard Worker {
269*f6dc9357SAndroid Build Coastguard Worker   const CArcItem &ai = (*_arcItems)[arcIndex];
270*f6dc9357SAndroid Build Coastguard Worker   {
271*f6dc9357SAndroid Build Coastguard Worker     CDirItemsStat &stat = *_stat;
272*f6dc9357SAndroid Build Coastguard Worker     if (ai.IsDir)
273*f6dc9357SAndroid Build Coastguard Worker       stat.NumDirs++;
274*f6dc9357SAndroid Build Coastguard Worker     else if (ai.IsAltStream)
275*f6dc9357SAndroid Build Coastguard Worker     {
276*f6dc9357SAndroid Build Coastguard Worker       stat.NumAltStreams++;
277*f6dc9357SAndroid Build Coastguard Worker       stat.AltStreamsSize += ai.Size;
278*f6dc9357SAndroid Build Coastguard Worker     }
279*f6dc9357SAndroid Build Coastguard Worker     else
280*f6dc9357SAndroid Build Coastguard Worker     {
281*f6dc9357SAndroid Build Coastguard Worker       stat.NumFiles++;
282*f6dc9357SAndroid Build Coastguard Worker       stat.FilesSize += ai.Size;
283*f6dc9357SAndroid Build Coastguard Worker     }
284*f6dc9357SAndroid Build Coastguard Worker   }
285*f6dc9357SAndroid Build Coastguard Worker   return _callback->ShowDeleteFile(ai.Name, ai.IsDir);
286*f6dc9357SAndroid Build Coastguard Worker }
287*f6dc9357SAndroid Build Coastguard Worker 
Prepare()288*f6dc9357SAndroid Build Coastguard Worker bool CRenamePair::Prepare()
289*f6dc9357SAndroid Build Coastguard Worker {
290*f6dc9357SAndroid Build Coastguard Worker   if (RecursedType != NRecursedType::kNonRecursed)
291*f6dc9357SAndroid Build Coastguard Worker     return false;
292*f6dc9357SAndroid Build Coastguard Worker   if (!WildcardParsing)
293*f6dc9357SAndroid Build Coastguard Worker     return true;
294*f6dc9357SAndroid Build Coastguard Worker   return !DoesNameContainWildcard(OldName);
295*f6dc9357SAndroid Build Coastguard Worker }
296*f6dc9357SAndroid Build Coastguard Worker 
297*f6dc9357SAndroid Build Coastguard Worker extern bool g_CaseSensitive;
298*f6dc9357SAndroid Build Coastguard Worker 
CompareTwoNames(const wchar_t * s1,const wchar_t * s2)299*f6dc9357SAndroid Build Coastguard Worker static unsigned CompareTwoNames(const wchar_t *s1, const wchar_t *s2)
300*f6dc9357SAndroid Build Coastguard Worker {
301*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0;; i++)
302*f6dc9357SAndroid Build Coastguard Worker   {
303*f6dc9357SAndroid Build Coastguard Worker     wchar_t c1 = s1[i];
304*f6dc9357SAndroid Build Coastguard Worker     wchar_t c2 = s2[i];
305*f6dc9357SAndroid Build Coastguard Worker     if (c1 == 0 || c2 == 0)
306*f6dc9357SAndroid Build Coastguard Worker       return i;
307*f6dc9357SAndroid Build Coastguard Worker     if (c1 == c2)
308*f6dc9357SAndroid Build Coastguard Worker       continue;
309*f6dc9357SAndroid Build Coastguard Worker     if (!g_CaseSensitive && (MyCharUpper(c1) == MyCharUpper(c2)))
310*f6dc9357SAndroid Build Coastguard Worker       continue;
311*f6dc9357SAndroid Build Coastguard Worker     if (IsPathSepar(c1) && IsPathSepar(c2))
312*f6dc9357SAndroid Build Coastguard Worker       continue;
313*f6dc9357SAndroid Build Coastguard Worker     return i;
314*f6dc9357SAndroid Build Coastguard Worker   }
315*f6dc9357SAndroid Build Coastguard Worker }
316*f6dc9357SAndroid Build Coastguard Worker 
GetNewPath(bool isFolder,const UString & src,UString & dest) const317*f6dc9357SAndroid Build Coastguard Worker bool CRenamePair::GetNewPath(bool isFolder, const UString &src, UString &dest) const
318*f6dc9357SAndroid Build Coastguard Worker {
319*f6dc9357SAndroid Build Coastguard Worker   unsigned num = CompareTwoNames(OldName, src);
320*f6dc9357SAndroid Build Coastguard Worker   if (OldName[num] == 0)
321*f6dc9357SAndroid Build Coastguard Worker   {
322*f6dc9357SAndroid Build Coastguard Worker     if (src[num] != 0 && !IsPathSepar(src[num]) && num != 0 && !IsPathSepar(src[num - 1]))
323*f6dc9357SAndroid Build Coastguard Worker       return false;
324*f6dc9357SAndroid Build Coastguard Worker   }
325*f6dc9357SAndroid Build Coastguard Worker   else
326*f6dc9357SAndroid Build Coastguard Worker   {
327*f6dc9357SAndroid Build Coastguard Worker     // OldName[num] != 0
328*f6dc9357SAndroid Build Coastguard Worker     // OldName = "1\1a.txt"
329*f6dc9357SAndroid Build Coastguard Worker     // src = "1"
330*f6dc9357SAndroid Build Coastguard Worker 
331*f6dc9357SAndroid Build Coastguard Worker     if (!isFolder
332*f6dc9357SAndroid Build Coastguard Worker         || src[num] != 0
333*f6dc9357SAndroid Build Coastguard Worker         || !IsPathSepar(OldName[num])
334*f6dc9357SAndroid Build Coastguard Worker         || OldName[num + 1] != 0)
335*f6dc9357SAndroid Build Coastguard Worker       return false;
336*f6dc9357SAndroid Build Coastguard Worker   }
337*f6dc9357SAndroid Build Coastguard Worker   dest = NewName + src.Ptr(num);
338*f6dc9357SAndroid Build Coastguard Worker   return true;
339*f6dc9357SAndroid Build Coastguard Worker }
340*f6dc9357SAndroid Build Coastguard Worker 
341*f6dc9357SAndroid Build Coastguard Worker #ifdef SUPPORT_ALT_STREAMS
342*f6dc9357SAndroid Build Coastguard Worker int FindAltStreamColon_in_Path(const wchar_t *path);
343*f6dc9357SAndroid Build Coastguard Worker #endif
344*f6dc9357SAndroid Build Coastguard Worker 
345*f6dc9357SAndroid Build Coastguard Worker 
346*f6dc9357SAndroid Build Coastguard Worker 
Compress(const CUpdateOptions & options,bool isUpdatingItself,CCodecs * codecs,const CActionSet & actionSet,const CArc * arc,CArchivePath & archivePath,const CObjectVector<CArcItem> & arcItems,Byte * processedItemsStatuses,const CDirItems & dirItems,const CDirItem * parentDirItem,CTempFiles & tempFiles,CMultiOutStream_Bunch & multiStreams,CUpdateErrorInfo & errorInfo,IUpdateCallbackUI * callback,CFinishArchiveStat & st)347*f6dc9357SAndroid Build Coastguard Worker static HRESULT Compress(
348*f6dc9357SAndroid Build Coastguard Worker     const CUpdateOptions &options,
349*f6dc9357SAndroid Build Coastguard Worker     bool isUpdatingItself,
350*f6dc9357SAndroid Build Coastguard Worker     CCodecs *codecs,
351*f6dc9357SAndroid Build Coastguard Worker     const CActionSet &actionSet,
352*f6dc9357SAndroid Build Coastguard Worker     const CArc *arc,
353*f6dc9357SAndroid Build Coastguard Worker     CArchivePath &archivePath,
354*f6dc9357SAndroid Build Coastguard Worker     const CObjectVector<CArcItem> &arcItems,
355*f6dc9357SAndroid Build Coastguard Worker     Byte *processedItemsStatuses,
356*f6dc9357SAndroid Build Coastguard Worker     const CDirItems &dirItems,
357*f6dc9357SAndroid Build Coastguard Worker     const CDirItem *parentDirItem,
358*f6dc9357SAndroid Build Coastguard Worker     CTempFiles &tempFiles,
359*f6dc9357SAndroid Build Coastguard Worker     CMultiOutStream_Bunch &multiStreams,
360*f6dc9357SAndroid Build Coastguard Worker     CUpdateErrorInfo &errorInfo,
361*f6dc9357SAndroid Build Coastguard Worker     IUpdateCallbackUI *callback,
362*f6dc9357SAndroid Build Coastguard Worker     CFinishArchiveStat &st)
363*f6dc9357SAndroid Build Coastguard Worker {
364*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IOutArchive> outArchive;
365*f6dc9357SAndroid Build Coastguard Worker   int formatIndex = options.MethodMode.Type.FormatIndex;
366*f6dc9357SAndroid Build Coastguard Worker 
367*f6dc9357SAndroid Build Coastguard Worker   if (arc)
368*f6dc9357SAndroid Build Coastguard Worker   {
369*f6dc9357SAndroid Build Coastguard Worker     formatIndex = arc->FormatIndex;
370*f6dc9357SAndroid Build Coastguard Worker     if (formatIndex < 0)
371*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
372*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<IInArchive> archive2 = arc->Archive;
373*f6dc9357SAndroid Build Coastguard Worker     HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);
374*f6dc9357SAndroid Build Coastguard Worker     if (result != S_OK)
375*f6dc9357SAndroid Build Coastguard Worker       throw kUpdateIsNotSupoorted;
376*f6dc9357SAndroid Build Coastguard Worker   }
377*f6dc9357SAndroid Build Coastguard Worker   else
378*f6dc9357SAndroid Build Coastguard Worker   {
379*f6dc9357SAndroid Build Coastguard Worker     RINOK(codecs->CreateOutArchive((unsigned)formatIndex, outArchive))
380*f6dc9357SAndroid Build Coastguard Worker 
381*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_EXTERNAL_CODECS
382*f6dc9357SAndroid Build Coastguard Worker     {
383*f6dc9357SAndroid Build Coastguard Worker       CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
384*f6dc9357SAndroid Build Coastguard Worker       outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
385*f6dc9357SAndroid Build Coastguard Worker       if (setCompressCodecsInfo)
386*f6dc9357SAndroid Build Coastguard Worker       {
387*f6dc9357SAndroid Build Coastguard Worker         RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs))
388*f6dc9357SAndroid Build Coastguard Worker       }
389*f6dc9357SAndroid Build Coastguard Worker     }
390*f6dc9357SAndroid Build Coastguard Worker     #endif
391*f6dc9357SAndroid Build Coastguard Worker   }
392*f6dc9357SAndroid Build Coastguard Worker 
393*f6dc9357SAndroid Build Coastguard Worker   if (!outArchive)
394*f6dc9357SAndroid Build Coastguard Worker     throw kUpdateIsNotSupoorted;
395*f6dc9357SAndroid Build Coastguard Worker 
396*f6dc9357SAndroid Build Coastguard Worker   // we need to set properties to get fileTimeType.
397*f6dc9357SAndroid Build Coastguard Worker   RINOK(SetProperties(outArchive, options.MethodMode.Properties))
398*f6dc9357SAndroid Build Coastguard Worker 
399*f6dc9357SAndroid Build Coastguard Worker   NFileTimeType::EEnum fileTimeType;
400*f6dc9357SAndroid Build Coastguard Worker   {
401*f6dc9357SAndroid Build Coastguard Worker     /*
402*f6dc9357SAndroid Build Coastguard Worker     how we compare file_in_archive::MTime with dirItem.MTime
403*f6dc9357SAndroid Build Coastguard Worker     for GetUpdatePairInfoList():
404*f6dc9357SAndroid Build Coastguard Worker 
405*f6dc9357SAndroid Build Coastguard Worker     if (kpidMTime is not defined), external MTime of archive is used.
406*f6dc9357SAndroid Build Coastguard Worker 
407*f6dc9357SAndroid Build Coastguard Worker     before 22.00:
408*f6dc9357SAndroid Build Coastguard Worker       if (kpidTimeType is defined)
409*f6dc9357SAndroid Build Coastguard Worker       {
410*f6dc9357SAndroid Build Coastguard Worker         kpidTimeType is used as precision.
411*f6dc9357SAndroid Build Coastguard Worker         (kpidTimeType > kDOS) is not allowed.
412*f6dc9357SAndroid Build Coastguard Worker       }
413*f6dc9357SAndroid Build Coastguard Worker       else GetFileTimeType() value is used as precision.
414*f6dc9357SAndroid Build Coastguard Worker 
415*f6dc9357SAndroid Build Coastguard Worker     22.00:
416*f6dc9357SAndroid Build Coastguard Worker       if (kpidMTime is defined)
417*f6dc9357SAndroid Build Coastguard Worker       {
418*f6dc9357SAndroid Build Coastguard Worker         if (kpidMTime::precision != 0), then kpidMTime::precision is used as precision.
419*f6dc9357SAndroid Build Coastguard Worker         else
420*f6dc9357SAndroid Build Coastguard Worker         {
421*f6dc9357SAndroid Build Coastguard Worker           if (kpidTimeType is defined), kpidTimeType is used as precision.
422*f6dc9357SAndroid Build Coastguard Worker           else GetFileTimeType() value is used as precision.
423*f6dc9357SAndroid Build Coastguard Worker         }
424*f6dc9357SAndroid Build Coastguard Worker       }
425*f6dc9357SAndroid Build Coastguard Worker       else external MTime of archive is used as precision.
426*f6dc9357SAndroid Build Coastguard Worker     */
427*f6dc9357SAndroid Build Coastguard Worker 
428*f6dc9357SAndroid Build Coastguard Worker     UInt32 value;
429*f6dc9357SAndroid Build Coastguard Worker     RINOK(outArchive->GetFileTimeType(&value))
430*f6dc9357SAndroid Build Coastguard Worker 
431*f6dc9357SAndroid Build Coastguard Worker     // we support any future fileType here.
432*f6dc9357SAndroid Build Coastguard Worker     fileTimeType = (NFileTimeType::EEnum)value;
433*f6dc9357SAndroid Build Coastguard Worker 
434*f6dc9357SAndroid Build Coastguard Worker     /*
435*f6dc9357SAndroid Build Coastguard Worker     old 21.07 code:
436*f6dc9357SAndroid Build Coastguard Worker     switch (value)
437*f6dc9357SAndroid Build Coastguard Worker     {
438*f6dc9357SAndroid Build Coastguard Worker       case NFileTimeType::kWindows:
439*f6dc9357SAndroid Build Coastguard Worker       case NFileTimeType::kUnix:
440*f6dc9357SAndroid Build Coastguard Worker       case NFileTimeType::kDOS:
441*f6dc9357SAndroid Build Coastguard Worker         fileTimeType = (NFileTimeType::EEnum)value;
442*f6dc9357SAndroid Build Coastguard Worker         break;
443*f6dc9357SAndroid Build Coastguard Worker       default:
444*f6dc9357SAndroid Build Coastguard Worker         return E_FAIL;
445*f6dc9357SAndroid Build Coastguard Worker     }
446*f6dc9357SAndroid Build Coastguard Worker     */
447*f6dc9357SAndroid Build Coastguard Worker   }
448*f6dc9357SAndroid Build Coastguard Worker 
449*f6dc9357SAndroid Build Coastguard Worker   // bool noTimestampExpected = false;
450*f6dc9357SAndroid Build Coastguard Worker   {
451*f6dc9357SAndroid Build Coastguard Worker     const CArcInfoEx &arcInfo = codecs->Formats[(unsigned)formatIndex];
452*f6dc9357SAndroid Build Coastguard Worker 
453*f6dc9357SAndroid Build Coastguard Worker     // if (arcInfo.Flags_KeepName()) noTimestampExpected = true;
454*f6dc9357SAndroid Build Coastguard Worker     if (arcInfo.Is_Xz() ||
455*f6dc9357SAndroid Build Coastguard Worker         arcInfo.Is_BZip2())
456*f6dc9357SAndroid Build Coastguard Worker     {
457*f6dc9357SAndroid Build Coastguard Worker       /* 7-zip before 22.00 returns NFileTimeType::kUnix for xz and bzip2,
458*f6dc9357SAndroid Build Coastguard Worker          but we want to set timestamp without reduction to unix. */
459*f6dc9357SAndroid Build Coastguard Worker       // noTimestampExpected = true;
460*f6dc9357SAndroid Build Coastguard Worker       fileTimeType = NFileTimeType::kNotDefined; // it means not defined
461*f6dc9357SAndroid Build Coastguard Worker     }
462*f6dc9357SAndroid Build Coastguard Worker 
463*f6dc9357SAndroid Build Coastguard Worker     if (options.AltStreams.Val && !arcInfo.Flags_AltStreams())
464*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
465*f6dc9357SAndroid Build Coastguard Worker     if (options.NtSecurity.Val && !arcInfo.Flags_NtSecurity())
466*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
467*f6dc9357SAndroid Build Coastguard Worker     if (options.DeleteAfterCompressing && arcInfo.Flags_HashHandler())
468*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
469*f6dc9357SAndroid Build Coastguard Worker   }
470*f6dc9357SAndroid Build Coastguard Worker 
471*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<CUpdatePair2> updatePairs2;
472*f6dc9357SAndroid Build Coastguard Worker 
473*f6dc9357SAndroid Build Coastguard Worker   UStringVector newNames;
474*f6dc9357SAndroid Build Coastguard Worker 
475*f6dc9357SAndroid Build Coastguard Worker   CArcToDoStat stat2;
476*f6dc9357SAndroid Build Coastguard Worker 
477*f6dc9357SAndroid Build Coastguard Worker   if (options.RenamePairs.Size() != 0)
478*f6dc9357SAndroid Build Coastguard Worker   {
479*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, arcItems)
480*f6dc9357SAndroid Build Coastguard Worker     {
481*f6dc9357SAndroid Build Coastguard Worker       const CArcItem &ai = arcItems[i];
482*f6dc9357SAndroid Build Coastguard Worker       bool needRename = false;
483*f6dc9357SAndroid Build Coastguard Worker       UString dest;
484*f6dc9357SAndroid Build Coastguard Worker 
485*f6dc9357SAndroid Build Coastguard Worker       if (ai.Censored)
486*f6dc9357SAndroid Build Coastguard Worker       {
487*f6dc9357SAndroid Build Coastguard Worker         FOR_VECTOR (j, options.RenamePairs)
488*f6dc9357SAndroid Build Coastguard Worker         {
489*f6dc9357SAndroid Build Coastguard Worker           const CRenamePair &rp = options.RenamePairs[j];
490*f6dc9357SAndroid Build Coastguard Worker           if (rp.GetNewPath(ai.IsDir, ai.Name, dest))
491*f6dc9357SAndroid Build Coastguard Worker           {
492*f6dc9357SAndroid Build Coastguard Worker             needRename = true;
493*f6dc9357SAndroid Build Coastguard Worker             break;
494*f6dc9357SAndroid Build Coastguard Worker           }
495*f6dc9357SAndroid Build Coastguard Worker 
496*f6dc9357SAndroid Build Coastguard Worker           #ifdef SUPPORT_ALT_STREAMS
497*f6dc9357SAndroid Build Coastguard Worker           if (ai.IsAltStream)
498*f6dc9357SAndroid Build Coastguard Worker           {
499*f6dc9357SAndroid Build Coastguard Worker             int colonPos = FindAltStreamColon_in_Path(ai.Name);
500*f6dc9357SAndroid Build Coastguard Worker             if (colonPos >= 0)
501*f6dc9357SAndroid Build Coastguard Worker             {
502*f6dc9357SAndroid Build Coastguard Worker               UString mainName = ai.Name.Left((unsigned)colonPos);
503*f6dc9357SAndroid Build Coastguard Worker               /*
504*f6dc9357SAndroid Build Coastguard Worker               actually we must improve that code to support cases
505*f6dc9357SAndroid Build Coastguard Worker               with folder renaming like: rn arc dir1\ dir2\
506*f6dc9357SAndroid Build Coastguard Worker               */
507*f6dc9357SAndroid Build Coastguard Worker               if (rp.GetNewPath(false, mainName, dest))
508*f6dc9357SAndroid Build Coastguard Worker               {
509*f6dc9357SAndroid Build Coastguard Worker                 needRename = true;
510*f6dc9357SAndroid Build Coastguard Worker                 dest.Add_Colon();
511*f6dc9357SAndroid Build Coastguard Worker                 dest += ai.Name.Ptr((unsigned)(colonPos + 1));
512*f6dc9357SAndroid Build Coastguard Worker                 break;
513*f6dc9357SAndroid Build Coastguard Worker               }
514*f6dc9357SAndroid Build Coastguard Worker             }
515*f6dc9357SAndroid Build Coastguard Worker           }
516*f6dc9357SAndroid Build Coastguard Worker           #endif
517*f6dc9357SAndroid Build Coastguard Worker         }
518*f6dc9357SAndroid Build Coastguard Worker       }
519*f6dc9357SAndroid Build Coastguard Worker 
520*f6dc9357SAndroid Build Coastguard Worker       CUpdatePair2 up2;
521*f6dc9357SAndroid Build Coastguard Worker       up2.SetAs_NoChangeArcItem(ai.IndexInServer);
522*f6dc9357SAndroid Build Coastguard Worker       if (needRename)
523*f6dc9357SAndroid Build Coastguard Worker       {
524*f6dc9357SAndroid Build Coastguard Worker         up2.NewProps = true;
525*f6dc9357SAndroid Build Coastguard Worker         RINOK(arc->IsItem_Anti(i, up2.IsAnti))
526*f6dc9357SAndroid Build Coastguard Worker         up2.NewNameIndex = (int)newNames.Add(dest);
527*f6dc9357SAndroid Build Coastguard Worker       }
528*f6dc9357SAndroid Build Coastguard Worker       updatePairs2.Add(up2);
529*f6dc9357SAndroid Build Coastguard Worker     }
530*f6dc9357SAndroid Build Coastguard Worker   }
531*f6dc9357SAndroid Build Coastguard Worker   else
532*f6dc9357SAndroid Build Coastguard Worker   {
533*f6dc9357SAndroid Build Coastguard Worker     CRecordVector<CUpdatePair> updatePairs;
534*f6dc9357SAndroid Build Coastguard Worker     GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!!
535*f6dc9357SAndroid Build Coastguard Worker     CUpdateProduceCallbackImp upCallback(&arcItems, &stat2.DeleteData, callback);
536*f6dc9357SAndroid Build Coastguard Worker 
537*f6dc9357SAndroid Build Coastguard Worker     UpdateProduce(updatePairs, actionSet, updatePairs2, isUpdatingItself ? &upCallback : NULL);
538*f6dc9357SAndroid Build Coastguard Worker   }
539*f6dc9357SAndroid Build Coastguard Worker 
540*f6dc9357SAndroid Build Coastguard Worker   {
541*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, updatePairs2)
542*f6dc9357SAndroid Build Coastguard Worker     {
543*f6dc9357SAndroid Build Coastguard Worker       const CUpdatePair2 &up = updatePairs2[i];
544*f6dc9357SAndroid Build Coastguard Worker 
545*f6dc9357SAndroid Build Coastguard Worker       // 17.01: anti-item is (up.NewData && (p.UseArcProps in most cases))
546*f6dc9357SAndroid Build Coastguard Worker 
547*f6dc9357SAndroid Build Coastguard Worker       if (up.NewData && !up.UseArcProps)
548*f6dc9357SAndroid Build Coastguard Worker       {
549*f6dc9357SAndroid Build Coastguard Worker         if (up.ExistOnDisk())
550*f6dc9357SAndroid Build Coastguard Worker         {
551*f6dc9357SAndroid Build Coastguard Worker           CDirItemsStat2 &stat = stat2.NewData;
552*f6dc9357SAndroid Build Coastguard Worker           const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex];
553*f6dc9357SAndroid Build Coastguard Worker           if (di.IsDir())
554*f6dc9357SAndroid Build Coastguard Worker           {
555*f6dc9357SAndroid Build Coastguard Worker             if (up.IsAnti)
556*f6dc9357SAndroid Build Coastguard Worker               stat.Anti_NumDirs++;
557*f6dc9357SAndroid Build Coastguard Worker             else
558*f6dc9357SAndroid Build Coastguard Worker               stat.NumDirs++;
559*f6dc9357SAndroid Build Coastguard Worker           }
560*f6dc9357SAndroid Build Coastguard Worker          #ifdef _WIN32
561*f6dc9357SAndroid Build Coastguard Worker           else if (di.IsAltStream)
562*f6dc9357SAndroid Build Coastguard Worker           {
563*f6dc9357SAndroid Build Coastguard Worker             if (up.IsAnti)
564*f6dc9357SAndroid Build Coastguard Worker               stat.Anti_NumAltStreams++;
565*f6dc9357SAndroid Build Coastguard Worker             else
566*f6dc9357SAndroid Build Coastguard Worker             {
567*f6dc9357SAndroid Build Coastguard Worker               stat.NumAltStreams++;
568*f6dc9357SAndroid Build Coastguard Worker               stat.AltStreamsSize += di.Size;
569*f6dc9357SAndroid Build Coastguard Worker             }
570*f6dc9357SAndroid Build Coastguard Worker           }
571*f6dc9357SAndroid Build Coastguard Worker          #endif
572*f6dc9357SAndroid Build Coastguard Worker           else
573*f6dc9357SAndroid Build Coastguard Worker           {
574*f6dc9357SAndroid Build Coastguard Worker             if (up.IsAnti)
575*f6dc9357SAndroid Build Coastguard Worker               stat.Anti_NumFiles++;
576*f6dc9357SAndroid Build Coastguard Worker             else
577*f6dc9357SAndroid Build Coastguard Worker             {
578*f6dc9357SAndroid Build Coastguard Worker               stat.NumFiles++;
579*f6dc9357SAndroid Build Coastguard Worker               stat.FilesSize += di.Size;
580*f6dc9357SAndroid Build Coastguard Worker             }
581*f6dc9357SAndroid Build Coastguard Worker           }
582*f6dc9357SAndroid Build Coastguard Worker         }
583*f6dc9357SAndroid Build Coastguard Worker       }
584*f6dc9357SAndroid Build Coastguard Worker       else if (up.ArcIndex >= 0)
585*f6dc9357SAndroid Build Coastguard Worker       {
586*f6dc9357SAndroid Build Coastguard Worker         CDirItemsStat2 &stat = *(up.NewData ? &stat2.NewData : &stat2.OldData);
587*f6dc9357SAndroid Build Coastguard Worker         const CArcItem &ai = arcItems[(unsigned)up.ArcIndex];
588*f6dc9357SAndroid Build Coastguard Worker         if (ai.IsDir)
589*f6dc9357SAndroid Build Coastguard Worker         {
590*f6dc9357SAndroid Build Coastguard Worker           if (up.IsAnti)
591*f6dc9357SAndroid Build Coastguard Worker             stat.Anti_NumDirs++;
592*f6dc9357SAndroid Build Coastguard Worker           else
593*f6dc9357SAndroid Build Coastguard Worker             stat.NumDirs++;
594*f6dc9357SAndroid Build Coastguard Worker         }
595*f6dc9357SAndroid Build Coastguard Worker         else if (ai.IsAltStream)
596*f6dc9357SAndroid Build Coastguard Worker         {
597*f6dc9357SAndroid Build Coastguard Worker           if (up.IsAnti)
598*f6dc9357SAndroid Build Coastguard Worker             stat.Anti_NumAltStreams++;
599*f6dc9357SAndroid Build Coastguard Worker           else
600*f6dc9357SAndroid Build Coastguard Worker           {
601*f6dc9357SAndroid Build Coastguard Worker             stat.NumAltStreams++;
602*f6dc9357SAndroid Build Coastguard Worker             stat.AltStreamsSize += ai.Size;
603*f6dc9357SAndroid Build Coastguard Worker           }
604*f6dc9357SAndroid Build Coastguard Worker         }
605*f6dc9357SAndroid Build Coastguard Worker         else
606*f6dc9357SAndroid Build Coastguard Worker         {
607*f6dc9357SAndroid Build Coastguard Worker           if (up.IsAnti)
608*f6dc9357SAndroid Build Coastguard Worker             stat.Anti_NumFiles++;
609*f6dc9357SAndroid Build Coastguard Worker           else
610*f6dc9357SAndroid Build Coastguard Worker           {
611*f6dc9357SAndroid Build Coastguard Worker             stat.NumFiles++;
612*f6dc9357SAndroid Build Coastguard Worker             stat.FilesSize += ai.Size;
613*f6dc9357SAndroid Build Coastguard Worker           }
614*f6dc9357SAndroid Build Coastguard Worker         }
615*f6dc9357SAndroid Build Coastguard Worker       }
616*f6dc9357SAndroid Build Coastguard Worker     }
617*f6dc9357SAndroid Build Coastguard Worker     RINOK(callback->SetNumItems(stat2))
618*f6dc9357SAndroid Build Coastguard Worker   }
619*f6dc9357SAndroid Build Coastguard Worker 
620*f6dc9357SAndroid Build Coastguard Worker   CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
621*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
622*f6dc9357SAndroid Build Coastguard Worker 
623*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->PreserveATime = options.PreserveATime;
624*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->ShareForWrite = options.OpenShareForWrite;
625*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->StopAfterOpenError = options.StopAfterOpenError;
626*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->StdInMode = options.StdInMode;
627*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->Callback = callback;
628*f6dc9357SAndroid Build Coastguard Worker 
629*f6dc9357SAndroid Build Coastguard Worker   if (arc)
630*f6dc9357SAndroid Build Coastguard Worker   {
631*f6dc9357SAndroid Build Coastguard Worker     // we set Archive to allow to transfer GetProperty requests back to DLL.
632*f6dc9357SAndroid Build Coastguard Worker     updateCallbackSpec->Archive = arc->Archive;
633*f6dc9357SAndroid Build Coastguard Worker   }
634*f6dc9357SAndroid Build Coastguard Worker 
635*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->DirItems = &dirItems;
636*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->ParentDirItem = parentDirItem;
637*f6dc9357SAndroid Build Coastguard Worker 
638*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->StoreNtSecurity = options.NtSecurity.Val;
639*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->StoreHardLinks = options.HardLinks.Val;
640*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->StoreSymLinks = options.SymLinks.Val;
641*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->StoreOwnerName = options.StoreOwnerName.Val;
642*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->StoreOwnerId = options.StoreOwnerId.Val;
643*f6dc9357SAndroid Build Coastguard Worker 
644*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->Arc = arc;
645*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->ArcItems = &arcItems;
646*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->UpdatePairs = &updatePairs2;
647*f6dc9357SAndroid Build Coastguard Worker 
648*f6dc9357SAndroid Build Coastguard Worker   updateCallbackSpec->ProcessedItemsStatuses = processedItemsStatuses;
649*f6dc9357SAndroid Build Coastguard Worker 
650*f6dc9357SAndroid Build Coastguard Worker   {
651*f6dc9357SAndroid Build Coastguard Worker     const UString arcPath = archivePath.GetFinalPath();
652*f6dc9357SAndroid Build Coastguard Worker     updateCallbackSpec->ArcFileName = ExtractFileNameFromPath(arcPath);
653*f6dc9357SAndroid Build Coastguard Worker   }
654*f6dc9357SAndroid Build Coastguard Worker 
655*f6dc9357SAndroid Build Coastguard Worker   if (options.RenamePairs.Size() != 0)
656*f6dc9357SAndroid Build Coastguard Worker     updateCallbackSpec->NewNames = &newNames;
657*f6dc9357SAndroid Build Coastguard Worker 
658*f6dc9357SAndroid Build Coastguard Worker   if (options.SetArcMTime)
659*f6dc9357SAndroid Build Coastguard Worker   {
660*f6dc9357SAndroid Build Coastguard Worker     // updateCallbackSpec->Need_ArcMTime_Report = true;
661*f6dc9357SAndroid Build Coastguard Worker     updateCallbackSpec->Need_LatestMTime = true;
662*f6dc9357SAndroid Build Coastguard Worker   }
663*f6dc9357SAndroid Build Coastguard Worker 
664*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IOutStream> outSeekStream;
665*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialOutStream> outStream;
666*f6dc9357SAndroid Build Coastguard Worker 
667*f6dc9357SAndroid Build Coastguard Worker   if (!options.StdOutMode)
668*f6dc9357SAndroid Build Coastguard Worker   {
669*f6dc9357SAndroid Build Coastguard Worker     FString dirPrefix;
670*f6dc9357SAndroid Build Coastguard Worker     if (!GetOnlyDirPrefix(us2fs(archivePath.GetFinalPath()), dirPrefix))
671*f6dc9357SAndroid Build Coastguard Worker       throw 1417161;
672*f6dc9357SAndroid Build Coastguard Worker     CreateComplexDir(dirPrefix);
673*f6dc9357SAndroid Build Coastguard Worker   }
674*f6dc9357SAndroid Build Coastguard Worker 
675*f6dc9357SAndroid Build Coastguard Worker   COutFileStream *outStreamSpec = NULL;
676*f6dc9357SAndroid Build Coastguard Worker   CStdOutFileStream *stdOutFileStreamSpec = NULL;
677*f6dc9357SAndroid Build Coastguard Worker   CMultiOutStream *volStreamSpec = NULL;
678*f6dc9357SAndroid Build Coastguard Worker 
679*f6dc9357SAndroid Build Coastguard Worker   if (options.VolumesSizes.Size() == 0)
680*f6dc9357SAndroid Build Coastguard Worker   {
681*f6dc9357SAndroid Build Coastguard Worker     if (options.StdOutMode)
682*f6dc9357SAndroid Build Coastguard Worker     {
683*f6dc9357SAndroid Build Coastguard Worker       stdOutFileStreamSpec = new CStdOutFileStream;
684*f6dc9357SAndroid Build Coastguard Worker       outStream = stdOutFileStreamSpec;
685*f6dc9357SAndroid Build Coastguard Worker     }
686*f6dc9357SAndroid Build Coastguard Worker     else
687*f6dc9357SAndroid Build Coastguard Worker     {
688*f6dc9357SAndroid Build Coastguard Worker       outStreamSpec = new COutFileStream;
689*f6dc9357SAndroid Build Coastguard Worker       outSeekStream = outStreamSpec;
690*f6dc9357SAndroid Build Coastguard Worker       outStream = outSeekStream;
691*f6dc9357SAndroid Build Coastguard Worker       bool isOK = false;
692*f6dc9357SAndroid Build Coastguard Worker       FString realPath;
693*f6dc9357SAndroid Build Coastguard Worker 
694*f6dc9357SAndroid Build Coastguard Worker       for (unsigned i = 0; i < (1 << 16); i++)
695*f6dc9357SAndroid Build Coastguard Worker       {
696*f6dc9357SAndroid Build Coastguard Worker         if (archivePath.Temp)
697*f6dc9357SAndroid Build Coastguard Worker         {
698*f6dc9357SAndroid Build Coastguard Worker           if (i > 0)
699*f6dc9357SAndroid Build Coastguard Worker           {
700*f6dc9357SAndroid Build Coastguard Worker             archivePath.TempPostfix.Empty();
701*f6dc9357SAndroid Build Coastguard Worker             archivePath.TempPostfix.Add_UInt32(i);
702*f6dc9357SAndroid Build Coastguard Worker           }
703*f6dc9357SAndroid Build Coastguard Worker           realPath = archivePath.GetTempPath();
704*f6dc9357SAndroid Build Coastguard Worker         }
705*f6dc9357SAndroid Build Coastguard Worker         else
706*f6dc9357SAndroid Build Coastguard Worker           realPath = us2fs(archivePath.GetFinalPath());
707*f6dc9357SAndroid Build Coastguard Worker         if (outStreamSpec->Create_NEW(realPath))
708*f6dc9357SAndroid Build Coastguard Worker         {
709*f6dc9357SAndroid Build Coastguard Worker           tempFiles.Paths.Add(realPath);
710*f6dc9357SAndroid Build Coastguard Worker           isOK = true;
711*f6dc9357SAndroid Build Coastguard Worker           break;
712*f6dc9357SAndroid Build Coastguard Worker         }
713*f6dc9357SAndroid Build Coastguard Worker         if (::GetLastError() != ERROR_FILE_EXISTS)
714*f6dc9357SAndroid Build Coastguard Worker           break;
715*f6dc9357SAndroid Build Coastguard Worker         if (!archivePath.Temp)
716*f6dc9357SAndroid Build Coastguard Worker           break;
717*f6dc9357SAndroid Build Coastguard Worker       }
718*f6dc9357SAndroid Build Coastguard Worker 
719*f6dc9357SAndroid Build Coastguard Worker       if (!isOK)
720*f6dc9357SAndroid Build Coastguard Worker         return errorInfo.SetFromLastError("cannot open file", realPath);
721*f6dc9357SAndroid Build Coastguard Worker     }
722*f6dc9357SAndroid Build Coastguard Worker   }
723*f6dc9357SAndroid Build Coastguard Worker   else
724*f6dc9357SAndroid Build Coastguard Worker   {
725*f6dc9357SAndroid Build Coastguard Worker     if (options.StdOutMode)
726*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
727*f6dc9357SAndroid Build Coastguard Worker     if (arc && arc->GetGlobalOffset() > 0)
728*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
729*f6dc9357SAndroid Build Coastguard Worker 
730*f6dc9357SAndroid Build Coastguard Worker     volStreamSpec = new CMultiOutStream();
731*f6dc9357SAndroid Build Coastguard Worker     outSeekStream = volStreamSpec;
732*f6dc9357SAndroid Build Coastguard Worker     outStream = outSeekStream;
733*f6dc9357SAndroid Build Coastguard Worker     volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath());
734*f6dc9357SAndroid Build Coastguard Worker     volStreamSpec->Prefix.Add_Dot();
735*f6dc9357SAndroid Build Coastguard Worker     volStreamSpec->Init(options.VolumesSizes);
736*f6dc9357SAndroid Build Coastguard Worker     {
737*f6dc9357SAndroid Build Coastguard Worker       CMultiOutStream_Rec &rec = multiStreams.Items.AddNew();
738*f6dc9357SAndroid Build Coastguard Worker       rec.Spec = volStreamSpec;
739*f6dc9357SAndroid Build Coastguard Worker       rec.Ref = rec.Spec;
740*f6dc9357SAndroid Build Coastguard Worker     }
741*f6dc9357SAndroid Build Coastguard Worker 
742*f6dc9357SAndroid Build Coastguard Worker     /*
743*f6dc9357SAndroid Build Coastguard Worker     updateCallbackSpec->VolumesSizes = volumesSizes;
744*f6dc9357SAndroid Build Coastguard Worker     updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name;
745*f6dc9357SAndroid Build Coastguard Worker     if (!archivePath.VolExtension.IsEmpty())
746*f6dc9357SAndroid Build Coastguard Worker       updateCallbackSpec->VolExt = UString('.') + archivePath.VolExtension;
747*f6dc9357SAndroid Build Coastguard Worker     */
748*f6dc9357SAndroid Build Coastguard Worker   }
749*f6dc9357SAndroid Build Coastguard Worker 
750*f6dc9357SAndroid Build Coastguard Worker   if (options.SfxMode)
751*f6dc9357SAndroid Build Coastguard Worker   {
752*f6dc9357SAndroid Build Coastguard Worker     CInFileStream *sfxStreamSpec = new CInFileStream;
753*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
754*f6dc9357SAndroid Build Coastguard Worker     if (!sfxStreamSpec->Open(options.SfxModule))
755*f6dc9357SAndroid Build Coastguard Worker       return errorInfo.SetFromLastError("cannot open SFX module", options.SfxModule);
756*f6dc9357SAndroid Build Coastguard Worker 
757*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ISequentialOutStream> sfxOutStream;
758*f6dc9357SAndroid Build Coastguard Worker     COutFileStream *outStreamSpec2 = NULL;
759*f6dc9357SAndroid Build Coastguard Worker     if (options.VolumesSizes.Size() == 0)
760*f6dc9357SAndroid Build Coastguard Worker       sfxOutStream = outStream;
761*f6dc9357SAndroid Build Coastguard Worker     else
762*f6dc9357SAndroid Build Coastguard Worker     {
763*f6dc9357SAndroid Build Coastguard Worker       outStreamSpec2 = new COutFileStream;
764*f6dc9357SAndroid Build Coastguard Worker       sfxOutStream = outStreamSpec2;
765*f6dc9357SAndroid Build Coastguard Worker       const FString realPath = us2fs(archivePath.GetFinalPath());
766*f6dc9357SAndroid Build Coastguard Worker       if (!outStreamSpec2->Create_NEW(realPath))
767*f6dc9357SAndroid Build Coastguard Worker         return errorInfo.SetFromLastError("cannot open file", realPath);
768*f6dc9357SAndroid Build Coastguard Worker     }
769*f6dc9357SAndroid Build Coastguard Worker 
770*f6dc9357SAndroid Build Coastguard Worker     {
771*f6dc9357SAndroid Build Coastguard Worker       UInt64 sfxSize;
772*f6dc9357SAndroid Build Coastguard Worker       RINOK(sfxStreamSpec->GetSize(&sfxSize))
773*f6dc9357SAndroid Build Coastguard Worker       RINOK(callback->WriteSfx(fs2us(options.SfxModule), sfxSize))
774*f6dc9357SAndroid Build Coastguard Worker     }
775*f6dc9357SAndroid Build Coastguard Worker 
776*f6dc9357SAndroid Build Coastguard Worker     RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL))
777*f6dc9357SAndroid Build Coastguard Worker 
778*f6dc9357SAndroid Build Coastguard Worker     if (outStreamSpec2)
779*f6dc9357SAndroid Build Coastguard Worker     {
780*f6dc9357SAndroid Build Coastguard Worker       RINOK(outStreamSpec2->Close())
781*f6dc9357SAndroid Build Coastguard Worker     }
782*f6dc9357SAndroid Build Coastguard Worker   }
783*f6dc9357SAndroid Build Coastguard Worker 
784*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialOutStream> tailStream;
785*f6dc9357SAndroid Build Coastguard Worker 
786*f6dc9357SAndroid Build Coastguard Worker   if (options.SfxMode || !arc || arc->ArcStreamOffset == 0)
787*f6dc9357SAndroid Build Coastguard Worker     tailStream = outStream;
788*f6dc9357SAndroid Build Coastguard Worker   else
789*f6dc9357SAndroid Build Coastguard Worker   {
790*f6dc9357SAndroid Build Coastguard Worker     // Int64 globalOffset = arc->GetGlobalOffset();
791*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_SeekToBegin(arc->InStream))
792*f6dc9357SAndroid Build Coastguard Worker     RINOK(NCompress::CopyStream_ExactSize(arc->InStream, outStream, arc->ArcStreamOffset, NULL))
793*f6dc9357SAndroid Build Coastguard Worker     if (options.StdOutMode)
794*f6dc9357SAndroid Build Coastguard Worker       tailStream = outStream;
795*f6dc9357SAndroid Build Coastguard Worker     else
796*f6dc9357SAndroid Build Coastguard Worker     {
797*f6dc9357SAndroid Build Coastguard Worker       CTailOutStream *tailStreamSpec = new CTailOutStream;
798*f6dc9357SAndroid Build Coastguard Worker       tailStream = tailStreamSpec;
799*f6dc9357SAndroid Build Coastguard Worker       tailStreamSpec->Stream = outSeekStream;
800*f6dc9357SAndroid Build Coastguard Worker       tailStreamSpec->Offset = arc->ArcStreamOffset;
801*f6dc9357SAndroid Build Coastguard Worker       tailStreamSpec->Init();
802*f6dc9357SAndroid Build Coastguard Worker     }
803*f6dc9357SAndroid Build Coastguard Worker   }
804*f6dc9357SAndroid Build Coastguard Worker 
805*f6dc9357SAndroid Build Coastguard Worker   CFiTime ft;
806*f6dc9357SAndroid Build Coastguard Worker   FiTime_Clear(ft);
807*f6dc9357SAndroid Build Coastguard Worker   bool ft_Defined = false;
808*f6dc9357SAndroid Build Coastguard Worker   {
809*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, updatePairs2)
810*f6dc9357SAndroid Build Coastguard Worker     {
811*f6dc9357SAndroid Build Coastguard Worker       const CUpdatePair2 &pair2 = updatePairs2[i];
812*f6dc9357SAndroid Build Coastguard Worker       CFiTime ft2;
813*f6dc9357SAndroid Build Coastguard Worker       FiTime_Clear(ft2);
814*f6dc9357SAndroid Build Coastguard Worker       bool ft2_Defined = false;
815*f6dc9357SAndroid Build Coastguard Worker       /* we use full precision of dirItem, if dirItem is defined
816*f6dc9357SAndroid Build Coastguard Worker          and (dirItem will be used or dirItem is sameTime in dir and arc */
817*f6dc9357SAndroid Build Coastguard Worker       if (pair2.DirIndex >= 0 &&
818*f6dc9357SAndroid Build Coastguard Worker           (pair2.NewProps || pair2.IsSameTime))
819*f6dc9357SAndroid Build Coastguard Worker       {
820*f6dc9357SAndroid Build Coastguard Worker         ft2 = dirItems.Items[(unsigned)pair2.DirIndex].MTime;
821*f6dc9357SAndroid Build Coastguard Worker         ft2_Defined = true;
822*f6dc9357SAndroid Build Coastguard Worker       }
823*f6dc9357SAndroid Build Coastguard Worker       else if (pair2.UseArcProps && pair2.ArcIndex >= 0)
824*f6dc9357SAndroid Build Coastguard Worker       {
825*f6dc9357SAndroid Build Coastguard Worker         const CArcItem &arcItem = arcItems[(unsigned)pair2.ArcIndex];
826*f6dc9357SAndroid Build Coastguard Worker         if (arcItem.MTime.Def)
827*f6dc9357SAndroid Build Coastguard Worker         {
828*f6dc9357SAndroid Build Coastguard Worker           arcItem.MTime.Write_To_FiTime(ft2);
829*f6dc9357SAndroid Build Coastguard Worker           ft2_Defined = true;
830*f6dc9357SAndroid Build Coastguard Worker         }
831*f6dc9357SAndroid Build Coastguard Worker       }
832*f6dc9357SAndroid Build Coastguard Worker       if (ft2_Defined)
833*f6dc9357SAndroid Build Coastguard Worker       {
834*f6dc9357SAndroid Build Coastguard Worker         if (!ft_Defined || Compare_FiTime(&ft, &ft2) < 0)
835*f6dc9357SAndroid Build Coastguard Worker         {
836*f6dc9357SAndroid Build Coastguard Worker           ft = ft2;
837*f6dc9357SAndroid Build Coastguard Worker           ft_Defined = true;
838*f6dc9357SAndroid Build Coastguard Worker         }
839*f6dc9357SAndroid Build Coastguard Worker       }
840*f6dc9357SAndroid Build Coastguard Worker     }
841*f6dc9357SAndroid Build Coastguard Worker     /*
842*f6dc9357SAndroid Build Coastguard Worker     if (fileTimeType != NFileTimeType::kNotDefined)
843*f6dc9357SAndroid Build Coastguard Worker     FiTime_Normalize_With_Prec(ft, fileTimeType);
844*f6dc9357SAndroid Build Coastguard Worker     */
845*f6dc9357SAndroid Build Coastguard Worker   }
846*f6dc9357SAndroid Build Coastguard Worker 
847*f6dc9357SAndroid Build Coastguard Worker   if (volStreamSpec && options.SetArcMTime && ft_Defined)
848*f6dc9357SAndroid Build Coastguard Worker   {
849*f6dc9357SAndroid Build Coastguard Worker     volStreamSpec->MTime = ft;
850*f6dc9357SAndroid Build Coastguard Worker     volStreamSpec->MTime_Defined = true;
851*f6dc9357SAndroid Build Coastguard Worker   }
852*f6dc9357SAndroid Build Coastguard Worker 
853*f6dc9357SAndroid Build Coastguard Worker   HRESULT result = outArchive->UpdateItems(tailStream, updatePairs2.Size(), updateCallback);
854*f6dc9357SAndroid Build Coastguard Worker   // callback->Finalize();
855*f6dc9357SAndroid Build Coastguard Worker   RINOK(result)
856*f6dc9357SAndroid Build Coastguard Worker 
857*f6dc9357SAndroid Build Coastguard Worker   if (!updateCallbackSpec->AreAllFilesClosed())
858*f6dc9357SAndroid Build Coastguard Worker   {
859*f6dc9357SAndroid Build Coastguard Worker     errorInfo.Message = "There are unclosed input files:";
860*f6dc9357SAndroid Build Coastguard Worker     errorInfo.FileNames = updateCallbackSpec->_openFiles_Paths;
861*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
862*f6dc9357SAndroid Build Coastguard Worker   }
863*f6dc9357SAndroid Build Coastguard Worker 
864*f6dc9357SAndroid Build Coastguard Worker   if (options.SetArcMTime)
865*f6dc9357SAndroid Build Coastguard Worker   {
866*f6dc9357SAndroid Build Coastguard Worker     // bool needNormalizeAfterStream;
867*f6dc9357SAndroid Build Coastguard Worker     // needParse;
868*f6dc9357SAndroid Build Coastguard Worker     /*
869*f6dc9357SAndroid Build Coastguard Worker     if (updateCallbackSpec->ArcMTime_WasReported)
870*f6dc9357SAndroid Build Coastguard Worker     {
871*f6dc9357SAndroid Build Coastguard Worker       isDefined = updateCallbackSpec->Reported_ArcMTime.Def;
872*f6dc9357SAndroid Build Coastguard Worker       if (isDefined)
873*f6dc9357SAndroid Build Coastguard Worker         updateCallbackSpec->Reported_ArcMTime.Write_To_FiTime(ft);
874*f6dc9357SAndroid Build Coastguard Worker       else
875*f6dc9357SAndroid Build Coastguard Worker         fileTimeType = NFileTimeType::kNotDefined;
876*f6dc9357SAndroid Build Coastguard Worker     }
877*f6dc9357SAndroid Build Coastguard Worker     if (!isDefined)
878*f6dc9357SAndroid Build Coastguard Worker     */
879*f6dc9357SAndroid Build Coastguard Worker     {
880*f6dc9357SAndroid Build Coastguard Worker       if (updateCallbackSpec->LatestMTime_Defined)
881*f6dc9357SAndroid Build Coastguard Worker       {
882*f6dc9357SAndroid Build Coastguard Worker         // CArcTime at = StreamCallback_ArcMTime;
883*f6dc9357SAndroid Build Coastguard Worker         // updateCallbackSpec->StreamCallback_ArcMTime.Write_To_FiTime(ft);
884*f6dc9357SAndroid Build Coastguard Worker         // we must normalize with precision from archive;
885*f6dc9357SAndroid Build Coastguard Worker         if (!ft_Defined || Compare_FiTime(&ft, &updateCallbackSpec->LatestMTime) < 0)
886*f6dc9357SAndroid Build Coastguard Worker           ft = updateCallbackSpec->LatestMTime;
887*f6dc9357SAndroid Build Coastguard Worker         ft_Defined = true;
888*f6dc9357SAndroid Build Coastguard Worker       }
889*f6dc9357SAndroid Build Coastguard Worker       /*
890*f6dc9357SAndroid Build Coastguard Worker       if (fileTimeType != NFileTimeType::kNotDefined)
891*f6dc9357SAndroid Build Coastguard Worker         FiTime_Normalize_With_Prec(ft, fileTimeType);
892*f6dc9357SAndroid Build Coastguard Worker       */
893*f6dc9357SAndroid Build Coastguard Worker     }
894*f6dc9357SAndroid Build Coastguard Worker     // if (ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0)
895*f6dc9357SAndroid Build Coastguard Worker     if (ft_Defined)
896*f6dc9357SAndroid Build Coastguard Worker     {
897*f6dc9357SAndroid Build Coastguard Worker       // we ignore set time errors here.
898*f6dc9357SAndroid Build Coastguard Worker       // note that user could move some finished volumes to another folder.
899*f6dc9357SAndroid Build Coastguard Worker       if (outStreamSpec)
900*f6dc9357SAndroid Build Coastguard Worker         outStreamSpec->SetMTime(&ft);
901*f6dc9357SAndroid Build Coastguard Worker       else if (volStreamSpec)
902*f6dc9357SAndroid Build Coastguard Worker         volStreamSpec->SetMTime_Final(ft);
903*f6dc9357SAndroid Build Coastguard Worker     }
904*f6dc9357SAndroid Build Coastguard Worker   }
905*f6dc9357SAndroid Build Coastguard Worker 
906*f6dc9357SAndroid Build Coastguard Worker   if (callback)
907*f6dc9357SAndroid Build Coastguard Worker   {
908*f6dc9357SAndroid Build Coastguard Worker     UInt64 size = 0;
909*f6dc9357SAndroid Build Coastguard Worker     if (outStreamSpec)
910*f6dc9357SAndroid Build Coastguard Worker       outStreamSpec->GetSize(&size);
911*f6dc9357SAndroid Build Coastguard Worker     else if (stdOutFileStreamSpec)
912*f6dc9357SAndroid Build Coastguard Worker       size = stdOutFileStreamSpec->GetSize();
913*f6dc9357SAndroid Build Coastguard Worker     else
914*f6dc9357SAndroid Build Coastguard Worker       size = volStreamSpec->GetSize();
915*f6dc9357SAndroid Build Coastguard Worker 
916*f6dc9357SAndroid Build Coastguard Worker     st.OutArcFileSize = size;
917*f6dc9357SAndroid Build Coastguard Worker   }
918*f6dc9357SAndroid Build Coastguard Worker 
919*f6dc9357SAndroid Build Coastguard Worker   if (outStreamSpec)
920*f6dc9357SAndroid Build Coastguard Worker     result = outStreamSpec->Close();
921*f6dc9357SAndroid Build Coastguard Worker   else if (volStreamSpec)
922*f6dc9357SAndroid Build Coastguard Worker   {
923*f6dc9357SAndroid Build Coastguard Worker     result = volStreamSpec->FinalFlush_and_CloseFiles(st.NumVolumes);
924*f6dc9357SAndroid Build Coastguard Worker     st.IsMultiVolMode = true;
925*f6dc9357SAndroid Build Coastguard Worker   }
926*f6dc9357SAndroid Build Coastguard Worker 
927*f6dc9357SAndroid Build Coastguard Worker   RINOK(result)
928*f6dc9357SAndroid Build Coastguard Worker 
929*f6dc9357SAndroid Build Coastguard Worker   if (processedItemsStatuses)
930*f6dc9357SAndroid Build Coastguard Worker   {
931*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, updatePairs2)
932*f6dc9357SAndroid Build Coastguard Worker     {
933*f6dc9357SAndroid Build Coastguard Worker       const CUpdatePair2 &up = updatePairs2[i];
934*f6dc9357SAndroid Build Coastguard Worker       if (up.NewData && up.DirIndex >= 0)
935*f6dc9357SAndroid Build Coastguard Worker       {
936*f6dc9357SAndroid Build Coastguard Worker         const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex];
937*f6dc9357SAndroid Build Coastguard Worker         if (di.AreReparseData() || (!di.IsDir() && di.Size == 0))
938*f6dc9357SAndroid Build Coastguard Worker           processedItemsStatuses[(unsigned)up.DirIndex] = 1;
939*f6dc9357SAndroid Build Coastguard Worker       }
940*f6dc9357SAndroid Build Coastguard Worker     }
941*f6dc9357SAndroid Build Coastguard Worker   }
942*f6dc9357SAndroid Build Coastguard Worker 
943*f6dc9357SAndroid Build Coastguard Worker   return result;
944*f6dc9357SAndroid Build Coastguard Worker }
945*f6dc9357SAndroid Build Coastguard Worker 
946*f6dc9357SAndroid Build Coastguard Worker 
947*f6dc9357SAndroid Build Coastguard Worker 
Censor_AreAllAllowed(const NWildcard::CCensor & censor)948*f6dc9357SAndroid Build Coastguard Worker static bool Censor_AreAllAllowed(const NWildcard::CCensor &censor)
949*f6dc9357SAndroid Build Coastguard Worker {
950*f6dc9357SAndroid Build Coastguard Worker   if (censor.Pairs.Size() != 1)
951*f6dc9357SAndroid Build Coastguard Worker     return false;
952*f6dc9357SAndroid Build Coastguard Worker   const NWildcard::CPair &pair = censor.Pairs[0];
953*f6dc9357SAndroid Build Coastguard Worker   /* Censor_CheckPath() ignores (CPair::Prefix).
954*f6dc9357SAndroid Build Coastguard Worker      So we also ignore (CPair::Prefix) here */
955*f6dc9357SAndroid Build Coastguard Worker   // if (!pair.Prefix.IsEmpty()) return false;
956*f6dc9357SAndroid Build Coastguard Worker   return pair.Head.AreAllAllowed();
957*f6dc9357SAndroid Build Coastguard Worker }
958*f6dc9357SAndroid Build Coastguard Worker 
959*f6dc9357SAndroid Build Coastguard Worker bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include);
960*f6dc9357SAndroid Build Coastguard Worker 
Censor_CheckPath(const NWildcard::CCensor & censor,const CReadArcItem & item)961*f6dc9357SAndroid Build Coastguard Worker static bool Censor_CheckPath(const NWildcard::CCensor &censor, const CReadArcItem &item)
962*f6dc9357SAndroid Build Coastguard Worker {
963*f6dc9357SAndroid Build Coastguard Worker   bool finded = false;
964*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, censor.Pairs)
965*f6dc9357SAndroid Build Coastguard Worker   {
966*f6dc9357SAndroid Build Coastguard Worker     /* (CPair::Prefix) in not used for matching items in archive.
967*f6dc9357SAndroid Build Coastguard Worker        So we ignore (CPair::Prefix) here */
968*f6dc9357SAndroid Build Coastguard Worker     bool include;
969*f6dc9357SAndroid Build Coastguard Worker     if (CensorNode_CheckPath2(censor.Pairs[i].Head, item, include))
970*f6dc9357SAndroid Build Coastguard Worker     {
971*f6dc9357SAndroid Build Coastguard Worker       // Check it and FIXME !!!!
972*f6dc9357SAndroid Build Coastguard Worker       // here we can exclude item via some Pair, that is still allowed by another Pair
973*f6dc9357SAndroid Build Coastguard Worker       if (!include)
974*f6dc9357SAndroid Build Coastguard Worker         return false;
975*f6dc9357SAndroid Build Coastguard Worker       finded = true;
976*f6dc9357SAndroid Build Coastguard Worker     }
977*f6dc9357SAndroid Build Coastguard Worker   }
978*f6dc9357SAndroid Build Coastguard Worker   return finded;
979*f6dc9357SAndroid Build Coastguard Worker }
980*f6dc9357SAndroid Build Coastguard Worker 
EnumerateInArchiveItems(const NWildcard::CCensor & censor,const CArc & arc,CObjectVector<CArcItem> & arcItems)981*f6dc9357SAndroid Build Coastguard Worker static HRESULT EnumerateInArchiveItems(
982*f6dc9357SAndroid Build Coastguard Worker     // bool storeStreamsMode,
983*f6dc9357SAndroid Build Coastguard Worker     const NWildcard::CCensor &censor,
984*f6dc9357SAndroid Build Coastguard Worker     const CArc &arc,
985*f6dc9357SAndroid Build Coastguard Worker     CObjectVector<CArcItem> &arcItems)
986*f6dc9357SAndroid Build Coastguard Worker {
987*f6dc9357SAndroid Build Coastguard Worker   arcItems.Clear();
988*f6dc9357SAndroid Build Coastguard Worker   UInt32 numItems;
989*f6dc9357SAndroid Build Coastguard Worker   IInArchive *archive = arc.Archive;
990*f6dc9357SAndroid Build Coastguard Worker   RINOK(archive->GetNumberOfItems(&numItems))
991*f6dc9357SAndroid Build Coastguard Worker   arcItems.ClearAndReserve(numItems);
992*f6dc9357SAndroid Build Coastguard Worker 
993*f6dc9357SAndroid Build Coastguard Worker   CReadArcItem item;
994*f6dc9357SAndroid Build Coastguard Worker 
995*f6dc9357SAndroid Build Coastguard Worker   const bool allFilesAreAllowed = Censor_AreAllAllowed(censor);
996*f6dc9357SAndroid Build Coastguard Worker 
997*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < numItems; i++)
998*f6dc9357SAndroid Build Coastguard Worker   {
999*f6dc9357SAndroid Build Coastguard Worker     CArcItem ai;
1000*f6dc9357SAndroid Build Coastguard Worker 
1001*f6dc9357SAndroid Build Coastguard Worker     RINOK(arc.GetItem(i, item))
1002*f6dc9357SAndroid Build Coastguard Worker     ai.Name = item.Path;
1003*f6dc9357SAndroid Build Coastguard Worker     ai.IsDir = item.IsDir;
1004*f6dc9357SAndroid Build Coastguard Worker     ai.IsAltStream =
1005*f6dc9357SAndroid Build Coastguard Worker         #ifdef SUPPORT_ALT_STREAMS
1006*f6dc9357SAndroid Build Coastguard Worker           item.IsAltStream;
1007*f6dc9357SAndroid Build Coastguard Worker         #else
1008*f6dc9357SAndroid Build Coastguard Worker           false;
1009*f6dc9357SAndroid Build Coastguard Worker         #endif
1010*f6dc9357SAndroid Build Coastguard Worker 
1011*f6dc9357SAndroid Build Coastguard Worker     /*
1012*f6dc9357SAndroid Build Coastguard Worker     if (!storeStreamsMode && ai.IsAltStream)
1013*f6dc9357SAndroid Build Coastguard Worker       continue;
1014*f6dc9357SAndroid Build Coastguard Worker     */
1015*f6dc9357SAndroid Build Coastguard Worker     if (allFilesAreAllowed)
1016*f6dc9357SAndroid Build Coastguard Worker       ai.Censored = true;
1017*f6dc9357SAndroid Build Coastguard Worker     else
1018*f6dc9357SAndroid Build Coastguard Worker       ai.Censored = Censor_CheckPath(censor, item);
1019*f6dc9357SAndroid Build Coastguard Worker 
1020*f6dc9357SAndroid Build Coastguard Worker     // ai.MTime will be set to archive MTime, if not present in archive item
1021*f6dc9357SAndroid Build Coastguard Worker     RINOK(arc.GetItem_MTime(i, ai.MTime))
1022*f6dc9357SAndroid Build Coastguard Worker     RINOK(arc.GetItem_Size(i, ai.Size, ai.Size_Defined))
1023*f6dc9357SAndroid Build Coastguard Worker 
1024*f6dc9357SAndroid Build Coastguard Worker     ai.IndexInServer = i;
1025*f6dc9357SAndroid Build Coastguard Worker     arcItems.AddInReserved(ai);
1026*f6dc9357SAndroid Build Coastguard Worker   }
1027*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1028*f6dc9357SAndroid Build Coastguard Worker }
1029*f6dc9357SAndroid Build Coastguard Worker 
1030*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(UNDER_CE)
1031*f6dc9357SAndroid Build Coastguard Worker 
1032*f6dc9357SAndroid Build Coastguard Worker #if defined(__MINGW32__) || defined(__MINGW64__)
1033*f6dc9357SAndroid Build Coastguard Worker #include <mapi.h>
1034*f6dc9357SAndroid Build Coastguard Worker #else
1035*f6dc9357SAndroid Build Coastguard Worker #include <MAPI.h>
1036*f6dc9357SAndroid Build Coastguard Worker #endif
1037*f6dc9357SAndroid Build Coastguard Worker 
1038*f6dc9357SAndroid Build Coastguard Worker extern "C" {
1039*f6dc9357SAndroid Build Coastguard Worker 
1040*f6dc9357SAndroid Build Coastguard Worker #ifdef MAPI_FORCE_UNICODE
1041*f6dc9357SAndroid Build Coastguard Worker 
1042*f6dc9357SAndroid Build Coastguard Worker #define Z7_WIN_LPMAPISENDMAILW  LPMAPISENDMAILW
1043*f6dc9357SAndroid Build Coastguard Worker #define Z7_WIN_MapiFileDescW    MapiFileDescW
1044*f6dc9357SAndroid Build Coastguard Worker #define Z7_WIN_MapiMessageW     MapiMessageW
1045*f6dc9357SAndroid Build Coastguard Worker #define Z7_WIN_MapiRecipDescW   MapiRecipDescW
1046*f6dc9357SAndroid Build Coastguard Worker 
1047*f6dc9357SAndroid Build Coastguard Worker #else
1048*f6dc9357SAndroid Build Coastguard Worker 
1049*f6dc9357SAndroid Build Coastguard Worker typedef struct
1050*f6dc9357SAndroid Build Coastguard Worker {
1051*f6dc9357SAndroid Build Coastguard Worker     ULONG ulReserved;
1052*f6dc9357SAndroid Build Coastguard Worker     ULONG ulRecipClass;
1053*f6dc9357SAndroid Build Coastguard Worker     PWSTR lpszName;
1054*f6dc9357SAndroid Build Coastguard Worker     PWSTR lpszAddress;
1055*f6dc9357SAndroid Build Coastguard Worker     ULONG ulEIDSize;
1056*f6dc9357SAndroid Build Coastguard Worker     PVOID lpEntryID;
1057*f6dc9357SAndroid Build Coastguard Worker } Z7_WIN_MapiRecipDescW, *Z7_WIN_lpMapiRecipDescW;
1058*f6dc9357SAndroid Build Coastguard Worker 
1059*f6dc9357SAndroid Build Coastguard Worker typedef struct
1060*f6dc9357SAndroid Build Coastguard Worker {
1061*f6dc9357SAndroid Build Coastguard Worker     ULONG ulReserved;
1062*f6dc9357SAndroid Build Coastguard Worker     ULONG flFlags;
1063*f6dc9357SAndroid Build Coastguard Worker     ULONG nPosition;
1064*f6dc9357SAndroid Build Coastguard Worker     PWSTR lpszPathName;
1065*f6dc9357SAndroid Build Coastguard Worker     PWSTR lpszFileName;
1066*f6dc9357SAndroid Build Coastguard Worker     PVOID lpFileType;
1067*f6dc9357SAndroid Build Coastguard Worker } Z7_WIN_MapiFileDescW, *Z7_WIN_lpMapiFileDescW;
1068*f6dc9357SAndroid Build Coastguard Worker 
1069*f6dc9357SAndroid Build Coastguard Worker typedef struct
1070*f6dc9357SAndroid Build Coastguard Worker {
1071*f6dc9357SAndroid Build Coastguard Worker   ULONG ulReserved;
1072*f6dc9357SAndroid Build Coastguard Worker   PWSTR lpszSubject;
1073*f6dc9357SAndroid Build Coastguard Worker   PWSTR lpszNoteText;
1074*f6dc9357SAndroid Build Coastguard Worker   PWSTR lpszMessageType;
1075*f6dc9357SAndroid Build Coastguard Worker   PWSTR lpszDateReceived;
1076*f6dc9357SAndroid Build Coastguard Worker   PWSTR lpszConversationID;
1077*f6dc9357SAndroid Build Coastguard Worker   FLAGS flFlags;
1078*f6dc9357SAndroid Build Coastguard Worker   Z7_WIN_lpMapiRecipDescW lpOriginator;
1079*f6dc9357SAndroid Build Coastguard Worker   ULONG nRecipCount;
1080*f6dc9357SAndroid Build Coastguard Worker   Z7_WIN_lpMapiRecipDescW lpRecips;
1081*f6dc9357SAndroid Build Coastguard Worker   ULONG nFileCount;
1082*f6dc9357SAndroid Build Coastguard Worker   Z7_WIN_lpMapiFileDescW lpFiles;
1083*f6dc9357SAndroid Build Coastguard Worker } Z7_WIN_MapiMessageW, *Z7_WIN_lpMapiMessageW;
1084*f6dc9357SAndroid Build Coastguard Worker 
1085*f6dc9357SAndroid Build Coastguard Worker typedef ULONG (FAR PASCAL Z7_WIN_MAPISENDMAILW)(
1086*f6dc9357SAndroid Build Coastguard Worker   LHANDLE lhSession,
1087*f6dc9357SAndroid Build Coastguard Worker   ULONG_PTR ulUIParam,
1088*f6dc9357SAndroid Build Coastguard Worker   Z7_WIN_lpMapiMessageW lpMessage,
1089*f6dc9357SAndroid Build Coastguard Worker   FLAGS flFlags,
1090*f6dc9357SAndroid Build Coastguard Worker   ULONG ulReserved
1091*f6dc9357SAndroid Build Coastguard Worker );
1092*f6dc9357SAndroid Build Coastguard Worker typedef Z7_WIN_MAPISENDMAILW FAR *Z7_WIN_LPMAPISENDMAILW;
1093*f6dc9357SAndroid Build Coastguard Worker 
1094*f6dc9357SAndroid Build Coastguard Worker #endif // MAPI_FORCE_UNICODE
1095*f6dc9357SAndroid Build Coastguard Worker }
1096*f6dc9357SAndroid Build Coastguard Worker #endif // _WIN32
1097*f6dc9357SAndroid Build Coastguard Worker 
1098*f6dc9357SAndroid Build Coastguard Worker 
1099*f6dc9357SAndroid Build Coastguard Worker struct C_CopyFileProgress_to_IUpdateCallbackUI2 Z7_final:
1100*f6dc9357SAndroid Build Coastguard Worker   public ICopyFileProgress
1101*f6dc9357SAndroid Build Coastguard Worker {
1102*f6dc9357SAndroid Build Coastguard Worker   IUpdateCallbackUI2 *Callback;
1103*f6dc9357SAndroid Build Coastguard Worker   HRESULT CallbackResult;
1104*f6dc9357SAndroid Build Coastguard Worker   // bool Disable_Break;
1105*f6dc9357SAndroid Build Coastguard Worker 
CopyFileProgressZ7_final1106*f6dc9357SAndroid Build Coastguard Worker   virtual DWORD CopyFileProgress(UInt64 total, UInt64 current) Z7_override
1107*f6dc9357SAndroid Build Coastguard Worker   {
1108*f6dc9357SAndroid Build Coastguard Worker     const HRESULT res = Callback->MoveArc_Progress(total, current);
1109*f6dc9357SAndroid Build Coastguard Worker     CallbackResult = res;
1110*f6dc9357SAndroid Build Coastguard Worker     // if (Disable_Break && res == E_ABORT) res = S_OK;
1111*f6dc9357SAndroid Build Coastguard Worker     return res == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL;
1112*f6dc9357SAndroid Build Coastguard Worker   }
1113*f6dc9357SAndroid Build Coastguard Worker 
C_CopyFileProgress_to_IUpdateCallbackUI2Z7_final1114*f6dc9357SAndroid Build Coastguard Worker   C_CopyFileProgress_to_IUpdateCallbackUI2(
1115*f6dc9357SAndroid Build Coastguard Worker       IUpdateCallbackUI2 *callback) :
1116*f6dc9357SAndroid Build Coastguard Worker     Callback(callback),
1117*f6dc9357SAndroid Build Coastguard Worker     CallbackResult(S_OK)
1118*f6dc9357SAndroid Build Coastguard Worker     // , Disable_Break(false)
1119*f6dc9357SAndroid Build Coastguard Worker     {}
1120*f6dc9357SAndroid Build Coastguard Worker };
1121*f6dc9357SAndroid Build Coastguard Worker 
1122*f6dc9357SAndroid Build Coastguard Worker 
UpdateArchive(CCodecs * codecs,const CObjectVector<COpenType> & types,const UString & cmdArcPath2,NWildcard::CCensor & censor,CUpdateOptions & options,CUpdateErrorInfo & errorInfo,IOpenCallbackUI * openCallback,IUpdateCallbackUI2 * callback,bool needSetPath)1123*f6dc9357SAndroid Build Coastguard Worker HRESULT UpdateArchive(
1124*f6dc9357SAndroid Build Coastguard Worker     CCodecs *codecs,
1125*f6dc9357SAndroid Build Coastguard Worker     const CObjectVector<COpenType> &types,
1126*f6dc9357SAndroid Build Coastguard Worker     const UString &cmdArcPath2,
1127*f6dc9357SAndroid Build Coastguard Worker     NWildcard::CCensor &censor,
1128*f6dc9357SAndroid Build Coastguard Worker     CUpdateOptions &options,
1129*f6dc9357SAndroid Build Coastguard Worker     CUpdateErrorInfo &errorInfo,
1130*f6dc9357SAndroid Build Coastguard Worker     IOpenCallbackUI *openCallback,
1131*f6dc9357SAndroid Build Coastguard Worker     IUpdateCallbackUI2 *callback,
1132*f6dc9357SAndroid Build Coastguard Worker     bool needSetPath)
1133*f6dc9357SAndroid Build Coastguard Worker {
1134*f6dc9357SAndroid Build Coastguard Worker   if (options.StdOutMode && options.EMailMode)
1135*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
1136*f6dc9357SAndroid Build Coastguard Worker 
1137*f6dc9357SAndroid Build Coastguard Worker   if (types.Size() > 1)
1138*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
1139*f6dc9357SAndroid Build Coastguard Worker 
1140*f6dc9357SAndroid Build Coastguard Worker   bool renameMode = !options.RenamePairs.IsEmpty();
1141*f6dc9357SAndroid Build Coastguard Worker   if (renameMode)
1142*f6dc9357SAndroid Build Coastguard Worker   {
1143*f6dc9357SAndroid Build Coastguard Worker     if (options.Commands.Size() != 1)
1144*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
1145*f6dc9357SAndroid Build Coastguard Worker   }
1146*f6dc9357SAndroid Build Coastguard Worker 
1147*f6dc9357SAndroid Build Coastguard Worker   if (options.DeleteAfterCompressing)
1148*f6dc9357SAndroid Build Coastguard Worker   {
1149*f6dc9357SAndroid Build Coastguard Worker     if (options.Commands.Size() != 1)
1150*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
1151*f6dc9357SAndroid Build Coastguard Worker     const CActionSet &as = options.Commands[0].ActionSet;
1152*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 2; i < NPairState::kNumValues; i++)
1153*f6dc9357SAndroid Build Coastguard Worker       if (as.StateActions[i] != NPairAction::kCompress)
1154*f6dc9357SAndroid Build Coastguard Worker         return E_NOTIMPL;
1155*f6dc9357SAndroid Build Coastguard Worker   }
1156*f6dc9357SAndroid Build Coastguard Worker 
1157*f6dc9357SAndroid Build Coastguard Worker   censor.AddPathsToCensor(options.PathMode);
1158*f6dc9357SAndroid Build Coastguard Worker   #ifdef _WIN32
1159*f6dc9357SAndroid Build Coastguard Worker   ConvertToLongNames(censor);
1160*f6dc9357SAndroid Build Coastguard Worker   #endif
1161*f6dc9357SAndroid Build Coastguard Worker   censor.ExtendExclude();
1162*f6dc9357SAndroid Build Coastguard Worker 
1163*f6dc9357SAndroid Build Coastguard Worker 
1164*f6dc9357SAndroid Build Coastguard Worker   if (options.VolumesSizes.Size() > 0 && (options.EMailMode /* || options.SfxMode */))
1165*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
1166*f6dc9357SAndroid Build Coastguard Worker 
1167*f6dc9357SAndroid Build Coastguard Worker   if (options.SfxMode)
1168*f6dc9357SAndroid Build Coastguard Worker   {
1169*f6dc9357SAndroid Build Coastguard Worker     CProperty property;
1170*f6dc9357SAndroid Build Coastguard Worker     property.Name = "rsfx";
1171*f6dc9357SAndroid Build Coastguard Worker     options.MethodMode.Properties.Add(property);
1172*f6dc9357SAndroid Build Coastguard Worker     if (options.SfxModule.IsEmpty())
1173*f6dc9357SAndroid Build Coastguard Worker     {
1174*f6dc9357SAndroid Build Coastguard Worker       errorInfo.Message = "SFX file is not specified";
1175*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
1176*f6dc9357SAndroid Build Coastguard Worker     }
1177*f6dc9357SAndroid Build Coastguard Worker     bool found = false;
1178*f6dc9357SAndroid Build Coastguard Worker     if (options.SfxModule.Find(FCHAR_PATH_SEPARATOR) < 0)
1179*f6dc9357SAndroid Build Coastguard Worker     {
1180*f6dc9357SAndroid Build Coastguard Worker       const FString fullName = NDLL::GetModuleDirPrefix() + options.SfxModule;
1181*f6dc9357SAndroid Build Coastguard Worker       if (NFind::DoesFileExist_FollowLink(fullName))
1182*f6dc9357SAndroid Build Coastguard Worker       {
1183*f6dc9357SAndroid Build Coastguard Worker         options.SfxModule = fullName;
1184*f6dc9357SAndroid Build Coastguard Worker         found = true;
1185*f6dc9357SAndroid Build Coastguard Worker       }
1186*f6dc9357SAndroid Build Coastguard Worker     }
1187*f6dc9357SAndroid Build Coastguard Worker     if (!found)
1188*f6dc9357SAndroid Build Coastguard Worker     {
1189*f6dc9357SAndroid Build Coastguard Worker       if (!NFind::DoesFileExist_FollowLink(options.SfxModule))
1190*f6dc9357SAndroid Build Coastguard Worker         return errorInfo.SetFromLastError("cannot find specified SFX module", options.SfxModule);
1191*f6dc9357SAndroid Build Coastguard Worker     }
1192*f6dc9357SAndroid Build Coastguard Worker   }
1193*f6dc9357SAndroid Build Coastguard Worker 
1194*f6dc9357SAndroid Build Coastguard Worker   CArchiveLink arcLink;
1195*f6dc9357SAndroid Build Coastguard Worker 
1196*f6dc9357SAndroid Build Coastguard Worker 
1197*f6dc9357SAndroid Build Coastguard Worker   if (needSetPath)
1198*f6dc9357SAndroid Build Coastguard Worker   {
1199*f6dc9357SAndroid Build Coastguard Worker     if (!options.InitFormatIndex(codecs, types, cmdArcPath2) ||
1200*f6dc9357SAndroid Build Coastguard Worker         !options.SetArcPath(codecs, cmdArcPath2))
1201*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
1202*f6dc9357SAndroid Build Coastguard Worker   }
1203*f6dc9357SAndroid Build Coastguard Worker 
1204*f6dc9357SAndroid Build Coastguard Worker   UString arcPath = options.ArchivePath.GetFinalPath();
1205*f6dc9357SAndroid Build Coastguard Worker 
1206*f6dc9357SAndroid Build Coastguard Worker   if (!options.VolumesSizes.IsEmpty())
1207*f6dc9357SAndroid Build Coastguard Worker   {
1208*f6dc9357SAndroid Build Coastguard Worker     arcPath = options.ArchivePath.GetFinalVolPath();
1209*f6dc9357SAndroid Build Coastguard Worker     arcPath += ".001";
1210*f6dc9357SAndroid Build Coastguard Worker   }
1211*f6dc9357SAndroid Build Coastguard Worker 
1212*f6dc9357SAndroid Build Coastguard Worker   if (cmdArcPath2.IsEmpty())
1213*f6dc9357SAndroid Build Coastguard Worker   {
1214*f6dc9357SAndroid Build Coastguard Worker     if (options.MethodMode.Type.FormatIndex < 0)
1215*f6dc9357SAndroid Build Coastguard Worker       throw "type of archive is not specified";
1216*f6dc9357SAndroid Build Coastguard Worker   }
1217*f6dc9357SAndroid Build Coastguard Worker   else
1218*f6dc9357SAndroid Build Coastguard Worker   {
1219*f6dc9357SAndroid Build Coastguard Worker     NFind::CFileInfo fi;
1220*f6dc9357SAndroid Build Coastguard Worker     if (!fi.Find_FollowLink(us2fs(arcPath)))
1221*f6dc9357SAndroid Build Coastguard Worker     {
1222*f6dc9357SAndroid Build Coastguard Worker       if (renameMode)
1223*f6dc9357SAndroid Build Coastguard Worker         throw "can't find archive";
1224*f6dc9357SAndroid Build Coastguard Worker       if (options.MethodMode.Type.FormatIndex < 0)
1225*f6dc9357SAndroid Build Coastguard Worker       {
1226*f6dc9357SAndroid Build Coastguard Worker         if (!options.SetArcPath(codecs, cmdArcPath2))
1227*f6dc9357SAndroid Build Coastguard Worker           return E_NOTIMPL;
1228*f6dc9357SAndroid Build Coastguard Worker       }
1229*f6dc9357SAndroid Build Coastguard Worker     }
1230*f6dc9357SAndroid Build Coastguard Worker     else
1231*f6dc9357SAndroid Build Coastguard Worker     {
1232*f6dc9357SAndroid Build Coastguard Worker       if (fi.IsDir())
1233*f6dc9357SAndroid Build Coastguard Worker         return errorInfo.SetFromError_DWORD("There is a folder with the name of archive",
1234*f6dc9357SAndroid Build Coastguard Worker             us2fs(arcPath),
1235*f6dc9357SAndroid Build Coastguard Worker             #ifdef _WIN32
1236*f6dc9357SAndroid Build Coastguard Worker               ERROR_ACCESS_DENIED
1237*f6dc9357SAndroid Build Coastguard Worker             #else
1238*f6dc9357SAndroid Build Coastguard Worker               EISDIR
1239*f6dc9357SAndroid Build Coastguard Worker             #endif
1240*f6dc9357SAndroid Build Coastguard Worker             );
1241*f6dc9357SAndroid Build Coastguard Worker      #ifdef _WIN32
1242*f6dc9357SAndroid Build Coastguard Worker       if (fi.IsDevice)
1243*f6dc9357SAndroid Build Coastguard Worker         return E_NOTIMPL;
1244*f6dc9357SAndroid Build Coastguard Worker      #endif
1245*f6dc9357SAndroid Build Coastguard Worker 
1246*f6dc9357SAndroid Build Coastguard Worker       if (!options.StdOutMode && options.UpdateArchiveItself)
1247*f6dc9357SAndroid Build Coastguard Worker         if (fi.IsReadOnly())
1248*f6dc9357SAndroid Build Coastguard Worker         {
1249*f6dc9357SAndroid Build Coastguard Worker           return errorInfo.SetFromError_DWORD("The file is read-only",
1250*f6dc9357SAndroid Build Coastguard Worker               us2fs(arcPath),
1251*f6dc9357SAndroid Build Coastguard Worker               #ifdef _WIN32
1252*f6dc9357SAndroid Build Coastguard Worker                 ERROR_ACCESS_DENIED
1253*f6dc9357SAndroid Build Coastguard Worker               #else
1254*f6dc9357SAndroid Build Coastguard Worker                 EACCES
1255*f6dc9357SAndroid Build Coastguard Worker               #endif
1256*f6dc9357SAndroid Build Coastguard Worker               );
1257*f6dc9357SAndroid Build Coastguard Worker         }
1258*f6dc9357SAndroid Build Coastguard Worker 
1259*f6dc9357SAndroid Build Coastguard Worker       if (options.VolumesSizes.Size() > 0)
1260*f6dc9357SAndroid Build Coastguard Worker       {
1261*f6dc9357SAndroid Build Coastguard Worker         errorInfo.FileNames.Add(us2fs(arcPath));
1262*f6dc9357SAndroid Build Coastguard Worker         // errorInfo.SystemError = (DWORD)E_NOTIMPL;
1263*f6dc9357SAndroid Build Coastguard Worker         errorInfo.Message = kUpdateIsNotSupported_MultiVol;
1264*f6dc9357SAndroid Build Coastguard Worker         return E_NOTIMPL;
1265*f6dc9357SAndroid Build Coastguard Worker       }
1266*f6dc9357SAndroid Build Coastguard Worker       CObjectVector<COpenType> types2;
1267*f6dc9357SAndroid Build Coastguard Worker       // change it.
1268*f6dc9357SAndroid Build Coastguard Worker       if (options.MethodMode.Type_Defined)
1269*f6dc9357SAndroid Build Coastguard Worker         types2.Add(options.MethodMode.Type);
1270*f6dc9357SAndroid Build Coastguard Worker       // We need to set Properties to open archive only in some cases (WIM archives).
1271*f6dc9357SAndroid Build Coastguard Worker 
1272*f6dc9357SAndroid Build Coastguard Worker       CIntVector excl;
1273*f6dc9357SAndroid Build Coastguard Worker       COpenOptions op;
1274*f6dc9357SAndroid Build Coastguard Worker       #ifndef Z7_SFX
1275*f6dc9357SAndroid Build Coastguard Worker       op.props = &options.MethodMode.Properties;
1276*f6dc9357SAndroid Build Coastguard Worker       #endif
1277*f6dc9357SAndroid Build Coastguard Worker       op.codecs = codecs;
1278*f6dc9357SAndroid Build Coastguard Worker       op.types = &types2;
1279*f6dc9357SAndroid Build Coastguard Worker       op.excludedFormats = &excl;
1280*f6dc9357SAndroid Build Coastguard Worker       op.stdInMode = false;
1281*f6dc9357SAndroid Build Coastguard Worker       op.stream = NULL;
1282*f6dc9357SAndroid Build Coastguard Worker       op.filePath = arcPath;
1283*f6dc9357SAndroid Build Coastguard Worker 
1284*f6dc9357SAndroid Build Coastguard Worker       RINOK(callback->StartOpenArchive(arcPath))
1285*f6dc9357SAndroid Build Coastguard Worker 
1286*f6dc9357SAndroid Build Coastguard Worker       HRESULT result = arcLink.Open_Strict(op, openCallback);
1287*f6dc9357SAndroid Build Coastguard Worker 
1288*f6dc9357SAndroid Build Coastguard Worker       if (result == E_ABORT)
1289*f6dc9357SAndroid Build Coastguard Worker         return result;
1290*f6dc9357SAndroid Build Coastguard Worker 
1291*f6dc9357SAndroid Build Coastguard Worker       HRESULT res2 = callback->OpenResult(codecs, arcLink, arcPath, result);
1292*f6dc9357SAndroid Build Coastguard Worker       /*
1293*f6dc9357SAndroid Build Coastguard Worker       if (result == S_FALSE)
1294*f6dc9357SAndroid Build Coastguard Worker         return E_FAIL;
1295*f6dc9357SAndroid Build Coastguard Worker       */
1296*f6dc9357SAndroid Build Coastguard Worker       RINOK(res2)
1297*f6dc9357SAndroid Build Coastguard Worker       RINOK(result)
1298*f6dc9357SAndroid Build Coastguard Worker 
1299*f6dc9357SAndroid Build Coastguard Worker       if (arcLink.VolumePaths.Size() > 1)
1300*f6dc9357SAndroid Build Coastguard Worker       {
1301*f6dc9357SAndroid Build Coastguard Worker         // errorInfo.SystemError = (DWORD)E_NOTIMPL;
1302*f6dc9357SAndroid Build Coastguard Worker         errorInfo.Message = kUpdateIsNotSupported_MultiVol;
1303*f6dc9357SAndroid Build Coastguard Worker         return E_NOTIMPL;
1304*f6dc9357SAndroid Build Coastguard Worker       }
1305*f6dc9357SAndroid Build Coastguard Worker 
1306*f6dc9357SAndroid Build Coastguard Worker       CArc &arc = arcLink.Arcs.Back();
1307*f6dc9357SAndroid Build Coastguard Worker       arc.MTime.Def =
1308*f6dc9357SAndroid Build Coastguard Worker         #ifdef _WIN32
1309*f6dc9357SAndroid Build Coastguard Worker           !fi.IsDevice;
1310*f6dc9357SAndroid Build Coastguard Worker         #else
1311*f6dc9357SAndroid Build Coastguard Worker           true;
1312*f6dc9357SAndroid Build Coastguard Worker         #endif
1313*f6dc9357SAndroid Build Coastguard Worker       if (arc.MTime.Def)
1314*f6dc9357SAndroid Build Coastguard Worker         arc.MTime.Set_From_FiTime(fi.MTime);
1315*f6dc9357SAndroid Build Coastguard Worker 
1316*f6dc9357SAndroid Build Coastguard Worker       if (arc.ErrorInfo.ThereIsTail)
1317*f6dc9357SAndroid Build Coastguard Worker       {
1318*f6dc9357SAndroid Build Coastguard Worker         // errorInfo.SystemError = (DWORD)E_NOTIMPL;
1319*f6dc9357SAndroid Build Coastguard Worker         errorInfo.Message = "There is some data block after the end of the archive";
1320*f6dc9357SAndroid Build Coastguard Worker         return E_NOTIMPL;
1321*f6dc9357SAndroid Build Coastguard Worker       }
1322*f6dc9357SAndroid Build Coastguard Worker       if (options.MethodMode.Type.FormatIndex < 0)
1323*f6dc9357SAndroid Build Coastguard Worker       {
1324*f6dc9357SAndroid Build Coastguard Worker         options.MethodMode.Type.FormatIndex = arcLink.GetArc()->FormatIndex;
1325*f6dc9357SAndroid Build Coastguard Worker         if (!options.SetArcPath(codecs, cmdArcPath2))
1326*f6dc9357SAndroid Build Coastguard Worker           return E_NOTIMPL;
1327*f6dc9357SAndroid Build Coastguard Worker       }
1328*f6dc9357SAndroid Build Coastguard Worker     }
1329*f6dc9357SAndroid Build Coastguard Worker   }
1330*f6dc9357SAndroid Build Coastguard Worker 
1331*f6dc9357SAndroid Build Coastguard Worker   if (options.MethodMode.Type.FormatIndex < 0)
1332*f6dc9357SAndroid Build Coastguard Worker   {
1333*f6dc9357SAndroid Build Coastguard Worker     options.MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveType((UString)kDefaultArcType);
1334*f6dc9357SAndroid Build Coastguard Worker     if (options.MethodMode.Type.FormatIndex < 0)
1335*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
1336*f6dc9357SAndroid Build Coastguard Worker   }
1337*f6dc9357SAndroid Build Coastguard Worker 
1338*f6dc9357SAndroid Build Coastguard Worker   const bool thereIsInArchive = arcLink.IsOpen;
1339*f6dc9357SAndroid Build Coastguard Worker   if (!thereIsInArchive && renameMode)
1340*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
1341*f6dc9357SAndroid Build Coastguard Worker 
1342*f6dc9357SAndroid Build Coastguard Worker   CDirItems dirItems;
1343*f6dc9357SAndroid Build Coastguard Worker   dirItems.Callback = callback;
1344*f6dc9357SAndroid Build Coastguard Worker 
1345*f6dc9357SAndroid Build Coastguard Worker   CDirItem parentDirItem;
1346*f6dc9357SAndroid Build Coastguard Worker   CDirItem *parentDirItem_Ptr = NULL;
1347*f6dc9357SAndroid Build Coastguard Worker 
1348*f6dc9357SAndroid Build Coastguard Worker   /*
1349*f6dc9357SAndroid Build Coastguard Worker   FStringVector requestedPaths;
1350*f6dc9357SAndroid Build Coastguard Worker   FStringVector *requestedPaths_Ptr = NULL;
1351*f6dc9357SAndroid Build Coastguard Worker   if (options.DeleteAfterCompressing)
1352*f6dc9357SAndroid Build Coastguard Worker     requestedPaths_Ptr = &requestedPaths;
1353*f6dc9357SAndroid Build Coastguard Worker   */
1354*f6dc9357SAndroid Build Coastguard Worker 
1355*f6dc9357SAndroid Build Coastguard Worker   if (options.StdInMode)
1356*f6dc9357SAndroid Build Coastguard Worker   {
1357*f6dc9357SAndroid Build Coastguard Worker     CDirItem di;
1358*f6dc9357SAndroid Build Coastguard Worker     // di.ClearBase();
1359*f6dc9357SAndroid Build Coastguard Worker     // di.Size = (UInt64)(Int64)-1;
1360*f6dc9357SAndroid Build Coastguard Worker     if (!di.SetAs_StdInFile())
1361*f6dc9357SAndroid Build Coastguard Worker       return GetLastError_noZero_HRESULT();
1362*f6dc9357SAndroid Build Coastguard Worker     di.Name = options.StdInFileName;
1363*f6dc9357SAndroid Build Coastguard Worker     // di.Attrib_IsDefined = false;
1364*f6dc9357SAndroid Build Coastguard Worker     // NTime::GetCurUtc_FiTime(di.MTime);
1365*f6dc9357SAndroid Build Coastguard Worker     // di.CTime = di.ATime = di.MTime;
1366*f6dc9357SAndroid Build Coastguard Worker     dirItems.Items.Add(di);
1367*f6dc9357SAndroid Build Coastguard Worker   }
1368*f6dc9357SAndroid Build Coastguard Worker   else
1369*f6dc9357SAndroid Build Coastguard Worker   {
1370*f6dc9357SAndroid Build Coastguard Worker     bool needScanning = false;
1371*f6dc9357SAndroid Build Coastguard Worker 
1372*f6dc9357SAndroid Build Coastguard Worker     if (!renameMode)
1373*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, options.Commands)
1374*f6dc9357SAndroid Build Coastguard Worker       if (options.Commands[i].ActionSet.NeedScanning())
1375*f6dc9357SAndroid Build Coastguard Worker         needScanning = true;
1376*f6dc9357SAndroid Build Coastguard Worker 
1377*f6dc9357SAndroid Build Coastguard Worker     if (needScanning)
1378*f6dc9357SAndroid Build Coastguard Worker     {
1379*f6dc9357SAndroid Build Coastguard Worker       RINOK(callback->StartScanning())
1380*f6dc9357SAndroid Build Coastguard Worker 
1381*f6dc9357SAndroid Build Coastguard Worker       dirItems.SymLinks = options.SymLinks.Val;
1382*f6dc9357SAndroid Build Coastguard Worker 
1383*f6dc9357SAndroid Build Coastguard Worker       #if defined(_WIN32) && !defined(UNDER_CE)
1384*f6dc9357SAndroid Build Coastguard Worker       dirItems.ReadSecure = options.NtSecurity.Val;
1385*f6dc9357SAndroid Build Coastguard Worker       #endif
1386*f6dc9357SAndroid Build Coastguard Worker 
1387*f6dc9357SAndroid Build Coastguard Worker       dirItems.ScanAltStreams = options.AltStreams.Val;
1388*f6dc9357SAndroid Build Coastguard Worker       dirItems.ExcludeDirItems = censor.ExcludeDirItems;
1389*f6dc9357SAndroid Build Coastguard Worker       dirItems.ExcludeFileItems = censor.ExcludeFileItems;
1390*f6dc9357SAndroid Build Coastguard Worker 
1391*f6dc9357SAndroid Build Coastguard Worker       dirItems.ShareForWrite = options.OpenShareForWrite;
1392*f6dc9357SAndroid Build Coastguard Worker 
1393*f6dc9357SAndroid Build Coastguard Worker      #ifndef _WIN32
1394*f6dc9357SAndroid Build Coastguard Worker       dirItems.StoreOwnerName = options.StoreOwnerName.Val;
1395*f6dc9357SAndroid Build Coastguard Worker      #endif
1396*f6dc9357SAndroid Build Coastguard Worker 
1397*f6dc9357SAndroid Build Coastguard Worker       const HRESULT res = EnumerateItems(censor,
1398*f6dc9357SAndroid Build Coastguard Worker           options.PathMode,
1399*f6dc9357SAndroid Build Coastguard Worker           UString(), // options.AddPathPrefix,
1400*f6dc9357SAndroid Build Coastguard Worker           dirItems);
1401*f6dc9357SAndroid Build Coastguard Worker 
1402*f6dc9357SAndroid Build Coastguard Worker       if (res != S_OK)
1403*f6dc9357SAndroid Build Coastguard Worker       {
1404*f6dc9357SAndroid Build Coastguard Worker         if (res != E_ABORT)
1405*f6dc9357SAndroid Build Coastguard Worker           errorInfo.Message = "Scanning error";
1406*f6dc9357SAndroid Build Coastguard Worker         return res;
1407*f6dc9357SAndroid Build Coastguard Worker       }
1408*f6dc9357SAndroid Build Coastguard Worker 
1409*f6dc9357SAndroid Build Coastguard Worker       RINOK(callback->FinishScanning(dirItems.Stat))
1410*f6dc9357SAndroid Build Coastguard Worker 
1411*f6dc9357SAndroid Build Coastguard Worker       // 22.00: we don't need parent folder, if absolute path mode
1412*f6dc9357SAndroid Build Coastguard Worker       if (options.PathMode != NWildcard::k_AbsPath)
1413*f6dc9357SAndroid Build Coastguard Worker       if (censor.Pairs.Size() == 1)
1414*f6dc9357SAndroid Build Coastguard Worker       {
1415*f6dc9357SAndroid Build Coastguard Worker         NFind::CFileInfo fi;
1416*f6dc9357SAndroid Build Coastguard Worker         FString prefix = us2fs(censor.Pairs[0].Prefix);
1417*f6dc9357SAndroid Build Coastguard Worker         prefix.Add_Dot();
1418*f6dc9357SAndroid Build Coastguard Worker         // UString prefix = censor.Pairs[0].Prefix;
1419*f6dc9357SAndroid Build Coastguard Worker         /*
1420*f6dc9357SAndroid Build Coastguard Worker         if (prefix.Back() == WCHAR_PATH_SEPARATOR)
1421*f6dc9357SAndroid Build Coastguard Worker         {
1422*f6dc9357SAndroid Build Coastguard Worker           prefix.DeleteBack();
1423*f6dc9357SAndroid Build Coastguard Worker         }
1424*f6dc9357SAndroid Build Coastguard Worker         */
1425*f6dc9357SAndroid Build Coastguard Worker         if (fi.Find(prefix))
1426*f6dc9357SAndroid Build Coastguard Worker           if (fi.IsDir())
1427*f6dc9357SAndroid Build Coastguard Worker           {
1428*f6dc9357SAndroid Build Coastguard Worker             parentDirItem.Copy_From_FileInfoBase(fi);
1429*f6dc9357SAndroid Build Coastguard Worker             parentDirItem_Ptr = &parentDirItem;
1430*f6dc9357SAndroid Build Coastguard Worker 
1431*f6dc9357SAndroid Build Coastguard Worker             int secureIndex = -1;
1432*f6dc9357SAndroid Build Coastguard Worker             #if defined(_WIN32) && !defined(UNDER_CE)
1433*f6dc9357SAndroid Build Coastguard Worker             if (options.NtSecurity.Val)
1434*f6dc9357SAndroid Build Coastguard Worker               dirItems.AddSecurityItem(prefix, secureIndex);
1435*f6dc9357SAndroid Build Coastguard Worker             #endif
1436*f6dc9357SAndroid Build Coastguard Worker             parentDirItem.SecureIndex = secureIndex;
1437*f6dc9357SAndroid Build Coastguard Worker           }
1438*f6dc9357SAndroid Build Coastguard Worker       }
1439*f6dc9357SAndroid Build Coastguard Worker     }
1440*f6dc9357SAndroid Build Coastguard Worker   }
1441*f6dc9357SAndroid Build Coastguard Worker 
1442*f6dc9357SAndroid Build Coastguard Worker   FString tempDirPrefix;
1443*f6dc9357SAndroid Build Coastguard Worker   bool usesTempDir = false;
1444*f6dc9357SAndroid Build Coastguard Worker 
1445*f6dc9357SAndroid Build Coastguard Worker   #ifdef _WIN32
1446*f6dc9357SAndroid Build Coastguard Worker   CTempDir tempDirectory;
1447*f6dc9357SAndroid Build Coastguard Worker   if (options.EMailMode && options.EMailRemoveAfter)
1448*f6dc9357SAndroid Build Coastguard Worker   {
1449*f6dc9357SAndroid Build Coastguard Worker     tempDirectory.Create(kTempFolderPrefix);
1450*f6dc9357SAndroid Build Coastguard Worker     tempDirPrefix = tempDirectory.GetPath();
1451*f6dc9357SAndroid Build Coastguard Worker     NormalizeDirPathPrefix(tempDirPrefix);
1452*f6dc9357SAndroid Build Coastguard Worker     usesTempDir = true;
1453*f6dc9357SAndroid Build Coastguard Worker   }
1454*f6dc9357SAndroid Build Coastguard Worker   #endif
1455*f6dc9357SAndroid Build Coastguard Worker 
1456*f6dc9357SAndroid Build Coastguard Worker   CTempFiles tempFiles;
1457*f6dc9357SAndroid Build Coastguard Worker 
1458*f6dc9357SAndroid Build Coastguard Worker   bool createTempFile = false;
1459*f6dc9357SAndroid Build Coastguard Worker 
1460*f6dc9357SAndroid Build Coastguard Worker   if (!options.StdOutMode && options.UpdateArchiveItself)
1461*f6dc9357SAndroid Build Coastguard Worker   {
1462*f6dc9357SAndroid Build Coastguard Worker     CArchivePath &ap = options.Commands[0].ArchivePath;
1463*f6dc9357SAndroid Build Coastguard Worker     ap = options.ArchivePath;
1464*f6dc9357SAndroid Build Coastguard Worker     // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty())
1465*f6dc9357SAndroid Build Coastguard Worker     if ((thereIsInArchive || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0)
1466*f6dc9357SAndroid Build Coastguard Worker     {
1467*f6dc9357SAndroid Build Coastguard Worker       createTempFile = true;
1468*f6dc9357SAndroid Build Coastguard Worker       ap.Temp = true;
1469*f6dc9357SAndroid Build Coastguard Worker       if (!options.WorkingDir.IsEmpty())
1470*f6dc9357SAndroid Build Coastguard Worker         ap.TempPrefix = options.WorkingDir;
1471*f6dc9357SAndroid Build Coastguard Worker       else
1472*f6dc9357SAndroid Build Coastguard Worker         ap.TempPrefix = us2fs(ap.Prefix);
1473*f6dc9357SAndroid Build Coastguard Worker       NormalizeDirPathPrefix(ap.TempPrefix);
1474*f6dc9357SAndroid Build Coastguard Worker     }
1475*f6dc9357SAndroid Build Coastguard Worker   }
1476*f6dc9357SAndroid Build Coastguard Worker 
1477*f6dc9357SAndroid Build Coastguard Worker   unsigned ci;
1478*f6dc9357SAndroid Build Coastguard Worker 
1479*f6dc9357SAndroid Build Coastguard Worker 
1480*f6dc9357SAndroid Build Coastguard Worker   // self including protection
1481*f6dc9357SAndroid Build Coastguard Worker   if (options.DeleteAfterCompressing)
1482*f6dc9357SAndroid Build Coastguard Worker   {
1483*f6dc9357SAndroid Build Coastguard Worker     for (ci = 0; ci < options.Commands.Size(); ci++)
1484*f6dc9357SAndroid Build Coastguard Worker     {
1485*f6dc9357SAndroid Build Coastguard Worker       CArchivePath &ap = options.Commands[ci].ArchivePath;
1486*f6dc9357SAndroid Build Coastguard Worker       const FString path = us2fs(ap.GetFinalPath());
1487*f6dc9357SAndroid Build Coastguard Worker       // maybe we must compare absolute paths path here
1488*f6dc9357SAndroid Build Coastguard Worker       FOR_VECTOR (i, dirItems.Items)
1489*f6dc9357SAndroid Build Coastguard Worker       {
1490*f6dc9357SAndroid Build Coastguard Worker         const FString phyPath = dirItems.GetPhyPath(i);
1491*f6dc9357SAndroid Build Coastguard Worker         if (phyPath == path)
1492*f6dc9357SAndroid Build Coastguard Worker         {
1493*f6dc9357SAndroid Build Coastguard Worker           UString s;
1494*f6dc9357SAndroid Build Coastguard Worker           s = "It is not allowed to include archive to itself";
1495*f6dc9357SAndroid Build Coastguard Worker           s.Add_LF();
1496*f6dc9357SAndroid Build Coastguard Worker           s += fs2us(path);
1497*f6dc9357SAndroid Build Coastguard Worker           throw s;
1498*f6dc9357SAndroid Build Coastguard Worker         }
1499*f6dc9357SAndroid Build Coastguard Worker       }
1500*f6dc9357SAndroid Build Coastguard Worker     }
1501*f6dc9357SAndroid Build Coastguard Worker   }
1502*f6dc9357SAndroid Build Coastguard Worker 
1503*f6dc9357SAndroid Build Coastguard Worker 
1504*f6dc9357SAndroid Build Coastguard Worker   for (ci = 0; ci < options.Commands.Size(); ci++)
1505*f6dc9357SAndroid Build Coastguard Worker   {
1506*f6dc9357SAndroid Build Coastguard Worker     CArchivePath &ap = options.Commands[ci].ArchivePath;
1507*f6dc9357SAndroid Build Coastguard Worker     if (usesTempDir)
1508*f6dc9357SAndroid Build Coastguard Worker     {
1509*f6dc9357SAndroid Build Coastguard Worker       // Check it
1510*f6dc9357SAndroid Build Coastguard Worker       ap.Prefix = fs2us(tempDirPrefix);
1511*f6dc9357SAndroid Build Coastguard Worker       // ap.Temp = true;
1512*f6dc9357SAndroid Build Coastguard Worker       // ap.TempPrefix = tempDirPrefix;
1513*f6dc9357SAndroid Build Coastguard Worker     }
1514*f6dc9357SAndroid Build Coastguard Worker     if (!options.StdOutMode &&
1515*f6dc9357SAndroid Build Coastguard Worker         (ci > 0 || !createTempFile))
1516*f6dc9357SAndroid Build Coastguard Worker     {
1517*f6dc9357SAndroid Build Coastguard Worker       const FString path = us2fs(ap.GetFinalPath());
1518*f6dc9357SAndroid Build Coastguard Worker       if (NFind::DoesFileOrDirExist(path))
1519*f6dc9357SAndroid Build Coastguard Worker       {
1520*f6dc9357SAndroid Build Coastguard Worker         errorInfo.SystemError = ERROR_FILE_EXISTS;
1521*f6dc9357SAndroid Build Coastguard Worker         errorInfo.Message = "The file already exists";
1522*f6dc9357SAndroid Build Coastguard Worker         errorInfo.FileNames.Add(path);
1523*f6dc9357SAndroid Build Coastguard Worker         return errorInfo.Get_HRESULT_Error();
1524*f6dc9357SAndroid Build Coastguard Worker       }
1525*f6dc9357SAndroid Build Coastguard Worker     }
1526*f6dc9357SAndroid Build Coastguard Worker   }
1527*f6dc9357SAndroid Build Coastguard Worker 
1528*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CArcItem> arcItems;
1529*f6dc9357SAndroid Build Coastguard Worker   if (thereIsInArchive)
1530*f6dc9357SAndroid Build Coastguard Worker   {
1531*f6dc9357SAndroid Build Coastguard Worker     RINOK(EnumerateInArchiveItems(
1532*f6dc9357SAndroid Build Coastguard Worker       // options.StoreAltStreams,
1533*f6dc9357SAndroid Build Coastguard Worker       censor, arcLink.Arcs.Back(), arcItems))
1534*f6dc9357SAndroid Build Coastguard Worker   }
1535*f6dc9357SAndroid Build Coastguard Worker 
1536*f6dc9357SAndroid Build Coastguard Worker   /*
1537*f6dc9357SAndroid Build Coastguard Worker   FStringVector processedFilePaths;
1538*f6dc9357SAndroid Build Coastguard Worker   FStringVector *processedFilePaths_Ptr = NULL;
1539*f6dc9357SAndroid Build Coastguard Worker   if (options.DeleteAfterCompressing)
1540*f6dc9357SAndroid Build Coastguard Worker     processedFilePaths_Ptr = &processedFilePaths;
1541*f6dc9357SAndroid Build Coastguard Worker   */
1542*f6dc9357SAndroid Build Coastguard Worker 
1543*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer processedItems;
1544*f6dc9357SAndroid Build Coastguard Worker   if (options.DeleteAfterCompressing)
1545*f6dc9357SAndroid Build Coastguard Worker   {
1546*f6dc9357SAndroid Build Coastguard Worker     const unsigned num = dirItems.Items.Size();
1547*f6dc9357SAndroid Build Coastguard Worker     processedItems.Alloc(num);
1548*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < num; i++)
1549*f6dc9357SAndroid Build Coastguard Worker       processedItems[i] = 0;
1550*f6dc9357SAndroid Build Coastguard Worker   }
1551*f6dc9357SAndroid Build Coastguard Worker 
1552*f6dc9357SAndroid Build Coastguard Worker   CMultiOutStream_Bunch multiStreams;
1553*f6dc9357SAndroid Build Coastguard Worker 
1554*f6dc9357SAndroid Build Coastguard Worker   /*
1555*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_NO_CRYPTO
1556*f6dc9357SAndroid Build Coastguard Worker   if (arcLink.PasswordWasAsked)
1557*f6dc9357SAndroid Build Coastguard Worker   {
1558*f6dc9357SAndroid Build Coastguard Worker     // We set password, if open have requested password
1559*f6dc9357SAndroid Build Coastguard Worker     RINOK(callback->SetPassword(arcLink.Password));
1560*f6dc9357SAndroid Build Coastguard Worker   }
1561*f6dc9357SAndroid Build Coastguard Worker   #endif
1562*f6dc9357SAndroid Build Coastguard Worker   */
1563*f6dc9357SAndroid Build Coastguard Worker 
1564*f6dc9357SAndroid Build Coastguard Worker   for (ci = 0; ci < options.Commands.Size(); ci++)
1565*f6dc9357SAndroid Build Coastguard Worker   {
1566*f6dc9357SAndroid Build Coastguard Worker     const CArc *arc = thereIsInArchive ? arcLink.GetArc() : NULL;
1567*f6dc9357SAndroid Build Coastguard Worker     CUpdateArchiveCommand &command = options.Commands[ci];
1568*f6dc9357SAndroid Build Coastguard Worker     UString name;
1569*f6dc9357SAndroid Build Coastguard Worker     bool isUpdating;
1570*f6dc9357SAndroid Build Coastguard Worker 
1571*f6dc9357SAndroid Build Coastguard Worker     if (options.StdOutMode)
1572*f6dc9357SAndroid Build Coastguard Worker     {
1573*f6dc9357SAndroid Build Coastguard Worker       name = "stdout";
1574*f6dc9357SAndroid Build Coastguard Worker       isUpdating = thereIsInArchive;
1575*f6dc9357SAndroid Build Coastguard Worker     }
1576*f6dc9357SAndroid Build Coastguard Worker     else
1577*f6dc9357SAndroid Build Coastguard Worker     {
1578*f6dc9357SAndroid Build Coastguard Worker       name = command.ArchivePath.GetFinalPath();
1579*f6dc9357SAndroid Build Coastguard Worker       isUpdating = (ci == 0 && options.UpdateArchiveItself && thereIsInArchive);
1580*f6dc9357SAndroid Build Coastguard Worker     }
1581*f6dc9357SAndroid Build Coastguard Worker 
1582*f6dc9357SAndroid Build Coastguard Worker     RINOK(callback->StartArchive(name, isUpdating))
1583*f6dc9357SAndroid Build Coastguard Worker 
1584*f6dc9357SAndroid Build Coastguard Worker     CFinishArchiveStat st;
1585*f6dc9357SAndroid Build Coastguard Worker 
1586*f6dc9357SAndroid Build Coastguard Worker     RINOK(Compress(options,
1587*f6dc9357SAndroid Build Coastguard Worker         isUpdating,
1588*f6dc9357SAndroid Build Coastguard Worker         codecs,
1589*f6dc9357SAndroid Build Coastguard Worker         command.ActionSet,
1590*f6dc9357SAndroid Build Coastguard Worker         arc,
1591*f6dc9357SAndroid Build Coastguard Worker         command.ArchivePath,
1592*f6dc9357SAndroid Build Coastguard Worker         arcItems,
1593*f6dc9357SAndroid Build Coastguard Worker         options.DeleteAfterCompressing ? (Byte *)processedItems : NULL,
1594*f6dc9357SAndroid Build Coastguard Worker 
1595*f6dc9357SAndroid Build Coastguard Worker         dirItems,
1596*f6dc9357SAndroid Build Coastguard Worker         parentDirItem_Ptr,
1597*f6dc9357SAndroid Build Coastguard Worker 
1598*f6dc9357SAndroid Build Coastguard Worker         tempFiles,
1599*f6dc9357SAndroid Build Coastguard Worker         multiStreams,
1600*f6dc9357SAndroid Build Coastguard Worker         errorInfo, callback, st))
1601*f6dc9357SAndroid Build Coastguard Worker 
1602*f6dc9357SAndroid Build Coastguard Worker     RINOK(callback->FinishArchive(st))
1603*f6dc9357SAndroid Build Coastguard Worker   }
1604*f6dc9357SAndroid Build Coastguard Worker 
1605*f6dc9357SAndroid Build Coastguard Worker 
1606*f6dc9357SAndroid Build Coastguard Worker   if (thereIsInArchive)
1607*f6dc9357SAndroid Build Coastguard Worker   {
1608*f6dc9357SAndroid Build Coastguard Worker     RINOK(arcLink.Close())
1609*f6dc9357SAndroid Build Coastguard Worker     arcLink.Release();
1610*f6dc9357SAndroid Build Coastguard Worker   }
1611*f6dc9357SAndroid Build Coastguard Worker 
1612*f6dc9357SAndroid Build Coastguard Worker   multiStreams.DisableDeletion();
1613*f6dc9357SAndroid Build Coastguard Worker   RINOK(multiStreams.Destruct())
1614*f6dc9357SAndroid Build Coastguard Worker 
1615*f6dc9357SAndroid Build Coastguard Worker   // here we disable deleting of temp archives.
1616*f6dc9357SAndroid Build Coastguard Worker   // note: archive moving can fail, or it can be interrupted,
1617*f6dc9357SAndroid Build Coastguard Worker   // if we move new temp update from another volume.
1618*f6dc9357SAndroid Build Coastguard Worker   // And we still want to keep temp archive in that case,
1619*f6dc9357SAndroid Build Coastguard Worker   // because we will have deleted original archive.
1620*f6dc9357SAndroid Build Coastguard Worker   tempFiles.NeedDeleteFiles = false;
1621*f6dc9357SAndroid Build Coastguard Worker   // tempFiles.Paths.Clear();
1622*f6dc9357SAndroid Build Coastguard Worker 
1623*f6dc9357SAndroid Build Coastguard Worker   if (createTempFile)
1624*f6dc9357SAndroid Build Coastguard Worker   {
1625*f6dc9357SAndroid Build Coastguard Worker     try
1626*f6dc9357SAndroid Build Coastguard Worker     {
1627*f6dc9357SAndroid Build Coastguard Worker       CArchivePath &ap = options.Commands[0].ArchivePath;
1628*f6dc9357SAndroid Build Coastguard Worker       const FString &tempPath = ap.GetTempPath();
1629*f6dc9357SAndroid Build Coastguard Worker 
1630*f6dc9357SAndroid Build Coastguard Worker       // DWORD attrib = 0;
1631*f6dc9357SAndroid Build Coastguard Worker       if (thereIsInArchive)
1632*f6dc9357SAndroid Build Coastguard Worker       {
1633*f6dc9357SAndroid Build Coastguard Worker         // attrib = NFind::GetFileAttrib(us2fs(arcPath));
1634*f6dc9357SAndroid Build Coastguard Worker         if (!DeleteFileAlways(us2fs(arcPath)))
1635*f6dc9357SAndroid Build Coastguard Worker           return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath));
1636*f6dc9357SAndroid Build Coastguard Worker       }
1637*f6dc9357SAndroid Build Coastguard Worker 
1638*f6dc9357SAndroid Build Coastguard Worker       UInt64 totalArcSize = 0;
1639*f6dc9357SAndroid Build Coastguard Worker       {
1640*f6dc9357SAndroid Build Coastguard Worker         NFind::CFileInfo fi;
1641*f6dc9357SAndroid Build Coastguard Worker         if (fi.Find(tempPath))
1642*f6dc9357SAndroid Build Coastguard Worker           totalArcSize = fi.Size;
1643*f6dc9357SAndroid Build Coastguard Worker       }
1644*f6dc9357SAndroid Build Coastguard Worker       RINOK(callback->MoveArc_Start(fs2us(tempPath), arcPath,
1645*f6dc9357SAndroid Build Coastguard Worker           totalArcSize, BoolToInt(thereIsInArchive)))
1646*f6dc9357SAndroid Build Coastguard Worker 
1647*f6dc9357SAndroid Build Coastguard Worker       C_CopyFileProgress_to_IUpdateCallbackUI2 prox(callback);
1648*f6dc9357SAndroid Build Coastguard Worker       // if we update archive, we have removed original archive.
1649*f6dc9357SAndroid Build Coastguard Worker       // So if we break archive moving, we will have only temporary archive.
1650*f6dc9357SAndroid Build Coastguard Worker       // We can disable breaking here:
1651*f6dc9357SAndroid Build Coastguard Worker       // prox.Disable_Break = thereIsInArchive;
1652*f6dc9357SAndroid Build Coastguard Worker 
1653*f6dc9357SAndroid Build Coastguard Worker       if (!MyMoveFile_with_Progress(tempPath, us2fs(arcPath), &prox))
1654*f6dc9357SAndroid Build Coastguard Worker       {
1655*f6dc9357SAndroid Build Coastguard Worker         errorInfo.SystemError = ::GetLastError();
1656*f6dc9357SAndroid Build Coastguard Worker         errorInfo.Message = "cannot move the file";
1657*f6dc9357SAndroid Build Coastguard Worker         if (errorInfo.SystemError == ERROR_INVALID_PARAMETER)
1658*f6dc9357SAndroid Build Coastguard Worker         {
1659*f6dc9357SAndroid Build Coastguard Worker           if (totalArcSize > (UInt32)(Int32)-1)
1660*f6dc9357SAndroid Build Coastguard Worker           {
1661*f6dc9357SAndroid Build Coastguard Worker             // bool isFsDetected = false;
1662*f6dc9357SAndroid Build Coastguard Worker             // if (NSystem::Is_File_LimitedBy_4GB(us2fs(arcPath), isFsDetected) || !isFsDetected)
1663*f6dc9357SAndroid Build Coastguard Worker             {
1664*f6dc9357SAndroid Build Coastguard Worker               errorInfo.Message.Add_LF();
1665*f6dc9357SAndroid Build Coastguard Worker               errorInfo.Message += "Archive file size exceeds 4 GB";
1666*f6dc9357SAndroid Build Coastguard Worker             }
1667*f6dc9357SAndroid Build Coastguard Worker           }
1668*f6dc9357SAndroid Build Coastguard Worker         }
1669*f6dc9357SAndroid Build Coastguard Worker         // if there was no input archive, and we have operation breaking.
1670*f6dc9357SAndroid Build Coastguard Worker         // then we can remove temporary archive, because we still have original uncompressed files.
1671*f6dc9357SAndroid Build Coastguard Worker         if (!thereIsInArchive
1672*f6dc9357SAndroid Build Coastguard Worker             && prox.CallbackResult == E_ABORT)
1673*f6dc9357SAndroid Build Coastguard Worker           tempFiles.NeedDeleteFiles = true;
1674*f6dc9357SAndroid Build Coastguard Worker         errorInfo.FileNames.Add(tempPath);
1675*f6dc9357SAndroid Build Coastguard Worker         errorInfo.FileNames.Add(us2fs(arcPath));
1676*f6dc9357SAndroid Build Coastguard Worker         RINOK(prox.CallbackResult)
1677*f6dc9357SAndroid Build Coastguard Worker         return errorInfo.Get_HRESULT_Error();
1678*f6dc9357SAndroid Build Coastguard Worker       }
1679*f6dc9357SAndroid Build Coastguard Worker 
1680*f6dc9357SAndroid Build Coastguard Worker       // MoveArc_Finish() can return delayed user break (E_ABORT) status,
1681*f6dc9357SAndroid Build Coastguard Worker       // if callback callee ignored interruption to finish archive creation operation.
1682*f6dc9357SAndroid Build Coastguard Worker       RINOK(callback->MoveArc_Finish())
1683*f6dc9357SAndroid Build Coastguard Worker 
1684*f6dc9357SAndroid Build Coastguard Worker       /*
1685*f6dc9357SAndroid Build Coastguard Worker       if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY))
1686*f6dc9357SAndroid Build Coastguard Worker       {
1687*f6dc9357SAndroid Build Coastguard Worker         DWORD attrib2 = NFind::GetFileAttrib(us2fs(arcPath));
1688*f6dc9357SAndroid Build Coastguard Worker         if (attrib2 != INVALID_FILE_ATTRIBUTES)
1689*f6dc9357SAndroid Build Coastguard Worker           NDir::SetFileAttrib(us2fs(arcPath), attrib2 | FILE_ATTRIBUTE_READONLY);
1690*f6dc9357SAndroid Build Coastguard Worker       }
1691*f6dc9357SAndroid Build Coastguard Worker       */
1692*f6dc9357SAndroid Build Coastguard Worker     }
1693*f6dc9357SAndroid Build Coastguard Worker     catch(...)
1694*f6dc9357SAndroid Build Coastguard Worker     {
1695*f6dc9357SAndroid Build Coastguard Worker       throw;
1696*f6dc9357SAndroid Build Coastguard Worker     }
1697*f6dc9357SAndroid Build Coastguard Worker   }
1698*f6dc9357SAndroid Build Coastguard Worker 
1699*f6dc9357SAndroid Build Coastguard Worker 
1700*f6dc9357SAndroid Build Coastguard Worker   #if defined(_WIN32) && !defined(UNDER_CE)
1701*f6dc9357SAndroid Build Coastguard Worker 
1702*f6dc9357SAndroid Build Coastguard Worker Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
1703*f6dc9357SAndroid Build Coastguard Worker 
1704*f6dc9357SAndroid Build Coastguard Worker   if (options.EMailMode)
1705*f6dc9357SAndroid Build Coastguard Worker   {
1706*f6dc9357SAndroid Build Coastguard Worker     NDLL::CLibrary mapiLib;
1707*f6dc9357SAndroid Build Coastguard Worker     if (!mapiLib.Load(FTEXT("Mapi32.dll")))
1708*f6dc9357SAndroid Build Coastguard Worker     {
1709*f6dc9357SAndroid Build Coastguard Worker       errorInfo.SetFromLastError("cannot load Mapi32.dll");
1710*f6dc9357SAndroid Build Coastguard Worker       return errorInfo.Get_HRESULT_Error();
1711*f6dc9357SAndroid Build Coastguard Worker     }
1712*f6dc9357SAndroid Build Coastguard Worker 
1713*f6dc9357SAndroid Build Coastguard Worker     FStringVector fullPaths;
1714*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
1715*f6dc9357SAndroid Build Coastguard Worker 
1716*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < options.Commands.Size(); i++)
1717*f6dc9357SAndroid Build Coastguard Worker     {
1718*f6dc9357SAndroid Build Coastguard Worker       CArchivePath &ap = options.Commands[i].ArchivePath;
1719*f6dc9357SAndroid Build Coastguard Worker       const FString finalPath = us2fs(ap.GetFinalPath());
1720*f6dc9357SAndroid Build Coastguard Worker       FString arcPath2;
1721*f6dc9357SAndroid Build Coastguard Worker       if (!MyGetFullPathName(finalPath, arcPath2))
1722*f6dc9357SAndroid Build Coastguard Worker         return errorInfo.SetFromLastError("GetFullPathName error", finalPath);
1723*f6dc9357SAndroid Build Coastguard Worker       fullPaths.Add(arcPath2);
1724*f6dc9357SAndroid Build Coastguard Worker     }
1725*f6dc9357SAndroid Build Coastguard Worker 
1726*f6dc9357SAndroid Build Coastguard Worker     /*
1727*f6dc9357SAndroid Build Coastguard Worker     LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments");
1728*f6dc9357SAndroid Build Coastguard Worker     if (fnSend == 0)
1729*f6dc9357SAndroid Build Coastguard Worker     {
1730*f6dc9357SAndroid Build Coastguard Worker       errorInfo.SetFromLastError)("7-Zip cannot find MAPISendDocuments function");
1731*f6dc9357SAndroid Build Coastguard Worker       return errorInfo.Get_HRESULT_Error();
1732*f6dc9357SAndroid Build Coastguard Worker     }
1733*f6dc9357SAndroid Build Coastguard Worker     */
1734*f6dc9357SAndroid Build Coastguard Worker     const
1735*f6dc9357SAndroid Build Coastguard Worker     Z7_WIN_LPMAPISENDMAILW sendMailW = Z7_GET_PROC_ADDRESS(
1736*f6dc9357SAndroid Build Coastguard Worker     Z7_WIN_LPMAPISENDMAILW, mapiLib.Get_HMODULE(),
1737*f6dc9357SAndroid Build Coastguard Worker             "MAPISendMailW");
1738*f6dc9357SAndroid Build Coastguard Worker    if (sendMailW)
1739*f6dc9357SAndroid Build Coastguard Worker    {
1740*f6dc9357SAndroid Build Coastguard Worker 
1741*f6dc9357SAndroid Build Coastguard Worker     CCurrentDirRestorer curDirRestorer;
1742*f6dc9357SAndroid Build Coastguard Worker 
1743*f6dc9357SAndroid Build Coastguard Worker     UStringVector paths;
1744*f6dc9357SAndroid Build Coastguard Worker     UStringVector names;
1745*f6dc9357SAndroid Build Coastguard Worker 
1746*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < fullPaths.Size(); i++)
1747*f6dc9357SAndroid Build Coastguard Worker     {
1748*f6dc9357SAndroid Build Coastguard Worker       const UString arcPath2 = fs2us(fullPaths[i]);
1749*f6dc9357SAndroid Build Coastguard Worker       const UString fileName = ExtractFileNameFromPath(arcPath2);
1750*f6dc9357SAndroid Build Coastguard Worker       paths.Add(arcPath2);
1751*f6dc9357SAndroid Build Coastguard Worker       names.Add(fileName);
1752*f6dc9357SAndroid Build Coastguard Worker       // Warning!!! MAPISendDocuments function changes Current directory
1753*f6dc9357SAndroid Build Coastguard Worker       // fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
1754*f6dc9357SAndroid Build Coastguard Worker     }
1755*f6dc9357SAndroid Build Coastguard Worker 
1756*f6dc9357SAndroid Build Coastguard Worker     CRecordVector<Z7_WIN_MapiFileDescW> files;
1757*f6dc9357SAndroid Build Coastguard Worker     files.ClearAndSetSize(paths.Size());
1758*f6dc9357SAndroid Build Coastguard Worker 
1759*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < paths.Size(); i++)
1760*f6dc9357SAndroid Build Coastguard Worker     {
1761*f6dc9357SAndroid Build Coastguard Worker       Z7_WIN_MapiFileDescW &f = files[i];
1762*f6dc9357SAndroid Build Coastguard Worker       memset(&f, 0, sizeof(f));
1763*f6dc9357SAndroid Build Coastguard Worker       f.nPosition = 0xFFFFFFFF;
1764*f6dc9357SAndroid Build Coastguard Worker       f.lpszPathName = paths[i].Ptr_non_const();
1765*f6dc9357SAndroid Build Coastguard Worker       f.lpszFileName = names[i].Ptr_non_const();
1766*f6dc9357SAndroid Build Coastguard Worker     }
1767*f6dc9357SAndroid Build Coastguard Worker 
1768*f6dc9357SAndroid Build Coastguard Worker     {
1769*f6dc9357SAndroid Build Coastguard Worker       Z7_WIN_MapiMessageW m;
1770*f6dc9357SAndroid Build Coastguard Worker       memset(&m, 0, sizeof(m));
1771*f6dc9357SAndroid Build Coastguard Worker       m.nFileCount = files.Size();
1772*f6dc9357SAndroid Build Coastguard Worker       m.lpFiles = files.NonConstData();
1773*f6dc9357SAndroid Build Coastguard Worker 
1774*f6dc9357SAndroid Build Coastguard Worker       const UString addr (options.EMailAddress);
1775*f6dc9357SAndroid Build Coastguard Worker       Z7_WIN_MapiRecipDescW rec;
1776*f6dc9357SAndroid Build Coastguard Worker       if (!addr.IsEmpty())
1777*f6dc9357SAndroid Build Coastguard Worker       {
1778*f6dc9357SAndroid Build Coastguard Worker         memset(&rec, 0, sizeof(rec));
1779*f6dc9357SAndroid Build Coastguard Worker         rec.ulRecipClass = MAPI_TO;
1780*f6dc9357SAndroid Build Coastguard Worker         rec.lpszAddress = addr.Ptr_non_const();
1781*f6dc9357SAndroid Build Coastguard Worker         m.nRecipCount = 1;
1782*f6dc9357SAndroid Build Coastguard Worker         m.lpRecips = &rec;
1783*f6dc9357SAndroid Build Coastguard Worker       }
1784*f6dc9357SAndroid Build Coastguard Worker 
1785*f6dc9357SAndroid Build Coastguard Worker       sendMailW((LHANDLE)0, 0, &m, MAPI_DIALOG, 0);
1786*f6dc9357SAndroid Build Coastguard Worker     }
1787*f6dc9357SAndroid Build Coastguard Worker    }
1788*f6dc9357SAndroid Build Coastguard Worker    else
1789*f6dc9357SAndroid Build Coastguard Worker    {
1790*f6dc9357SAndroid Build Coastguard Worker     const
1791*f6dc9357SAndroid Build Coastguard Worker     LPMAPISENDMAIL sendMail = Z7_GET_PROC_ADDRESS(
1792*f6dc9357SAndroid Build Coastguard Worker     LPMAPISENDMAIL, mapiLib.Get_HMODULE(),
1793*f6dc9357SAndroid Build Coastguard Worker      "MAPISendMail");
1794*f6dc9357SAndroid Build Coastguard Worker     if (!sendMail)
1795*f6dc9357SAndroid Build Coastguard Worker     {
1796*f6dc9357SAndroid Build Coastguard Worker       errorInfo.SetFromLastError("7-Zip cannot find MAPISendMail function");
1797*f6dc9357SAndroid Build Coastguard Worker       return errorInfo.Get_HRESULT_Error();
1798*f6dc9357SAndroid Build Coastguard Worker     }
1799*f6dc9357SAndroid Build Coastguard Worker 
1800*f6dc9357SAndroid Build Coastguard Worker     CCurrentDirRestorer curDirRestorer;
1801*f6dc9357SAndroid Build Coastguard Worker 
1802*f6dc9357SAndroid Build Coastguard Worker     AStringVector paths;
1803*f6dc9357SAndroid Build Coastguard Worker     AStringVector names;
1804*f6dc9357SAndroid Build Coastguard Worker 
1805*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < fullPaths.Size(); i++)
1806*f6dc9357SAndroid Build Coastguard Worker     {
1807*f6dc9357SAndroid Build Coastguard Worker       const UString arcPath2 = fs2us(fullPaths[i]);
1808*f6dc9357SAndroid Build Coastguard Worker       const UString fileName = ExtractFileNameFromPath(arcPath2);
1809*f6dc9357SAndroid Build Coastguard Worker       paths.Add(GetAnsiString(arcPath2));
1810*f6dc9357SAndroid Build Coastguard Worker       names.Add(GetAnsiString(fileName));
1811*f6dc9357SAndroid Build Coastguard Worker       // const AString path (GetAnsiString(arcPath2));
1812*f6dc9357SAndroid Build Coastguard Worker       // const AString name (GetAnsiString(fileName));
1813*f6dc9357SAndroid Build Coastguard Worker       // Warning!!! MAPISendDocuments function changes Current directory
1814*f6dc9357SAndroid Build Coastguard Worker       // fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
1815*f6dc9357SAndroid Build Coastguard Worker     }
1816*f6dc9357SAndroid Build Coastguard Worker 
1817*f6dc9357SAndroid Build Coastguard Worker     CRecordVector<MapiFileDesc> files;
1818*f6dc9357SAndroid Build Coastguard Worker     files.ClearAndSetSize(paths.Size());
1819*f6dc9357SAndroid Build Coastguard Worker 
1820*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < paths.Size(); i++)
1821*f6dc9357SAndroid Build Coastguard Worker     {
1822*f6dc9357SAndroid Build Coastguard Worker       MapiFileDesc &f = files[i];
1823*f6dc9357SAndroid Build Coastguard Worker       memset(&f, 0, sizeof(f));
1824*f6dc9357SAndroid Build Coastguard Worker       f.nPosition = 0xFFFFFFFF;
1825*f6dc9357SAndroid Build Coastguard Worker       f.lpszPathName = paths[i].Ptr_non_const();
1826*f6dc9357SAndroid Build Coastguard Worker       f.lpszFileName = names[i].Ptr_non_const();
1827*f6dc9357SAndroid Build Coastguard Worker     }
1828*f6dc9357SAndroid Build Coastguard Worker 
1829*f6dc9357SAndroid Build Coastguard Worker     {
1830*f6dc9357SAndroid Build Coastguard Worker       MapiMessage m;
1831*f6dc9357SAndroid Build Coastguard Worker       memset(&m, 0, sizeof(m));
1832*f6dc9357SAndroid Build Coastguard Worker       m.nFileCount = files.Size();
1833*f6dc9357SAndroid Build Coastguard Worker       m.lpFiles = files.NonConstData();
1834*f6dc9357SAndroid Build Coastguard Worker 
1835*f6dc9357SAndroid Build Coastguard Worker       const AString addr (GetAnsiString(options.EMailAddress));
1836*f6dc9357SAndroid Build Coastguard Worker       MapiRecipDesc rec;
1837*f6dc9357SAndroid Build Coastguard Worker       if (!addr.IsEmpty())
1838*f6dc9357SAndroid Build Coastguard Worker       {
1839*f6dc9357SAndroid Build Coastguard Worker         memset(&rec, 0, sizeof(rec));
1840*f6dc9357SAndroid Build Coastguard Worker         rec.ulRecipClass = MAPI_TO;
1841*f6dc9357SAndroid Build Coastguard Worker         rec.lpszAddress = addr.Ptr_non_const();
1842*f6dc9357SAndroid Build Coastguard Worker         m.nRecipCount = 1;
1843*f6dc9357SAndroid Build Coastguard Worker         m.lpRecips = &rec;
1844*f6dc9357SAndroid Build Coastguard Worker       }
1845*f6dc9357SAndroid Build Coastguard Worker 
1846*f6dc9357SAndroid Build Coastguard Worker       sendMail((LHANDLE)0, 0, &m, MAPI_DIALOG, 0);
1847*f6dc9357SAndroid Build Coastguard Worker     }
1848*f6dc9357SAndroid Build Coastguard Worker    }
1849*f6dc9357SAndroid Build Coastguard Worker   }
1850*f6dc9357SAndroid Build Coastguard Worker 
1851*f6dc9357SAndroid Build Coastguard Worker   #endif
1852*f6dc9357SAndroid Build Coastguard Worker 
1853*f6dc9357SAndroid Build Coastguard Worker   if (options.DeleteAfterCompressing)
1854*f6dc9357SAndroid Build Coastguard Worker   {
1855*f6dc9357SAndroid Build Coastguard Worker     CRecordVector<CDirPathSortPair> pairs;
1856*f6dc9357SAndroid Build Coastguard Worker     FStringVector foldersNames;
1857*f6dc9357SAndroid Build Coastguard Worker 
1858*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
1859*f6dc9357SAndroid Build Coastguard Worker 
1860*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < dirItems.Items.Size(); i++)
1861*f6dc9357SAndroid Build Coastguard Worker     {
1862*f6dc9357SAndroid Build Coastguard Worker       const CDirItem &dirItem = dirItems.Items[i];
1863*f6dc9357SAndroid Build Coastguard Worker       const FString phyPath = dirItems.GetPhyPath(i);
1864*f6dc9357SAndroid Build Coastguard Worker       if (dirItem.IsDir())
1865*f6dc9357SAndroid Build Coastguard Worker       {
1866*f6dc9357SAndroid Build Coastguard Worker         CDirPathSortPair pair;
1867*f6dc9357SAndroid Build Coastguard Worker         pair.Index = i;
1868*f6dc9357SAndroid Build Coastguard Worker         pair.SetNumSlashes(phyPath);
1869*f6dc9357SAndroid Build Coastguard Worker         pairs.Add(pair);
1870*f6dc9357SAndroid Build Coastguard Worker       }
1871*f6dc9357SAndroid Build Coastguard Worker       else
1872*f6dc9357SAndroid Build Coastguard Worker       {
1873*f6dc9357SAndroid Build Coastguard Worker         // 21.04: we have set processedItems[*] before for all required items
1874*f6dc9357SAndroid Build Coastguard Worker         if (processedItems[i] != 0
1875*f6dc9357SAndroid Build Coastguard Worker             // || dirItem.Size == 0
1876*f6dc9357SAndroid Build Coastguard Worker             // || dirItem.AreReparseData()
1877*f6dc9357SAndroid Build Coastguard Worker             )
1878*f6dc9357SAndroid Build Coastguard Worker         {
1879*f6dc9357SAndroid Build Coastguard Worker           NFind::CFileInfo fileInfo;
1880*f6dc9357SAndroid Build Coastguard Worker           /* if (!SymLinks), we follow link here, similar to (dirItem) filling */
1881*f6dc9357SAndroid Build Coastguard Worker           if (fileInfo.Find(phyPath, !options.SymLinks.Val))
1882*f6dc9357SAndroid Build Coastguard Worker           {
1883*f6dc9357SAndroid Build Coastguard Worker             bool is_SameSize = false;
1884*f6dc9357SAndroid Build Coastguard Worker             if (options.SymLinks.Val && dirItem.AreReparseData())
1885*f6dc9357SAndroid Build Coastguard Worker             {
1886*f6dc9357SAndroid Build Coastguard Worker               /* (dirItem.Size = dirItem.ReparseData.Size()) was set before.
1887*f6dc9357SAndroid Build Coastguard Worker                  So we don't compare sizes for that case here */
1888*f6dc9357SAndroid Build Coastguard Worker               is_SameSize = fileInfo.IsOsSymLink();
1889*f6dc9357SAndroid Build Coastguard Worker             }
1890*f6dc9357SAndroid Build Coastguard Worker             else
1891*f6dc9357SAndroid Build Coastguard Worker               is_SameSize = (fileInfo.Size == dirItem.Size);
1892*f6dc9357SAndroid Build Coastguard Worker 
1893*f6dc9357SAndroid Build Coastguard Worker             if (is_SameSize
1894*f6dc9357SAndroid Build Coastguard Worker                 && Compare_FiTime(&fileInfo.MTime, &dirItem.MTime) == 0
1895*f6dc9357SAndroid Build Coastguard Worker                 && Compare_FiTime(&fileInfo.CTime, &dirItem.CTime) == 0)
1896*f6dc9357SAndroid Build Coastguard Worker             {
1897*f6dc9357SAndroid Build Coastguard Worker               RINOK(callback->DeletingAfterArchiving(phyPath, false))
1898*f6dc9357SAndroid Build Coastguard Worker               DeleteFileAlways(phyPath);
1899*f6dc9357SAndroid Build Coastguard Worker             }
1900*f6dc9357SAndroid Build Coastguard Worker           }
1901*f6dc9357SAndroid Build Coastguard Worker         }
1902*f6dc9357SAndroid Build Coastguard Worker         else
1903*f6dc9357SAndroid Build Coastguard Worker         {
1904*f6dc9357SAndroid Build Coastguard Worker           // file was skipped by some reason. We can throw error for debug:
1905*f6dc9357SAndroid Build Coastguard Worker           /*
1906*f6dc9357SAndroid Build Coastguard Worker           errorInfo.SystemError = 0;
1907*f6dc9357SAndroid Build Coastguard Worker           errorInfo.Message = "file was not processed";
1908*f6dc9357SAndroid Build Coastguard Worker           errorInfo.FileNames.Add(phyPath);
1909*f6dc9357SAndroid Build Coastguard Worker           return E_FAIL;
1910*f6dc9357SAndroid Build Coastguard Worker           */
1911*f6dc9357SAndroid Build Coastguard Worker         }
1912*f6dc9357SAndroid Build Coastguard Worker       }
1913*f6dc9357SAndroid Build Coastguard Worker     }
1914*f6dc9357SAndroid Build Coastguard Worker 
1915*f6dc9357SAndroid Build Coastguard Worker     pairs.Sort2();
1916*f6dc9357SAndroid Build Coastguard Worker 
1917*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < pairs.Size(); i++)
1918*f6dc9357SAndroid Build Coastguard Worker     {
1919*f6dc9357SAndroid Build Coastguard Worker       const FString phyPath = dirItems.GetPhyPath(pairs[i].Index);
1920*f6dc9357SAndroid Build Coastguard Worker       if (NFind::DoesDirExist(phyPath))
1921*f6dc9357SAndroid Build Coastguard Worker       {
1922*f6dc9357SAndroid Build Coastguard Worker         RINOK(callback->DeletingAfterArchiving(phyPath, true))
1923*f6dc9357SAndroid Build Coastguard Worker         RemoveDir(phyPath);
1924*f6dc9357SAndroid Build Coastguard Worker       }
1925*f6dc9357SAndroid Build Coastguard Worker     }
1926*f6dc9357SAndroid Build Coastguard Worker 
1927*f6dc9357SAndroid Build Coastguard Worker     RINOK(callback->FinishDeletingAfterArchiving())
1928*f6dc9357SAndroid Build Coastguard Worker   }
1929*f6dc9357SAndroid Build Coastguard Worker 
1930*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1931*f6dc9357SAndroid Build Coastguard Worker }
1932