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 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 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 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 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 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 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 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 239 static inline char GetHex(unsigned val) 240 { 241 return (char)((val < 10) ? ('0' + val) : ('A' + (val - 10))); 242 } 243 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 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 336 static void ThrowException_if_Error(HRESULT res) 337 { 338 if (res != S_OK) 339 throw CSystemException(res); 340 } 341 342 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 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 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 396 static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } 397 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 466 static void PrintHexId(CStdOutStream &so, UInt64 id) 467 { 468 char s[32]; 469 ConvertUInt64ToHex(id, s); 470 PrintStringRight(so, s, 8); 471 } 472 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