Source code
Revision control
Copy as Markdown
Other Tools
// List.cpp↩
↩
#include "StdAfx.h"↩
↩
#include "../../../Common/IntToString.h"↩
#include "../../../Common/MyCom.h"↩
#include "../../../Common/StdOutStream.h"↩
#include "../../../Common/StringConvert.h"↩
#include "../../../Common/UTFConvert.h"↩
↩
#include "../../../Windows/ErrorMsg.h"↩
#include "../../../Windows/FileDir.h"↩
#include "../../../Windows/PropVariant.h"↩
#include "../../../Windows/PropVariantConv.h"↩
↩
#include "../Common/OpenArchive.h"↩
#include "../Common/PropIDUtils.h"↩
↩
#include "ConsoleClose.h"↩
#include "List.h"↩
#include "OpenCallbackConsole.h"↩
↩
using namespace NWindows;↩
using namespace NCOM;↩
↩
extern CStdOutStream *g_StdStream;↩
extern CStdOutStream *g_ErrStream;↩
↩
static const char * const kPropIdToName[] =↩
{↩
"0"↩
, "1"↩
, "2"↩
, "Path"↩
, "Name"↩
, "Extension"↩
, "Folder"↩
, "Size"↩
, "Packed Size"↩
, "Attributes"↩
, "Created"↩
, "Accessed"↩
, "Modified"↩
, "Solid"↩
, "Commented"↩
, "Encrypted"↩
, "Split Before"↩
, "Split After"↩
, "Dictionary Size"↩
, "CRC"↩
, "Type"↩
, "Anti"↩
, "Method"↩
, "Host OS"↩
, "File System"↩
, "User"↩
, "Group"↩
, "Block"↩
, "Comment"↩
, "Position"↩
, "Path Prefix"↩
, "Folders"↩
, "Files"↩
, "Version"↩
, "Volume"↩
, "Multivolume"↩
, "Offset"↩
, "Links"↩
, "Blocks"↩
, "Volumes"↩
, "Time Type"↩
, "64-bit"↩
, "Big-endian"↩
, "CPU"↩
, "Physical Size"↩
, "Headers Size"↩
, "Checksum"↩
, "Characteristics"↩
, "Virtual Address"↩
, "ID"↩
, "Short Name"↩
, "Creator Application"↩
, "Sector Size"↩
, "Mode"↩
, "Symbolic Link"↩
, "Error"↩
, "Total Size"↩
, "Free Space"↩
, "Cluster Size"↩
, "Label"↩
, "Local Name"↩
, "Provider"↩
, "NT Security"↩
, "Alternate Stream"↩
, "Aux"↩
, "Deleted"↩
, "Tree"↩
, "SHA-1"↩
, "SHA-256"↩
, "Error Type"↩
, "Errors"↩
, "Errors"↩
, "Warnings"↩
, "Warning"↩
, "Streams"↩
, "Alternate Streams"↩
, "Alternate Streams Size"↩
, "Virtual Size"↩
, "Unpack Size"↩
, "Total Physical Size"↩
, "Volume Index"↩
, "SubType"↩
, "Short Comment"↩
, "Code Page"↩
, "Is not archive type"↩
, "Physical Size can't be detected"↩
, "Zeros Tail Is Allowed"↩
, "Tail Size"↩
, "Embedded Stub Size"↩
, "Link"↩
, "Hard Link"↩
, "iNode"↩
, "Stream ID"↩
, "Read-only"↩
, "Out Name"↩
, "Copy Link"↩
};↩
↩
static const char kEmptyAttribChar = '.';↩
↩
static const char * const kListing = "Listing archive: ";↩
↩
static const char * const kString_Files = "files";↩
static const char * const kString_Dirs = "folders";↩
static const char * const kString_AltStreams = "alternate streams";↩
static const char * const kString_Streams = "streams";↩
↩
static const char * const kError = "ERROR: ";↩
↩
static void GetAttribString(UInt32 wa, bool isDir, bool allAttribs, char *s)↩
{↩
if (isDir)↩
wa |= FILE_ATTRIBUTE_DIRECTORY;↩
if (allAttribs)↩
{↩
ConvertWinAttribToString(s, wa);↩
return;↩
}↩
s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0) ? 'D': kEmptyAttribChar;↩
s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar;↩
s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar;↩
s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar;↩
s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar;↩
s[5] = 0;↩
}↩
↩
enum EAdjustment↩
{↩
kLeft,↩
kCenter,↩
kRight↩
};↩
↩
struct CFieldInfo↩
{↩
PROPID PropID;↩
bool IsRawProp;↩
UString NameU;↩
AString NameA;↩
EAdjustment TitleAdjustment;↩
EAdjustment TextAdjustment;↩
unsigned PrefixSpacesWidth;↩
unsigned Width;↩
};↩
↩
struct CFieldInfoInit↩
{↩
PROPID PropID;↩
const char *Name;↩
EAdjustment TitleAdjustment;↩
EAdjustment TextAdjustment;↩
unsigned PrefixSpacesWidth;↩
unsigned Width;↩
};↩
↩
static const CFieldInfoInit kStandardFieldTable[] =↩
{↩
{ kpidMTime, " Date Time", kLeft, kLeft, 0, 19 },↩
{ kpidAttrib, "Attr", kRight, kCenter, 1, 5 },↩
{ kpidSize, "Size", kRight, kRight, 1, 12 },↩
{ kpidPackSize, "Compressed", kRight, kRight, 1, 12 },↩
{ kpidPath, "Name", kLeft, kLeft, 2, 24 }↩
};↩
↩
const unsigned kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width↩
static const char *g_Spaces =↩
" " ;↩
↩
static void PrintSpaces(unsigned numSpaces)↩
{↩
if (numSpaces > 0 && numSpaces <= kNumSpacesMax)↩
g_StdOut << g_Spaces + (kNumSpacesMax - numSpaces);↩
}↩
↩
static void PrintSpacesToString(char *dest, unsigned numSpaces)↩
{↩
unsigned i;↩
for (i = 0; i < numSpaces; i++)↩
dest[i] = ' ';↩
dest[i] = 0;↩
}↩
↩
// extern int g_CodePage;↩
↩
static void PrintUString(EAdjustment adj, unsigned width, const UString &s, AString &temp)↩
{↩
/*↩
// we don't need multibyte align.↩
int codePage = g_CodePage;↩
if (codePage == -1)↩
codePage = CP_OEMCP;↩
if (codePage == CP_UTF8)↩
ConvertUnicodeToUTF8(s, temp);↩
else↩
UnicodeStringToMultiByte2(temp, s, (UINT)codePage);↩
*/↩
↩
unsigned numSpaces = 0;↩
↩
if (width > s.Len())↩
{↩
numSpaces = width - s.Len();↩
unsigned numLeftSpaces = 0;↩
switch (adj)↩
{↩
case kLeft: numLeftSpaces = 0; break;↩
case kCenter: numLeftSpaces = numSpaces / 2; break;↩
case kRight: numLeftSpaces = numSpaces; break;↩
}↩
PrintSpaces(numLeftSpaces);↩
numSpaces -= numLeftSpaces;↩
}↩
↩
g_StdOut.PrintUString(s, temp);↩
PrintSpaces(numSpaces);↩
}↩
↩
static void PrintString(EAdjustment adj, unsigned width, const char *s)↩
{↩
unsigned numSpaces = 0;↩
unsigned len = (unsigned)strlen(s);↩
↩
if (width > len)↩
{↩
numSpaces = width - len;↩
unsigned numLeftSpaces = 0;↩
switch (adj)↩
{↩
case kLeft: numLeftSpaces = 0; break;↩
case kCenter: numLeftSpaces = numSpaces / 2; break;↩
case kRight: numLeftSpaces = numSpaces; break;↩
}↩
PrintSpaces(numLeftSpaces);↩
numSpaces -= numLeftSpaces;↩
}↩
↩
g_StdOut << s;↩
PrintSpaces(numSpaces);↩
}↩
↩
static void PrintStringToString(char *dest, EAdjustment adj, unsigned width, const char *textString)↩
{↩
unsigned numSpaces = 0;↩
unsigned len = (unsigned)strlen(textString);↩
↩
if (width > len)↩
{↩
numSpaces = width - len;↩
unsigned numLeftSpaces = 0;↩
switch (adj)↩
{↩
case kLeft: numLeftSpaces = 0; break;↩
case kCenter: numLeftSpaces = numSpaces / 2; break;↩
case kRight: numLeftSpaces = numSpaces; break;↩
}↩
PrintSpacesToString(dest, numLeftSpaces);↩
dest += numLeftSpaces;↩
numSpaces -= numLeftSpaces;↩
}↩
↩
memcpy(dest, textString, len);↩
dest += len;↩
PrintSpacesToString(dest, numSpaces);↩
}↩
↩
struct CListUInt64Def↩
{↩
UInt64 Val;↩
bool Def;↩
↩
CListUInt64Def(): Val(0), Def(false) {}↩
void Add(UInt64 v) { Val += v; Def = true; }↩
void Add(const CListUInt64Def &v) { if (v.Def) Add(v.Val); }↩
};↩
↩
struct CListFileTimeDef↩
{↩
FILETIME Val;↩
bool Def;↩
↩
CListFileTimeDef(): Def(false) { Val.dwLowDateTime = 0; Val.dwHighDateTime = 0; }↩
void Update(const CListFileTimeDef &t)↩
{↩
if (t.Def && (!Def || CompareFileTime(&Val, &t.Val) < 0))↩
{↩
Val = t.Val;↩
Def = true;↩
}↩
}↩
};↩
↩
struct CListStat↩
{↩
CListUInt64Def Size;↩
CListUInt64Def PackSize;↩
CListFileTimeDef MTime;↩
UInt64 NumFiles;↩
↩
CListStat(): NumFiles(0) {}↩
void Update(const CListStat &st)↩
{↩
Size.Add(st.Size);↩
PackSize.Add(st.PackSize);↩
MTime.Update(st.MTime);↩
NumFiles += st.NumFiles;↩
}↩
void SetSizeDefIfNoFiles() { if (NumFiles == 0) Size.Def = true; }↩
};↩
↩
struct CListStat2↩
{↩
CListStat MainFiles;↩
CListStat AltStreams;↩
UInt64 NumDirs;↩
↩
CListStat2(): NumDirs(0) {}↩
↩
void Update(const CListStat2 &st)↩
{↩
MainFiles.Update(st.MainFiles);↩
AltStreams.Update(st.AltStreams);↩
NumDirs += st.NumDirs;↩
}↩
const UInt64 GetNumStreams() const { return MainFiles.NumFiles + AltStreams.NumFiles; }↩
CListStat &GetStat(bool altStreamsMode) { return altStreamsMode ? AltStreams : MainFiles; }↩
};↩
↩
class CFieldPrinter↩
{↩
CObjectVector<CFieldInfo> _fields;↩
↩
void AddProp(const wchar_t *name, PROPID propID, bool isRawProp);↩
public:↩
const CArc *Arc;↩
bool TechMode;↩
UString FilePath;↩
AString TempAString;↩
UString TempWString;↩
bool IsDir;↩
↩
AString LinesString;↩
↩
void Clear() { _fields.Clear(); LinesString.Empty(); }↩
void Init(const CFieldInfoInit *standardFieldTable, unsigned numItems);↩
↩
HRESULT AddMainProps(IInArchive *archive);↩
HRESULT AddRawProps(IArchiveGetRawProps *getRawProps);↩
↩
void PrintTitle();↩
void PrintTitleLines();↩
HRESULT PrintItemInfo(UInt32 index, const CListStat &st);↩
void PrintSum(const CListStat &st, UInt64 numDirs, const char *str);↩
void PrintSum(const CListStat2 &stat2);↩
};↩
↩
void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, unsigned numItems)↩
{↩
Clear();↩
for (unsigned i = 0; i < numItems; i++)↩
{↩
CFieldInfo &f = _fields.AddNew();↩
const CFieldInfoInit &fii = standardFieldTable[i];↩
f.PropID = fii.PropID;↩
f.IsRawProp = false;↩
f.NameA = fii.Name;↩
f.TitleAdjustment = fii.TitleAdjustment;↩
f.TextAdjustment = fii.TextAdjustment;↩
f.PrefixSpacesWidth = fii.PrefixSpacesWidth;↩
f.Width = fii.Width;↩
↩
unsigned k;↩
for (k = 0; k < fii.PrefixSpacesWidth; k++)↩
LinesString.Add_Space();↩
for (k = 0; k < fii.Width; k++)↩
LinesString += '-';↩
}↩
}↩
↩
static void GetPropName(PROPID propID, const wchar_t *name, AString &nameA, UString &nameU)↩
{↩
if (propID < ARRAY_SIZE(kPropIdToName))↩
{↩
nameA = kPropIdToName[propID];↩
return;↩
}↩
if (name)↩
nameU = name;↩
else↩
{↩
nameA.Empty();↩
nameA.Add_UInt32(propID);↩
}↩
}↩
↩
void CFieldPrinter::AddProp(const wchar_t *name, PROPID propID, bool isRawProp)↩
{↩
CFieldInfo f;↩
f.PropID = propID;↩
f.IsRawProp = isRawProp;↩
GetPropName(propID, name, f.NameA, f.NameU);↩
f.NameU += " = ";↩
if (!f.NameA.IsEmpty())↩
f.NameA += " = ";↩
else↩
{↩
const UString &s = f.NameU;↩
AString sA;↩
unsigned i;↩
for (i = 0; i < s.Len(); i++)↩
{↩
wchar_t c = s[i];↩
if (c >= 0x80)↩
break;↩
sA += (char)c;↩
}↩
if (i == s.Len())↩
f.NameA = sA;↩
}↩
_fields.Add(f);↩
}↩
↩
HRESULT CFieldPrinter::AddMainProps(IInArchive *archive)↩
{↩
UInt32 numProps;↩
RINOK(archive->GetNumberOfProperties(&numProps));↩
for (UInt32 i = 0; i < numProps; i++)↩
{↩
CMyComBSTR name;↩
PROPID propID;↩
VARTYPE vt;↩
RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt));↩
AddProp(name, propID, false);↩
}↩
return S_OK;↩
}↩
↩
HRESULT CFieldPrinter::AddRawProps(IArchiveGetRawProps *getRawProps)↩
{↩
UInt32 numProps;↩
RINOK(getRawProps->GetNumRawProps(&numProps));↩
for (UInt32 i = 0; i < numProps; i++)↩
{↩
CMyComBSTR name;↩
PROPID propID;↩
RINOK(getRawProps->GetRawPropInfo(i, &name, &propID));↩
AddProp(name, propID, true);↩
}↩
return S_OK;↩
}↩
↩
void CFieldPrinter::PrintTitle()↩
{↩
FOR_VECTOR (i, _fields)↩
{↩
const CFieldInfo &f = _fields[i];↩
PrintSpaces(f.PrefixSpacesWidth);↩
PrintString(f.TitleAdjustment, ((f.PropID == kpidPath) ? 0: f.Width), f.NameA);↩
}↩
}↩
↩
void CFieldPrinter::PrintTitleLines()↩
{↩
g_StdOut << LinesString;↩
}↩
↩
static void PrintTime(char *dest, const FILETIME *ft)↩
{↩
*dest = 0;↩
if (ft->dwLowDateTime == 0 && ft->dwHighDateTime == 0)↩
return;↩
ConvertUtcFileTimeToString(*ft, dest, kTimestampPrintLevel_SEC);↩
}↩
↩
#ifndef _SFX↩
↩
static inline char GetHex(Byte value)↩
{↩
return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));↩
}↩
↩
static void HexToString(char *dest, const Byte *data, UInt32 size)↩
{↩
for (UInt32 i = 0; i < size; i++)↩
{↩
Byte b = data[i];↩
dest[0] = GetHex((Byte)((b >> 4) & 0xF));↩
dest[1] = GetHex((Byte)(b & 0xF));↩
dest += 2;↩
}↩
*dest = 0;↩
}↩
↩
#endif↩
↩
#define MY_ENDL endl↩
↩
HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st)↩
{↩
char temp[128];↩
size_t tempPos = 0;↩
↩
bool techMode = this->TechMode;↩
/*↩
if (techMode)↩
{↩
g_StdOut << "Index = ";↩
g_StdOut << (UInt64)index;↩
g_StdOut << endl;↩
}↩
*/↩
FOR_VECTOR (i, _fields)↩
{↩
const CFieldInfo &f = _fields[i];↩
↩
if (!techMode)↩
{↩
PrintSpacesToString(temp + tempPos, f.PrefixSpacesWidth);↩
tempPos += f.PrefixSpacesWidth;↩
}↩
↩
if (techMode)↩
{↩
if (!f.NameA.IsEmpty())↩
g_StdOut << f.NameA;↩
else↩
g_StdOut << f.NameU;↩
}↩
↩
if (f.PropID == kpidPath)↩
{↩
if (!techMode)↩
g_StdOut << temp;↩
g_StdOut.NormalizePrint_UString(FilePath, TempWString, TempAString);↩
if (techMode)↩
g_StdOut << MY_ENDL;↩
continue;↩
}↩
↩
const unsigned width = f.Width;↩
↩
if (f.IsRawProp)↩
{↩
#ifndef _SFX↩
↩
const void *data;↩
UInt32 dataSize;↩
UInt32 propType;↩
RINOK(Arc->GetRawProps->GetRawProp(index, f.PropID, &data, &dataSize, &propType));↩
↩
if (dataSize != 0)↩
{↩
bool needPrint = true;↩
↩
if (f.PropID == kpidNtSecure)↩
{↩
if (propType != NPropDataType::kRaw)↩
return E_FAIL;↩
#ifndef _SFX↩
ConvertNtSecureToString((const Byte *)data, dataSize, TempAString);↩
g_StdOut << TempAString;↩
needPrint = false;↩
#endif↩
}↩
else if (f.PropID == kpidNtReparse)↩
{↩
UString s;↩
if (ConvertNtReparseToString((const Byte *)data, dataSize, s))↩
{↩
needPrint = false;↩
g_StdOut.PrintUString(s, TempAString);↩
}↩
}↩
↩
if (needPrint)↩
{↩
if (propType != NPropDataType::kRaw)↩
return E_FAIL;↩
↩
const UInt32 kMaxDataSize = 64;↩
↩
if (dataSize > kMaxDataSize)↩
{↩
g_StdOut << "data:";↩
g_StdOut << dataSize;↩
}↩
else↩
{↩
char hexStr[kMaxDataSize * 2 + 4];↩
HexToString(hexStr, (const Byte *)data, dataSize);↩
g_StdOut << hexStr;↩
}↩
}↩
}↩
↩
#endif↩
}↩
else↩
{↩
CPropVariant prop;↩
switch (f.PropID)↩
{↩
case kpidSize: if (st.Size.Def) prop = st.Size.Val; break;↩
case kpidPackSize: if (st.PackSize.Def) prop = st.PackSize.Val; break;↩
case kpidMTime: if (st.MTime.Def) prop = st.MTime.Val; break;↩
default:↩
RINOK(Arc->Archive->GetProperty(index, f.PropID, &prop));↩
}↩
if (f.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4))↩
{↩
GetAttribString((prop.vt == VT_EMPTY) ? 0 : prop.ulVal, IsDir, techMode, temp + tempPos);↩
if (techMode)↩
g_StdOut << temp + tempPos;↩
else↩
tempPos += strlen(temp + tempPos);↩
}↩
else if (prop.vt == VT_EMPTY)↩
{↩
if (!techMode)↩
{↩
PrintSpacesToString(temp + tempPos, width);↩
tempPos += width;↩
}↩
}↩
else if (prop.vt == VT_FILETIME)↩
{↩
PrintTime(temp + tempPos, &prop.filetime);↩
if (techMode)↩
g_StdOut << temp + tempPos;↩
else↩
{↩
size_t len = strlen(temp + tempPos);↩
tempPos += len;↩
if (len < (unsigned)f.Width)↩
{↩
len = f.Width - len;↩
PrintSpacesToString(temp + tempPos, (unsigned)len);↩
tempPos += len;↩
}↩
}↩
}↩
else if (prop.vt == VT_BSTR)↩
{↩
TempWString.SetFromBstr(prop.bstrVal);↩
// do we need multi-line support here ?↩
g_StdOut.Normalize_UString(TempWString);↩
if (techMode)↩
{↩
g_StdOut.PrintUString(TempWString, TempAString);↩
}↩
else↩
PrintUString(f.TextAdjustment, width, TempWString, TempAString);↩
}↩
else↩
{↩
char s[64];↩
ConvertPropertyToShortString2(s, prop, f.PropID);↩
if (techMode)↩
g_StdOut << s;↩
else↩
{↩
PrintStringToString(temp + tempPos, f.TextAdjustment, width, s);↩
tempPos += strlen(temp + tempPos);↩
}↩
}↩
}↩
if (techMode)↩
g_StdOut << MY_ENDL;↩
}↩
g_StdOut << MY_ENDL;↩
return S_OK;↩
}↩
↩
static void PrintNumber(EAdjustment adj, unsigned width, const CListUInt64Def &value)↩
{↩
char s[32];↩
s[0] = 0;↩
if (value.Def)↩
ConvertUInt64ToString(value.Val, s);↩
PrintString(adj, width, s);↩
}↩
↩
void Print_UInt64_and_String(AString &s, UInt64 val, const char *name);↩
↩
void CFieldPrinter::PrintSum(const CListStat &st, UInt64 numDirs, const char *str)↩
{↩
FOR_VECTOR (i, _fields)↩
{↩
const CFieldInfo &f = _fields[i];↩
PrintSpaces(f.PrefixSpacesWidth);↩
if (f.PropID == kpidSize)↩
PrintNumber(f.TextAdjustment, f.Width, st.Size);↩
else if (f.PropID == kpidPackSize)↩
PrintNumber(f.TextAdjustment, f.Width, st.PackSize);↩
else if (f.PropID == kpidMTime)↩
{↩
char s[64];↩
s[0] = 0;↩
if (st.MTime.Def)↩
PrintTime(s, &st.MTime.Val);↩
PrintString(f.TextAdjustment, f.Width, s);↩
}↩
else if (f.PropID == kpidPath)↩
{↩
AString s;↩
Print_UInt64_and_String(s, st.NumFiles, str);↩
if (numDirs != 0)↩
{↩
s += ", ";↩
Print_UInt64_and_String(s, numDirs, kString_Dirs);↩
}↩
PrintString(f.TextAdjustment, 0, s);↩
}↩
else↩
PrintString(f.TextAdjustment, f.Width, "");↩
}↩
g_StdOut << endl;↩
}↩
↩
void CFieldPrinter::PrintSum(const CListStat2 &stat2)↩
{↩
PrintSum(stat2.MainFiles, stat2.NumDirs, kString_Files);↩
if (stat2.AltStreams.NumFiles != 0)↩
{↩
PrintSum(stat2.AltStreams, 0, kString_AltStreams);;↩
CListStat st = stat2.MainFiles;↩
st.Update(stat2.AltStreams);↩
PrintSum(st, 0, kString_Streams);↩
}↩
}↩
↩
static HRESULT GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, CListUInt64Def &value)↩
{↩
value.Val = 0;↩
value.Def = false;↩
CPropVariant prop;↩
RINOK(archive->GetProperty(index, propID, &prop));↩
value.Def = ConvertPropVariantToUInt64(prop, value.Val);↩
return S_OK;↩
}↩
↩
static HRESULT GetItemMTime(IInArchive *archive, UInt32 index, CListFileTimeDef &t)↩
{↩
t.Val.dwLowDateTime = 0;↩
t.Val.dwHighDateTime = 0;↩
t.Def = false;↩
CPropVariant prop;↩
RINOK(archive->GetProperty(index, kpidMTime, &prop));↩
if (prop.vt == VT_FILETIME)↩
{↩
t.Val = prop.filetime;↩
t.Def = true;↩
}↩
else if (prop.vt != VT_EMPTY)↩
return E_FAIL;↩
return S_OK;↩
}↩
↩
static void PrintPropNameAndNumber(CStdOutStream &so, const char *name, UInt64 val)↩
{↩
so << name << ": " << val << endl;↩
}↩
↩
static void PrintPropName_and_Eq(CStdOutStream &so, PROPID propID)↩
{↩
const char *s;↩
char temp[16];↩
if (propID < ARRAY_SIZE(kPropIdToName))↩
s = kPropIdToName[propID];↩
else↩
{↩
ConvertUInt32ToString(propID, temp);↩
s = temp;↩
}↩
so << s << " = ";↩
}↩
↩
static void PrintPropNameAndNumber(CStdOutStream &so, PROPID propID, UInt64 val)↩
{↩
PrintPropName_and_Eq(so, propID);↩
so << val << endl;↩
}↩
↩
static void PrintPropNameAndNumber_Signed(CStdOutStream &so, PROPID propID, Int64 val)↩
{↩
PrintPropName_and_Eq(so, propID);↩
so << val << endl;↩
}↩
↩
↩
static void UString_Replace_CRLF_to_LF(UString &s)↩
{↩
// s.Replace(L"\r\n", L"\n");↩
wchar_t *src = s.GetBuf();↩
wchar_t *dest = src;↩
for (;;)↩
{↩
wchar_t c = *src++;↩
if (c == 0)↩
break;↩
if (c == '\r' && *src == '\n')↩
{↩
src++;↩
c = '\n';↩
}↩
*dest++ = c;↩
}↩
s.ReleaseBuf_SetEnd((unsigned)(dest - s.GetBuf()));↩
}↩
↩
↩
static void PrintPropVal_MultiLine(CStdOutStream &so, const wchar_t *val)↩
{↩
UString s = val;↩
if (s.Find(L'\n') >= 0)↩
{↩
so << endl;↩
so << "{";↩
so << endl;↩
UString_Replace_CRLF_to_LF(s);↩
so.Normalize_UString__LF_Allowed(s);↩
so << s;↩
so << endl;↩
so << "}";↩
}↩
else↩
{↩
so.Normalize_UString(s);↩
so << s;↩
}↩
so << endl;↩
}↩
↩
↩
static void PrintPropPair(CStdOutStream &so, const char *name, const wchar_t *val, bool multiLine)↩
{↩
so << name << " = ";↩
if (multiLine)↩
{↩
PrintPropVal_MultiLine(so, val);↩
return;↩
}↩
UString s = val;↩
so.Normalize_UString(s);↩
so << s;↩
so << endl;↩
}↩
↩
↩
static void PrintPropertyPair2(CStdOutStream &so, PROPID propID, const wchar_t *name, const CPropVariant &prop)↩
{↩
UString s;↩
ConvertPropertyToString2(s, prop, propID);↩
if (!s.IsEmpty())↩
{↩
AString nameA;↩
UString nameU;↩
GetPropName(propID, name, nameA, nameU);↩
if (!nameA.IsEmpty())↩
so << nameA;↩
else↩
so << nameU;↩
so << " = ";↩
PrintPropVal_MultiLine(so, s);↩
}↩
}↩
↩
static HRESULT PrintArcProp(CStdOutStream &so, IInArchive *archive, PROPID propID, const wchar_t *name)↩
{↩
CPropVariant prop;↩
RINOK(archive->GetArchiveProperty(propID, &prop));↩
PrintPropertyPair2(so, propID, name, prop);↩
return S_OK;↩
}↩
↩
static void PrintArcTypeError(CStdOutStream &so, const UString &type, bool isWarning)↩
{↩
so << "Open " << (isWarning ? "WARNING" : "ERROR")↩
<< ": Can not open the file as ["↩
<< type↩
<< "] archive"↩
<< endl;↩
}↩
↩
int Find_FileName_InSortedVector(const UStringVector &fileName, const UString& name);↩
↩
void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags);↩
↩
static void ErrorInfo_Print(CStdOutStream &so, const CArcErrorInfo &er)↩
{↩
PrintErrorFlags(so, "ERRORS:", er.GetErrorFlags());↩
if (!er.ErrorMessage.IsEmpty())↩
PrintPropPair(so, "ERROR", er.ErrorMessage, true);↩
↩
PrintErrorFlags(so, "WARNINGS:", er.GetWarningFlags());↩
if (!er.WarningMessage.IsEmpty())↩
PrintPropPair(so, "WARNING", er.WarningMessage, true);↩
}↩
↩
HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink)↩
{↩
FOR_VECTOR (r, arcLink.Arcs)↩
{↩
const CArc &arc = arcLink.Arcs[r];↩
const CArcErrorInfo &er = arc.ErrorInfo;↩
↩
so << "--\n";↩
PrintPropPair(so, "Path", arc.Path, false);↩
if (er.ErrorFormatIndex >= 0)↩
{↩
if (er.ErrorFormatIndex == arc.FormatIndex)↩
so << "Warning: The archive is open with offset" << endl;↩
else↩
PrintArcTypeError(so, codecs->GetFormatNamePtr(er.ErrorFormatIndex), true);↩
}↩
PrintPropPair(so, "Type", codecs->GetFormatNamePtr(arc.FormatIndex), false);↩
↩
ErrorInfo_Print(so, er);↩
↩
Int64 offset = arc.GetGlobalOffset();↩
if (offset != 0)↩
PrintPropNameAndNumber_Signed(so, kpidOffset, offset);↩
IInArchive *archive = arc.Archive;↩
RINOK(PrintArcProp(so, archive, kpidPhySize, NULL));↩
if (er.TailSize != 0)↩
PrintPropNameAndNumber(so, kpidTailSize, er.TailSize);↩
{↩
UInt32 numProps;↩
RINOK(archive->GetNumberOfArchiveProperties(&numProps));↩
↩
for (UInt32 j = 0; j < numProps; j++)↩
{↩
CMyComBSTR name;↩
PROPID propID;↩
VARTYPE vt;↩
RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt));↩
RINOK(PrintArcProp(so, archive, propID, name));↩
}↩
}↩
↩
if (r != arcLink.Arcs.Size() - 1)↩
{↩
UInt32 numProps;↩
so << "----\n";↩
if (archive->GetNumberOfProperties(&numProps) == S_OK)↩
{↩
UInt32 mainIndex = arcLink.Arcs[r + 1].SubfileIndex;↩
for (UInt32 j = 0; j < numProps; j++)↩
{↩
CMyComBSTR name;↩
PROPID propID;↩
VARTYPE vt;↩
RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt));↩
CPropVariant prop;↩
RINOK(archive->GetProperty(mainIndex, propID, &prop));↩
PrintPropertyPair2(so, propID, name, prop);↩
}↩
}↩
}↩
}↩
return S_OK;↩
}↩
↩
HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink)↩
{↩
#ifndef _NO_CRYPTO↩
if (arcLink.PasswordWasAsked)↩
so << "Can not open encrypted archive. Wrong password?";↩
else↩
#endif↩
{↩
if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)↩
{↩
so.NormalizePrint_UString(arcLink.NonOpen_ArcPath);↩
so << endl;↩
PrintArcTypeError(so, codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);↩
}↩
else↩
so << "Can not open the file as archive";↩
}↩
↩
so << endl;↩
so << endl;↩
ErrorInfo_Print(so, arcLink.NonOpen_ErrorInfo);↩
↩
return S_OK;↩
}↩
↩
bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);↩
↩
HRESULT ListArchives(CCodecs *codecs,↩
const CObjectVector<COpenType> &types,↩
const CIntVector &excludedFormats,↩
bool stdInMode,↩
UStringVector &arcPaths, UStringVector &arcPathsFull,↩
bool processAltStreams, bool showAltStreams,↩
const NWildcard::CCensorNode &wildcardCensor,↩
bool enableHeaders, bool techMode,↩
#ifndef _NO_CRYPTO↩
bool &passwordEnabled, UString &password,↩
#endif↩
#ifndef _SFX↩
const CObjectVector<CProperty> *props,↩
#endif↩
UInt64 &numErrors,↩
UInt64 &numWarnings)↩
{↩
bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();↩
↩
numErrors = 0;↩
numWarnings = 0;↩
↩
CFieldPrinter fp;↩
if (!techMode)↩
fp.Init(kStandardFieldTable, ARRAY_SIZE(kStandardFieldTable));↩
↩
CListStat2 stat2total;↩
↩
CBoolArr skipArcs(arcPaths.Size());↩
unsigned arcIndex;↩
for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++)↩
skipArcs[arcIndex] = false;↩
UInt64 numVolumes = 0;↩
UInt64 numArcs = 0;↩
UInt64 totalArcSizes = 0;↩
↩
HRESULT lastError = 0;↩
↩
for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++)↩
{↩
if (skipArcs[arcIndex])↩
continue;↩
const UString &arcPath = arcPaths[arcIndex];↩
UInt64 arcPackSize = 0;↩
↩
if (!stdInMode)↩
{↩
NFile::NFind::CFileInfo fi;↩
if (!fi.Find(us2fs(arcPath)))↩
{↩
DWORD errorCode = GetLastError();↩
if (errorCode == 0)↩
errorCode = ERROR_FILE_NOT_FOUND;↩
lastError = HRESULT_FROM_WIN32(lastError);;↩
g_StdOut.Flush();↩
*g_ErrStream << endl << kError << NError::MyFormatMessage(errorCode) << endl;↩
g_ErrStream->NormalizePrint_UString(arcPath);↩
*g_ErrStream << endl << endl;↩
numErrors++;↩
continue;↩
}↩
if (fi.IsDir())↩
{↩
g_StdOut.Flush();↩
*g_ErrStream << endl << kError;↩
g_ErrStream->NormalizePrint_UString(arcPath);↩
*g_ErrStream << " is not a file" << endl << endl;↩
numErrors++;↩
continue;↩
}↩
arcPackSize = fi.Size;↩
totalArcSizes += arcPackSize;↩
}↩
↩
CArchiveLink arcLink;↩
↩
COpenCallbackConsole openCallback;↩
openCallback.Init(&g_StdOut, g_ErrStream, NULL);↩
↩
#ifndef _NO_CRYPTO↩
↩
openCallback.PasswordIsDefined = passwordEnabled;↩
openCallback.Password = password;↩
↩
#endif↩
↩
/*↩
CObjectVector<COptionalOpenProperties> optPropsVector;↩
COptionalOpenProperties &optProps = optPropsVector.AddNew();↩
optProps.Props = *props;↩
*/↩
↩
COpenOptions options;↩
#ifndef _SFX↩
options.props = props;↩
#endif↩
options.codecs = codecs;↩
options.types = &types;↩
options.excludedFormats = &excludedFormats;↩
options.stdInMode = stdInMode;↩
options.stream = NULL;↩
options.filePath = arcPath;↩
↩
if (enableHeaders)↩
{↩
g_StdOut << endl << kListing;↩
g_StdOut.NormalizePrint_UString(arcPath);↩
g_StdOut << endl << endl;↩
}↩
↩
HRESULT result = arcLink.Open_Strict(options, &openCallback);↩
↩
if (result != S_OK)↩
{↩
if (result == E_ABORT)↩
return result;↩
g_StdOut.Flush();↩
*g_ErrStream << endl << kError;↩
g_ErrStream->NormalizePrint_UString(arcPath);↩
*g_ErrStream << " : ";↩
if (result == S_FALSE)↩
{↩
Print_OpenArchive_Error(*g_ErrStream, codecs, arcLink);↩
}↩
else↩
{↩
lastError = result;↩
*g_ErrStream << "opening : ";↩
if (result == E_OUTOFMEMORY)↩
*g_ErrStream << "Can't allocate required memory";↩
else↩
*g_ErrStream << NError::MyFormatMessage(result);↩
}↩
*g_ErrStream << endl;↩
numErrors++;↩
continue;↩
}↩
↩
{↩
FOR_VECTOR (r, arcLink.Arcs)↩
{↩
const CArcErrorInfo &arc = arcLink.Arcs[r].ErrorInfo;↩
if (!arc.WarningMessage.IsEmpty())↩
numWarnings++;↩
if (arc.AreThereWarnings())↩
numWarnings++;↩
if (arc.ErrorFormatIndex >= 0)↩
numWarnings++;↩
if (arc.AreThereErrors())↩
{↩
numErrors++;↩
// break;↩
}↩
if (!arc.ErrorMessage.IsEmpty())↩
numErrors++;↩
}↩
}↩
↩
numArcs++;↩
numVolumes++;↩
↩
if (!stdInMode)↩
{↩
numVolumes += arcLink.VolumePaths.Size();↩
totalArcSizes += arcLink.VolumesSize;↩
FOR_VECTOR (v, arcLink.VolumePaths)↩
{↩
int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]);↩
if (index >= 0 && (unsigned)index > arcIndex)↩
skipArcs[(unsigned)index] = true;↩
}↩
}↩
↩
↩
if (enableHeaders)↩
{↩
RINOK(Print_OpenArchive_Props(g_StdOut, codecs, arcLink));↩
↩
g_StdOut << endl;↩
if (techMode)↩
g_StdOut << "----------\n";↩
}↩
↩
if (enableHeaders && !techMode)↩
{↩
fp.PrintTitle();↩
g_StdOut << endl;↩
fp.PrintTitleLines();↩
g_StdOut << endl;↩
}↩
↩
const CArc &arc = arcLink.Arcs.Back();↩
fp.Arc = &arc;↩
fp.TechMode = techMode;↩
IInArchive *archive = arc.Archive;↩
if (techMode)↩
{↩
fp.Clear();↩
RINOK(fp.AddMainProps(archive));↩
if (arc.GetRawProps)↩
{↩
RINOK(fp.AddRawProps(arc.GetRawProps));↩
}↩
}↩
↩
CListStat2 stat2;↩
↩
UInt32 numItems;↩
RINOK(archive->GetNumberOfItems(&numItems));↩
↩
CReadArcItem item;↩
UStringVector pathParts;↩
↩
for (UInt32 i = 0; i < numItems; i++)↩
{↩
if (NConsoleClose::TestBreakSignal())↩
return E_ABORT;↩
↩
HRESULT res = arc.GetItemPath2(i, fp.FilePath);↩
↩
if (stdInMode && res == E_INVALIDARG)↩
break;↩
RINOK(res);↩
↩
if (arc.Ask_Aux)↩
{↩
bool isAux;↩
RINOK(Archive_IsItem_Aux(archive, i, isAux));↩
if (isAux)↩
continue;↩
}↩
↩
bool isAltStream = false;↩
if (arc.Ask_AltStream)↩
{↩
RINOK(Archive_IsItem_AltStream(archive, i, isAltStream));↩
if (isAltStream && !processAltStreams)↩
continue;↩
}↩
↩
RINOK(Archive_IsItem_Dir(archive, i, fp.IsDir));↩
↩
if (!allFilesAreAllowed)↩
{↩
if (isAltStream)↩
{↩
RINOK(arc.GetItem(i, item));↩
if (!CensorNode_CheckPath(wildcardCensor, item))↩
continue;↩
}↩
else↩
{↩
SplitPathToParts(fp.FilePath, pathParts);;↩
bool include;↩
if (!wildcardCensor.CheckPathVect(pathParts, !fp.IsDir, include))↩
continue;↩
if (!include)↩
continue;↩
}↩
}↩
↩
CListStat st;↩
↩
RINOK(GetUInt64Value(archive, i, kpidSize, st.Size));↩
RINOK(GetUInt64Value(archive, i, kpidPackSize, st.PackSize));↩
RINOK(GetItemMTime(archive, i, st.MTime));↩
↩
if (fp.IsDir)↩
stat2.NumDirs++;↩
else↩
st.NumFiles = 1;↩
stat2.GetStat(isAltStream).Update(st);↩
↩
if (isAltStream && !showAltStreams)↩
continue;↩
RINOK(fp.PrintItemInfo(i, st));↩
}↩
↩
UInt64 numStreams = stat2.GetNumStreams();↩
if (!stdInMode↩
&& !stat2.MainFiles.PackSize.Def↩
&& !stat2.AltStreams.PackSize.Def)↩
{↩
if (arcLink.VolumePaths.Size() != 0)↩
arcPackSize += arcLink.VolumesSize;↩
stat2.MainFiles.PackSize.Add((numStreams == 0) ? 0 : arcPackSize);↩
}↩
↩
stat2.MainFiles.SetSizeDefIfNoFiles();↩
stat2.AltStreams.SetSizeDefIfNoFiles();↩
↩
if (enableHeaders && !techMode)↩
{↩
fp.PrintTitleLines();↩
g_StdOut << endl;↩
fp.PrintSum(stat2);↩
}↩
↩
if (enableHeaders)↩
{↩
if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)↩
{↩
g_StdOut << "----------\n";↩
PrintPropPair(g_StdOut, "Path", arcLink.NonOpen_ArcPath, false);↩
PrintArcTypeError(g_StdOut, codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);↩
}↩
}↩
↩
stat2total.Update(stat2);↩
↩
g_StdOut.Flush();↩
}↩
↩
if (enableHeaders && !techMode && (arcPaths.Size() > 1 || numVolumes > 1))↩
{↩
g_StdOut << endl;↩
fp.PrintTitleLines();↩
g_StdOut << endl;↩
fp.PrintSum(stat2total);↩
g_StdOut << endl;↩
PrintPropNameAndNumber(g_StdOut, "Archives", numArcs);↩
PrintPropNameAndNumber(g_StdOut, "Volumes", numVolumes);↩
PrintPropNameAndNumber(g_StdOut, "Total archives size", totalArcSizes);↩
}↩
↩
if (numErrors == 1 && lastError != 0)↩
return lastError;↩
↩
return S_OK;↩
}↩