xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // ArchiveExtractCallback.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #undef sprintf
6*f6dc9357SAndroid Build Coastguard Worker #undef printf
7*f6dc9357SAndroid Build Coastguard Worker 
8*f6dc9357SAndroid Build Coastguard Worker // #include <stdio.h>
9*f6dc9357SAndroid Build Coastguard Worker // #include "../../../../C/CpuTicks.h"
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/Alloc.h"
12*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/CpuArch.h"
13*f6dc9357SAndroid Build Coastguard Worker 
14*f6dc9357SAndroid Build Coastguard Worker 
15*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/ComTry.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/IntToString.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringConvert.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/UTFConvert.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/Wildcard.h"
20*f6dc9357SAndroid Build Coastguard Worker 
21*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/ErrorMsg.h"
22*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileDir.h"
23*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileFind.h"
24*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileName.h"
25*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariant.h"
26*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariantConv.h"
27*f6dc9357SAndroid Build Coastguard Worker 
28*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(UNDER_CE)  && !defined(Z7_SFX)
29*f6dc9357SAndroid Build Coastguard Worker #define Z7_USE_SECURITY_CODE
30*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/SecurityUtils.h"
31*f6dc9357SAndroid Build Coastguard Worker #endif
32*f6dc9357SAndroid Build Coastguard Worker 
33*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/FilePathAutoRename.h"
34*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamUtils.h"
35*f6dc9357SAndroid Build Coastguard Worker 
36*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ExtractingFilePath.h"
37*f6dc9357SAndroid Build Coastguard Worker #include "../Common/PropIDUtils.h"
38*f6dc9357SAndroid Build Coastguard Worker 
39*f6dc9357SAndroid Build Coastguard Worker #include "ArchiveExtractCallback.h"
40*f6dc9357SAndroid Build Coastguard Worker 
41*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
42*f6dc9357SAndroid Build Coastguard Worker using namespace NFile;
43*f6dc9357SAndroid Build Coastguard Worker using namespace NDir;
44*f6dc9357SAndroid Build Coastguard Worker 
45*f6dc9357SAndroid Build Coastguard Worker static const char * const kCantAutoRename = "Cannot create file with auto name";
46*f6dc9357SAndroid Build Coastguard Worker static const char * const kCantRenameFile = "Cannot rename existing file";
47*f6dc9357SAndroid Build Coastguard Worker static const char * const kCantDeleteOutputFile = "Cannot delete output file";
48*f6dc9357SAndroid Build Coastguard Worker static const char * const kCantDeleteOutputDir = "Cannot delete output folder";
49*f6dc9357SAndroid Build Coastguard Worker static const char * const kCantOpenOutFile = "Cannot open output file";
50*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_SFX
51*f6dc9357SAndroid Build Coastguard Worker static const char * const kCantOpenInFile = "Cannot open input file";
52*f6dc9357SAndroid Build Coastguard Worker #endif
53*f6dc9357SAndroid Build Coastguard Worker static const char * const kCantSetFileLen = "Cannot set length for output file";
54*f6dc9357SAndroid Build Coastguard Worker #ifdef SUPPORT_LINKS
55*f6dc9357SAndroid Build Coastguard Worker static const char * const kCantCreateHardLink = "Cannot create hard link";
56*f6dc9357SAndroid Build Coastguard Worker static const char * const kCantCreateSymLink = "Cannot create symbolic link";
57*f6dc9357SAndroid Build Coastguard Worker #endif
58*f6dc9357SAndroid Build Coastguard Worker 
59*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_SFX
60*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(COutStreamWithHash::Write (const void * data,UInt32 size,UInt32 * processedSize))61*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize))
62*f6dc9357SAndroid Build Coastguard Worker {
63*f6dc9357SAndroid Build Coastguard Worker   HRESULT result = S_OK;
64*f6dc9357SAndroid Build Coastguard Worker   if (_stream)
65*f6dc9357SAndroid Build Coastguard Worker     result = _stream->Write(data, size, &size);
66*f6dc9357SAndroid Build Coastguard Worker   if (_calculate)
67*f6dc9357SAndroid Build Coastguard Worker     _hash->Update(data, size);
68*f6dc9357SAndroid Build Coastguard Worker   _size += size;
69*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
70*f6dc9357SAndroid Build Coastguard Worker     *processedSize = size;
71*f6dc9357SAndroid Build Coastguard Worker   return result;
72*f6dc9357SAndroid Build Coastguard Worker }
73*f6dc9357SAndroid Build Coastguard Worker 
74*f6dc9357SAndroid Build Coastguard Worker #endif // Z7_SFX
75*f6dc9357SAndroid Build Coastguard Worker 
76*f6dc9357SAndroid Build Coastguard Worker 
77*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_SECURITY_CODE
78*f6dc9357SAndroid Build Coastguard Worker bool InitLocalPrivileges();
InitLocalPrivileges()79*f6dc9357SAndroid Build Coastguard Worker bool InitLocalPrivileges()
80*f6dc9357SAndroid Build Coastguard Worker {
81*f6dc9357SAndroid Build Coastguard Worker   NSecurity::CAccessToken token;
82*f6dc9357SAndroid Build Coastguard Worker   if (!token.OpenProcessToken(GetCurrentProcess(),
83*f6dc9357SAndroid Build Coastguard Worker       TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES))
84*f6dc9357SAndroid Build Coastguard Worker     return false;
85*f6dc9357SAndroid Build Coastguard Worker 
86*f6dc9357SAndroid Build Coastguard Worker   TOKEN_PRIVILEGES tp;
87*f6dc9357SAndroid Build Coastguard Worker 
88*f6dc9357SAndroid Build Coastguard Worker   tp.PrivilegeCount = 1;
89*f6dc9357SAndroid Build Coastguard Worker   tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
90*f6dc9357SAndroid Build Coastguard Worker 
91*f6dc9357SAndroid Build Coastguard Worker   if  (!::LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid))
92*f6dc9357SAndroid Build Coastguard Worker     return false;
93*f6dc9357SAndroid Build Coastguard Worker   if (!token.AdjustPrivileges(&tp))
94*f6dc9357SAndroid Build Coastguard Worker     return false;
95*f6dc9357SAndroid Build Coastguard Worker   return (GetLastError() == ERROR_SUCCESS);
96*f6dc9357SAndroid Build Coastguard Worker }
97*f6dc9357SAndroid Build Coastguard Worker #endif // Z7_USE_SECURITY_CODE
98*f6dc9357SAndroid Build Coastguard Worker 
99*f6dc9357SAndroid Build Coastguard Worker 
100*f6dc9357SAndroid Build Coastguard Worker 
101*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
102*f6dc9357SAndroid Build Coastguard Worker 
103*f6dc9357SAndroid Build Coastguard Worker static const char * const kOfficeExtensions =
104*f6dc9357SAndroid Build Coastguard Worker   " doc dot wbk"
105*f6dc9357SAndroid Build Coastguard Worker   " docx docm dotx dotm docb wll wwl"
106*f6dc9357SAndroid Build Coastguard Worker   " xls xlt xlm"
107*f6dc9357SAndroid Build Coastguard Worker   " xlsx xlsm xltx xltm xlsb xla xlam"
108*f6dc9357SAndroid Build Coastguard Worker   " ppt pot pps ppa ppam"
109*f6dc9357SAndroid Build Coastguard Worker   " pptx pptm potx potm ppam ppsx ppsm sldx sldm"
110*f6dc9357SAndroid Build Coastguard Worker   " ";
111*f6dc9357SAndroid Build Coastguard Worker 
FindExt2(const char * p,const UString & name)112*f6dc9357SAndroid Build Coastguard Worker static bool FindExt2(const char *p, const UString &name)
113*f6dc9357SAndroid Build Coastguard Worker {
114*f6dc9357SAndroid Build Coastguard Worker   const int pathPos = name.ReverseFind_PathSepar();
115*f6dc9357SAndroid Build Coastguard Worker   const int dotPos = name.ReverseFind_Dot();
116*f6dc9357SAndroid Build Coastguard Worker   if (dotPos < 0
117*f6dc9357SAndroid Build Coastguard Worker       || dotPos < pathPos
118*f6dc9357SAndroid Build Coastguard Worker       || dotPos == (int)name.Len() - 1)
119*f6dc9357SAndroid Build Coastguard Worker     return false;
120*f6dc9357SAndroid Build Coastguard Worker 
121*f6dc9357SAndroid Build Coastguard Worker   AString s;
122*f6dc9357SAndroid Build Coastguard Worker   for (unsigned pos = (unsigned)(dotPos + 1);; pos++)
123*f6dc9357SAndroid Build Coastguard Worker   {
124*f6dc9357SAndroid Build Coastguard Worker     const wchar_t c = name[pos];
125*f6dc9357SAndroid Build Coastguard Worker     if (c <= 0)
126*f6dc9357SAndroid Build Coastguard Worker       break;
127*f6dc9357SAndroid Build Coastguard Worker     if (c >= 0x80)
128*f6dc9357SAndroid Build Coastguard Worker       return false;
129*f6dc9357SAndroid Build Coastguard Worker     s.Add_Char((char)MyCharLower_Ascii((char)c));
130*f6dc9357SAndroid Build Coastguard Worker   }
131*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; p[i] != 0;)
132*f6dc9357SAndroid Build Coastguard Worker   {
133*f6dc9357SAndroid Build Coastguard Worker     unsigned j;
134*f6dc9357SAndroid Build Coastguard Worker     for (j = i; p[j] != ' '; j++);
135*f6dc9357SAndroid Build Coastguard Worker     if (s.Len() == j - i && memcmp(p + i, (const char *)s, s.Len()) == 0)
136*f6dc9357SAndroid Build Coastguard Worker       return true;
137*f6dc9357SAndroid Build Coastguard Worker     i = j + 1;
138*f6dc9357SAndroid Build Coastguard Worker   }
139*f6dc9357SAndroid Build Coastguard Worker   return false;
140*f6dc9357SAndroid Build Coastguard Worker }
141*f6dc9357SAndroid Build Coastguard Worker 
142*f6dc9357SAndroid Build Coastguard Worker 
143*f6dc9357SAndroid Build Coastguard Worker static const char * const k_ZoneId_StreamName_With_Colon_Prefix = ":Zone.Identifier";
144*f6dc9357SAndroid Build Coastguard Worker 
Is_ZoneId_StreamName(const wchar_t * s)145*f6dc9357SAndroid Build Coastguard Worker bool Is_ZoneId_StreamName(const wchar_t *s)
146*f6dc9357SAndroid Build Coastguard Worker {
147*f6dc9357SAndroid Build Coastguard Worker   return StringsAreEqualNoCase_Ascii(s, k_ZoneId_StreamName_With_Colon_Prefix + 1);
148*f6dc9357SAndroid Build Coastguard Worker }
149*f6dc9357SAndroid Build Coastguard Worker 
ReadZoneFile_Of_BaseFile(CFSTR fileName,CByteBuffer & buf)150*f6dc9357SAndroid Build Coastguard Worker void ReadZoneFile_Of_BaseFile(CFSTR fileName, CByteBuffer &buf)
151*f6dc9357SAndroid Build Coastguard Worker {
152*f6dc9357SAndroid Build Coastguard Worker   buf.Free();
153*f6dc9357SAndroid Build Coastguard Worker   FString path (fileName);
154*f6dc9357SAndroid Build Coastguard Worker   path += k_ZoneId_StreamName_With_Colon_Prefix;
155*f6dc9357SAndroid Build Coastguard Worker   NIO::CInFile file;
156*f6dc9357SAndroid Build Coastguard Worker   if (!file.Open(path))
157*f6dc9357SAndroid Build Coastguard Worker     return;
158*f6dc9357SAndroid Build Coastguard Worker   UInt64 fileSize;
159*f6dc9357SAndroid Build Coastguard Worker   if (!file.GetLength(fileSize))
160*f6dc9357SAndroid Build Coastguard Worker     return;
161*f6dc9357SAndroid Build Coastguard Worker   if (fileSize == 0 || fileSize >= (1u << 15))
162*f6dc9357SAndroid Build Coastguard Worker     return;
163*f6dc9357SAndroid Build Coastguard Worker   buf.Alloc((size_t)fileSize);
164*f6dc9357SAndroid Build Coastguard Worker   size_t processed;
165*f6dc9357SAndroid Build Coastguard Worker   if (file.ReadFull(buf, (size_t)fileSize, processed) && processed == fileSize)
166*f6dc9357SAndroid Build Coastguard Worker     return;
167*f6dc9357SAndroid Build Coastguard Worker   buf.Free();
168*f6dc9357SAndroid Build Coastguard Worker }
169*f6dc9357SAndroid Build Coastguard Worker 
WriteZoneFile_To_BaseFile(CFSTR fileName,const CByteBuffer & buf)170*f6dc9357SAndroid Build Coastguard Worker bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf)
171*f6dc9357SAndroid Build Coastguard Worker {
172*f6dc9357SAndroid Build Coastguard Worker   FString path (fileName);
173*f6dc9357SAndroid Build Coastguard Worker   path += k_ZoneId_StreamName_With_Colon_Prefix;
174*f6dc9357SAndroid Build Coastguard Worker   NIO::COutFile file;
175*f6dc9357SAndroid Build Coastguard Worker   if (!file.Create_ALWAYS(path))
176*f6dc9357SAndroid Build Coastguard Worker     return false;
177*f6dc9357SAndroid Build Coastguard Worker   return file.WriteFull(buf, buf.Size());
178*f6dc9357SAndroid Build Coastguard Worker }
179*f6dc9357SAndroid Build Coastguard Worker 
180*f6dc9357SAndroid Build Coastguard Worker #endif
181*f6dc9357SAndroid Build Coastguard Worker 
182*f6dc9357SAndroid Build Coastguard Worker 
183*f6dc9357SAndroid Build Coastguard Worker #ifdef SUPPORT_LINKS
184*f6dc9357SAndroid Build Coastguard Worker 
Compare(const CHardLinkNode & a) const185*f6dc9357SAndroid Build Coastguard Worker int CHardLinkNode::Compare(const CHardLinkNode &a) const
186*f6dc9357SAndroid Build Coastguard Worker {
187*f6dc9357SAndroid Build Coastguard Worker   if (StreamId < a.StreamId) return -1;
188*f6dc9357SAndroid Build Coastguard Worker   if (StreamId > a.StreamId) return 1;
189*f6dc9357SAndroid Build Coastguard Worker   return MyCompare(INode, a.INode);
190*f6dc9357SAndroid Build Coastguard Worker }
191*f6dc9357SAndroid Build Coastguard Worker 
Archive_Get_HardLinkNode(IInArchive * archive,UInt32 index,CHardLinkNode & h,bool & defined)192*f6dc9357SAndroid Build Coastguard Worker static HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined)
193*f6dc9357SAndroid Build Coastguard Worker {
194*f6dc9357SAndroid Build Coastguard Worker   h.INode = 0;
195*f6dc9357SAndroid Build Coastguard Worker   h.StreamId = (UInt64)(Int64)-1;
196*f6dc9357SAndroid Build Coastguard Worker   defined = false;
197*f6dc9357SAndroid Build Coastguard Worker   {
198*f6dc9357SAndroid Build Coastguard Worker     NCOM::CPropVariant prop;
199*f6dc9357SAndroid Build Coastguard Worker     RINOK(archive->GetProperty(index, kpidINode, &prop))
200*f6dc9357SAndroid Build Coastguard Worker     if (!ConvertPropVariantToUInt64(prop, h.INode))
201*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
202*f6dc9357SAndroid Build Coastguard Worker   }
203*f6dc9357SAndroid Build Coastguard Worker   {
204*f6dc9357SAndroid Build Coastguard Worker     NCOM::CPropVariant prop;
205*f6dc9357SAndroid Build Coastguard Worker     RINOK(archive->GetProperty(index, kpidStreamId, &prop))
206*f6dc9357SAndroid Build Coastguard Worker     ConvertPropVariantToUInt64(prop, h.StreamId);
207*f6dc9357SAndroid Build Coastguard Worker   }
208*f6dc9357SAndroid Build Coastguard Worker   defined = true;
209*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
210*f6dc9357SAndroid Build Coastguard Worker }
211*f6dc9357SAndroid Build Coastguard Worker 
212*f6dc9357SAndroid Build Coastguard Worker 
PrepareHardLinks(const CRecordVector<UInt32> * realIndices)213*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *realIndices)
214*f6dc9357SAndroid Build Coastguard Worker {
215*f6dc9357SAndroid Build Coastguard Worker   _hardLinks.Clear();
216*f6dc9357SAndroid Build Coastguard Worker 
217*f6dc9357SAndroid Build Coastguard Worker   if (!_arc->Ask_INode)
218*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
219*f6dc9357SAndroid Build Coastguard Worker 
220*f6dc9357SAndroid Build Coastguard Worker   IInArchive *archive = _arc->Archive;
221*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<CHardLinkNode> &hardIDs = _hardLinks.IDs;
222*f6dc9357SAndroid Build Coastguard Worker 
223*f6dc9357SAndroid Build Coastguard Worker   {
224*f6dc9357SAndroid Build Coastguard Worker     UInt32 numItems;
225*f6dc9357SAndroid Build Coastguard Worker     if (realIndices)
226*f6dc9357SAndroid Build Coastguard Worker       numItems = realIndices->Size();
227*f6dc9357SAndroid Build Coastguard Worker     else
228*f6dc9357SAndroid Build Coastguard Worker     {
229*f6dc9357SAndroid Build Coastguard Worker       RINOK(archive->GetNumberOfItems(&numItems))
230*f6dc9357SAndroid Build Coastguard Worker     }
231*f6dc9357SAndroid Build Coastguard Worker 
232*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 i = 0; i < numItems; i++)
233*f6dc9357SAndroid Build Coastguard Worker     {
234*f6dc9357SAndroid Build Coastguard Worker       CHardLinkNode h;
235*f6dc9357SAndroid Build Coastguard Worker       bool defined;
236*f6dc9357SAndroid Build Coastguard Worker       const UInt32 realIndex = realIndices ? (*realIndices)[i] : i;
237*f6dc9357SAndroid Build Coastguard Worker 
238*f6dc9357SAndroid Build Coastguard Worker       RINOK(Archive_Get_HardLinkNode(archive, realIndex, h, defined))
239*f6dc9357SAndroid Build Coastguard Worker       if (defined)
240*f6dc9357SAndroid Build Coastguard Worker       {
241*f6dc9357SAndroid Build Coastguard Worker         bool isAltStream = false;
242*f6dc9357SAndroid Build Coastguard Worker         RINOK(Archive_IsItem_AltStream(archive, realIndex, isAltStream))
243*f6dc9357SAndroid Build Coastguard Worker         if (!isAltStream)
244*f6dc9357SAndroid Build Coastguard Worker         {
245*f6dc9357SAndroid Build Coastguard Worker           bool isDir = false;
246*f6dc9357SAndroid Build Coastguard Worker           RINOK(Archive_IsItem_Dir(archive, realIndex, isDir))
247*f6dc9357SAndroid Build Coastguard Worker           if (!isDir)
248*f6dc9357SAndroid Build Coastguard Worker             hardIDs.Add(h);
249*f6dc9357SAndroid Build Coastguard Worker         }
250*f6dc9357SAndroid Build Coastguard Worker       }
251*f6dc9357SAndroid Build Coastguard Worker     }
252*f6dc9357SAndroid Build Coastguard Worker   }
253*f6dc9357SAndroid Build Coastguard Worker 
254*f6dc9357SAndroid Build Coastguard Worker   hardIDs.Sort2();
255*f6dc9357SAndroid Build Coastguard Worker 
256*f6dc9357SAndroid Build Coastguard Worker   {
257*f6dc9357SAndroid Build Coastguard Worker     // we keep only items that have 2 or more items
258*f6dc9357SAndroid Build Coastguard Worker     unsigned k = 0;
259*f6dc9357SAndroid Build Coastguard Worker     unsigned numSame = 1;
260*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 1; i < hardIDs.Size(); i++)
261*f6dc9357SAndroid Build Coastguard Worker     {
262*f6dc9357SAndroid Build Coastguard Worker       if (hardIDs[i].Compare(hardIDs[i - 1]) != 0)
263*f6dc9357SAndroid Build Coastguard Worker         numSame = 1;
264*f6dc9357SAndroid Build Coastguard Worker       else if (++numSame == 2)
265*f6dc9357SAndroid Build Coastguard Worker       {
266*f6dc9357SAndroid Build Coastguard Worker         if (i - 1 != k)
267*f6dc9357SAndroid Build Coastguard Worker           hardIDs[k] = hardIDs[i - 1];
268*f6dc9357SAndroid Build Coastguard Worker         k++;
269*f6dc9357SAndroid Build Coastguard Worker       }
270*f6dc9357SAndroid Build Coastguard Worker     }
271*f6dc9357SAndroid Build Coastguard Worker     hardIDs.DeleteFrom(k);
272*f6dc9357SAndroid Build Coastguard Worker   }
273*f6dc9357SAndroid Build Coastguard Worker 
274*f6dc9357SAndroid Build Coastguard Worker   _hardLinks.PrepareLinks();
275*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
276*f6dc9357SAndroid Build Coastguard Worker }
277*f6dc9357SAndroid Build Coastguard Worker 
278*f6dc9357SAndroid Build Coastguard Worker #endif // SUPPORT_LINKS
279*f6dc9357SAndroid Build Coastguard Worker 
280*f6dc9357SAndroid Build Coastguard Worker 
CArchiveExtractCallback()281*f6dc9357SAndroid Build Coastguard Worker CArchiveExtractCallback::CArchiveExtractCallback():
282*f6dc9357SAndroid Build Coastguard Worker     // Write_CTime(true),
283*f6dc9357SAndroid Build Coastguard Worker     // Write_ATime(true),
284*f6dc9357SAndroid Build Coastguard Worker     // Write_MTime(true),
285*f6dc9357SAndroid Build Coastguard Worker     Is_elimPrefix_Mode(false),
286*f6dc9357SAndroid Build Coastguard Worker     _arc(NULL),
287*f6dc9357SAndroid Build Coastguard Worker     _multiArchives(false)
288*f6dc9357SAndroid Build Coastguard Worker {
289*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_USE_SECURITY_CODE
290*f6dc9357SAndroid Build Coastguard Worker   _saclEnabled = InitLocalPrivileges();
291*f6dc9357SAndroid Build Coastguard Worker   #endif
292*f6dc9357SAndroid Build Coastguard Worker }
293*f6dc9357SAndroid Build Coastguard Worker 
294*f6dc9357SAndroid Build Coastguard Worker 
InitBeforeNewArchive()295*f6dc9357SAndroid Build Coastguard Worker void CArchiveExtractCallback::InitBeforeNewArchive()
296*f6dc9357SAndroid Build Coastguard Worker {
297*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
298*f6dc9357SAndroid Build Coastguard Worker   ZoneBuf.Free();
299*f6dc9357SAndroid Build Coastguard Worker #endif
300*f6dc9357SAndroid Build Coastguard Worker }
301*f6dc9357SAndroid Build Coastguard Worker 
Init(const CExtractNtOptions & ntOptions,const NWildcard::CCensorNode * wildcardCensor,const CArc * arc,IFolderArchiveExtractCallback * extractCallback2,bool stdOutMode,bool testMode,const FString & directoryPath,const UStringVector & removePathParts,bool removePartsForAltStreams,UInt64 packSize)302*f6dc9357SAndroid Build Coastguard Worker void CArchiveExtractCallback::Init(
303*f6dc9357SAndroid Build Coastguard Worker     const CExtractNtOptions &ntOptions,
304*f6dc9357SAndroid Build Coastguard Worker     const NWildcard::CCensorNode *wildcardCensor,
305*f6dc9357SAndroid Build Coastguard Worker     const CArc *arc,
306*f6dc9357SAndroid Build Coastguard Worker     IFolderArchiveExtractCallback *extractCallback2,
307*f6dc9357SAndroid Build Coastguard Worker     bool stdOutMode, bool testMode,
308*f6dc9357SAndroid Build Coastguard Worker     const FString &directoryPath,
309*f6dc9357SAndroid Build Coastguard Worker     const UStringVector &removePathParts, bool removePartsForAltStreams,
310*f6dc9357SAndroid Build Coastguard Worker     UInt64 packSize)
311*f6dc9357SAndroid Build Coastguard Worker {
312*f6dc9357SAndroid Build Coastguard Worker   ClearExtractedDirsInfo();
313*f6dc9357SAndroid Build Coastguard Worker   _outFileStream.Release();
314*f6dc9357SAndroid Build Coastguard Worker   _bufPtrSeqOutStream.Release();
315*f6dc9357SAndroid Build Coastguard Worker 
316*f6dc9357SAndroid Build Coastguard Worker   #ifdef SUPPORT_LINKS
317*f6dc9357SAndroid Build Coastguard Worker   _hardLinks.Clear();
318*f6dc9357SAndroid Build Coastguard Worker   #endif
319*f6dc9357SAndroid Build Coastguard Worker 
320*f6dc9357SAndroid Build Coastguard Worker   #ifdef SUPPORT_ALT_STREAMS
321*f6dc9357SAndroid Build Coastguard Worker   _renamedFiles.Clear();
322*f6dc9357SAndroid Build Coastguard Worker   #endif
323*f6dc9357SAndroid Build Coastguard Worker 
324*f6dc9357SAndroid Build Coastguard Worker   _ntOptions = ntOptions;
325*f6dc9357SAndroid Build Coastguard Worker   _wildcardCensor = wildcardCensor;
326*f6dc9357SAndroid Build Coastguard Worker   _stdOutMode = stdOutMode;
327*f6dc9357SAndroid Build Coastguard Worker   _testMode = testMode;
328*f6dc9357SAndroid Build Coastguard Worker   _packTotal = packSize;
329*f6dc9357SAndroid Build Coastguard Worker   _progressTotal = packSize;
330*f6dc9357SAndroid Build Coastguard Worker   // _progressTotal = 0;
331*f6dc9357SAndroid Build Coastguard Worker   // _progressTotal_Defined = false;
332*f6dc9357SAndroid Build Coastguard Worker   // _progressTotal_Defined = true;
333*f6dc9357SAndroid Build Coastguard Worker   _extractCallback2 = extractCallback2;
334*f6dc9357SAndroid Build Coastguard Worker   /*
335*f6dc9357SAndroid Build Coastguard Worker   _compressProgress.Release();
336*f6dc9357SAndroid Build Coastguard Worker   _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);
337*f6dc9357SAndroid Build Coastguard Worker   _callbackMessage.Release();
338*f6dc9357SAndroid Build Coastguard Worker   _extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage2, &_callbackMessage);
339*f6dc9357SAndroid Build Coastguard Worker   */
340*f6dc9357SAndroid Build Coastguard Worker   _folderArchiveExtractCallback2.Release();
341*f6dc9357SAndroid Build Coastguard Worker   _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2);
342*f6dc9357SAndroid Build Coastguard Worker 
343*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_SFX
344*f6dc9357SAndroid Build Coastguard Worker 
345*f6dc9357SAndroid Build Coastguard Worker   ExtractToStreamCallback.Release();
346*f6dc9357SAndroid Build Coastguard Worker   _extractCallback2.QueryInterface(IID_IFolderExtractToStreamCallback, &ExtractToStreamCallback);
347*f6dc9357SAndroid Build Coastguard Worker   if (ExtractToStreamCallback)
348*f6dc9357SAndroid Build Coastguard Worker   {
349*f6dc9357SAndroid Build Coastguard Worker     Int32 useStreams = 0;
350*f6dc9357SAndroid Build Coastguard Worker     if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK)
351*f6dc9357SAndroid Build Coastguard Worker       useStreams = 0;
352*f6dc9357SAndroid Build Coastguard Worker     if (useStreams == 0)
353*f6dc9357SAndroid Build Coastguard Worker       ExtractToStreamCallback.Release();
354*f6dc9357SAndroid Build Coastguard Worker   }
355*f6dc9357SAndroid Build Coastguard Worker 
356*f6dc9357SAndroid Build Coastguard Worker   #endif
357*f6dc9357SAndroid Build Coastguard Worker 
358*f6dc9357SAndroid Build Coastguard Worker   LocalProgressSpec->Init(extractCallback2, true);
359*f6dc9357SAndroid Build Coastguard Worker   LocalProgressSpec->SendProgress = false;
360*f6dc9357SAndroid Build Coastguard Worker 
361*f6dc9357SAndroid Build Coastguard Worker   _removePathParts = removePathParts;
362*f6dc9357SAndroid Build Coastguard Worker   _removePartsForAltStreams = removePartsForAltStreams;
363*f6dc9357SAndroid Build Coastguard Worker 
364*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_SFX
365*f6dc9357SAndroid Build Coastguard Worker   _baseParentFolder = (UInt32)(Int32)-1;
366*f6dc9357SAndroid Build Coastguard Worker   _use_baseParentFolder_mode = false;
367*f6dc9357SAndroid Build Coastguard Worker   #endif
368*f6dc9357SAndroid Build Coastguard Worker 
369*f6dc9357SAndroid Build Coastguard Worker   _arc = arc;
370*f6dc9357SAndroid Build Coastguard Worker   _dirPathPrefix = directoryPath;
371*f6dc9357SAndroid Build Coastguard Worker   _dirPathPrefix_Full = directoryPath;
372*f6dc9357SAndroid Build Coastguard Worker   #if defined(_WIN32) && !defined(UNDER_CE)
373*f6dc9357SAndroid Build Coastguard Worker   if (!NName::IsAltPathPrefix(_dirPathPrefix))
374*f6dc9357SAndroid Build Coastguard Worker   #endif
375*f6dc9357SAndroid Build Coastguard Worker   {
376*f6dc9357SAndroid Build Coastguard Worker     NName::NormalizeDirPathPrefix(_dirPathPrefix);
377*f6dc9357SAndroid Build Coastguard Worker     NDir::MyGetFullPathName(directoryPath, _dirPathPrefix_Full);
378*f6dc9357SAndroid Build Coastguard Worker     NName::NormalizeDirPathPrefix(_dirPathPrefix_Full);
379*f6dc9357SAndroid Build Coastguard Worker   }
380*f6dc9357SAndroid Build Coastguard Worker }
381*f6dc9357SAndroid Build Coastguard Worker 
382*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CArchiveExtractCallback::SetTotal (UInt64 size))383*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CArchiveExtractCallback::SetTotal(UInt64 size))
384*f6dc9357SAndroid Build Coastguard Worker {
385*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
386*f6dc9357SAndroid Build Coastguard Worker   _progressTotal = size;
387*f6dc9357SAndroid Build Coastguard Worker   // _progressTotal_Defined = true;
388*f6dc9357SAndroid Build Coastguard Worker   if (!_multiArchives && _extractCallback2)
389*f6dc9357SAndroid Build Coastguard Worker     return _extractCallback2->SetTotal(size);
390*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
391*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
392*f6dc9357SAndroid Build Coastguard Worker }
393*f6dc9357SAndroid Build Coastguard Worker 
394*f6dc9357SAndroid Build Coastguard Worker 
NormalizeVals(UInt64 & v1,UInt64 & v2)395*f6dc9357SAndroid Build Coastguard Worker static void NormalizeVals(UInt64 &v1, UInt64 &v2)
396*f6dc9357SAndroid Build Coastguard Worker {
397*f6dc9357SAndroid Build Coastguard Worker   const UInt64 kMax = (UInt64)1 << 31;
398*f6dc9357SAndroid Build Coastguard Worker   while (v1 > kMax)
399*f6dc9357SAndroid Build Coastguard Worker   {
400*f6dc9357SAndroid Build Coastguard Worker     v1 >>= 1;
401*f6dc9357SAndroid Build Coastguard Worker     v2 >>= 1;
402*f6dc9357SAndroid Build Coastguard Worker   }
403*f6dc9357SAndroid Build Coastguard Worker }
404*f6dc9357SAndroid Build Coastguard Worker 
405*f6dc9357SAndroid Build Coastguard Worker 
MyMultDiv64(UInt64 unpCur,UInt64 unpTotal,UInt64 packTotal)406*f6dc9357SAndroid Build Coastguard Worker static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal)
407*f6dc9357SAndroid Build Coastguard Worker {
408*f6dc9357SAndroid Build Coastguard Worker   NormalizeVals(packTotal, unpTotal);
409*f6dc9357SAndroid Build Coastguard Worker   NormalizeVals(unpCur, unpTotal);
410*f6dc9357SAndroid Build Coastguard Worker   if (unpTotal == 0)
411*f6dc9357SAndroid Build Coastguard Worker     unpTotal = 1;
412*f6dc9357SAndroid Build Coastguard Worker   return unpCur * packTotal / unpTotal;
413*f6dc9357SAndroid Build Coastguard Worker }
414*f6dc9357SAndroid Build Coastguard Worker 
415*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CArchiveExtractCallback::SetCompleted (const UInt64 * completeValue))416*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue))
417*f6dc9357SAndroid Build Coastguard Worker {
418*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
419*f6dc9357SAndroid Build Coastguard Worker 
420*f6dc9357SAndroid Build Coastguard Worker   if (!_extractCallback2)
421*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
422*f6dc9357SAndroid Build Coastguard Worker 
423*f6dc9357SAndroid Build Coastguard Worker   UInt64 packCur;
424*f6dc9357SAndroid Build Coastguard Worker   if (_multiArchives)
425*f6dc9357SAndroid Build Coastguard Worker   {
426*f6dc9357SAndroid Build Coastguard Worker     packCur = LocalProgressSpec->InSize;
427*f6dc9357SAndroid Build Coastguard Worker     if (completeValue /* && _progressTotal_Defined */)
428*f6dc9357SAndroid Build Coastguard Worker       packCur += MyMultDiv64(*completeValue, _progressTotal, _packTotal);
429*f6dc9357SAndroid Build Coastguard Worker     completeValue = &packCur;
430*f6dc9357SAndroid Build Coastguard Worker   }
431*f6dc9357SAndroid Build Coastguard Worker   return _extractCallback2->SetCompleted(completeValue);
432*f6dc9357SAndroid Build Coastguard Worker 
433*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
434*f6dc9357SAndroid Build Coastguard Worker }
435*f6dc9357SAndroid Build Coastguard Worker 
436*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CArchiveExtractCallback::SetRatioInfo (const UInt64 * inSize,const UInt64 * outSize))437*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))
438*f6dc9357SAndroid Build Coastguard Worker {
439*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
440*f6dc9357SAndroid Build Coastguard Worker   return LocalProgressSpec.Interface()->SetRatioInfo(inSize, outSize);
441*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
442*f6dc9357SAndroid Build Coastguard Worker }
443*f6dc9357SAndroid Build Coastguard Worker 
444*f6dc9357SAndroid Build Coastguard Worker 
CreateComplexDirectory(const UStringVector & dirPathParts,FString & fullPath)445*f6dc9357SAndroid Build Coastguard Worker void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath)
446*f6dc9357SAndroid Build Coastguard Worker {
447*f6dc9357SAndroid Build Coastguard Worker   // we use (_item.IsDir) in this function
448*f6dc9357SAndroid Build Coastguard Worker 
449*f6dc9357SAndroid Build Coastguard Worker   bool isAbsPath = false;
450*f6dc9357SAndroid Build Coastguard Worker 
451*f6dc9357SAndroid Build Coastguard Worker   if (!dirPathParts.IsEmpty())
452*f6dc9357SAndroid Build Coastguard Worker   {
453*f6dc9357SAndroid Build Coastguard Worker     const UString &s = dirPathParts[0];
454*f6dc9357SAndroid Build Coastguard Worker     if (s.IsEmpty())
455*f6dc9357SAndroid Build Coastguard Worker       isAbsPath = true;
456*f6dc9357SAndroid Build Coastguard Worker     #if defined(_WIN32) && !defined(UNDER_CE)
457*f6dc9357SAndroid Build Coastguard Worker     else
458*f6dc9357SAndroid Build Coastguard Worker     {
459*f6dc9357SAndroid Build Coastguard Worker       if (NName::IsDrivePath2(s))
460*f6dc9357SAndroid Build Coastguard Worker         isAbsPath = true;
461*f6dc9357SAndroid Build Coastguard Worker     }
462*f6dc9357SAndroid Build Coastguard Worker     #endif
463*f6dc9357SAndroid Build Coastguard Worker   }
464*f6dc9357SAndroid Build Coastguard Worker 
465*f6dc9357SAndroid Build Coastguard Worker   if (_pathMode == NExtract::NPathMode::kAbsPaths && isAbsPath)
466*f6dc9357SAndroid Build Coastguard Worker     fullPath.Empty();
467*f6dc9357SAndroid Build Coastguard Worker   else
468*f6dc9357SAndroid Build Coastguard Worker     fullPath = _dirPathPrefix;
469*f6dc9357SAndroid Build Coastguard Worker 
470*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, dirPathParts)
471*f6dc9357SAndroid Build Coastguard Worker   {
472*f6dc9357SAndroid Build Coastguard Worker     if (i != 0)
473*f6dc9357SAndroid Build Coastguard Worker       fullPath.Add_PathSepar();
474*f6dc9357SAndroid Build Coastguard Worker     const UString &s = dirPathParts[i];
475*f6dc9357SAndroid Build Coastguard Worker     fullPath += us2fs(s);
476*f6dc9357SAndroid Build Coastguard Worker 
477*f6dc9357SAndroid Build Coastguard Worker     const bool isFinalDir = (i == dirPathParts.Size() - 1 && _item.IsDir);
478*f6dc9357SAndroid Build Coastguard Worker 
479*f6dc9357SAndroid Build Coastguard Worker     if (fullPath.IsEmpty())
480*f6dc9357SAndroid Build Coastguard Worker     {
481*f6dc9357SAndroid Build Coastguard Worker       if (isFinalDir)
482*f6dc9357SAndroid Build Coastguard Worker         _itemFailure = true;
483*f6dc9357SAndroid Build Coastguard Worker       continue;
484*f6dc9357SAndroid Build Coastguard Worker     }
485*f6dc9357SAndroid Build Coastguard Worker 
486*f6dc9357SAndroid Build Coastguard Worker     #if defined(_WIN32) && !defined(UNDER_CE)
487*f6dc9357SAndroid Build Coastguard Worker     if (_pathMode == NExtract::NPathMode::kAbsPaths)
488*f6dc9357SAndroid Build Coastguard Worker       if (i == 0 && s.Len() == 2 && NName::IsDrivePath2(s))
489*f6dc9357SAndroid Build Coastguard Worker       {
490*f6dc9357SAndroid Build Coastguard Worker         if (isFinalDir)
491*f6dc9357SAndroid Build Coastguard Worker         {
492*f6dc9357SAndroid Build Coastguard Worker           // we don't want to call SetAttrib() for root drive path
493*f6dc9357SAndroid Build Coastguard Worker           _itemFailure = true;
494*f6dc9357SAndroid Build Coastguard Worker         }
495*f6dc9357SAndroid Build Coastguard Worker         continue;
496*f6dc9357SAndroid Build Coastguard Worker       }
497*f6dc9357SAndroid Build Coastguard Worker     #endif
498*f6dc9357SAndroid Build Coastguard Worker 
499*f6dc9357SAndroid Build Coastguard Worker     HRESULT hres = S_OK;
500*f6dc9357SAndroid Build Coastguard Worker     if (!CreateDir(fullPath))
501*f6dc9357SAndroid Build Coastguard Worker       hres = GetLastError_noZero_HRESULT();
502*f6dc9357SAndroid Build Coastguard Worker     if (isFinalDir)
503*f6dc9357SAndroid Build Coastguard Worker     {
504*f6dc9357SAndroid Build Coastguard Worker       if (!NFile::NFind::DoesDirExist(fullPath))
505*f6dc9357SAndroid Build Coastguard Worker       {
506*f6dc9357SAndroid Build Coastguard Worker         _itemFailure = true;
507*f6dc9357SAndroid Build Coastguard Worker         SendMessageError_with_Error(hres, "Cannot create folder", fullPath);
508*f6dc9357SAndroid Build Coastguard Worker       }
509*f6dc9357SAndroid Build Coastguard Worker     }
510*f6dc9357SAndroid Build Coastguard Worker   }
511*f6dc9357SAndroid Build Coastguard Worker }
512*f6dc9357SAndroid Build Coastguard Worker 
513*f6dc9357SAndroid Build Coastguard Worker 
GetTime(UInt32 index,PROPID propID,CArcTime & ft)514*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, CArcTime &ft)
515*f6dc9357SAndroid Build Coastguard Worker {
516*f6dc9357SAndroid Build Coastguard Worker   ft.Clear();
517*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
518*f6dc9357SAndroid Build Coastguard Worker   RINOK(_arc->Archive->GetProperty(index, propID, &prop))
519*f6dc9357SAndroid Build Coastguard Worker   if (prop.vt == VT_FILETIME)
520*f6dc9357SAndroid Build Coastguard Worker     ft.Set_From_Prop(prop);
521*f6dc9357SAndroid Build Coastguard Worker   else if (prop.vt != VT_EMPTY)
522*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
523*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
524*f6dc9357SAndroid Build Coastguard Worker }
525*f6dc9357SAndroid Build Coastguard Worker 
526*f6dc9357SAndroid Build Coastguard Worker 
GetUnpackSize()527*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::GetUnpackSize()
528*f6dc9357SAndroid Build Coastguard Worker {
529*f6dc9357SAndroid Build Coastguard Worker   return _arc->GetItem_Size(_index, _curSize, _curSize_Defined);
530*f6dc9357SAndroid Build Coastguard Worker }
531*f6dc9357SAndroid Build Coastguard Worker 
AddPathToMessage(UString & s,const FString & path)532*f6dc9357SAndroid Build Coastguard Worker static void AddPathToMessage(UString &s, const FString &path)
533*f6dc9357SAndroid Build Coastguard Worker {
534*f6dc9357SAndroid Build Coastguard Worker   s += " : ";
535*f6dc9357SAndroid Build Coastguard Worker   s += fs2us(path);
536*f6dc9357SAndroid Build Coastguard Worker }
537*f6dc9357SAndroid Build Coastguard Worker 
SendMessageError(const char * message,const FString & path)538*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path)
539*f6dc9357SAndroid Build Coastguard Worker {
540*f6dc9357SAndroid Build Coastguard Worker   UString s (message);
541*f6dc9357SAndroid Build Coastguard Worker   AddPathToMessage(s, path);
542*f6dc9357SAndroid Build Coastguard Worker   return _extractCallback2->MessageError(s);
543*f6dc9357SAndroid Build Coastguard Worker }
544*f6dc9357SAndroid Build Coastguard Worker 
545*f6dc9357SAndroid Build Coastguard Worker 
SendMessageError_with_Error(HRESULT errorCode,const char * message,const FString & path)546*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path)
547*f6dc9357SAndroid Build Coastguard Worker {
548*f6dc9357SAndroid Build Coastguard Worker   UString s (message);
549*f6dc9357SAndroid Build Coastguard Worker   if (errorCode != S_OK)
550*f6dc9357SAndroid Build Coastguard Worker   {
551*f6dc9357SAndroid Build Coastguard Worker     s += " : ";
552*f6dc9357SAndroid Build Coastguard Worker     s += NError::MyFormatMessage(errorCode);
553*f6dc9357SAndroid Build Coastguard Worker   }
554*f6dc9357SAndroid Build Coastguard Worker   AddPathToMessage(s, path);
555*f6dc9357SAndroid Build Coastguard Worker   return _extractCallback2->MessageError(s);
556*f6dc9357SAndroid Build Coastguard Worker }
557*f6dc9357SAndroid Build Coastguard Worker 
SendMessageError_with_LastError(const char * message,const FString & path)558*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path)
559*f6dc9357SAndroid Build Coastguard Worker {
560*f6dc9357SAndroid Build Coastguard Worker   const HRESULT errorCode = GetLastError_noZero_HRESULT();
561*f6dc9357SAndroid Build Coastguard Worker   return SendMessageError_with_Error(errorCode, message, path);
562*f6dc9357SAndroid Build Coastguard Worker }
563*f6dc9357SAndroid Build Coastguard Worker 
SendMessageError2(HRESULT errorCode,const char * message,const FString & path1,const FString & path2)564*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2)
565*f6dc9357SAndroid Build Coastguard Worker {
566*f6dc9357SAndroid Build Coastguard Worker   UString s (message);
567*f6dc9357SAndroid Build Coastguard Worker   if (errorCode != 0)
568*f6dc9357SAndroid Build Coastguard Worker   {
569*f6dc9357SAndroid Build Coastguard Worker     s += " : ";
570*f6dc9357SAndroid Build Coastguard Worker     s += NError::MyFormatMessage(errorCode);
571*f6dc9357SAndroid Build Coastguard Worker   }
572*f6dc9357SAndroid Build Coastguard Worker   AddPathToMessage(s, path1);
573*f6dc9357SAndroid Build Coastguard Worker   AddPathToMessage(s, path2);
574*f6dc9357SAndroid Build Coastguard Worker   return _extractCallback2->MessageError(s);
575*f6dc9357SAndroid Build Coastguard Worker }
576*f6dc9357SAndroid Build Coastguard Worker 
577*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_SFX
578*f6dc9357SAndroid Build Coastguard Worker 
579*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_1(
580*f6dc9357SAndroid Build Coastguard Worker   CGetProp
581*f6dc9357SAndroid Build Coastguard Worker   , IGetProp
582*f6dc9357SAndroid Build Coastguard Worker )
583*f6dc9357SAndroid Build Coastguard Worker public:
584*f6dc9357SAndroid Build Coastguard Worker   UInt32 IndexInArc;
585*f6dc9357SAndroid Build Coastguard Worker   const CArc *Arc;
586*f6dc9357SAndroid Build Coastguard Worker   // UString BaseName; // relative path
587*f6dc9357SAndroid Build Coastguard Worker };
588*f6dc9357SAndroid Build Coastguard Worker 
589*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CGetProp::GetProp(PROPID propID, PROPVARIANT *value))
590*f6dc9357SAndroid Build Coastguard Worker {
591*f6dc9357SAndroid Build Coastguard Worker   /*
592*f6dc9357SAndroid Build Coastguard Worker   if (propID == kpidBaseName)
593*f6dc9357SAndroid Build Coastguard Worker   {
594*f6dc9357SAndroid Build Coastguard Worker     COM_TRY_BEGIN
595*f6dc9357SAndroid Build Coastguard Worker     NCOM::CPropVariant prop = BaseName;
596*f6dc9357SAndroid Build Coastguard Worker     prop.Detach(value);
597*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
598*f6dc9357SAndroid Build Coastguard Worker     COM_TRY_END
599*f6dc9357SAndroid Build Coastguard Worker   }
600*f6dc9357SAndroid Build Coastguard Worker   */
601*f6dc9357SAndroid Build Coastguard Worker   return Arc->Archive->GetProperty(IndexInArc, propID, value);
602*f6dc9357SAndroid Build Coastguard Worker }
603*f6dc9357SAndroid Build Coastguard Worker 
604*f6dc9357SAndroid Build Coastguard Worker #endif // Z7_SFX
605*f6dc9357SAndroid Build Coastguard Worker 
606*f6dc9357SAndroid Build Coastguard Worker 
607*f6dc9357SAndroid Build Coastguard Worker #ifdef SUPPORT_LINKS
608*f6dc9357SAndroid Build Coastguard Worker 
609*f6dc9357SAndroid Build Coastguard Worker static UString GetDirPrefixOf(const UString &src)
610*f6dc9357SAndroid Build Coastguard Worker {
611*f6dc9357SAndroid Build Coastguard Worker   UString s (src);
612*f6dc9357SAndroid Build Coastguard Worker   if (!s.IsEmpty())
613*f6dc9357SAndroid Build Coastguard Worker   {
614*f6dc9357SAndroid Build Coastguard Worker     if (IsPathSepar(s.Back()))
615*f6dc9357SAndroid Build Coastguard Worker       s.DeleteBack();
616*f6dc9357SAndroid Build Coastguard Worker     int pos = s.ReverseFind_PathSepar();
617*f6dc9357SAndroid Build Coastguard Worker     s.DeleteFrom((unsigned)(pos + 1));
618*f6dc9357SAndroid Build Coastguard Worker   }
619*f6dc9357SAndroid Build Coastguard Worker   return s;
620*f6dc9357SAndroid Build Coastguard Worker }
621*f6dc9357SAndroid Build Coastguard Worker 
622*f6dc9357SAndroid Build Coastguard Worker #endif // SUPPORT_LINKS
623*f6dc9357SAndroid Build Coastguard Worker 
624*f6dc9357SAndroid Build Coastguard Worker struct CLinkLevelsInfo
625*f6dc9357SAndroid Build Coastguard Worker {
626*f6dc9357SAndroid Build Coastguard Worker   bool IsAbsolute;
627*f6dc9357SAndroid Build Coastguard Worker   int LowLevel;
628*f6dc9357SAndroid Build Coastguard Worker   int FinalLevel;
629*f6dc9357SAndroid Build Coastguard Worker 
630*f6dc9357SAndroid Build Coastguard Worker   void Parse(const UString &path);
631*f6dc9357SAndroid Build Coastguard Worker };
632*f6dc9357SAndroid Build Coastguard Worker 
633*f6dc9357SAndroid Build Coastguard Worker void CLinkLevelsInfo::Parse(const UString &path)
634*f6dc9357SAndroid Build Coastguard Worker {
635*f6dc9357SAndroid Build Coastguard Worker   IsAbsolute = NName::IsAbsolutePath(path);
636*f6dc9357SAndroid Build Coastguard Worker 
637*f6dc9357SAndroid Build Coastguard Worker   LowLevel = 0;
638*f6dc9357SAndroid Build Coastguard Worker   FinalLevel = 0;
639*f6dc9357SAndroid Build Coastguard Worker 
640*f6dc9357SAndroid Build Coastguard Worker   UStringVector parts;
641*f6dc9357SAndroid Build Coastguard Worker   SplitPathToParts(path, parts);
642*f6dc9357SAndroid Build Coastguard Worker   int level = 0;
643*f6dc9357SAndroid Build Coastguard Worker 
644*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, parts)
645*f6dc9357SAndroid Build Coastguard Worker   {
646*f6dc9357SAndroid Build Coastguard Worker     const UString &s = parts[i];
647*f6dc9357SAndroid Build Coastguard Worker     if (s.IsEmpty())
648*f6dc9357SAndroid Build Coastguard Worker     {
649*f6dc9357SAndroid Build Coastguard Worker       if (i == 0)
650*f6dc9357SAndroid Build Coastguard Worker         IsAbsolute = true;
651*f6dc9357SAndroid Build Coastguard Worker       continue;
652*f6dc9357SAndroid Build Coastguard Worker     }
653*f6dc9357SAndroid Build Coastguard Worker     if (s == L".")
654*f6dc9357SAndroid Build Coastguard Worker       continue;
655*f6dc9357SAndroid Build Coastguard Worker     if (s == L"..")
656*f6dc9357SAndroid Build Coastguard Worker     {
657*f6dc9357SAndroid Build Coastguard Worker       level--;
658*f6dc9357SAndroid Build Coastguard Worker       if (LowLevel > level)
659*f6dc9357SAndroid Build Coastguard Worker         LowLevel = level;
660*f6dc9357SAndroid Build Coastguard Worker     }
661*f6dc9357SAndroid Build Coastguard Worker     else
662*f6dc9357SAndroid Build Coastguard Worker       level++;
663*f6dc9357SAndroid Build Coastguard Worker   }
664*f6dc9357SAndroid Build Coastguard Worker 
665*f6dc9357SAndroid Build Coastguard Worker   FinalLevel = level;
666*f6dc9357SAndroid Build Coastguard Worker }
667*f6dc9357SAndroid Build Coastguard Worker 
668*f6dc9357SAndroid Build Coastguard Worker 
669*f6dc9357SAndroid Build Coastguard Worker bool IsSafePath(const UString &path);
670*f6dc9357SAndroid Build Coastguard Worker bool IsSafePath(const UString &path)
671*f6dc9357SAndroid Build Coastguard Worker {
672*f6dc9357SAndroid Build Coastguard Worker   CLinkLevelsInfo levelsInfo;
673*f6dc9357SAndroid Build Coastguard Worker   levelsInfo.Parse(path);
674*f6dc9357SAndroid Build Coastguard Worker   return !levelsInfo.IsAbsolute
675*f6dc9357SAndroid Build Coastguard Worker       && levelsInfo.LowLevel >= 0
676*f6dc9357SAndroid Build Coastguard Worker       && levelsInfo.FinalLevel > 0;
677*f6dc9357SAndroid Build Coastguard Worker }
678*f6dc9357SAndroid Build Coastguard Worker 
679*f6dc9357SAndroid Build Coastguard Worker 
680*f6dc9357SAndroid Build Coastguard Worker bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include);
681*f6dc9357SAndroid Build Coastguard Worker bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include)
682*f6dc9357SAndroid Build Coastguard Worker {
683*f6dc9357SAndroid Build Coastguard Worker   bool found = false;
684*f6dc9357SAndroid Build Coastguard Worker 
685*f6dc9357SAndroid Build Coastguard Worker   // CheckPathVect() doesn't check path to Parent nodes
686*f6dc9357SAndroid Build Coastguard Worker   if (node.CheckPathVect(item.PathParts, !item.MainIsDir, include))
687*f6dc9357SAndroid Build Coastguard Worker   {
688*f6dc9357SAndroid Build Coastguard Worker     if (!include)
689*f6dc9357SAndroid Build Coastguard Worker       return true;
690*f6dc9357SAndroid Build Coastguard Worker 
691*f6dc9357SAndroid Build Coastguard Worker     #ifdef SUPPORT_ALT_STREAMS
692*f6dc9357SAndroid Build Coastguard Worker     if (!item.IsAltStream)
693*f6dc9357SAndroid Build Coastguard Worker       return true;
694*f6dc9357SAndroid Build Coastguard Worker     #endif
695*f6dc9357SAndroid Build Coastguard Worker 
696*f6dc9357SAndroid Build Coastguard Worker     found = true;
697*f6dc9357SAndroid Build Coastguard Worker   }
698*f6dc9357SAndroid Build Coastguard Worker 
699*f6dc9357SAndroid Build Coastguard Worker   #ifdef SUPPORT_ALT_STREAMS
700*f6dc9357SAndroid Build Coastguard Worker 
701*f6dc9357SAndroid Build Coastguard Worker   if (!item.IsAltStream)
702*f6dc9357SAndroid Build Coastguard Worker     return false;
703*f6dc9357SAndroid Build Coastguard Worker 
704*f6dc9357SAndroid Build Coastguard Worker   UStringVector pathParts2 = item.PathParts;
705*f6dc9357SAndroid Build Coastguard Worker   if (pathParts2.IsEmpty())
706*f6dc9357SAndroid Build Coastguard Worker     pathParts2.AddNew();
707*f6dc9357SAndroid Build Coastguard Worker   UString &back = pathParts2.Back();
708*f6dc9357SAndroid Build Coastguard Worker   back.Add_Colon();
709*f6dc9357SAndroid Build Coastguard Worker   back += item.AltStreamName;
710*f6dc9357SAndroid Build Coastguard Worker   bool include2;
711*f6dc9357SAndroid Build Coastguard Worker 
712*f6dc9357SAndroid Build Coastguard Worker   if (node.CheckPathVect(pathParts2,
713*f6dc9357SAndroid Build Coastguard Worker       true, // isFile,
714*f6dc9357SAndroid Build Coastguard Worker       include2))
715*f6dc9357SAndroid Build Coastguard Worker   {
716*f6dc9357SAndroid Build Coastguard Worker     include = include2;
717*f6dc9357SAndroid Build Coastguard Worker     return true;
718*f6dc9357SAndroid Build Coastguard Worker   }
719*f6dc9357SAndroid Build Coastguard Worker 
720*f6dc9357SAndroid Build Coastguard Worker   #endif // SUPPORT_ALT_STREAMS
721*f6dc9357SAndroid Build Coastguard Worker 
722*f6dc9357SAndroid Build Coastguard Worker   return found;
723*f6dc9357SAndroid Build Coastguard Worker }
724*f6dc9357SAndroid Build Coastguard Worker 
725*f6dc9357SAndroid Build Coastguard Worker 
726*f6dc9357SAndroid Build Coastguard Worker bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item)
727*f6dc9357SAndroid Build Coastguard Worker {
728*f6dc9357SAndroid Build Coastguard Worker   bool include;
729*f6dc9357SAndroid Build Coastguard Worker   if (CensorNode_CheckPath2(node, item, include))
730*f6dc9357SAndroid Build Coastguard Worker     return include;
731*f6dc9357SAndroid Build Coastguard Worker   return false;
732*f6dc9357SAndroid Build Coastguard Worker }
733*f6dc9357SAndroid Build Coastguard Worker 
734*f6dc9357SAndroid Build Coastguard Worker 
735*f6dc9357SAndroid Build Coastguard Worker static FString MakePath_from_2_Parts(const FString &prefix, const FString &path)
736*f6dc9357SAndroid Build Coastguard Worker {
737*f6dc9357SAndroid Build Coastguard Worker   FString s (prefix);
738*f6dc9357SAndroid Build Coastguard Worker   #if defined(_WIN32) && !defined(UNDER_CE)
739*f6dc9357SAndroid Build Coastguard Worker   if (!path.IsEmpty() && path[0] == ':' && !prefix.IsEmpty() && IsPathSepar(prefix.Back()))
740*f6dc9357SAndroid Build Coastguard Worker   {
741*f6dc9357SAndroid Build Coastguard Worker     if (!NName::IsDriveRootPath_SuperAllowed(prefix))
742*f6dc9357SAndroid Build Coastguard Worker       s.DeleteBack();
743*f6dc9357SAndroid Build Coastguard Worker   }
744*f6dc9357SAndroid Build Coastguard Worker   #endif
745*f6dc9357SAndroid Build Coastguard Worker   s += path;
746*f6dc9357SAndroid Build Coastguard Worker   return s;
747*f6dc9357SAndroid Build Coastguard Worker }
748*f6dc9357SAndroid Build Coastguard Worker 
749*f6dc9357SAndroid Build Coastguard Worker 
750*f6dc9357SAndroid Build Coastguard Worker 
751*f6dc9357SAndroid Build Coastguard Worker #ifdef SUPPORT_LINKS
752*f6dc9357SAndroid Build Coastguard Worker 
753*f6dc9357SAndroid Build Coastguard Worker /*
754*f6dc9357SAndroid Build Coastguard Worker struct CTempMidBuffer
755*f6dc9357SAndroid Build Coastguard Worker {
756*f6dc9357SAndroid Build Coastguard Worker   void *Buf;
757*f6dc9357SAndroid Build Coastguard Worker 
758*f6dc9357SAndroid Build Coastguard Worker   CTempMidBuffer(size_t size): Buf(NULL) { Buf = ::MidAlloc(size); }
759*f6dc9357SAndroid Build Coastguard Worker   ~CTempMidBuffer() { ::MidFree(Buf); }
760*f6dc9357SAndroid Build Coastguard Worker };
761*f6dc9357SAndroid Build Coastguard Worker 
762*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::MyCopyFile(ISequentialOutStream *outStream)
763*f6dc9357SAndroid Build Coastguard Worker {
764*f6dc9357SAndroid Build Coastguard Worker   const size_t kBufSize = 1 << 16;
765*f6dc9357SAndroid Build Coastguard Worker   CTempMidBuffer buf(kBufSize);
766*f6dc9357SAndroid Build Coastguard Worker   if (!buf.Buf)
767*f6dc9357SAndroid Build Coastguard Worker     return E_OUTOFMEMORY;
768*f6dc9357SAndroid Build Coastguard Worker 
769*f6dc9357SAndroid Build Coastguard Worker   NIO::CInFile inFile;
770*f6dc9357SAndroid Build Coastguard Worker   NIO::COutFile outFile;
771*f6dc9357SAndroid Build Coastguard Worker 
772*f6dc9357SAndroid Build Coastguard Worker   if (!inFile.Open(_copyFile_Path))
773*f6dc9357SAndroid Build Coastguard Worker     return SendMessageError_with_LastError("Open error", _copyFile_Path);
774*f6dc9357SAndroid Build Coastguard Worker 
775*f6dc9357SAndroid Build Coastguard Worker   for (;;)
776*f6dc9357SAndroid Build Coastguard Worker   {
777*f6dc9357SAndroid Build Coastguard Worker     UInt32 num;
778*f6dc9357SAndroid Build Coastguard Worker 
779*f6dc9357SAndroid Build Coastguard Worker     if (!inFile.Read(buf.Buf, kBufSize, num))
780*f6dc9357SAndroid Build Coastguard Worker       return SendMessageError_with_LastError("Read error", _copyFile_Path);
781*f6dc9357SAndroid Build Coastguard Worker 
782*f6dc9357SAndroid Build Coastguard Worker     if (num == 0)
783*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
784*f6dc9357SAndroid Build Coastguard Worker 
785*f6dc9357SAndroid Build Coastguard Worker 
786*f6dc9357SAndroid Build Coastguard Worker     RINOK(WriteStream(outStream, buf.Buf, num));
787*f6dc9357SAndroid Build Coastguard Worker   }
788*f6dc9357SAndroid Build Coastguard Worker }
789*f6dc9357SAndroid Build Coastguard Worker */
790*f6dc9357SAndroid Build Coastguard Worker 
791*f6dc9357SAndroid Build Coastguard Worker 
792*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::ReadLink()
793*f6dc9357SAndroid Build Coastguard Worker {
794*f6dc9357SAndroid Build Coastguard Worker   IInArchive *archive = _arc->Archive;
795*f6dc9357SAndroid Build Coastguard Worker   const UInt32 index = _index;
796*f6dc9357SAndroid Build Coastguard Worker   _link.Clear();
797*f6dc9357SAndroid Build Coastguard Worker 
798*f6dc9357SAndroid Build Coastguard Worker   {
799*f6dc9357SAndroid Build Coastguard Worker     NCOM::CPropVariant prop;
800*f6dc9357SAndroid Build Coastguard Worker     RINOK(archive->GetProperty(index, kpidHardLink, &prop))
801*f6dc9357SAndroid Build Coastguard Worker     if (prop.vt == VT_BSTR)
802*f6dc9357SAndroid Build Coastguard Worker     {
803*f6dc9357SAndroid Build Coastguard Worker       _link.isHardLink = true;
804*f6dc9357SAndroid Build Coastguard Worker       // _link.isCopyLink = false;
805*f6dc9357SAndroid Build Coastguard Worker       _link.isRelative = false; // RAR5, TAR: hard links are from root folder of archive
806*f6dc9357SAndroid Build Coastguard Worker       _link.linkPath.SetFromBstr(prop.bstrVal);
807*f6dc9357SAndroid Build Coastguard Worker     }
808*f6dc9357SAndroid Build Coastguard Worker     else if (prop.vt != VT_EMPTY)
809*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
810*f6dc9357SAndroid Build Coastguard Worker   }
811*f6dc9357SAndroid Build Coastguard Worker 
812*f6dc9357SAndroid Build Coastguard Worker   /*
813*f6dc9357SAndroid Build Coastguard Worker   {
814*f6dc9357SAndroid Build Coastguard Worker     NCOM::CPropVariant prop;
815*f6dc9357SAndroid Build Coastguard Worker     RINOK(archive->GetProperty(index, kpidCopyLink, &prop));
816*f6dc9357SAndroid Build Coastguard Worker     if (prop.vt == VT_BSTR)
817*f6dc9357SAndroid Build Coastguard Worker     {
818*f6dc9357SAndroid Build Coastguard Worker       _link.isHardLink = false;
819*f6dc9357SAndroid Build Coastguard Worker       _link.isCopyLink = true;
820*f6dc9357SAndroid Build Coastguard Worker       _link.isRelative = false; // RAR5: copy links are from root folder of archive
821*f6dc9357SAndroid Build Coastguard Worker       _link.linkPath.SetFromBstr(prop.bstrVal);
822*f6dc9357SAndroid Build Coastguard Worker     }
823*f6dc9357SAndroid Build Coastguard Worker     else if (prop.vt != VT_EMPTY)
824*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
825*f6dc9357SAndroid Build Coastguard Worker   }
826*f6dc9357SAndroid Build Coastguard Worker   */
827*f6dc9357SAndroid Build Coastguard Worker 
828*f6dc9357SAndroid Build Coastguard Worker   {
829*f6dc9357SAndroid Build Coastguard Worker     NCOM::CPropVariant prop;
830*f6dc9357SAndroid Build Coastguard Worker     RINOK(archive->GetProperty(index, kpidSymLink, &prop))
831*f6dc9357SAndroid Build Coastguard Worker     if (prop.vt == VT_BSTR)
832*f6dc9357SAndroid Build Coastguard Worker     {
833*f6dc9357SAndroid Build Coastguard Worker       _link.isHardLink = false;
834*f6dc9357SAndroid Build Coastguard Worker       // _link.isCopyLink = false;
835*f6dc9357SAndroid Build Coastguard Worker       _link.isRelative = true; // RAR5, TAR: symbolic links can be relative
836*f6dc9357SAndroid Build Coastguard Worker       _link.linkPath.SetFromBstr(prop.bstrVal);
837*f6dc9357SAndroid Build Coastguard Worker     }
838*f6dc9357SAndroid Build Coastguard Worker     else if (prop.vt != VT_EMPTY)
839*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
840*f6dc9357SAndroid Build Coastguard Worker   }
841*f6dc9357SAndroid Build Coastguard Worker 
842*f6dc9357SAndroid Build Coastguard Worker   NtReparse_Data = NULL;
843*f6dc9357SAndroid Build Coastguard Worker   NtReparse_Size = 0;
844*f6dc9357SAndroid Build Coastguard Worker 
845*f6dc9357SAndroid Build Coastguard Worker   if (_link.linkPath.IsEmpty() && _arc->GetRawProps)
846*f6dc9357SAndroid Build Coastguard Worker   {
847*f6dc9357SAndroid Build Coastguard Worker     const void *data;
848*f6dc9357SAndroid Build Coastguard Worker     UInt32 dataSize;
849*f6dc9357SAndroid Build Coastguard Worker     UInt32 propType;
850*f6dc9357SAndroid Build Coastguard Worker 
851*f6dc9357SAndroid Build Coastguard Worker     _arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType);
852*f6dc9357SAndroid Build Coastguard Worker 
853*f6dc9357SAndroid Build Coastguard Worker     // if (dataSize == 1234567) // for debug: unpacking without reparse
854*f6dc9357SAndroid Build Coastguard Worker     if (dataSize != 0)
855*f6dc9357SAndroid Build Coastguard Worker     {
856*f6dc9357SAndroid Build Coastguard Worker       if (propType != NPropDataType::kRaw)
857*f6dc9357SAndroid Build Coastguard Worker         return E_FAIL;
858*f6dc9357SAndroid Build Coastguard Worker 
859*f6dc9357SAndroid Build Coastguard Worker       // 21.06: we need kpidNtReparse in linux for wim archives created in Windows
860*f6dc9357SAndroid Build Coastguard Worker       // #ifdef _WIN32
861*f6dc9357SAndroid Build Coastguard Worker 
862*f6dc9357SAndroid Build Coastguard Worker       NtReparse_Data = data;
863*f6dc9357SAndroid Build Coastguard Worker       NtReparse_Size = dataSize;
864*f6dc9357SAndroid Build Coastguard Worker 
865*f6dc9357SAndroid Build Coastguard Worker       CReparseAttr reparse;
866*f6dc9357SAndroid Build Coastguard Worker       bool isOkReparse = reparse.Parse((const Byte *)data, dataSize);
867*f6dc9357SAndroid Build Coastguard Worker       if (isOkReparse)
868*f6dc9357SAndroid Build Coastguard Worker       {
869*f6dc9357SAndroid Build Coastguard Worker         _link.isHardLink = false;
870*f6dc9357SAndroid Build Coastguard Worker         // _link.isCopyLink = false;
871*f6dc9357SAndroid Build Coastguard Worker         _link.linkPath = reparse.GetPath();
872*f6dc9357SAndroid Build Coastguard Worker         _link.isJunction = reparse.IsMountPoint();
873*f6dc9357SAndroid Build Coastguard Worker 
874*f6dc9357SAndroid Build Coastguard Worker         if (reparse.IsSymLink_WSL())
875*f6dc9357SAndroid Build Coastguard Worker         {
876*f6dc9357SAndroid Build Coastguard Worker           _link.isWSL = true;
877*f6dc9357SAndroid Build Coastguard Worker           _link.isRelative = reparse.IsRelative_WSL();
878*f6dc9357SAndroid Build Coastguard Worker         }
879*f6dc9357SAndroid Build Coastguard Worker         else
880*f6dc9357SAndroid Build Coastguard Worker           _link.isRelative = reparse.IsRelative_Win();
881*f6dc9357SAndroid Build Coastguard Worker 
882*f6dc9357SAndroid Build Coastguard Worker         // const AString s = GetAnsiString(_link.linkPath);
883*f6dc9357SAndroid Build Coastguard Worker         // printf("\n_link.linkPath: %s\n", s.Ptr());
884*f6dc9357SAndroid Build Coastguard Worker 
885*f6dc9357SAndroid Build Coastguard Worker         #ifndef _WIN32
886*f6dc9357SAndroid Build Coastguard Worker         _link.linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR);
887*f6dc9357SAndroid Build Coastguard Worker         #endif
888*f6dc9357SAndroid Build Coastguard Worker       }
889*f6dc9357SAndroid Build Coastguard Worker       // #endif
890*f6dc9357SAndroid Build Coastguard Worker     }
891*f6dc9357SAndroid Build Coastguard Worker   }
892*f6dc9357SAndroid Build Coastguard Worker 
893*f6dc9357SAndroid Build Coastguard Worker   if (_link.linkPath.IsEmpty())
894*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
895*f6dc9357SAndroid Build Coastguard Worker 
896*f6dc9357SAndroid Build Coastguard Worker   {
897*f6dc9357SAndroid Build Coastguard Worker     #ifdef _WIN32
898*f6dc9357SAndroid Build Coastguard Worker     _link.linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR);
899*f6dc9357SAndroid Build Coastguard Worker     #endif
900*f6dc9357SAndroid Build Coastguard Worker 
901*f6dc9357SAndroid Build Coastguard Worker     // rar5 uses "\??\" prefix for absolute links
902*f6dc9357SAndroid Build Coastguard Worker     if (_link.linkPath.IsPrefixedBy(WSTRING_PATH_SEPARATOR L"??" WSTRING_PATH_SEPARATOR))
903*f6dc9357SAndroid Build Coastguard Worker     {
904*f6dc9357SAndroid Build Coastguard Worker       _link.isRelative = false;
905*f6dc9357SAndroid Build Coastguard Worker       _link.linkPath.DeleteFrontal(4);
906*f6dc9357SAndroid Build Coastguard Worker     }
907*f6dc9357SAndroid Build Coastguard Worker 
908*f6dc9357SAndroid Build Coastguard Worker     for (;;)
909*f6dc9357SAndroid Build Coastguard Worker     // while (NName::IsAbsolutePath(linkPath))
910*f6dc9357SAndroid Build Coastguard Worker     {
911*f6dc9357SAndroid Build Coastguard Worker       unsigned n = NName::GetRootPrefixSize(_link.linkPath);
912*f6dc9357SAndroid Build Coastguard Worker       if (n == 0)
913*f6dc9357SAndroid Build Coastguard Worker         break;
914*f6dc9357SAndroid Build Coastguard Worker       _link.isRelative = false;
915*f6dc9357SAndroid Build Coastguard Worker       _link.linkPath.DeleteFrontal(n);
916*f6dc9357SAndroid Build Coastguard Worker     }
917*f6dc9357SAndroid Build Coastguard Worker   }
918*f6dc9357SAndroid Build Coastguard Worker 
919*f6dc9357SAndroid Build Coastguard Worker   if (_link.linkPath.IsEmpty())
920*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
921*f6dc9357SAndroid Build Coastguard Worker 
922*f6dc9357SAndroid Build Coastguard Worker   if (!_link.isRelative && _removePathParts.Size() != 0)
923*f6dc9357SAndroid Build Coastguard Worker   {
924*f6dc9357SAndroid Build Coastguard Worker     UStringVector pathParts;
925*f6dc9357SAndroid Build Coastguard Worker     SplitPathToParts(_link.linkPath, pathParts);
926*f6dc9357SAndroid Build Coastguard Worker     bool badPrefix = false;
927*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, _removePathParts)
928*f6dc9357SAndroid Build Coastguard Worker     {
929*f6dc9357SAndroid Build Coastguard Worker       if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0)
930*f6dc9357SAndroid Build Coastguard Worker       {
931*f6dc9357SAndroid Build Coastguard Worker         badPrefix = true;
932*f6dc9357SAndroid Build Coastguard Worker         break;
933*f6dc9357SAndroid Build Coastguard Worker       }
934*f6dc9357SAndroid Build Coastguard Worker     }
935*f6dc9357SAndroid Build Coastguard Worker     if (!badPrefix)
936*f6dc9357SAndroid Build Coastguard Worker       pathParts.DeleteFrontal(_removePathParts.Size());
937*f6dc9357SAndroid Build Coastguard Worker     _link.linkPath = MakePathFromParts(pathParts);
938*f6dc9357SAndroid Build Coastguard Worker   }
939*f6dc9357SAndroid Build Coastguard Worker 
940*f6dc9357SAndroid Build Coastguard Worker   /*
941*f6dc9357SAndroid Build Coastguard Worker   if (!_link.linkPath.IsEmpty())
942*f6dc9357SAndroid Build Coastguard Worker   {
943*f6dc9357SAndroid Build Coastguard Worker     printf("\n_link %s to -> %s\n", GetOemString(_item.Path).Ptr(), GetOemString(_link.linkPath).Ptr());
944*f6dc9357SAndroid Build Coastguard Worker   }
945*f6dc9357SAndroid Build Coastguard Worker   */
946*f6dc9357SAndroid Build Coastguard Worker 
947*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
948*f6dc9357SAndroid Build Coastguard Worker }
949*f6dc9357SAndroid Build Coastguard Worker 
950*f6dc9357SAndroid Build Coastguard Worker #endif // SUPPORT_LINKS
951*f6dc9357SAndroid Build Coastguard Worker 
952*f6dc9357SAndroid Build Coastguard Worker 
953*f6dc9357SAndroid Build Coastguard Worker #ifndef _WIN32
954*f6dc9357SAndroid Build Coastguard Worker 
955*f6dc9357SAndroid Build Coastguard Worker static HRESULT GetOwner(IInArchive *archive,
956*f6dc9357SAndroid Build Coastguard Worker     UInt32 index, UInt32 pidName, UInt32 pidId, COwnerInfo &res)
957*f6dc9357SAndroid Build Coastguard Worker {
958*f6dc9357SAndroid Build Coastguard Worker   {
959*f6dc9357SAndroid Build Coastguard Worker     NWindows::NCOM::CPropVariant prop;
960*f6dc9357SAndroid Build Coastguard Worker     RINOK(archive->GetProperty(index, pidId, &prop))
961*f6dc9357SAndroid Build Coastguard Worker     if (prop.vt == VT_UI4)
962*f6dc9357SAndroid Build Coastguard Worker     {
963*f6dc9357SAndroid Build Coastguard Worker       res.Id_Defined = true;
964*f6dc9357SAndroid Build Coastguard Worker       res.Id = prop.ulVal; // for debug
965*f6dc9357SAndroid Build Coastguard Worker       // res.Id++; // for debug
966*f6dc9357SAndroid Build Coastguard Worker       // if (pidId == kpidGroupId) res.Id += 7; // for debug
967*f6dc9357SAndroid Build Coastguard Worker       // res.Id = 0; // for debug
968*f6dc9357SAndroid Build Coastguard Worker     }
969*f6dc9357SAndroid Build Coastguard Worker     else if (prop.vt != VT_EMPTY)
970*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
971*f6dc9357SAndroid Build Coastguard Worker   }
972*f6dc9357SAndroid Build Coastguard Worker   {
973*f6dc9357SAndroid Build Coastguard Worker     NWindows::NCOM::CPropVariant prop;
974*f6dc9357SAndroid Build Coastguard Worker     RINOK(archive->GetProperty(index, pidName, &prop))
975*f6dc9357SAndroid Build Coastguard Worker     if (prop.vt == VT_BSTR)
976*f6dc9357SAndroid Build Coastguard Worker     {
977*f6dc9357SAndroid Build Coastguard Worker       const UString s = prop.bstrVal;
978*f6dc9357SAndroid Build Coastguard Worker       ConvertUnicodeToUTF8(s, res.Name);
979*f6dc9357SAndroid Build Coastguard Worker     }
980*f6dc9357SAndroid Build Coastguard Worker     else if (prop.vt == VT_UI4)
981*f6dc9357SAndroid Build Coastguard Worker     {
982*f6dc9357SAndroid Build Coastguard Worker       res.Id_Defined = true;
983*f6dc9357SAndroid Build Coastguard Worker       res.Id = prop.ulVal;
984*f6dc9357SAndroid Build Coastguard Worker     }
985*f6dc9357SAndroid Build Coastguard Worker     else if (prop.vt != VT_EMPTY)
986*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
987*f6dc9357SAndroid Build Coastguard Worker   }
988*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
989*f6dc9357SAndroid Build Coastguard Worker }
990*f6dc9357SAndroid Build Coastguard Worker 
991*f6dc9357SAndroid Build Coastguard Worker #endif
992*f6dc9357SAndroid Build Coastguard Worker 
993*f6dc9357SAndroid Build Coastguard Worker 
994*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::Read_fi_Props()
995*f6dc9357SAndroid Build Coastguard Worker {
996*f6dc9357SAndroid Build Coastguard Worker   IInArchive *archive = _arc->Archive;
997*f6dc9357SAndroid Build Coastguard Worker   const UInt32 index = _index;
998*f6dc9357SAndroid Build Coastguard Worker 
999*f6dc9357SAndroid Build Coastguard Worker   _fi.Attrib_Defined = false;
1000*f6dc9357SAndroid Build Coastguard Worker 
1001*f6dc9357SAndroid Build Coastguard Worker  #ifndef _WIN32
1002*f6dc9357SAndroid Build Coastguard Worker   _fi.Owner.Clear();
1003*f6dc9357SAndroid Build Coastguard Worker   _fi.Group.Clear();
1004*f6dc9357SAndroid Build Coastguard Worker  #endif
1005*f6dc9357SAndroid Build Coastguard Worker 
1006*f6dc9357SAndroid Build Coastguard Worker   {
1007*f6dc9357SAndroid Build Coastguard Worker     NCOM::CPropVariant prop;
1008*f6dc9357SAndroid Build Coastguard Worker     RINOK(archive->GetProperty(index, kpidPosixAttrib, &prop))
1009*f6dc9357SAndroid Build Coastguard Worker     if (prop.vt == VT_UI4)
1010*f6dc9357SAndroid Build Coastguard Worker     {
1011*f6dc9357SAndroid Build Coastguard Worker       _fi.SetFromPosixAttrib(prop.ulVal);
1012*f6dc9357SAndroid Build Coastguard Worker     }
1013*f6dc9357SAndroid Build Coastguard Worker     else if (prop.vt != VT_EMPTY)
1014*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
1015*f6dc9357SAndroid Build Coastguard Worker   }
1016*f6dc9357SAndroid Build Coastguard Worker 
1017*f6dc9357SAndroid Build Coastguard Worker   {
1018*f6dc9357SAndroid Build Coastguard Worker     NCOM::CPropVariant prop;
1019*f6dc9357SAndroid Build Coastguard Worker     RINOK(archive->GetProperty(index, kpidAttrib, &prop))
1020*f6dc9357SAndroid Build Coastguard Worker     if (prop.vt == VT_UI4)
1021*f6dc9357SAndroid Build Coastguard Worker     {
1022*f6dc9357SAndroid Build Coastguard Worker       _fi.Attrib = prop.ulVal;
1023*f6dc9357SAndroid Build Coastguard Worker       _fi.Attrib_Defined = true;
1024*f6dc9357SAndroid Build Coastguard Worker     }
1025*f6dc9357SAndroid Build Coastguard Worker     else if (prop.vt != VT_EMPTY)
1026*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
1027*f6dc9357SAndroid Build Coastguard Worker   }
1028*f6dc9357SAndroid Build Coastguard Worker 
1029*f6dc9357SAndroid Build Coastguard Worker   RINOK(GetTime(index, kpidCTime, _fi.CTime))
1030*f6dc9357SAndroid Build Coastguard Worker   RINOK(GetTime(index, kpidATime, _fi.ATime))
1031*f6dc9357SAndroid Build Coastguard Worker   RINOK(GetTime(index, kpidMTime, _fi.MTime))
1032*f6dc9357SAndroid Build Coastguard Worker 
1033*f6dc9357SAndroid Build Coastguard Worker  #ifndef _WIN32
1034*f6dc9357SAndroid Build Coastguard Worker   if (_ntOptions.ExtractOwner)
1035*f6dc9357SAndroid Build Coastguard Worker   {
1036*f6dc9357SAndroid Build Coastguard Worker     // SendMessageError_with_LastError("_ntOptions.ExtractOwner", _diskFilePath);
1037*f6dc9357SAndroid Build Coastguard Worker     GetOwner(archive, index, kpidUser, kpidUserId, _fi.Owner);
1038*f6dc9357SAndroid Build Coastguard Worker     GetOwner(archive, index, kpidGroup, kpidGroupId, _fi.Group);
1039*f6dc9357SAndroid Build Coastguard Worker   }
1040*f6dc9357SAndroid Build Coastguard Worker  #endif
1041*f6dc9357SAndroid Build Coastguard Worker 
1042*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1043*f6dc9357SAndroid Build Coastguard Worker }
1044*f6dc9357SAndroid Build Coastguard Worker 
1045*f6dc9357SAndroid Build Coastguard Worker 
1046*f6dc9357SAndroid Build Coastguard Worker 
1047*f6dc9357SAndroid Build Coastguard Worker void CArchiveExtractCallback::CorrectPathParts()
1048*f6dc9357SAndroid Build Coastguard Worker {
1049*f6dc9357SAndroid Build Coastguard Worker   UStringVector &pathParts = _item.PathParts;
1050*f6dc9357SAndroid Build Coastguard Worker 
1051*f6dc9357SAndroid Build Coastguard Worker   #ifdef SUPPORT_ALT_STREAMS
1052*f6dc9357SAndroid Build Coastguard Worker   if (!_item.IsAltStream
1053*f6dc9357SAndroid Build Coastguard Worker       || !pathParts.IsEmpty()
1054*f6dc9357SAndroid Build Coastguard Worker       || !(_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt))
1055*f6dc9357SAndroid Build Coastguard Worker   #endif
1056*f6dc9357SAndroid Build Coastguard Worker     Correct_FsPath(_pathMode == NExtract::NPathMode::kAbsPaths, _keepAndReplaceEmptyDirPrefixes, pathParts, _item.MainIsDir);
1057*f6dc9357SAndroid Build Coastguard Worker 
1058*f6dc9357SAndroid Build Coastguard Worker   #ifdef SUPPORT_ALT_STREAMS
1059*f6dc9357SAndroid Build Coastguard Worker 
1060*f6dc9357SAndroid Build Coastguard Worker   if (_item.IsAltStream)
1061*f6dc9357SAndroid Build Coastguard Worker   {
1062*f6dc9357SAndroid Build Coastguard Worker     UString s (_item.AltStreamName);
1063*f6dc9357SAndroid Build Coastguard Worker     Correct_AltStream_Name(s);
1064*f6dc9357SAndroid Build Coastguard Worker     bool needColon = true;
1065*f6dc9357SAndroid Build Coastguard Worker 
1066*f6dc9357SAndroid Build Coastguard Worker     if (pathParts.IsEmpty())
1067*f6dc9357SAndroid Build Coastguard Worker     {
1068*f6dc9357SAndroid Build Coastguard Worker       pathParts.AddNew();
1069*f6dc9357SAndroid Build Coastguard Worker       if (_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt)
1070*f6dc9357SAndroid Build Coastguard Worker         needColon = false;
1071*f6dc9357SAndroid Build Coastguard Worker     }
1072*f6dc9357SAndroid Build Coastguard Worker     #ifdef _WIN32
1073*f6dc9357SAndroid Build Coastguard Worker     else if (_pathMode == NExtract::NPathMode::kAbsPaths &&
1074*f6dc9357SAndroid Build Coastguard Worker         NWildcard::GetNumPrefixParts_if_DrivePath(pathParts) == pathParts.Size())
1075*f6dc9357SAndroid Build Coastguard Worker       pathParts.AddNew();
1076*f6dc9357SAndroid Build Coastguard Worker     #endif
1077*f6dc9357SAndroid Build Coastguard Worker 
1078*f6dc9357SAndroid Build Coastguard Worker     UString &name = pathParts.Back();
1079*f6dc9357SAndroid Build Coastguard Worker     if (needColon)
1080*f6dc9357SAndroid Build Coastguard Worker       name.Add_Char((char)(_ntOptions.ReplaceColonForAltStream ? '_' : ':'));
1081*f6dc9357SAndroid Build Coastguard Worker     name += s;
1082*f6dc9357SAndroid Build Coastguard Worker   }
1083*f6dc9357SAndroid Build Coastguard Worker 
1084*f6dc9357SAndroid Build Coastguard Worker   #endif // SUPPORT_ALT_STREAMS
1085*f6dc9357SAndroid Build Coastguard Worker }
1086*f6dc9357SAndroid Build Coastguard Worker 
1087*f6dc9357SAndroid Build Coastguard Worker 
1088*f6dc9357SAndroid Build Coastguard Worker void CArchiveExtractCallback::GetFiTimesCAM(CFiTimesCAM &pt)
1089*f6dc9357SAndroid Build Coastguard Worker {
1090*f6dc9357SAndroid Build Coastguard Worker   pt.CTime_Defined = false;
1091*f6dc9357SAndroid Build Coastguard Worker   pt.ATime_Defined = false;
1092*f6dc9357SAndroid Build Coastguard Worker   pt.MTime_Defined = false;
1093*f6dc9357SAndroid Build Coastguard Worker 
1094*f6dc9357SAndroid Build Coastguard Worker   // if (Write_MTime)
1095*f6dc9357SAndroid Build Coastguard Worker   {
1096*f6dc9357SAndroid Build Coastguard Worker     if (_fi.MTime.Def)
1097*f6dc9357SAndroid Build Coastguard Worker     {
1098*f6dc9357SAndroid Build Coastguard Worker       _fi.MTime.Write_To_FiTime(pt.MTime);
1099*f6dc9357SAndroid Build Coastguard Worker       pt.MTime_Defined = true;
1100*f6dc9357SAndroid Build Coastguard Worker     }
1101*f6dc9357SAndroid Build Coastguard Worker     else if (_arc->MTime.Def)
1102*f6dc9357SAndroid Build Coastguard Worker     {
1103*f6dc9357SAndroid Build Coastguard Worker       _arc->MTime.Write_To_FiTime(pt.MTime);
1104*f6dc9357SAndroid Build Coastguard Worker       pt.MTime_Defined = true;
1105*f6dc9357SAndroid Build Coastguard Worker     }
1106*f6dc9357SAndroid Build Coastguard Worker   }
1107*f6dc9357SAndroid Build Coastguard Worker 
1108*f6dc9357SAndroid Build Coastguard Worker   if (/* Write_CTime && */ _fi.CTime.Def)
1109*f6dc9357SAndroid Build Coastguard Worker   {
1110*f6dc9357SAndroid Build Coastguard Worker     _fi.CTime.Write_To_FiTime(pt.CTime);
1111*f6dc9357SAndroid Build Coastguard Worker     pt.CTime_Defined = true;
1112*f6dc9357SAndroid Build Coastguard Worker   }
1113*f6dc9357SAndroid Build Coastguard Worker 
1114*f6dc9357SAndroid Build Coastguard Worker   if (/* Write_ATime && */ _fi.ATime.Def)
1115*f6dc9357SAndroid Build Coastguard Worker   {
1116*f6dc9357SAndroid Build Coastguard Worker     _fi.ATime.Write_To_FiTime(pt.ATime);
1117*f6dc9357SAndroid Build Coastguard Worker     pt.ATime_Defined = true;
1118*f6dc9357SAndroid Build Coastguard Worker   }
1119*f6dc9357SAndroid Build Coastguard Worker }
1120*f6dc9357SAndroid Build Coastguard Worker 
1121*f6dc9357SAndroid Build Coastguard Worker 
1122*f6dc9357SAndroid Build Coastguard Worker void CArchiveExtractCallback::CreateFolders()
1123*f6dc9357SAndroid Build Coastguard Worker {
1124*f6dc9357SAndroid Build Coastguard Worker   // 21.04 : we don't change original (_item.PathParts) here
1125*f6dc9357SAndroid Build Coastguard Worker   UStringVector pathParts = _item.PathParts;
1126*f6dc9357SAndroid Build Coastguard Worker 
1127*f6dc9357SAndroid Build Coastguard Worker   // bool is_DirOp = false;
1128*f6dc9357SAndroid Build Coastguard Worker   if (!pathParts.IsEmpty())
1129*f6dc9357SAndroid Build Coastguard Worker   {
1130*f6dc9357SAndroid Build Coastguard Worker     /* v23: if we extract symlink, and we know that it links to dir:
1131*f6dc9357SAndroid Build Coastguard Worker         Linux:   we don't create dir item (symlink_from_path) here.
1132*f6dc9357SAndroid Build Coastguard Worker         Windows: SetReparseData() will create dir item, if it doesn't exist,
1133*f6dc9357SAndroid Build Coastguard Worker                  but if we create dir item here, it's not problem. */
1134*f6dc9357SAndroid Build Coastguard Worker     if (!_item.IsDir
1135*f6dc9357SAndroid Build Coastguard Worker         #ifdef SUPPORT_LINKS
1136*f6dc9357SAndroid Build Coastguard Worker         #ifndef WIN32
1137*f6dc9357SAndroid Build Coastguard Worker           || !_link.linkPath.IsEmpty()
1138*f6dc9357SAndroid Build Coastguard Worker         #endif
1139*f6dc9357SAndroid Build Coastguard Worker         #endif
1140*f6dc9357SAndroid Build Coastguard Worker        )
1141*f6dc9357SAndroid Build Coastguard Worker       pathParts.DeleteBack();
1142*f6dc9357SAndroid Build Coastguard Worker     // else is_DirOp = true;
1143*f6dc9357SAndroid Build Coastguard Worker   }
1144*f6dc9357SAndroid Build Coastguard Worker 
1145*f6dc9357SAndroid Build Coastguard Worker   if (pathParts.IsEmpty())
1146*f6dc9357SAndroid Build Coastguard Worker   {
1147*f6dc9357SAndroid Build Coastguard Worker     /* if (_some_pathParts_wereRemoved && Is_elimPrefix_Mode),
1148*f6dc9357SAndroid Build Coastguard Worker        then we can have empty pathParts() here for root folder.
1149*f6dc9357SAndroid Build Coastguard Worker        v24.00: fixed: we set timestamps for such folder still.
1150*f6dc9357SAndroid Build Coastguard Worker     */
1151*f6dc9357SAndroid Build Coastguard Worker     if (!_some_pathParts_wereRemoved ||
1152*f6dc9357SAndroid Build Coastguard Worker         !Is_elimPrefix_Mode)
1153*f6dc9357SAndroid Build Coastguard Worker       return;
1154*f6dc9357SAndroid Build Coastguard Worker     // return; // ignore empty paths case
1155*f6dc9357SAndroid Build Coastguard Worker   }
1156*f6dc9357SAndroid Build Coastguard Worker   /*
1157*f6dc9357SAndroid Build Coastguard Worker   if (is_DirOp)
1158*f6dc9357SAndroid Build Coastguard Worker   {
1159*f6dc9357SAndroid Build Coastguard Worker     RINOK(PrepareOperation(NArchive::NExtract::NAskMode::kExtract))
1160*f6dc9357SAndroid Build Coastguard Worker     _op_WasReported = true;
1161*f6dc9357SAndroid Build Coastguard Worker   }
1162*f6dc9357SAndroid Build Coastguard Worker   */
1163*f6dc9357SAndroid Build Coastguard Worker 
1164*f6dc9357SAndroid Build Coastguard Worker   FString fullPathNew;
1165*f6dc9357SAndroid Build Coastguard Worker   CreateComplexDirectory(pathParts, fullPathNew);
1166*f6dc9357SAndroid Build Coastguard Worker 
1167*f6dc9357SAndroid Build Coastguard Worker   /*
1168*f6dc9357SAndroid Build Coastguard Worker   if (is_DirOp)
1169*f6dc9357SAndroid Build Coastguard Worker   {
1170*f6dc9357SAndroid Build Coastguard Worker     RINOK(SetOperationResult(
1171*f6dc9357SAndroid Build Coastguard Worker         // _itemFailure ? NArchive::NExtract::NOperationResult::kDataError :
1172*f6dc9357SAndroid Build Coastguard Worker         NArchive::NExtract::NOperationResult::kOK
1173*f6dc9357SAndroid Build Coastguard Worker         ))
1174*f6dc9357SAndroid Build Coastguard Worker   }
1175*f6dc9357SAndroid Build Coastguard Worker   */
1176*f6dc9357SAndroid Build Coastguard Worker 
1177*f6dc9357SAndroid Build Coastguard Worker   if (!_item.IsDir)
1178*f6dc9357SAndroid Build Coastguard Worker     return;
1179*f6dc9357SAndroid Build Coastguard Worker   if (fullPathNew.IsEmpty())
1180*f6dc9357SAndroid Build Coastguard Worker     return;
1181*f6dc9357SAndroid Build Coastguard Worker 
1182*f6dc9357SAndroid Build Coastguard Worker   if (_itemFailure)
1183*f6dc9357SAndroid Build Coastguard Worker     return;
1184*f6dc9357SAndroid Build Coastguard Worker 
1185*f6dc9357SAndroid Build Coastguard Worker   CDirPathTime pt;
1186*f6dc9357SAndroid Build Coastguard Worker   GetFiTimesCAM(pt);
1187*f6dc9357SAndroid Build Coastguard Worker 
1188*f6dc9357SAndroid Build Coastguard Worker   if (pt.IsSomeTimeDefined())
1189*f6dc9357SAndroid Build Coastguard Worker   {
1190*f6dc9357SAndroid Build Coastguard Worker     pt.Path = fullPathNew;
1191*f6dc9357SAndroid Build Coastguard Worker     pt.SetDirTime();
1192*f6dc9357SAndroid Build Coastguard Worker     _extractedFolders.Add(pt);
1193*f6dc9357SAndroid Build Coastguard Worker   }
1194*f6dc9357SAndroid Build Coastguard Worker }
1195*f6dc9357SAndroid Build Coastguard Worker 
1196*f6dc9357SAndroid Build Coastguard Worker 
1197*f6dc9357SAndroid Build Coastguard Worker 
1198*f6dc9357SAndroid Build Coastguard Worker /*
1199*f6dc9357SAndroid Build Coastguard Worker   CheckExistFile(fullProcessedPath)
1200*f6dc9357SAndroid Build Coastguard Worker     it can change: fullProcessedPath, _isRenamed, _overwriteMode
1201*f6dc9357SAndroid Build Coastguard Worker   (needExit = true) means that we must exit GetStream() even for S_OK result.
1202*f6dc9357SAndroid Build Coastguard Worker */
1203*f6dc9357SAndroid Build Coastguard Worker 
1204*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool &needExit)
1205*f6dc9357SAndroid Build Coastguard Worker {
1206*f6dc9357SAndroid Build Coastguard Worker   needExit = true; // it was set already before
1207*f6dc9357SAndroid Build Coastguard Worker 
1208*f6dc9357SAndroid Build Coastguard Worker   NFind::CFileInfo fileInfo;
1209*f6dc9357SAndroid Build Coastguard Worker 
1210*f6dc9357SAndroid Build Coastguard Worker   if (fileInfo.Find(fullProcessedPath))
1211*f6dc9357SAndroid Build Coastguard Worker   {
1212*f6dc9357SAndroid Build Coastguard Worker     if (_overwriteMode == NExtract::NOverwriteMode::kSkip)
1213*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1214*f6dc9357SAndroid Build Coastguard Worker 
1215*f6dc9357SAndroid Build Coastguard Worker     if (_overwriteMode == NExtract::NOverwriteMode::kAsk)
1216*f6dc9357SAndroid Build Coastguard Worker     {
1217*f6dc9357SAndroid Build Coastguard Worker       const int slashPos = fullProcessedPath.ReverseFind_PathSepar();
1218*f6dc9357SAndroid Build Coastguard Worker       const FString realFullProcessedPath = fullProcessedPath.Left((unsigned)(slashPos + 1)) + fileInfo.Name;
1219*f6dc9357SAndroid Build Coastguard Worker 
1220*f6dc9357SAndroid Build Coastguard Worker       /* (fileInfo) can be symbolic link.
1221*f6dc9357SAndroid Build Coastguard Worker          we can show final file properties here. */
1222*f6dc9357SAndroid Build Coastguard Worker 
1223*f6dc9357SAndroid Build Coastguard Worker       FILETIME ft1;
1224*f6dc9357SAndroid Build Coastguard Worker       FiTime_To_FILETIME(fileInfo.MTime, ft1);
1225*f6dc9357SAndroid Build Coastguard Worker 
1226*f6dc9357SAndroid Build Coastguard Worker       Int32 overwriteResult;
1227*f6dc9357SAndroid Build Coastguard Worker       RINOK(_extractCallback2->AskOverwrite(
1228*f6dc9357SAndroid Build Coastguard Worker           fs2us(realFullProcessedPath), &ft1, &fileInfo.Size, _item.Path,
1229*f6dc9357SAndroid Build Coastguard Worker           _fi.MTime.Def ? &_fi.MTime.FT : NULL,
1230*f6dc9357SAndroid Build Coastguard Worker           _curSize_Defined ? &_curSize : NULL,
1231*f6dc9357SAndroid Build Coastguard Worker           &overwriteResult))
1232*f6dc9357SAndroid Build Coastguard Worker 
1233*f6dc9357SAndroid Build Coastguard Worker       switch (overwriteResult)
1234*f6dc9357SAndroid Build Coastguard Worker       {
1235*f6dc9357SAndroid Build Coastguard Worker         case NOverwriteAnswer::kCancel:
1236*f6dc9357SAndroid Build Coastguard Worker           return E_ABORT;
1237*f6dc9357SAndroid Build Coastguard Worker         case NOverwriteAnswer::kNo:
1238*f6dc9357SAndroid Build Coastguard Worker           return S_OK;
1239*f6dc9357SAndroid Build Coastguard Worker         case NOverwriteAnswer::kNoToAll:
1240*f6dc9357SAndroid Build Coastguard Worker           _overwriteMode = NExtract::NOverwriteMode::kSkip;
1241*f6dc9357SAndroid Build Coastguard Worker           return S_OK;
1242*f6dc9357SAndroid Build Coastguard Worker 
1243*f6dc9357SAndroid Build Coastguard Worker         case NOverwriteAnswer::kYes:
1244*f6dc9357SAndroid Build Coastguard Worker           break;
1245*f6dc9357SAndroid Build Coastguard Worker         case NOverwriteAnswer::kYesToAll:
1246*f6dc9357SAndroid Build Coastguard Worker           _overwriteMode = NExtract::NOverwriteMode::kOverwrite;
1247*f6dc9357SAndroid Build Coastguard Worker           break;
1248*f6dc9357SAndroid Build Coastguard Worker         case NOverwriteAnswer::kAutoRename:
1249*f6dc9357SAndroid Build Coastguard Worker           _overwriteMode = NExtract::NOverwriteMode::kRename;
1250*f6dc9357SAndroid Build Coastguard Worker           break;
1251*f6dc9357SAndroid Build Coastguard Worker         default:
1252*f6dc9357SAndroid Build Coastguard Worker           return E_FAIL;
1253*f6dc9357SAndroid Build Coastguard Worker       }
1254*f6dc9357SAndroid Build Coastguard Worker     } // NExtract::NOverwriteMode::kAsk
1255*f6dc9357SAndroid Build Coastguard Worker 
1256*f6dc9357SAndroid Build Coastguard Worker     if (_overwriteMode == NExtract::NOverwriteMode::kRename)
1257*f6dc9357SAndroid Build Coastguard Worker     {
1258*f6dc9357SAndroid Build Coastguard Worker       if (!AutoRenamePath(fullProcessedPath))
1259*f6dc9357SAndroid Build Coastguard Worker       {
1260*f6dc9357SAndroid Build Coastguard Worker         RINOK(SendMessageError(kCantAutoRename, fullProcessedPath))
1261*f6dc9357SAndroid Build Coastguard Worker         return E_FAIL;
1262*f6dc9357SAndroid Build Coastguard Worker       }
1263*f6dc9357SAndroid Build Coastguard Worker       _isRenamed = true;
1264*f6dc9357SAndroid Build Coastguard Worker     }
1265*f6dc9357SAndroid Build Coastguard Worker     else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting)
1266*f6dc9357SAndroid Build Coastguard Worker     {
1267*f6dc9357SAndroid Build Coastguard Worker       FString existPath (fullProcessedPath);
1268*f6dc9357SAndroid Build Coastguard Worker       if (!AutoRenamePath(existPath))
1269*f6dc9357SAndroid Build Coastguard Worker       {
1270*f6dc9357SAndroid Build Coastguard Worker         RINOK(SendMessageError(kCantAutoRename, fullProcessedPath))
1271*f6dc9357SAndroid Build Coastguard Worker         return E_FAIL;
1272*f6dc9357SAndroid Build Coastguard Worker       }
1273*f6dc9357SAndroid Build Coastguard Worker       // MyMoveFile can rename folders. So it's OK to use it for folders too
1274*f6dc9357SAndroid Build Coastguard Worker       if (!MyMoveFile(fullProcessedPath, existPath))
1275*f6dc9357SAndroid Build Coastguard Worker       {
1276*f6dc9357SAndroid Build Coastguard Worker         HRESULT errorCode = GetLastError_noZero_HRESULT();
1277*f6dc9357SAndroid Build Coastguard Worker         RINOK(SendMessageError2(errorCode, kCantRenameFile, existPath, fullProcessedPath))
1278*f6dc9357SAndroid Build Coastguard Worker         return E_FAIL;
1279*f6dc9357SAndroid Build Coastguard Worker       }
1280*f6dc9357SAndroid Build Coastguard Worker     }
1281*f6dc9357SAndroid Build Coastguard Worker     else // not Rename*
1282*f6dc9357SAndroid Build Coastguard Worker     {
1283*f6dc9357SAndroid Build Coastguard Worker       if (fileInfo.IsDir())
1284*f6dc9357SAndroid Build Coastguard Worker       {
1285*f6dc9357SAndroid Build Coastguard Worker         // do we need to delete all files in folder?
1286*f6dc9357SAndroid Build Coastguard Worker         if (!RemoveDir(fullProcessedPath))
1287*f6dc9357SAndroid Build Coastguard Worker         {
1288*f6dc9357SAndroid Build Coastguard Worker           RINOK(SendMessageError_with_LastError(kCantDeleteOutputDir, fullProcessedPath))
1289*f6dc9357SAndroid Build Coastguard Worker           return S_OK;
1290*f6dc9357SAndroid Build Coastguard Worker         }
1291*f6dc9357SAndroid Build Coastguard Worker       }
1292*f6dc9357SAndroid Build Coastguard Worker       else // fileInfo is not Dir
1293*f6dc9357SAndroid Build Coastguard Worker       {
1294*f6dc9357SAndroid Build Coastguard Worker         if (NFind::DoesFileExist_Raw(fullProcessedPath))
1295*f6dc9357SAndroid Build Coastguard Worker           if (!DeleteFileAlways(fullProcessedPath))
1296*f6dc9357SAndroid Build Coastguard Worker             if (GetLastError() != ERROR_FILE_NOT_FOUND) // check it in linux
1297*f6dc9357SAndroid Build Coastguard Worker             {
1298*f6dc9357SAndroid Build Coastguard Worker               RINOK(SendMessageError_with_LastError(kCantDeleteOutputFile, fullProcessedPath))
1299*f6dc9357SAndroid Build Coastguard Worker               return S_OK;
1300*f6dc9357SAndroid Build Coastguard Worker               // return E_FAIL;
1301*f6dc9357SAndroid Build Coastguard Worker             }
1302*f6dc9357SAndroid Build Coastguard Worker       } // fileInfo is not Dir
1303*f6dc9357SAndroid Build Coastguard Worker     } // not Rename*
1304*f6dc9357SAndroid Build Coastguard Worker   }
1305*f6dc9357SAndroid Build Coastguard Worker   else // not Find(fullProcessedPath)
1306*f6dc9357SAndroid Build Coastguard Worker   {
1307*f6dc9357SAndroid Build Coastguard Worker     #if defined(_WIN32) && !defined(UNDER_CE)
1308*f6dc9357SAndroid Build Coastguard Worker     // we need to clear READ-ONLY of parent before creating alt stream
1309*f6dc9357SAndroid Build Coastguard Worker     const int colonPos = NName::FindAltStreamColon(fullProcessedPath);
1310*f6dc9357SAndroid Build Coastguard Worker     if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0)
1311*f6dc9357SAndroid Build Coastguard Worker     {
1312*f6dc9357SAndroid Build Coastguard Worker       FString parentFsPath (fullProcessedPath);
1313*f6dc9357SAndroid Build Coastguard Worker       parentFsPath.DeleteFrom((unsigned)colonPos);
1314*f6dc9357SAndroid Build Coastguard Worker       NFind::CFileInfo parentFi;
1315*f6dc9357SAndroid Build Coastguard Worker       if (parentFi.Find(parentFsPath))
1316*f6dc9357SAndroid Build Coastguard Worker       {
1317*f6dc9357SAndroid Build Coastguard Worker         if (parentFi.IsReadOnly())
1318*f6dc9357SAndroid Build Coastguard Worker         {
1319*f6dc9357SAndroid Build Coastguard Worker           _altStream_NeedRestore_Attrib_for_parentFsPath = parentFsPath;
1320*f6dc9357SAndroid Build Coastguard Worker           _altStream_NeedRestore_AttribVal = parentFi.Attrib;
1321*f6dc9357SAndroid Build Coastguard Worker           SetFileAttrib(parentFsPath, parentFi.Attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY);
1322*f6dc9357SAndroid Build Coastguard Worker         }
1323*f6dc9357SAndroid Build Coastguard Worker       }
1324*f6dc9357SAndroid Build Coastguard Worker     }
1325*f6dc9357SAndroid Build Coastguard Worker     #endif // defined(_WIN32) && !defined(UNDER_CE)
1326*f6dc9357SAndroid Build Coastguard Worker   }
1327*f6dc9357SAndroid Build Coastguard Worker 
1328*f6dc9357SAndroid Build Coastguard Worker   needExit = false;
1329*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1330*f6dc9357SAndroid Build Coastguard Worker }
1331*f6dc9357SAndroid Build Coastguard Worker 
1332*f6dc9357SAndroid Build Coastguard Worker 
1333*f6dc9357SAndroid Build Coastguard Worker 
1334*f6dc9357SAndroid Build Coastguard Worker 
1335*f6dc9357SAndroid Build Coastguard Worker 
1336*f6dc9357SAndroid Build Coastguard Worker 
1337*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit)
1338*f6dc9357SAndroid Build Coastguard Worker {
1339*f6dc9357SAndroid Build Coastguard Worker   needExit = true;
1340*f6dc9357SAndroid Build Coastguard Worker 
1341*f6dc9357SAndroid Build Coastguard Worker   RINOK(Read_fi_Props())
1342*f6dc9357SAndroid Build Coastguard Worker 
1343*f6dc9357SAndroid Build Coastguard Worker   #ifdef SUPPORT_LINKS
1344*f6dc9357SAndroid Build Coastguard Worker   IInArchive *archive = _arc->Archive;
1345*f6dc9357SAndroid Build Coastguard Worker   #endif
1346*f6dc9357SAndroid Build Coastguard Worker 
1347*f6dc9357SAndroid Build Coastguard Worker   const UInt32 index = _index;
1348*f6dc9357SAndroid Build Coastguard Worker 
1349*f6dc9357SAndroid Build Coastguard Worker   bool isAnti = false;
1350*f6dc9357SAndroid Build Coastguard Worker   RINOK(_arc->IsItem_Anti(index, isAnti))
1351*f6dc9357SAndroid Build Coastguard Worker 
1352*f6dc9357SAndroid Build Coastguard Worker   CorrectPathParts();
1353*f6dc9357SAndroid Build Coastguard Worker   UString processedPath (MakePathFromParts(_item.PathParts));
1354*f6dc9357SAndroid Build Coastguard Worker 
1355*f6dc9357SAndroid Build Coastguard Worker   if (!isAnti)
1356*f6dc9357SAndroid Build Coastguard Worker   {
1357*f6dc9357SAndroid Build Coastguard Worker     // 21.04: CreateFolders doesn't change (_item.PathParts)
1358*f6dc9357SAndroid Build Coastguard Worker     CreateFolders();
1359*f6dc9357SAndroid Build Coastguard Worker   }
1360*f6dc9357SAndroid Build Coastguard Worker 
1361*f6dc9357SAndroid Build Coastguard Worker   FString fullProcessedPath (us2fs(processedPath));
1362*f6dc9357SAndroid Build Coastguard Worker   if (_pathMode != NExtract::NPathMode::kAbsPaths
1363*f6dc9357SAndroid Build Coastguard Worker       || !NName::IsAbsolutePath(processedPath))
1364*f6dc9357SAndroid Build Coastguard Worker   {
1365*f6dc9357SAndroid Build Coastguard Worker     fullProcessedPath = MakePath_from_2_Parts(_dirPathPrefix, fullProcessedPath);
1366*f6dc9357SAndroid Build Coastguard Worker   }
1367*f6dc9357SAndroid Build Coastguard Worker 
1368*f6dc9357SAndroid Build Coastguard Worker   #ifdef SUPPORT_ALT_STREAMS
1369*f6dc9357SAndroid Build Coastguard Worker   if (_item.IsAltStream && _item.ParentIndex != (UInt32)(Int32)-1)
1370*f6dc9357SAndroid Build Coastguard Worker   {
1371*f6dc9357SAndroid Build Coastguard Worker     const int renIndex = _renamedFiles.FindInSorted(CIndexToPathPair(_item.ParentIndex));
1372*f6dc9357SAndroid Build Coastguard Worker     if (renIndex != -1)
1373*f6dc9357SAndroid Build Coastguard Worker     {
1374*f6dc9357SAndroid Build Coastguard Worker       const CIndexToPathPair &pair = _renamedFiles[(unsigned)renIndex];
1375*f6dc9357SAndroid Build Coastguard Worker       fullProcessedPath = pair.Path;
1376*f6dc9357SAndroid Build Coastguard Worker       fullProcessedPath.Add_Colon();
1377*f6dc9357SAndroid Build Coastguard Worker       UString s (_item.AltStreamName);
1378*f6dc9357SAndroid Build Coastguard Worker       Correct_AltStream_Name(s);
1379*f6dc9357SAndroid Build Coastguard Worker       fullProcessedPath += us2fs(s);
1380*f6dc9357SAndroid Build Coastguard Worker     }
1381*f6dc9357SAndroid Build Coastguard Worker   }
1382*f6dc9357SAndroid Build Coastguard Worker   #endif // SUPPORT_ALT_STREAMS
1383*f6dc9357SAndroid Build Coastguard Worker 
1384*f6dc9357SAndroid Build Coastguard Worker   if (_item.IsDir)
1385*f6dc9357SAndroid Build Coastguard Worker   {
1386*f6dc9357SAndroid Build Coastguard Worker     _diskFilePath = fullProcessedPath;
1387*f6dc9357SAndroid Build Coastguard Worker     if (isAnti)
1388*f6dc9357SAndroid Build Coastguard Worker       RemoveDir(_diskFilePath);
1389*f6dc9357SAndroid Build Coastguard Worker     #ifdef SUPPORT_LINKS
1390*f6dc9357SAndroid Build Coastguard Worker     if (_link.linkPath.IsEmpty())
1391*f6dc9357SAndroid Build Coastguard Worker     #endif
1392*f6dc9357SAndroid Build Coastguard Worker     {
1393*f6dc9357SAndroid Build Coastguard Worker       if (!isAnti)
1394*f6dc9357SAndroid Build Coastguard Worker         SetAttrib();
1395*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1396*f6dc9357SAndroid Build Coastguard Worker     }
1397*f6dc9357SAndroid Build Coastguard Worker   }
1398*f6dc9357SAndroid Build Coastguard Worker   else if (!_isSplit)
1399*f6dc9357SAndroid Build Coastguard Worker   {
1400*f6dc9357SAndroid Build Coastguard Worker     RINOK(CheckExistFile(fullProcessedPath, needExit))
1401*f6dc9357SAndroid Build Coastguard Worker     if (needExit)
1402*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1403*f6dc9357SAndroid Build Coastguard Worker     needExit = true;
1404*f6dc9357SAndroid Build Coastguard Worker   }
1405*f6dc9357SAndroid Build Coastguard Worker 
1406*f6dc9357SAndroid Build Coastguard Worker   _diskFilePath = fullProcessedPath;
1407*f6dc9357SAndroid Build Coastguard Worker 
1408*f6dc9357SAndroid Build Coastguard Worker 
1409*f6dc9357SAndroid Build Coastguard Worker   if (isAnti)
1410*f6dc9357SAndroid Build Coastguard Worker   {
1411*f6dc9357SAndroid Build Coastguard Worker     needExit = false;
1412*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1413*f6dc9357SAndroid Build Coastguard Worker   }
1414*f6dc9357SAndroid Build Coastguard Worker 
1415*f6dc9357SAndroid Build Coastguard Worker   // not anti
1416*f6dc9357SAndroid Build Coastguard Worker 
1417*f6dc9357SAndroid Build Coastguard Worker   #ifdef SUPPORT_LINKS
1418*f6dc9357SAndroid Build Coastguard Worker 
1419*f6dc9357SAndroid Build Coastguard Worker   if (!_link.linkPath.IsEmpty())
1420*f6dc9357SAndroid Build Coastguard Worker   {
1421*f6dc9357SAndroid Build Coastguard Worker     #ifndef UNDER_CE
1422*f6dc9357SAndroid Build Coastguard Worker     {
1423*f6dc9357SAndroid Build Coastguard Worker       bool linkWasSet = false;
1424*f6dc9357SAndroid Build Coastguard Worker       RINOK(SetFromLinkPath(fullProcessedPath, _link, linkWasSet))
1425*f6dc9357SAndroid Build Coastguard Worker       if (linkWasSet)
1426*f6dc9357SAndroid Build Coastguard Worker       {
1427*f6dc9357SAndroid Build Coastguard Worker         _isSymLinkCreated = _link.IsSymLink();
1428*f6dc9357SAndroid Build Coastguard Worker         SetAttrib();
1429*f6dc9357SAndroid Build Coastguard Worker         // printf("\nlinkWasSet %s\n", GetAnsiString(_diskFilePath));
1430*f6dc9357SAndroid Build Coastguard Worker       }
1431*f6dc9357SAndroid Build Coastguard Worker     }
1432*f6dc9357SAndroid Build Coastguard Worker     #endif // UNDER_CE
1433*f6dc9357SAndroid Build Coastguard Worker 
1434*f6dc9357SAndroid Build Coastguard Worker     // if (_copyFile_Path.IsEmpty())
1435*f6dc9357SAndroid Build Coastguard Worker     {
1436*f6dc9357SAndroid Build Coastguard Worker       needExit = false;
1437*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1438*f6dc9357SAndroid Build Coastguard Worker     }
1439*f6dc9357SAndroid Build Coastguard Worker   }
1440*f6dc9357SAndroid Build Coastguard Worker 
1441*f6dc9357SAndroid Build Coastguard Worker   if (!_hardLinks.IDs.IsEmpty() && !_item.IsAltStream && !_item.IsDir)
1442*f6dc9357SAndroid Build Coastguard Worker   {
1443*f6dc9357SAndroid Build Coastguard Worker     CHardLinkNode h;
1444*f6dc9357SAndroid Build Coastguard Worker     bool defined;
1445*f6dc9357SAndroid Build Coastguard Worker     RINOK(Archive_Get_HardLinkNode(archive, index, h, defined))
1446*f6dc9357SAndroid Build Coastguard Worker     if (defined)
1447*f6dc9357SAndroid Build Coastguard Worker     {
1448*f6dc9357SAndroid Build Coastguard Worker       const int linkIndex = _hardLinks.IDs.FindInSorted2(h);
1449*f6dc9357SAndroid Build Coastguard Worker       if (linkIndex != -1)
1450*f6dc9357SAndroid Build Coastguard Worker       {
1451*f6dc9357SAndroid Build Coastguard Worker         FString &hl = _hardLinks.Links[(unsigned)linkIndex];
1452*f6dc9357SAndroid Build Coastguard Worker         if (hl.IsEmpty())
1453*f6dc9357SAndroid Build Coastguard Worker           hl = fullProcessedPath;
1454*f6dc9357SAndroid Build Coastguard Worker         else
1455*f6dc9357SAndroid Build Coastguard Worker         {
1456*f6dc9357SAndroid Build Coastguard Worker           if (!MyCreateHardLink(fullProcessedPath, hl))
1457*f6dc9357SAndroid Build Coastguard Worker           {
1458*f6dc9357SAndroid Build Coastguard Worker             const HRESULT errorCode = GetLastError_noZero_HRESULT();
1459*f6dc9357SAndroid Build Coastguard Worker             RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, hl))
1460*f6dc9357SAndroid Build Coastguard Worker             return S_OK;
1461*f6dc9357SAndroid Build Coastguard Worker           }
1462*f6dc9357SAndroid Build Coastguard Worker 
1463*f6dc9357SAndroid Build Coastguard Worker           // printf("\nHard linkWasSet Archive_Get_HardLinkNode %s\n", GetAnsiString(_diskFilePath));
1464*f6dc9357SAndroid Build Coastguard Worker           // _needSetAttrib = true; // do we need to set attribute ?
1465*f6dc9357SAndroid Build Coastguard Worker           SetAttrib();
1466*f6dc9357SAndroid Build Coastguard Worker           needExit = false;
1467*f6dc9357SAndroid Build Coastguard Worker           return S_OK;
1468*f6dc9357SAndroid Build Coastguard Worker         }
1469*f6dc9357SAndroid Build Coastguard Worker       }
1470*f6dc9357SAndroid Build Coastguard Worker     }
1471*f6dc9357SAndroid Build Coastguard Worker   }
1472*f6dc9357SAndroid Build Coastguard Worker 
1473*f6dc9357SAndroid Build Coastguard Worker   #endif // SUPPORT_LINKS
1474*f6dc9357SAndroid Build Coastguard Worker 
1475*f6dc9357SAndroid Build Coastguard Worker 
1476*f6dc9357SAndroid Build Coastguard Worker   // ---------- CREATE WRITE FILE -----
1477*f6dc9357SAndroid Build Coastguard Worker 
1478*f6dc9357SAndroid Build Coastguard Worker   _outFileStreamSpec = new COutFileStream;
1479*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IOutStream> outFileStream_Loc(_outFileStreamSpec);
1480*f6dc9357SAndroid Build Coastguard Worker 
1481*f6dc9357SAndroid Build Coastguard Worker   if (!_outFileStreamSpec->Create_ALWAYS_or_Open_ALWAYS(fullProcessedPath, !_isSplit))
1482*f6dc9357SAndroid Build Coastguard Worker   {
1483*f6dc9357SAndroid Build Coastguard Worker     // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)
1484*f6dc9357SAndroid Build Coastguard Worker     {
1485*f6dc9357SAndroid Build Coastguard Worker       RINOK(SendMessageError_with_LastError(kCantOpenOutFile, fullProcessedPath))
1486*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1487*f6dc9357SAndroid Build Coastguard Worker     }
1488*f6dc9357SAndroid Build Coastguard Worker   }
1489*f6dc9357SAndroid Build Coastguard Worker 
1490*f6dc9357SAndroid Build Coastguard Worker   _needSetAttrib = true;
1491*f6dc9357SAndroid Build Coastguard Worker 
1492*f6dc9357SAndroid Build Coastguard Worker   bool is_SymLink_in_Data = false;
1493*f6dc9357SAndroid Build Coastguard Worker 
1494*f6dc9357SAndroid Build Coastguard Worker   if (_curSize_Defined && _curSize > 0 && _curSize < (1 << 12))
1495*f6dc9357SAndroid Build Coastguard Worker   {
1496*f6dc9357SAndroid Build Coastguard Worker     if (_fi.IsLinuxSymLink())
1497*f6dc9357SAndroid Build Coastguard Worker     {
1498*f6dc9357SAndroid Build Coastguard Worker       is_SymLink_in_Data = true;
1499*f6dc9357SAndroid Build Coastguard Worker       _is_SymLink_in_Data_Linux = true;
1500*f6dc9357SAndroid Build Coastguard Worker     }
1501*f6dc9357SAndroid Build Coastguard Worker     else if (_fi.IsReparse())
1502*f6dc9357SAndroid Build Coastguard Worker     {
1503*f6dc9357SAndroid Build Coastguard Worker       is_SymLink_in_Data = true;
1504*f6dc9357SAndroid Build Coastguard Worker       _is_SymLink_in_Data_Linux = false;
1505*f6dc9357SAndroid Build Coastguard Worker     }
1506*f6dc9357SAndroid Build Coastguard Worker   }
1507*f6dc9357SAndroid Build Coastguard Worker 
1508*f6dc9357SAndroid Build Coastguard Worker   if (is_SymLink_in_Data)
1509*f6dc9357SAndroid Build Coastguard Worker   {
1510*f6dc9357SAndroid Build Coastguard Worker     _outMemBuf.Alloc((size_t)_curSize);
1511*f6dc9357SAndroid Build Coastguard Worker     _bufPtrSeqOutStream_Spec = new CBufPtrSeqOutStream;
1512*f6dc9357SAndroid Build Coastguard Worker     _bufPtrSeqOutStream = _bufPtrSeqOutStream_Spec;
1513*f6dc9357SAndroid Build Coastguard Worker     _bufPtrSeqOutStream_Spec->Init(_outMemBuf, _outMemBuf.Size());
1514*f6dc9357SAndroid Build Coastguard Worker     outStreamLoc = _bufPtrSeqOutStream;
1515*f6dc9357SAndroid Build Coastguard Worker   }
1516*f6dc9357SAndroid Build Coastguard Worker   else // not reprase
1517*f6dc9357SAndroid Build Coastguard Worker   {
1518*f6dc9357SAndroid Build Coastguard Worker     if (_ntOptions.PreAllocateOutFile && !_isSplit && _curSize_Defined && _curSize > (1 << 12))
1519*f6dc9357SAndroid Build Coastguard Worker     {
1520*f6dc9357SAndroid Build Coastguard Worker       // UInt64 ticks = GetCpuTicks();
1521*f6dc9357SAndroid Build Coastguard Worker       _fileLength_that_WasSet = _curSize;
1522*f6dc9357SAndroid Build Coastguard Worker       bool res = _outFileStreamSpec->File.SetLength(_curSize);
1523*f6dc9357SAndroid Build Coastguard Worker       _fileLength_WasSet = res;
1524*f6dc9357SAndroid Build Coastguard Worker 
1525*f6dc9357SAndroid Build Coastguard Worker       // ticks = GetCpuTicks() - ticks;
1526*f6dc9357SAndroid Build Coastguard Worker       // printf("\nticks = %10d\n", (unsigned)ticks);
1527*f6dc9357SAndroid Build Coastguard Worker       if (!res)
1528*f6dc9357SAndroid Build Coastguard Worker       {
1529*f6dc9357SAndroid Build Coastguard Worker         RINOK(SendMessageError_with_LastError(kCantSetFileLen, fullProcessedPath))
1530*f6dc9357SAndroid Build Coastguard Worker       }
1531*f6dc9357SAndroid Build Coastguard Worker 
1532*f6dc9357SAndroid Build Coastguard Worker       /*
1533*f6dc9357SAndroid Build Coastguard Worker       _outFileStreamSpec->File.Close();
1534*f6dc9357SAndroid Build Coastguard Worker       ticks = GetCpuTicks() - ticks;
1535*f6dc9357SAndroid Build Coastguard Worker       printf("\nticks = %10d\n", (unsigned)ticks);
1536*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
1537*f6dc9357SAndroid Build Coastguard Worker       */
1538*f6dc9357SAndroid Build Coastguard Worker 
1539*f6dc9357SAndroid Build Coastguard Worker       /*
1540*f6dc9357SAndroid Build Coastguard Worker       File.SetLength() on FAT (xp64): is fast, but then File.Close() can be slow,
1541*f6dc9357SAndroid Build Coastguard Worker       if we don't write any data.
1542*f6dc9357SAndroid Build Coastguard Worker       File.SetLength() for remote share file (exFAT) can be slow in some cases,
1543*f6dc9357SAndroid Build Coastguard Worker       and the Windows can return "network error" after 1 minute,
1544*f6dc9357SAndroid Build Coastguard Worker       while remote file still can grow.
1545*f6dc9357SAndroid Build Coastguard Worker       We need some way to detect such bad cases and disable PreAllocateOutFile mode.
1546*f6dc9357SAndroid Build Coastguard Worker       */
1547*f6dc9357SAndroid Build Coastguard Worker 
1548*f6dc9357SAndroid Build Coastguard Worker       res = _outFileStreamSpec->SeekToBegin_bool();
1549*f6dc9357SAndroid Build Coastguard Worker       if (!res)
1550*f6dc9357SAndroid Build Coastguard Worker       {
1551*f6dc9357SAndroid Build Coastguard Worker         RINOK(SendMessageError_with_LastError("Cannot seek to begin of file", fullProcessedPath))
1552*f6dc9357SAndroid Build Coastguard Worker       }
1553*f6dc9357SAndroid Build Coastguard Worker     } // PreAllocateOutFile
1554*f6dc9357SAndroid Build Coastguard Worker 
1555*f6dc9357SAndroid Build Coastguard Worker     #ifdef SUPPORT_ALT_STREAMS
1556*f6dc9357SAndroid Build Coastguard Worker     if (_isRenamed && !_item.IsAltStream)
1557*f6dc9357SAndroid Build Coastguard Worker     {
1558*f6dc9357SAndroid Build Coastguard Worker       CIndexToPathPair pair(index, fullProcessedPath);
1559*f6dc9357SAndroid Build Coastguard Worker       unsigned oldSize = _renamedFiles.Size();
1560*f6dc9357SAndroid Build Coastguard Worker       unsigned insertIndex = _renamedFiles.AddToUniqueSorted(pair);
1561*f6dc9357SAndroid Build Coastguard Worker       if (oldSize == _renamedFiles.Size())
1562*f6dc9357SAndroid Build Coastguard Worker         _renamedFiles[insertIndex].Path = fullProcessedPath;
1563*f6dc9357SAndroid Build Coastguard Worker     }
1564*f6dc9357SAndroid Build Coastguard Worker     #endif // SUPPORT_ALT_STREAMS
1565*f6dc9357SAndroid Build Coastguard Worker 
1566*f6dc9357SAndroid Build Coastguard Worker     if (_isSplit)
1567*f6dc9357SAndroid Build Coastguard Worker     {
1568*f6dc9357SAndroid Build Coastguard Worker       RINOK(outFileStream_Loc->Seek((Int64)_position, STREAM_SEEK_SET, NULL))
1569*f6dc9357SAndroid Build Coastguard Worker     }
1570*f6dc9357SAndroid Build Coastguard Worker     outStreamLoc = outFileStream_Loc;
1571*f6dc9357SAndroid Build Coastguard Worker   } // if not reprase
1572*f6dc9357SAndroid Build Coastguard Worker 
1573*f6dc9357SAndroid Build Coastguard Worker   _outFileStream = outFileStream_Loc;
1574*f6dc9357SAndroid Build Coastguard Worker 
1575*f6dc9357SAndroid Build Coastguard Worker   needExit = false;
1576*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1577*f6dc9357SAndroid Build Coastguard Worker }
1578*f6dc9357SAndroid Build Coastguard Worker 
1579*f6dc9357SAndroid Build Coastguard Worker 
1580*f6dc9357SAndroid Build Coastguard Worker 
1581*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::GetItem(UInt32 index)
1582*f6dc9357SAndroid Build Coastguard Worker {
1583*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_SFX
1584*f6dc9357SAndroid Build Coastguard Worker   _item._use_baseParentFolder_mode = _use_baseParentFolder_mode;
1585*f6dc9357SAndroid Build Coastguard Worker   if (_use_baseParentFolder_mode)
1586*f6dc9357SAndroid Build Coastguard Worker   {
1587*f6dc9357SAndroid Build Coastguard Worker     _item._baseParentFolder = (int)_baseParentFolder;
1588*f6dc9357SAndroid Build Coastguard Worker     if (_pathMode == NExtract::NPathMode::kFullPaths ||
1589*f6dc9357SAndroid Build Coastguard Worker         _pathMode == NExtract::NPathMode::kAbsPaths)
1590*f6dc9357SAndroid Build Coastguard Worker       _item._baseParentFolder = -1;
1591*f6dc9357SAndroid Build Coastguard Worker   }
1592*f6dc9357SAndroid Build Coastguard Worker   #endif // Z7_SFX
1593*f6dc9357SAndroid Build Coastguard Worker 
1594*f6dc9357SAndroid Build Coastguard Worker   #ifdef SUPPORT_ALT_STREAMS
1595*f6dc9357SAndroid Build Coastguard Worker   _item.WriteToAltStreamIfColon = _ntOptions.WriteToAltStreamIfColon;
1596*f6dc9357SAndroid Build Coastguard Worker   #endif
1597*f6dc9357SAndroid Build Coastguard Worker 
1598*f6dc9357SAndroid Build Coastguard Worker   return _arc->GetItem(index, _item);
1599*f6dc9357SAndroid Build Coastguard Worker }
1600*f6dc9357SAndroid Build Coastguard Worker 
1601*f6dc9357SAndroid Build Coastguard Worker 
1602*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode))
1603*f6dc9357SAndroid Build Coastguard Worker {
1604*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
1605*f6dc9357SAndroid Build Coastguard Worker 
1606*f6dc9357SAndroid Build Coastguard Worker   *outStream = NULL;
1607*f6dc9357SAndroid Build Coastguard Worker 
1608*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_SFX
1609*f6dc9357SAndroid Build Coastguard Worker   if (_hashStream)
1610*f6dc9357SAndroid Build Coastguard Worker     _hashStreamSpec->ReleaseStream();
1611*f6dc9357SAndroid Build Coastguard Worker   _hashStreamWasUsed = false;
1612*f6dc9357SAndroid Build Coastguard Worker   #endif
1613*f6dc9357SAndroid Build Coastguard Worker 
1614*f6dc9357SAndroid Build Coastguard Worker   _outFileStream.Release();
1615*f6dc9357SAndroid Build Coastguard Worker   _bufPtrSeqOutStream.Release();
1616*f6dc9357SAndroid Build Coastguard Worker 
1617*f6dc9357SAndroid Build Coastguard Worker   _encrypted = false;
1618*f6dc9357SAndroid Build Coastguard Worker   _isSplit = false;
1619*f6dc9357SAndroid Build Coastguard Worker   _curSize_Defined = false;
1620*f6dc9357SAndroid Build Coastguard Worker   _fileLength_WasSet = false;
1621*f6dc9357SAndroid Build Coastguard Worker   _isRenamed = false;
1622*f6dc9357SAndroid Build Coastguard Worker   // _fi.Clear();
1623*f6dc9357SAndroid Build Coastguard Worker  _extractMode = false;
1624*f6dc9357SAndroid Build Coastguard Worker   // _is_SymLink_in_Data = false;
1625*f6dc9357SAndroid Build Coastguard Worker   _is_SymLink_in_Data_Linux = false;
1626*f6dc9357SAndroid Build Coastguard Worker   _needSetAttrib = false;
1627*f6dc9357SAndroid Build Coastguard Worker   _isSymLinkCreated = false;
1628*f6dc9357SAndroid Build Coastguard Worker   _itemFailure = false;
1629*f6dc9357SAndroid Build Coastguard Worker   _some_pathParts_wereRemoved = false;
1630*f6dc9357SAndroid Build Coastguard Worker   // _op_WasReported = false;
1631*f6dc9357SAndroid Build Coastguard Worker 
1632*f6dc9357SAndroid Build Coastguard Worker   _position = 0;
1633*f6dc9357SAndroid Build Coastguard Worker   _curSize = 0;
1634*f6dc9357SAndroid Build Coastguard Worker   _fileLength_that_WasSet = 0;
1635*f6dc9357SAndroid Build Coastguard Worker   _index = index;
1636*f6dc9357SAndroid Build Coastguard Worker 
1637*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(UNDER_CE)
1638*f6dc9357SAndroid Build Coastguard Worker   _altStream_NeedRestore_AttribVal = 0;
1639*f6dc9357SAndroid Build Coastguard Worker   _altStream_NeedRestore_Attrib_for_parentFsPath.Empty();
1640*f6dc9357SAndroid Build Coastguard Worker #endif
1641*f6dc9357SAndroid Build Coastguard Worker 
1642*f6dc9357SAndroid Build Coastguard Worker   _diskFilePath.Empty();
1643*f6dc9357SAndroid Build Coastguard Worker 
1644*f6dc9357SAndroid Build Coastguard Worker   #ifdef SUPPORT_LINKS
1645*f6dc9357SAndroid Build Coastguard Worker   // _copyFile_Path.Empty();
1646*f6dc9357SAndroid Build Coastguard Worker   _link.Clear();
1647*f6dc9357SAndroid Build Coastguard Worker   #endif
1648*f6dc9357SAndroid Build Coastguard Worker 
1649*f6dc9357SAndroid Build Coastguard Worker 
1650*f6dc9357SAndroid Build Coastguard Worker   switch (askExtractMode)
1651*f6dc9357SAndroid Build Coastguard Worker   {
1652*f6dc9357SAndroid Build Coastguard Worker     case NArchive::NExtract::NAskMode::kExtract:
1653*f6dc9357SAndroid Build Coastguard Worker       if (_testMode)
1654*f6dc9357SAndroid Build Coastguard Worker       {
1655*f6dc9357SAndroid Build Coastguard Worker         // askExtractMode = NArchive::NExtract::NAskMode::kTest;
1656*f6dc9357SAndroid Build Coastguard Worker       }
1657*f6dc9357SAndroid Build Coastguard Worker       else
1658*f6dc9357SAndroid Build Coastguard Worker         _extractMode = true;
1659*f6dc9357SAndroid Build Coastguard Worker       break;
1660*f6dc9357SAndroid Build Coastguard Worker     default: break;
1661*f6dc9357SAndroid Build Coastguard Worker   }
1662*f6dc9357SAndroid Build Coastguard Worker 
1663*f6dc9357SAndroid Build Coastguard Worker 
1664*f6dc9357SAndroid Build Coastguard Worker   IInArchive *archive = _arc->Archive;
1665*f6dc9357SAndroid Build Coastguard Worker 
1666*f6dc9357SAndroid Build Coastguard Worker   RINOK(GetItem(index))
1667*f6dc9357SAndroid Build Coastguard Worker 
1668*f6dc9357SAndroid Build Coastguard Worker   {
1669*f6dc9357SAndroid Build Coastguard Worker     NCOM::CPropVariant prop;
1670*f6dc9357SAndroid Build Coastguard Worker     RINOK(archive->GetProperty(index, kpidPosition, &prop))
1671*f6dc9357SAndroid Build Coastguard Worker     if (prop.vt != VT_EMPTY)
1672*f6dc9357SAndroid Build Coastguard Worker     {
1673*f6dc9357SAndroid Build Coastguard Worker       if (prop.vt != VT_UI8)
1674*f6dc9357SAndroid Build Coastguard Worker         return E_FAIL;
1675*f6dc9357SAndroid Build Coastguard Worker       _position = prop.uhVal.QuadPart;
1676*f6dc9357SAndroid Build Coastguard Worker       _isSplit = true;
1677*f6dc9357SAndroid Build Coastguard Worker     }
1678*f6dc9357SAndroid Build Coastguard Worker   }
1679*f6dc9357SAndroid Build Coastguard Worker 
1680*f6dc9357SAndroid Build Coastguard Worker   #ifdef SUPPORT_LINKS
1681*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadLink())
1682*f6dc9357SAndroid Build Coastguard Worker   #endif // SUPPORT_LINKS
1683*f6dc9357SAndroid Build Coastguard Worker 
1684*f6dc9357SAndroid Build Coastguard Worker 
1685*f6dc9357SAndroid Build Coastguard Worker   RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted))
1686*f6dc9357SAndroid Build Coastguard Worker 
1687*f6dc9357SAndroid Build Coastguard Worker   RINOK(GetUnpackSize())
1688*f6dc9357SAndroid Build Coastguard Worker 
1689*f6dc9357SAndroid Build Coastguard Worker   #ifdef SUPPORT_ALT_STREAMS
1690*f6dc9357SAndroid Build Coastguard Worker   if (!_ntOptions.AltStreams.Val && _item.IsAltStream)
1691*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1692*f6dc9357SAndroid Build Coastguard Worker   #endif // SUPPORT_ALT_STREAMS
1693*f6dc9357SAndroid Build Coastguard Worker 
1694*f6dc9357SAndroid Build Coastguard Worker   // we can change (_item.PathParts) in this function
1695*f6dc9357SAndroid Build Coastguard Worker   UStringVector &pathParts = _item.PathParts;
1696*f6dc9357SAndroid Build Coastguard Worker 
1697*f6dc9357SAndroid Build Coastguard Worker   if (_wildcardCensor)
1698*f6dc9357SAndroid Build Coastguard Worker   {
1699*f6dc9357SAndroid Build Coastguard Worker     if (!CensorNode_CheckPath(*_wildcardCensor, _item))
1700*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1701*f6dc9357SAndroid Build Coastguard Worker   }
1702*f6dc9357SAndroid Build Coastguard Worker 
1703*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
1704*f6dc9357SAndroid Build Coastguard Worker   if (askExtractMode == NArchive::NExtract::NAskMode::kExtract
1705*f6dc9357SAndroid Build Coastguard Worker       && !_testMode
1706*f6dc9357SAndroid Build Coastguard Worker       && _item.IsAltStream
1707*f6dc9357SAndroid Build Coastguard Worker       && ZoneBuf.Size() != 0
1708*f6dc9357SAndroid Build Coastguard Worker       && Is_ZoneId_StreamName(_item.AltStreamName))
1709*f6dc9357SAndroid Build Coastguard Worker     if (ZoneMode != NExtract::NZoneIdMode::kOffice
1710*f6dc9357SAndroid Build Coastguard Worker         || _item.PathParts.IsEmpty()
1711*f6dc9357SAndroid Build Coastguard Worker         || FindExt2(kOfficeExtensions, _item.PathParts.Back()))
1712*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1713*f6dc9357SAndroid Build Coastguard Worker #endif
1714*f6dc9357SAndroid Build Coastguard Worker 
1715*f6dc9357SAndroid Build Coastguard Worker 
1716*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_SFX
1717*f6dc9357SAndroid Build Coastguard Worker   if (_use_baseParentFolder_mode)
1718*f6dc9357SAndroid Build Coastguard Worker   {
1719*f6dc9357SAndroid Build Coastguard Worker     if (!pathParts.IsEmpty())
1720*f6dc9357SAndroid Build Coastguard Worker     {
1721*f6dc9357SAndroid Build Coastguard Worker       unsigned numRemovePathParts = 0;
1722*f6dc9357SAndroid Build Coastguard Worker 
1723*f6dc9357SAndroid Build Coastguard Worker       #ifdef SUPPORT_ALT_STREAMS
1724*f6dc9357SAndroid Build Coastguard Worker       if (_pathMode == NExtract::NPathMode::kNoPathsAlt && _item.IsAltStream)
1725*f6dc9357SAndroid Build Coastguard Worker         numRemovePathParts = pathParts.Size();
1726*f6dc9357SAndroid Build Coastguard Worker       else
1727*f6dc9357SAndroid Build Coastguard Worker       #endif
1728*f6dc9357SAndroid Build Coastguard Worker       if (_pathMode == NExtract::NPathMode::kNoPaths ||
1729*f6dc9357SAndroid Build Coastguard Worker           _pathMode == NExtract::NPathMode::kNoPathsAlt)
1730*f6dc9357SAndroid Build Coastguard Worker         numRemovePathParts = pathParts.Size() - 1;
1731*f6dc9357SAndroid Build Coastguard Worker       pathParts.DeleteFrontal(numRemovePathParts);
1732*f6dc9357SAndroid Build Coastguard Worker     }
1733*f6dc9357SAndroid Build Coastguard Worker   }
1734*f6dc9357SAndroid Build Coastguard Worker   else
1735*f6dc9357SAndroid Build Coastguard Worker   #endif // Z7_SFX
1736*f6dc9357SAndroid Build Coastguard Worker   {
1737*f6dc9357SAndroid Build Coastguard Worker     if (pathParts.IsEmpty())
1738*f6dc9357SAndroid Build Coastguard Worker     {
1739*f6dc9357SAndroid Build Coastguard Worker       if (_item.IsDir)
1740*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
1741*f6dc9357SAndroid Build Coastguard Worker       /*
1742*f6dc9357SAndroid Build Coastguard Worker       #ifdef SUPPORT_ALT_STREAMS
1743*f6dc9357SAndroid Build Coastguard Worker       if (!_item.IsAltStream)
1744*f6dc9357SAndroid Build Coastguard Worker       #endif
1745*f6dc9357SAndroid Build Coastguard Worker         return E_FAIL;
1746*f6dc9357SAndroid Build Coastguard Worker       */
1747*f6dc9357SAndroid Build Coastguard Worker     }
1748*f6dc9357SAndroid Build Coastguard Worker 
1749*f6dc9357SAndroid Build Coastguard Worker     unsigned numRemovePathParts = 0;
1750*f6dc9357SAndroid Build Coastguard Worker 
1751*f6dc9357SAndroid Build Coastguard Worker     switch ((int)_pathMode)
1752*f6dc9357SAndroid Build Coastguard Worker     {
1753*f6dc9357SAndroid Build Coastguard Worker       case NExtract::NPathMode::kFullPaths:
1754*f6dc9357SAndroid Build Coastguard Worker       case NExtract::NPathMode::kCurPaths:
1755*f6dc9357SAndroid Build Coastguard Worker       {
1756*f6dc9357SAndroid Build Coastguard Worker         if (_removePathParts.IsEmpty())
1757*f6dc9357SAndroid Build Coastguard Worker           break;
1758*f6dc9357SAndroid Build Coastguard Worker         bool badPrefix = false;
1759*f6dc9357SAndroid Build Coastguard Worker 
1760*f6dc9357SAndroid Build Coastguard Worker         if (pathParts.Size() < _removePathParts.Size())
1761*f6dc9357SAndroid Build Coastguard Worker           badPrefix = true;
1762*f6dc9357SAndroid Build Coastguard Worker         else
1763*f6dc9357SAndroid Build Coastguard Worker         {
1764*f6dc9357SAndroid Build Coastguard Worker           if (pathParts.Size() == _removePathParts.Size())
1765*f6dc9357SAndroid Build Coastguard Worker           {
1766*f6dc9357SAndroid Build Coastguard Worker             if (_removePartsForAltStreams)
1767*f6dc9357SAndroid Build Coastguard Worker             {
1768*f6dc9357SAndroid Build Coastguard Worker               #ifdef SUPPORT_ALT_STREAMS
1769*f6dc9357SAndroid Build Coastguard Worker               if (!_item.IsAltStream)
1770*f6dc9357SAndroid Build Coastguard Worker               #endif
1771*f6dc9357SAndroid Build Coastguard Worker                 badPrefix = true;
1772*f6dc9357SAndroid Build Coastguard Worker             }
1773*f6dc9357SAndroid Build Coastguard Worker             else
1774*f6dc9357SAndroid Build Coastguard Worker             {
1775*f6dc9357SAndroid Build Coastguard Worker               if (!_item.MainIsDir)
1776*f6dc9357SAndroid Build Coastguard Worker                 badPrefix = true;
1777*f6dc9357SAndroid Build Coastguard Worker             }
1778*f6dc9357SAndroid Build Coastguard Worker           }
1779*f6dc9357SAndroid Build Coastguard Worker 
1780*f6dc9357SAndroid Build Coastguard Worker           if (!badPrefix)
1781*f6dc9357SAndroid Build Coastguard Worker           FOR_VECTOR (i, _removePathParts)
1782*f6dc9357SAndroid Build Coastguard Worker           {
1783*f6dc9357SAndroid Build Coastguard Worker             if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0)
1784*f6dc9357SAndroid Build Coastguard Worker             {
1785*f6dc9357SAndroid Build Coastguard Worker               badPrefix = true;
1786*f6dc9357SAndroid Build Coastguard Worker               break;
1787*f6dc9357SAndroid Build Coastguard Worker             }
1788*f6dc9357SAndroid Build Coastguard Worker           }
1789*f6dc9357SAndroid Build Coastguard Worker         }
1790*f6dc9357SAndroid Build Coastguard Worker 
1791*f6dc9357SAndroid Build Coastguard Worker         if (badPrefix)
1792*f6dc9357SAndroid Build Coastguard Worker         {
1793*f6dc9357SAndroid Build Coastguard Worker           if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
1794*f6dc9357SAndroid Build Coastguard Worker             return E_FAIL;
1795*f6dc9357SAndroid Build Coastguard Worker         }
1796*f6dc9357SAndroid Build Coastguard Worker         else
1797*f6dc9357SAndroid Build Coastguard Worker         {
1798*f6dc9357SAndroid Build Coastguard Worker           numRemovePathParts = _removePathParts.Size();
1799*f6dc9357SAndroid Build Coastguard Worker           _some_pathParts_wereRemoved = true;
1800*f6dc9357SAndroid Build Coastguard Worker         }
1801*f6dc9357SAndroid Build Coastguard Worker         break;
1802*f6dc9357SAndroid Build Coastguard Worker       }
1803*f6dc9357SAndroid Build Coastguard Worker 
1804*f6dc9357SAndroid Build Coastguard Worker       case NExtract::NPathMode::kNoPaths:
1805*f6dc9357SAndroid Build Coastguard Worker       {
1806*f6dc9357SAndroid Build Coastguard Worker         if (!pathParts.IsEmpty())
1807*f6dc9357SAndroid Build Coastguard Worker           numRemovePathParts = pathParts.Size() - 1;
1808*f6dc9357SAndroid Build Coastguard Worker         break;
1809*f6dc9357SAndroid Build Coastguard Worker       }
1810*f6dc9357SAndroid Build Coastguard Worker       case NExtract::NPathMode::kNoPathsAlt:
1811*f6dc9357SAndroid Build Coastguard Worker       {
1812*f6dc9357SAndroid Build Coastguard Worker         #ifdef SUPPORT_ALT_STREAMS
1813*f6dc9357SAndroid Build Coastguard Worker         if (_item.IsAltStream)
1814*f6dc9357SAndroid Build Coastguard Worker           numRemovePathParts = pathParts.Size();
1815*f6dc9357SAndroid Build Coastguard Worker         else
1816*f6dc9357SAndroid Build Coastguard Worker         #endif
1817*f6dc9357SAndroid Build Coastguard Worker         if (!pathParts.IsEmpty())
1818*f6dc9357SAndroid Build Coastguard Worker           numRemovePathParts = pathParts.Size() - 1;
1819*f6dc9357SAndroid Build Coastguard Worker         break;
1820*f6dc9357SAndroid Build Coastguard Worker       }
1821*f6dc9357SAndroid Build Coastguard Worker       case NExtract::NPathMode::kAbsPaths:
1822*f6dc9357SAndroid Build Coastguard Worker       default:
1823*f6dc9357SAndroid Build Coastguard Worker         break;
1824*f6dc9357SAndroid Build Coastguard Worker     }
1825*f6dc9357SAndroid Build Coastguard Worker 
1826*f6dc9357SAndroid Build Coastguard Worker     pathParts.DeleteFrontal(numRemovePathParts);
1827*f6dc9357SAndroid Build Coastguard Worker   }
1828*f6dc9357SAndroid Build Coastguard Worker 
1829*f6dc9357SAndroid Build Coastguard Worker 
1830*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_SFX
1831*f6dc9357SAndroid Build Coastguard Worker 
1832*f6dc9357SAndroid Build Coastguard Worker   if (ExtractToStreamCallback)
1833*f6dc9357SAndroid Build Coastguard Worker   {
1834*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr2_Create<IGetProp, CGetProp> GetProp;
1835*f6dc9357SAndroid Build Coastguard Worker     GetProp->Arc = _arc;
1836*f6dc9357SAndroid Build Coastguard Worker     GetProp->IndexInArc = index;
1837*f6dc9357SAndroid Build Coastguard Worker     UString name (MakePathFromParts(pathParts));
1838*f6dc9357SAndroid Build Coastguard Worker     // GetProp->BaseName = name;
1839*f6dc9357SAndroid Build Coastguard Worker     #ifdef SUPPORT_ALT_STREAMS
1840*f6dc9357SAndroid Build Coastguard Worker     if (_item.IsAltStream)
1841*f6dc9357SAndroid Build Coastguard Worker     {
1842*f6dc9357SAndroid Build Coastguard Worker       if (!pathParts.IsEmpty() || (!_removePartsForAltStreams && _pathMode != NExtract::NPathMode::kNoPathsAlt))
1843*f6dc9357SAndroid Build Coastguard Worker         name.Add_Colon();
1844*f6dc9357SAndroid Build Coastguard Worker       name += _item.AltStreamName;
1845*f6dc9357SAndroid Build Coastguard Worker     }
1846*f6dc9357SAndroid Build Coastguard Worker     #endif
1847*f6dc9357SAndroid Build Coastguard Worker 
1848*f6dc9357SAndroid Build Coastguard Worker     return ExtractToStreamCallback->GetStream7(name, BoolToInt(_item.IsDir), outStream, askExtractMode, GetProp);
1849*f6dc9357SAndroid Build Coastguard Worker   }
1850*f6dc9357SAndroid Build Coastguard Worker 
1851*f6dc9357SAndroid Build Coastguard Worker   #endif // Z7_SFX
1852*f6dc9357SAndroid Build Coastguard Worker 
1853*f6dc9357SAndroid Build Coastguard Worker 
1854*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialOutStream> outStreamLoc;
1855*f6dc9357SAndroid Build Coastguard Worker 
1856*f6dc9357SAndroid Build Coastguard Worker   if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
1857*f6dc9357SAndroid Build Coastguard Worker   {
1858*f6dc9357SAndroid Build Coastguard Worker     if (_stdOutMode)
1859*f6dc9357SAndroid Build Coastguard Worker       outStreamLoc = new CStdOutFileStream;
1860*f6dc9357SAndroid Build Coastguard Worker     else
1861*f6dc9357SAndroid Build Coastguard Worker     {
1862*f6dc9357SAndroid Build Coastguard Worker       bool needExit = true;
1863*f6dc9357SAndroid Build Coastguard Worker       RINOK(GetExtractStream(outStreamLoc, needExit))
1864*f6dc9357SAndroid Build Coastguard Worker       if (needExit)
1865*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
1866*f6dc9357SAndroid Build Coastguard Worker     }
1867*f6dc9357SAndroid Build Coastguard Worker   }
1868*f6dc9357SAndroid Build Coastguard Worker 
1869*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_SFX
1870*f6dc9357SAndroid Build Coastguard Worker   if (_hashStream)
1871*f6dc9357SAndroid Build Coastguard Worker   {
1872*f6dc9357SAndroid Build Coastguard Worker     if (askExtractMode == NArchive::NExtract::NAskMode::kExtract ||
1873*f6dc9357SAndroid Build Coastguard Worker         askExtractMode == NArchive::NExtract::NAskMode::kTest)
1874*f6dc9357SAndroid Build Coastguard Worker     {
1875*f6dc9357SAndroid Build Coastguard Worker       _hashStreamSpec->SetStream(outStreamLoc);
1876*f6dc9357SAndroid Build Coastguard Worker       outStreamLoc = _hashStream;
1877*f6dc9357SAndroid Build Coastguard Worker       _hashStreamSpec->Init(true);
1878*f6dc9357SAndroid Build Coastguard Worker       _hashStreamWasUsed = true;
1879*f6dc9357SAndroid Build Coastguard Worker     }
1880*f6dc9357SAndroid Build Coastguard Worker   }
1881*f6dc9357SAndroid Build Coastguard Worker   #endif // Z7_SFX
1882*f6dc9357SAndroid Build Coastguard Worker 
1883*f6dc9357SAndroid Build Coastguard Worker   if (outStreamLoc)
1884*f6dc9357SAndroid Build Coastguard Worker   {
1885*f6dc9357SAndroid Build Coastguard Worker     /*
1886*f6dc9357SAndroid Build Coastguard Worker     #ifdef SUPPORT_LINKS
1887*f6dc9357SAndroid Build Coastguard Worker     if (!_copyFile_Path.IsEmpty())
1888*f6dc9357SAndroid Build Coastguard Worker     {
1889*f6dc9357SAndroid Build Coastguard Worker       RINOK(PrepareOperation(askExtractMode));
1890*f6dc9357SAndroid Build Coastguard Worker       RINOK(MyCopyFile(outStreamLoc));
1891*f6dc9357SAndroid Build Coastguard Worker       return SetOperationResult(NArchive::NExtract::NOperationResult::kOK);
1892*f6dc9357SAndroid Build Coastguard Worker     }
1893*f6dc9357SAndroid Build Coastguard Worker     if (_link.isCopyLink && _testMode)
1894*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1895*f6dc9357SAndroid Build Coastguard Worker     #endif
1896*f6dc9357SAndroid Build Coastguard Worker     */
1897*f6dc9357SAndroid Build Coastguard Worker     *outStream = outStreamLoc.Detach();
1898*f6dc9357SAndroid Build Coastguard Worker   }
1899*f6dc9357SAndroid Build Coastguard Worker 
1900*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1901*f6dc9357SAndroid Build Coastguard Worker 
1902*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
1903*f6dc9357SAndroid Build Coastguard Worker }
1904*f6dc9357SAndroid Build Coastguard Worker 
1905*f6dc9357SAndroid Build Coastguard Worker 
1906*f6dc9357SAndroid Build Coastguard Worker 
1907*f6dc9357SAndroid Build Coastguard Worker 
1908*f6dc9357SAndroid Build Coastguard Worker 
1909*f6dc9357SAndroid Build Coastguard Worker 
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 Z7_COM7F_IMF(CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode))
1916*f6dc9357SAndroid Build Coastguard Worker {
1917*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
1918*f6dc9357SAndroid Build Coastguard Worker 
1919*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_SFX
1920*f6dc9357SAndroid Build Coastguard Worker   // if (!_op_WasReported)
1921*f6dc9357SAndroid Build Coastguard Worker   if (ExtractToStreamCallback)
1922*f6dc9357SAndroid Build Coastguard Worker     return ExtractToStreamCallback->PrepareOperation7(askExtractMode);
1923*f6dc9357SAndroid Build Coastguard Worker   #endif
1924*f6dc9357SAndroid Build Coastguard Worker 
1925*f6dc9357SAndroid Build Coastguard Worker   _extractMode = false;
1926*f6dc9357SAndroid Build Coastguard Worker 
1927*f6dc9357SAndroid Build Coastguard Worker   switch (askExtractMode)
1928*f6dc9357SAndroid Build Coastguard Worker   {
1929*f6dc9357SAndroid Build Coastguard Worker     case NArchive::NExtract::NAskMode::kExtract:
1930*f6dc9357SAndroid Build Coastguard Worker       if (_testMode)
1931*f6dc9357SAndroid Build Coastguard Worker         askExtractMode = NArchive::NExtract::NAskMode::kTest;
1932*f6dc9357SAndroid Build Coastguard Worker       else
1933*f6dc9357SAndroid Build Coastguard Worker         _extractMode = true;
1934*f6dc9357SAndroid Build Coastguard Worker       break;
1935*f6dc9357SAndroid Build Coastguard Worker     default: break;
1936*f6dc9357SAndroid Build Coastguard Worker   }
1937*f6dc9357SAndroid Build Coastguard Worker 
1938*f6dc9357SAndroid Build Coastguard Worker   // if (_op_WasReported) return S_OK;
1939*f6dc9357SAndroid Build Coastguard Worker 
1940*f6dc9357SAndroid Build Coastguard Worker   return _extractCallback2->PrepareOperation(_item.Path, BoolToInt(_item.IsDir),
1941*f6dc9357SAndroid Build Coastguard Worker       askExtractMode, _isSplit ? &_position: NULL);
1942*f6dc9357SAndroid Build Coastguard Worker 
1943*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
1944*f6dc9357SAndroid Build Coastguard Worker }
1945*f6dc9357SAndroid Build Coastguard Worker 
1946*f6dc9357SAndroid Build Coastguard Worker 
1947*f6dc9357SAndroid Build Coastguard Worker 
1948*f6dc9357SAndroid Build Coastguard Worker 
1949*f6dc9357SAndroid Build Coastguard Worker 
1950*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::CloseFile()
1951*f6dc9357SAndroid Build Coastguard Worker {
1952*f6dc9357SAndroid Build Coastguard Worker   if (!_outFileStream)
1953*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1954*f6dc9357SAndroid Build Coastguard Worker 
1955*f6dc9357SAndroid Build Coastguard Worker   HRESULT hres = S_OK;
1956*f6dc9357SAndroid Build Coastguard Worker 
1957*f6dc9357SAndroid Build Coastguard Worker   const UInt64 processedSize = _outFileStreamSpec->ProcessedSize;
1958*f6dc9357SAndroid Build Coastguard Worker   if (_fileLength_WasSet && _fileLength_that_WasSet > processedSize)
1959*f6dc9357SAndroid Build Coastguard Worker   {
1960*f6dc9357SAndroid Build Coastguard Worker     const bool res = _outFileStreamSpec->File.SetLength(processedSize);
1961*f6dc9357SAndroid Build Coastguard Worker     _fileLength_WasSet = res;
1962*f6dc9357SAndroid Build Coastguard Worker     if (!res)
1963*f6dc9357SAndroid Build Coastguard Worker     {
1964*f6dc9357SAndroid Build Coastguard Worker       const HRESULT hres2 = SendMessageError_with_LastError(kCantSetFileLen, us2fs(_item.Path));
1965*f6dc9357SAndroid Build Coastguard Worker       if (hres == S_OK)
1966*f6dc9357SAndroid Build Coastguard Worker         hres = hres2;
1967*f6dc9357SAndroid Build Coastguard Worker     }
1968*f6dc9357SAndroid Build Coastguard Worker   }
1969*f6dc9357SAndroid Build Coastguard Worker 
1970*f6dc9357SAndroid Build Coastguard Worker   _curSize = processedSize;
1971*f6dc9357SAndroid Build Coastguard Worker   _curSize_Defined = true;
1972*f6dc9357SAndroid Build Coastguard Worker 
1973*f6dc9357SAndroid Build Coastguard Worker  #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
1974*f6dc9357SAndroid Build Coastguard Worker   if (ZoneBuf.Size() != 0
1975*f6dc9357SAndroid Build Coastguard Worker       && !_item.IsAltStream)
1976*f6dc9357SAndroid Build Coastguard Worker   {
1977*f6dc9357SAndroid Build Coastguard Worker     // if (NFind::DoesFileExist_Raw(tempFilePath))
1978*f6dc9357SAndroid Build Coastguard Worker     if (ZoneMode != NExtract::NZoneIdMode::kOffice ||
1979*f6dc9357SAndroid Build Coastguard Worker         FindExt2(kOfficeExtensions, fs2us(_diskFilePath)))
1980*f6dc9357SAndroid Build Coastguard Worker     {
1981*f6dc9357SAndroid Build Coastguard Worker       // we must write zone file before setting of timestamps
1982*f6dc9357SAndroid Build Coastguard Worker       if (!WriteZoneFile_To_BaseFile(_diskFilePath, ZoneBuf))
1983*f6dc9357SAndroid Build Coastguard Worker       {
1984*f6dc9357SAndroid Build Coastguard Worker         // we can't write it in FAT
1985*f6dc9357SAndroid Build Coastguard Worker         // SendMessageError_with_LastError("Can't write Zone.Identifier stream", path);
1986*f6dc9357SAndroid Build Coastguard Worker       }
1987*f6dc9357SAndroid Build Coastguard Worker     }
1988*f6dc9357SAndroid Build Coastguard Worker   }
1989*f6dc9357SAndroid Build Coastguard Worker  #endif
1990*f6dc9357SAndroid Build Coastguard Worker 
1991*f6dc9357SAndroid Build Coastguard Worker   CFiTimesCAM t;
1992*f6dc9357SAndroid Build Coastguard Worker   GetFiTimesCAM(t);
1993*f6dc9357SAndroid Build Coastguard Worker 
1994*f6dc9357SAndroid Build Coastguard Worker   // #ifdef _WIN32
1995*f6dc9357SAndroid Build Coastguard Worker   if (t.IsSomeTimeDefined())
1996*f6dc9357SAndroid Build Coastguard Worker     _outFileStreamSpec->SetTime(
1997*f6dc9357SAndroid Build Coastguard Worker         t.CTime_Defined ? &t.CTime : NULL,
1998*f6dc9357SAndroid Build Coastguard Worker         t.ATime_Defined ? &t.ATime : NULL,
1999*f6dc9357SAndroid Build Coastguard Worker         t.MTime_Defined ? &t.MTime : NULL);
2000*f6dc9357SAndroid Build Coastguard Worker   // #endif
2001*f6dc9357SAndroid Build Coastguard Worker 
2002*f6dc9357SAndroid Build Coastguard Worker   RINOK(_outFileStreamSpec->Close())
2003*f6dc9357SAndroid Build Coastguard Worker   _outFileStream.Release();
2004*f6dc9357SAndroid Build Coastguard Worker 
2005*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(UNDER_CE)
2006*f6dc9357SAndroid Build Coastguard Worker   if (!_altStream_NeedRestore_Attrib_for_parentFsPath.IsEmpty())
2007*f6dc9357SAndroid Build Coastguard Worker   {
2008*f6dc9357SAndroid Build Coastguard Worker     SetFileAttrib(_altStream_NeedRestore_Attrib_for_parentFsPath, _altStream_NeedRestore_AttribVal);
2009*f6dc9357SAndroid Build Coastguard Worker     _altStream_NeedRestore_Attrib_for_parentFsPath.Empty();
2010*f6dc9357SAndroid Build Coastguard Worker   }
2011*f6dc9357SAndroid Build Coastguard Worker #endif
2012*f6dc9357SAndroid Build Coastguard Worker 
2013*f6dc9357SAndroid Build Coastguard Worker   return hres;
2014*f6dc9357SAndroid Build Coastguard Worker }
2015*f6dc9357SAndroid Build Coastguard Worker 
2016*f6dc9357SAndroid Build Coastguard Worker 
2017*f6dc9357SAndroid Build Coastguard Worker #ifdef SUPPORT_LINKS
2018*f6dc9357SAndroid Build Coastguard Worker 
2019*f6dc9357SAndroid Build Coastguard Worker 
2020*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::SetFromLinkPath(
2021*f6dc9357SAndroid Build Coastguard Worker     const FString &fullProcessedPath,
2022*f6dc9357SAndroid Build Coastguard Worker     const CLinkInfo &linkInfo,
2023*f6dc9357SAndroid Build Coastguard Worker     bool &linkWasSet)
2024*f6dc9357SAndroid Build Coastguard Worker {
2025*f6dc9357SAndroid Build Coastguard Worker   linkWasSet = false;
2026*f6dc9357SAndroid Build Coastguard Worker   if (!_ntOptions.SymLinks.Val && !linkInfo.isHardLink)
2027*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
2028*f6dc9357SAndroid Build Coastguard Worker 
2029*f6dc9357SAndroid Build Coastguard Worker   UString relatPath;
2030*f6dc9357SAndroid Build Coastguard Worker 
2031*f6dc9357SAndroid Build Coastguard Worker   /* if (linkInfo.isRelative)
2032*f6dc9357SAndroid Build Coastguard Worker        linkInfo.linkPath is final link path that must be stored to file link field
2033*f6dc9357SAndroid Build Coastguard Worker      else
2034*f6dc9357SAndroid Build Coastguard Worker        linkInfo.linkPath is path from root of archive. So we must add _dirPathPrefix_Full before linkPath.
2035*f6dc9357SAndroid Build Coastguard Worker   */
2036*f6dc9357SAndroid Build Coastguard Worker 
2037*f6dc9357SAndroid Build Coastguard Worker   if (linkInfo.isRelative)
2038*f6dc9357SAndroid Build Coastguard Worker     relatPath = GetDirPrefixOf(_item.Path);
2039*f6dc9357SAndroid Build Coastguard Worker   relatPath += linkInfo.linkPath;
2040*f6dc9357SAndroid Build Coastguard Worker 
2041*f6dc9357SAndroid Build Coastguard Worker   if (!IsSafePath(relatPath))
2042*f6dc9357SAndroid Build Coastguard Worker   {
2043*f6dc9357SAndroid Build Coastguard Worker     return SendMessageError2(
2044*f6dc9357SAndroid Build Coastguard Worker           0, // errorCode
2045*f6dc9357SAndroid Build Coastguard Worker           "Dangerous link path was ignored",
2046*f6dc9357SAndroid Build Coastguard Worker           us2fs(_item.Path),
2047*f6dc9357SAndroid Build Coastguard Worker           us2fs(linkInfo.linkPath)); // us2fs(relatPath)
2048*f6dc9357SAndroid Build Coastguard Worker   }
2049*f6dc9357SAndroid Build Coastguard Worker 
2050*f6dc9357SAndroid Build Coastguard Worker   FString existPath;
2051*f6dc9357SAndroid Build Coastguard Worker   if (linkInfo.isHardLink /* || linkInfo.IsCopyLink */ || !linkInfo.isRelative)
2052*f6dc9357SAndroid Build Coastguard Worker   {
2053*f6dc9357SAndroid Build Coastguard Worker     if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath))
2054*f6dc9357SAndroid Build Coastguard Worker     {
2055*f6dc9357SAndroid Build Coastguard Worker       RINOK(SendMessageError("Incorrect path", us2fs(relatPath)))
2056*f6dc9357SAndroid Build Coastguard Worker     }
2057*f6dc9357SAndroid Build Coastguard Worker   }
2058*f6dc9357SAndroid Build Coastguard Worker   else
2059*f6dc9357SAndroid Build Coastguard Worker   {
2060*f6dc9357SAndroid Build Coastguard Worker     existPath = us2fs(linkInfo.linkPath);
2061*f6dc9357SAndroid Build Coastguard Worker     // printf("\nlinkPath = : %s\n", GetOemString(linkInfo.linkPath).Ptr());
2062*f6dc9357SAndroid Build Coastguard Worker   }
2063*f6dc9357SAndroid Build Coastguard Worker 
2064*f6dc9357SAndroid Build Coastguard Worker   if (existPath.IsEmpty())
2065*f6dc9357SAndroid Build Coastguard Worker     return SendMessageError("Empty link", fullProcessedPath);
2066*f6dc9357SAndroid Build Coastguard Worker 
2067*f6dc9357SAndroid Build Coastguard Worker   if (linkInfo.isHardLink /* || linkInfo.IsCopyLink */)
2068*f6dc9357SAndroid Build Coastguard Worker   {
2069*f6dc9357SAndroid Build Coastguard Worker     // if (linkInfo.isHardLink)
2070*f6dc9357SAndroid Build Coastguard Worker     {
2071*f6dc9357SAndroid Build Coastguard Worker       if (!MyCreateHardLink(fullProcessedPath, existPath))
2072*f6dc9357SAndroid Build Coastguard Worker       {
2073*f6dc9357SAndroid Build Coastguard Worker         const HRESULT errorCode = GetLastError_noZero_HRESULT();
2074*f6dc9357SAndroid Build Coastguard Worker         RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, existPath))
2075*f6dc9357SAndroid Build Coastguard Worker       }
2076*f6dc9357SAndroid Build Coastguard Worker       /*
2077*f6dc9357SAndroid Build Coastguard Worker       RINOK(PrepareOperation(NArchive::NExtract::NAskMode::kExtract))
2078*f6dc9357SAndroid Build Coastguard Worker       _op_WasReported = true;
2079*f6dc9357SAndroid Build Coastguard Worker       RINOK(SetOperationResult(NArchive::NExtract::NOperationResult::kOK))
2080*f6dc9357SAndroid Build Coastguard Worker       */
2081*f6dc9357SAndroid Build Coastguard Worker       linkWasSet = true;
2082*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
2083*f6dc9357SAndroid Build Coastguard Worker     }
2084*f6dc9357SAndroid Build Coastguard Worker     /*
2085*f6dc9357SAndroid Build Coastguard Worker     // IsCopyLink
2086*f6dc9357SAndroid Build Coastguard Worker     {
2087*f6dc9357SAndroid Build Coastguard Worker       NFind::CFileInfo fi;
2088*f6dc9357SAndroid Build Coastguard Worker       if (!fi.Find(existPath))
2089*f6dc9357SAndroid Build Coastguard Worker       {
2090*f6dc9357SAndroid Build Coastguard Worker         RINOK(SendMessageError2("Cannot find the file for copying", existPath, fullProcessedPath));
2091*f6dc9357SAndroid Build Coastguard Worker       }
2092*f6dc9357SAndroid Build Coastguard Worker       else
2093*f6dc9357SAndroid Build Coastguard Worker       {
2094*f6dc9357SAndroid Build Coastguard Worker         if (_curSize_Defined && _curSize == fi.Size)
2095*f6dc9357SAndroid Build Coastguard Worker           _copyFile_Path = existPath;
2096*f6dc9357SAndroid Build Coastguard Worker         else
2097*f6dc9357SAndroid Build Coastguard Worker         {
2098*f6dc9357SAndroid Build Coastguard Worker           RINOK(SendMessageError2("File size collision for file copying", existPath, fullProcessedPath));
2099*f6dc9357SAndroid Build Coastguard Worker         }
2100*f6dc9357SAndroid Build Coastguard Worker         // RINOK(MyCopyFile(existPath, fullProcessedPath));
2101*f6dc9357SAndroid Build Coastguard Worker       }
2102*f6dc9357SAndroid Build Coastguard Worker     }
2103*f6dc9357SAndroid Build Coastguard Worker     */
2104*f6dc9357SAndroid Build Coastguard Worker   }
2105*f6dc9357SAndroid Build Coastguard Worker 
2106*f6dc9357SAndroid Build Coastguard Worker   // is Symbolic link
2107*f6dc9357SAndroid Build Coastguard Worker 
2108*f6dc9357SAndroid Build Coastguard Worker   /*
2109*f6dc9357SAndroid Build Coastguard Worker   if (_item.IsDir && !isRelative)
2110*f6dc9357SAndroid Build Coastguard Worker   {
2111*f6dc9357SAndroid Build Coastguard Worker     // Windows before Vista doesn't support symbolic links.
2112*f6dc9357SAndroid Build Coastguard Worker     // we could convert such symbolic links to Junction Points
2113*f6dc9357SAndroid Build Coastguard Worker     // isJunction = true;
2114*f6dc9357SAndroid Build Coastguard Worker     // convertToAbs = true;
2115*f6dc9357SAndroid Build Coastguard Worker   }
2116*f6dc9357SAndroid Build Coastguard Worker   */
2117*f6dc9357SAndroid Build Coastguard Worker 
2118*f6dc9357SAndroid Build Coastguard Worker   if (!_ntOptions.SymLinks_AllowDangerous.Val)
2119*f6dc9357SAndroid Build Coastguard Worker   {
2120*f6dc9357SAndroid Build Coastguard Worker     #ifdef _WIN32
2121*f6dc9357SAndroid Build Coastguard Worker     if (_item.IsDir)
2122*f6dc9357SAndroid Build Coastguard Worker     #endif
2123*f6dc9357SAndroid Build Coastguard Worker     if (linkInfo.isRelative)
2124*f6dc9357SAndroid Build Coastguard Worker       {
2125*f6dc9357SAndroid Build Coastguard Worker         CLinkLevelsInfo levelsInfo;
2126*f6dc9357SAndroid Build Coastguard Worker         levelsInfo.Parse(linkInfo.linkPath);
2127*f6dc9357SAndroid Build Coastguard Worker         if (levelsInfo.FinalLevel < 1 || levelsInfo.IsAbsolute)
2128*f6dc9357SAndroid Build Coastguard Worker         {
2129*f6dc9357SAndroid Build Coastguard Worker           return SendMessageError2(
2130*f6dc9357SAndroid Build Coastguard Worker             0, // errorCode
2131*f6dc9357SAndroid Build Coastguard Worker             "Dangerous symbolic link path was ignored",
2132*f6dc9357SAndroid Build Coastguard Worker             us2fs(_item.Path),
2133*f6dc9357SAndroid Build Coastguard Worker             us2fs(linkInfo.linkPath));
2134*f6dc9357SAndroid Build Coastguard Worker         }
2135*f6dc9357SAndroid Build Coastguard Worker       }
2136*f6dc9357SAndroid Build Coastguard Worker   }
2137*f6dc9357SAndroid Build Coastguard Worker 
2138*f6dc9357SAndroid Build Coastguard Worker 
2139*f6dc9357SAndroid Build Coastguard Worker   #ifdef _WIN32
2140*f6dc9357SAndroid Build Coastguard Worker 
2141*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer data;
2142*f6dc9357SAndroid Build Coastguard Worker   // printf("\nFillLinkData(): %s\n", GetOemString(existPath).Ptr());
2143*f6dc9357SAndroid Build Coastguard Worker   if (!FillLinkData(data, fs2us(existPath), !linkInfo.isJunction, linkInfo.isWSL))
2144*f6dc9357SAndroid Build Coastguard Worker     return SendMessageError("Cannot fill link data", us2fs(_item.Path));
2145*f6dc9357SAndroid Build Coastguard Worker 
2146*f6dc9357SAndroid Build Coastguard Worker   /*
2147*f6dc9357SAndroid Build Coastguard Worker   if (NtReparse_Size != data.Size() || memcmp(NtReparse_Data, data, data.Size()) != 0)
2148*f6dc9357SAndroid Build Coastguard Worker   {
2149*f6dc9357SAndroid Build Coastguard Worker     SendMessageError("reconstructed Reparse is different", fs2us(existPath));
2150*f6dc9357SAndroid Build Coastguard Worker   }
2151*f6dc9357SAndroid Build Coastguard Worker   */
2152*f6dc9357SAndroid Build Coastguard Worker 
2153*f6dc9357SAndroid Build Coastguard Worker   CReparseAttr attr;
2154*f6dc9357SAndroid Build Coastguard Worker   if (!attr.Parse(data, data.Size()))
2155*f6dc9357SAndroid Build Coastguard Worker   {
2156*f6dc9357SAndroid Build Coastguard Worker     RINOK(SendMessageError("Internal error for symbolic link file", us2fs(_item.Path)))
2157*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
2158*f6dc9357SAndroid Build Coastguard Worker   }
2159*f6dc9357SAndroid Build Coastguard Worker   if (!NFile::NIO::SetReparseData(fullProcessedPath, _item.IsDir, data, (DWORD)data.Size()))
2160*f6dc9357SAndroid Build Coastguard Worker   {
2161*f6dc9357SAndroid Build Coastguard Worker     RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath))
2162*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
2163*f6dc9357SAndroid Build Coastguard Worker   }
2164*f6dc9357SAndroid Build Coastguard Worker   linkWasSet = true;
2165*f6dc9357SAndroid Build Coastguard Worker 
2166*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
2167*f6dc9357SAndroid Build Coastguard Worker 
2168*f6dc9357SAndroid Build Coastguard Worker 
2169*f6dc9357SAndroid Build Coastguard Worker   #else // ! _WIN32
2170*f6dc9357SAndroid Build Coastguard Worker 
2171*f6dc9357SAndroid Build Coastguard Worker   if (!NFile::NIO::SetSymLink(fullProcessedPath, existPath))
2172*f6dc9357SAndroid Build Coastguard Worker   {
2173*f6dc9357SAndroid Build Coastguard Worker     RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath))
2174*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
2175*f6dc9357SAndroid Build Coastguard Worker   }
2176*f6dc9357SAndroid Build Coastguard Worker   linkWasSet = true;
2177*f6dc9357SAndroid Build Coastguard Worker 
2178*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
2179*f6dc9357SAndroid Build Coastguard Worker 
2180*f6dc9357SAndroid Build Coastguard Worker   #endif // ! _WIN32
2181*f6dc9357SAndroid Build Coastguard Worker }
2182*f6dc9357SAndroid Build Coastguard Worker 
2183*f6dc9357SAndroid Build Coastguard Worker 
2184*f6dc9357SAndroid Build Coastguard Worker bool CLinkInfo::Parse(const Byte *data, size_t dataSize, bool isLinuxData)
2185*f6dc9357SAndroid Build Coastguard Worker {
2186*f6dc9357SAndroid Build Coastguard Worker   Clear();
2187*f6dc9357SAndroid Build Coastguard Worker   // this->isLinux = isLinuxData;
2188*f6dc9357SAndroid Build Coastguard Worker 
2189*f6dc9357SAndroid Build Coastguard Worker   if (isLinuxData)
2190*f6dc9357SAndroid Build Coastguard Worker   {
2191*f6dc9357SAndroid Build Coastguard Worker     isJunction = false;
2192*f6dc9357SAndroid Build Coastguard Worker     isHardLink = false;
2193*f6dc9357SAndroid Build Coastguard Worker     AString utf;
2194*f6dc9357SAndroid Build Coastguard Worker     if (dataSize >= (1 << 12))
2195*f6dc9357SAndroid Build Coastguard Worker       return false;
2196*f6dc9357SAndroid Build Coastguard Worker     utf.SetFrom_CalcLen((const char *)data, (unsigned)dataSize);
2197*f6dc9357SAndroid Build Coastguard Worker     UString u;
2198*f6dc9357SAndroid Build Coastguard Worker     if (!ConvertUTF8ToUnicode(utf, u))
2199*f6dc9357SAndroid Build Coastguard Worker       return false;
2200*f6dc9357SAndroid Build Coastguard Worker     linkPath = u;
2201*f6dc9357SAndroid Build Coastguard Worker 
2202*f6dc9357SAndroid Build Coastguard Worker     // in linux symbolic data: we expect that linux separator '/' is used
2203*f6dc9357SAndroid Build Coastguard Worker     // if windows link was created, then we also must use linux separator
2204*f6dc9357SAndroid Build Coastguard Worker     if (u.IsEmpty())
2205*f6dc9357SAndroid Build Coastguard Worker       return false;
2206*f6dc9357SAndroid Build Coastguard Worker     const wchar_t c = u[0];
2207*f6dc9357SAndroid Build Coastguard Worker     isRelative = !IS_PATH_SEPAR(c);
2208*f6dc9357SAndroid Build Coastguard Worker     return true;
2209*f6dc9357SAndroid Build Coastguard Worker   }
2210*f6dc9357SAndroid Build Coastguard Worker 
2211*f6dc9357SAndroid Build Coastguard Worker   CReparseAttr reparse;
2212*f6dc9357SAndroid Build Coastguard Worker   if (!reparse.Parse(data, dataSize))
2213*f6dc9357SAndroid Build Coastguard Worker     return false;
2214*f6dc9357SAndroid Build Coastguard Worker   isHardLink = false;
2215*f6dc9357SAndroid Build Coastguard Worker   // isCopyLink = false;
2216*f6dc9357SAndroid Build Coastguard Worker   linkPath = reparse.GetPath();
2217*f6dc9357SAndroid Build Coastguard Worker   isJunction = reparse.IsMountPoint();
2218*f6dc9357SAndroid Build Coastguard Worker 
2219*f6dc9357SAndroid Build Coastguard Worker   if (reparse.IsSymLink_WSL())
2220*f6dc9357SAndroid Build Coastguard Worker   {
2221*f6dc9357SAndroid Build Coastguard Worker     isWSL = true;
2222*f6dc9357SAndroid Build Coastguard Worker     isRelative = reparse.IsRelative_WSL();
2223*f6dc9357SAndroid Build Coastguard Worker   }
2224*f6dc9357SAndroid Build Coastguard Worker   else
2225*f6dc9357SAndroid Build Coastguard Worker     isRelative = reparse.IsRelative_Win();
2226*f6dc9357SAndroid Build Coastguard Worker 
2227*f6dc9357SAndroid Build Coastguard Worker   // FIXME !!!
2228*f6dc9357SAndroid Build Coastguard Worker   #ifndef _WIN32
2229*f6dc9357SAndroid Build Coastguard Worker   linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR);
2230*f6dc9357SAndroid Build Coastguard Worker   #endif
2231*f6dc9357SAndroid Build Coastguard Worker 
2232*f6dc9357SAndroid Build Coastguard Worker   return true;
2233*f6dc9357SAndroid Build Coastguard Worker }
2234*f6dc9357SAndroid Build Coastguard Worker 
2235*f6dc9357SAndroid Build Coastguard Worker #endif // SUPPORT_LINKS
2236*f6dc9357SAndroid Build Coastguard Worker 
2237*f6dc9357SAndroid Build Coastguard Worker 
2238*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::CloseReparseAndFile()
2239*f6dc9357SAndroid Build Coastguard Worker {
2240*f6dc9357SAndroid Build Coastguard Worker   HRESULT res = S_OK;
2241*f6dc9357SAndroid Build Coastguard Worker 
2242*f6dc9357SAndroid Build Coastguard Worker   #ifdef SUPPORT_LINKS
2243*f6dc9357SAndroid Build Coastguard Worker 
2244*f6dc9357SAndroid Build Coastguard Worker   size_t reparseSize = 0;
2245*f6dc9357SAndroid Build Coastguard Worker   bool repraseMode = false;
2246*f6dc9357SAndroid Build Coastguard Worker   bool needSetReparse = false;
2247*f6dc9357SAndroid Build Coastguard Worker   CLinkInfo linkInfo;
2248*f6dc9357SAndroid Build Coastguard Worker 
2249*f6dc9357SAndroid Build Coastguard Worker   if (_bufPtrSeqOutStream)
2250*f6dc9357SAndroid Build Coastguard Worker   {
2251*f6dc9357SAndroid Build Coastguard Worker     repraseMode = true;
2252*f6dc9357SAndroid Build Coastguard Worker     reparseSize = _bufPtrSeqOutStream_Spec->GetPos();
2253*f6dc9357SAndroid Build Coastguard Worker     if (_curSize_Defined && reparseSize == _outMemBuf.Size())
2254*f6dc9357SAndroid Build Coastguard Worker     {
2255*f6dc9357SAndroid Build Coastguard Worker       /*
2256*f6dc9357SAndroid Build Coastguard Worker       CReparseAttr reparse;
2257*f6dc9357SAndroid Build Coastguard Worker       DWORD errorCode = 0;
2258*f6dc9357SAndroid Build Coastguard Worker       needSetReparse = reparse.Parse(_outMemBuf, reparseSize, errorCode);
2259*f6dc9357SAndroid Build Coastguard Worker       if (needSetReparse)
2260*f6dc9357SAndroid Build Coastguard Worker       {
2261*f6dc9357SAndroid Build Coastguard Worker         UString linkPath = reparse.GetPath();
2262*f6dc9357SAndroid Build Coastguard Worker         #ifndef _WIN32
2263*f6dc9357SAndroid Build Coastguard Worker         linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR);
2264*f6dc9357SAndroid Build Coastguard Worker         #endif
2265*f6dc9357SAndroid Build Coastguard Worker       }
2266*f6dc9357SAndroid Build Coastguard Worker       */
2267*f6dc9357SAndroid Build Coastguard Worker       needSetReparse = linkInfo.Parse(_outMemBuf, reparseSize, _is_SymLink_in_Data_Linux);
2268*f6dc9357SAndroid Build Coastguard Worker       if (!needSetReparse)
2269*f6dc9357SAndroid Build Coastguard Worker         res = SendMessageError_with_LastError("Incorrect reparse stream", us2fs(_item.Path));
2270*f6dc9357SAndroid Build Coastguard Worker     }
2271*f6dc9357SAndroid Build Coastguard Worker     else
2272*f6dc9357SAndroid Build Coastguard Worker     {
2273*f6dc9357SAndroid Build Coastguard Worker       res = SendMessageError_with_LastError("Unknown reparse stream", us2fs(_item.Path));
2274*f6dc9357SAndroid Build Coastguard Worker     }
2275*f6dc9357SAndroid Build Coastguard Worker     if (!needSetReparse && _outFileStream)
2276*f6dc9357SAndroid Build Coastguard Worker     {
2277*f6dc9357SAndroid Build Coastguard Worker       const HRESULT res2 = WriteStream(_outFileStream, _outMemBuf, reparseSize);
2278*f6dc9357SAndroid Build Coastguard Worker       if (res == S_OK)
2279*f6dc9357SAndroid Build Coastguard Worker         res = res2;
2280*f6dc9357SAndroid Build Coastguard Worker     }
2281*f6dc9357SAndroid Build Coastguard Worker     _bufPtrSeqOutStream.Release();
2282*f6dc9357SAndroid Build Coastguard Worker   }
2283*f6dc9357SAndroid Build Coastguard Worker 
2284*f6dc9357SAndroid Build Coastguard Worker   #endif // SUPPORT_LINKS
2285*f6dc9357SAndroid Build Coastguard Worker 
2286*f6dc9357SAndroid Build Coastguard Worker 
2287*f6dc9357SAndroid Build Coastguard Worker   const HRESULT res2 = CloseFile();
2288*f6dc9357SAndroid Build Coastguard Worker 
2289*f6dc9357SAndroid Build Coastguard Worker   if (res == S_OK)
2290*f6dc9357SAndroid Build Coastguard Worker     res = res2;
2291*f6dc9357SAndroid Build Coastguard Worker 
2292*f6dc9357SAndroid Build Coastguard Worker   RINOK(res)
2293*f6dc9357SAndroid Build Coastguard Worker 
2294*f6dc9357SAndroid Build Coastguard Worker   #ifdef SUPPORT_LINKS
2295*f6dc9357SAndroid Build Coastguard Worker   if (repraseMode)
2296*f6dc9357SAndroid Build Coastguard Worker   {
2297*f6dc9357SAndroid Build Coastguard Worker     _curSize = reparseSize;
2298*f6dc9357SAndroid Build Coastguard Worker     _curSize_Defined = true;
2299*f6dc9357SAndroid Build Coastguard Worker 
2300*f6dc9357SAndroid Build Coastguard Worker     #ifdef SUPPORT_LINKS
2301*f6dc9357SAndroid Build Coastguard Worker     if (needSetReparse)
2302*f6dc9357SAndroid Build Coastguard Worker     {
2303*f6dc9357SAndroid Build Coastguard Worker       // in Linux   : we must delete empty file before symbolic link creation
2304*f6dc9357SAndroid Build Coastguard Worker       // in Windows : we can create symbolic link even without file deleting
2305*f6dc9357SAndroid Build Coastguard Worker       if (!DeleteFileAlways(_diskFilePath))
2306*f6dc9357SAndroid Build Coastguard Worker       {
2307*f6dc9357SAndroid Build Coastguard Worker         RINOK(SendMessageError_with_LastError("can't delete file", _diskFilePath))
2308*f6dc9357SAndroid Build Coastguard Worker       }
2309*f6dc9357SAndroid Build Coastguard Worker       {
2310*f6dc9357SAndroid Build Coastguard Worker         /*
2311*f6dc9357SAndroid Build Coastguard Worker         // for DEBUG ONLY: we can extract sym links as WSL links
2312*f6dc9357SAndroid Build Coastguard Worker         // to eliminate (non-admin) errors for sym links.
2313*f6dc9357SAndroid Build Coastguard Worker         #ifdef _WIN32
2314*f6dc9357SAndroid Build Coastguard Worker         if (!linkInfo.isHardLink && !linkInfo.isJunction)
2315*f6dc9357SAndroid Build Coastguard Worker           linkInfo.isWSL = true;
2316*f6dc9357SAndroid Build Coastguard Worker         #endif
2317*f6dc9357SAndroid Build Coastguard Worker         */
2318*f6dc9357SAndroid Build Coastguard Worker         bool linkWasSet = false;
2319*f6dc9357SAndroid Build Coastguard Worker         RINOK(SetFromLinkPath(_diskFilePath, linkInfo, linkWasSet))
2320*f6dc9357SAndroid Build Coastguard Worker         if (linkWasSet)
2321*f6dc9357SAndroid Build Coastguard Worker           _isSymLinkCreated = linkInfo.IsSymLink();
2322*f6dc9357SAndroid Build Coastguard Worker         else
2323*f6dc9357SAndroid Build Coastguard Worker           _needSetAttrib = false;
2324*f6dc9357SAndroid Build Coastguard Worker       }
2325*f6dc9357SAndroid Build Coastguard Worker       /*
2326*f6dc9357SAndroid Build Coastguard Worker       if (!NFile::NIO::SetReparseData(_diskFilePath, _item.IsDir, ))
2327*f6dc9357SAndroid Build Coastguard Worker       {
2328*f6dc9357SAndroid Build Coastguard Worker         res = SendMessageError_with_LastError(kCantCreateSymLink, _diskFilePath);
2329*f6dc9357SAndroid Build Coastguard Worker       }
2330*f6dc9357SAndroid Build Coastguard Worker       */
2331*f6dc9357SAndroid Build Coastguard Worker     }
2332*f6dc9357SAndroid Build Coastguard Worker     #endif
2333*f6dc9357SAndroid Build Coastguard Worker   }
2334*f6dc9357SAndroid Build Coastguard Worker   #endif
2335*f6dc9357SAndroid Build Coastguard Worker   return res;
2336*f6dc9357SAndroid Build Coastguard Worker }
2337*f6dc9357SAndroid Build Coastguard Worker 
2338*f6dc9357SAndroid Build Coastguard Worker 
2339*f6dc9357SAndroid Build Coastguard Worker void CArchiveExtractCallback::SetAttrib()
2340*f6dc9357SAndroid Build Coastguard Worker {
2341*f6dc9357SAndroid Build Coastguard Worker  #ifndef _WIN32
2342*f6dc9357SAndroid Build Coastguard Worker   // Linux now doesn't support permissions for symlinks
2343*f6dc9357SAndroid Build Coastguard Worker   if (_isSymLinkCreated)
2344*f6dc9357SAndroid Build Coastguard Worker     return;
2345*f6dc9357SAndroid Build Coastguard Worker  #endif
2346*f6dc9357SAndroid Build Coastguard Worker 
2347*f6dc9357SAndroid Build Coastguard Worker   if (_itemFailure
2348*f6dc9357SAndroid Build Coastguard Worker       || _diskFilePath.IsEmpty()
2349*f6dc9357SAndroid Build Coastguard Worker       || _stdOutMode
2350*f6dc9357SAndroid Build Coastguard Worker       || !_extractMode)
2351*f6dc9357SAndroid Build Coastguard Worker     return;
2352*f6dc9357SAndroid Build Coastguard Worker 
2353*f6dc9357SAndroid Build Coastguard Worker  #ifndef _WIN32
2354*f6dc9357SAndroid Build Coastguard Worker   if (_fi.Owner.Id_Defined &&
2355*f6dc9357SAndroid Build Coastguard Worker       _fi.Group.Id_Defined)
2356*f6dc9357SAndroid Build Coastguard Worker   {
2357*f6dc9357SAndroid Build Coastguard Worker     if (my_chown(_diskFilePath, _fi.Owner.Id, _fi.Group.Id) != 0)
2358*f6dc9357SAndroid Build Coastguard Worker     {
2359*f6dc9357SAndroid Build Coastguard Worker       SendMessageError_with_LastError("Cannot set owner", _diskFilePath);
2360*f6dc9357SAndroid Build Coastguard Worker     }
2361*f6dc9357SAndroid Build Coastguard Worker   }
2362*f6dc9357SAndroid Build Coastguard Worker  #endif
2363*f6dc9357SAndroid Build Coastguard Worker 
2364*f6dc9357SAndroid Build Coastguard Worker   if (_fi.Attrib_Defined)
2365*f6dc9357SAndroid Build Coastguard Worker   {
2366*f6dc9357SAndroid Build Coastguard Worker     // const AString s = GetAnsiString(_diskFilePath);
2367*f6dc9357SAndroid Build Coastguard Worker     // printf("\nSetFileAttrib_PosixHighDetect: %s: hex:%x\n", s.Ptr(), _fi.Attrib);
2368*f6dc9357SAndroid Build Coastguard Worker     bool res = SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib);
2369*f6dc9357SAndroid Build Coastguard Worker     if (!res)
2370*f6dc9357SAndroid Build Coastguard Worker     {
2371*f6dc9357SAndroid Build Coastguard Worker       // do we need error message here in Windows and in posix?
2372*f6dc9357SAndroid Build Coastguard Worker       SendMessageError_with_LastError("Cannot set file attribute", _diskFilePath);
2373*f6dc9357SAndroid Build Coastguard Worker     }
2374*f6dc9357SAndroid Build Coastguard Worker   }
2375*f6dc9357SAndroid Build Coastguard Worker }
2376*f6dc9357SAndroid Build Coastguard Worker 
2377*f6dc9357SAndroid Build Coastguard Worker 
2378*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 opRes))
2379*f6dc9357SAndroid Build Coastguard Worker {
2380*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
2381*f6dc9357SAndroid Build Coastguard Worker 
2382*f6dc9357SAndroid Build Coastguard Worker   // printf("\nCArchiveExtractCallback::SetOperationResult: %d %s\n", opRes, GetAnsiString(_diskFilePath));
2383*f6dc9357SAndroid Build Coastguard Worker 
2384*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_SFX
2385*f6dc9357SAndroid Build Coastguard Worker   if (ExtractToStreamCallback)
2386*f6dc9357SAndroid Build Coastguard Worker   {
2387*f6dc9357SAndroid Build Coastguard Worker     GetUnpackSize();
2388*f6dc9357SAndroid Build Coastguard Worker     return ExtractToStreamCallback->SetOperationResult8(opRes, BoolToInt(_encrypted), _curSize);
2389*f6dc9357SAndroid Build Coastguard Worker   }
2390*f6dc9357SAndroid Build Coastguard Worker   #endif
2391*f6dc9357SAndroid Build Coastguard Worker 
2392*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_SFX
2393*f6dc9357SAndroid Build Coastguard Worker 
2394*f6dc9357SAndroid Build Coastguard Worker   if (_hashStreamWasUsed)
2395*f6dc9357SAndroid Build Coastguard Worker   {
2396*f6dc9357SAndroid Build Coastguard Worker     _hashStreamSpec->_hash->Final(_item.IsDir,
2397*f6dc9357SAndroid Build Coastguard Worker         #ifdef SUPPORT_ALT_STREAMS
2398*f6dc9357SAndroid Build Coastguard Worker           _item.IsAltStream
2399*f6dc9357SAndroid Build Coastguard Worker         #else
2400*f6dc9357SAndroid Build Coastguard Worker           false
2401*f6dc9357SAndroid Build Coastguard Worker         #endif
2402*f6dc9357SAndroid Build Coastguard Worker         , _item.Path);
2403*f6dc9357SAndroid Build Coastguard Worker     _curSize = _hashStreamSpec->GetSize();
2404*f6dc9357SAndroid Build Coastguard Worker     _curSize_Defined = true;
2405*f6dc9357SAndroid Build Coastguard Worker     _hashStreamSpec->ReleaseStream();
2406*f6dc9357SAndroid Build Coastguard Worker     _hashStreamWasUsed = false;
2407*f6dc9357SAndroid Build Coastguard Worker   }
2408*f6dc9357SAndroid Build Coastguard Worker 
2409*f6dc9357SAndroid Build Coastguard Worker   #endif // Z7_SFX
2410*f6dc9357SAndroid Build Coastguard Worker 
2411*f6dc9357SAndroid Build Coastguard Worker   RINOK(CloseReparseAndFile())
2412*f6dc9357SAndroid Build Coastguard Worker 
2413*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_USE_SECURITY_CODE
2414*f6dc9357SAndroid Build Coastguard Worker   if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps)
2415*f6dc9357SAndroid Build Coastguard Worker   {
2416*f6dc9357SAndroid Build Coastguard Worker     const void *data;
2417*f6dc9357SAndroid Build Coastguard Worker     UInt32 dataSize;
2418*f6dc9357SAndroid Build Coastguard Worker     UInt32 propType;
2419*f6dc9357SAndroid Build Coastguard Worker     _arc->GetRawProps->GetRawProp(_index, kpidNtSecure, &data, &dataSize, &propType);
2420*f6dc9357SAndroid Build Coastguard Worker     if (dataSize != 0)
2421*f6dc9357SAndroid Build Coastguard Worker     {
2422*f6dc9357SAndroid Build Coastguard Worker       if (propType != NPropDataType::kRaw)
2423*f6dc9357SAndroid Build Coastguard Worker         return E_FAIL;
2424*f6dc9357SAndroid Build Coastguard Worker       if (CheckNtSecure((const Byte *)data, dataSize))
2425*f6dc9357SAndroid Build Coastguard Worker       {
2426*f6dc9357SAndroid Build Coastguard Worker         SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION;
2427*f6dc9357SAndroid Build Coastguard Worker         if (_saclEnabled)
2428*f6dc9357SAndroid Build Coastguard Worker           securInfo |= SACL_SECURITY_INFORMATION;
2429*f6dc9357SAndroid Build Coastguard Worker         ::SetFileSecurityW(fs2us(_diskFilePath), securInfo, (PSECURITY_DESCRIPTOR)(void *)(const Byte *)(data));
2430*f6dc9357SAndroid Build Coastguard Worker       }
2431*f6dc9357SAndroid Build Coastguard Worker     }
2432*f6dc9357SAndroid Build Coastguard Worker   }
2433*f6dc9357SAndroid Build Coastguard Worker   #endif // Z7_USE_SECURITY_CODE
2434*f6dc9357SAndroid Build Coastguard Worker 
2435*f6dc9357SAndroid Build Coastguard Worker   if (!_curSize_Defined)
2436*f6dc9357SAndroid Build Coastguard Worker     GetUnpackSize();
2437*f6dc9357SAndroid Build Coastguard Worker 
2438*f6dc9357SAndroid Build Coastguard Worker   if (_curSize_Defined)
2439*f6dc9357SAndroid Build Coastguard Worker   {
2440*f6dc9357SAndroid Build Coastguard Worker     #ifdef SUPPORT_ALT_STREAMS
2441*f6dc9357SAndroid Build Coastguard Worker     if (_item.IsAltStream)
2442*f6dc9357SAndroid Build Coastguard Worker       AltStreams_UnpackSize += _curSize;
2443*f6dc9357SAndroid Build Coastguard Worker     else
2444*f6dc9357SAndroid Build Coastguard Worker     #endif
2445*f6dc9357SAndroid Build Coastguard Worker       UnpackSize += _curSize;
2446*f6dc9357SAndroid Build Coastguard Worker   }
2447*f6dc9357SAndroid Build Coastguard Worker 
2448*f6dc9357SAndroid Build Coastguard Worker   if (_item.IsDir)
2449*f6dc9357SAndroid Build Coastguard Worker     NumFolders++;
2450*f6dc9357SAndroid Build Coastguard Worker   #ifdef SUPPORT_ALT_STREAMS
2451*f6dc9357SAndroid Build Coastguard Worker   else if (_item.IsAltStream)
2452*f6dc9357SAndroid Build Coastguard Worker     NumAltStreams++;
2453*f6dc9357SAndroid Build Coastguard Worker   #endif
2454*f6dc9357SAndroid Build Coastguard Worker   else
2455*f6dc9357SAndroid Build Coastguard Worker     NumFiles++;
2456*f6dc9357SAndroid Build Coastguard Worker 
2457*f6dc9357SAndroid Build Coastguard Worker   if (_needSetAttrib)
2458*f6dc9357SAndroid Build Coastguard Worker     SetAttrib();
2459*f6dc9357SAndroid Build Coastguard Worker 
2460*f6dc9357SAndroid Build Coastguard Worker   RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted)))
2461*f6dc9357SAndroid Build Coastguard Worker 
2462*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
2463*f6dc9357SAndroid Build Coastguard Worker 
2464*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
2465*f6dc9357SAndroid Build Coastguard Worker }
2466*f6dc9357SAndroid Build Coastguard Worker 
2467*f6dc9357SAndroid Build Coastguard Worker 
2468*f6dc9357SAndroid Build Coastguard Worker 
2469*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CArchiveExtractCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes))
2470*f6dc9357SAndroid Build Coastguard Worker {
2471*f6dc9357SAndroid Build Coastguard Worker   if (_folderArchiveExtractCallback2)
2472*f6dc9357SAndroid Build Coastguard Worker   {
2473*f6dc9357SAndroid Build Coastguard Worker     bool isEncrypted = false;
2474*f6dc9357SAndroid Build Coastguard Worker     UString s;
2475*f6dc9357SAndroid Build Coastguard Worker 
2476*f6dc9357SAndroid Build Coastguard Worker     if (indexType == NArchive::NEventIndexType::kInArcIndex && index != (UInt32)(Int32)-1)
2477*f6dc9357SAndroid Build Coastguard Worker     {
2478*f6dc9357SAndroid Build Coastguard Worker       CReadArcItem item;
2479*f6dc9357SAndroid Build Coastguard Worker       RINOK(_arc->GetItem(index, item))
2480*f6dc9357SAndroid Build Coastguard Worker       s = item.Path;
2481*f6dc9357SAndroid Build Coastguard Worker       RINOK(Archive_GetItemBoolProp(_arc->Archive, index, kpidEncrypted, isEncrypted))
2482*f6dc9357SAndroid Build Coastguard Worker     }
2483*f6dc9357SAndroid Build Coastguard Worker     else
2484*f6dc9357SAndroid Build Coastguard Worker     {
2485*f6dc9357SAndroid Build Coastguard Worker       s = '#';
2486*f6dc9357SAndroid Build Coastguard Worker       s.Add_UInt32(index);
2487*f6dc9357SAndroid Build Coastguard Worker       // if (indexType == NArchive::NEventIndexType::kBlockIndex) {}
2488*f6dc9357SAndroid Build Coastguard Worker     }
2489*f6dc9357SAndroid Build Coastguard Worker 
2490*f6dc9357SAndroid Build Coastguard Worker     return _folderArchiveExtractCallback2->ReportExtractResult(opRes, isEncrypted, s);
2491*f6dc9357SAndroid Build Coastguard Worker   }
2492*f6dc9357SAndroid Build Coastguard Worker 
2493*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
2494*f6dc9357SAndroid Build Coastguard Worker }
2495*f6dc9357SAndroid Build Coastguard Worker 
2496*f6dc9357SAndroid Build Coastguard Worker 
2497*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password))
2498*f6dc9357SAndroid Build Coastguard Worker {
2499*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
2500*f6dc9357SAndroid Build Coastguard Worker   if (!_cryptoGetTextPassword)
2501*f6dc9357SAndroid Build Coastguard Worker   {
2502*f6dc9357SAndroid Build Coastguard Worker     RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword,
2503*f6dc9357SAndroid Build Coastguard Worker         &_cryptoGetTextPassword))
2504*f6dc9357SAndroid Build Coastguard Worker   }
2505*f6dc9357SAndroid Build Coastguard Worker   return _cryptoGetTextPassword->CryptoGetTextPassword(password);
2506*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
2507*f6dc9357SAndroid Build Coastguard Worker }
2508*f6dc9357SAndroid Build Coastguard Worker 
2509*f6dc9357SAndroid Build Coastguard Worker 
2510*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_SFX
2511*f6dc9357SAndroid Build Coastguard Worker 
2512*f6dc9357SAndroid Build Coastguard Worker // ---------- HASH functions ----------
2513*f6dc9357SAndroid Build Coastguard Worker 
2514*f6dc9357SAndroid Build Coastguard Worker FString CArchiveExtractCallback::Hash_GetFullFilePath()
2515*f6dc9357SAndroid Build Coastguard Worker {
2516*f6dc9357SAndroid Build Coastguard Worker   // this function changes _item.PathParts.
2517*f6dc9357SAndroid Build Coastguard Worker   CorrectPathParts();
2518*f6dc9357SAndroid Build Coastguard Worker   const UStringVector &pathParts = _item.PathParts;
2519*f6dc9357SAndroid Build Coastguard Worker   const UString processedPath (MakePathFromParts(pathParts));
2520*f6dc9357SAndroid Build Coastguard Worker   FString fullProcessedPath (us2fs(processedPath));
2521*f6dc9357SAndroid Build Coastguard Worker   if (_pathMode != NExtract::NPathMode::kAbsPaths
2522*f6dc9357SAndroid Build Coastguard Worker       || !NName::IsAbsolutePath(processedPath))
2523*f6dc9357SAndroid Build Coastguard Worker   {
2524*f6dc9357SAndroid Build Coastguard Worker     fullProcessedPath = MakePath_from_2_Parts(
2525*f6dc9357SAndroid Build Coastguard Worker         DirPathPrefix_for_HashFiles,
2526*f6dc9357SAndroid Build Coastguard Worker         // _dirPathPrefix,
2527*f6dc9357SAndroid Build Coastguard Worker         fullProcessedPath);
2528*f6dc9357SAndroid Build Coastguard Worker   }
2529*f6dc9357SAndroid Build Coastguard Worker   return fullProcessedPath;
2530*f6dc9357SAndroid Build Coastguard Worker }
2531*f6dc9357SAndroid Build Coastguard Worker 
2532*f6dc9357SAndroid Build Coastguard Worker 
2533*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CArchiveExtractCallback::GetDiskProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
2534*f6dc9357SAndroid Build Coastguard Worker {
2535*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
2536*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
2537*f6dc9357SAndroid Build Coastguard Worker   if (propID == kpidSize)
2538*f6dc9357SAndroid Build Coastguard Worker   {
2539*f6dc9357SAndroid Build Coastguard Worker     RINOK(GetItem(index))
2540*f6dc9357SAndroid Build Coastguard Worker     const FString fullProcessedPath = Hash_GetFullFilePath();
2541*f6dc9357SAndroid Build Coastguard Worker     NFile::NFind::CFileInfo fi;
2542*f6dc9357SAndroid Build Coastguard Worker     if (fi.Find_FollowLink(fullProcessedPath))
2543*f6dc9357SAndroid Build Coastguard Worker       if (!fi.IsDir())
2544*f6dc9357SAndroid Build Coastguard Worker         prop = (UInt64)fi.Size;
2545*f6dc9357SAndroid Build Coastguard Worker   }
2546*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
2547*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
2548*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
2549*f6dc9357SAndroid Build Coastguard Worker }
2550*f6dc9357SAndroid Build Coastguard Worker 
2551*f6dc9357SAndroid Build Coastguard Worker 
2552*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CArchiveExtractCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode))
2553*f6dc9357SAndroid Build Coastguard Worker {
2554*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
2555*f6dc9357SAndroid Build Coastguard Worker   *inStream = NULL;
2556*f6dc9357SAndroid Build Coastguard Worker   // if (index != _index) return E_FAIL;
2557*f6dc9357SAndroid Build Coastguard Worker   if (mode != NUpdateNotifyOp::kHashRead)
2558*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
2559*f6dc9357SAndroid Build Coastguard Worker 
2560*f6dc9357SAndroid Build Coastguard Worker   RINOK(GetItem(index))
2561*f6dc9357SAndroid Build Coastguard Worker   const FString fullProcessedPath = Hash_GetFullFilePath();
2562*f6dc9357SAndroid Build Coastguard Worker 
2563*f6dc9357SAndroid Build Coastguard Worker   CInFileStream *inStreamSpec = new CInFileStream;
2564*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialInStream> inStreamRef = inStreamSpec;
2565*f6dc9357SAndroid Build Coastguard Worker   inStreamSpec->Set_PreserveATime(_ntOptions.PreserveATime);
2566*f6dc9357SAndroid Build Coastguard Worker   if (!inStreamSpec->OpenShared(fullProcessedPath, _ntOptions.OpenShareForWrite))
2567*f6dc9357SAndroid Build Coastguard Worker   {
2568*f6dc9357SAndroid Build Coastguard Worker     RINOK(SendMessageError_with_LastError(kCantOpenInFile, fullProcessedPath))
2569*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
2570*f6dc9357SAndroid Build Coastguard Worker   }
2571*f6dc9357SAndroid Build Coastguard Worker   *inStream = inStreamRef.Detach();
2572*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
2573*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
2574*f6dc9357SAndroid Build Coastguard Worker }
2575*f6dc9357SAndroid Build Coastguard Worker 
2576*f6dc9357SAndroid Build Coastguard Worker 
2577*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CArchiveExtractCallback::ReportOperation(
2578*f6dc9357SAndroid Build Coastguard Worker     UInt32 /* indexType */, UInt32 /* index */, UInt32 /* op */))
2579*f6dc9357SAndroid Build Coastguard Worker {
2580*f6dc9357SAndroid Build Coastguard Worker   // COM_TRY_BEGIN
2581*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
2582*f6dc9357SAndroid Build Coastguard Worker   // COM_TRY_END
2583*f6dc9357SAndroid Build Coastguard Worker }
2584*f6dc9357SAndroid Build Coastguard Worker 
2585*f6dc9357SAndroid Build Coastguard Worker 
2586*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CArchiveExtractCallback::RequestMemoryUse(
2587*f6dc9357SAndroid Build Coastguard Worker     UInt32 flags, UInt32 indexType, UInt32 index, const wchar_t *path,
2588*f6dc9357SAndroid Build Coastguard Worker     UInt64 requiredSize, UInt64 *allowedSize, UInt32 *answerFlags))
2589*f6dc9357SAndroid Build Coastguard Worker {
2590*f6dc9357SAndroid Build Coastguard Worker   if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0)
2591*f6dc9357SAndroid Build Coastguard Worker   {
2592*f6dc9357SAndroid Build Coastguard Worker     const UInt64 memLimit = _ntOptions.MemLimit;
2593*f6dc9357SAndroid Build Coastguard Worker     if (memLimit != (UInt64)(Int64)-1)
2594*f6dc9357SAndroid Build Coastguard Worker     {
2595*f6dc9357SAndroid Build Coastguard Worker       // we overwrite allowedSize
2596*f6dc9357SAndroid Build Coastguard Worker       *allowedSize = memLimit;
2597*f6dc9357SAndroid Build Coastguard Worker       if (requiredSize <= memLimit)
2598*f6dc9357SAndroid Build Coastguard Worker       {
2599*f6dc9357SAndroid Build Coastguard Worker         *answerFlags = NRequestMemoryAnswerFlags::k_Allow;
2600*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
2601*f6dc9357SAndroid Build Coastguard Worker       }
2602*f6dc9357SAndroid Build Coastguard Worker       *answerFlags = NRequestMemoryAnswerFlags::k_Limit_Exceeded;
2603*f6dc9357SAndroid Build Coastguard Worker       if (flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected)
2604*f6dc9357SAndroid Build Coastguard Worker         *answerFlags |= NRequestMemoryAnswerFlags::k_SkipArc;
2605*f6dc9357SAndroid Build Coastguard Worker       flags |= NRequestMemoryUseFlags::k_SLimit_Exceeded
2606*f6dc9357SAndroid Build Coastguard Worker             |  NRequestMemoryUseFlags::k_AllowedSize_WasForced;
2607*f6dc9357SAndroid Build Coastguard Worker     }
2608*f6dc9357SAndroid Build Coastguard Worker   }
2609*f6dc9357SAndroid Build Coastguard Worker 
2610*f6dc9357SAndroid Build Coastguard Worker   if (!_requestMemoryUseCallback)
2611*f6dc9357SAndroid Build Coastguard Worker   {
2612*f6dc9357SAndroid Build Coastguard Worker     _extractCallback2.QueryInterface(IID_IArchiveRequestMemoryUseCallback,
2613*f6dc9357SAndroid Build Coastguard Worker         &_requestMemoryUseCallback);
2614*f6dc9357SAndroid Build Coastguard Worker     if (!_requestMemoryUseCallback)
2615*f6dc9357SAndroid Build Coastguard Worker     {
2616*f6dc9357SAndroid Build Coastguard Worker       // keep default (answerFlags) from caller or (answerFlags) that was set in this function
2617*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
2618*f6dc9357SAndroid Build Coastguard Worker     }
2619*f6dc9357SAndroid Build Coastguard Worker   }
2620*f6dc9357SAndroid Build Coastguard Worker 
2621*f6dc9357SAndroid Build Coastguard Worker #if 0
2622*f6dc9357SAndroid Build Coastguard Worker   if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0)
2623*f6dc9357SAndroid Build Coastguard Worker   if (requiredSize <= *allowedSize)
2624*f6dc9357SAndroid Build Coastguard Worker   {
2625*f6dc9357SAndroid Build Coastguard Worker     // it's expected, that *answerFlags was set to NRequestMemoryAnswerFlags::k_Allow already,
2626*f6dc9357SAndroid Build Coastguard Worker     // because it's default answer for (requiredSize <= *allowedSize) case.
2627*f6dc9357SAndroid Build Coastguard Worker     *answerFlags = NRequestMemoryAnswerFlags::k_Allow; // optional code
2628*f6dc9357SAndroid Build Coastguard Worker   }
2629*f6dc9357SAndroid Build Coastguard Worker   else
2630*f6dc9357SAndroid Build Coastguard Worker   {
2631*f6dc9357SAndroid Build Coastguard Worker     // we clear *answerFlags, because we want to disable dafault "Allow", if it's set.
2632*f6dc9357SAndroid Build Coastguard Worker     // *answerFlags = 0;
2633*f6dc9357SAndroid Build Coastguard Worker   /*
2634*f6dc9357SAndroid Build Coastguard Worker       NRequestMemoryAnswerFlags::k_SkipArc |
2635*f6dc9357SAndroid Build Coastguard Worker       NRequestMemoryAnswerFlags::k_Limit_Exceeded;
2636*f6dc9357SAndroid Build Coastguard Worker   */
2637*f6dc9357SAndroid Build Coastguard Worker   }
2638*f6dc9357SAndroid Build Coastguard Worker #endif
2639*f6dc9357SAndroid Build Coastguard Worker 
2640*f6dc9357SAndroid Build Coastguard Worker   UString s;
2641*f6dc9357SAndroid Build Coastguard Worker   if (!path
2642*f6dc9357SAndroid Build Coastguard Worker       && indexType == NArchive::NEventIndexType::kInArcIndex
2643*f6dc9357SAndroid Build Coastguard Worker       && index != (UInt32)(Int32)-1
2644*f6dc9357SAndroid Build Coastguard Worker       && _arc)
2645*f6dc9357SAndroid Build Coastguard Worker   {
2646*f6dc9357SAndroid Build Coastguard Worker     RINOK(_arc->GetItem_Path(index, s))
2647*f6dc9357SAndroid Build Coastguard Worker     path = s.Ptr();
2648*f6dc9357SAndroid Build Coastguard Worker   }
2649*f6dc9357SAndroid Build Coastguard Worker 
2650*f6dc9357SAndroid Build Coastguard Worker   return _requestMemoryUseCallback->RequestMemoryUse(
2651*f6dc9357SAndroid Build Coastguard Worker       flags, indexType, index, path,
2652*f6dc9357SAndroid Build Coastguard Worker       requiredSize, allowedSize, answerFlags);
2653*f6dc9357SAndroid Build Coastguard Worker }
2654*f6dc9357SAndroid Build Coastguard Worker 
2655*f6dc9357SAndroid Build Coastguard Worker #endif // Z7_SFX
2656*f6dc9357SAndroid Build Coastguard Worker 
2657*f6dc9357SAndroid Build Coastguard Worker 
2658*f6dc9357SAndroid Build Coastguard Worker 
2659*f6dc9357SAndroid Build Coastguard Worker // ------------ After Extracting functions ------------
2660*f6dc9357SAndroid Build Coastguard Worker 
2661*f6dc9357SAndroid Build Coastguard Worker void CDirPathSortPair::SetNumSlashes(const FChar *s)
2662*f6dc9357SAndroid Build Coastguard Worker {
2663*f6dc9357SAndroid Build Coastguard Worker   for (unsigned numSlashes = 0;;)
2664*f6dc9357SAndroid Build Coastguard Worker   {
2665*f6dc9357SAndroid Build Coastguard Worker     FChar c = *s++;
2666*f6dc9357SAndroid Build Coastguard Worker     if (c == 0)
2667*f6dc9357SAndroid Build Coastguard Worker     {
2668*f6dc9357SAndroid Build Coastguard Worker       Len = numSlashes;
2669*f6dc9357SAndroid Build Coastguard Worker       return;
2670*f6dc9357SAndroid Build Coastguard Worker     }
2671*f6dc9357SAndroid Build Coastguard Worker     if (IS_PATH_SEPAR(c))
2672*f6dc9357SAndroid Build Coastguard Worker       numSlashes++;
2673*f6dc9357SAndroid Build Coastguard Worker   }
2674*f6dc9357SAndroid Build Coastguard Worker }
2675*f6dc9357SAndroid Build Coastguard Worker 
2676*f6dc9357SAndroid Build Coastguard Worker 
2677*f6dc9357SAndroid Build Coastguard Worker bool CDirPathTime::SetDirTime() const
2678*f6dc9357SAndroid Build Coastguard Worker {
2679*f6dc9357SAndroid Build Coastguard Worker   return NDir::SetDirTime(Path,
2680*f6dc9357SAndroid Build Coastguard Worker       CTime_Defined ? &CTime : NULL,
2681*f6dc9357SAndroid Build Coastguard Worker       ATime_Defined ? &ATime : NULL,
2682*f6dc9357SAndroid Build Coastguard Worker       MTime_Defined ? &MTime : NULL);
2683*f6dc9357SAndroid Build Coastguard Worker }
2684*f6dc9357SAndroid Build Coastguard Worker 
2685*f6dc9357SAndroid Build Coastguard Worker 
2686*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::SetDirsTimes()
2687*f6dc9357SAndroid Build Coastguard Worker {
2688*f6dc9357SAndroid Build Coastguard Worker   if (!_arc)
2689*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
2690*f6dc9357SAndroid Build Coastguard Worker 
2691*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<CDirPathSortPair> pairs;
2692*f6dc9357SAndroid Build Coastguard Worker   pairs.ClearAndSetSize(_extractedFolders.Size());
2693*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
2694*f6dc9357SAndroid Build Coastguard Worker 
2695*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < _extractedFolders.Size(); i++)
2696*f6dc9357SAndroid Build Coastguard Worker   {
2697*f6dc9357SAndroid Build Coastguard Worker     CDirPathSortPair &pair = pairs[i];
2698*f6dc9357SAndroid Build Coastguard Worker     pair.Index = i;
2699*f6dc9357SAndroid Build Coastguard Worker     pair.SetNumSlashes(_extractedFolders[i].Path);
2700*f6dc9357SAndroid Build Coastguard Worker   }
2701*f6dc9357SAndroid Build Coastguard Worker 
2702*f6dc9357SAndroid Build Coastguard Worker   pairs.Sort2();
2703*f6dc9357SAndroid Build Coastguard Worker 
2704*f6dc9357SAndroid Build Coastguard Worker   HRESULT res = S_OK;
2705*f6dc9357SAndroid Build Coastguard Worker 
2706*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < pairs.Size(); i++)
2707*f6dc9357SAndroid Build Coastguard Worker   {
2708*f6dc9357SAndroid Build Coastguard Worker     const CDirPathTime &dpt = _extractedFolders[pairs[i].Index];
2709*f6dc9357SAndroid Build Coastguard Worker     if (!dpt.SetDirTime())
2710*f6dc9357SAndroid Build Coastguard Worker     {
2711*f6dc9357SAndroid Build Coastguard Worker       // result = E_FAIL;
2712*f6dc9357SAndroid Build Coastguard Worker       // do we need error message here in Windows and in posix?
2713*f6dc9357SAndroid Build Coastguard Worker       // SendMessageError_with_LastError("Cannot set directory time", dpt.Path);
2714*f6dc9357SAndroid Build Coastguard Worker     }
2715*f6dc9357SAndroid Build Coastguard Worker   }
2716*f6dc9357SAndroid Build Coastguard Worker 
2717*f6dc9357SAndroid Build Coastguard Worker   /*
2718*f6dc9357SAndroid Build Coastguard Worker   #ifndef _WIN32
2719*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < _delayedSymLinks.Size(); i++)
2720*f6dc9357SAndroid Build Coastguard Worker   {
2721*f6dc9357SAndroid Build Coastguard Worker     const CDelayedSymLink &link = _delayedSymLinks[i];
2722*f6dc9357SAndroid Build Coastguard Worker     if (!link.Create())
2723*f6dc9357SAndroid Build Coastguard Worker     {
2724*f6dc9357SAndroid Build Coastguard Worker       if (res == S_OK)
2725*f6dc9357SAndroid Build Coastguard Worker         res = GetLastError_noZero_HRESULT();
2726*f6dc9357SAndroid Build Coastguard Worker       // res = E_FAIL;
2727*f6dc9357SAndroid Build Coastguard Worker       // do we need error message here in Windows and in posix?
2728*f6dc9357SAndroid Build Coastguard Worker       SendMessageError_with_LastError("Cannot create Symbolic Link", link._source);
2729*f6dc9357SAndroid Build Coastguard Worker     }
2730*f6dc9357SAndroid Build Coastguard Worker   }
2731*f6dc9357SAndroid Build Coastguard Worker   #endif // _WIN32
2732*f6dc9357SAndroid Build Coastguard Worker   */
2733*f6dc9357SAndroid Build Coastguard Worker 
2734*f6dc9357SAndroid Build Coastguard Worker   ClearExtractedDirsInfo();
2735*f6dc9357SAndroid Build Coastguard Worker   return res;
2736*f6dc9357SAndroid Build Coastguard Worker }
2737*f6dc9357SAndroid Build Coastguard Worker 
2738*f6dc9357SAndroid Build Coastguard Worker 
2739*f6dc9357SAndroid Build Coastguard Worker HRESULT CArchiveExtractCallback::CloseArc()
2740*f6dc9357SAndroid Build Coastguard Worker {
2741*f6dc9357SAndroid Build Coastguard Worker   HRESULT res = CloseReparseAndFile();
2742*f6dc9357SAndroid Build Coastguard Worker   const HRESULT res2 = SetDirsTimes();
2743*f6dc9357SAndroid Build Coastguard Worker   if (res == S_OK)
2744*f6dc9357SAndroid Build Coastguard Worker     res = res2;
2745*f6dc9357SAndroid Build Coastguard Worker   _arc = NULL;
2746*f6dc9357SAndroid Build Coastguard Worker   return res;
2747*f6dc9357SAndroid Build Coastguard Worker }
2748