diff options
Diffstat (limited to 'CPP/7zip/UI/Console/Main.cpp')
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/UI/Console/Main.cpp | 799 |
1 files changed, 546 insertions, 253 deletions
diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp index f5a70397..0038dba4 100755..100644 --- a/CPP/7zip/UI/Console/Main.cpp +++ b/CPP/7zip/UI/Console/Main.cpp @@ -2,24 +2,31 @@ #include "StdAfx.h" +#include <Psapi.h> + #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) #include "../../../../C/Alloc.h" #endif -#include "Common/MyInitGuid.h" +#include "../../../Common/MyInitGuid.h" -#include "Common/CommandLineParser.h" -#include "Common/IntToString.h" -#include "Common/MyException.h" -#include "Common/StdOutStream.h" -#include "Common/StringConvert.h" -#include "Common/StringToInt.h" +#include "../../../Common/CommandLineParser.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/MyException.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" -#include "Windows/Error.h" +#include "../../../Windows/ErrorMsg.h" #ifdef _WIN32 -#include "Windows/MemoryLock.h" +#include "../../../Windows/MemoryLock.h" +#endif + +#ifndef _7ZIP_ST +#include "../../../Windows/Synchronization.h" #endif +#include "../../../Windows/TimeUtils.h" + #include "../Common/ArchiveCommandLine.h" #include "../Common/ExitCode.h" #include "../Common/Extract.h" @@ -28,11 +35,14 @@ #endif #include "BenchCon.h" +#include "ConsoleClose.h" #include "ExtractCallbackConsole.h" #include "List.h" #include "OpenCallbackConsole.h" #include "UpdateCallbackConsole.h" +#include "HashCon.h" + #if !defined(EXTERNAL_CODECS) && defined(_NO_CRYPTO) #define IT_IS_REDUCED_VERSION #endif @@ -80,42 +90,45 @@ static const char *kHelpString = " [<@listfiles...>]\n" "\n" "<Commands>\n" - " a: Add files to archive\n" - " b: Benchmark\n" - " d: Delete files from archive\n" - " e: Extract files from archive (without using directory names)\n" - " l: List contents of archive\n" -// " l[a|t][f]: List contents of archive\n" + " a : Add files to archive\n" + " b : Benchmark\n" + " d : Delete files from archive\n" + " e : Extract files from archive (without using directory names)\n" + " h : Calculate hash values for files\n" + " l : List contents of archive\n" +// " l[a|t][f] : List contents of archive\n" // " a - with Additional fields\n" // " t - with all fields\n" // " f - with Full pathnames\n" - " t: Test integrity of archive\n" - " u: Update files to archive\n" - " x: eXtract files with full paths\n" + " rn : Rename files in archive\n" + " t : Test integrity of archive\n" + " u : Update files to archive\n" + " x : eXtract files with full paths\n" "<Switches>\n" - " -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n" - " -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n" - " -bd: Disable percentage indicator\n" - " -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n" - " -m{Parameters}: set compression Method\n" - " -o{Directory}: set Output directory\n" + " -- : Stop switches parsing\n" + " -ai[r[-|0]]{@listfile|!wildcard} : Include archives\n" + " -ax[r[-|0]]{@listfile|!wildcard} : eXclude archives\n" + " -bd : Disable percentage indicator\n" + " -i[r[-|0]]{@listfile|!wildcard} : Include filenames\n" + " -m{Parameters} : set compression Method\n" + " -o{Directory} : set Output directory\n" #ifndef _NO_CRYPTO - " -p{Password}: set Password\n" + " -p{Password} : set Password\n" #endif - " -r[-|0]: Recurse subdirectories\n" - " -scs{UTF-8 | WIN | DOS}: set charset for list files\n" - " -sfx[{name}]: Create SFX archive\n" - " -si[{name}]: read data from stdin\n" - " -slt: show technical information for l (List) command\n" - " -so: write data to stdout\n" - " -ssc[-]: set sensitive case mode\n" - " -ssw: compress shared files\n" - " -t{Type}: Set type of archive\n" - " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n" - " -v{Size}[b|k|m|g]: Create volumes\n" - " -w[{path}]: assign Work directory. Empty path means a temporary directory\n" - " -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n" - " -y: assume Yes on all queries\n"; + " -r[-|0] : Recurse subdirectories\n" + " -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files\n" + " -sfx[{name}] : Create SFX archive\n" + " -si[{name}] : read data from stdin\n" + " -slt : show technical information for l (List) command\n" + " -so : write data to stdout\n" + " -ssc[-] : set sensitive case mode\n" + " -ssw : compress shared files\n" + " -t{Type} : Set type of archive\n" + " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName] : Update options\n" + " -v{Size}[b|k|m|g] : Create volumes\n" + " -w[{path}] : assign Work directory. Empty path means a temporary directory\n" + " -x[r[-|0]]]{@listfile|!wildcard} : eXclude filenames\n" + " -y : assume Yes on all queries\n"; // --------------------------- // exception messages @@ -124,21 +137,16 @@ static const char *kEverythingIsOk = "Everything is Ok"; static const char *kUserErrorMessage = "Incorrect command line"; static const char *kNoFormats = "7-Zip cannot find the code that works with archives."; static const char *kUnsupportedArcTypeMessage = "Unsupported archive type"; +// static const char *kUnsupportedUpdateArcType = "Can't create archive for that type"; static CFSTR kDefaultSfxModule = FTEXT("7zCon.sfx"); static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code) { - s << message << endl; + s << endl << "Error: " << message << endl; throw code; } -static void PrintHelpAndExit(CStdOutStream &s) -{ - s << kHelpString; - ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError); -} - #ifndef _WIN32 static void GetArguments(int numArgs, const char *args[], UStringVector &parts) { @@ -160,26 +168,253 @@ static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp) } #ifdef EXTERNAL_CODECS + static void PrintString(CStdOutStream &stdStream, const AString &s, int size) { - int len = s.Length(); - stdStream << s; + int len = s.Len(); for (int i = len; i < size; i++) stdStream << ' '; + stdStream << s; +} + +static void PrintUInt32(CStdOutStream &stdStream, UInt32 val, int size) +{ + char s[16]; + ConvertUInt32ToString(val, s); + PrintString(stdStream, s, size); } + +static void PrintLibIndex(CStdOutStream &stdStream, int libIndex) +{ + if (libIndex >= 0) + PrintUInt32(stdStream, libIndex, 2); + else + stdStream << " "; + stdStream << ' '; +} + #endif static void PrintString(CStdOutStream &stdStream, const UString &s, int size) { - int len = s.Length(); + int len = s.Len(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } -static inline char GetHex(Byte value) +static inline char GetHex(unsigned val) +{ + return (char)((val < 10) ? ('0' + val) : ('A' + (val - 10))); +} + +static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback, + const CErrorInfo &errorInfo, CStdOutStream &stdStream) +{ + int exitCode = NExitCode::kSuccess; + + if (callback.CantFindFiles.Size() > 0) + { + stdStream << endl; + stdStream << "WARNINGS for files:" << endl << endl; + unsigned numErrors = callback.CantFindFiles.Size(); + for (unsigned i = 0; i < numErrors; i++) + { + stdStream << callback.CantFindFiles[i] << " : "; + stdStream << NError::MyFormatMessage(callback.CantFindCodes[i]) << endl; + } + stdStream << "----------------" << endl; + stdStream << "WARNING: Cannot find " << numErrors << " file"; + if (numErrors > 1) + stdStream << "s"; + stdStream << endl; + exitCode = NExitCode::kWarning; + } + + if (result != S_OK) + { + UString message; + if (!errorInfo.Message.IsEmpty()) + { + message += errorInfo.Message; + message += L"\n"; + } + if (!errorInfo.FileName.IsEmpty()) + { + message += fs2us(errorInfo.FileName); + message += L"\n"; + } + if (!errorInfo.FileName2.IsEmpty()) + { + message += fs2us(errorInfo.FileName2); + message += L"\n"; + } + if (errorInfo.SystemError != 0) + { + message += NError::MyFormatMessage(errorInfo.SystemError); + message += L"\n"; + } + if (!message.IsEmpty()) + stdStream << L"\nError:\n" << message; + + // we will work with (result) later + // throw CSystemException(result); + return NExitCode::kFatalError; + } + + unsigned numErrors = callback.FailedFiles.Size(); + if (numErrors == 0) + { + if (callback.CantFindFiles.Size() == 0) + stdStream << kEverythingIsOk << endl; + } + else + { + stdStream << endl; + stdStream << "WARNINGS for files:" << endl << endl; + for (unsigned i = 0; i < numErrors; i++) + { + stdStream << callback.FailedFiles[i] << " : "; + stdStream << NError::MyFormatMessage(callback.FailedCodes[i]) << endl; + } + stdStream << "----------------" << endl; + stdStream << "WARNING: Cannot open " << numErrors << " file"; + if (numErrors > 1) + stdStream << "s"; + stdStream << endl; + exitCode = NExitCode::kWarning; + } + return exitCode; +} + +static void ThrowException_if_Error(HRESULT res) +{ + if (res != S_OK) + throw CSystemException(res); +} + + +static void PrintNum(UInt64 val, unsigned numDigits, char c = ' ') +{ + char temp[64]; + char *p = temp + 32; + ConvertUInt64ToString(val, p); + unsigned len = MyStringLen(p); + for (; len < numDigits; len++) + *--p = c; + *g_StdStream << p; +} + +static void PrintTime(const char *s, UInt64 val, UInt64 total) +{ + *g_StdStream << endl << s << " Time ="; + const UInt32 kFreq = 10000000; + UInt64 sec = val / kFreq; + PrintNum(sec, 6); + *g_StdStream << '.'; + UInt32 ms = (UInt32)(val - (sec * kFreq)) / (kFreq / 1000); + PrintNum(ms, 3, '0'); + + while (val > ((UInt64)1 << 56)) + { + val >>= 1; + total >>= 1; + } + + UInt64 percent = 0; + if (total != 0) + percent = val * 100 / total; + *g_StdStream << " ="; + PrintNum(percent, 5); + *g_StdStream << '%'; +} + +#ifndef UNDER_CE + +#define SHIFT_SIZE_VALUE(x, num) (((x) + (1 << (num)) - 1) >> (num)) + +static void PrintMemUsage(const char *s, UInt64 val) { - return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); + *g_StdStream << " " << s << " Memory ="; + PrintNum(SHIFT_SIZE_VALUE(val, 20), 7); + *g_StdStream << " MB"; +} + +EXTERN_C_BEGIN +typedef BOOL (WINAPI *Func_GetProcessMemoryInfo)(HANDLE Process, + PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb); +EXTERN_C_END + +#endif + +static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } + +static void PrintStat() +{ + FILETIME creationTimeFT, exitTimeFT, kernelTimeFT, userTimeFT; + if (! + #ifdef UNDER_CE + ::GetThreadTimes(::GetCurrentThread() + #else + // NT 3.5 + ::GetProcessTimes(::GetCurrentProcess() + #endif + , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT)) + return; + FILETIME curTimeFT; + NTime::GetCurUtcFileTime(curTimeFT); + + #ifndef UNDER_CE + + PROCESS_MEMORY_COUNTERS m; + memset(&m, 0, sizeof(m)); + BOOL memDefined = FALSE; + { + /* NT 4.0: GetProcessMemoryInfo() in Psapi.dll + Win7: new function K32GetProcessMemoryInfo() in kernel32.dll + It's faster to call kernel32.dll code than Psapi.dll code + GetProcessMemoryInfo() requires Psapi.lib + Psapi.lib in SDK7+ can link to K32GetProcessMemoryInfo in kernel32.dll + The program with K32GetProcessMemoryInfo will not work on systems before Win7 + // memDefined = GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m)); + */ + + Func_GetProcessMemoryInfo my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo) + ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "K32GetProcessMemoryInfo"); + if (!my_GetProcessMemoryInfo) + { + HMODULE lib = LoadLibraryW(L"Psapi.dll"); + if (lib) + my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo)::GetProcAddress(lib, "GetProcessMemoryInfo"); + } + if (my_GetProcessMemoryInfo) + memDefined = my_GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m)); + // FreeLibrary(lib); + } + + #endif + + UInt64 curTime = GetTime64(curTimeFT); + UInt64 creationTime = GetTime64(creationTimeFT); + UInt64 kernelTime = GetTime64(kernelTimeFT); + UInt64 userTime = GetTime64(userTimeFT); + + UInt64 totalTime = curTime - creationTime; + + PrintTime("Kernel ", kernelTime, totalTime); + PrintTime("User ", userTime, totalTime); + + PrintTime("Process", kernelTime + userTime, totalTime); + #ifndef UNDER_CE + if (memDefined) PrintMemUsage("Virtual ", m.PeakPagefileUsage); + #endif + + PrintTime("Global ", totalTime, totalTime); + #ifndef UNDER_CE + if (memDefined) PrintMemUsage("Physical", m.PeakWorkingSetSize); + #endif + + *g_StdStream << endl; } int Main2( @@ -191,7 +426,7 @@ int Main2( #if defined(_WIN32) && !defined(UNDER_CE) SetFileApisToOEM(); #endif - + UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); @@ -204,11 +439,12 @@ int Main2( ShowCopyrightAndHelp(g_StdOut, true); return 0; } + commandStrings.Delete(0); - CArchiveCommandLineOptions options; + CArcCmdLineOptions options; - CArchiveCommandLineParser parser; + CArcCmdLineParser parser; parser.Parse1(commandStrings, options); @@ -218,11 +454,16 @@ int Main2( return 0; } - #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) + #if defined(_WIN32) && !defined(UNDER_CE) + NSecurity::EnablePrivilege_SymLink(); + #endif + #ifdef _7ZIP_LARGE_PAGES if (options.LargePages) { SetLargePageSize(); - NSecurity::EnableLockMemoryPrivilege(); + #if defined(_WIN32) && !defined(UNDER_CE) + NSecurity::EnablePrivilege_LockMemory(); + #endif } #endif @@ -235,55 +476,98 @@ int Main2( parser.Parse2(options); CCodecs *codecs = new CCodecs; - CMyComPtr< - #ifdef EXTERNAL_CODECS - ICompressCodecsInfo - #else - IUnknown - #endif - > compressCodecsInfo = codecs; - HRESULT result = codecs->Load(); - if (result != S_OK) - throw CSystemException(result); + #ifdef EXTERNAL_CODECS + CExternalCodecs __externalCodecs; + __externalCodecs.GetCodecs = codecs; + __externalCodecs.GetHashers = codecs; + #else + CMyComPtr<IUnknown> compressCodecsInfo = codecs; + #endif + codecs->CaseSensitiveChange = options.CaseSensitiveChange; + codecs->CaseSensitive = options.CaseSensitive; + ThrowException_if_Error(codecs->Load()); bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); if (codecs->Formats.Size() == 0 && - (isExtractGroupCommand || - options.Command.CommandType == NCommandType::kList || - options.Command.IsFromUpdateGroup())) + (isExtractGroupCommand + || options.Command.CommandType == NCommandType::kList + || options.Command.IsFromUpdateGroup())) throw kNoFormats; - CIntVector formatIndices; - if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices)) + CObjectVector<COpenType> types; + if (!ParseOpenTypes(*codecs, options.ArcType, types)) throw kUnsupportedArcTypeMessage; + CIntVector excludedFormats; + FOR_VECTOR (k, options.ExcludedArcTypes) + { + CIntVector tempIndices; + if (!codecs->FindFormatForArchiveType(options.ExcludedArcTypes[k], tempIndices) + || tempIndices.Size() != 1) + throw kUnsupportedArcTypeMessage; + excludedFormats.AddToUniqueSorted(tempIndices[0]); + // excludedFormats.Sort(); + } + + + #ifdef EXTERNAL_CODECS + if (isExtractGroupCommand + || options.Command.CommandType == NCommandType::kHash + || options.Command.CommandType == NCommandType::kBenchmark) + ThrowException_if_Error(__externalCodecs.LoadCodecs()); + #endif + + int retCode = NExitCode::kSuccess; + HRESULT hresultMain = S_OK; + + bool showStat = true; + if (!options.EnableHeaders || + options.TechMode) + showStat = false; + + if (options.Command.CommandType == NCommandType::kInfo) { + unsigned i; + + #ifdef EXTERNAL_CODECS + stdStream << endl << "Libs:" << endl; + for (i = 0; i < codecs->Libs.Size(); i++) + { + PrintLibIndex(stdStream, i); + stdStream << ' ' << codecs->Libs[i].Path << endl; + } + #endif + stdStream << endl << "Formats:" << endl; - int i; + + const char *kArcFlags = "KSNFMGOPBELH"; + const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags); + for (i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arc = codecs->Formats[i]; #ifdef EXTERNAL_CODECS - if (arc.LibIndex >= 0) + PrintLibIndex(stdStream, arc.LibIndex); + #else + stdStream << " "; + #endif + stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); + for (unsigned b = 0; b < kNumArcFlags; b++) { - char s[16]; - ConvertUInt32ToString(arc.LibIndex, s); - PrintString(stdStream, s, 2); + stdStream << (char) + ((arc.Flags & ((UInt32)1 << b)) != 0 ? kArcFlags[b] : ' '); } - else - #endif - stdStream << " "; + + stdStream << ' '; + PrintString(stdStream, arc.Name, 8); stdStream << ' '; - stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); - stdStream << (char)(arc.KeepName ? 'K' : ' '); - stdStream << " "; - PrintString(stdStream, arc.Name, 6); - stdStream << " "; UString s; - for (int t = 0; t < arc.Exts.Size(); t++) + FOR_VECTOR (t, arc.Exts) { + if (t != 0) + s += L' '; const CArcExtInfo &ext = arc.Exts[t]; s += ext.Ext; if (!ext.AddExt.IsEmpty()) @@ -292,44 +576,46 @@ int Main2( s += ext.AddExt; s += L')'; } - s += L' '; } - PrintString(stdStream, s, 14); - stdStream << " "; - const CByteBuffer &sig = arc.StartSignature; - for (size_t j = 0; j < sig.GetCapacity(); j++) + PrintString(stdStream, s, 13); + stdStream << ' '; + if (arc.SignatureOffset != 0) + stdStream << "offset=" << arc.SignatureOffset << ' '; + + FOR_VECTOR(si, arc.Signatures) { - Byte b = sig[j]; - if (b > 0x20 && b < 0x80) - { - stdStream << (char)b; - } - else + if (si != 0) + stdStream << " || "; + + const CByteBuffer &sig = arc.Signatures[si]; + + for (size_t j = 0; j < sig.Size(); j++) { - stdStream << GetHex((Byte)((b >> 4) & 0xF)); - stdStream << GetHex((Byte)(b & 0xF)); + if (j != 0) + stdStream << ' '; + Byte b = sig[j]; + if (b > 0x20 && b < 0x80) + { + stdStream << (char)b; + } + else + { + stdStream << GetHex((b >> 4) & 0xF); + stdStream << GetHex(b & 0xF); + } } - stdStream << ' '; } stdStream << endl; } - stdStream << endl << "Codecs:" << endl; #ifdef EXTERNAL_CODECS + + stdStream << endl << "Codecs:" << endl << "Lib ID Name" << endl; UInt32 numMethods; if (codecs->GetNumberOfMethods(&numMethods) == S_OK) for (UInt32 j = 0; j < numMethods; j++) { - int libIndex = codecs->GetCodecLibIndex(j); - if (libIndex >= 0) - { - char s[16]; - ConvertUInt32ToString(libIndex, s); - PrintString(stdStream, s, 2); - } - else - stdStream << " "; - stdStream << ' '; + PrintLibIndex(stdStream, codecs->GetCodecLibIndex(j)); stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' '); UInt64 id; stdStream << " "; @@ -337,43 +623,36 @@ int Main2( if (res != S_OK) id = (UInt64)(Int64)-1; char s[32]; - ConvertUInt64ToString(id, s, 16); + ConvertUInt64ToHex(id, s); PrintString(stdStream, s, 8); - stdStream << " "; - PrintString(stdStream, codecs->GetCodecName(j), 11); - stdStream << endl; - /* - if (res != S_OK) - throw "incorrect Codec ID"; - */ + stdStream << " " << codecs->GetCodecName(j) << endl; } + + stdStream << endl << "Hashers:" << endl << " L Size ID Name" << endl; + numMethods = codecs->GetNumHashers(); + for (UInt32 j = 0; j < numMethods; j++) + { + PrintLibIndex(stdStream, codecs->GetHasherLibIndex(j)); + PrintUInt32(stdStream, codecs->GetHasherDigestSize(j), 4); + stdStream << ' '; + char s[32]; + ConvertUInt64ToHex(codecs->GetHasherId(j), s); + PrintString(stdStream, s, 6); + stdStream << " " << codecs->GetHasherName(j) << endl; + } + #endif - return S_OK; + } else if (options.Command.CommandType == NCommandType::kBenchmark) { + hresultMain = BenchCon(EXTERNAL_CODECS_VARS + options.Properties, options.NumIterations, (FILE *)stdStream); + if (hresultMain == S_FALSE) { - HRESULT res; - #ifdef EXTERNAL_CODECS - CObjectVector<CCodecInfoEx> externalCodecs; - res = LoadExternalCodecs(compressCodecsInfo, externalCodecs); - if (res != S_OK) - throw CSystemException(res); - #endif - res = BenchCon( - #ifdef EXTERNAL_CODECS - compressCodecsInfo, &externalCodecs, - #endif - options.Properties, options.NumIterations, (FILE *)stdStream); - if (res != S_OK) - { - if (res == S_FALSE) - { - stdStream << "\nDecoding Error\n"; - return NExitCode::kFatalError; - } - throw CSystemException(res); - } + stdStream << "\nDecoding Error\n"; + retCode = NExitCode::kFatalError; + hresultMain = S_OK; } } else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) @@ -401,90 +680,145 @@ int Main2( #endif CExtractOptions eo; + (CExtractOptionsBase &)eo = options.ExtractOptions; eo.StdInMode = options.StdInMode; eo.StdOutMode = options.StdOutMode; - eo.PathMode = options.Command.GetPathMode(); - eo.TestMode = options.Command.IsTestMode(); - eo.OverwriteMode = options.OverwriteMode; - eo.OutputDir = options.OutputDir; eo.YesToAll = options.YesToAll; - eo.CalcCrc = options.CalcCrc; - #if !defined(_7ZIP_ST) && !defined(_SFX) + eo.TestMode = options.Command.IsTestCommand(); + + #ifndef _SFX eo.Properties = options.Properties; #endif + UString errorMessage; CDecompressStat stat; - HRESULT result = DecompressArchives( + CHashBundle hb; + IHashCalc *hashCalc = NULL; + + if (!options.HashMethods.IsEmpty()) + { + hashCalc = &hb; + ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS options.HashMethods)); + hb.Init(); + } + hresultMain = Extract( codecs, - formatIndices, + types, + excludedFormats, options.ArchivePathsSorted, options.ArchivePathsFullSorted, - options.WildcardCensor.Pairs.Front().Head, - eo, &openCallback, ecs, errorMessage, stat); + options.Censor.Pairs.Front().Head, + eo, &openCallback, ecs, hashCalc, errorMessage, stat); if (!errorMessage.IsEmpty()) { stdStream << endl << "Error: " << errorMessage; - if (result == S_OK) - result = E_FAIL; + if (hresultMain == S_OK) + hresultMain = E_FAIL; } stdStream << endl; - if (ecs->NumArchives > 1) - stdStream << "Archives: " << ecs->NumArchives << endl; - if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) + + if (ecs->NumTryArcs > 1) { - if (ecs->NumArchives > 1) + stdStream << "Archives: " << ecs->NumTryArcs << endl; + stdStream << "OK archives: " << ecs->NumOkArcs << endl; + } + bool isError = false; + if (ecs->NumCantOpenArcs != 0) + { + isError = true; + stdStream << "Can't open as archive: " << ecs->NumCantOpenArcs << endl; + } + if (ecs->NumArcsWithError != 0) + { + isError = true; + stdStream << "Archives with Errors: " << ecs->NumArcsWithError << endl; + } + if (ecs->NumArcsWithWarnings != 0) + stdStream << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl; + + if (ecs->NumOpenArcWarnings != 0) + { + stdStream << endl; + if (ecs->NumOpenArcWarnings != 0) + stdStream << "Warnings: " << ecs->NumOpenArcWarnings << endl; + } + + if (ecs->NumOpenArcErrors != 0) + { + isError = true; + stdStream << endl; + if (ecs->NumOpenArcErrors != 0) + stdStream << "Open Errors: " << ecs->NumOpenArcErrors << endl; + } + + if (isError) + retCode = NExitCode::kFatalError; + + if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0) + { + // if (ecs->NumArchives > 1) { stdStream << endl; - if (ecs->NumArchiveErrors != 0) - stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl; if (ecs->NumFileErrors != 0) stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl; } - if (result != S_OK) - throw CSystemException(result); - return NExitCode::kFatalError; } - if (result != S_OK) - throw CSystemException(result); + else if (hresultMain == S_OK) + { + if (stat.NumFolders != 0) stdStream << "Folders: " << stat.NumFolders << endl; - if (stat.NumFiles != 1 || stat.NumFolders != 0) - stdStream << "Files: " << stat.NumFiles << endl; + if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0) + stdStream << "Files: " << stat.NumFiles << endl; + if (stat.NumAltStreams != 0) + { + stdStream << "Alternate Streams: " << stat.NumAltStreams << endl; + stdStream << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl; + } + stdStream << "Size: " << stat.UnpackSize << endl << "Compressed: " << stat.PackSize << endl; - if (options.CalcCrc) - { - char s[16]; - ConvertUInt32ToHexWithZeros(stat.CrcSum, s); - stdStream << "CRC: " << s << endl; + if (hashCalc) + PrintHashStat(stdStream, hb); } } else { UInt64 numErrors = 0; - HRESULT result = ListArchives( + UInt64 numWarnings = 0; + + // options.ExtractNtOptions.StoreAltStreams = true, if -sns[-] is not definmed + + hresultMain = ListArchives( codecs, - formatIndices, + types, + excludedFormats, options.StdInMode, options.ArchivePathsSorted, options.ArchivePathsFullSorted, - options.WildcardCensor.Pairs.Front().Head, + options.ExtractOptions.NtOptions.AltStreams.Val, + options.AltStreams.Val, // we don't want to show AltStreams by default + options.Censor.Pairs.Front().Head, options.EnableHeaders, options.TechMode, #ifndef _NO_CRYPTO options.PasswordEnabled, options.Password, #endif - numErrors); + &options.Properties, + numErrors, numWarnings); + + if (options.EnableHeaders) + if (numWarnings > 0) + g_StdOut << endl << "Warnings: " << numWarnings << endl; if (numErrors > 0) { - g_StdOut << endl << "Errors: " << numErrors << endl; - return NExitCode::kFatalError; + if (options.EnableHeaders) + g_StdOut << endl << "Errors: " << numErrors << endl; + retCode = NExitCode::kFatalError; } - if (result != S_OK) - throw CSystemException(result); } } else if (options.Command.IsFromUpdateGroup()) @@ -516,83 +850,42 @@ int Main2( CUpdateErrorInfo errorInfo; - if (!uo.Init(codecs, formatIndices, options.ArchiveName)) - throw kUnsupportedArcTypeMessage; - HRESULT result = UpdateArchive(codecs, - options.WildcardCensor, uo, - errorInfo, &openCallback, &callback); + /* + if (!uo.Init(codecs, types, options.ArchiveName)) + throw kUnsupportedUpdateArcType; + */ + hresultMain = UpdateArchive(codecs, + types, + options.ArchiveName, + options.Censor, + uo, + errorInfo, &openCallback, &callback, true); + retCode = WarningsCheck(hresultMain, callback, errorInfo, stdStream); + } + else if (options.Command.CommandType == NCommandType::kHash) + { + const CHashOptions &uo = options.HashOptions; - int exitCode = NExitCode::kSuccess; - if (callback.CantFindFiles.Size() > 0) - { - stdStream << endl; - stdStream << "WARNINGS for files:" << endl << endl; - int numErrors = callback.CantFindFiles.Size(); - for (int i = 0; i < numErrors; i++) - { - stdStream << callback.CantFindFiles[i] << " : "; - stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl; - } - stdStream << "----------------" << endl; - stdStream << "WARNING: Cannot find " << numErrors << " file"; - if (numErrors > 1) - stdStream << "s"; - stdStream << endl; - exitCode = NExitCode::kWarning; - } + CHashCallbackConsole callback; + callback.EnablePercents = options.EnablePercents; - if (result != S_OK) - { - UString message; - if (!errorInfo.Message.IsEmpty()) - { - message += errorInfo.Message; - message += L"\n"; - } - if (!errorInfo.FileName.IsEmpty()) - { - message += fs2us(errorInfo.FileName); - message += L"\n"; - } - if (!errorInfo.FileName2.IsEmpty()) - { - message += fs2us(errorInfo.FileName2); - message += L"\n"; - } - if (errorInfo.SystemError != 0) - { - message += NError::MyFormatMessageW(errorInfo.SystemError); - message += L"\n"; - } - if (!message.IsEmpty()) - stdStream << L"\nError:\n" << message; - throw CSystemException(result); - } - int numErrors = callback.FailedFiles.Size(); - if (numErrors == 0) - { - if (callback.CantFindFiles.Size() == 0) - stdStream << kEverythingIsOk << endl; - } - else - { - stdStream << endl; - stdStream << "WARNINGS for files:" << endl << endl; - for (int i = 0; i < numErrors; i++) - { - stdStream << callback.FailedFiles[i] << " : "; - stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl; - } - stdStream << "----------------" << endl; - stdStream << "WARNING: Cannot open " << numErrors << " file"; - if (numErrors > 1) - stdStream << "s"; - stdStream << endl; - exitCode = NExitCode::kWarning; - } - return exitCode; + callback.Init(&stdStream); + + UString errorInfoString; + hresultMain = HashCalc(EXTERNAL_CODECS_VARS + options.Censor, uo, + errorInfoString, &callback); + CErrorInfo errorInfo; + errorInfo.Message = errorInfoString; + retCode = WarningsCheck(hresultMain, callback, errorInfo, stdStream); } else - PrintHelpAndExit(stdStream); - return 0; + ShowMessageAndThrowException(stdStream, kUserErrorMessage, NExitCode::kUserError); + + if (showStat) + PrintStat(); + + ThrowException_if_Error(hresultMain); + + return retCode; } |