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