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