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