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