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