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