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 PreAllocateOutFile; 64 65 // used for hash arcs only, when we open external files 66 bool PreserveATime; 67 bool OpenShareForWrite; 68 CExtractNtOptionsCExtractNtOptions69 CExtractNtOptions(): 70 ReplaceColonForAltStream(false), 71 WriteToAltStreamIfColon(false), 72 PreserveATime(false), 73 OpenShareForWrite(false) 74 { 75 SymLinks.Val = true; 76 SymLinks_AllowDangerous.Val = false; 77 HardLinks.Val = true; 78 AltStreams.Val = true; 79 80 PreAllocateOutFile = 81 #ifdef _WIN32 82 true; 83 #else 84 false; 85 #endif 86 } 87 }; 88 89 #ifndef _SFX 90 91 class CGetProp: 92 public IGetProp, 93 public CMyUnknownImp 94 { 95 public: 96 const CArc *Arc; 97 UInt32 IndexInArc; 98 // UString Name; // relative path 99 100 MY_UNKNOWN_IMP1(IGetProp) 101 INTERFACE_IGetProp(;) 102 }; 103 104 #endif 105 106 #ifndef _SFX 107 #ifndef UNDER_CE 108 109 #define SUPPORT_LINKS 110 111 #endif 112 #endif 113 114 115 #ifdef SUPPORT_LINKS 116 117 struct CHardLinkNode 118 { 119 UInt64 StreamId; 120 UInt64 INode; 121 122 int Compare(const CHardLinkNode &a) const; 123 }; 124 125 class CHardLinks 126 { 127 public: 128 CRecordVector<CHardLinkNode> IDs; 129 CObjectVector<FString> Links; 130 Clear()131 void Clear() 132 { 133 IDs.Clear(); 134 Links.Clear(); 135 } 136 PrepareLinks()137 void PrepareLinks() 138 { 139 while (Links.Size() < IDs.Size()) 140 Links.AddNew(); 141 } 142 }; 143 144 #endif 145 146 #ifdef SUPPORT_ALT_STREAMS 147 148 struct CIndexToPathPair 149 { 150 UInt32 Index; 151 FString Path; 152 CIndexToPathPairCIndexToPathPair153 CIndexToPathPair(UInt32 index): Index(index) {} CIndexToPathPairCIndexToPathPair154 CIndexToPathPair(UInt32 index, const FString &path): Index(index), Path(path) {} 155 CompareCIndexToPathPair156 int Compare(const CIndexToPathPair &pair) const 157 { 158 return MyCompare(Index, pair.Index); 159 } 160 }; 161 162 #endif 163 164 165 166 struct CDirPathTime 167 { 168 FILETIME CTime; 169 FILETIME ATime; 170 FILETIME MTime; 171 172 bool CTimeDefined; 173 bool ATimeDefined; 174 bool MTimeDefined; 175 176 FString Path; 177 178 bool SetDirTime() const; 179 }; 180 181 182 #ifdef SUPPORT_LINKS 183 184 struct CLinkInfo 185 { 186 // bool isCopyLink; 187 bool isHardLink; 188 bool isJunction; 189 bool isRelative; 190 bool isWSL; 191 UString linkPath; 192 IsSymLinkCLinkInfo193 bool IsSymLink() const { return !isHardLink; } 194 CLinkInfoCLinkInfo195 CLinkInfo(): 196 // IsCopyLink(false), 197 isHardLink(false), 198 isJunction(false), 199 isRelative(false), 200 isWSL(false) 201 {} 202 ClearCLinkInfo203 void Clear() 204 { 205 // IsCopyLink = false; 206 isHardLink = false; 207 isJunction = false; 208 isRelative = false; 209 isWSL = false; 210 linkPath.Empty(); 211 } 212 213 bool Parse(const Byte *data, size_t dataSize, bool isLinuxData); 214 }; 215 216 #endif // SUPPORT_LINKS 217 218 219 class CArchiveExtractCallback: 220 public IArchiveExtractCallback, 221 public IArchiveExtractCallbackMessage, 222 public ICryptoGetTextPassword, 223 public ICompressProgressInfo, 224 public IArchiveUpdateCallbackFile, 225 public IArchiveGetDiskProperty, 226 public CMyUnknownImp 227 { 228 const CArc *_arc; 229 CExtractNtOptions _ntOptions; 230 231 const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin) 232 CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; 233 CMyComPtr<ICompressProgressInfo> _compressProgress; 234 CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; 235 CMyComPtr<IArchiveExtractCallbackMessage> _callbackMessage; 236 CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2; 237 238 FString _dirPathPrefix; 239 FString _dirPathPrefix_Full; 240 NExtract::NPathMode::EEnum _pathMode; 241 NExtract::NOverwriteMode::EEnum _overwriteMode; 242 bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_"; 243 244 #ifndef _SFX 245 246 CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback; 247 CGetProp *GetProp_Spec; 248 CMyComPtr<IGetProp> GetProp; 249 250 #endif 251 252 CReadArcItem _item; 253 FString _diskFilePath; 254 UInt64 _position; 255 bool _isSplit; 256 257 bool _extractMode; 258 259 bool WriteCTime; 260 bool WriteATime; 261 bool WriteMTime; 262 263 bool _encrypted; 264 265 struct CProcessedFileInfo 266 { 267 FILETIME CTime; 268 FILETIME ATime; 269 FILETIME MTime; 270 UInt32 Attrib; 271 272 bool CTimeDefined; 273 bool ATimeDefined; 274 bool MTimeDefined; 275 bool AttribDefined; 276 IsReparseCProcessedFileInfo277 bool IsReparse() const 278 { 279 return (AttribDefined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0); 280 } 281 IsLinuxSymLinkCProcessedFileInfo282 bool IsLinuxSymLink() const 283 { 284 return (AttribDefined && MY_LIN_S_ISLNK(Attrib >> 16)); 285 } 286 SetFromPosixAttribCProcessedFileInfo287 void SetFromPosixAttrib(UInt32 a) 288 { 289 // here we set only part of combined attribute required by SetFileAttrib() call 290 #ifdef _WIN32 291 // Windows sets FILE_ATTRIBUTE_NORMAL, if we try to set 0 as attribute. 292 Attrib = MY_LIN_S_ISDIR(a) ? 293 FILE_ATTRIBUTE_DIRECTORY : 294 FILE_ATTRIBUTE_ARCHIVE; 295 if ((a & 0222) == 0) // (& S_IWUSR) in p7zip 296 Attrib |= FILE_ATTRIBUTE_READONLY; 297 #else 298 Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION; 299 #endif 300 AttribDefined = true; 301 } 302 } _fi; 303 304 // bool _is_SymLink_in_Data; 305 bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX 306 307 bool _needSetAttrib; 308 bool _isSymLinkCreated; 309 bool _itemFailure; 310 311 UInt32 _index; 312 UInt64 _curSize; 313 bool _curSizeDefined; 314 bool _fileLengthWasSet; 315 UInt64 _fileLength_that_WasSet; 316 317 COutFileStream *_outFileStreamSpec; 318 CMyComPtr<ISequentialOutStream> _outFileStream; 319 320 CByteBuffer _outMemBuf; 321 CBufPtrSeqOutStream *_bufPtrSeqOutStream_Spec; 322 CMyComPtr<ISequentialOutStream> _bufPtrSeqOutStream; 323 324 325 #ifndef _SFX 326 327 COutStreamWithHash *_hashStreamSpec; 328 CMyComPtr<ISequentialOutStream> _hashStream; 329 bool _hashStreamWasUsed; 330 331 #endif 332 333 bool _removePartsForAltStreams; 334 UStringVector _removePathParts; 335 336 #ifndef _SFX 337 bool _use_baseParentFolder_mode; 338 UInt32 _baseParentFolder; 339 #endif 340 341 bool _stdOutMode; 342 bool _testMode; 343 bool _multiArchives; 344 345 CMyComPtr<ICompressProgressInfo> _localProgress; 346 UInt64 _packTotal; 347 348 UInt64 _progressTotal; 349 bool _progressTotal_Defined; 350 351 CObjectVector<CDirPathTime> _extractedFolders; 352 353 #ifndef _WIN32 354 // CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks; 355 #endif 356 357 #if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX) 358 bool _saclEnabled; 359 #endif 360 361 void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath); 362 HRESULT GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); 363 HRESULT GetUnpackSize(); 364 365 FString Hash_GetFullFilePath(); 366 367 void SetAttrib(); 368 369 public: 370 HRESULT SendMessageError(const char *message, const FString &path); 371 HRESULT SendMessageError_with_LastError(const char *message, const FString &path); 372 HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2); 373 374 public: 375 376 CLocalProgress *LocalProgressSpec; 377 378 UInt64 NumFolders; 379 UInt64 NumFiles; 380 UInt64 NumAltStreams; 381 UInt64 UnpackSize; 382 UInt64 AltStreams_UnpackSize; 383 384 FString DirPathPrefix_for_HashFiles; 385 386 MY_UNKNOWN_IMP5( 387 IArchiveExtractCallbackMessage, 388 ICryptoGetTextPassword, 389 ICompressProgressInfo, 390 IArchiveUpdateCallbackFile, 391 IArchiveGetDiskProperty 392 ) 393 394 INTERFACE_IArchiveExtractCallback(;) 395 INTERFACE_IArchiveExtractCallbackMessage(;) 396 INTERFACE_IArchiveUpdateCallbackFile(;) 397 INTERFACE_IArchiveGetDiskProperty(;) 398 399 STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); 400 401 STDMETHOD(CryptoGetTextPassword)(BSTR *password); 402 403 CArchiveExtractCallback(); 404 InitForMulti(bool multiArchives,NExtract::NPathMode::EEnum pathMode,NExtract::NOverwriteMode::EEnum overwriteMode,bool keepAndReplaceEmptyDirPrefixes)405 void InitForMulti(bool multiArchives, 406 NExtract::NPathMode::EEnum pathMode, 407 NExtract::NOverwriteMode::EEnum overwriteMode, 408 bool keepAndReplaceEmptyDirPrefixes) 409 { 410 _multiArchives = multiArchives; 411 _pathMode = pathMode; 412 _overwriteMode = overwriteMode; 413 _keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes; 414 NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0; 415 } 416 417 #ifndef _SFX 418 SetHashMethods(IHashCalc * hash)419 void SetHashMethods(IHashCalc *hash) 420 { 421 if (!hash) 422 return; 423 _hashStreamSpec = new COutStreamWithHash; 424 _hashStream = _hashStreamSpec; 425 _hashStreamSpec->_hash = hash; 426 } 427 428 #endif 429 430 void Init( 431 const CExtractNtOptions &ntOptions, 432 const NWildcard::CCensorNode *wildcardCensor, 433 const CArc *arc, 434 IFolderArchiveExtractCallback *extractCallback2, 435 bool stdOutMode, bool testMode, 436 const FString &directoryPath, 437 const UStringVector &removePathParts, bool removePartsForAltStreams, 438 UInt64 packSize); 439 440 441 #ifdef SUPPORT_LINKS 442 443 private: 444 CHardLinks _hardLinks; 445 CLinkInfo _link; 446 447 // FString _CopyFile_Path; 448 // HRESULT MyCopyFile(ISequentialOutStream *outStream); 449 HRESULT Link(const FString &fullProcessedPath); 450 HRESULT ReadLink(); 451 452 public: 453 // call PrepareHardLinks() after Init() 454 HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items 455 456 #endif 457 458 459 #ifdef SUPPORT_ALT_STREAMS 460 CObjectVector<CIndexToPathPair> _renamedFiles; 461 #endif 462 463 // call it after Init() 464 465 #ifndef _SFX SetBaseParentFolderIndex(UInt32 indexInArc)466 void SetBaseParentFolderIndex(UInt32 indexInArc) 467 { 468 _baseParentFolder = indexInArc; 469 _use_baseParentFolder_mode = true; 470 } 471 #endif 472 473 HRESULT CloseArc(); 474 475 private: ClearExtractedDirsInfo()476 void ClearExtractedDirsInfo() 477 { 478 _extractedFolders.Clear(); 479 #ifndef _WIN32 480 // _delayedSymLinks.Clear(); 481 #endif 482 } 483 484 HRESULT Read_fi_Props(); 485 void CorrectPathParts(); 486 void CreateFolders(); 487 488 bool _isRenamed; 489 HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit); 490 HRESULT GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit); 491 HRESULT GetItem(UInt32 index); 492 493 HRESULT CloseFile(); 494 HRESULT CloseReparseAndFile(); 495 HRESULT CloseReparseAndFile2(); 496 HRESULT SetDirsTimes(); 497 498 const void *NtReparse_Data; 499 UInt32 NtReparse_Size; 500 501 #ifdef SUPPORT_LINKS 502 HRESULT SetFromLinkPath( 503 const FString &fullProcessedPath, 504 const CLinkInfo &linkInfo, 505 bool &linkWasSet); 506 #endif 507 }; 508 509 510 struct CArchiveExtractCallback_Closer 511 { 512 CArchiveExtractCallback *_ref; 513 CArchiveExtractCallback_CloserCArchiveExtractCallback_Closer514 CArchiveExtractCallback_Closer(CArchiveExtractCallback *ref): _ref(ref) {} 515 CloseCArchiveExtractCallback_Closer516 HRESULT Close() 517 { 518 HRESULT res = S_OK; 519 if (_ref) 520 { 521 res = _ref->CloseArc(); 522 _ref = NULL; 523 } 524 return res; 525 } 526 ~CArchiveExtractCallback_CloserCArchiveExtractCallback_Closer527 ~CArchiveExtractCallback_Closer() 528 { 529 Close(); 530 } 531 }; 532 533 534 bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); 535 536 #endif 537