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 26Z7_CLASS_IMP_NOQIB_1( 27 COutStreamWithHash 28 , ISequentialOutStream 29) 30 CMyComPtr<ISequentialOutStream> _stream; 31 UInt64 _size; 32 bool _calculate; 33public: 34 IHashCalc *_hash; 35 36 void SetStream(ISequentialOutStream *stream) { _stream = stream; } 37 void ReleaseStream() { _stream.Release(); } 38 void Init(bool calculate = true) 39 { 40 InitCRC(); 41 _size = 0; 42 _calculate = calculate; 43 } 44 void EnableCalc(bool calculate) { _calculate = calculate; } 45 void InitCRC() { _hash->InitForNewFile(); } 46 UInt64 GetSize() const { return _size; } 47}; 48 49#endif 50 51struct 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 92Z7_CLASS_IMP_COM_1( 93 CGetProp 94 , IGetProp 95) 96public: 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 115struct CHardLinkNode 116{ 117 UInt64 StreamId; 118 UInt64 INode; 119 120 int Compare(const CHardLinkNode &a) const; 121}; 122 123class CHardLinks 124{ 125public: 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 146struct 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 164struct 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 183struct CDirPathTime: public CFiTimesCAM 184{ 185 FString Path; 186 187 bool SetDirTime() const; 188}; 189 190 191#ifdef SUPPORT_LINKS 192 193struct 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 230struct 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 247class 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 419public: 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 424public: 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 488private: 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 497public: 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 520private: 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 556struct 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 580bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); 581 582void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf); 583 584#endif 585