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 *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 
     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 << 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 
    156 HRESULT CUpdateCallbackConsole::StartScanning()
    157 {
    158   if (_so)
    159     *_so << kScanningMessage << endl;
    160   _percent.Command = "Scan ";
    161   return S_OK;
    162 }
    163 
    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 
    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 
    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 
    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 
    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 
    227 HRESULT CUpdateCallbackConsole::ScanError(const FString &path, DWORD systemError)
    228 {
    229   return ScanError_Base(path, systemError);
    230 }
    231 
    232 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    380 HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving()
    381 {
    382   ClosePercents2();
    383   if (_so && DeleteMessageWasShown)
    384     *_so << endl;
    385   return S_OK;
    386 }
    387 
    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 
    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 
    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 
    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 
    438 HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)
    439 {
    440   return CheckBreak2();
    441 }
    442 
    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 
    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 
    519 HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError)
    520 {
    521   return OpenFileError_Base(path, systemError);
    522 }
    523 
    524 HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError)
    525 {
    526   return ReadingFileError_Base(path, systemError);
    527 }
    528 
    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 
    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 
    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 
    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 
    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 
    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