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