blob: 46ffaba0216a64dfa5083d55129525bcb45da8bf [file] [log] [blame]
// UpdateCallbackConsole.cpp
#include "StdAfx.h"
#include "../../../Common/IntToString.h"
#include "../../../Windows/ErrorMsg.h"
#ifndef _7ZIP_ST
#include "../../../Windows/Synchronization.h"
#endif
#include "ConsoleClose.h"
#include "UserInputUtils.h"
#include "UpdateCallbackConsole.h"
using namespace NWindows;
#ifndef _7ZIP_ST
static NSynchronization::CCriticalSection g_CriticalSection;
#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
#else
#define MT_LOCK
#endif
static const wchar_t * const kEmptyFileAlias = L"[Content]";
static const char * const kOpenArchiveMessage = "Open archive: ";
static const char * const kCreatingArchiveMessage = "Creating archive: ";
static const char * const kUpdatingArchiveMessage = "Updating archive: ";
static const char * const kScanningMessage = "Scanning the drive:";
static const char * const kError = "ERROR: ";
static const char * const kWarning = "WARNING: ";
static HRESULT CheckBreak2()
{
return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
}
HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags);
void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc);
HRESULT CUpdateCallbackConsole::OpenResult(
const CCodecs *codecs, const CArchiveLink &arcLink,
const wchar_t *name, HRESULT result)
{
ClosePercents2();
FOR_VECTOR (level, arcLink.Arcs)
{
const CArc &arc = arcLink.Arcs[level];
const CArcErrorInfo &er = arc.ErrorInfo;
UInt32 errorFlags = er.GetErrorFlags();
if (errorFlags != 0 || !er.ErrorMessage.IsEmpty())
{
if (_se)
{
*_se << endl;
if (level != 0)
*_se << arc.Path << endl;
}
if (errorFlags != 0)
{
if (_se)
PrintErrorFlags(*_se, "ERRORS:", errorFlags);
}
if (!er.ErrorMessage.IsEmpty())
{
if (_se)
*_se << "ERRORS:" << endl << er.ErrorMessage << endl;
}
if (_se)
{
*_se << endl;
_se->Flush();
}
}
UInt32 warningFlags = er.GetWarningFlags();
if (warningFlags != 0 || !er.WarningMessage.IsEmpty())
{
if (_so)
{
*_so << endl;
if (level != 0)
*_so << arc.Path << endl;
}
if (warningFlags != 0)
{
if (_so)
PrintErrorFlags(*_so, "WARNINGS:", warningFlags);
}
if (!er.WarningMessage.IsEmpty())
{
if (_so)
*_so << "WARNINGS:" << endl << er.WarningMessage << endl;
}
if (_so)
{
*_so << endl;
if (NeedFlush)
_so->Flush();
}
}
if (er.ErrorFormatIndex >= 0)
{
if (_so)
{
Print_ErrorFormatIndex_Warning(_so, codecs, arc);
if (NeedFlush)
_so->Flush();
}
}
}
if (result == S_OK)
{
if (_so)
{
RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink));
*_so << endl;
}
}
else
{
if (_so)
_so->Flush();
if (_se)
{
*_se << kError;
_se->NormalizePrint_wstr(name);
*_se << endl;
HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);
RINOK(res);
_se->Flush();
}
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::StartScanning()
{
if (_so)
*_so << kScanningMessage << endl;
_percent.Command = "Scan ";
return S_OK;
}
HRESULT CUpdateCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)
{
if (NeedPercents())
{
_percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams;
_percent.Completed = st.GetTotalBytes();
_percent.FileName = fs2us(path);
_percent.Print();
}
return CheckBreak();
}
void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, bool isWarning)
{
ClosePercents2();
if (_se)
{
if (_so)
_so->Flush();
*_se << endl << (isWarning ? kWarning : kError)
<< NError::MyFormatMessage(systemError)
<< endl;
_se->NormalizePrint_UString(fs2us(path));
*_se << endl << endl;
_se->Flush();
}
}
HRESULT CCallbackConsoleBase::ScanError_Base(const FString &path, DWORD systemError)
{
MT_LOCK
ScanErrors.AddError(path, systemError);
CommonError(path, systemError, true);
return S_OK;
}
HRESULT CCallbackConsoleBase::OpenFileError_Base(const FString &path, DWORD systemError)
{
MT_LOCK
FailedFiles.AddError(path, systemError);
/*
if (systemError == ERROR_SHARING_VIOLATION)
{
*/
CommonError(path, systemError, true);
return S_FALSE;
/*
}
return systemError;
*/
}
HRESULT CCallbackConsoleBase::ReadingFileError_Base(const FString &path, DWORD systemError)
{
MT_LOCK
CommonError(path, systemError, false);
return HRESULT_FROM_WIN32(systemError);
}
HRESULT CUpdateCallbackConsole::ScanError(const FString &path, DWORD systemError)
{
return ScanError_Base(path, systemError);
}
static void PrintPropPair(AString &s, const char *name, UInt64 val)
{
char temp[32];
ConvertUInt64ToString(val, temp);
s += name;
s += ": ";
s += temp;
}
void PrintSize_bytes_Smart(AString &s, UInt64 val);
void Print_DirItemsStat(AString &s, const CDirItemsStat &st);
void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st);
HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st)
{
if (NeedPercents())
{
_percent.ClosePrint(true);
_percent.ClearCurState();
}
if (_so)
{
AString s;
Print_DirItemsStat(s, st);
*_so << s << endl << endl;
}
return S_OK;
}
static const char * const k_StdOut_ArcName = "StdOut";
HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name)
{
if (_so)
{
*_so << kOpenArchiveMessage;
if (name)
*_so << name;
else
*_so << k_StdOut_ArcName;
*_so << endl;
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)
{
if (_so)
{
*_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage);
if (name)
_so->NormalizePrint_wstr(name);
else
*_so << k_StdOut_ArcName;
*_so << endl << endl;
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::FinishArchive(const CFinishArchiveStat &st)
{
ClosePercents2();
if (_so)
{
AString s;
// Print_UInt64_and_String(s, _percent.Files == 1 ? "file" : "files", _percent.Files);
PrintPropPair(s, "Files read from disk", _percent.Files);
s.Add_LF();
s += "Archive size: ";
PrintSize_bytes_Smart(s, st.OutArcFileSize);
s.Add_LF();
*_so << endl;
*_so << s;
// *_so << endl;
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size)
{
if (_so)
{
*_so << "Write SFX: ";
*_so << name;
AString s (" : ");
PrintSize_bytes_Smart(s, size);
*_so << s << endl;
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */)
{
if (LogLevel > 0 && _so)
{
ClosePercents_for_so();
if (!DeleteMessageWasShown)
{
if (_so)
*_so << endl << ": Removing files after including to archive" << endl;
}
{
{
_tempA = "Removing";
_tempA.Add_Space();
*_so << _tempA;
_tempU = fs2us(path);
_so->Normalize_UString(_tempU);
_so->PrintUString(_tempU, _tempA);
*_so << endl;
if (NeedFlush)
_so->Flush();
}
}
}
if (!DeleteMessageWasShown)
{
if (NeedPercents())
{
_percent.ClearCurState();
}
DeleteMessageWasShown = true;
}
else
{
_percent.Files++;
}
if (NeedPercents())
{
// if (!FullLog)
{
_percent.Command = "Removing";
_percent.FileName = fs2us(path);
}
_percent.Print();
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving()
{
ClosePercents2();
if (_so && DeleteMessageWasShown)
*_so << endl;
return S_OK;
}
HRESULT CUpdateCallbackConsole::CheckBreak()
{
return CheckBreak2();
}
/*
HRESULT CUpdateCallbackConsole::Finalize()
{
// MT_LOCK
return S_OK;
}
*/
void static PrintToDoStat(CStdOutStream *_so, const CDirItemsStat2 &stat, const char *name)
{
AString s;
Print_DirItemsStat2(s, stat);
*_so << name << ": " << s << endl;
}
HRESULT CUpdateCallbackConsole::SetNumItems(const CArcToDoStat &stat)
{
if (_so)
{
ClosePercents_for_so();
if (!stat.DeleteData.IsEmpty())
{
*_so << endl;
PrintToDoStat(_so, stat.DeleteData, "Delete data from archive");
}
if (!stat.OldData.IsEmpty())
PrintToDoStat(_so, stat.OldData, "Keep old data in archive");
// if (!stat.NewData.IsEmpty())
{
PrintToDoStat(_so, stat.NewData, "Add new data to archive");
}
*_so << endl;
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)
{
MT_LOCK
if (NeedPercents())
{
_percent.Total = size;
_percent.Print();
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)
{
MT_LOCK
if (completeValue)
{
if (NeedPercents())
{
_percent.Completed = *completeValue;
_percent.Print();
}
}
return CheckBreak2();
}
HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)
{
return CheckBreak2();
}
HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *command, bool showInLog)
{
MT_LOCK
bool show2 = (showInLog && _so);
if (show2)
{
ClosePercents_for_so();
_tempA = command;
if (name)
_tempA.Add_Space();
*_so << _tempA;
_tempU.Empty();
if (name)
{
_tempU = name;
_so->Normalize_UString(_tempU);
}
_so->PrintUString(_tempU, _tempA);
*_so << endl;
if (NeedFlush)
_so->Flush();
}
if (NeedPercents())
{
if (PercentsNameLevel >= 1)
{
_percent.FileName.Empty();
_percent.Command.Empty();
if (PercentsNameLevel > 1 || !show2)
{
_percent.Command = command;
if (name)
_percent.FileName = name;
}
}
_percent.Print();
}
return CheckBreak2();
}
HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool /* isDir */, bool isAnti, UInt32 mode)
{
if (StdOutMode)
return S_OK;
if (!name || name[0] == 0)
name = kEmptyFileAlias;
unsigned requiredLevel = 1;
const char *s;
if (mode == NUpdateNotifyOp::kAdd ||
mode == NUpdateNotifyOp::kUpdate)
{
if (isAnti)
s = "Anti";
else if (mode == NUpdateNotifyOp::kAdd)
s = "+";
else
s = "U";
}
else
{
requiredLevel = 3;
if (mode == NUpdateNotifyOp::kAnalyze)
s = "A";
else
s = "Reading";
}
return PrintProgress(name, s, LogLevel >= requiredLevel);
}
HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError)
{
return OpenFileError_Base(path, systemError);
}
HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError)
{
return ReadingFileError_Base(path, systemError);
}
HRESULT CUpdateCallbackConsole::SetOperationResult(Int32)
{
MT_LOCK
_percent.Files++;
return S_OK;
}
void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest);
HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
{
// if (StdOutMode) return S_OK;
if (opRes != NArchive::NExtract::NOperationResult::kOK)
{
ClosePercents2();
if (_se)
{
if (_so)
_so->Flush();
AString s;
SetExtractErrorMessage(opRes, isEncrypted, s);
*_se << s << " : " << endl;
_se->NormalizePrint_wstr(name);
*_se << endl << endl;
_se->Flush();
}
return S_OK;
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool /* isDir */)
{
// if (StdOutMode) return S_OK;
char temp[16];
const char *s;
unsigned requiredLevel = 1;
switch (op)
{
case NUpdateNotifyOp::kAdd: s = "+"; break;
case NUpdateNotifyOp::kUpdate: s = "U"; break;
case NUpdateNotifyOp::kAnalyze: s = "A"; requiredLevel = 3; break;
case NUpdateNotifyOp::kReplicate: s = "="; requiredLevel = 3; break;
case NUpdateNotifyOp::kRepack: s = "R"; requiredLevel = 2; break;
case NUpdateNotifyOp::kSkip: s = "."; requiredLevel = 2; break;
case NUpdateNotifyOp::kDelete: s = "D"; requiredLevel = 3; break;
case NUpdateNotifyOp::kHeader: s = "Header creation"; requiredLevel = 100; break;
default:
{
temp[0] = 'o';
temp[1] = 'p';
ConvertUInt64ToString(op, temp + 2);
s = temp;
}
}
return PrintProgress(name, s, LogLevel >= requiredLevel);
}
/*
HRESULT CUpdateCallbackConsole::SetPassword(const UString &
#ifndef _NO_CRYPTO
password
#endif
)
{
#ifndef _NO_CRYPTO
PasswordIsDefined = true;
Password = password;
#endif
return S_OK;
}
*/
HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
COM_TRY_BEGIN
*password = NULL;
#ifdef _NO_CRYPTO
*passwordIsDefined = false;
return S_OK;
#else
if (!PasswordIsDefined)
{
if (AskPassword)
{
RINOK(GetPassword_HRESULT(_so, Password));
PasswordIsDefined = true;
}
}
*passwordIsDefined = BoolToInt(PasswordIsDefined);
return StringToBstr(Password, password);
#endif
COM_TRY_END
}
HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)
{
COM_TRY_BEGIN
*password = NULL;
#ifdef _NO_CRYPTO
return E_NOTIMPL;
#else
if (!PasswordIsDefined)
{
{
RINOK(GetPassword_HRESULT(_so, Password))
PasswordIsDefined = true;
}
}
return StringToBstr(Password, password);
#endif
COM_TRY_END
}
HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool /* isDir */)
{
if (StdOutMode)
return S_OK;
if (LogLevel > 7)
{
if (!name || name[0] == 0)
name = kEmptyFileAlias;
return PrintProgress(name, "D", true);
}
return S_OK;
}