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