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