1 // UpdateCallbackConsole.cpp 2 3 #include "StdAfx.h" 4 5 #include "../../../Common/IntToString.h" 6 7 #include "../../../Windows/ErrorMsg.h" 8 9 #ifndef _7ZIP_ST 10 #include "../../../Windows/Synchronization.h" 11 #endif 12 13 #include "ConsoleClose.h" 14 #include "UserInputUtils.h" 15 #include "UpdateCallbackConsole.h" 16 17 using namespace NWindows; 18 19 #ifndef _7ZIP_ST 20 static NSynchronization::CCriticalSection g_CriticalSection; 21 #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); 22 #else 23 #define MT_LOCK 24 #endif 25 26 static const wchar_t * const kEmptyFileAlias = L"[Content]"; 27 28 static const char * const kOpenArchiveMessage = "Open archive: "; 29 static const char * const kCreatingArchiveMessage = "Creating archive: "; 30 static const char * const kUpdatingArchiveMessage = "Updating archive: "; 31 static const char * const kScanningMessage = "Scanning the drive:"; 32 33 static const char * const kError = "ERROR: "; 34 static const char * const kWarning = "WARNING: "; 35 36 static HRESULT CheckBreak2() 37 { 38 return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; 39 } 40 41 HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); 42 HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); 43 44 void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags); 45 46 void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc); 47 48 HRESULT CUpdateCallbackConsole::OpenResult( 49 const CCodecs *codecs, const CArchiveLink &arcLink, 50 const wchar_t *name, HRESULT result) 51 { 52 ClosePercents2(); 53 54 FOR_VECTOR (level, arcLink.Arcs) 55 { 56 const CArc &arc = arcLink.Arcs[level]; 57 const CArcErrorInfo &er = arc.ErrorInfo; 58 59 UInt32 errorFlags = er.GetErrorFlags(); 60 61 if (errorFlags != 0 || !er.ErrorMessage.IsEmpty()) 62 { 63 if (_se) 64 { 65 *_se << endl; 66 if (level != 0) 67 *_se << arc.Path << endl; 68 } 69 70 if (errorFlags != 0) 71 { 72 if (_se) 73 PrintErrorFlags(*_se, "ERRORS:", errorFlags); 74 } 75 76 if (!er.ErrorMessage.IsEmpty()) 77 { 78 if (_se) 79 *_se << "ERRORS:" << endl << er.ErrorMessage << endl; 80 } 81 82 if (_se) 83 { 84 *_se << endl; 85 _se->Flush(); 86 } 87 } 88 89 UInt32 warningFlags = er.GetWarningFlags(); 90 91 if (warningFlags != 0 || !er.WarningMessage.IsEmpty()) 92 { 93 if (_so) 94 { 95 *_so << endl; 96 if (level != 0) 97 *_so << arc.Path << endl; 98 } 99 100 if (warningFlags != 0) 101 { 102 if (_so) 103 PrintErrorFlags(*_so, "WARNINGS:", warningFlags); 104 } 105 106 if (!er.WarningMessage.IsEmpty()) 107 { 108 if (_so) 109 *_so << "WARNINGS:" << endl << er.WarningMessage << endl; 110 } 111 112 if (_so) 113 { 114 *_so << endl; 115 if (NeedFlush) 116 _so->Flush(); 117 } 118 } 119 120 121 if (er.ErrorFormatIndex >= 0) 122 { 123 if (_so) 124 { 125 Print_ErrorFormatIndex_Warning(_so, codecs, arc); 126 if (NeedFlush) 127 _so->Flush(); 128 } 129 } 130 } 131 132 if (result == S_OK) 133 { 134 if (_so) 135 { 136 RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink)); 137 *_so << endl; 138 } 139 } 140 else 141 { 142 if (_so) 143 _so->Flush(); 144 if (_se) 145 { 146 *_se << kError; 147 _se->NormalizePrint_wstr(name); 148 *_se << endl; 149 HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink); 150 RINOK(res); 151 _se->Flush(); 152 } 153 } 154 155 return S_OK; 156 } 157 158 HRESULT CUpdateCallbackConsole::StartScanning() 159 { 160 if (_so) 161 *_so << kScanningMessage << endl; 162 _percent.Command = "Scan "; 163 return S_OK; 164 } 165 166 HRESULT CUpdateCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */) 167 { 168 if (NeedPercents()) 169 { 170 _percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams; 171 _percent.Completed = st.GetTotalBytes(); 172 _percent.FileName = fs2us(path); 173 _percent.Print(); 174 } 175 176 return CheckBreak(); 177 } 178 179 void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, bool isWarning) 180 { 181 ClosePercents2(); 182 183 if (_se) 184 { 185 if (_so) 186 _so->Flush(); 187 188 *_se << endl << (isWarning ? kWarning : kError) 189 << NError::MyFormatMessage(systemError) 190 << endl; 191 _se->NormalizePrint_UString(fs2us(path)); 192 *_se << endl << endl; 193 _se->Flush(); 194 } 195 } 196 197 198 HRESULT CCallbackConsoleBase::ScanError_Base(const FString &path, DWORD systemError) 199 { 200 MT_LOCK 201 202 ScanErrors.AddError(path, systemError); 203 CommonError(path, systemError, true); 204 205 return S_OK; 206 } 207 208 HRESULT CCallbackConsoleBase::OpenFileError_Base(const FString &path, DWORD systemError) 209 { 210 MT_LOCK 211 FailedFiles.AddError(path, systemError); 212 /* 213 if (systemError == ERROR_SHARING_VIOLATION) 214 { 215 */ 216 CommonError(path, systemError, true); 217 return S_FALSE; 218 /* 219 } 220 return systemError; 221 */ 222 } 223 224 HRESULT CCallbackConsoleBase::ReadingFileError_Base(const FString &path, DWORD systemError) 225 { 226 MT_LOCK 227 CommonError(path, systemError, false); 228 return HRESULT_FROM_WIN32(systemError); 229 } 230 231 HRESULT CUpdateCallbackConsole::ScanError(const FString &path, DWORD systemError) 232 { 233 return ScanError_Base(path, systemError); 234 } 235 236 237 static void PrintPropPair(AString &s, const char *name, UInt64 val) 238 { 239 char temp[32]; 240 ConvertUInt64ToString(val, temp); 241 s += name; 242 s += ": "; 243 s += temp; 244 } 245 246 void PrintSize_bytes_Smart(AString &s, UInt64 val); 247 void Print_DirItemsStat(AString &s, const CDirItemsStat &st); 248 void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st); 249 250 HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st) 251 { 252 if (NeedPercents()) 253 { 254 _percent.ClosePrint(true); 255 _percent.ClearCurState(); 256 } 257 258 if (_so) 259 { 260 AString s; 261 Print_DirItemsStat(s, st); 262 *_so << s << endl << endl; 263 } 264 return S_OK; 265 } 266 267 static const char * const k_StdOut_ArcName = "StdOut"; 268 269 HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name) 270 { 271 if (_so) 272 { 273 *_so << kOpenArchiveMessage; 274 if (name) 275 *_so << name; 276 else 277 *_so << k_StdOut_ArcName; 278 *_so << endl; 279 } 280 return S_OK; 281 } 282 283 HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) 284 { 285 if (_so) 286 { 287 *_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage); 288 if (name) 289 _so->NormalizePrint_wstr(name); 290 else 291 *_so << k_StdOut_ArcName; 292 *_so << endl << endl; 293 } 294 return S_OK; 295 } 296 297 HRESULT CUpdateCallbackConsole::FinishArchive(const CFinishArchiveStat &st) 298 { 299 ClosePercents2(); 300 301 if (_so) 302 { 303 AString s; 304 // Print_UInt64_and_String(s, _percent.Files == 1 ? "file" : "files", _percent.Files); 305 PrintPropPair(s, "Files read from disk", _percent.Files); 306 s.Add_LF(); 307 s += "Archive size: "; 308 PrintSize_bytes_Smart(s, st.OutArcFileSize); 309 s.Add_LF(); 310 *_so << endl; 311 *_so << s; 312 // *_so << endl; 313 } 314 315 return S_OK; 316 } 317 318 HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size) 319 { 320 if (_so) 321 { 322 *_so << "Write SFX: "; 323 *_so << name; 324 AString s (" : "); 325 PrintSize_bytes_Smart(s, size); 326 *_so << s << endl; 327 } 328 return S_OK; 329 } 330 331 332 HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */) 333 { 334 if (LogLevel > 0 && _so) 335 { 336 ClosePercents_for_so(); 337 338 if (!DeleteMessageWasShown) 339 { 340 if (_so) 341 *_so << endl << ": Removing files after including to archive" << endl; 342 } 343 344 { 345 { 346 _tempA = "Removing"; 347 _tempA.Add_Space(); 348 *_so << _tempA; 349 _tempU = fs2us(path); 350 _so->Normalize_UString(_tempU); 351 _so->PrintUString(_tempU, _tempA); 352 *_so << endl; 353 if (NeedFlush) 354 _so->Flush(); 355 } 356 } 357 } 358 359 if (!DeleteMessageWasShown) 360 { 361 if (NeedPercents()) 362 { 363 _percent.ClearCurState(); 364 } 365 DeleteMessageWasShown = true; 366 } 367 else 368 { 369 _percent.Files++; 370 } 371 372 if (NeedPercents()) 373 { 374 // if (!FullLog) 375 { 376 _percent.Command = "Removing"; 377 _percent.FileName = fs2us(path); 378 } 379 _percent.Print(); 380 } 381 382 return S_OK; 383 } 384 385 386 HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving() 387 { 388 ClosePercents2(); 389 if (_so && DeleteMessageWasShown) 390 *_so << endl; 391 return S_OK; 392 } 393 394 HRESULT CUpdateCallbackConsole::CheckBreak() 395 { 396 return CheckBreak2(); 397 } 398 399 /* 400 HRESULT CUpdateCallbackConsole::Finalize() 401 { 402 // MT_LOCK 403 return S_OK; 404 } 405 */ 406 407 408 void static PrintToDoStat(CStdOutStream *_so, const CDirItemsStat2 &stat, const char *name) 409 { 410 AString s; 411 Print_DirItemsStat2(s, stat); 412 *_so << name << ": " << s << endl; 413 } 414 415 HRESULT CUpdateCallbackConsole::SetNumItems(const CArcToDoStat &stat) 416 { 417 if (_so) 418 { 419 ClosePercents_for_so(); 420 if (!stat.DeleteData.IsEmpty()) 421 { 422 *_so << endl; 423 PrintToDoStat(_so, stat.DeleteData, "Delete data from archive"); 424 } 425 if (!stat.OldData.IsEmpty()) 426 PrintToDoStat(_so, stat.OldData, "Keep old data in archive"); 427 // if (!stat.NewData.IsEmpty()) 428 { 429 PrintToDoStat(_so, stat.NewData, "Add new data to archive"); 430 } 431 *_so << endl; 432 } 433 return S_OK; 434 } 435 436 HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size) 437 { 438 MT_LOCK 439 if (NeedPercents()) 440 { 441 _percent.Total = size; 442 _percent.Print(); 443 } 444 return S_OK; 445 } 446 447 HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue) 448 { 449 MT_LOCK 450 if (completeValue) 451 { 452 if (NeedPercents()) 453 { 454 _percent.Completed = *completeValue; 455 _percent.Print(); 456 } 457 } 458 return CheckBreak2(); 459 } 460 461 HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */) 462 { 463 return CheckBreak2(); 464 } 465 466 HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *command, bool showInLog) 467 { 468 MT_LOCK 469 470 bool show2 = (showInLog && _so); 471 472 if (show2) 473 { 474 ClosePercents_for_so(); 475 476 _tempA = command; 477 if (name) 478 _tempA.Add_Space(); 479 *_so << _tempA; 480 481 _tempU.Empty(); 482 if (name) 483 { 484 _tempU = name; 485 _so->Normalize_UString(_tempU); 486 } 487 _so->PrintUString(_tempU, _tempA); 488 *_so << endl; 489 if (NeedFlush) 490 _so->Flush(); 491 } 492 493 if (NeedPercents()) 494 { 495 if (PercentsNameLevel >= 1) 496 { 497 _percent.FileName.Empty(); 498 _percent.Command.Empty(); 499 if (PercentsNameLevel > 1 || !show2) 500 { 501 _percent.Command = command; 502 if (name) 503 _percent.FileName = name; 504 } 505 } 506 _percent.Print(); 507 } 508 509 return CheckBreak2(); 510 } 511 512 HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool /* isDir */, bool isAnti, UInt32 mode) 513 { 514 if (StdOutMode) 515 return S_OK; 516 517 if (!name || name[0] == 0) 518 name = kEmptyFileAlias; 519 520 unsigned requiredLevel = 1; 521 522 const char *s; 523 if (mode == NUpdateNotifyOp::kAdd || 524 mode == NUpdateNotifyOp::kUpdate) 525 { 526 if (isAnti) 527 s = "Anti"; 528 else if (mode == NUpdateNotifyOp::kAdd) 529 s = "+"; 530 else 531 s = "U"; 532 } 533 else 534 { 535 requiredLevel = 3; 536 if (mode == NUpdateNotifyOp::kAnalyze) 537 s = "A"; 538 else 539 s = "Reading"; 540 } 541 542 return PrintProgress(name, s, LogLevel >= requiredLevel); 543 } 544 545 HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError) 546 { 547 return OpenFileError_Base(path, systemError); 548 } 549 550 HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError) 551 { 552 return ReadingFileError_Base(path, systemError); 553 } 554 555 HRESULT CUpdateCallbackConsole::SetOperationResult(Int32) 556 { 557 MT_LOCK 558 _percent.Files++; 559 return S_OK; 560 } 561 562 void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest); 563 564 HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) 565 { 566 // if (StdOutMode) return S_OK; 567 568 if (opRes != NArchive::NExtract::NOperationResult::kOK) 569 { 570 ClosePercents2(); 571 572 if (_se) 573 { 574 if (_so) 575 _so->Flush(); 576 577 AString s; 578 SetExtractErrorMessage(opRes, isEncrypted, s); 579 *_se << s << " : " << endl; 580 _se->NormalizePrint_wstr(name); 581 *_se << endl << endl; 582 _se->Flush(); 583 } 584 return S_OK; 585 } 586 return S_OK; 587 } 588 589 590 HRESULT CUpdateCallbackConsole::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool /* isDir */) 591 { 592 // if (StdOutMode) return S_OK; 593 594 char temp[16]; 595 const char *s; 596 597 unsigned requiredLevel = 1; 598 599 switch (op) 600 { 601 case NUpdateNotifyOp::kAdd: s = "+"; break; 602 case NUpdateNotifyOp::kUpdate: s = "U"; break; 603 case NUpdateNotifyOp::kAnalyze: s = "A"; requiredLevel = 3; break; 604 case NUpdateNotifyOp::kReplicate: s = "="; requiredLevel = 3; break; 605 case NUpdateNotifyOp::kRepack: s = "R"; requiredLevel = 2; break; 606 case NUpdateNotifyOp::kSkip: s = "."; requiredLevel = 2; break; 607 case NUpdateNotifyOp::kDelete: s = "D"; requiredLevel = 3; break; 608 case NUpdateNotifyOp::kHeader: s = "Header creation"; requiredLevel = 100; break; 609 default: 610 { 611 temp[0] = 'o'; 612 temp[1] = 'p'; 613 ConvertUInt64ToString(op, temp + 2); 614 s = temp; 615 } 616 } 617 618 return PrintProgress(name, s, LogLevel >= requiredLevel); 619 } 620 621 /* 622 HRESULT CUpdateCallbackConsole::SetPassword(const UString & 623 #ifndef _NO_CRYPTO 624 password 625 #endif 626 ) 627 { 628 #ifndef _NO_CRYPTO 629 PasswordIsDefined = true; 630 Password = password; 631 #endif 632 return S_OK; 633 } 634 */ 635 636 HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) 637 { 638 COM_TRY_BEGIN 639 640 *password = NULL; 641 642 #ifdef _NO_CRYPTO 643 644 *passwordIsDefined = false; 645 return S_OK; 646 647 #else 648 649 if (!PasswordIsDefined) 650 { 651 if (AskPassword) 652 { 653 RINOK(GetPassword_HRESULT(_so, Password)); 654 PasswordIsDefined = true; 655 } 656 } 657 *passwordIsDefined = BoolToInt(PasswordIsDefined); 658 return StringToBstr(Password, password); 659 660 #endif 661 662 COM_TRY_END 663 } 664 665 HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password) 666 { 667 COM_TRY_BEGIN 668 669 *password = NULL; 670 671 #ifdef _NO_CRYPTO 672 673 return E_NOTIMPL; 674 675 #else 676 677 if (!PasswordIsDefined) 678 { 679 { 680 RINOK(GetPassword_HRESULT(_so, Password)) 681 PasswordIsDefined = true; 682 } 683 } 684 return StringToBstr(Password, password); 685 686 #endif 687 COM_TRY_END 688 } 689 690 HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool /* isDir */) 691 { 692 if (StdOutMode) 693 return S_OK; 694 695 if (LogLevel > 7) 696 { 697 if (!name || name[0] == 0) 698 name = kEmptyFileAlias; 699 return PrintProgress(name, "D", true); 700 } 701 return S_OK; 702 } 703