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