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