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