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 *kEmptyFileAlias = L"[Content]";
27
28 static const char *kOpenArchiveMessage = "Open archive: ";
29 static const char *kCreatingArchiveMessage = "Creating archive: ";
30 static const char *kUpdatingArchiveMessage = "Updating archive: ";
31 static const char *kScanningMessage = "Scanning the drive:";
32
33 static const char *kError = "ERROR: ";
34 static const char *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
FinishScanning(const CDirItemsStat & st)245 HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st)
246 {
247 if (NeedPercents())
248 {
249 _percent.ClosePrint(true);
250 _percent.ClearCurState();
251 }
252
253 if (_so)
254 {
255 AString s;
256 Print_DirItemsStat(s, st);
257 *_so << s << endl << endl;
258 }
259 return S_OK;
260 }
261
262 static const char *k_StdOut_ArcName = "StdOut";
263
StartOpenArchive(const wchar_t * name)264 HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name)
265 {
266 if (_so)
267 {
268 *_so << kOpenArchiveMessage;
269 if (name)
270 *_so << name;
271 else
272 *_so << k_StdOut_ArcName;
273 *_so << endl;
274 }
275 return S_OK;
276 }
277
StartArchive(const wchar_t * name,bool updating)278 HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)
279 {
280 if (_so)
281 {
282 *_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage);
283 if (name != 0)
284 *_so << name;
285 else
286 *_so << k_StdOut_ArcName;
287 *_so << endl << endl;
288 }
289 return S_OK;
290 }
291
FinishArchive(const CFinishArchiveStat & st)292 HRESULT CUpdateCallbackConsole::FinishArchive(const CFinishArchiveStat &st)
293 {
294 ClosePercents2();
295
296 if (_so)
297 {
298 AString s;
299 // Print_UInt64_and_String(s, _percent.Files == 1 ? "file" : "files", _percent.Files);
300 PrintPropPair(s, "Files read from disk", _percent.Files);
301 s.Add_LF();
302 s += "Archive size: ";
303 PrintSize_bytes_Smart(s, st.OutArcFileSize);
304 s.Add_LF();
305 *_so << endl;
306 *_so << s;
307 // *_so << endl;
308 }
309
310 return S_OK;
311 }
312
WriteSfx(const wchar_t * name,UInt64 size)313 HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size)
314 {
315 if (_so)
316 {
317 *_so << "Write SFX: ";
318 *_so << name;
319 AString s = " : ";
320 PrintSize_bytes_Smart(s, size);
321 *_so << s << endl;
322 }
323 return S_OK;
324 }
325
326
DeletingAfterArchiving(const FString & path,bool)327 HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */)
328 {
329 if (LogLevel > 0 && _so)
330 {
331 ClosePercents_for_so();
332
333 if (!DeleteMessageWasShown)
334 {
335 if (_so)
336 *_so << endl << ": Removing files after including to archive" << endl;
337 }
338
339 {
340 {
341 _tempA = "Removing";
342 _tempA.Add_Space();
343 *_so << _tempA;
344 _tempU = fs2us(path);
345 _so->PrintUString(_tempU, _tempA);
346 *_so << endl;
347 if (NeedFlush)
348 _so->Flush();
349 }
350 }
351 }
352
353 if (!DeleteMessageWasShown)
354 {
355 if (NeedPercents())
356 {
357 _percent.ClearCurState();
358 }
359 DeleteMessageWasShown = true;
360 }
361 else
362 {
363 _percent.Files++;
364 }
365
366 if (NeedPercents())
367 {
368 // if (!FullLog)
369 {
370 _percent.Command = "Removing";
371 _percent.FileName = fs2us(path);
372 }
373 _percent.Print();
374 }
375
376 return S_OK;
377 }
378
379
FinishDeletingAfterArchiving()380 HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving()
381 {
382 ClosePercents2();
383 if (_so && DeleteMessageWasShown)
384 *_so << endl;
385 return S_OK;
386 }
387
CheckBreak()388 HRESULT CUpdateCallbackConsole::CheckBreak()
389 {
390 return CheckBreak2();
391 }
392
393 /*
394 HRESULT CUpdateCallbackConsole::Finalize()
395 {
396 // MT_LOCK
397 return S_OK;
398 }
399 */
400
SetNumItems(UInt64 numItems)401 HRESULT CUpdateCallbackConsole::SetNumItems(UInt64 numItems)
402 {
403 if (_so)
404 {
405 ClosePercents_for_so();
406 AString s;
407 PrintPropPair(s, "Items to compress", numItems);
408 *_so << s << endl << endl;
409 }
410 return S_OK;
411 }
412
SetTotal(UInt64 size)413 HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)
414 {
415 MT_LOCK
416 if (NeedPercents())
417 {
418 _percent.Total = size;
419 _percent.Print();
420 }
421 return S_OK;
422 }
423
SetCompleted(const UInt64 * completeValue)424 HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)
425 {
426 MT_LOCK
427 if (completeValue)
428 {
429 if (NeedPercents())
430 {
431 _percent.Completed = *completeValue;
432 _percent.Print();
433 }
434 }
435 return CheckBreak2();
436 }
437
SetRatioInfo(const UInt64 *,const UInt64 *)438 HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)
439 {
440 return CheckBreak2();
441 }
442
PrintProgress(const wchar_t * name,const char * command,bool showInLog)443 HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *command, bool showInLog)
444 {
445 MT_LOCK
446
447 bool show2 = (showInLog && _so);
448
449 if (show2)
450 {
451 ClosePercents_for_so();
452
453 _tempA = command;
454 if (name)
455 _tempA.Add_Space();
456 *_so << _tempA;
457
458 _tempU.Empty();
459 if (name)
460 _tempU = name;
461 _so->PrintUString(_tempU, _tempA);
462 *_so << endl;
463 if (NeedFlush)
464 _so->Flush();
465 }
466
467 if (NeedPercents())
468 {
469 if (PercentsNameLevel >= 1)
470 {
471 _percent.FileName.Empty();
472 _percent.Command.Empty();
473 if (PercentsNameLevel > 1 || !show2)
474 {
475 _percent.Command = command;
476 if (name)
477 _percent.FileName = name;
478 }
479 }
480 _percent.Print();
481 }
482
483 return CheckBreak2();
484 }
485
GetStream(const wchar_t * name,bool,bool isAnti,UInt32 mode)486 HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool /* isDir */, bool isAnti, UInt32 mode)
487 {
488 if (StdOutMode)
489 return S_OK;
490
491 if (!name || name[0] == 0)
492 name = kEmptyFileAlias;
493
494 unsigned requiredLevel = 1;
495
496 const char *s;
497 if (mode == NUpdateNotifyOp::kAdd ||
498 mode == NUpdateNotifyOp::kUpdate)
499 {
500 if (isAnti)
501 s = "Anti";
502 else if (mode == NUpdateNotifyOp::kAdd)
503 s = "+";
504 else
505 s = "U";
506 }
507 else
508 {
509 requiredLevel = 3;
510 if (mode == NUpdateNotifyOp::kAnalyze)
511 s = "A";
512 else
513 s = "Reading";
514 }
515
516 return PrintProgress(name, s, LogLevel >= requiredLevel);
517 }
518
OpenFileError(const FString & path,DWORD systemError)519 HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError)
520 {
521 return OpenFileError_Base(path, systemError);
522 }
523
ReadingFileError(const FString & path,DWORD systemError)524 HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError)
525 {
526 return ReadingFileError_Base(path, systemError);
527 }
528
SetOperationResult(Int32)529 HRESULT CUpdateCallbackConsole::SetOperationResult(Int32)
530 {
531 MT_LOCK
532 _percent.Files++;
533 return S_OK;
534 }
535
536 void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest);
537
ReportExtractResult(Int32 opRes,Int32 isEncrypted,const wchar_t * name)538 HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
539 {
540 // if (StdOutMode) return S_OK;
541
542 if (opRes != NArchive::NExtract::NOperationResult::kOK)
543 {
544 ClosePercents2();
545
546 if (_se)
547 {
548 if (_so)
549 _so->Flush();
550
551 AString s;
552 SetExtractErrorMessage(opRes, isEncrypted, s);
553 *_se << s << " : " << endl << name << endl << endl;
554 _se->Flush();
555 }
556 return S_OK;
557 }
558 return S_OK;
559 }
560
561
ReportUpdateOpeartion(UInt32 op,const wchar_t * name,bool)562 HRESULT CUpdateCallbackConsole::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool /* isDir */)
563 {
564 // if (StdOutMode) return S_OK;
565
566 char temp[16];
567 const char *s;
568
569 unsigned requiredLevel = 1;
570
571 switch (op)
572 {
573 case NUpdateNotifyOp::kAdd: s = "+"; break;
574 case NUpdateNotifyOp::kUpdate: s = "U"; break;
575 case NUpdateNotifyOp::kAnalyze: s = "A"; requiredLevel = 3; break;
576 case NUpdateNotifyOp::kReplicate: s = "="; requiredLevel = 3; break;
577 case NUpdateNotifyOp::kRepack: s = "R"; requiredLevel = 2; break;
578 case NUpdateNotifyOp::kSkip: s = "."; requiredLevel = 2; break;
579 case NUpdateNotifyOp::kDelete: s = "D"; requiredLevel = 3; break;
580 case NUpdateNotifyOp::kHeader: s = "Header creation"; requiredLevel = 100; break;
581 default:
582 {
583 temp[0] = 'o';
584 temp[1] = 'p';
585 ConvertUInt64ToString(op, temp + 2);
586 s = temp;
587 }
588 }
589
590 return PrintProgress(name, s, LogLevel >= requiredLevel);
591 }
592
593 /*
594 HRESULT CUpdateCallbackConsole::SetPassword(const UString &
595 #ifndef _NO_CRYPTO
596 password
597 #endif
598 )
599 {
600 #ifndef _NO_CRYPTO
601 PasswordIsDefined = true;
602 Password = password;
603 #endif
604 return S_OK;
605 }
606 */
607
CryptoGetTextPassword2(Int32 * passwordIsDefined,BSTR * password)608 HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
609 {
610 COM_TRY_BEGIN
611
612 *password = NULL;
613
614 #ifdef _NO_CRYPTO
615
616 *passwordIsDefined = false;
617 return S_OK;
618
619 #else
620
621 if (!PasswordIsDefined)
622 {
623 if (AskPassword)
624 {
625 Password = GetPassword(_so);
626 PasswordIsDefined = true;
627 }
628 }
629 *passwordIsDefined = BoolToInt(PasswordIsDefined);
630 return StringToBstr(Password, password);
631
632 #endif
633
634 COM_TRY_END
635 }
636
CryptoGetTextPassword(BSTR * password)637 HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)
638 {
639 COM_TRY_BEGIN
640
641 *password = NULL;
642
643 #ifdef _NO_CRYPTO
644
645 return E_NOTIMPL;
646
647 #else
648
649 if (!PasswordIsDefined)
650 {
651 {
652 Password = GetPassword(_so);
653 PasswordIsDefined = true;
654 }
655 }
656 return StringToBstr(Password, password);
657
658 #endif
659 COM_TRY_END
660 }
661
ShowDeleteFile(const wchar_t * name,bool)662 HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool /* isDir */)
663 {
664 if (StdOutMode)
665 return S_OK;
666
667 if (LogLevel > 7)
668 {
669 if (!name || name[0] == 0)
670 name = kEmptyFileAlias;
671 return PrintProgress(name, "D", true);
672 }
673 return S_OK;
674 }
675