xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/Console/Main.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // Main.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../Common/MyWindows.h"
6 
7 #ifdef _WIN32
8 
9 #ifndef Z7_OLD_WIN_SDK
10 
11 #if defined(__MINGW32__) || defined(__MINGW64__)
12 #include <psapi.h>
13 #else
14 #include <Psapi.h>
15 #endif
16 
17 #else // Z7_OLD_WIN_SDK
18 
19 typedef struct {
20     DWORD cb;
21     DWORD PageFaultCount;
22     SIZE_T PeakWorkingSetSize;
23     SIZE_T WorkingSetSize;
24     SIZE_T QuotaPeakPagedPoolUsage;
25     SIZE_T QuotaPagedPoolUsage;
26     SIZE_T QuotaPeakNonPagedPoolUsage;
27     SIZE_T QuotaNonPagedPoolUsage;
28     SIZE_T PagefileUsage;
29     SIZE_T PeakPagefileUsage;
30 } PROCESS_MEMORY_COUNTERS;
31 typedef PROCESS_MEMORY_COUNTERS *PPROCESS_MEMORY_COUNTERS;
32 
33 #endif // Z7_OLD_WIN_SDK
34 
35 #else // _WIN32
36 #include <unistd.h>
37 #include <sys/ioctl.h>
38 #include <sys/time.h>
39 #include <sys/times.h>
40 #endif // _WIN32
41 
42 #include "../../../../C/CpuArch.h"
43 
44 #include "../../../Common/MyInitGuid.h"
45 
46 #include "../../../Common/CommandLineParser.h"
47 #include "../../../Common/IntToString.h"
48 #include "../../../Common/MyException.h"
49 #include "../../../Common/StdInStream.h"
50 #include "../../../Common/StdOutStream.h"
51 #include "../../../Common/StringConvert.h"
52 #include "../../../Common/StringToInt.h"
53 #include "../../../Common/UTFConvert.h"
54 
55 #include "../../../Windows/ErrorMsg.h"
56 #include "../../../Windows/TimeUtils.h"
57 #include "../../../Windows/FileDir.h"
58 
59 #include "../Common/ArchiveCommandLine.h"
60 #include "../Common/Bench.h"
61 #include "../Common/ExitCode.h"
62 #include "../Common/Extract.h"
63 
64 #ifdef Z7_EXTERNAL_CODECS
65 #include "../Common/LoadCodecs.h"
66 #endif
67 
68 #include "../../Common/RegisterCodec.h"
69 
70 #include "BenchCon.h"
71 #include "ConsoleClose.h"
72 #include "ExtractCallbackConsole.h"
73 #include "HashCon.h"
74 #include "List.h"
75 #include "OpenCallbackConsole.h"
76 #include "UpdateCallbackConsole.h"
77 
78 #ifdef Z7_PROG_VARIANT_R
79 #include "../../../../C/7zVersion.h"
80 #else
81 #include "../../MyVersion.h"
82 #endif
83 
84 using namespace NWindows;
85 using namespace NFile;
86 using namespace NCommandLineParser;
87 
88 #ifdef _WIN32
89 extern
90 HINSTANCE g_hInstance;
91 HINSTANCE g_hInstance = NULL;
92 #endif
93 
94 extern CStdOutStream *g_StdStream;
95 extern CStdOutStream *g_ErrStream;
96 
97 extern unsigned g_NumCodecs;
98 extern const CCodecInfo *g_Codecs[];
99 
100 extern unsigned g_NumHashers;
101 extern const CHasherInfo *g_Hashers[];
102 
103 #ifdef Z7_EXTERNAL_CODECS
104 extern
105 const CExternalCodecs *g_ExternalCodecs_Ptr;
106 const CExternalCodecs *g_ExternalCodecs_Ptr;
107 #endif
108 
109 DECLARE_AND_SET_CLIENT_VERSION_VAR
110 
111 #if defined(Z7_PROG_VARIANT_Z)
112   #define PROG_POSTFIX      "z"
113   #define PROG_POSTFIX_2  " (z)"
114 #elif defined(Z7_PROG_VARIANT_R)
115   #define PROG_POSTFIX      "r"
116   #define PROG_POSTFIX_2  " (r)"
117 #elif defined(Z7_PROG_VARIANT_A) || !defined(Z7_EXTERNAL_CODECS)
118   #define PROG_POSTFIX      "a"
119   #define PROG_POSTFIX_2  " (a)"
120 #else
121   #define PROG_POSTFIX    ""
122   #define PROG_POSTFIX_2  ""
123 #endif
124 
125 
126 static const char * const kCopyrightString = "\n7-Zip"
127   PROG_POSTFIX_2
128   " " MY_VERSION_CPU
129   " : " MY_COPYRIGHT_DATE "\n";
130 
131 static const char * const kHelpString =
132     "Usage: 7z"
133     PROG_POSTFIX
134     " <command> [<switches>...] <archive_name> [<file_names>...] [@listfile]\n"
135     "\n"
136     "<Commands>\n"
137     "  a : Add files to archive\n"
138     "  b : Benchmark\n"
139     "  d : Delete files from archive\n"
140     "  e : Extract files from archive (without using directory names)\n"
141     "  h : Calculate hash values for files\n"
142     "  i : Show information about supported formats\n"
143     "  l : List contents of archive\n"
144     "  rn : Rename files in archive\n"
145     "  t : Test integrity of archive\n"
146     "  u : Update files to archive\n"
147     "  x : eXtract files with full paths\n"
148     "\n"
149     "<Switches>\n"
150     "  -- : Stop switches and @listfile parsing\n"
151     "  -ai[r[-|0]][m[-|2]][w[-]]{@listfile|!wildcard} : Include archives\n"
152     "  -ax[r[-|0]][m[-|2]][w[-]]{@listfile|!wildcard} : eXclude archives\n"
153     "  -ao{a|s|t|u} : set Overwrite mode\n"
154     "  -an : disable archive_name field\n"
155     "  -bb[0-3] : set output log level\n"
156     "  -bd : disable progress indicator\n"
157     "  -bs{o|e|p}{0|1|2} : set output stream for output/error/progress line\n"
158     "  -bt : show execution time statistics\n"
159     "  -i[r[-|0]][m[-|2]][w[-]]{@listfile|!wildcard} : Include filenames\n"
160     "  -m{Parameters} : set compression Method\n"
161     "    -mmt[N] : set number of CPU threads\n"
162     "    -mx[N] : set compression level: -mx1 (fastest) ... -mx9 (ultra)\n"
163     "  -o{Directory} : set Output directory\n"
164     #ifndef Z7_NO_CRYPTO
165     "  -p{Password} : set Password\n"
166     #endif
167     "  -r[-|0] : Recurse subdirectories for name search\n"
168     "  -sa{a|e|s} : set Archive name mode\n"
169     "  -scc{UTF-8|WIN|DOS} : set charset for console input/output\n"
170     "  -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files\n"
171     "  -scrc[CRC32|CRC64|SHA256"
172 #ifndef Z7_PROG_VARIANT_R
173     "|SHA1|XXH64"
174 #ifdef Z7_PROG_VARIANT_Z
175     "|BLAKE2SP"
176 #endif
177 #endif
178     "|*] : set hash function for x, e, h commands\n"
179     "  -sdel : delete files after compression\n"
180     "  -seml[.] : send archive by email\n"
181     "  -sfx[{name}] : Create SFX archive\n"
182     "  -si[{name}] : read data from stdin\n"
183     "  -slp : set Large Pages mode\n"
184     "  -slt : show technical information for l (List) command\n"
185     "  -snh : store hard links as links\n"
186     "  -snl : store symbolic links as links\n"
187     "  -sni : store NT security information\n"
188     "  -sns[-] : store NTFS alternate streams\n"
189     "  -so : write data to stdout\n"
190     "  -spd : disable wildcard matching for file names\n"
191     "  -spe : eliminate duplication of root folder for extract command\n"
192     "  -spf[2] : use fully qualified file paths\n"
193     "  -ssc[-] : set sensitive case mode\n"
194     "  -sse : stop archive creating, if it can't open some input file\n"
195     "  -ssp : do not change Last Access Time of source files while archiving\n"
196     "  -ssw : compress shared files\n"
197     "  -stl : set archive timestamp from the most recently modified file\n"
198     "  -stm{HexMask} : set CPU thread affinity mask (hexadecimal number)\n"
199     "  -stx{Type} : exclude archive type\n"
200     "  -t{Type} : Set type of archive\n"
201     "  -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName] : Update options\n"
202     "  -v{Size}[b|k|m|g] : Create volumes\n"
203     "  -w[{path}] : assign Work directory. Empty path means a temporary directory\n"
204     "  -x[r[-|0]][m[-|2]][w[-]]{@listfile|!wildcard} : eXclude filenames\n"
205     "  -y : assume Yes on all queries\n";
206 
207 // ---------------------------
208 // exception messages
209 
210 static const char * const kEverythingIsOk = "Everything is Ok";
211 static const char * const kUserErrorMessage = "Incorrect command line";
212 static const char * const kNoFormats = "7-Zip cannot find the code that works with archives.";
213 static const char * const kUnsupportedArcTypeMessage = "Unsupported archive type";
214 // static const char * const kUnsupportedUpdateArcType = "Can't create archive for that type";
215 
216 #ifndef Z7_EXTRACT_ONLY
217 #define kDefaultSfxModule "7zCon.sfx"
218 #endif
219 
220 Z7_ATTR_NORETURN
ShowMessageAndThrowException(LPCSTR message,NExitCode::EEnum code)221 static void ShowMessageAndThrowException(LPCSTR message, NExitCode::EEnum code)
222 {
223   if (g_ErrStream)
224     *g_ErrStream << endl << "ERROR: " << message << endl;
225   throw code;
226 }
227 
228 
229 #ifdef _WIN32
230 #define ShowProgInfo(so)
231 #else
ShowProgInfo(CStdOutStream * so)232 static void ShowProgInfo(CStdOutStream *so)
233 {
234   if (!so)
235     return;
236 
237   *so
238 
239   /*
240   #ifdef __DATE__
241       << " " << __DATE__
242   #endif
243   #ifdef __TIME__
244       << " " << __TIME__
245   #endif
246   */
247 
248   << " " << (unsigned)(sizeof(void *)) * 8 << "-bit"
249 
250   #ifdef __ILP32__
251     << " ILP32"
252   #endif
253 
254   #ifdef __ARM_ARCH
255   << " arm_v:" << __ARM_ARCH
256   #if (__ARM_ARCH == 8)
257     // for macos:
258     #if   defined(__ARM_ARCH_8_9__)
259       << ".9"
260     #elif defined(__ARM_ARCH_8_8__)
261       << ".8"
262     #elif defined(__ARM_ARCH_8_7__)
263       << ".7"
264     #elif defined(__ARM_ARCH_8_6__)
265       << ".6"
266     #elif defined(__ARM_ARCH_8_5__)
267       << ".5"
268     #elif defined(__ARM_ARCH_8_4__)
269       << ".4"
270     #elif defined(__ARM_ARCH_8_3__)
271       << ".3"
272     #elif defined(__ARM_ARCH_8_2__)
273       << ".2"
274     #elif defined(__ARM_ARCH_8_1__)
275       << ".1"
276     #endif
277   #endif
278 
279     #if defined(__ARM_ARCH_PROFILE) && \
280         (   __ARM_ARCH_PROFILE >= 'A' && __ARM_ARCH_PROFILE <= 'Z' \
281          || __ARM_ARCH_PROFILE >= 65  && __ARM_ARCH_PROFILE <= 65 + 25)
282       << "-" << (char)__ARM_ARCH_PROFILE
283     #endif
284 
285   #ifdef __ARM_ARCH_ISA_THUMB
286   << " thumb:" << __ARM_ARCH_ISA_THUMB
287   #endif
288   #endif
289 
290   #ifdef _MIPS_ARCH
291   << " mips_arch:" << _MIPS_ARCH
292   #endif
293   #ifdef __mips_isa_rev
294   << " mips_isa_rev:" << __mips_isa_rev
295   #endif
296 
297   #ifdef __iset__
298   << " e2k_v:" << __iset__
299   #endif
300   ;
301 
302 
303 
304   #ifdef ENV_HAVE_LOCALE
305     *so << " locale=" << GetLocale();
306   #endif
307   #ifndef _WIN32
308   {
309     const bool is_IsNativeUTF8 = IsNativeUTF8();
310     if (!is_IsNativeUTF8)
311       *so << " UTF8=" << (is_IsNativeUTF8 ? "+" : "-");
312   }
313   if (!g_ForceToUTF8)
314     *so << " use-UTF8=" << (g_ForceToUTF8 ? "+" : "-");
315   {
316     const unsigned wchar_t_size = (unsigned)sizeof(wchar_t);
317     if (wchar_t_size != 4)
318       *so << " wchar_t=" << wchar_t_size * 8 << "-bit";
319   }
320   {
321     const unsigned off_t_size = (unsigned)sizeof(off_t);
322     if (off_t_size != 8)
323       *so << " Files=" << off_t_size * 8 << "-bit";
324   }
325   #endif
326 
327   {
328     const UInt32 numCpus = NWindows::NSystem::GetNumberOfProcessors();
329     *so << " Threads:" << numCpus;
330     const UInt64 openMAX= NWindows::NSystem::Get_File_OPEN_MAX();
331     *so << " OPEN_MAX:" << openMAX;
332     {
333       FString temp;
334       NDir::MyGetTempPath(temp);
335       if (!temp.IsEqualTo(STRING_PATH_SEPARATOR "tmp" STRING_PATH_SEPARATOR))
336         *so << " temp_path:" << temp;
337     }
338   }
339 
340   #ifdef Z7_7ZIP_ASM
341   *so << ", ASM";
342   #endif
343 
344   /*
345   {
346     AString s;
347     GetCpuName(s);
348     s.Trim();
349     *so << ", " << s;
350   }
351 
352   #ifdef __ARM_FEATURE_CRC32
353      << " CRC32"
354   #endif
355 
356 
357   #if (defined MY_CPU_X86_OR_AMD64 || defined(MY_CPU_ARM_OR_ARM64))
358   if (CPU_IsSupported_AES()) *so << ",AES";
359   #endif
360 
361   #ifdef MY_CPU_ARM_OR_ARM64
362   if (CPU_IsSupported_CRC32()) *so << ",CRC32";
363   #if defined(_WIN32)
364   if (CPU_IsSupported_CRYPTO()) *so << ",CRYPTO";
365   #else
366   if (CPU_IsSupported_SHA1()) *so << ",SHA1";
367   if (CPU_IsSupported_SHA2()) *so << ",SHA2";
368   #endif
369   #endif
370   */
371 
372   *so << endl;
373 }
374 #endif
375 
ShowCopyrightAndHelp(CStdOutStream * so,bool needHelp)376 static void ShowCopyrightAndHelp(CStdOutStream *so, bool needHelp)
377 {
378   if (!so)
379     return;
380   *so << kCopyrightString;
381   // *so << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << endl;
382   ShowProgInfo(so);
383   *so << endl;
384   if (needHelp)
385     *so << kHelpString;
386 }
387 
388 
PrintStringRight(CStdOutStream & so,const char * s,unsigned size)389 static void PrintStringRight(CStdOutStream &so, const char *s, unsigned size)
390 {
391   unsigned len = MyStringLen(s);
392   for (unsigned i = len; i < size; i++)
393     so << ' ';
394   so << s;
395 }
396 
PrintUInt32(CStdOutStream & so,UInt32 val,unsigned size)397 static void PrintUInt32(CStdOutStream &so, UInt32 val, unsigned size)
398 {
399   char s[16];
400   ConvertUInt32ToString(val, s);
401   PrintStringRight(so, s, size);
402 }
403 
404 #ifdef Z7_EXTERNAL_CODECS
PrintNumber(CStdOutStream & so,UInt32 val,unsigned numDigits)405 static void PrintNumber(CStdOutStream &so, UInt32 val, unsigned numDigits)
406 {
407   AString s;
408   s.Add_UInt32(val);
409   while (s.Len() < numDigits)
410     s.InsertAtFront('0');
411   so << s;
412 }
413 #endif
414 
PrintLibIndex(CStdOutStream & so,int libIndex)415 static void PrintLibIndex(CStdOutStream &so, int libIndex)
416 {
417   if (libIndex >= 0)
418     PrintUInt32(so, (UInt32)libIndex, 2);
419   else
420     so << "  ";
421   so << ' ';
422 }
423 
PrintString(CStdOutStream & so,const UString & s,unsigned size)424 static void PrintString(CStdOutStream &so, const UString &s, unsigned size)
425 {
426   unsigned len = s.Len();
427   so << s;
428   for (unsigned i = len; i < size; i++)
429     so << ' ';
430 }
431 
PrintWarningsPaths(const CErrorPathCodes & pc,CStdOutStream & so)432 static void PrintWarningsPaths(const CErrorPathCodes &pc, CStdOutStream &so)
433 {
434   FOR_VECTOR(i, pc.Paths)
435   {
436     so.NormalizePrint_UString_Path(fs2us(pc.Paths[i]));
437     so << " : ";
438     so << NError::MyFormatMessage(pc.Codes[i]) << endl;
439   }
440   so << "----------------" << endl;
441 }
442 
WarningsCheck(HRESULT result,const CCallbackConsoleBase & callback,const CUpdateErrorInfo & errorInfo,CStdOutStream * so,CStdOutStream * se,bool showHeaders)443 static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,
444     const CUpdateErrorInfo &errorInfo,
445     CStdOutStream *so,
446     CStdOutStream *se,
447     bool showHeaders)
448 {
449   int exitCode = NExitCode::kSuccess;
450 
451   if (callback.ScanErrors.Paths.Size() != 0)
452   {
453     if (se)
454     {
455       *se << endl;
456       *se << "Scan WARNINGS for files and folders:" << endl << endl;
457       PrintWarningsPaths(callback.ScanErrors, *se);
458       *se << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size();
459       *se << endl;
460     }
461     exitCode = NExitCode::kWarning;
462   }
463 
464   if (result != S_OK || errorInfo.ThereIsError())
465   {
466     if (se)
467     {
468       UString message;
469       if (!errorInfo.Message.IsEmpty())
470       {
471         message += errorInfo.Message.Ptr();
472         message.Add_LF();
473       }
474       {
475         FOR_VECTOR(i, errorInfo.FileNames)
476         {
477           message += fs2us(errorInfo.FileNames[i]);
478           message.Add_LF();
479         }
480       }
481       if (errorInfo.SystemError != 0)
482       {
483         message += NError::MyFormatMessage(errorInfo.SystemError);
484         message.Add_LF();
485       }
486       if (!message.IsEmpty())
487         *se << L"\nError:\n" << message;
488     }
489 
490     // we will work with (result) later
491     // throw CSystemException(result);
492     return NExitCode::kFatalError;
493   }
494 
495   unsigned numErrors = callback.FailedFiles.Paths.Size();
496   if (numErrors == 0)
497   {
498     if (showHeaders)
499       if (callback.ScanErrors.Paths.Size() == 0)
500         if (so)
501         {
502           if (se)
503             se->Flush();
504           *so << kEverythingIsOk << endl;
505         }
506   }
507   else
508   {
509     if (se)
510     {
511       *se << endl;
512       *se << "WARNINGS for files:" << endl << endl;
513       PrintWarningsPaths(callback.FailedFiles, *se);
514       *se << "WARNING: Cannot open " << numErrors << " file";
515       if (numErrors > 1)
516         *se << 's';
517       *se << endl;
518     }
519     exitCode = NExitCode::kWarning;
520   }
521 
522   return exitCode;
523 }
524 
ThrowException_if_Error(HRESULT res)525 static void ThrowException_if_Error(HRESULT res)
526 {
527   if (res != S_OK)
528     throw CSystemException(res);
529 }
530 
PrintNum(UInt64 val,unsigned numDigits,char c=' ')531 static void PrintNum(UInt64 val, unsigned numDigits, char c = ' ')
532 {
533   char temp[64];
534   char *p = temp + 32;
535   ConvertUInt64ToString(val, p);
536   unsigned len = MyStringLen(p);
537   for (; len < numDigits; len++)
538     *--p = c;
539   *g_StdStream << p;
540 }
541 
542 #ifdef _WIN32
543 
PrintTime(const char * s,UInt64 val,UInt64 total)544 static void PrintTime(const char *s, UInt64 val, UInt64 total)
545 {
546   *g_StdStream << endl << s << " Time =";
547   const UInt32 kFreq = 10000000;
548   UInt64 sec = val / kFreq;
549   PrintNum(sec, 6);
550   *g_StdStream << '.';
551   UInt32 ms = (UInt32)(val - (sec * kFreq)) / (kFreq / 1000);
552   PrintNum(ms, 3, '0');
553 
554   while (val > ((UInt64)1 << 56))
555   {
556     val >>= 1;
557     total >>= 1;
558   }
559 
560   UInt64 percent = 0;
561   if (total != 0)
562     percent = val * 100 / total;
563   *g_StdStream << " =";
564   PrintNum(percent, 5);
565   *g_StdStream << '%';
566 }
567 
568 #ifndef UNDER_CE
569 
570 #define SHIFT_SIZE_VALUE(x, num) (((x) + (1 << (num)) - 1) >> (num))
571 
PrintMemUsage(const char * s,UInt64 val)572 static void PrintMemUsage(const char *s, UInt64 val)
573 {
574   *g_StdStream << "    " << s << " Memory =";
575   PrintNum(SHIFT_SIZE_VALUE(val, 20), 7);
576   *g_StdStream << " MB";
577   /*
578   *g_StdStream << " =";
579   PrintNum(SHIFT_SIZE_VALUE(val, 10), 9);
580   *g_StdStream << " KB";
581   */
582   #ifdef Z7_LARGE_PAGES
583   AString lp;
584   Add_LargePages_String(lp);
585   if (!lp.IsEmpty())
586     *g_StdStream << lp;
587   #endif
588 }
589 
590 EXTERN_C_BEGIN
591 typedef BOOL (WINAPI *Func_GetProcessMemoryInfo)(HANDLE Process,
592     PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb);
593 typedef BOOL (WINAPI *Func_QueryProcessCycleTime)(HANDLE Process, PULONG64 CycleTime);
594 EXTERN_C_END
595 
596 #endif
597 
GetTime64(const FILETIME & t)598 static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; }
599 
PrintStat()600 static void PrintStat()
601 {
602   FILETIME creationTimeFT, exitTimeFT, kernelTimeFT, userTimeFT;
603   if (!
604       #ifdef UNDER_CE
605         ::GetThreadTimes(::GetCurrentThread()
606       #else
607         // NT 3.5
608         ::GetProcessTimes(::GetCurrentProcess()
609       #endif
610       , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT))
611     return;
612   FILETIME curTimeFT;
613   NTime::GetCurUtc_FiTime(curTimeFT);
614 
615   #ifndef UNDER_CE
616 
617 Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
618 
619   PROCESS_MEMORY_COUNTERS m;
620   memset(&m, 0, sizeof(m));
621   BOOL memDefined = FALSE;
622   BOOL cycleDefined = FALSE;
623   ULONG64 cycleTime = 0;
624   {
625     /* NT 4.0: GetProcessMemoryInfo() in Psapi.dll
626        Win7: new function K32GetProcessMemoryInfo() in kernel32.dll
627        It's faster to call kernel32.dll code than Psapi.dll code
628        GetProcessMemoryInfo() requires Psapi.lib
629        Psapi.lib in SDK7+ can link to K32GetProcessMemoryInfo in kernel32.dll
630        The program with K32GetProcessMemoryInfo will not work on systems before Win7
631        // memDefined = GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m));
632     */
633     const HMODULE kern = ::GetModuleHandleW(L"kernel32.dll");
634     Func_GetProcessMemoryInfo
635       my_GetProcessMemoryInfo = Z7_GET_PROC_ADDRESS(
636     Func_GetProcessMemoryInfo, kern,
637      "K32GetProcessMemoryInfo");
638     if (!my_GetProcessMemoryInfo)
639     {
640       const HMODULE lib = LoadLibraryW(L"Psapi.dll");
641       if (lib)
642           my_GetProcessMemoryInfo = Z7_GET_PROC_ADDRESS(
643         Func_GetProcessMemoryInfo, lib,
644             "GetProcessMemoryInfo");
645     }
646     if (my_GetProcessMemoryInfo)
647       memDefined = my_GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m));
648     // FreeLibrary(lib);
649     const
650     Func_QueryProcessCycleTime
651       my_QueryProcessCycleTime = Z7_GET_PROC_ADDRESS(
652     Func_QueryProcessCycleTime, kern,
653         "QueryProcessCycleTime");
654     if (my_QueryProcessCycleTime)
655       cycleDefined = my_QueryProcessCycleTime(GetCurrentProcess(), &cycleTime);
656   }
657 
658   #endif
659 
660   UInt64 curTime = GetTime64(curTimeFT);
661   UInt64 creationTime = GetTime64(creationTimeFT);
662   UInt64 kernelTime = GetTime64(kernelTimeFT);
663   UInt64 userTime = GetTime64(userTimeFT);
664 
665   UInt64 totalTime = curTime - creationTime;
666 
667   PrintTime("Kernel ", kernelTime, totalTime);
668 
669   const UInt64 processTime = kernelTime + userTime;
670 
671   #ifndef UNDER_CE
672   if (cycleDefined)
673   {
674     *g_StdStream << "    Cnt:";
675     PrintNum(cycleTime / 1000000, 15);
676     *g_StdStream << " MCycles";
677   }
678   #endif
679 
680   PrintTime("User   ", userTime, totalTime);
681 
682   #ifndef UNDER_CE
683   if (cycleDefined)
684   {
685     *g_StdStream << "    Freq (cnt/ptime):";
686     UInt64 us = processTime / 10;
687     if (us == 0)
688       us = 1;
689     PrintNum(cycleTime / us, 6);
690     *g_StdStream << " MHz";
691   }
692   #endif
693 
694   PrintTime("Process", processTime, totalTime);
695   #ifndef UNDER_CE
696   if (memDefined) PrintMemUsage("Virtual ", m.PeakPagefileUsage);
697   #endif
698 
699   PrintTime("Global ", totalTime, totalTime);
700   #ifndef UNDER_CE
701   if (memDefined) PrintMemUsage("Physical", m.PeakWorkingSetSize);
702   #endif
703   *g_StdStream << endl;
704 }
705 
706 
707 #else  // ! _WIN32
708 
Get_timeofday_us()709 static UInt64 Get_timeofday_us()
710 {
711   struct timeval now;
712   if (gettimeofday(&now, NULL) == 0)
713     return (UInt64)now.tv_sec * 1000000 + (UInt64)now.tv_usec;
714   return 0;
715 }
716 
PrintTime(const char * s,UInt64 val,UInt64 total_us,UInt64 kFreq)717 static void PrintTime(const char *s, UInt64 val, UInt64 total_us, UInt64 kFreq)
718 {
719   *g_StdStream << endl << s << " Time =";
720 
721   {
722     UInt64 sec, ms;
723 
724     if (kFreq == 0)
725     {
726       sec = val / 1000000;
727       ms  = val % 1000000 / 1000;
728     }
729     else
730     {
731       sec = val / kFreq;
732       ms = (UInt32)((val - (sec * kFreq)) * 1000 / kFreq);
733     }
734 
735     PrintNum(sec, 6);
736     *g_StdStream << '.';
737     PrintNum(ms, 3, '0');
738   }
739 
740   if (total_us == 0)
741     return;
742 
743   UInt64 percent = 0;
744   if (kFreq == 0)
745     percent = val * 100 / total_us;
746   else
747   {
748     const UInt64 kMaxVal = (UInt64)(Int64)-1;
749     UInt32 m = 100000000;
750     for (;;)
751     {
752       if (m == 0 || kFreq == 0)
753         break;
754       if (kMaxVal / m > val &&
755         kMaxVal / kFreq > total_us)
756         break;
757       if (val > m)
758         val >>= 1;
759       else
760         m >>= 1;
761       if (kFreq > total_us)
762         kFreq >>= 1;
763       else
764         total_us >>= 1;
765     }
766     const UInt64 total = kFreq * total_us;
767     if (total != 0)
768       percent = val * m / total;
769   }
770   *g_StdStream << " =";
771   PrintNum(percent, 5);
772   *g_StdStream << '%';
773 }
774 
PrintStat(const UInt64 startTime)775 static void PrintStat(const UInt64 startTime)
776 {
777   tms t;
778   /* clock_t res = */ times(&t);
779   const UInt64 totalTime = Get_timeofday_us() - startTime;
780   const UInt64 kFreq = (UInt64)sysconf(_SC_CLK_TCK);
781   PrintTime("Kernel ", (UInt64)t.tms_stime, totalTime, kFreq);
782   PrintTime("User   ", (UInt64)t.tms_utime, totalTime, kFreq);
783   PrintTime("Process", (UInt64)t.tms_utime + (UInt64)t.tms_stime, totalTime, kFreq);
784   PrintTime("Global ", totalTime, totalTime, 0);
785   *g_StdStream << endl;
786 }
787 
788 #endif // ! _WIN32
789 
790 
791 
792 
793 
PrintHexId(CStdOutStream & so,UInt64 id)794 static void PrintHexId(CStdOutStream &so, UInt64 id)
795 {
796   char s[32];
797   ConvertUInt64ToHex(id, s);
798   PrintStringRight(so, s, 8);
799 }
800 
801 #ifndef _WIN32
802 void Set_ModuleDirPrefix_From_ProgArg0(const char *s);
803 #endif
804 
805 int Main2(
806   #ifndef _WIN32
807   int numArgs, char *args[]
808   #endif
809 );
Main2(int numArgs,char * args[])810 int Main2(
811   #ifndef _WIN32
812   int numArgs, char *args[]
813   #endif
814 )
815 {
816   #if defined(MY_CPU_SIZEOF_POINTER)
817     { unsigned k = sizeof(void *); if (k != MY_CPU_SIZEOF_POINTER) throw "incorrect MY_CPU_PTR_SIZE"; }
818   #endif
819 
820   #if defined(_WIN32) && !defined(UNDER_CE)
821   SetFileApisToOEM();
822   #endif
823 
824   #ifdef ENV_HAVE_LOCALE
825   // printf("\nBefore SetLocale() : %s\n", IsNativeUtf8() ? "NATIVE UTF-8" : "IS NOT NATIVE UTF-8");
826   MY_SetLocale();
827   // printf("\nAfter  SetLocale() : %s\n", IsNativeUtf8() ? "NATIVE UTF-8" : "IS NOT NATIVE UTF-8");
828   #endif
829 
830   #ifndef _WIN32
831   const UInt64 startTime = Get_timeofday_us();
832   #endif
833 
834   /*
835   {
836     g_StdOut << "DWORD:" << (unsigned)sizeof(DWORD);
837     g_StdOut << " LONG:" << (unsigned)sizeof(LONG);
838     g_StdOut << " long:" << (unsigned)sizeof(long);
839     #ifdef _WIN64
840     // g_StdOut << " long long:" << (unsigned)sizeof(long long);
841     #endif
842     g_StdOut << " int:" << (unsigned)sizeof(int);
843     g_StdOut << " void*:"  << (unsigned)sizeof(void *);
844     g_StdOut << endl;
845   }
846   */
847 
848   UStringVector commandStrings;
849 
850   #ifdef _WIN32
851   NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
852   #else
853   {
854     if (numArgs > 0)
855       Set_ModuleDirPrefix_From_ProgArg0(args[0]);
856 
857     for (int i = 0; i < numArgs; i++)
858     {
859       AString a (args[i]);
860 #if 0
861       printf("\n%d %s :", i, a.Ptr());
862       for (unsigned k = 0; k < a.Len(); k++)
863         printf(" %2x", (unsigned)(Byte)a[k]);
864 #endif
865       const UString s = MultiByteToUnicodeString(a);
866       commandStrings.Add(s);
867     }
868     // printf("\n");
869   }
870 
871   #endif
872 
873   #ifndef UNDER_CE
874   if (commandStrings.Size() > 0)
875     commandStrings.Delete(0);
876   #endif
877 
878   if (commandStrings.Size() == 0)
879   {
880     ShowCopyrightAndHelp(g_StdStream, true);
881     return 0;
882   }
883 
884   CArcCmdLineOptions options;
885 
886   CArcCmdLineParser parser;
887 
888   parser.Parse1(commandStrings, options);
889 
890   g_StdOut.IsTerminalMode = options.IsStdOutTerminal;
891   g_StdErr.IsTerminalMode = options.IsStdErrTerminal;
892 
893   if (options.Number_for_Out != k_OutStream_stdout)
894     g_StdStream = (options.Number_for_Out == k_OutStream_stderr ? &g_StdErr : NULL);
895 
896   if (options.Number_for_Errors != k_OutStream_stderr)
897     g_ErrStream = (options.Number_for_Errors == k_OutStream_stdout ? &g_StdOut : NULL);
898 
899   CStdOutStream *percentsStream = NULL;
900   if (options.Number_for_Percents != k_OutStream_disabled)
901     percentsStream = (options.Number_for_Percents == k_OutStream_stderr) ? &g_StdErr : &g_StdOut;
902 
903   if (options.HelpMode)
904   {
905     ShowCopyrightAndHelp(g_StdStream, true);
906     return 0;
907   }
908 
909   if (options.EnableHeaders)
910   {
911     ShowCopyrightAndHelp(g_StdStream, false);
912     if (!parser.Parse1Log.IsEmpty())
913       *g_StdStream << parser.Parse1Log;
914   }
915 
916   parser.Parse2(options);
917 
918   {
919     int cp = options.ConsoleCodePage;
920 
921     int stdout_cp = cp;
922     int stderr_cp = cp;
923     int stdin_cp = cp;
924 
925     /*
926     // these cases are complicated.
927     // maybe we must use CRT functions instead of console WIN32.
928     // different Windows/CRT versions also can work different ways.
929     // so the following code was not enabled:
930     if (cp == -1)
931     {
932       // we set CodePage only if stream is attached to terminal
933       // maybe we should set CodePage even if is not terminal?
934       #ifdef _WIN32
935       {
936         UINT ccp = GetConsoleOutputCP();
937         if (ccp != 0)
938         {
939           if (options.IsStdOutTerminal) stdout_cp = ccp;
940           if (options.IsStdErrTerminal) stderr_cp = ccp;
941         }
942       }
943       if (options.IsInTerminal)
944       {
945         UINT ccp = GetConsoleCP();
946         if (ccp != 0) stdin_cp = ccp;
947       }
948       #endif
949     }
950     */
951 
952     if (stdout_cp != -1) g_StdOut.CodePage = stdout_cp;
953     if (stderr_cp != -1) g_StdErr.CodePage = stderr_cp;
954     if (stdin_cp != -1) g_StdIn.CodePage = stdin_cp;
955   }
956   g_StdOut.ListPathSeparatorSlash = options.ListPathSeparatorSlash;
957   g_StdErr.ListPathSeparatorSlash = options.ListPathSeparatorSlash;
958 
959   unsigned percentsNameLevel = 1;
960   if (options.LogLevel == 0 || options.Number_for_Percents != options.Number_for_Out)
961     percentsNameLevel = 2;
962 
963   unsigned consoleWidth = 80;
964 
965   if (percentsStream)
966   {
967     #ifdef _WIN32
968 
969     #if !defined(UNDER_CE)
970     CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
971     if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo))
972       consoleWidth = (USHORT)consoleInfo.dwSize.X;
973     #endif
974 
975     #else
976 
977 #if !defined(__sun)
978     struct winsize w;
979     if (ioctl(0, TIOCGWINSZ, &w) == 0)
980       consoleWidth = w.ws_col;
981 #endif
982     #endif
983   }
984 
985   CREATE_CODECS_OBJECT
986 
987   codecs->CaseSensitive_Change = options.CaseSensitive_Change;
988   codecs->CaseSensitive = options.CaseSensitive;
989   ThrowException_if_Error(codecs->Load());
990   Codecs_AddHashArcHandler(codecs);
991 
992   #ifdef Z7_EXTERNAL_CODECS
993   {
994     g_ExternalCodecs_Ptr = &_externalCodecs;
995     UString s;
996     codecs->GetCodecsErrorMessage(s);
997     if (!s.IsEmpty())
998     {
999       CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
1000       so << endl << s << endl;
1001     }
1002   }
1003   #endif
1004 
1005   const bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
1006 
1007   if (codecs->Formats.Size() == 0 &&
1008         (isExtractGroupCommand
1009         || options.Command.CommandType == NCommandType::kList
1010         || options.Command.IsFromUpdateGroup()))
1011   {
1012     #ifdef Z7_EXTERNAL_CODECS
1013     if (!codecs->MainDll_ErrorPath.IsEmpty())
1014     {
1015       UString s ("Can't load module: ");
1016       s += fs2us(codecs->MainDll_ErrorPath);
1017       throw s;
1018     }
1019     #endif
1020     throw kNoFormats;
1021   }
1022 
1023   CObjectVector<COpenType> types;
1024   if (!ParseOpenTypes(*codecs, options.ArcType, types))
1025   {
1026     throw kUnsupportedArcTypeMessage;
1027   }
1028 
1029 
1030   CIntVector excludedFormats;
1031   FOR_VECTOR (k, options.ExcludedArcTypes)
1032   {
1033     CIntVector tempIndices;
1034     if (!codecs->FindFormatForArchiveType(options.ExcludedArcTypes[k], tempIndices)
1035         || tempIndices.Size() != 1)
1036       throw kUnsupportedArcTypeMessage;
1037 
1038 
1039 
1040     excludedFormats.AddToUniqueSorted(tempIndices[0]);
1041     // excludedFormats.Sort();
1042   }
1043 
1044   #ifdef Z7_EXTERNAL_CODECS
1045   if (isExtractGroupCommand
1046       || options.Command.IsFromUpdateGroup()
1047       || options.Command.CommandType == NCommandType::kHash
1048       || options.Command.CommandType == NCommandType::kBenchmark)
1049     ThrowException_if_Error(_externalCodecs.Load());
1050   #endif
1051 
1052   int retCode = NExitCode::kSuccess;
1053   HRESULT hresultMain = S_OK;
1054 
1055   // bool showStat = options.ShowTime;
1056 
1057   /*
1058   if (!options.EnableHeaders ||
1059       options.TechMode)
1060     showStat = false;
1061   */
1062 
1063 
1064   if (options.Command.CommandType == NCommandType::kInfo)
1065   {
1066     CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
1067     unsigned i;
1068 
1069     #ifdef Z7_EXTERNAL_CODECS
1070     so << endl << "Libs:" << endl;
1071     for (i = 0; i < codecs->Libs.Size(); i++)
1072     {
1073       PrintLibIndex(so, (int)i);
1074       const CCodecLib &lib = codecs->Libs[i];
1075       // if (lib.Version != 0)
1076       so << ": " << (lib.Version >> 16) << ".";
1077       PrintNumber(so, lib.Version & 0xffff, 2);
1078       so << " : " << lib.Path << endl;
1079     }
1080     #endif
1081 
1082     so << endl << "Formats:" << endl;
1083 
1084     const char * const kArcFlags = "KSNFMGOPBELHXCc+a+m+r+";
1085     const char * const kArcTimeFlags = "wudn";
1086     const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags);
1087     const unsigned kNumArcTimeFlags = (unsigned)strlen(kArcTimeFlags);
1088 
1089     for (i = 0; i < codecs->Formats.Size(); i++)
1090     {
1091       const CArcInfoEx &arc = codecs->Formats[i];
1092 
1093       #ifdef Z7_EXTERNAL_CODECS
1094       PrintLibIndex(so, arc.LibIndex);
1095       #else
1096       so << "   ";
1097       #endif
1098 
1099       so << (char)(arc.UpdateEnabled ? 'C' : ' ');
1100 
1101       {
1102         unsigned b;
1103         for (b = 0; b < kNumArcFlags; b++)
1104           so << (char)((arc.Flags & ((UInt32)1 << b)) != 0 ? kArcFlags[b] : '.');
1105         so << ' ';
1106       }
1107 
1108       if (arc.TimeFlags != 0)
1109       {
1110         unsigned b;
1111         for (b = 0; b < kNumArcTimeFlags; b++)
1112           so << (char)((arc.TimeFlags & ((UInt32)1 << b)) != 0 ? kArcTimeFlags[b] : '.');
1113         so << arc.Get_DefaultTimePrec();
1114         so << ' ';
1115       }
1116 
1117       so << ' ';
1118       PrintString(so, arc.Name, 8);
1119       so << ' ';
1120       UString s;
1121 
1122       FOR_VECTOR (t, arc.Exts)
1123       {
1124         if (t != 0)
1125           s.Add_Space();
1126         const CArcExtInfo &ext = arc.Exts[t];
1127         s += ext.Ext;
1128         if (!ext.AddExt.IsEmpty())
1129         {
1130           s += " (";
1131           s += ext.AddExt;
1132           s.Add_Char(')');
1133         }
1134       }
1135 
1136       PrintString(so, s, 13);
1137       so << ' ';
1138 
1139       if (arc.SignatureOffset != 0)
1140         so << "offset=" << arc.SignatureOffset << ' ';
1141 
1142       // so << "numSignatures = " << arc.Signatures.Size() << " ";
1143 
1144       FOR_VECTOR(si, arc.Signatures)
1145       {
1146         if (si != 0)
1147           so << "  ||  ";
1148 
1149         const CByteBuffer &sig = arc.Signatures[si];
1150 
1151         for (size_t j = 0; j < sig.Size(); j++)
1152         {
1153           if (j != 0)
1154             so << ' ';
1155           const unsigned b = sig.ConstData()[j];
1156           if (b > 0x20 && b < 0x80)
1157           {
1158             so << (char)b;
1159           }
1160           else
1161           {
1162             so << GET_HEX_CHAR_UPPER(b >> 4);
1163             so << GET_HEX_CHAR_UPPER(b & 15);
1164           }
1165         }
1166       }
1167       so << endl;
1168     }
1169 
1170     so << endl << "Codecs:" << endl; //  << "Lib          ID Name" << endl;
1171 
1172     for (i = 0; i < g_NumCodecs; i++)
1173     {
1174       const CCodecInfo &cod = *g_Codecs[i];
1175 
1176       PrintLibIndex(so, -1);
1177 
1178       if (cod.NumStreams == 1)
1179         so << ' ';
1180       else
1181         so << cod.NumStreams;
1182 
1183       so << (char)(cod.CreateEncoder ? 'E' : ' ');
1184       so << (char)(cod.CreateDecoder ? 'D' : ' ');
1185       so << (char)(cod.IsFilter      ? 'F' : ' ');
1186 
1187       so << ' ';
1188       PrintHexId(so, cod.Id);
1189       so << ' ' << cod.Name << endl;
1190     }
1191 
1192 
1193     #ifdef Z7_EXTERNAL_CODECS
1194 
1195     UInt32 numMethods;
1196     if (_externalCodecs.GetCodecs->GetNumMethods(&numMethods) == S_OK)
1197     for (UInt32 j = 0; j < numMethods; j++)
1198     {
1199       PrintLibIndex(so, codecs->GetCodec_LibIndex(j));
1200 
1201       UInt32 numStreams = codecs->GetCodec_NumStreams(j);
1202       if (numStreams == 1)
1203         so << ' ';
1204       else
1205         so << numStreams;
1206 
1207       so << (char)(codecs->GetCodec_EncoderIsAssigned(j) ? 'E' : ' ');
1208       so << (char)(codecs->GetCodec_DecoderIsAssigned(j) ? 'D' : ' ');
1209       {
1210         bool isFilter_Assigned;
1211         const bool isFilter = codecs->GetCodec_IsFilter(j, isFilter_Assigned);
1212         so << (char)(isFilter ? 'F' : isFilter_Assigned ? ' ' : '*');
1213       }
1214 
1215 
1216       so << ' ';
1217       UInt64 id;
1218       HRESULT res = codecs->GetCodec_Id(j, id);
1219       if (res != S_OK)
1220         id = (UInt64)(Int64)-1;
1221       PrintHexId(so, id);
1222       so << ' ' << codecs->GetCodec_Name(j) << endl;
1223     }
1224 
1225     #endif
1226 
1227 
1228     so << endl << "Hashers:" << endl; //  << " L Size       ID Name" << endl;
1229 
1230     for (i = 0; i < g_NumHashers; i++)
1231     {
1232       const CHasherInfo &codec = *g_Hashers[i];
1233       PrintLibIndex(so, -1);
1234       PrintUInt32(so, codec.DigestSize, 4);
1235       so << ' ';
1236       PrintHexId(so, codec.Id);
1237       so << ' ' << codec.Name << endl;
1238     }
1239 
1240     #ifdef Z7_EXTERNAL_CODECS
1241 
1242     numMethods = _externalCodecs.GetHashers->GetNumHashers();
1243     for (UInt32 j = 0; j < numMethods; j++)
1244     {
1245       PrintLibIndex(so, codecs->GetHasherLibIndex(j));
1246       PrintUInt32(so, codecs->GetHasherDigestSize(j), 4);
1247       so << ' ';
1248       PrintHexId(so, codecs->GetHasherId(j));
1249       so << ' ' << codecs->GetHasherName(j) << endl;
1250     }
1251 
1252     #endif
1253 
1254   }
1255   else if (options.Command.CommandType == NCommandType::kBenchmark)
1256   {
1257     CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
1258     hresultMain = BenchCon(EXTERNAL_CODECS_VARS_L
1259         options.Properties, options.NumIterations, (FILE *)so);
1260     if (hresultMain == S_FALSE)
1261     {
1262       so << endl;
1263       if (g_ErrStream)
1264         *g_ErrStream << "\nDecoding ERROR\n";
1265       retCode = NExitCode::kFatalError;
1266       hresultMain = S_OK;
1267     }
1268   }
1269   else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)
1270   {
1271     UStringVector ArchivePathsSorted;
1272     UStringVector ArchivePathsFullSorted;
1273 
1274     if (options.StdInMode)
1275     {
1276       ArchivePathsSorted.Add(options.ArcName_for_StdInMode);
1277       ArchivePathsFullSorted.Add(options.ArcName_for_StdInMode);
1278     }
1279     else
1280     {
1281       CExtractScanConsole scan;
1282 
1283       scan.Init(options.EnableHeaders ? g_StdStream : NULL,
1284           g_ErrStream, percentsStream,
1285           options.DisablePercents);
1286       scan.SetWindowWidth(consoleWidth);
1287 
1288       if (g_StdStream && options.EnableHeaders)
1289         *g_StdStream << "Scanning the drive for archives:" << endl;
1290 
1291       CDirItemsStat st;
1292 
1293       scan.StartScanning();
1294 
1295       hresultMain = EnumerateDirItemsAndSort(
1296           options.arcCensor,
1297           NWildcard::k_RelatPath,
1298           UString(), // addPathPrefix
1299           ArchivePathsSorted,
1300           ArchivePathsFullSorted,
1301           st,
1302           &scan);
1303 
1304       scan.CloseScanning();
1305 
1306       if (hresultMain == S_OK)
1307       {
1308         if (options.EnableHeaders)
1309           scan.PrintStat(st);
1310       }
1311       else
1312       {
1313         /*
1314         if (res != E_ABORT)
1315         {
1316           throw CSystemException(res);
1317           // errorInfo.Message = "Scanning error";
1318         }
1319         return res;
1320         */
1321       }
1322     }
1323 
1324     if (hresultMain == S_OK) {
1325     if (isExtractGroupCommand)
1326     {
1327       CExtractCallbackConsole *ecs = new CExtractCallbackConsole;
1328       CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
1329 
1330       #ifndef Z7_NO_CRYPTO
1331       ecs->PasswordIsDefined = options.PasswordEnabled;
1332       ecs->Password = options.Password;
1333       #endif
1334 
1335       ecs->Init(g_StdStream, g_ErrStream, percentsStream, options.DisablePercents);
1336       ecs->MultiArcMode = (ArchivePathsSorted.Size() > 1);
1337 
1338       ecs->LogLevel = options.LogLevel;
1339       ecs->PercentsNameLevel = percentsNameLevel;
1340 
1341       if (percentsStream)
1342         ecs->SetWindowWidth(consoleWidth);
1343 
1344       /*
1345       COpenCallbackConsole openCallback;
1346       openCallback.Init(g_StdStream, g_ErrStream);
1347 
1348       #ifndef Z7_NO_CRYPTO
1349       openCallback.PasswordIsDefined = options.PasswordEnabled;
1350       openCallback.Password = options.Password;
1351       #endif
1352       */
1353 
1354       CExtractOptions eo;
1355       (CExtractOptionsBase &)eo = options.ExtractOptions;
1356 
1357       eo.StdInMode = options.StdInMode;
1358       eo.StdOutMode = options.StdOutMode;
1359       eo.YesToAll = options.YesToAll;
1360       eo.TestMode = options.Command.IsTestCommand();
1361 
1362       #ifndef Z7_SFX
1363       eo.Properties = options.Properties;
1364       #endif
1365 
1366       UString errorMessage;
1367       CDecompressStat stat;
1368       CHashBundle hb;
1369       IHashCalc *hashCalc = NULL;
1370 
1371       if (!options.HashMethods.IsEmpty())
1372       {
1373         hashCalc = &hb;
1374         ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS_L options.HashMethods));
1375         // hb.Init();
1376       }
1377 
1378       hresultMain = Extract(
1379           // EXTERNAL_CODECS_VARS_L
1380           codecs,
1381           types,
1382           excludedFormats,
1383           ArchivePathsSorted,
1384           ArchivePathsFullSorted,
1385           options.Censor.Pairs.Front().Head,
1386           eo,
1387           ecs, ecs, ecs,
1388           hashCalc, errorMessage, stat);
1389 
1390       ecs->ClosePercents();
1391 
1392       if (!errorMessage.IsEmpty())
1393       {
1394         if (g_ErrStream)
1395           *g_ErrStream << endl << "ERROR:" << endl << errorMessage << endl;
1396         if (hresultMain == S_OK)
1397           hresultMain = E_FAIL;
1398       }
1399 
1400       CStdOutStream *so = g_StdStream;
1401 
1402       bool isError = false;
1403 
1404       if (so)
1405       {
1406         *so << endl;
1407 
1408         if (ecs->NumTryArcs > 1)
1409         {
1410           *so << "Archives: " << ecs->NumTryArcs << endl;
1411           *so << "OK archives: " << ecs->NumOkArcs << endl;
1412         }
1413       }
1414 
1415       if (ecs->NumCantOpenArcs != 0)
1416       {
1417         isError = true;
1418         if (so)
1419           *so << "Can't open as archive: " << ecs->NumCantOpenArcs << endl;
1420       }
1421 
1422       if (ecs->NumArcsWithError != 0)
1423       {
1424         isError = true;
1425         if (so)
1426           *so << "Archives with Errors: " << ecs->NumArcsWithError << endl;
1427       }
1428 
1429       if (so)
1430       {
1431         if (ecs->NumArcsWithWarnings != 0)
1432           *so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;
1433 
1434         if (ecs->NumOpenArcWarnings != 0)
1435         {
1436           *so << endl;
1437           if (ecs->NumOpenArcWarnings != 0)
1438             *so << "Warnings: " << ecs->NumOpenArcWarnings << endl;
1439         }
1440       }
1441 
1442       if (ecs->NumOpenArcErrors != 0)
1443       {
1444         isError = true;
1445         if (so)
1446         {
1447           *so << endl;
1448           if (ecs->NumOpenArcErrors != 0)
1449             *so << "Open Errors: " << ecs->NumOpenArcErrors << endl;
1450         }
1451       }
1452 
1453       if (isError)
1454         retCode = NExitCode::kFatalError;
1455 
1456       if (so) {
1457       if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0)
1458       {
1459         // if (ecs->NumArchives > 1)
1460         {
1461           *so << endl;
1462           if (ecs->NumFileErrors != 0)
1463             *so << "Sub items Errors: " << ecs->NumFileErrors << endl;
1464         }
1465       }
1466       else if (hresultMain == S_OK)
1467       {
1468         if (stat.NumFolders != 0)
1469           *so << "Folders: " << stat.NumFolders << endl;
1470         if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0)
1471           *so << "Files: " << stat.NumFiles << endl;
1472         if (stat.NumAltStreams != 0)
1473         {
1474           *so << "Alternate Streams: " << stat.NumAltStreams << endl;
1475           *so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl;
1476         }
1477 
1478         *so
1479           << "Size:       " << stat.UnpackSize << endl
1480           << "Compressed: " << stat.PackSize << endl;
1481         if (hashCalc)
1482         {
1483           *so << endl;
1484           PrintHashStat(*so, hb);
1485         }
1486       }
1487       } // if (so)
1488     }
1489     else // if_(!isExtractGroupCommand)
1490     {
1491       UInt64 numErrors = 0;
1492       UInt64 numWarnings = 0;
1493 
1494       // options.ExtractNtOptions.StoreAltStreams = true, if -sns[-] is not definmed
1495 
1496       CListOptions lo;
1497       lo.ExcludeDirItems = options.Censor.ExcludeDirItems;
1498       lo.ExcludeFileItems = options.Censor.ExcludeFileItems;
1499       lo.DisablePercents = options.DisablePercents;
1500 
1501       hresultMain = ListArchives(
1502           lo,
1503           codecs,
1504           types,
1505           excludedFormats,
1506           options.StdInMode,
1507           ArchivePathsSorted,
1508           ArchivePathsFullSorted,
1509           options.ExtractOptions.NtOptions.AltStreams.Val,
1510           options.AltStreams.Val, // we don't want to show AltStreams by default
1511           options.Censor.Pairs.Front().Head,
1512           options.EnableHeaders,
1513           options.TechMode,
1514           #ifndef Z7_NO_CRYPTO
1515           options.PasswordEnabled,
1516           options.Password,
1517           #endif
1518           &options.Properties,
1519           numErrors, numWarnings);
1520 
1521       if (options.EnableHeaders)
1522         if (numWarnings > 0)
1523           g_StdOut << endl << "Warnings: " << numWarnings << endl;
1524 
1525       if (numErrors > 0)
1526       {
1527         if (options.EnableHeaders)
1528           g_StdOut << endl << "Errors: " << numErrors << endl;
1529         retCode = NExitCode::kFatalError;
1530       }
1531     } // if_(isExtractGroupCommand)
1532     } // if_(hresultMain == S_OK)
1533   }
1534   else if (options.Command.IsFromUpdateGroup())
1535   {
1536    #ifdef Z7_EXTRACT_ONLY
1537     throw "update commands are not implemented";
1538    #else
1539     CUpdateOptions &uo = options.UpdateOptions;
1540     if (uo.SfxMode && uo.SfxModule.IsEmpty())
1541       uo.SfxModule = kDefaultSfxModule;
1542 
1543     COpenCallbackConsole openCallback;
1544     openCallback.Init(g_StdStream, g_ErrStream, percentsStream, options.DisablePercents);
1545 
1546     #ifndef Z7_NO_CRYPTO
1547     bool passwordIsDefined =
1548         (options.PasswordEnabled && !options.Password.IsEmpty());
1549     openCallback.PasswordIsDefined = passwordIsDefined;
1550     openCallback.Password = options.Password;
1551     #endif
1552 
1553     CUpdateCallbackConsole callback;
1554     callback.LogLevel = options.LogLevel;
1555     callback.PercentsNameLevel = percentsNameLevel;
1556 
1557     if (percentsStream)
1558       callback.SetWindowWidth(consoleWidth);
1559 
1560     #ifndef Z7_NO_CRYPTO
1561     callback.PasswordIsDefined = passwordIsDefined;
1562     callback.AskPassword = (options.PasswordEnabled && options.Password.IsEmpty());
1563     callback.Password = options.Password;
1564     #endif
1565 
1566     callback.StdOutMode = uo.StdOutMode;
1567     callback.Init(
1568       // NULL,
1569       g_StdStream, g_ErrStream, percentsStream, options.DisablePercents);
1570 
1571     CUpdateErrorInfo errorInfo;
1572 
1573     /*
1574     if (!uo.Init(codecs, types, options.ArchiveName))
1575       throw kUnsupportedUpdateArcType;
1576     */
1577     hresultMain = UpdateArchive(codecs,
1578         types,
1579         options.ArchiveName,
1580         options.Censor,
1581         uo,
1582         errorInfo, &openCallback, &callback, true);
1583 
1584     callback.ClosePercents2();
1585 
1586     CStdOutStream *se = g_StdStream;
1587     if (!se)
1588       se = g_ErrStream;
1589 
1590     retCode = WarningsCheck(hresultMain, callback, errorInfo,
1591         g_StdStream, se,
1592         true // options.EnableHeaders
1593         );
1594    #endif
1595   }
1596   else if (options.Command.CommandType == NCommandType::kHash)
1597   {
1598     const CHashOptions &uo = options.HashOptions;
1599 
1600     CHashCallbackConsole callback;
1601     if (percentsStream)
1602       callback.SetWindowWidth(consoleWidth);
1603 
1604     callback.Init(g_StdStream, g_ErrStream, percentsStream, options.DisablePercents);
1605     callback.PrintHeaders = options.EnableHeaders;
1606     callback.PrintFields = options.ListFields;
1607 
1608     AString errorInfoString;
1609     hresultMain = HashCalc(EXTERNAL_CODECS_VARS_L
1610         options.Censor, uo,
1611         errorInfoString, &callback);
1612     CUpdateErrorInfo errorInfo;
1613     errorInfo.Message = errorInfoString;
1614     CStdOutStream *se = g_StdStream;
1615     if (!se)
1616       se = g_ErrStream;
1617     retCode = WarningsCheck(hresultMain, callback, errorInfo, g_StdStream, se, options.EnableHeaders);
1618   }
1619   else
1620     ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);
1621 
1622   if (options.ShowTime && g_StdStream)
1623     PrintStat(
1624       #ifndef _WIN32
1625         startTime
1626       #endif
1627     );
1628 
1629   ThrowException_if_Error(hresultMain);
1630 
1631   return retCode;
1632 }
1633