1 // Main.cpp 2 3 #include "StdAfx.h" 4 5 #include <Psapi.h> 6 7 #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) 8 #include "../../../../C/Alloc.h" 9 #endif 10 11 #include "../../../Common/MyInitGuid.h" 12 13 #include "../../../Common/CommandLineParser.h" 14 #include "../../../Common/IntToString.h" 15 #include "../../../Common/MyException.h" 16 #include "../../../Common/StringConvert.h" 17 #include "../../../Common/StringToInt.h" 18 19 #include "../../../Windows/ErrorMsg.h" 20 #ifdef _WIN32 21 #include "../../../Windows/MemoryLock.h" 22 #endif 23 24 #ifndef _7ZIP_ST 25 #include "../../../Windows/Synchronization.h" 26 #endif 27 28 #include "../../../Windows/TimeUtils.h" 29 30 #include "../Common/ArchiveCommandLine.h" 31 #include "../Common/ExitCode.h" 32 #include "../Common/Extract.h" 33 #ifdef EXTERNAL_CODECS 34 #include "../Common/LoadCodecs.h" 35 #endif 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 extern CStdOutStream *g_StdStream; 60 61 static const char *kCopyrightString = "\n7-Zip" 62 #ifndef EXTERNAL_CODECS 63 #ifdef PROG_VARIANT_R 64 " (r)" 65 #else 66 " (a)" 67 #endif 68 #endif 69 70 #ifdef _WIN64 71 " [64]" 72 #endif 73 74 " " MY_VERSION_COPYRIGHT_DATE "\n"; 75 76 static const char *kHelpString = 77 "\nUsage: 7z" 78 #ifndef EXTERNAL_CODECS 79 #ifdef PROG_VARIANT_R 80 "r" 81 #else 82 "a" 83 #endif 84 #endif 85 " <command> [<switches>...] <archive_name> [<file_names>...]\n" 86 " [<@listfiles...>]\n" 87 "\n" 88 "<Commands>\n" 89 " a : Add files to archive\n" 90 " b : Benchmark\n" 91 " d : Delete files from archive\n" 92 " e : Extract files from archive (without using directory names)\n" 93 " h : Calculate hash values for files\n" 94 " l : List contents of archive\n" 95 // " l[a|t][f] : List contents of archive\n" 96 // " a - with Additional fields\n" 97 // " t - with all fields\n" 98 // " f - with Full pathnames\n" 99 " rn : Rename files in archive\n" 100 " t : Test integrity of archive\n" 101 " u : Update files to archive\n" 102 " x : eXtract files with full paths\n" 103 "<Switches>\n" 104 " -- : Stop switches parsing\n" 105 " -ai[r[-|0]]{@listfile|!wildcard} : Include archives\n" 106 " -ax[r[-|0]]{@listfile|!wildcard} : eXclude archives\n" 107 " -bd : Disable percentage indicator\n" 108 " -i[r[-|0]]{@listfile|!wildcard} : Include filenames\n" 109 " -m{Parameters} : set compression Method\n" 110 " -o{Directory} : set Output directory\n" 111 #ifndef _NO_CRYPTO 112 " -p{Password} : set Password\n" 113 #endif 114 " -r[-|0] : Recurse subdirectories\n" 115 " -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files\n" 116 " -sfx[{name}] : Create SFX archive\n" 117 " -si[{name}] : read data from stdin\n" 118 " -slt : show technical information for l (List) command\n" 119 " -so : write data to stdout\n" 120 " -ssc[-] : set sensitive case mode\n" 121 " -ssw : compress shared files\n" 122 " -t{Type} : Set type of archive\n" 123 " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName] : Update options\n" 124 " -v{Size}[b|k|m|g] : Create volumes\n" 125 " -w[{path}] : assign Work directory. Empty path means a temporary directory\n" 126 " -x[r[-|0]]]{@listfile|!wildcard} : eXclude filenames\n" 127 " -y : assume Yes on all queries\n"; 128 129 // --------------------------- 130 // exception messages 131 132 static const char *kEverythingIsOk = "Everything is Ok"; 133 static const char *kUserErrorMessage = "Incorrect command line"; 134 static const char *kNoFormats = "7-Zip cannot find the code that works with archives."; 135 static const char *kUnsupportedArcTypeMessage = "Unsupported archive type"; 136 // static const char *kUnsupportedUpdateArcType = "Can't create archive for that type"; 137 138 static CFSTR kDefaultSfxModule = FTEXT("7zCon.sfx"); 139 140 static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code) 141 { 142 s << endl << "Error: " << message << endl; 143 throw code; 144 } 145 146 #ifndef _WIN32 147 static void GetArguments(int numArgs, const char *args[], UStringVector &parts) 148 { 149 parts.Clear(); 150 for (int i = 0; i < numArgs; i++) 151 { 152 UString s = MultiByteToUnicodeString(args[i]); 153 parts.Add(s); 154 } 155 } 156 #endif 157 158 static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp) 159 { 160 s << kCopyrightString; 161 // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n"; 162 if (needHelp) 163 s << kHelpString; 164 } 165 166 #ifdef EXTERNAL_CODECS 167 168 static void PrintString(CStdOutStream &stdStream, const AString &s, int size) 169 { 170 int len = s.Len(); 171 for (int i = len; i < size; i++) 172 stdStream << ' '; 173 stdStream << s; 174 } 175 176 static void PrintUInt32(CStdOutStream &stdStream, UInt32 val, int size) 177 { 178 char s[16]; 179 ConvertUInt32ToString(val, s); 180 PrintString(stdStream, s, size); 181 } 182 183 static void PrintLibIndex(CStdOutStream &stdStream, int libIndex) 184 { 185 if (libIndex >= 0) 186 PrintUInt32(stdStream, libIndex, 2); 187 else 188 stdStream << " "; 189 stdStream << ' '; 190 } 191 192 #endif 193 194 static void PrintString(CStdOutStream &stdStream, const UString &s, int size) 195 { 196 int len = s.Len(); 197 stdStream << s; 198 for (int i = len; i < size; i++) 199 stdStream << ' '; 200 } 201 202 static inline char GetHex(unsigned val) 203 { 204 return (char)((val < 10) ? ('0' + val) : ('A' + (val - 10))); 205 } 206 207 static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback, 208 const CErrorInfo &errorInfo, CStdOutStream &stdStream) 209 { 210 int exitCode = NExitCode::kSuccess; 211 212 if (callback.CantFindFiles.Size() > 0) 213 { 214 stdStream << endl; 215 stdStream << "WARNINGS for files:" << endl << endl; 216 unsigned numErrors = callback.CantFindFiles.Size(); 217 for (unsigned i = 0; i < numErrors; i++) 218 { 219 stdStream << callback.CantFindFiles[i] << " : "; 220 stdStream << NError::MyFormatMessage(callback.CantFindCodes[i]) << endl; 221 } 222 stdStream << "----------------" << endl; 223 stdStream << "WARNING: Cannot find " << numErrors << " file"; 224 if (numErrors > 1) 225 stdStream << "s"; 226 stdStream << endl; 227 exitCode = NExitCode::kWarning; 228 } 229 230 if (result != S_OK) 231 { 232 UString message; 233 if (!errorInfo.Message.IsEmpty()) 234 { 235 message += errorInfo.Message; 236 message += L"\n"; 237 } 238 if (!errorInfo.FileName.IsEmpty()) 239 { 240 message += fs2us(errorInfo.FileName); 241 message += L"\n"; 242 } 243 if (!errorInfo.FileName2.IsEmpty()) 244 { 245 message += fs2us(errorInfo.FileName2); 246 message += L"\n"; 247 } 248 if (errorInfo.SystemError != 0) 249 { 250 message += NError::MyFormatMessage(errorInfo.SystemError); 251 message += L"\n"; 252 } 253 if (!message.IsEmpty()) 254 stdStream << L"\nError:\n" << message; 255 256 // we will work with (result) later 257 // throw CSystemException(result); 258 return NExitCode::kFatalError; 259 } 260 261 unsigned numErrors = callback.FailedFiles.Size(); 262 if (numErrors == 0) 263 { 264 if (callback.CantFindFiles.Size() == 0) 265 stdStream << kEverythingIsOk << endl; 266 } 267 else 268 { 269 stdStream << endl; 270 stdStream << "WARNINGS for files:" << endl << endl; 271 for (unsigned i = 0; i < numErrors; i++) 272 { 273 stdStream << callback.FailedFiles[i] << " : "; 274 stdStream << NError::MyFormatMessage(callback.FailedCodes[i]) << endl; 275 } 276 stdStream << "----------------" << endl; 277 stdStream << "WARNING: Cannot open " << numErrors << " file"; 278 if (numErrors > 1) 279 stdStream << "s"; 280 stdStream << endl; 281 exitCode = NExitCode::kWarning; 282 } 283 return exitCode; 284 } 285 286 static void ThrowException_if_Error(HRESULT res) 287 { 288 if (res != S_OK) 289 throw CSystemException(res); 290 } 291 292 293 static void PrintNum(UInt64 val, unsigned numDigits, char c = ' ') 294 { 295 char temp[64]; 296 char *p = temp + 32; 297 ConvertUInt64ToString(val, p); 298 unsigned len = MyStringLen(p); 299 for (; len < numDigits; len++) 300 *--p = c; 301 *g_StdStream << p; 302 } 303 304 static void PrintTime(const char *s, UInt64 val, UInt64 total) 305 { 306 *g_StdStream << endl << s << " Time ="; 307 const UInt32 kFreq = 10000000; 308 UInt64 sec = val / kFreq; 309 PrintNum(sec, 6); 310 *g_StdStream << '.'; 311 UInt32 ms = (UInt32)(val - (sec * kFreq)) / (kFreq / 1000); 312 PrintNum(ms, 3, '0'); 313 314 while (val > ((UInt64)1 << 56)) 315 { 316 val >>= 1; 317 total >>= 1; 318 } 319 320 UInt64 percent = 0; 321 if (total != 0) 322 percent = val * 100 / total; 323 *g_StdStream << " ="; 324 PrintNum(percent, 5); 325 *g_StdStream << '%'; 326 } 327 328 #ifndef UNDER_CE 329 330 #define SHIFT_SIZE_VALUE(x, num) (((x) + (1 << (num)) - 1) >> (num)) 331 332 static void PrintMemUsage(const char *s, UInt64 val) 333 { 334 *g_StdStream << " " << s << " Memory ="; 335 PrintNum(SHIFT_SIZE_VALUE(val, 20), 7); 336 *g_StdStream << " MB"; 337 } 338 339 EXTERN_C_BEGIN 340 typedef BOOL (WINAPI *Func_GetProcessMemoryInfo)(HANDLE Process, 341 PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb); 342 EXTERN_C_END 343 344 #endif 345 346 static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } 347 348 static void PrintStat() 349 { 350 FILETIME creationTimeFT, exitTimeFT, kernelTimeFT, userTimeFT; 351 if (! 352 #ifdef UNDER_CE 353 ::GetThreadTimes(::GetCurrentThread() 354 #else 355 // NT 3.5 356 ::GetProcessTimes(::GetCurrentProcess() 357 #endif 358 , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT)) 359 return; 360 FILETIME curTimeFT; 361 NTime::GetCurUtcFileTime(curTimeFT); 362 363 #ifndef UNDER_CE 364 365 PROCESS_MEMORY_COUNTERS m; 366 memset(&m, 0, sizeof(m)); 367 BOOL memDefined = FALSE; 368 { 369 /* NT 4.0: GetProcessMemoryInfo() in Psapi.dll 370 Win7: new function K32GetProcessMemoryInfo() in kernel32.dll 371 It's faster to call kernel32.dll code than Psapi.dll code 372 GetProcessMemoryInfo() requires Psapi.lib 373 Psapi.lib in SDK7+ can link to K32GetProcessMemoryInfo in kernel32.dll 374 The program with K32GetProcessMemoryInfo will not work on systems before Win7 375 // memDefined = GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m)); 376 */ 377 378 Func_GetProcessMemoryInfo my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo) 379 ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "K32GetProcessMemoryInfo"); 380 if (!my_GetProcessMemoryInfo) 381 { 382 HMODULE lib = LoadLibraryW(L"Psapi.dll"); 383 if (lib) 384 my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo)::GetProcAddress(lib, "GetProcessMemoryInfo"); 385 } 386 if (my_GetProcessMemoryInfo) 387 memDefined = my_GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m)); 388 // FreeLibrary(lib); 389 } 390 391 #endif 392 393 UInt64 curTime = GetTime64(curTimeFT); 394 UInt64 creationTime = GetTime64(creationTimeFT); 395 UInt64 kernelTime = GetTime64(kernelTimeFT); 396 UInt64 userTime = GetTime64(userTimeFT); 397 398 UInt64 totalTime = curTime - creationTime; 399 400 PrintTime("Kernel ", kernelTime, totalTime); 401 PrintTime("User ", userTime, totalTime); 402 403 PrintTime("Process", kernelTime + userTime, totalTime); 404 #ifndef UNDER_CE 405 if (memDefined) PrintMemUsage("Virtual ", m.PeakPagefileUsage); 406 #endif 407 408 PrintTime("Global ", totalTime, totalTime); 409 #ifndef UNDER_CE 410 if (memDefined) PrintMemUsage("Physical", m.PeakWorkingSetSize); 411 #endif 412 413 *g_StdStream << endl; 414 } 415 416 int Main2( 417 #ifndef _WIN32 418 int numArgs, const char *args[] 419 #endif 420 ) 421 { 422 #if defined(_WIN32) && !defined(UNDER_CE) 423 SetFileApisToOEM(); 424 #endif 425 426 UStringVector commandStrings; 427 #ifdef _WIN32 428 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); 429 #else 430 GetArguments(numArgs, args, commandStrings); 431 #endif 432 433 if (commandStrings.Size() == 1) 434 { 435 ShowCopyrightAndHelp(g_StdOut, true); 436 return 0; 437 } 438 439 commandStrings.Delete(0); 440 441 CArcCmdLineOptions options; 442 443 CArcCmdLineParser parser; 444 445 parser.Parse1(commandStrings, options); 446 447 if (options.HelpMode) 448 { 449 ShowCopyrightAndHelp(g_StdOut, true); 450 return 0; 451 } 452 453 #if defined(_WIN32) && !defined(UNDER_CE) 454 NSecurity::EnablePrivilege_SymLink(); 455 #endif 456 #ifdef _7ZIP_LARGE_PAGES 457 if (options.LargePages) 458 { 459 SetLargePageSize(); 460 #if defined(_WIN32) && !defined(UNDER_CE) 461 NSecurity::EnablePrivilege_LockMemory(); 462 #endif 463 } 464 #endif 465 466 CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut; 467 g_StdStream = &stdStream; 468 469 if (options.EnableHeaders) 470 ShowCopyrightAndHelp(stdStream, false); 471 472 parser.Parse2(options); 473 474 CCodecs *codecs = new CCodecs; 475 #ifdef EXTERNAL_CODECS 476 CExternalCodecs __externalCodecs; 477 __externalCodecs.GetCodecs = codecs; 478 __externalCodecs.GetHashers = codecs; 479 #else 480 CMyComPtr<IUnknown> compressCodecsInfo = codecs; 481 #endif 482 codecs->CaseSensitiveChange = options.CaseSensitiveChange; 483 codecs->CaseSensitive = options.CaseSensitive; 484 ThrowException_if_Error(codecs->Load()); 485 486 bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); 487 488 if (codecs->Formats.Size() == 0 && 489 (isExtractGroupCommand 490 || options.Command.CommandType == NCommandType::kList 491 || options.Command.IsFromUpdateGroup())) 492 throw kNoFormats; 493 494 CObjectVector<COpenType> types; 495 if (!ParseOpenTypes(*codecs, options.ArcType, types)) 496 throw kUnsupportedArcTypeMessage; 497 498 CIntVector excludedFormats; 499 FOR_VECTOR (k, options.ExcludedArcTypes) 500 { 501 CIntVector tempIndices; 502 if (!codecs->FindFormatForArchiveType(options.ExcludedArcTypes[k], tempIndices) 503 || tempIndices.Size() != 1) 504 throw kUnsupportedArcTypeMessage; 505 excludedFormats.AddToUniqueSorted(tempIndices[0]); 506 // excludedFormats.Sort(); 507 } 508 509 510 #ifdef EXTERNAL_CODECS 511 if (isExtractGroupCommand 512 || options.Command.CommandType == NCommandType::kHash 513 || options.Command.CommandType == NCommandType::kBenchmark) 514 ThrowException_if_Error(__externalCodecs.LoadCodecs()); 515 #endif 516 517 int retCode = NExitCode::kSuccess; 518 HRESULT hresultMain = S_OK; 519 520 bool showStat = true; 521 if (!options.EnableHeaders || 522 options.TechMode) 523 showStat = false; 524 525 526 if (options.Command.CommandType == NCommandType::kInfo) 527 { 528 unsigned i; 529 530 #ifdef EXTERNAL_CODECS 531 stdStream << endl << "Libs:" << endl; 532 for (i = 0; i < codecs->Libs.Size(); i++) 533 { 534 PrintLibIndex(stdStream, i); 535 stdStream << ' ' << codecs->Libs[i].Path << endl; 536 } 537 #endif 538 539 stdStream << endl << "Formats:" << endl; 540 541 const char *kArcFlags = "KSNFMGOPBELH"; 542 const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags); 543 544 for (i = 0; i < codecs->Formats.Size(); i++) 545 { 546 const CArcInfoEx &arc = codecs->Formats[i]; 547 #ifdef EXTERNAL_CODECS 548 PrintLibIndex(stdStream, arc.LibIndex); 549 #else 550 stdStream << " "; 551 #endif 552 stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); 553 for (unsigned b = 0; b < kNumArcFlags; b++) 554 { 555 stdStream << (char) 556 ((arc.Flags & ((UInt32)1 << b)) != 0 ? kArcFlags[b] : ' '); 557 } 558 559 stdStream << ' '; 560 PrintString(stdStream, arc.Name, 8); 561 stdStream << ' '; 562 UString s; 563 FOR_VECTOR (t, arc.Exts) 564 { 565 if (t != 0) 566 s += L' '; 567 const CArcExtInfo &ext = arc.Exts[t]; 568 s += ext.Ext; 569 if (!ext.AddExt.IsEmpty()) 570 { 571 s += L" ("; 572 s += ext.AddExt; 573 s += L')'; 574 } 575 } 576 PrintString(stdStream, s, 13); 577 stdStream << ' '; 578 if (arc.SignatureOffset != 0) 579 stdStream << "offset=" << arc.SignatureOffset << ' '; 580 581 FOR_VECTOR(si, arc.Signatures) 582 { 583 if (si != 0) 584 stdStream << " || "; 585 586 const CByteBuffer &sig = arc.Signatures[si]; 587 588 for (size_t j = 0; j < sig.Size(); j++) 589 { 590 if (j != 0) 591 stdStream << ' '; 592 Byte b = sig[j]; 593 if (b > 0x20 && b < 0x80) 594 { 595 stdStream << (char)b; 596 } 597 else 598 { 599 stdStream << GetHex((b >> 4) & 0xF); 600 stdStream << GetHex(b & 0xF); 601 } 602 } 603 } 604 stdStream << endl; 605 } 606 607 #ifdef EXTERNAL_CODECS 608 609 stdStream << endl << "Codecs:" << endl << "Lib ID Name" << endl; 610 UInt32 numMethods; 611 if (codecs->GetNumberOfMethods(&numMethods) == S_OK) 612 for (UInt32 j = 0; j < numMethods; j++) 613 { 614 PrintLibIndex(stdStream, codecs->GetCodecLibIndex(j)); 615 stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' '); 616 UInt64 id; 617 stdStream << " "; 618 HRESULT res = codecs->GetCodecId(j, id); 619 if (res != S_OK) 620 id = (UInt64)(Int64)-1; 621 char s[32]; 622 ConvertUInt64ToHex(id, s); 623 PrintString(stdStream, s, 8); 624 stdStream << " " << codecs->GetCodecName(j) << endl; 625 } 626 627 stdStream << endl << "Hashers:" << endl << " L Size ID Name" << endl; 628 numMethods = codecs->GetNumHashers(); 629 for (UInt32 j = 0; j < numMethods; j++) 630 { 631 PrintLibIndex(stdStream, codecs->GetHasherLibIndex(j)); 632 PrintUInt32(stdStream, codecs->GetHasherDigestSize(j), 4); 633 stdStream << ' '; 634 char s[32]; 635 ConvertUInt64ToHex(codecs->GetHasherId(j), s); 636 PrintString(stdStream, s, 6); 637 stdStream << " " << codecs->GetHasherName(j) << endl; 638 } 639 640 #endif 641 642 } 643 else if (options.Command.CommandType == NCommandType::kBenchmark) 644 { 645 hresultMain = BenchCon(EXTERNAL_CODECS_VARS 646 options.Properties, options.NumIterations, (FILE *)stdStream); 647 if (hresultMain == S_FALSE) 648 { 649 stdStream << "\nDecoding Error\n"; 650 retCode = NExitCode::kFatalError; 651 hresultMain = S_OK; 652 } 653 } 654 else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) 655 { 656 if (isExtractGroupCommand) 657 { 658 CExtractCallbackConsole *ecs = new CExtractCallbackConsole; 659 CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; 660 661 ecs->OutStream = &stdStream; 662 663 #ifndef _NO_CRYPTO 664 ecs->PasswordIsDefined = options.PasswordEnabled; 665 ecs->Password = options.Password; 666 #endif 667 668 ecs->Init(); 669 670 COpenCallbackConsole openCallback; 671 openCallback.OutStream = &stdStream; 672 673 #ifndef _NO_CRYPTO 674 openCallback.PasswordIsDefined = options.PasswordEnabled; 675 openCallback.Password = options.Password; 676 #endif 677 678 CExtractOptions eo; 679 (CExtractOptionsBase &)eo = options.ExtractOptions; 680 eo.StdInMode = options.StdInMode; 681 eo.StdOutMode = options.StdOutMode; 682 eo.YesToAll = options.YesToAll; 683 eo.TestMode = options.Command.IsTestCommand(); 684 685 #ifndef _SFX 686 eo.Properties = options.Properties; 687 #endif 688 689 UString errorMessage; 690 CDecompressStat stat; 691 CHashBundle hb; 692 IHashCalc *hashCalc = NULL; 693 694 if (!options.HashMethods.IsEmpty()) 695 { 696 hashCalc = &hb; 697 ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS options.HashMethods)); 698 hb.Init(); 699 } 700 hresultMain = Extract( 701 codecs, 702 types, 703 excludedFormats, 704 options.ArchivePathsSorted, 705 options.ArchivePathsFullSorted, 706 options.Censor.Pairs.Front().Head, 707 eo, &openCallback, ecs, hashCalc, errorMessage, stat); 708 if (!errorMessage.IsEmpty()) 709 { 710 stdStream << endl << "Error: " << errorMessage; 711 if (hresultMain == S_OK) 712 hresultMain = E_FAIL; 713 } 714 715 stdStream << endl; 716 717 if (ecs->NumTryArcs > 1) 718 { 719 stdStream << "Archives: " << ecs->NumTryArcs << endl; 720 stdStream << "OK archives: " << ecs->NumOkArcs << endl; 721 } 722 bool isError = false; 723 if (ecs->NumCantOpenArcs != 0) 724 { 725 isError = true; 726 stdStream << "Can't open as archive: " << ecs->NumCantOpenArcs << endl; 727 } 728 if (ecs->NumArcsWithError != 0) 729 { 730 isError = true; 731 stdStream << "Archives with Errors: " << ecs->NumArcsWithError << endl; 732 } 733 if (ecs->NumArcsWithWarnings != 0) 734 stdStream << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl; 735 736 if (ecs->NumOpenArcWarnings != 0) 737 { 738 stdStream << endl; 739 if (ecs->NumOpenArcWarnings != 0) 740 stdStream << "Warnings: " << ecs->NumOpenArcWarnings << endl; 741 } 742 743 if (ecs->NumOpenArcErrors != 0) 744 { 745 isError = true; 746 stdStream << endl; 747 if (ecs->NumOpenArcErrors != 0) 748 stdStream << "Open Errors: " << ecs->NumOpenArcErrors << endl; 749 } 750 751 if (isError) 752 retCode = NExitCode::kFatalError; 753 754 if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0) 755 { 756 // if (ecs->NumArchives > 1) 757 { 758 stdStream << endl; 759 if (ecs->NumFileErrors != 0) 760 stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl; 761 } 762 } 763 else if (hresultMain == S_OK) 764 { 765 766 if (stat.NumFolders != 0) 767 stdStream << "Folders: " << stat.NumFolders << endl; 768 if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0) 769 stdStream << "Files: " << stat.NumFiles << endl; 770 if (stat.NumAltStreams != 0) 771 { 772 stdStream << "Alternate Streams: " << stat.NumAltStreams << endl; 773 stdStream << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl; 774 } 775 776 stdStream 777 << "Size: " << stat.UnpackSize << endl 778 << "Compressed: " << stat.PackSize << endl; 779 if (hashCalc) 780 PrintHashStat(stdStream, hb); 781 } 782 } 783 else 784 { 785 UInt64 numErrors = 0; 786 UInt64 numWarnings = 0; 787 788 // options.ExtractNtOptions.StoreAltStreams = true, if -sns[-] is not definmed 789 790 hresultMain = ListArchives( 791 codecs, 792 types, 793 excludedFormats, 794 options.StdInMode, 795 options.ArchivePathsSorted, 796 options.ArchivePathsFullSorted, 797 options.ExtractOptions.NtOptions.AltStreams.Val, 798 options.AltStreams.Val, // we don't want to show AltStreams by default 799 options.Censor.Pairs.Front().Head, 800 options.EnableHeaders, 801 options.TechMode, 802 #ifndef _NO_CRYPTO 803 options.PasswordEnabled, 804 options.Password, 805 #endif 806 &options.Properties, 807 numErrors, numWarnings); 808 809 if (options.EnableHeaders) 810 if (numWarnings > 0) 811 g_StdOut << endl << "Warnings: " << numWarnings << endl; 812 if (numErrors > 0) 813 { 814 if (options.EnableHeaders) 815 g_StdOut << endl << "Errors: " << numErrors << endl; 816 retCode = NExitCode::kFatalError; 817 } 818 } 819 } 820 else if (options.Command.IsFromUpdateGroup()) 821 { 822 CUpdateOptions &uo = options.UpdateOptions; 823 if (uo.SfxMode && uo.SfxModule.IsEmpty()) 824 uo.SfxModule = kDefaultSfxModule; 825 826 COpenCallbackConsole openCallback; 827 openCallback.OutStream = &stdStream; 828 829 #ifndef _NO_CRYPTO 830 bool passwordIsDefined = 831 options.PasswordEnabled && !options.Password.IsEmpty(); 832 openCallback.PasswordIsDefined = passwordIsDefined; 833 openCallback.Password = options.Password; 834 #endif 835 836 CUpdateCallbackConsole callback; 837 callback.EnablePercents = options.EnablePercents; 838 839 #ifndef _NO_CRYPTO 840 callback.PasswordIsDefined = passwordIsDefined; 841 callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty(); 842 callback.Password = options.Password; 843 #endif 844 callback.StdOutMode = uo.StdOutMode; 845 callback.Init(&stdStream); 846 847 CUpdateErrorInfo errorInfo; 848 849 /* 850 if (!uo.Init(codecs, types, options.ArchiveName)) 851 throw kUnsupportedUpdateArcType; 852 */ 853 hresultMain = UpdateArchive(codecs, 854 types, 855 options.ArchiveName, 856 options.Censor, 857 uo, 858 errorInfo, &openCallback, &callback, true); 859 retCode = WarningsCheck(hresultMain, callback, errorInfo, stdStream); 860 } 861 else if (options.Command.CommandType == NCommandType::kHash) 862 { 863 const CHashOptions &uo = options.HashOptions; 864 865 CHashCallbackConsole callback; 866 callback.EnablePercents = options.EnablePercents; 867 868 callback.Init(&stdStream); 869 870 UString errorInfoString; 871 hresultMain = HashCalc(EXTERNAL_CODECS_VARS 872 options.Censor, uo, 873 errorInfoString, &callback); 874 CErrorInfo errorInfo; 875 errorInfo.Message = errorInfoString; 876 retCode = WarningsCheck(hresultMain, callback, errorInfo, stdStream); 877 } 878 else 879 ShowMessageAndThrowException(stdStream, kUserErrorMessage, NExitCode::kUserError); 880 881 if (showStat) 882 PrintStat(); 883 884 ThrowException_if_Error(hresultMain); 885 886 return retCode; 887 } 888