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
CheckBreak2()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
OpenResult(const CCodecs * codecs,const CArchiveLink & arcLink,const wchar_t * name,HRESULT result)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
StartScanning()158 HRESULT CUpdateCallbackConsole::StartScanning()
159 {
160 if (_so)
161 *_so << kScanningMessage << endl;
162 _percent.Command = "Scan ";
163 return S_OK;
164 }
165
ScanProgress(const CDirItemsStat & st,const FString & path,bool)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
CommonError(const FString & path,DWORD systemError,bool isWarning)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
ScanError_Base(const FString & path,DWORD systemError)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
OpenFileError_Base(const FString & path,DWORD systemError)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
ReadingFileError_Base(const FString & path,DWORD systemError)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
ScanError(const FString & path,DWORD systemError)231 HRESULT CUpdateCallbackConsole::ScanError(const FString &path, DWORD systemError)
232 {
233 return ScanError_Base(path, systemError);
234 }
235
236
PrintPropPair(AString & s,const char * name,UInt64 val)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
FinishScanning(const CDirItemsStat & st)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
StartOpenArchive(const wchar_t * name)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
StartArchive(const wchar_t * name,bool updating)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
FinishArchive(const CFinishArchiveStat & st)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
WriteSfx(const wchar_t * name,UInt64 size)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
DeletingAfterArchiving(const FString & path,bool)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
FinishDeletingAfterArchiving()386 HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving()
387 {
388 ClosePercents2();
389 if (_so && DeleteMessageWasShown)
390 *_so << endl;
391 return S_OK;
392 }
393
CheckBreak()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
PrintToDoStat(CStdOutStream * _so,const CDirItemsStat2 & stat,const char * name)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
SetNumItems(const CArcToDoStat & stat)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
SetTotal(UInt64 size)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
SetCompleted(const UInt64 * completeValue)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
SetRatioInfo(const UInt64 *,const UInt64 *)461 HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)
462 {
463 return CheckBreak2();
464 }
465
PrintProgress(const wchar_t * name,const char * command,bool showInLog)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
GetStream(const wchar_t * name,bool,bool isAnti,UInt32 mode)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
OpenFileError(const FString & path,DWORD systemError)545 HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError)
546 {
547 return OpenFileError_Base(path, systemError);
548 }
549
ReadingFileError(const FString & path,DWORD systemError)550 HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError)
551 {
552 return ReadingFileError_Base(path, systemError);
553 }
554
SetOperationResult(Int32)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
ReportExtractResult(Int32 opRes,Int32 isEncrypted,const wchar_t * name)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
ReportUpdateOpeartion(UInt32 op,const wchar_t * name,bool)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
CryptoGetTextPassword2(Int32 * passwordIsDefined,BSTR * password)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
CryptoGetTextPassword(BSTR * password)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
ShowDeleteFile(const wchar_t * name,bool)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