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