• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // ArchiveExtractCallback.h
2 
3 #ifndef ZIP7_INC_ARCHIVE_EXTRACT_CALLBACK_H
4 #define ZIP7_INC_ARCHIVE_EXTRACT_CALLBACK_H
5 
6 #include "../../../Common/MyCom.h"
7 #include "../../../Common/MyLinux.h"
8 #include "../../../Common/Wildcard.h"
9 
10 #include "../../IPassword.h"
11 
12 #include "../../Common/FileStreams.h"
13 #include "../../Common/ProgressUtils.h"
14 #include "../../Common/StreamObjects.h"
15 
16 #include "../../Archive/IArchive.h"
17 
18 #include "ExtractMode.h"
19 #include "IFileExtractCallback.h"
20 #include "OpenArchive.h"
21 
22 #include "HashCalc.h"
23 
24 #ifndef Z7_SFX
25 
26 Z7_CLASS_IMP_NOQIB_1(
27   COutStreamWithHash
28   , ISequentialOutStream
29 )
30   CMyComPtr<ISequentialOutStream> _stream;
31   UInt64 _size;
32   bool _calculate;
33 public:
34   IHashCalc *_hash;
35 
SetStream(ISequentialOutStream * stream)36   void SetStream(ISequentialOutStream *stream) { _stream = stream; }
ReleaseStream()37   void ReleaseStream() { _stream.Release(); }
38   void Init(bool calculate = true)
39   {
40     InitCRC();
41     _size = 0;
42     _calculate = calculate;
43   }
EnableCalc(bool calculate)44   void EnableCalc(bool calculate) { _calculate = calculate; }
InitCRC()45   void InitCRC() { _hash->InitForNewFile(); }
GetSize()46   UInt64 GetSize() const { return _size; }
47 };
48 
49 #endif
50 
51 struct CExtractNtOptions
52 {
53   CBoolPair NtSecurity;
54   CBoolPair SymLinks;
55   CBoolPair SymLinks_AllowDangerous;
56   CBoolPair HardLinks;
57   CBoolPair AltStreams;
58   bool ReplaceColonForAltStream;
59   bool WriteToAltStreamIfColon;
60 
61   bool ExtractOwner;
62 
63   bool PreAllocateOutFile;
64 
65   // used for hash arcs only, when we open external files
66   bool PreserveATime;
67   bool OpenShareForWrite;
68 
69   CExtractNtOptions():
70       ReplaceColonForAltStream(false),
71       WriteToAltStreamIfColon(false),
72       ExtractOwner(false),
73       PreserveATime(false),
74       OpenShareForWrite(false)
75   {
76     SymLinks.Val = true;
77     SymLinks_AllowDangerous.Val = false;
78     HardLinks.Val = true;
79     AltStreams.Val = true;
80 
81     PreAllocateOutFile =
82       #ifdef _WIN32
83         true;
84       #else
85         false;
86       #endif
87   }
88 };
89 
90 #ifndef Z7_SFX
91 
92 Z7_CLASS_IMP_COM_1(
93   CGetProp
94   , IGetProp
95 )
96 public:
97   UInt32 IndexInArc;
98   const CArc *Arc;
99   // UString Name; // relative path
100 };
101 
102 #endif
103 
104 #ifndef Z7_SFX
105 #ifndef UNDER_CE
106 
107 #define SUPPORT_LINKS
108 
109 #endif
110 #endif
111 
112 
113 #ifdef SUPPORT_LINKS
114 
115 struct CHardLinkNode
116 {
117   UInt64 StreamId;
118   UInt64 INode;
119 
120   int Compare(const CHardLinkNode &a) const;
121 };
122 
123 class CHardLinks
124 {
125 public:
126   CRecordVector<CHardLinkNode> IDs;
127   CObjectVector<FString> Links;
128 
129   void Clear()
130   {
131     IDs.Clear();
132     Links.Clear();
133   }
134 
135   void PrepareLinks()
136   {
137     while (Links.Size() < IDs.Size())
138       Links.AddNew();
139   }
140 };
141 
142 #endif
143 
144 #ifdef SUPPORT_ALT_STREAMS
145 
146 struct CIndexToPathPair
147 {
148   UInt32 Index;
149   FString Path;
150 
151   CIndexToPathPair(UInt32 index): Index(index) {}
152   CIndexToPathPair(UInt32 index, const FString &path): Index(index), Path(path) {}
153 
154   int Compare(const CIndexToPathPair &pair) const
155   {
156     return MyCompare(Index, pair.Index);
157   }
158 };
159 
160 #endif
161 
162 
163 
164 struct CFiTimesCAM
165 {
166   CFiTime CTime;
167   CFiTime ATime;
168   CFiTime MTime;
169 
170   bool CTime_Defined;
171   bool ATime_Defined;
172   bool MTime_Defined;
173 
174   bool IsSomeTimeDefined() const
175   {
176     return
177       CTime_Defined |
178       ATime_Defined |
179       MTime_Defined;
180   }
181 };
182 
183 struct CDirPathTime: public CFiTimesCAM
184 {
185   FString Path;
186 
187   bool SetDirTime() const;
188 };
189 
190 
191 #ifdef SUPPORT_LINKS
192 
193 struct CLinkInfo
194 {
195   // bool isCopyLink;
196   bool isHardLink;
197   bool isJunction;
198   bool isRelative;
199   bool isWSL;
200   UString linkPath;
201 
202   bool IsSymLink() const { return !isHardLink; }
203 
204   CLinkInfo():
205     // IsCopyLink(false),
206     isHardLink(false),
207     isJunction(false),
208     isRelative(false),
209     isWSL(false)
210     {}
211 
212   void Clear()
213   {
214     // IsCopyLink = false;
215     isHardLink = false;
216     isJunction = false;
217     isRelative = false;
218     isWSL = false;
219     linkPath.Empty();
220   }
221 
222   bool Parse(const Byte *data, size_t dataSize, bool isLinuxData);
223 };
224 
225 #endif // SUPPORT_LINKS
226 
227 
228 #ifndef _WIN32
229 
230 struct COwnerInfo
231 {
232   bool Id_Defined;
233   UInt32 Id;
234   AString Name;
235 
236   void Clear()
237   {
238     Id_Defined = false;
239     Id = 0;
240     Name.Empty();
241   }
242 };
243 
244 #endif
245 
246 
247 class CArchiveExtractCallback Z7_final:
248   public IArchiveExtractCallback,
249   public IArchiveExtractCallbackMessage2,
250   public ICryptoGetTextPassword,
251   public ICompressProgressInfo,
252   public IArchiveUpdateCallbackFile,
253   public IArchiveGetDiskProperty,
254   public CMyUnknownImp
255 {
256   Z7_COM_UNKNOWN_IMP_5(
257       /* IArchiveExtractCallback, */
258       IArchiveExtractCallbackMessage2,
259       ICryptoGetTextPassword,
260       ICompressProgressInfo,
261       IArchiveUpdateCallbackFile,
262       IArchiveGetDiskProperty)
263 
264   Z7_IFACE_COM7_IMP(IProgress)
265   Z7_IFACE_COM7_IMP(IArchiveExtractCallback)
266   Z7_IFACE_COM7_IMP(IArchiveExtractCallbackMessage2)
267   Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)
268   Z7_IFACE_COM7_IMP(ICompressProgressInfo)
269   Z7_IFACE_COM7_IMP(IArchiveUpdateCallbackFile)
270   Z7_IFACE_COM7_IMP(IArchiveGetDiskProperty)
271 
272   const CArc *_arc;
273   CExtractNtOptions _ntOptions;
274 
275   bool _isSplit;
276 
277   bool _extractMode;
278 
279   bool Write_CTime;
280   bool Write_ATime;
281   bool Write_MTime;
282   bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_";
283 
284   bool _encrypted;
285 
286   // bool _is_SymLink_in_Data;
287   bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX
288 
289   bool _needSetAttrib;
290   bool _isSymLinkCreated;
291   bool _itemFailure;
292 
293   bool _curSize_Defined;
294   bool _fileLength_WasSet;
295 
296   bool _removePartsForAltStreams;
297 
298   bool _stdOutMode;
299   bool _testMode;
300   bool _multiArchives;
301 
302   NExtract::NPathMode::EEnum _pathMode;
303   NExtract::NOverwriteMode::EEnum _overwriteMode;
304 
305   const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin)
306   CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
307   // CMyComPtr<ICompressProgressInfo> _compressProgress;
308   // CMyComPtr<IArchiveExtractCallbackMessage2> _callbackMessage;
309   CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2;
310   CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
311 
312   FString _dirPathPrefix;
313   FString _dirPathPrefix_Full;
314 
315   #ifndef Z7_SFX
316 
317   CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
318   CGetProp *GetProp_Spec;
319   CMyComPtr<IGetProp> GetProp;
320 
321   #endif
322 
323   CReadArcItem _item;
324   FString _diskFilePath;
325   UInt64 _position;
326 
327   struct CProcessedFileInfo
328   {
329     CArcTime CTime;
330     CArcTime ATime;
331     CArcTime MTime;
332     UInt32 Attrib;
333     bool Attrib_Defined;
334 
335    #ifndef _WIN32
336     COwnerInfo Owner;
337     COwnerInfo Group;
338    #endif
339 
340     bool IsReparse() const
341     {
342       return (Attrib_Defined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0);
343     }
344 
345     bool IsLinuxSymLink() const
346     {
347       return (Attrib_Defined && MY_LIN_S_ISLNK(Attrib >> 16));
348     }
349 
350     void SetFromPosixAttrib(UInt32 a)
351     {
352       // here we set only part of combined attribute required by SetFileAttrib() call
353       #ifdef _WIN32
354       // Windows sets FILE_ATTRIBUTE_NORMAL, if we try to set 0 as attribute.
355       Attrib = MY_LIN_S_ISDIR(a) ?
356           FILE_ATTRIBUTE_DIRECTORY :
357           FILE_ATTRIBUTE_ARCHIVE;
358       if ((a & 0222) == 0) // (& S_IWUSR) in p7zip
359         Attrib |= FILE_ATTRIBUTE_READONLY;
360       // 22.00 : we need type bits for (MY_LIN_S_IFLNK) for IsLinuxSymLink()
361       a &= MY_LIN_S_IFMT;
362       if (a == MY_LIN_S_IFLNK)
363         Attrib |= (a << 16);
364       #else
365       Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION;
366       #endif
367       Attrib_Defined = true;
368     }
369   } _fi;
370 
371   UInt32 _index;
372   UInt64 _curSize;
373   UInt64 _fileLength_that_WasSet;
374 
375   COutFileStream *_outFileStreamSpec;
376   CMyComPtr<ISequentialOutStream> _outFileStream;
377 
378   CByteBuffer _outMemBuf;
379   CBufPtrSeqOutStream *_bufPtrSeqOutStream_Spec;
380   CMyComPtr<ISequentialOutStream> _bufPtrSeqOutStream;
381 
382 
383  #ifndef Z7_SFX
384 
385   COutStreamWithHash *_hashStreamSpec;
386   CMyComPtr<ISequentialOutStream> _hashStream;
387   bool _hashStreamWasUsed;
388 
389   bool _use_baseParentFolder_mode;
390   UInt32 _baseParentFolder;
391  #endif
392 
393   UStringVector _removePathParts;
394 
395   CMyComPtr<ICompressProgressInfo> _localProgress;
396   UInt64 _packTotal;
397 
398   UInt64 _progressTotal;
399   bool _progressTotal_Defined;
400 
401   CObjectVector<CDirPathTime> _extractedFolders;
402 
403   #ifndef _WIN32
404   // CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks;
405   #endif
406 
407   #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
408   bool _saclEnabled;
409   #endif
410 
411   void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
412   HRESULT GetTime(UInt32 index, PROPID propID, CArcTime &ft);
413   HRESULT GetUnpackSize();
414 
415   FString Hash_GetFullFilePath();
416 
417   void SetAttrib();
418 
419 public:
420   HRESULT SendMessageError(const char *message, const FString &path);
421   HRESULT SendMessageError_with_LastError(const char *message, const FString &path);
422   HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2);
423 
424 public:
425   #if defined(_WIN32) && !defined(UNDER_CE)
426   NExtract::NZoneIdMode::EEnum ZoneMode;
427   CByteBuffer ZoneBuf;
428   #endif
429 
430   CLocalProgress *LocalProgressSpec;
431 
432   UInt64 NumFolders;
433   UInt64 NumFiles;
434   UInt64 NumAltStreams;
435   UInt64 UnpackSize;
436   UInt64 AltStreams_UnpackSize;
437 
438   FString DirPathPrefix_for_HashFiles;
439 
440   CArchiveExtractCallback();
441 
442   void InitForMulti(bool multiArchives,
443       NExtract::NPathMode::EEnum pathMode,
444       NExtract::NOverwriteMode::EEnum overwriteMode,
445       NExtract::NZoneIdMode::EEnum zoneMode,
446       bool keepAndReplaceEmptyDirPrefixes)
447   {
448     _multiArchives = multiArchives;
449     _pathMode = pathMode;
450     _overwriteMode = overwriteMode;
451    #if defined(_WIN32) && !defined(UNDER_CE)
452      ZoneMode = zoneMode;
453    #else
454      UNUSED_VAR(zoneMode)
455    #endif
456     _keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes;
457     NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0;
458   }
459 
460   #ifndef Z7_SFX
461 
462   void SetHashMethods(IHashCalc *hash)
463   {
464     if (!hash)
465       return;
466     _hashStreamSpec = new COutStreamWithHash;
467     _hashStream = _hashStreamSpec;
468     _hashStreamSpec->_hash = hash;
469   }
470 
471   #endif
472 
473   void InitBeforeNewArchive();
474 
475   void Init(
476       const CExtractNtOptions &ntOptions,
477       const NWildcard::CCensorNode *wildcardCensor,
478       const CArc *arc,
479       IFolderArchiveExtractCallback *extractCallback2,
480       bool stdOutMode, bool testMode,
481       const FString &directoryPath,
482       const UStringVector &removePathParts, bool removePartsForAltStreams,
483       UInt64 packSize);
484 
485 
486   #ifdef SUPPORT_LINKS
487 
488 private:
489   CHardLinks _hardLinks;
490   CLinkInfo _link;
491 
492   // FString _copyFile_Path;
493   // HRESULT MyCopyFile(ISequentialOutStream *outStream);
494   HRESULT Link(const FString &fullProcessedPath);
495   HRESULT ReadLink();
496 
497 public:
498   // call PrepareHardLinks() after Init()
499   HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices);  // NULL means all items
500 
501   #endif
502 
503 
504   #ifdef SUPPORT_ALT_STREAMS
505   CObjectVector<CIndexToPathPair> _renamedFiles;
506   #endif
507 
508   // call it after Init()
509 
510   #ifndef Z7_SFX
511   void SetBaseParentFolderIndex(UInt32 indexInArc)
512   {
513     _baseParentFolder = indexInArc;
514     _use_baseParentFolder_mode = true;
515   }
516   #endif
517 
518   HRESULT CloseArc();
519 
520 private:
521   void ClearExtractedDirsInfo()
522   {
523     _extractedFolders.Clear();
524     #ifndef _WIN32
525     // _delayedSymLinks.Clear();
526     #endif
527   }
528 
529   HRESULT Read_fi_Props();
530   void CorrectPathParts();
531   void GetFiTimesCAM(CFiTimesCAM &pt);
532   void CreateFolders();
533 
534   bool _isRenamed;
535   HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit);
536   HRESULT GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit);
537   HRESULT GetItem(UInt32 index);
538 
539   HRESULT CloseFile();
540   HRESULT CloseReparseAndFile();
541   HRESULT CloseReparseAndFile2();
542   HRESULT SetDirsTimes();
543 
544   const void *NtReparse_Data;
545   UInt32 NtReparse_Size;
546 
547   #ifdef SUPPORT_LINKS
548   HRESULT SetFromLinkPath(
549       const FString &fullProcessedPath,
550       const CLinkInfo &linkInfo,
551       bool &linkWasSet);
552   #endif
553 };
554 
555 
556 struct CArchiveExtractCallback_Closer
557 {
558   CArchiveExtractCallback *_ref;
559 
560   CArchiveExtractCallback_Closer(CArchiveExtractCallback *ref): _ref(ref) {}
561 
562   HRESULT Close()
563   {
564     HRESULT res = S_OK;
565     if (_ref)
566     {
567       res = _ref->CloseArc();
568       _ref = NULL;
569     }
570     return res;
571   }
572 
573   ~CArchiveExtractCallback_Closer()
574   {
575     Close();
576   }
577 };
578 
579 
580 bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
581 
582 void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf);
583 
584 #endif
585