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 << name << endl;
147 HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);
148 RINOK(res);
149 _se->Flush();
150 }
151 }
152
153 return S_OK;
154 }
155
StartScanning()156 HRESULT CUpdateCallbackConsole::StartScanning()
157 {
158 if (_so)
159 *_so << kScanningMessage << endl;
160 _percent.Command = "Scan ";
161 return S_OK;
162 }
163
ScanProgress(const CDirItemsStat & st,const FString & path,bool)164 HRESULT CUpdateCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)
165 {
166 if (NeedPercents())
167 {
168 _percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams;
169 _percent.Completed = st.GetTotalBytes();
170 _percent.FileName = fs2us(path);
171 _percent.Print();
172 }
173
174 return CheckBreak();
175 }
176
CommonError(const FString & path,DWORD systemError,bool isWarning)177 void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, bool isWarning)
178 {
179 ClosePercents2();
180
181 if (_se)
182 {
183 if (_so)
184 _so->Flush();
185
186 *_se << endl << (isWarning ? kWarning : kError)
187 << NError::MyFormatMessage(systemError)
188 << endl << fs2us(path) << endl << endl;
189 _se->Flush();
190 }
191 }
192
193
ScanError_Base(const FString & path,DWORD systemError)194 HRESULT CCallbackConsoleBase::ScanError_Base(const FString &path, DWORD systemError)
195 {
196 MT_LOCK
197
198 ScanErrors.AddError(path, systemError);
199 CommonError(path, systemError, true);
200
201 return S_OK;
202 }
203
OpenFileError_Base(const FString & path,DWORD systemError)204 HRESULT CCallbackConsoleBase::OpenFileError_Base(const FString &path, DWORD systemError)
205 {
206 MT_LOCK
207 FailedFiles.AddError(path, systemError);
208 /*
209 if (systemError == ERROR_SHARING_VIOLATION)
210 {
211 */
212 CommonError(path, systemError, true);
213 return S_FALSE;
214 /*
215 }
216 return systemError;
217 */
218 }
219
ReadingFileError_Base(const FString & path,DWORD systemError)220 HRESULT CCallbackConsoleBase::ReadingFileError_Base(const FString &path, DWORD systemError)
221 {
222 MT_LOCK
223 CommonError(path, systemError, false);
224 return HRESULT_FROM_WIN32(systemError);
225 }
226
ScanError(const FString & path,DWORD systemError)227 HRESULT CUpdateCallbackConsole::ScanError(const FString &path, DWORD systemError)
228 {
229 return ScanError_Base(path, systemError);
230 }
231
232
PrintPropPair(AString & s,const char * name,UInt64 val)233 static void PrintPropPair(AString &s, const char *name, UInt64 val)
234 {
235 char temp[32];
236 ConvertUInt64ToString(val, temp);
237 s += name;
238 s += ": ";
239 s += temp;
240 }
241
242 void PrintSize_bytes_Smart(AString &s, UInt64 val);
243 void Print_DirItemsStat(AString &s, const CDirItemsStat &st);
244 void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st);
245
FinishScanning(const CDirItemsStat & st)246 HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st)
247 {
248 if (NeedPercents())
249 {
250 _percent.ClosePrint(true);
251 _percent.ClearCurState();
252 }
253
254 if (_so)
255 {
256 AString s;
257 Print_DirItemsStat(s, st);
258 *_so << s << endl << endl;
259 }
260 return S_OK;
261 }
262
263 static const char * const k_StdOut_ArcName = "StdOut";
264
StartOpenArchive(const wchar_t * name)265 HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name)
266 {
267 if (_so)
268 {
269 *_so << kOpenArchiveMessage;
270 if (name)
271 *_so << name;
272 else
273 *_so << k_StdOut_ArcName;
274 *_so << endl;
275 }
276 return S_OK;
277 }
278
StartArchive(const wchar_t * name,bool updating)279 HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)
280 {
281 if (_so)
282 {
283 *_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage);
284 if (name != 0)
285 *_so << name;
286 else
287 *_so << k_StdOut_ArcName;
288 *_so << endl << endl;
289 }
290 return S_OK;
291 }
292
FinishArchive(const CFinishArchiveStat & st)293 HRESULT CUpdateCallbackConsole::FinishArchive(const CFinishArchiveStat &st)
294 {
295 ClosePercents2();
296
297 if (_so)
298 {
299 AString s;
300 // Print_UInt64_and_String(s, _percent.Files == 1 ? "file" : "files", _percent.Files);
301 PrintPropPair(s, "Files read from disk", _percent.Files);
302 s.Add_LF();
303 s += "Archive size: ";
304 PrintSize_bytes_Smart(s, st.OutArcFileSize);
305 s.Add_LF();
306 *_so << endl;
307 *_so << s;
308 // *_so << endl;
309 }
310
311 return S_OK;
312 }
313
WriteSfx(const wchar_t * name,UInt64 size)314 HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size)
315 {
316 if (_so)
317 {
318 *_so << "Write SFX: ";
319 *_so << name;
320 AString s (" : ");
321 PrintSize_bytes_Smart(s, size);
322 *_so << s << endl;
323 }
324 return S_OK;
325 }
326
327
DeletingAfterArchiving(const FString & path,bool)328 HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */)
329 {
330 if (LogLevel > 0 && _so)
331 {
332 ClosePercents_for_so();
333
334 if (!DeleteMessageWasShown)
335 {
336 if (_so)
337 *_so << endl << ": Removing files after including to archive" << endl;
338 }
339
340 {
341 {
342 _tempA = "Removing";
343 _tempA.Add_Space();
344 *_so << _tempA;
345 _tempU = fs2us(path);
346 _so->PrintUString(_tempU, _tempA);
347 *_so << endl;
348 if (NeedFlush)
349 _so->Flush();
350 }
351 }
352 }
353
354 if (!DeleteMessageWasShown)
355 {
356 if (NeedPercents())
357 {
358 _percent.ClearCurState();
359 }
360 DeleteMessageWasShown = true;
361 }
362 else
363 {
364 _percent.Files++;
365 }
366
367 if (NeedPercents())
368 {
369 // if (!FullLog)
370 {
371 _percent.Command = "Removing";
372 _percent.FileName = fs2us(path);
373 }
374 _percent.Print();
375 }
376
377 return S_OK;
378 }
379
380
FinishDeletingAfterArchiving()381 HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving()
382 {
383 ClosePercents2();
384 if (_so && DeleteMessageWasShown)
385 *_so << endl;
386 return S_OK;
387 }
388
CheckBreak()389 HRESULT CUpdateCallbackConsole::CheckBreak()
390 {
391 return CheckBreak2();
392 }
393
394 /*
395 HRESULT CUpdateCallbackConsole::Finalize()
396 {
397 // MT_LOCK
398 return S_OK;
399 }
400 */
401
402
PrintToDoStat(CStdOutStream * _so,const CDirItemsStat2 & stat,const char * name)403 void static PrintToDoStat(CStdOutStream *_so, const CDirItemsStat2 &stat, const char *name)
404 {
405 AString s;
406 Print_DirItemsStat2(s, stat);
407 *_so << name << ": " << s << endl;
408 }
409
SetNumItems(const CArcToDoStat & stat)410 HRESULT CUpdateCallbackConsole::SetNumItems(const CArcToDoStat &stat)
411 {
412 if (_so)
413 {
414 ClosePercents_for_so();
415 if (!stat.DeleteData.IsEmpty())
416 {
417 *_so << endl;
418 PrintToDoStat(_so, stat.DeleteData, "Delete data from archive");
419 }
420 if (!stat.OldData.IsEmpty())
421 PrintToDoStat(_so, stat.OldData, "Keep old data in archive");
422 // if (!stat.NewData.IsEmpty())
423 {
424 PrintToDoStat(_so, stat.NewData, "Add new data to archive");
425 }
426 *_so << endl;
427 }
428 return S_OK;
429 }
430
SetTotal(UInt64 size)431 HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)
432 {
433 MT_LOCK
434 if (NeedPercents())
435 {
436 _percent.Total = size;
437 _percent.Print();
438 }
439 return S_OK;
440 }
441
SetCompleted(const UInt64 * completeValue)442 HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)
443 {
444 MT_LOCK
445 if (completeValue)
446 {
447 if (NeedPercents())
448 {
449 _percent.Completed = *completeValue;
450 _percent.Print();
451 }
452 }
453 return CheckBreak2();
454 }
455
SetRatioInfo(const UInt64 *,const UInt64 *)456 HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)
457 {
458 return CheckBreak2();
459 }
460
PrintProgress(const wchar_t * name,const char * command,bool showInLog)461 HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *command, bool showInLog)
462 {
463 MT_LOCK
464
465 bool show2 = (showInLog && _so);
466
467 if (show2)
468 {
469 ClosePercents_for_so();
470
471 _tempA = command;
472 if (name)
473 _tempA.Add_Space();
474 *_so << _tempA;
475
476 _tempU.Empty();
477 if (name)
478 _tempU = name;
479 _so->PrintUString(_tempU, _tempA);
480 *_so << endl;
481 if (NeedFlush)
482 _so->Flush();
483 }
484
485 if (NeedPercents())
486 {
487 if (PercentsNameLevel >= 1)
488 {
489 _percent.FileName.Empty();
490 _percent.Command.Empty();
491 if (PercentsNameLevel > 1 || !show2)
492 {
493 _percent.Command = command;
494 if (name)
495 _percent.FileName = name;
496 }
497 }
498 _percent.Print();
499 }
500
501 return CheckBreak2();
502 }
503
GetStream(const wchar_t * name,bool,bool isAnti,UInt32 mode)504 HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool /* isDir */, bool isAnti, UInt32 mode)
505 {
506 if (StdOutMode)
507 return S_OK;
508
509 if (!name || name[0] == 0)
510 name = kEmptyFileAlias;
511
512 unsigned requiredLevel = 1;
513
514 const char *s;
515 if (mode == NUpdateNotifyOp::kAdd ||
516 mode == NUpdateNotifyOp::kUpdate)
517 {
518 if (isAnti)
519 s = "Anti";
520 else if (mode == NUpdateNotifyOp::kAdd)
521 s = "+";
522 else
523 s = "U";
524 }
525 else
526 {
527 requiredLevel = 3;
528 if (mode == NUpdateNotifyOp::kAnalyze)
529 s = "A";
530 else
531 s = "Reading";
532 }
533
534 return PrintProgress(name, s, LogLevel >= requiredLevel);
535 }
536
OpenFileError(const FString & path,DWORD systemError)537 HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError)
538 {
539 return OpenFileError_Base(path, systemError);
540 }
541
ReadingFileError(const FString & path,DWORD systemError)542 HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError)
543 {
544 return ReadingFileError_Base(path, systemError);
545 }
546
SetOperationResult(Int32)547 HRESULT CUpdateCallbackConsole::SetOperationResult(Int32)
548 {
549 MT_LOCK
550 _percent.Files++;
551 return S_OK;
552 }
553
554 void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest);
555
ReportExtractResult(Int32 opRes,Int32 isEncrypted,const wchar_t * name)556 HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
557 {
558 // if (StdOutMode) return S_OK;
559
560 if (opRes != NArchive::NExtract::NOperationResult::kOK)
561 {
562 ClosePercents2();
563
564 if (_se)
565 {
566 if (_so)
567 _so->Flush();
568
569 AString s;
570 SetExtractErrorMessage(opRes, isEncrypted, s);
571 *_se << s << " : " << endl << name << endl << endl;
572 _se->Flush();
573 }
574 return S_OK;
575 }
576 return S_OK;
577 }
578
579
ReportUpdateOpeartion(UInt32 op,const wchar_t * name,bool)580 HRESULT CUpdateCallbackConsole::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool /* isDir */)
581 {
582 // if (StdOutMode) return S_OK;
583
584 char temp[16];
585 const char *s;
586
587 unsigned requiredLevel = 1;
588
589 switch (op)
590 {
591 case NUpdateNotifyOp::kAdd: s = "+"; break;
592 case NUpdateNotifyOp::kUpdate: s = "U"; break;
593 case NUpdateNotifyOp::kAnalyze: s = "A"; requiredLevel = 3; break;
594 case NUpdateNotifyOp::kReplicate: s = "="; requiredLevel = 3; break;
595 case NUpdateNotifyOp::kRepack: s = "R"; requiredLevel = 2; break;
596 case NUpdateNotifyOp::kSkip: s = "."; requiredLevel = 2; break;
597 case NUpdateNotifyOp::kDelete: s = "D"; requiredLevel = 3; break;
598 case NUpdateNotifyOp::kHeader: s = "Header creation"; requiredLevel = 100; break;
599 default:
600 {
601 temp[0] = 'o';
602 temp[1] = 'p';
603 ConvertUInt64ToString(op, temp + 2);
604 s = temp;
605 }
606 }
607
608 return PrintProgress(name, s, LogLevel >= requiredLevel);
609 }
610
611 /*
612 HRESULT CUpdateCallbackConsole::SetPassword(const UString &
613 #ifndef _NO_CRYPTO
614 password
615 #endif
616 )
617 {
618 #ifndef _NO_CRYPTO
619 PasswordIsDefined = true;
620 Password = password;
621 #endif
622 return S_OK;
623 }
624 */
625
CryptoGetTextPassword2(Int32 * passwordIsDefined,BSTR * password)626 HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
627 {
628 COM_TRY_BEGIN
629
630 *password = NULL;
631
632 #ifdef _NO_CRYPTO
633
634 *passwordIsDefined = false;
635 return S_OK;
636
637 #else
638
639 if (!PasswordIsDefined)
640 {
641 if (AskPassword)
642 {
643 RINOK(GetPassword_HRESULT(_so, Password));
644 PasswordIsDefined = true;
645 }
646 }
647 *passwordIsDefined = BoolToInt(PasswordIsDefined);
648 return StringToBstr(Password, password);
649
650 #endif
651
652 COM_TRY_END
653 }
654
CryptoGetTextPassword(BSTR * password)655 HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)
656 {
657 COM_TRY_BEGIN
658
659 *password = NULL;
660
661 #ifdef _NO_CRYPTO
662
663 return E_NOTIMPL;
664
665 #else
666
667 if (!PasswordIsDefined)
668 {
669 {
670 RINOK(GetPassword_HRESULT(_so, Password))
671 PasswordIsDefined = true;
672 }
673 }
674 return StringToBstr(Password, password);
675
676 #endif
677 COM_TRY_END
678 }
679
ShowDeleteFile(const wchar_t * name,bool)680 HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool /* isDir */)
681 {
682 if (StdOutMode)
683 return S_OK;
684
685 if (LogLevel > 7)
686 {
687 if (!name || name[0] == 0)
688 name = kEmptyFileAlias;
689 return PrintProgress(name, "D", true);
690 }
691 return S_OK;
692 }
693