Main.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. // Main.cpp
  2. #include "StdAfx.h"
  3. #include "Common/MyInitGuid.h"
  4. #include "Common/CommandLineParser.h"
  5. #include "Common/MyException.h"
  6. #include "Common/IntToString.h"
  7. #include "Common/StdOutStream.h"
  8. #include "Common/StringConvert.h"
  9. #include "Common/StringToInt.h"
  10. #include "Windows/FileDir.h"
  11. #include "Windows/FileName.h"
  12. #include "Windows/Defs.h"
  13. #include "Windows/Error.h"
  14. #ifdef _WIN32
  15. #include "Windows/MemoryLock.h"
  16. #endif
  17. #include "../../IPassword.h"
  18. #include "../../ICoder.h"
  19. #include "../Common/UpdateAction.h"
  20. #include "../Common/Update.h"
  21. #include "../Common/Extract.h"
  22. #include "../Common/ArchiveCommandLine.h"
  23. #include "../Common/ExitCode.h"
  24. #ifdef EXTERNAL_CODECS
  25. #include "../Common/LoadCodecs.h"
  26. #endif
  27. #include "../../Compress/LZMA_Alone/LzmaBenchCon.h"
  28. #include "List.h"
  29. #include "OpenCallbackConsole.h"
  30. #include "ExtractCallbackConsole.h"
  31. #include "UpdateCallbackConsole.h"
  32. #include "../../MyVersion.h"
  33. #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES)
  34. extern "C"
  35. {
  36. #include "../../../../C/Alloc.h"
  37. }
  38. #endif
  39. using namespace NWindows;
  40. using namespace NFile;
  41. using namespace NCommandLineParser;
  42. HINSTANCE g_hInstance = 0;
  43. extern CStdOutStream *g_StdStream;
  44. static const char *kCopyrightString = "\n7-Zip"
  45. #ifndef EXTERNAL_CODECS
  46. " (A)"
  47. #endif
  48. #ifdef _WIN64
  49. " [64]"
  50. #endif
  51. " " MY_VERSION_COPYRIGHT_DATE "\n";
  52. static const char *kHelpString =
  53. "\nUsage: 7z"
  54. #ifdef _NO_CRYPTO
  55. "r"
  56. #else
  57. #ifndef EXTERNAL_CODECS
  58. "a"
  59. #endif
  60. #endif
  61. " <command> [<switches>...] <archive_name> [<file_names>...]\n"
  62. " [<@listfiles...>]\n"
  63. "\n"
  64. "<Commands>\n"
  65. " a: Add files to archive\n"
  66. " b: Benchmark\n"
  67. " d: Delete files from archive\n"
  68. " e: Extract files from archive (without using directory names)\n"
  69. " l: List contents of archive\n"
  70. // " l[a|t][f]: List contents of archive\n"
  71. // " a - with Additional fields\n"
  72. // " t - with all fields\n"
  73. // " f - with Full pathnames\n"
  74. " t: Test integrity of archive\n"
  75. " u: Update files to archive\n"
  76. " x: eXtract files with full paths\n"
  77. "<Switches>\n"
  78. " -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n"
  79. " -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n"
  80. " -bd: Disable percentage indicator\n"
  81. " -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n"
  82. " -m{Parameters}: set compression Method\n"
  83. " -o{Directory}: set Output directory\n"
  84. " -p{Password}: set Password\n"
  85. " -r[-|0]: Recurse subdirectories\n"
  86. " -scs{UTF-8 | WIN | DOS}: set charset for list files\n"
  87. " -sfx[{name}]: Create SFX archive\n"
  88. " -si[{name}]: read data from stdin\n"
  89. " -slt: show technical information for l (List) command\n"
  90. " -so: write data to stdout\n"
  91. " -ssc[-]: set sensitive case mode\n"
  92. " -ssw: compress shared files\n"
  93. " -t{Type}: Set type of archive\n"
  94. " -v{Size}[b|k|m|g]: Create volumes\n"
  95. " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n"
  96. " -w[{path}]: assign Work directory. Empty path means a temporary directory\n"
  97. " -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n"
  98. " -y: assume Yes on all queries\n";
  99. // ---------------------------
  100. // exception messages
  101. static const char *kEverythingIsOk = "Everything is Ok";
  102. static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError
  103. static const wchar_t *kDefaultSfxModule = L"7zCon.sfx";
  104. static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code)
  105. {
  106. s << message << endl;
  107. throw code;
  108. }
  109. static void PrintHelpAndExit(CStdOutStream &s) // yyy
  110. {
  111. s << kHelpString;
  112. ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError);
  113. }
  114. #ifndef _WIN32
  115. static void GetArguments(int numArguments, const char *arguments[], UStringVector &parts)
  116. {
  117. parts.Clear();
  118. for(int i = 0; i < numArguments; i++)
  119. {
  120. UString s = MultiByteToUnicodeString(arguments[i]);
  121. parts.Add(s);
  122. }
  123. }
  124. #endif
  125. static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp)
  126. {
  127. s << kCopyrightString;
  128. // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n";
  129. if (needHelp)
  130. s << kHelpString;
  131. }
  132. #ifdef EXTERNAL_CODECS
  133. static void PrintString(CStdOutStream &stdStream, const AString &s, int size)
  134. {
  135. int len = s.Length();
  136. stdStream << s;
  137. for (int i = len; i < size; i++)
  138. stdStream << ' ';
  139. }
  140. #endif
  141. static void PrintString(CStdOutStream &stdStream, const UString &s, int size)
  142. {
  143. int len = s.Length();
  144. stdStream << s;
  145. for (int i = len; i < size; i++)
  146. stdStream << ' ';
  147. }
  148. static inline char GetHex(Byte value)
  149. {
  150. return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
  151. }
  152. int Main2(
  153. #ifndef _WIN32
  154. int numArguments, const char *arguments[]
  155. #endif
  156. )
  157. {
  158. #ifdef _WIN32
  159. SetFileApisToOEM();
  160. #endif
  161. UStringVector commandStrings;
  162. #ifdef _WIN32
  163. NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
  164. #else
  165. GetArguments(numArguments, arguments, commandStrings);
  166. #endif
  167. if(commandStrings.Size() == 1)
  168. {
  169. ShowCopyrightAndHelp(g_StdOut, true);
  170. return 0;
  171. }
  172. commandStrings.Delete(0);
  173. CArchiveCommandLineOptions options;
  174. CArchiveCommandLineParser parser;
  175. parser.Parse1(commandStrings, options);
  176. if(options.HelpMode)
  177. {
  178. ShowCopyrightAndHelp(g_StdOut, true);
  179. return 0;
  180. }
  181. #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)
  182. if (options.LargePages)
  183. {
  184. SetLargePageSize();
  185. NSecurity::EnableLockMemoryPrivilege();
  186. }
  187. #endif
  188. CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut;
  189. g_StdStream = &stdStream;
  190. if (options.EnableHeaders)
  191. ShowCopyrightAndHelp(stdStream, false);
  192. parser.Parse2(options);
  193. CCodecs *codecs = new CCodecs;
  194. CMyComPtr<
  195. #ifdef EXTERNAL_CODECS
  196. ICompressCodecsInfo
  197. #else
  198. IUnknown
  199. #endif
  200. > compressCodecsInfo = codecs;
  201. HRESULT result = codecs->Load();
  202. if (result != S_OK)
  203. throw CSystemException(result);
  204. bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
  205. if (options.Command.CommandType == NCommandType::kInfo)
  206. {
  207. stdStream << endl << "Formats:" << endl;
  208. int i;
  209. for (i = 0; i < codecs->Formats.Size(); i++)
  210. {
  211. const CArcInfoEx &arc = codecs->Formats[i];
  212. #ifdef EXTERNAL_CODECS
  213. if (arc.LibIndex >= 0)
  214. {
  215. char s[32];
  216. ConvertUInt64ToString(arc.LibIndex, s);
  217. PrintString(stdStream, s, 2);
  218. }
  219. else
  220. #endif
  221. stdStream << " ";
  222. stdStream << ' ';
  223. stdStream << (char)(arc.UpdateEnabled ? 'C' : ' ');
  224. stdStream << (char)(arc.KeepName ? 'K' : ' ');
  225. stdStream << " ";
  226. PrintString(stdStream, arc.Name, 6);
  227. stdStream << " ";
  228. UString s;
  229. for (int t = 0; t < arc.Exts.Size(); t++)
  230. {
  231. const CArcExtInfo &ext = arc.Exts[t];
  232. s += ext.Ext;
  233. if (!ext.AddExt.IsEmpty())
  234. {
  235. s += L" (";
  236. s += ext.AddExt;
  237. s += L')';
  238. }
  239. s += L' ';
  240. }
  241. PrintString(stdStream, s, 14);
  242. stdStream << " ";
  243. const CByteBuffer &sig = arc.StartSignature;
  244. for (size_t j = 0; j < sig.GetCapacity(); j++)
  245. {
  246. Byte b = sig[j];
  247. if (b > 0x20 && b < 0x80)
  248. {
  249. stdStream << (char)b;
  250. }
  251. else
  252. {
  253. stdStream << GetHex((Byte)((b >> 4) & 0xF));
  254. stdStream << GetHex((Byte)(b & 0xF));
  255. }
  256. stdStream << ' ';
  257. }
  258. stdStream << endl;
  259. }
  260. stdStream << endl << "Codecs:" << endl;
  261. #ifdef EXTERNAL_CODECS
  262. UINT32 numMethods;
  263. if (codecs->GetNumberOfMethods(&numMethods) == S_OK)
  264. for (UInt32 j = 0; j < numMethods; j++)
  265. {
  266. int libIndex = codecs->GetCodecLibIndex(j);
  267. if (libIndex >= 0)
  268. {
  269. char s[32];
  270. ConvertUInt64ToString(libIndex, s);
  271. PrintString(stdStream, s, 2);
  272. }
  273. else
  274. stdStream << " ";
  275. stdStream << ' ';
  276. stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' ');
  277. UInt64 id;
  278. stdStream << " ";
  279. HRESULT res = codecs->GetCodecId(j, id);
  280. if (res != S_OK)
  281. id = (UInt64)(Int64)-1;
  282. char s[32];
  283. ConvertUInt64ToString(id, s, 16);
  284. PrintString(stdStream, s, 8);
  285. stdStream << " ";
  286. PrintString(stdStream, codecs->GetCodecName(j), 11);
  287. stdStream << endl;
  288. /*
  289. if (res != S_OK)
  290. throw "incorrect Codec ID";
  291. */
  292. }
  293. #endif
  294. return S_OK;
  295. }
  296. else if (options.Command.CommandType == NCommandType::kBenchmark)
  297. {
  298. if (options.Method.CompareNoCase(L"CRC") == 0)
  299. {
  300. HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize);
  301. if (res != S_OK)
  302. {
  303. if (res == S_FALSE)
  304. {
  305. stdStream << "\nCRC Error\n";
  306. return NExitCode::kFatalError;
  307. }
  308. throw CSystemException(res);
  309. }
  310. }
  311. else
  312. {
  313. HRESULT res = LzmaBenchCon(
  314. #ifdef EXTERNAL_LZMA
  315. codecs,
  316. #endif
  317. (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize);
  318. if (res != S_OK)
  319. {
  320. if (res == S_FALSE)
  321. {
  322. stdStream << "\nDecoding Error\n";
  323. return NExitCode::kFatalError;
  324. }
  325. throw CSystemException(res);
  326. }
  327. }
  328. }
  329. else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)
  330. {
  331. if(isExtractGroupCommand)
  332. {
  333. CExtractCallbackConsole *ecs = new CExtractCallbackConsole;
  334. CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
  335. ecs->OutStream = &stdStream;
  336. ecs->PasswordIsDefined = options.PasswordEnabled;
  337. ecs->Password = options.Password;
  338. ecs->Init();
  339. COpenCallbackConsole openCallback;
  340. openCallback.OutStream = &stdStream;
  341. openCallback.PasswordIsDefined = options.PasswordEnabled;
  342. openCallback.Password = options.Password;
  343. CExtractOptions eo;
  344. eo.StdOutMode = options.StdOutMode;
  345. eo.PathMode = options.Command.GetPathMode();
  346. eo.TestMode = options.Command.IsTestMode();
  347. eo.OverwriteMode = options.OverwriteMode;
  348. eo.OutputDir = options.OutputDir;
  349. eo.YesToAll = options.YesToAll;
  350. #ifdef COMPRESS_MT
  351. eo.Properties = options.ExtractProperties;
  352. #endif
  353. UString errorMessage;
  354. CDecompressStat stat;
  355. HRESULT result = DecompressArchives(
  356. codecs,
  357. options.ArchivePathsSorted,
  358. options.ArchivePathsFullSorted,
  359. options.WildcardCensor.Pairs.Front().Head,
  360. eo, &openCallback, ecs, errorMessage, stat);
  361. if (!errorMessage.IsEmpty())
  362. {
  363. stdStream << endl << "Error: " << errorMessage;
  364. if (result == S_OK)
  365. result = E_FAIL;
  366. }
  367. stdStream << endl;
  368. if (ecs->NumArchives > 1)
  369. stdStream << "Archives: " << ecs->NumArchives << endl;
  370. if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0)
  371. {
  372. if (ecs->NumArchives > 1)
  373. {
  374. stdStream << endl;
  375. if (ecs->NumArchiveErrors != 0)
  376. stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl;
  377. if (ecs->NumFileErrors != 0)
  378. stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl;
  379. }
  380. if (result != S_OK)
  381. throw CSystemException(result);
  382. return NExitCode::kFatalError;
  383. }
  384. if (result != S_OK)
  385. throw CSystemException(result);
  386. if (stat.NumFolders != 0)
  387. stdStream << "Folders: " << stat.NumFolders << endl;
  388. if (stat.NumFiles != 1 || stat.NumFolders != 0)
  389. stdStream << "Files: " << stat.NumFiles << endl;
  390. stdStream
  391. << "Size: " << stat.UnpackSize << endl
  392. << "Compressed: " << stat.PackSize << endl;
  393. }
  394. else
  395. {
  396. UInt64 numErrors = 0;
  397. HRESULT result = ListArchives(
  398. codecs,
  399. options.ArchivePathsSorted,
  400. options.ArchivePathsFullSorted,
  401. options.WildcardCensor.Pairs.Front().Head,
  402. options.EnableHeaders,
  403. options.TechMode,
  404. options.PasswordEnabled,
  405. options.Password, numErrors);
  406. if (numErrors > 0)
  407. {
  408. g_StdOut << endl << "Errors: " << numErrors;
  409. return NExitCode::kFatalError;
  410. }
  411. if (result != S_OK)
  412. throw CSystemException(result);
  413. }
  414. }
  415. else if(options.Command.IsFromUpdateGroup())
  416. {
  417. UString workingDir;
  418. CUpdateOptions &uo = options.UpdateOptions;
  419. if (uo.SfxMode && uo.SfxModule.IsEmpty())
  420. uo.SfxModule = kDefaultSfxModule;
  421. bool passwordIsDefined =
  422. options.PasswordEnabled && !options.Password.IsEmpty();
  423. COpenCallbackConsole openCallback;
  424. openCallback.OutStream = &stdStream;
  425. openCallback.PasswordIsDefined = passwordIsDefined;
  426. openCallback.Password = options.Password;
  427. CUpdateCallbackConsole callback;
  428. callback.EnablePercents = options.EnablePercents;
  429. callback.PasswordIsDefined = passwordIsDefined;
  430. callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty();
  431. callback.Password = options.Password;
  432. callback.StdOutMode = uo.StdOutMode;
  433. callback.Init(&stdStream);
  434. CUpdateErrorInfo errorInfo;
  435. if (!uo.Init(codecs, options.ArchiveName, options.ArcType))
  436. throw "Unsupported archive type";
  437. HRESULT result = UpdateArchive(codecs,
  438. options.WildcardCensor, uo,
  439. errorInfo, &openCallback, &callback);
  440. int exitCode = NExitCode::kSuccess;
  441. if (callback.CantFindFiles.Size() > 0)
  442. {
  443. stdStream << endl;
  444. stdStream << "WARNINGS for files:" << endl << endl;
  445. int numErrors = callback.CantFindFiles.Size();
  446. for (int i = 0; i < numErrors; i++)
  447. {
  448. stdStream << callback.CantFindFiles[i] << " : ";
  449. stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl;
  450. }
  451. stdStream << "----------------" << endl;
  452. stdStream << "WARNING: Cannot find " << numErrors << " file";
  453. if (numErrors > 1)
  454. stdStream << "s";
  455. stdStream << endl;
  456. exitCode = NExitCode::kWarning;
  457. }
  458. if (result != S_OK)
  459. {
  460. UString message;
  461. if (!errorInfo.Message.IsEmpty())
  462. {
  463. message += errorInfo.Message;
  464. message += L"\n";
  465. }
  466. if (!errorInfo.FileName.IsEmpty())
  467. {
  468. message += errorInfo.FileName;
  469. message += L"\n";
  470. }
  471. if (!errorInfo.FileName2.IsEmpty())
  472. {
  473. message += errorInfo.FileName2;
  474. message += L"\n";
  475. }
  476. if (errorInfo.SystemError != 0)
  477. {
  478. message += NError::MyFormatMessageW(errorInfo.SystemError);
  479. message += L"\n";
  480. }
  481. if (!message.IsEmpty())
  482. stdStream << L"\nError:\n" << message;
  483. throw CSystemException(result);
  484. }
  485. int numErrors = callback.FailedFiles.Size();
  486. if (numErrors == 0)
  487. {
  488. if (callback.CantFindFiles.Size() == 0)
  489. stdStream << kEverythingIsOk << endl;
  490. }
  491. else
  492. {
  493. stdStream << endl;
  494. stdStream << "WARNINGS for files:" << endl << endl;
  495. for (int i = 0; i < numErrors; i++)
  496. {
  497. stdStream << callback.FailedFiles[i] << " : ";
  498. stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl;
  499. }
  500. stdStream << "----------------" << endl;
  501. stdStream << "WARNING: Cannot open " << numErrors << " file";
  502. if (numErrors > 1)
  503. stdStream << "s";
  504. stdStream << endl;
  505. exitCode = NExitCode::kWarning;
  506. }
  507. return exitCode;
  508. }
  509. else
  510. PrintHelpAndExit(stdStream);
  511. return 0;
  512. }