Home | History | Annotate | Download | only in Console
      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