1 // List.cpp |
|
2 |
|
3 #include "StdAfx.h" |
|
4 |
|
5 #include "List.h" |
|
6 #include "ConsoleClose.h" |
|
7 |
|
8 #include "Common/StringConvert.h" |
|
9 #include "Common/StdOutStream.h" |
|
10 #include "Common/IntToString.h" |
|
11 #include "Common/MyCom.h" |
|
12 |
|
13 #include "Windows/PropVariant.h" |
|
14 #include "Windows/Defs.h" |
|
15 #include "Windows/PropVariantConversions.h" |
|
16 #include "Windows/FileDir.h" |
|
17 |
|
18 #include "../../Archive/IArchive.h" |
|
19 |
|
20 #include "../Common/PropIDUtils.h" |
|
21 #include "../Common/OpenArchive.h" |
|
22 |
|
23 #include "OpenCallbackConsole.h" |
|
24 |
|
25 using namespace NWindows; |
|
26 |
|
27 struct CPropIdToName |
|
28 { |
|
29 PROPID PropID; |
|
30 const wchar_t *Name; |
|
31 }; |
|
32 |
|
33 static CPropIdToName kPropIdToName[] = |
|
34 { |
|
35 { kpidPath, L"Path" }, |
|
36 { kpidName, L"Name" }, |
|
37 { kpidIsFolder, L"Folder" }, |
|
38 { kpidSize, L"Size" }, |
|
39 { kpidPackedSize, L"Packed Size" }, |
|
40 { kpidAttributes, L"Attributes" }, |
|
41 { kpidCreationTime, L"Created" }, |
|
42 { kpidLastAccessTime, L"Accessed" }, |
|
43 { kpidLastWriteTime, L"Modified" }, |
|
44 { kpidSolid, L"Solid" }, |
|
45 { kpidCommented, L"Commented" }, |
|
46 { kpidEncrypted, L"Encrypted" }, |
|
47 { kpidSplitBefore, L"Split Before" }, |
|
48 { kpidSplitAfter, L"Split After" }, |
|
49 { kpidDictionarySize, L"Dictionary Size" }, |
|
50 { kpidCRC, L"CRC" }, |
|
51 { kpidType, L"Type" }, |
|
52 { kpidIsAnti, L"Anti" }, |
|
53 { kpidMethod, L"Method" }, |
|
54 { kpidHostOS, L"Host OS" }, |
|
55 { kpidFileSystem, L"File System" }, |
|
56 { kpidUser, L"User" }, |
|
57 { kpidGroup, L"Group" }, |
|
58 { kpidBlock, L"Block" }, |
|
59 { kpidComment, L"Comment" }, |
|
60 { kpidPosition, L"Position" }, |
|
61 { kpidPrefix, L"Prefix" }, |
|
62 { kpidNumSubFolders, L"Folders" }, |
|
63 { kpidNumSubFiles, L"Files" }, |
|
64 { kpidUnpackVer, L"Version" }, |
|
65 { kpidVolume, L"Volume" }, |
|
66 { kpidIsVolume, L"Multivolume" }, |
|
67 { kpidOffset, L"Offset" }, |
|
68 { kpidLinks, L"Links" }, |
|
69 { kpidNumBlocks, L"Blocks" }, |
|
70 { kpidNumVolumes, L"Volumes" } |
|
71 }; |
|
72 |
|
73 static const char kEmptyAttributeChar = '.'; |
|
74 static const char kDirectoryAttributeChar = 'D'; |
|
75 static const char kReadonlyAttributeChar = 'R'; |
|
76 static const char kHiddenAttributeChar = 'H'; |
|
77 static const char kSystemAttributeChar = 'S'; |
|
78 static const char kArchiveAttributeChar = 'A'; |
|
79 |
|
80 static const char *kListing = "Listing archive: "; |
|
81 static const wchar_t *kFilesMessage = L"files"; |
|
82 static const wchar_t *kDirsMessage = L"folders"; |
|
83 |
|
84 static void GetAttributesString(DWORD wa, bool directory, char *s) |
|
85 { |
|
86 s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || directory) ? |
|
87 kDirectoryAttributeChar: kEmptyAttributeChar; |
|
88 s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0)? |
|
89 kReadonlyAttributeChar: kEmptyAttributeChar; |
|
90 s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? |
|
91 kHiddenAttributeChar: kEmptyAttributeChar; |
|
92 s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? |
|
93 kSystemAttributeChar: kEmptyAttributeChar; |
|
94 s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? |
|
95 kArchiveAttributeChar: kEmptyAttributeChar; |
|
96 s[5] = '\0'; |
|
97 } |
|
98 |
|
99 enum EAdjustment |
|
100 { |
|
101 kLeft, |
|
102 kCenter, |
|
103 kRight |
|
104 }; |
|
105 |
|
106 struct CFieldInfo |
|
107 { |
|
108 PROPID PropID; |
|
109 UString Name; |
|
110 EAdjustment TitleAdjustment; |
|
111 EAdjustment TextAdjustment; |
|
112 int PrefixSpacesWidth; |
|
113 int Width; |
|
114 }; |
|
115 |
|
116 struct CFieldInfoInit |
|
117 { |
|
118 PROPID PropID; |
|
119 const wchar_t *Name; |
|
120 EAdjustment TitleAdjustment; |
|
121 EAdjustment TextAdjustment; |
|
122 int PrefixSpacesWidth; |
|
123 int Width; |
|
124 }; |
|
125 |
|
126 CFieldInfoInit kStandardFieldTable[] = |
|
127 { |
|
128 { kpidLastWriteTime, L" Date Time", kLeft, kLeft, 0, 19 }, |
|
129 { kpidAttributes, L"Attr", kRight, kCenter, 1, 5 }, |
|
130 { kpidSize, L"Size", kRight, kRight, 1, 12 }, |
|
131 { kpidPackedSize, L"Compressed", kRight, kRight, 1, 12 }, |
|
132 { kpidPath, L"Name", kLeft, kLeft, 2, 24 } |
|
133 }; |
|
134 |
|
135 void PrintSpaces(int numSpaces) |
|
136 { |
|
137 for (int i = 0; i < numSpaces; i++) |
|
138 g_StdOut << ' '; |
|
139 } |
|
140 |
|
141 void PrintString(EAdjustment adjustment, int width, const UString &textString) |
|
142 { |
|
143 const int numSpaces = width - textString.Length(); |
|
144 int numLeftSpaces = 0; |
|
145 switch (adjustment) |
|
146 { |
|
147 case kLeft: |
|
148 numLeftSpaces = 0; |
|
149 break; |
|
150 case kCenter: |
|
151 numLeftSpaces = numSpaces / 2; |
|
152 break; |
|
153 case kRight: |
|
154 numLeftSpaces = numSpaces; |
|
155 break; |
|
156 } |
|
157 PrintSpaces(numLeftSpaces); |
|
158 g_StdOut << textString; |
|
159 PrintSpaces(numSpaces - numLeftSpaces); |
|
160 } |
|
161 |
|
162 class CFieldPrinter |
|
163 { |
|
164 CObjectVector<CFieldInfo> _fields; |
|
165 public: |
|
166 void Clear() { _fields.Clear(); } |
|
167 void Init(const CFieldInfoInit *standardFieldTable, int numItems); |
|
168 HRESULT Init(IInArchive *archive); |
|
169 void PrintTitle(); |
|
170 void PrintTitleLines(); |
|
171 HRESULT PrintItemInfo(IInArchive *archive, |
|
172 const UString &defaultItemName, |
|
173 const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, |
|
174 UInt32 index, |
|
175 bool techMode); |
|
176 HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, |
|
177 const UInt64 *size, const UInt64 *compressedSize); |
|
178 }; |
|
179 |
|
180 void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems) |
|
181 { |
|
182 Clear(); |
|
183 for (int i = 0; i < numItems; i++) |
|
184 { |
|
185 CFieldInfo fieldInfo; |
|
186 const CFieldInfoInit &fieldInfoInit = standardFieldTable[i]; |
|
187 fieldInfo.PropID = fieldInfoInit.PropID; |
|
188 fieldInfo.Name = fieldInfoInit.Name; |
|
189 fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment; |
|
190 fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment; |
|
191 fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth; |
|
192 fieldInfo.Width = fieldInfoInit.Width; |
|
193 _fields.Add(fieldInfo); |
|
194 } |
|
195 } |
|
196 |
|
197 static UString GetPropName(PROPID propID, BSTR name) |
|
198 { |
|
199 for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++) |
|
200 { |
|
201 const CPropIdToName &propIdToName = kPropIdToName[i]; |
|
202 if (propIdToName.PropID == propID) |
|
203 return propIdToName.Name; |
|
204 } |
|
205 if (name) |
|
206 return name; |
|
207 return L"?"; |
|
208 } |
|
209 |
|
210 HRESULT CFieldPrinter::Init(IInArchive *archive) |
|
211 { |
|
212 Clear(); |
|
213 UInt32 numProps; |
|
214 RINOK(archive->GetNumberOfProperties(&numProps)); |
|
215 for (UInt32 i = 0; i < numProps; i++) |
|
216 { |
|
217 CMyComBSTR name; |
|
218 PROPID propID; |
|
219 VARTYPE vt; |
|
220 RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt)); |
|
221 CFieldInfo fieldInfo; |
|
222 fieldInfo.PropID = propID; |
|
223 fieldInfo.Name = GetPropName(propID, name); |
|
224 _fields.Add(fieldInfo); |
|
225 } |
|
226 return S_OK; |
|
227 } |
|
228 |
|
229 void CFieldPrinter::PrintTitle() |
|
230 { |
|
231 for (int i = 0; i < _fields.Size(); i++) |
|
232 { |
|
233 const CFieldInfo &fieldInfo = _fields[i]; |
|
234 PrintSpaces(fieldInfo.PrefixSpacesWidth); |
|
235 PrintString(fieldInfo.TitleAdjustment, |
|
236 ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name); |
|
237 } |
|
238 } |
|
239 |
|
240 void CFieldPrinter::PrintTitleLines() |
|
241 { |
|
242 for (int i = 0; i < _fields.Size(); i++) |
|
243 { |
|
244 const CFieldInfo &fieldInfo = _fields[i]; |
|
245 PrintSpaces(fieldInfo.PrefixSpacesWidth); |
|
246 for (int i = 0; i < fieldInfo.Width; i++) |
|
247 g_StdOut << '-'; |
|
248 } |
|
249 } |
|
250 |
|
251 |
|
252 BOOL IsFileTimeZero(CONST FILETIME *lpFileTime) |
|
253 { |
|
254 return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0); |
|
255 } |
|
256 |
|
257 static const char *kEmptyTimeString = " "; |
|
258 void PrintTime(const NCOM::CPropVariant &propVariant) |
|
259 { |
|
260 if (propVariant.vt != VT_FILETIME) |
|
261 throw "incorrect item"; |
|
262 if (IsFileTimeZero(&propVariant.filetime)) |
|
263 g_StdOut << kEmptyTimeString; |
|
264 else |
|
265 { |
|
266 FILETIME localFileTime; |
|
267 if (!FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime)) |
|
268 throw "FileTimeToLocalFileTime error"; |
|
269 char s[32]; |
|
270 if (ConvertFileTimeToString(localFileTime, s, true, true)) |
|
271 g_StdOut << s; |
|
272 else |
|
273 g_StdOut << kEmptyTimeString; |
|
274 } |
|
275 } |
|
276 |
|
277 HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive, |
|
278 const UString &defaultItemName, |
|
279 const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, |
|
280 UInt32 index, |
|
281 bool techMode) |
|
282 { |
|
283 /* |
|
284 if (techMode) |
|
285 { |
|
286 g_StdOut << "Index = "; |
|
287 g_StdOut << (UInt64)index; |
|
288 g_StdOut << endl; |
|
289 } |
|
290 */ |
|
291 for (int i = 0; i < _fields.Size(); i++) |
|
292 { |
|
293 const CFieldInfo &fieldInfo = _fields[i]; |
|
294 if (!techMode) |
|
295 PrintSpaces(fieldInfo.PrefixSpacesWidth); |
|
296 |
|
297 NCOM::CPropVariant propVariant; |
|
298 RINOK(archive->GetProperty(index, fieldInfo.PropID, &propVariant)); |
|
299 if (techMode) |
|
300 { |
|
301 g_StdOut << fieldInfo.Name << " = "; |
|
302 } |
|
303 int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width; |
|
304 if (propVariant.vt == VT_EMPTY) |
|
305 { |
|
306 switch(fieldInfo.PropID) |
|
307 { |
|
308 case kpidPath: |
|
309 propVariant = defaultItemName; |
|
310 break; |
|
311 case kpidLastWriteTime: |
|
312 propVariant = archiveFileInfo.LastWriteTime; |
|
313 break; |
|
314 default: |
|
315 if (techMode) |
|
316 g_StdOut << endl; |
|
317 else |
|
318 PrintSpaces(width); |
|
319 continue; |
|
320 } |
|
321 } |
|
322 if (fieldInfo.PropID == kpidLastWriteTime) |
|
323 { |
|
324 PrintTime(propVariant); |
|
325 } |
|
326 else if (fieldInfo.PropID == kpidAttributes) |
|
327 { |
|
328 if (propVariant.vt != VT_UI4) |
|
329 throw "incorrect item"; |
|
330 UInt32 attributes = propVariant.ulVal; |
|
331 bool isFolder; |
|
332 RINOK(IsArchiveItemFolder(archive, index, isFolder)); |
|
333 char s[8]; |
|
334 GetAttributesString(attributes, isFolder, s); |
|
335 g_StdOut << s; |
|
336 } |
|
337 else if (propVariant.vt == VT_BSTR) |
|
338 { |
|
339 if (techMode) |
|
340 g_StdOut << propVariant.bstrVal; |
|
341 else |
|
342 PrintString(fieldInfo.TextAdjustment, width, propVariant.bstrVal); |
|
343 } |
|
344 else |
|
345 { |
|
346 UString s = ConvertPropertyToString(propVariant, fieldInfo.PropID); |
|
347 s.Replace(wchar_t(0xA), L' '); |
|
348 s.Replace(wchar_t(0xD), L' '); |
|
349 |
|
350 if (techMode) |
|
351 g_StdOut << s; |
|
352 else |
|
353 PrintString(fieldInfo.TextAdjustment, width, s); |
|
354 } |
|
355 if (techMode) |
|
356 g_StdOut << endl; |
|
357 } |
|
358 return S_OK; |
|
359 } |
|
360 |
|
361 void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value) |
|
362 { |
|
363 wchar_t textString[32] = { 0 }; |
|
364 if (value != NULL) |
|
365 ConvertUInt64ToString(*value, textString); |
|
366 PrintString(adjustment, width, textString); |
|
367 } |
|
368 |
|
369 |
|
370 HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, |
|
371 const UInt64 *size, const UInt64 *compressedSize) |
|
372 { |
|
373 for (int i = 0; i < _fields.Size(); i++) |
|
374 { |
|
375 const CFieldInfo &fieldInfo = _fields[i]; |
|
376 PrintSpaces(fieldInfo.PrefixSpacesWidth); |
|
377 NCOM::CPropVariant propVariant; |
|
378 if (fieldInfo.PropID == kpidSize) |
|
379 PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size); |
|
380 else if (fieldInfo.PropID == kpidPackedSize) |
|
381 PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize); |
|
382 else if (fieldInfo.PropID == kpidPath) |
|
383 { |
|
384 wchar_t textString[32]; |
|
385 ConvertUInt64ToString(numFiles, textString); |
|
386 UString temp = textString; |
|
387 temp += L" "; |
|
388 temp += kFilesMessage; |
|
389 temp += L", "; |
|
390 ConvertUInt64ToString(numDirs, textString); |
|
391 temp += textString; |
|
392 temp += L" "; |
|
393 temp += kDirsMessage; |
|
394 PrintString(fieldInfo.TextAdjustment, 0, temp); |
|
395 } |
|
396 else |
|
397 PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L""); |
|
398 } |
|
399 return S_OK; |
|
400 } |
|
401 |
|
402 bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value) |
|
403 { |
|
404 NCOM::CPropVariant propVariant; |
|
405 if (archive->GetProperty(index, propID, &propVariant) != S_OK) |
|
406 throw "GetPropertyValue error"; |
|
407 if (propVariant.vt == VT_EMPTY) |
|
408 return false; |
|
409 value = ConvertPropVariantToUInt64(propVariant); |
|
410 return true; |
|
411 } |
|
412 |
|
413 HRESULT ListArchives( |
|
414 CCodecs *codecs, |
|
415 UStringVector &archivePaths, UStringVector &archivePathsFull, |
|
416 const NWildcard::CCensorNode &wildcardCensor, |
|
417 bool enableHeaders, bool techMode, bool &passwordEnabled, UString &password, UInt64 &numErrors) |
|
418 { |
|
419 numErrors = 0; |
|
420 CFieldPrinter fieldPrinter; |
|
421 if (!techMode) |
|
422 fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); |
|
423 |
|
424 UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; |
|
425 UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0; |
|
426 for (int i = 0; i < archivePaths.Size(); i++) |
|
427 { |
|
428 const UString &archiveName = archivePaths[i]; |
|
429 NFile::NFind::CFileInfoW archiveFileInfo; |
|
430 if (!NFile::NFind::FindFile(archiveName, archiveFileInfo) || archiveFileInfo.IsDirectory()) |
|
431 { |
|
432 g_StdOut << endl << "Error: " << archiveName << " is not archive" << endl; |
|
433 numErrors++; |
|
434 continue; |
|
435 } |
|
436 if (archiveFileInfo.IsDirectory()) |
|
437 { |
|
438 g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; |
|
439 numErrors++; |
|
440 continue; |
|
441 } |
|
442 |
|
443 CArchiveLink archiveLink; |
|
444 |
|
445 COpenCallbackConsole openCallback; |
|
446 openCallback.OutStream = &g_StdOut; |
|
447 openCallback.PasswordIsDefined = passwordEnabled; |
|
448 openCallback.Password = password; |
|
449 |
|
450 HRESULT result = MyOpenArchive(codecs, archiveName, archiveLink, &openCallback); |
|
451 if (result != S_OK) |
|
452 { |
|
453 g_StdOut << endl << "Error: " << archiveName << " is not supported archive" << endl; |
|
454 numErrors++; |
|
455 continue; |
|
456 } |
|
457 |
|
458 for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) |
|
459 { |
|
460 int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); |
|
461 if (index >= 0 && index > i) |
|
462 { |
|
463 archivePaths.Delete(index); |
|
464 archivePathsFull.Delete(index); |
|
465 } |
|
466 } |
|
467 |
|
468 IInArchive *archive = archiveLink.GetArchive(); |
|
469 const UString defaultItemName = archiveLink.GetDefaultItemName(); |
|
470 |
|
471 if (enableHeaders) |
|
472 { |
|
473 g_StdOut << endl << kListing << archiveName << endl << endl; |
|
474 |
|
475 UInt32 numProps; |
|
476 if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) |
|
477 { |
|
478 for (UInt32 i = 0; i < numProps; i++) |
|
479 { |
|
480 CMyComBSTR name; |
|
481 PROPID propID; |
|
482 VARTYPE vt; |
|
483 if (archive->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK) |
|
484 continue; |
|
485 NCOM::CPropVariant prop; |
|
486 if (archive->GetArchiveProperty(propID, &prop) != S_OK) |
|
487 continue; |
|
488 UString s = ConvertPropertyToString(prop, propID); |
|
489 if (!s.IsEmpty()) |
|
490 g_StdOut << GetPropName(propID, name) << " = " << s << endl; |
|
491 } |
|
492 } |
|
493 if (techMode) |
|
494 g_StdOut << "----------\n"; |
|
495 if (numProps > 0) |
|
496 g_StdOut << endl; |
|
497 } |
|
498 |
|
499 if (enableHeaders && !techMode) |
|
500 { |
|
501 fieldPrinter.PrintTitle(); |
|
502 g_StdOut << endl; |
|
503 fieldPrinter.PrintTitleLines(); |
|
504 g_StdOut << endl; |
|
505 } |
|
506 |
|
507 if (techMode) |
|
508 { |
|
509 RINOK(fieldPrinter.Init(archive)); |
|
510 } |
|
511 UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0; |
|
512 UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0; |
|
513 UInt32 numItems; |
|
514 RINOK(archive->GetNumberOfItems(&numItems)); |
|
515 for(UInt32 i = 0; i < numItems; i++) |
|
516 { |
|
517 if (NConsoleClose::TestBreakSignal()) |
|
518 return E_ABORT; |
|
519 |
|
520 UString filePath; |
|
521 RINOK(GetArchiveItemPath(archive, i, defaultItemName, filePath)); |
|
522 |
|
523 bool isFolder; |
|
524 RINOK(IsArchiveItemFolder(archive, i, isFolder)); |
|
525 if (!wildcardCensor.CheckPath(filePath, !isFolder)) |
|
526 continue; |
|
527 |
|
528 fieldPrinter.PrintItemInfo(archive, defaultItemName, archiveFileInfo, i, techMode); |
|
529 |
|
530 UInt64 packSize, unpackSize; |
|
531 if (!GetUInt64Value(archive, i, kpidSize, unpackSize)) |
|
532 unpackSize = 0; |
|
533 else |
|
534 totalUnPackSizePointer = &totalUnPackSize; |
|
535 if (!GetUInt64Value(archive, i, kpidPackedSize, packSize)) |
|
536 packSize = 0; |
|
537 else |
|
538 totalPackSizePointer = &totalPackSize; |
|
539 |
|
540 g_StdOut << endl; |
|
541 |
|
542 if (isFolder) |
|
543 numDirs++; |
|
544 else |
|
545 numFiles++; |
|
546 totalPackSize += packSize; |
|
547 totalUnPackSize += unpackSize; |
|
548 } |
|
549 if (enableHeaders && !techMode) |
|
550 { |
|
551 fieldPrinter.PrintTitleLines(); |
|
552 g_StdOut << endl; |
|
553 fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); |
|
554 g_StdOut << endl; |
|
555 } |
|
556 if (totalPackSizePointer != 0) |
|
557 { |
|
558 totalPackSizePointer2 = &totalPackSize2; |
|
559 totalPackSize2 += totalPackSize; |
|
560 } |
|
561 if (totalUnPackSizePointer != 0) |
|
562 { |
|
563 totalUnPackSizePointer2 = &totalUnPackSize2; |
|
564 totalUnPackSize2 += totalUnPackSize; |
|
565 } |
|
566 numFiles2 += numFiles; |
|
567 numDirs2 += numDirs; |
|
568 } |
|
569 if (enableHeaders && !techMode && archivePaths.Size() > 1) |
|
570 { |
|
571 g_StdOut << endl; |
|
572 fieldPrinter.PrintTitleLines(); |
|
573 g_StdOut << endl; |
|
574 fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); |
|
575 g_StdOut << endl; |
|
576 g_StdOut << "Archives: " << archivePaths.Size() << endl; |
|
577 } |
|
578 return S_OK; |
|
579 } |
|