tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Main.cpp (31948B)


      1 // Main.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../../Common/MyWindows.h"
      6 
      7 #ifdef _WIN32
      8 #include <Psapi.h>
      9 #endif
     10 
     11 #include "../../../../C/CpuArch.h"
     12 
     13 #include "../../../Common/MyInitGuid.h"
     14 
     15 #include "../../../Common/CommandLineParser.h"
     16 #include "../../../Common/IntToString.h"
     17 #include "../../../Common/MyException.h"
     18 #include "../../../Common/StringConvert.h"
     19 #include "../../../Common/StringToInt.h"
     20 #include "../../../Common/UTFConvert.h"
     21 
     22 #include "../../../Windows/ErrorMsg.h"
     23 
     24 #include "../../../Windows/TimeUtils.h"
     25 
     26 #include "../Common/ArchiveCommandLine.h"
     27 #include "../Common/ExitCode.h"
     28 #include "../Common/Extract.h"
     29 
     30 #ifdef EXTERNAL_CODECS
     31 #include "../Common/LoadCodecs.h"
     32 #endif
     33 
     34 #include "../../Common/RegisterCodec.h"
     35 
     36 #include "BenchCon.h"
     37 #include "ConsoleClose.h"
     38 #include "ExtractCallbackConsole.h"
     39 #include "List.h"
     40 #include "OpenCallbackConsole.h"
     41 #include "UpdateCallbackConsole.h"
     42 
     43 #include "HashCon.h"
     44 
     45 #ifdef PROG_VARIANT_R
     46 #include "../../../../C/7zVersion.h"
     47 #else
     48 #include "../../MyVersion.h"
     49 #endif
     50 
     51 using namespace NWindows;
     52 using namespace NFile;
     53 using namespace NCommandLineParser;
     54 
     55 #ifdef _WIN32
     56 HINSTANCE g_hInstance = 0;
     57 #endif
     58 
     59 extern bool g_LargePagesMode;
     60 
     61 extern CStdOutStream *g_StdStream;
     62 extern CStdOutStream *g_ErrStream;
     63 
     64 extern unsigned g_NumCodecs;
     65 extern const CCodecInfo *g_Codecs[];
     66 
     67 extern unsigned g_NumHashers;
     68 extern const CHasherInfo *g_Hashers[];
     69 
     70 static const char * const kCopyrightString = "\n7-Zip"
     71  #ifndef EXTERNAL_CODECS
     72    #ifdef PROG_VARIANT_R
     73      " (r)"
     74    #else
     75      " (a)"
     76    #endif
     77  #endif
     78 
     79  " " MY_VERSION_CPU
     80  " : " MY_COPYRIGHT_DATE "\n\n";
     81 
     82 static const char * const kHelpString =
     83    "Usage: 7z"
     84 #ifndef EXTERNAL_CODECS
     85 #ifdef PROG_VARIANT_R
     86    "r"
     87 #else
     88    "a"
     89 #endif
     90 #endif
     91    " <command> [<switches>...] <archive_name> [<file_names>...]\n"
     92    "\n"
     93    "<Commands>\n"
     94    "  a : Add files to archive\n"
     95    "  b : Benchmark\n"
     96    "  d : Delete files from archive\n"
     97    "  e : Extract files from archive (without using directory names)\n"
     98    "  h : Calculate hash values for files\n"
     99    "  i : Show information about supported formats\n"
    100    "  l : List contents of archive\n"
    101    "  rn : Rename files in archive\n"
    102    "  t : Test integrity of archive\n"
    103    "  u : Update files to archive\n"
    104    "  x : eXtract files with full paths\n"
    105    "\n"
    106    "<Switches>\n"
    107    "  -- : Stop switches parsing\n"
    108    "  @listfile : set path to listfile that contains file names\n"
    109    "  -ai[r[-|0]]{@listfile|!wildcard} : Include archives\n"
    110    "  -ax[r[-|0]]{@listfile|!wildcard} : eXclude archives\n"
    111    "  -ao{a|s|t|u} : set Overwrite mode\n"
    112    "  -an : disable archive_name field\n"
    113    "  -bb[0-3] : set output log level\n"
    114    "  -bd : disable progress indicator\n"
    115    "  -bs{o|e|p}{0|1|2} : set output stream for output/error/progress line\n"
    116    "  -bt : show execution time statistics\n"
    117    "  -i[r[-|0]]{@listfile|!wildcard} : Include filenames\n"
    118    "  -m{Parameters} : set compression Method\n"
    119    "    -mmt[N] : set number of CPU threads\n"
    120    "    -mx[N] : set compression level: -mx1 (fastest) ... -mx9 (ultra)\n"
    121    "  -o{Directory} : set Output directory\n"
    122    #ifndef _NO_CRYPTO
    123    "  -p{Password} : set Password\n"
    124    #endif
    125    "  -r[-|0] : Recurse subdirectories\n"
    126    "  -sa{a|e|s} : set Archive name mode\n"
    127    "  -scc{UTF-8|WIN|DOS} : set charset for for console input/output\n"
    128    "  -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files\n"
    129    "  -scrc[CRC32|CRC64|SHA1|SHA256|*] : set hash function for x, e, h commands\n"
    130    "  -sdel : delete files after compression\n"
    131    "  -seml[.] : send archive by email\n"
    132    "  -sfx[{name}] : Create SFX archive\n"
    133    "  -si[{name}] : read data from stdin\n"
    134    "  -slp : set Large Pages mode\n"
    135    "  -slt : show technical information for l (List) command\n"
    136    "  -snh : store hard links as links\n"
    137    "  -snl : store symbolic links as links\n"
    138    "  -sni : store NT security information\n"
    139    "  -sns[-] : store NTFS alternate streams\n"
    140    "  -so : write data to stdout\n"
    141    "  -spd : disable wildcard matching for file names\n"
    142    "  -spe : eliminate duplication of root folder for extract command\n"
    143    "  -spf : use fully qualified file paths\n"
    144    "  -ssc[-] : set sensitive case mode\n"
    145    "  -sse : stop archive creating, if it can't open some input file\n"
    146    "  -ssw : compress shared files\n"
    147    "  -stl : set archive timestamp from the most recently modified file\n"
    148    "  -stm{HexMask} : set CPU thread affinity mask (hexadecimal number)\n"
    149    "  -stx{Type} : exclude archive type\n"
    150    "  -t{Type} : Set type of archive\n"
    151    "  -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName] : Update options\n"
    152    "  -v{Size}[b|k|m|g] : Create volumes\n"
    153    "  -w[{path}] : assign Work directory. Empty path means a temporary directory\n"
    154    "  -x[r[-|0]]{@listfile|!wildcard} : eXclude filenames\n"
    155    "  -y : assume Yes on all queries\n";
    156 
    157 // ---------------------------
    158 // exception messages
    159 
    160 static const char * const kEverythingIsOk = "Everything is Ok";
    161 static const char * const kUserErrorMessage = "Incorrect command line";
    162 static const char * const kNoFormats = "7-Zip cannot find the code that works with archives.";
    163 static const char * const kUnsupportedArcTypeMessage = "Unsupported archive type";
    164 // static const char * const kUnsupportedUpdateArcType = "Can't create archive for that type";
    165 
    166 #define kDefaultSfxModule "7zCon.sfx"
    167 
    168 static void ShowMessageAndThrowException(LPCSTR message, NExitCode::EEnum code)
    169 {
    170  if (g_ErrStream)
    171    *g_ErrStream << endl << "ERROR: " << message << endl;
    172  throw code;
    173 }
    174 
    175 #ifndef _WIN32
    176 static void GetArguments(int numArgs, const char *args[], UStringVector &parts)
    177 {
    178  parts.Clear();
    179  for (int i = 0; i < numArgs; i++)
    180  {
    181    UString s = MultiByteToUnicodeString(args[i]);
    182    parts.Add(s);
    183  }
    184 }
    185 #endif
    186 
    187 static void ShowCopyrightAndHelp(CStdOutStream *so, bool needHelp)
    188 {
    189  if (!so)
    190    return;
    191  *so << kCopyrightString;
    192  // *so << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << endl;
    193  if (needHelp)
    194    *so << kHelpString;
    195 }
    196 
    197 
    198 static void PrintStringRight(CStdOutStream &so, const char *s, unsigned size)
    199 {
    200  unsigned len = MyStringLen(s);
    201  for (unsigned i = len; i < size; i++)
    202    so << ' ';
    203  so << s;
    204 }
    205 
    206 static void PrintUInt32(CStdOutStream &so, UInt32 val, unsigned size)
    207 {
    208  char s[16];
    209  ConvertUInt32ToString(val, s);
    210  PrintStringRight(so, s, size);
    211 }
    212 
    213 static void PrintLibIndex(CStdOutStream &so, int libIndex)
    214 {
    215  if (libIndex >= 0)
    216    PrintUInt32(so, libIndex, 2);
    217  else
    218    so << "  ";
    219  so << ' ';
    220 }
    221 
    222 static void PrintString(CStdOutStream &so, const UString &s, unsigned size)
    223 {
    224  unsigned len = s.Len();
    225  so << s;
    226  for (unsigned i = len; i < size; i++)
    227    so << ' ';
    228 }
    229 
    230 static inline char GetHex(unsigned val)
    231 {
    232  return (char)((val < 10) ? ('0' + val) : ('A' + (val - 10)));
    233 }
    234 
    235 static void PrintWarningsPaths(const CErrorPathCodes &pc, CStdOutStream &so)
    236 {
    237  FOR_VECTOR(i, pc.Paths)
    238  {
    239    so.NormalizePrint_UString(pc.Paths[i]);
    240    so << " : ";
    241    so << NError::MyFormatMessage(pc.Codes[i]) << endl;
    242  }
    243  so << "----------------" << endl;
    244 }
    245 
    246 static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,
    247    const CUpdateErrorInfo &errorInfo,
    248    CStdOutStream *so,
    249    CStdOutStream *se,
    250    bool showHeaders)
    251 {
    252  int exitCode = NExitCode::kSuccess;
    253  
    254  if (callback.ScanErrors.Paths.Size() != 0)
    255  {
    256    if (se)
    257    {
    258      *se << endl;
    259      *se << "Scan WARNINGS for files and folders:" << endl << endl;
    260      PrintWarningsPaths(callback.ScanErrors, *se);
    261      *se << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size();
    262      *se << endl;
    263    }
    264    exitCode = NExitCode::kWarning;
    265  }
    266  
    267  if (result != S_OK || errorInfo.ThereIsError())
    268  {
    269    if (se)
    270    {
    271      UString message;
    272      if (!errorInfo.Message.IsEmpty())
    273      {
    274        message += errorInfo.Message.Ptr();
    275        message.Add_LF();
    276      }
    277      {
    278        FOR_VECTOR(i, errorInfo.FileNames)
    279        {
    280          message += fs2us(errorInfo.FileNames[i]);
    281          message.Add_LF();
    282        }
    283      }
    284      if (errorInfo.SystemError != 0)
    285      {
    286        message += NError::MyFormatMessage(errorInfo.SystemError);
    287        message.Add_LF();
    288      }
    289      if (!message.IsEmpty())
    290        *se << L"\nError:\n" << message;
    291    }
    292 
    293    // we will work with (result) later
    294    // throw CSystemException(result);
    295    return NExitCode::kFatalError;
    296  }
    297 
    298  unsigned numErrors = callback.FailedFiles.Paths.Size();
    299  if (numErrors == 0)
    300  {
    301    if (showHeaders)
    302      if (callback.ScanErrors.Paths.Size() == 0)
    303        if (so)
    304        {
    305          if (se)
    306            se->Flush();
    307          *so << kEverythingIsOk << endl;
    308        }
    309  }
    310  else
    311  {
    312    if (se)
    313    {
    314      *se << endl;
    315      *se << "WARNINGS for files:" << endl << endl;
    316      PrintWarningsPaths(callback.FailedFiles, *se);
    317      *se << "WARNING: Cannot open " << numErrors << " file";
    318      if (numErrors > 1)
    319        *se << 's';
    320      *se << endl;
    321    }
    322    exitCode = NExitCode::kWarning;
    323  }
    324  
    325  return exitCode;
    326 }
    327 
    328 static void ThrowException_if_Error(HRESULT res)
    329 {
    330  if (res != S_OK)
    331    throw CSystemException(res);
    332 }
    333 
    334 
    335 static void PrintNum(UInt64 val, unsigned numDigits, char c = ' ')
    336 {
    337  char temp[64];
    338  char *p = temp + 32;
    339  ConvertUInt64ToString(val, p);
    340  unsigned len = MyStringLen(p);
    341  for (; len < numDigits; len++)
    342    *--p = c;
    343  *g_StdStream << p;
    344 }
    345 
    346 static void PrintTime(const char *s, UInt64 val, UInt64 total)
    347 {
    348  *g_StdStream << endl << s << " Time =";
    349  const UInt32 kFreq = 10000000;
    350  UInt64 sec = val / kFreq;
    351  PrintNum(sec, 6);
    352  *g_StdStream << '.';
    353  UInt32 ms = (UInt32)(val - (sec * kFreq)) / (kFreq / 1000);
    354  PrintNum(ms, 3, '0');
    355  
    356  while (val > ((UInt64)1 << 56))
    357  {
    358    val >>= 1;
    359    total >>= 1;
    360  }
    361 
    362  UInt64 percent = 0;
    363  if (total != 0)
    364    percent = val * 100 / total;
    365  *g_StdStream << " =";
    366  PrintNum(percent, 5);
    367  *g_StdStream << '%';
    368 }
    369 
    370 #ifndef UNDER_CE
    371 
    372 #define SHIFT_SIZE_VALUE(x, num) (((x) + (1 << (num)) - 1) >> (num))
    373 
    374 static void PrintMemUsage(const char *s, UInt64 val)
    375 {
    376  *g_StdStream << "    " << s << " Memory =";
    377  PrintNum(SHIFT_SIZE_VALUE(val, 20), 7);
    378  *g_StdStream << " MB";
    379  if (g_LargePagesMode)
    380    *g_StdStream << " (LP)";
    381 }
    382 
    383 EXTERN_C_BEGIN
    384 typedef BOOL (WINAPI *Func_GetProcessMemoryInfo)(HANDLE Process,
    385    PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb);
    386 typedef BOOL (WINAPI *Func_QueryProcessCycleTime)(HANDLE Process, PULONG64 CycleTime);
    387 EXTERN_C_END
    388 
    389 #endif
    390 
    391 static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; }
    392 
    393 static void PrintStat()
    394 {
    395  FILETIME creationTimeFT, exitTimeFT, kernelTimeFT, userTimeFT;
    396  if (!
    397      #ifdef UNDER_CE
    398        ::GetThreadTimes(::GetCurrentThread()
    399      #else
    400        // NT 3.5
    401        ::GetProcessTimes(::GetCurrentProcess()
    402      #endif
    403      , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT))
    404    return;
    405  FILETIME curTimeFT;
    406  NTime::GetCurUtcFileTime(curTimeFT);
    407 
    408  #ifndef UNDER_CE
    409  
    410  PROCESS_MEMORY_COUNTERS m;
    411  memset(&m, 0, sizeof(m));
    412  BOOL memDefined = FALSE;
    413  BOOL cycleDefined = FALSE;
    414  ULONG64 cycleTime = 0;
    415  {
    416    /* NT 4.0: GetProcessMemoryInfo() in Psapi.dll
    417       Win7: new function K32GetProcessMemoryInfo() in kernel32.dll
    418       It's faster to call kernel32.dll code than Psapi.dll code
    419       GetProcessMemoryInfo() requires Psapi.lib
    420       Psapi.lib in SDK7+ can link to K32GetProcessMemoryInfo in kernel32.dll
    421       The program with K32GetProcessMemoryInfo will not work on systems before Win7
    422       // memDefined = GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m));
    423    */
    424 
    425    HMODULE kern = ::GetModuleHandleW(L"kernel32.dll");
    426    Func_GetProcessMemoryInfo my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo)
    427        ::GetProcAddress(kern, "K32GetProcessMemoryInfo");
    428    if (!my_GetProcessMemoryInfo)
    429    {
    430      HMODULE lib = LoadLibraryW(L"Psapi.dll");
    431      if (lib)
    432        my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo)::GetProcAddress(lib, "GetProcessMemoryInfo");
    433    }
    434    if (my_GetProcessMemoryInfo)
    435      memDefined = my_GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m));
    436    // FreeLibrary(lib);
    437 
    438    Func_QueryProcessCycleTime my_QueryProcessCycleTime = (Func_QueryProcessCycleTime)
    439        ::GetProcAddress(kern, "QueryProcessCycleTime");
    440    if (my_QueryProcessCycleTime)
    441      cycleDefined = my_QueryProcessCycleTime(GetCurrentProcess(), &cycleTime);
    442  }
    443 
    444  #endif
    445 
    446  UInt64 curTime = GetTime64(curTimeFT);
    447  UInt64 creationTime = GetTime64(creationTimeFT);
    448  UInt64 kernelTime = GetTime64(kernelTimeFT);
    449  UInt64 userTime = GetTime64(userTimeFT);
    450 
    451  UInt64 totalTime = curTime - creationTime;
    452  
    453  PrintTime("Kernel ", kernelTime, totalTime);
    454 
    455  #ifndef UNDER_CE
    456  if (cycleDefined)
    457  {
    458    *g_StdStream << " ";
    459    PrintNum(cycleTime / 1000000, 22);
    460    *g_StdStream << " MCycles";
    461  }
    462  #endif
    463 
    464  PrintTime("User   ", userTime, totalTime);
    465  
    466  PrintTime("Process", kernelTime + userTime, totalTime);
    467  #ifndef UNDER_CE
    468  if (memDefined) PrintMemUsage("Virtual ", m.PeakPagefileUsage);
    469  #endif
    470  
    471  PrintTime("Global ", totalTime, totalTime);
    472  #ifndef UNDER_CE
    473  if (memDefined) PrintMemUsage("Physical", m.PeakWorkingSetSize);
    474  #endif
    475  
    476  *g_StdStream << endl;
    477 }
    478 
    479 static void PrintHexId(CStdOutStream &so, UInt64 id)
    480 {
    481  char s[32];
    482  ConvertUInt64ToHex(id, s);
    483  PrintStringRight(so, s, 8);
    484 }
    485 
    486 
    487 int Main2(
    488  #ifndef _WIN32
    489  int numArgs, char *args[]
    490  #endif
    491 )
    492 {
    493  #if defined(_WIN32) && !defined(UNDER_CE)
    494  SetFileApisToOEM();
    495  #endif
    496 
    497  UStringVector commandStrings;
    498  
    499  #ifdef _WIN32
    500  NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
    501  #else
    502  GetArguments(numArgs, args, commandStrings);
    503  #endif
    504 
    505  #ifndef UNDER_CE
    506  if (commandStrings.Size() > 0)
    507    commandStrings.Delete(0);
    508  #endif
    509 
    510  if (commandStrings.Size() == 0)
    511  {
    512    ShowCopyrightAndHelp(g_StdStream, true);
    513    return 0;
    514  }
    515 
    516  CArcCmdLineOptions options;
    517 
    518  CArcCmdLineParser parser;
    519 
    520  parser.Parse1(commandStrings, options);
    521 
    522  g_StdOut.IsTerminalMode = options.IsStdOutTerminal;
    523  g_StdErr.IsTerminalMode = options.IsStdErrTerminal;
    524 
    525  if (options.Number_for_Out != k_OutStream_stdout)
    526    g_StdStream = (options.Number_for_Out == k_OutStream_stderr ? &g_StdErr : NULL);
    527 
    528  if (options.Number_for_Errors != k_OutStream_stderr)
    529    g_ErrStream = (options.Number_for_Errors == k_OutStream_stdout ? &g_StdOut : NULL);
    530 
    531  CStdOutStream *percentsStream = NULL;
    532  if (options.Number_for_Percents != k_OutStream_disabled)
    533    percentsStream = (options.Number_for_Percents == k_OutStream_stderr) ? &g_StdErr : &g_StdOut;;
    534  
    535  if (options.HelpMode)
    536  {
    537    ShowCopyrightAndHelp(g_StdStream, true);
    538    return 0;
    539  }
    540 
    541  if (options.EnableHeaders)
    542    ShowCopyrightAndHelp(g_StdStream, false);
    543 
    544  parser.Parse2(options);
    545 
    546  unsigned percentsNameLevel = 1;
    547  if (options.LogLevel == 0 || options.Number_for_Percents != options.Number_for_Out)
    548    percentsNameLevel = 2;
    549 
    550  unsigned consoleWidth = 80;
    551 
    552  if (percentsStream)
    553  {
    554    #ifdef _WIN32
    555    
    556    #if !defined(UNDER_CE)
    557    CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
    558    if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo))
    559      consoleWidth = consoleInfo.dwSize.X;
    560    #endif
    561    
    562    #else
    563    
    564    struct winsize w;
    565    if (ioctl(0, TIOCGWINSZ, &w) == )
    566      consoleWidth = w.ws_col;
    567    
    568    #endif
    569  }
    570 
    571  CREATE_CODECS_OBJECT
    572 
    573  codecs->CaseSensitiveChange = options.CaseSensitiveChange;
    574  codecs->CaseSensitive = options.CaseSensitive;
    575  ThrowException_if_Error(codecs->Load());
    576 
    577  bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
    578 
    579  if (codecs->Formats.Size() == 0 &&
    580        (isExtractGroupCommand
    581        || options.Command.CommandType == NCommandType::kList
    582        || options.Command.IsFromUpdateGroup()))
    583  {
    584    #ifdef EXTERNAL_CODECS
    585    if (!codecs->MainDll_ErrorPath.IsEmpty())
    586    {
    587      UString s ("Can't load module: ");
    588      s += fs2us(codecs->MainDll_ErrorPath);
    589      throw s;
    590    }
    591    #endif
    592    
    593    throw kNoFormats;
    594  }
    595 
    596  CObjectVector<COpenType> types;
    597  if (!ParseOpenTypes(*codecs, options.ArcType, types))
    598    throw kUnsupportedArcTypeMessage;
    599 
    600  CIntVector excludedFormats;
    601  FOR_VECTOR (k, options.ExcludedArcTypes)
    602  {
    603    CIntVector tempIndices;
    604    if (!codecs->FindFormatForArchiveType(options.ExcludedArcTypes[k], tempIndices)
    605        || tempIndices.Size() != 1)
    606      throw kUnsupportedArcTypeMessage;
    607    excludedFormats.AddToUniqueSorted(tempIndices[0]);
    608    // excludedFormats.Sort();
    609  }
    610 
    611  
    612  #ifdef EXTERNAL_CODECS
    613  if (isExtractGroupCommand
    614      || options.Command.CommandType == NCommandType::kHash
    615      || options.Command.CommandType == NCommandType::kBenchmark)
    616    ThrowException_if_Error(__externalCodecs.Load());
    617  #endif
    618 
    619  int retCode = NExitCode::kSuccess;
    620  HRESULT hresultMain = S_OK;
    621 
    622  // bool showStat = options.ShowTime;
    623  
    624  /*
    625  if (!options.EnableHeaders ||
    626      options.TechMode)
    627    showStat = false;
    628  */
    629  
    630 
    631  if (options.Command.CommandType == NCommandType::kInfo)
    632  {
    633    CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
    634    unsigned i;
    635 
    636    #ifdef EXTERNAL_CODECS
    637    so << endl << "Libs:" << endl;
    638    for (i = 0; i < codecs->Libs.Size(); i++)
    639    {
    640      PrintLibIndex(so, i);
    641      so << ' ' << codecs->Libs[i].Path << endl;
    642    }
    643    #endif
    644 
    645    so << endl << "Formats:" << endl;
    646    
    647    const char * const kArcFlags = "KSNFMGOPBELH";
    648    const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags);
    649    
    650    for (i = 0; i < codecs->Formats.Size(); i++)
    651    {
    652      const CArcInfoEx &arc = codecs->Formats[i];
    653 
    654      #ifdef EXTERNAL_CODECS
    655      PrintLibIndex(so, arc.LibIndex);
    656      #else
    657      so << "  ";
    658      #endif
    659 
    660      so << (char)(arc.UpdateEnabled ? 'C' : ' ');
    661      
    662      for (unsigned b = 0; b < kNumArcFlags; b++)
    663      {
    664        so << (char)
    665          ((arc.Flags & ((UInt32)1 << b)) != 0 ? kArcFlags[b] : ' ');
    666      }
    667        
    668      so << ' ';
    669      PrintString(so, arc.Name, 8);
    670      so << ' ';
    671      UString s;
    672      
    673      FOR_VECTOR (t, arc.Exts)
    674      {
    675        if (t != 0)
    676          s.Add_Space();
    677        const CArcExtInfo &ext = arc.Exts[t];
    678        s += ext.Ext;
    679        if (!ext.AddExt.IsEmpty())
    680        {
    681          s += " (";
    682          s += ext.AddExt;
    683          s += ')';
    684        }
    685      }
    686      
    687      PrintString(so, s, 13);
    688      so << ' ';
    689      
    690      if (arc.SignatureOffset != 0)
    691        so << "offset=" << arc.SignatureOffset << ' ';
    692 
    693      FOR_VECTOR(si, arc.Signatures)
    694      {
    695        if (si != 0)
    696          so << "  ||  ";
    697 
    698        const CByteBuffer &sig = arc.Signatures[si];
    699        
    700        for (size_t j = 0; j < sig.Size(); j++)
    701        {
    702          if (j != 0)
    703            so << ' ';
    704          Byte b = sig[j];
    705          if (b > 0x20 && b < 0x80)
    706          {
    707            so << (char)b;
    708          }
    709          else
    710          {
    711            so << GetHex((b >> 4) & 0xF);
    712            so << GetHex(b & 0xF);
    713          }
    714        }
    715      }
    716      so << endl;
    717    }
    718 
    719    so << endl << "Codecs:" << endl; //  << "Lib          ID Name" << endl;
    720 
    721    for (i = 0; i < g_NumCodecs; i++)
    722    {
    723      const CCodecInfo &cod = *g_Codecs[i];
    724 
    725      PrintLibIndex(so, -1);
    726 
    727      if (cod.NumStreams == 1)
    728        so << ' ';
    729      else
    730        so << cod.NumStreams;
    731      
    732      so << (char)(cod.CreateEncoder ? 'E' : ' ');
    733      so << (char)(cod.CreateDecoder ? 'D' : ' ');
    734 
    735      so << ' ';
    736      PrintHexId(so, cod.Id);
    737      so << ' ' << cod.Name << endl;
    738    }
    739 
    740 
    741    #ifdef EXTERNAL_CODECS
    742 
    743    UInt32 numMethods;
    744    if (codecs->GetNumMethods(&numMethods) == S_OK)
    745    for (UInt32 j = 0; j < numMethods; j++)
    746    {
    747      PrintLibIndex(so, codecs->GetCodec_LibIndex(j));
    748 
    749      UInt32 numStreams = codecs->GetCodec_NumStreams(j);
    750      if (numStreams == 1)
    751        so << ' ';
    752      else
    753        so << numStreams;
    754      
    755      so << (char)(codecs->GetCodec_EncoderIsAssigned(j) ? 'E' : ' ');
    756      so << (char)(codecs->GetCodec_DecoderIsAssigned(j) ? 'D' : ' ');
    757 
    758      so << ' ';
    759      UInt64 id;
    760      HRESULT res = codecs->GetCodec_Id(j, id);
    761      if (res != S_OK)
    762        id = (UInt64)(Int64)-1;
    763      PrintHexId(so, id);
    764      so << ' ' << codecs->GetCodec_Name(j) << endl;
    765    }
    766 
    767    #endif
    768    
    769 
    770    so << endl << "Hashers:" << endl; //  << " L Size       ID Name" << endl;
    771 
    772    for (i = 0; i < g_NumHashers; i++)
    773    {
    774      const CHasherInfo &codec = *g_Hashers[i];
    775      PrintLibIndex(so, -1);
    776      PrintUInt32(so, codec.DigestSize, 4);
    777      so << ' ';
    778      PrintHexId(so, codec.Id);
    779      so << ' ' << codec.Name << endl;
    780    }
    781 
    782    #ifdef EXTERNAL_CODECS
    783    
    784    numMethods = codecs->GetNumHashers();
    785    for (UInt32 j = 0; j < numMethods; j++)
    786    {
    787      PrintLibIndex(so, codecs->GetHasherLibIndex(j));
    788      PrintUInt32(so, codecs->GetHasherDigestSize(j), 4);
    789      so << ' ';
    790      PrintHexId(so, codecs->GetHasherId(j));
    791      so << ' ' << codecs->GetHasherName(j) << endl;
    792    }
    793 
    794    #endif
    795    
    796  }
    797  else if (options.Command.CommandType == NCommandType::kBenchmark)
    798  {
    799    CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
    800    hresultMain = BenchCon(EXTERNAL_CODECS_VARS_L
    801        options.Properties, options.NumIterations, (FILE *)so);
    802    if (hresultMain == S_FALSE)
    803    {
    804      if (g_ErrStream)
    805        *g_ErrStream << "\nDecoding ERROR\n";
    806      retCode = NExitCode::kFatalError;
    807      hresultMain = S_OK;
    808    }
    809  }
    810  else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)
    811  {
    812    UStringVector ArchivePathsSorted;
    813    UStringVector ArchivePathsFullSorted;
    814 
    815    if (options.StdInMode)
    816    {
    817      ArchivePathsSorted.Add(options.ArcName_for_StdInMode);
    818      ArchivePathsFullSorted.Add(options.ArcName_for_StdInMode);
    819    }
    820    else
    821    {
    822      CExtractScanConsole scan;
    823      
    824      scan.Init(options.EnableHeaders ? g_StdStream : NULL, g_ErrStream, percentsStream);
    825      scan.SetWindowWidth(consoleWidth);
    826 
    827      if (g_StdStream && options.EnableHeaders)
    828        *g_StdStream << "Scanning the drive for archives:" << endl;
    829 
    830      CDirItemsStat st;
    831 
    832      scan.StartScanning();
    833 
    834      hresultMain = EnumerateDirItemsAndSort(
    835          options.arcCensor,
    836          NWildcard::k_RelatPath,
    837          UString(), // addPathPrefix
    838          ArchivePathsSorted,
    839          ArchivePathsFullSorted,
    840          st,
    841          &scan);
    842 
    843      scan.CloseScanning();
    844 
    845      if (hresultMain == S_OK)
    846      {
    847        if (options.EnableHeaders)
    848          scan.PrintStat(st);
    849      }
    850      else
    851      {
    852        /*
    853        if (res != E_ABORT)
    854        {
    855          throw CSystemException(res);
    856          // errorInfo.Message = "Scanning error";
    857        }
    858        return res;
    859        */
    860      }
    861    }
    862 
    863    if (hresultMain == S_OK)
    864    if (isExtractGroupCommand)
    865    {
    866      CExtractCallbackConsole *ecs = new CExtractCallbackConsole;
    867      CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
    868 
    869      #ifndef _NO_CRYPTO
    870      ecs->PasswordIsDefined = options.PasswordEnabled;
    871      ecs->Password = options.Password;
    872      #endif
    873 
    874      ecs->Init(g_StdStream, g_ErrStream, percentsStream);
    875      ecs->MultiArcMode = (ArchivePathsSorted.Size() > 1);
    876 
    877      ecs->LogLevel = options.LogLevel;
    878      ecs->PercentsNameLevel = percentsNameLevel;
    879      
    880      if (percentsStream)
    881        ecs->SetWindowWidth(consoleWidth);
    882 
    883      /*
    884      COpenCallbackConsole openCallback;
    885      openCallback.Init(g_StdStream, g_ErrStream);
    886 
    887      #ifndef _NO_CRYPTO
    888      openCallback.PasswordIsDefined = options.PasswordEnabled;
    889      openCallback.Password = options.Password;
    890      #endif
    891      */
    892 
    893      CExtractOptions eo;
    894      (CExtractOptionsBase &)eo = options.ExtractOptions;
    895      
    896      eo.StdInMode = options.StdInMode;
    897      eo.StdOutMode = options.StdOutMode;
    898      eo.YesToAll = options.YesToAll;
    899      eo.TestMode = options.Command.IsTestCommand();
    900      
    901      #ifndef _SFX
    902      eo.Properties = options.Properties;
    903      #endif
    904 
    905      UString errorMessage;
    906      CDecompressStat stat;
    907      CHashBundle hb;
    908      IHashCalc *hashCalc = NULL;
    909 
    910      if (!options.HashMethods.IsEmpty())
    911      {
    912        hashCalc = &hb;
    913        ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS_L options.HashMethods));
    914        hb.Init();
    915      }
    916      
    917      hresultMain = Extract(
    918          codecs,
    919          types,
    920          excludedFormats,
    921          ArchivePathsSorted,
    922          ArchivePathsFullSorted,
    923          options.Censor.Pairs.Front().Head,
    924          eo, ecs, ecs, hashCalc, errorMessage, stat);
    925      
    926      ecs->ClosePercents();
    927 
    928      if (!errorMessage.IsEmpty())
    929      {
    930        if (g_ErrStream)
    931          *g_ErrStream << endl << "ERROR:" << endl << errorMessage << endl;
    932        if (hresultMain == S_OK)
    933          hresultMain = E_FAIL;
    934      }
    935 
    936      CStdOutStream *so = g_StdStream;
    937 
    938      bool isError = false;
    939 
    940      if (so)
    941      {
    942        *so << endl;
    943        
    944        if (ecs->NumTryArcs > 1)
    945        {
    946          *so << "Archives: " << ecs->NumTryArcs << endl;
    947          *so << "OK archives: " << ecs->NumOkArcs << endl;
    948        }
    949      }
    950 
    951      if (ecs->NumCantOpenArcs != 0)
    952      {
    953        isError = true;
    954        if (so)
    955          *so << "Can't open as archive: " << ecs->NumCantOpenArcs << endl;
    956      }
    957      
    958      if (ecs->NumArcsWithError != 0)
    959      {
    960        isError = true;
    961        if (so)
    962          *so << "Archives with Errors: " << ecs->NumArcsWithError << endl;
    963      }
    964      
    965      if (so)
    966      {
    967        if (ecs->NumArcsWithWarnings != 0)
    968          *so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;
    969        
    970        if (ecs->NumOpenArcWarnings != 0)
    971        {
    972          *so << endl;
    973          if (ecs->NumOpenArcWarnings != 0)
    974            *so << "Warnings: " << ecs->NumOpenArcWarnings << endl;
    975        }
    976      }
    977      
    978      if (ecs->NumOpenArcErrors != 0)
    979      {
    980        isError = true;
    981        if (so)
    982        {
    983          *so << endl;
    984          if (ecs->NumOpenArcErrors != 0)
    985            *so << "Open Errors: " << ecs->NumOpenArcErrors << endl;
    986        }
    987      }
    988 
    989      if (isError)
    990        retCode = NExitCode::kFatalError;
    991      
    992      if (so)
    993      if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0)
    994      {
    995        // if (ecs->NumArchives > 1)
    996        {
    997          *so << endl;
    998          if (ecs->NumFileErrors != 0)
    999            *so << "Sub items Errors: " << ecs->NumFileErrors << endl;
   1000        }
   1001      }
   1002      else if (hresultMain == S_OK)
   1003      {
   1004        if (stat.NumFolders != 0)
   1005          *so << "Folders: " << stat.NumFolders << endl;
   1006        if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0)
   1007          *so << "Files: " << stat.NumFiles << endl;
   1008        if (stat.NumAltStreams != 0)
   1009        {
   1010          *so << "Alternate Streams: " << stat.NumAltStreams << endl;
   1011          *so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl;
   1012        }
   1013        
   1014        *so
   1015          << "Size:       " << stat.UnpackSize << endl
   1016          << "Compressed: " << stat.PackSize << endl;
   1017        if (hashCalc)
   1018        {
   1019          *so << endl;
   1020          PrintHashStat(*so, hb);
   1021        }
   1022      }
   1023    }
   1024    else
   1025    {
   1026      UInt64 numErrors = 0;
   1027      UInt64 numWarnings = 0;
   1028      
   1029      // options.ExtractNtOptions.StoreAltStreams = true, if -sns[-] is not definmed
   1030 
   1031      hresultMain = ListArchives(
   1032          codecs,
   1033          types,
   1034          excludedFormats,
   1035          options.StdInMode,
   1036          ArchivePathsSorted,
   1037          ArchivePathsFullSorted,
   1038          options.ExtractOptions.NtOptions.AltStreams.Val,
   1039          options.AltStreams.Val, // we don't want to show AltStreams by default
   1040          options.Censor.Pairs.Front().Head,
   1041          options.EnableHeaders,
   1042          options.TechMode,
   1043          #ifndef _NO_CRYPTO
   1044          options.PasswordEnabled,
   1045          options.Password,
   1046          #endif
   1047          &options.Properties,
   1048          numErrors, numWarnings);
   1049 
   1050      if (options.EnableHeaders)
   1051        if (numWarnings > 0)
   1052          g_StdOut << endl << "Warnings: " << numWarnings << endl;
   1053      
   1054      if (numErrors > 0)
   1055      {
   1056        if (options.EnableHeaders)
   1057          g_StdOut << endl << "Errors: " << numErrors << endl;
   1058        retCode = NExitCode::kFatalError;
   1059      }
   1060    }
   1061  }
   1062  else if (options.Command.IsFromUpdateGroup())
   1063  {
   1064    CUpdateOptions &uo = options.UpdateOptions;
   1065    if (uo.SfxMode && uo.SfxModule.IsEmpty())
   1066      uo.SfxModule = kDefaultSfxModule;
   1067 
   1068    COpenCallbackConsole openCallback;
   1069    openCallback.Init(g_StdStream, g_ErrStream, percentsStream);
   1070 
   1071    #ifndef _NO_CRYPTO
   1072    bool passwordIsDefined =
   1073        (options.PasswordEnabled && !options.Password.IsEmpty());
   1074    openCallback.PasswordIsDefined = passwordIsDefined;
   1075    openCallback.Password = options.Password;
   1076    #endif
   1077 
   1078    CUpdateCallbackConsole callback;
   1079    callback.LogLevel = options.LogLevel;
   1080    callback.PercentsNameLevel = percentsNameLevel;
   1081 
   1082    if (percentsStream)
   1083      callback.SetWindowWidth(consoleWidth);
   1084 
   1085    #ifndef _NO_CRYPTO
   1086    callback.PasswordIsDefined = passwordIsDefined;
   1087    callback.AskPassword = (options.PasswordEnabled && options.Password.IsEmpty());
   1088    callback.Password = options.Password;
   1089    #endif
   1090 
   1091    callback.StdOutMode = uo.StdOutMode;
   1092    callback.Init(
   1093      // NULL,
   1094      g_StdStream, g_ErrStream, percentsStream);
   1095 
   1096    CUpdateErrorInfo errorInfo;
   1097 
   1098    /*
   1099    if (!uo.Init(codecs, types, options.ArchiveName))
   1100      throw kUnsupportedUpdateArcType;
   1101    */
   1102    hresultMain = UpdateArchive(codecs,
   1103        types,
   1104        options.ArchiveName,
   1105        options.Censor,
   1106        uo,
   1107        errorInfo, &openCallback, &callback, true);
   1108 
   1109    callback.ClosePercents2();
   1110 
   1111    CStdOutStream *se = g_StdStream;
   1112    if (!se)
   1113      se = g_ErrStream;
   1114 
   1115    retCode = WarningsCheck(hresultMain, callback, errorInfo,
   1116        g_StdStream, se,
   1117        true // options.EnableHeaders
   1118        );
   1119  }
   1120  else if (options.Command.CommandType == NCommandType::kHash)
   1121  {
   1122    const CHashOptions &uo = options.HashOptions;
   1123 
   1124    CHashCallbackConsole callback;
   1125    if (percentsStream)
   1126      callback.SetWindowWidth(consoleWidth);
   1127  
   1128    callback.Init(g_StdStream, g_ErrStream, percentsStream);
   1129    callback.PrintHeaders = options.EnableHeaders;
   1130 
   1131    AString errorInfoString;
   1132    hresultMain = HashCalc(EXTERNAL_CODECS_VARS_L
   1133        options.Censor, uo,
   1134        errorInfoString, &callback);
   1135    CUpdateErrorInfo errorInfo;
   1136    errorInfo.Message = errorInfoString;
   1137    CStdOutStream *se = g_StdStream;
   1138    if (!se)
   1139      se = g_ErrStream;
   1140    retCode = WarningsCheck(hresultMain, callback, errorInfo, g_StdStream, se, options.EnableHeaders);
   1141  }
   1142  else
   1143    ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);
   1144 
   1145  if (options.ShowTime && g_StdStream)
   1146    PrintStat();
   1147 
   1148  ThrowException_if_Error(hresultMain);
   1149 
   1150  return retCode;
   1151 }