mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-08 12:07:03 -06:00
9.34
This commit is contained in:
committed by
Kornel Lesiński
parent
83f8ddcc5b
commit
f08f4dcc3c
843
CPP/7zip/Archive/RpmHandler.cpp
Executable file → Normal file
843
CPP/7zip/Archive/RpmHandler.cpp
Executable file → Normal file
@@ -4,10 +4,14 @@
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
#include "Common/MyString.h"
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/IntToString.h"
|
||||
#include "../../Common/MyString.h"
|
||||
#include "../../Common/StringConvert.h"
|
||||
#include "../../Common/UTFConvert.h"
|
||||
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "../../Windows/PropVariant.h"
|
||||
#include "../../Windows/TimeUtils.h"
|
||||
|
||||
#include "../Common/LimitedStreams.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
@@ -16,6 +20,8 @@
|
||||
|
||||
#include "../Compress/CopyCoder.h"
|
||||
|
||||
// #define _SHOW_RPM_METADATA
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
#define Get16(p) GetBe16(p)
|
||||
@@ -24,130 +30,144 @@ using namespace NWindows;
|
||||
namespace NArchive {
|
||||
namespace NRpm {
|
||||
|
||||
/* Reference: lib/signature.h of rpm package */
|
||||
#define RPMSIG_NONE 0 /* Do not change! */
|
||||
/* The following types are no longer generated */
|
||||
#define RPMSIG_PGP262_1024 1 /* No longer generated */ /* 256 byte */
|
||||
/* These are the new-style signatures. They are Header structures. */
|
||||
/* Inside them we can put any number of any type of signature we like. */
|
||||
static const unsigned kNameSize = 66;
|
||||
static const unsigned kLeadSize = kNameSize + 30;
|
||||
static const unsigned k_HeaderSig_Size = 16;
|
||||
static const unsigned k_Entry_Size = 16;
|
||||
|
||||
#define RPMSIG_HEADERSIG 5 /* New Header style signature */
|
||||
#define RPMSIG_NONE 0 // Old signature
|
||||
#define RPMSIG_PGP262_1024 1 // Old signature
|
||||
#define RPMSIG_HEADERSIG 5 // New signature
|
||||
|
||||
enum
|
||||
{
|
||||
kRpmType_Bin = 0,
|
||||
kRpmType_Src = 1
|
||||
};
|
||||
|
||||
// There are two sets of TAGs: signature tags and header tags
|
||||
|
||||
// ----- Signature TAGs -----
|
||||
|
||||
#define RPMSIGTAG_SIZE 1000 // Header + Payload size (32bit)
|
||||
|
||||
// ----- Header TAGs -----
|
||||
|
||||
#define RPMTAG_NAME 1000
|
||||
#define RPMTAG_VERSION 1001
|
||||
#define RPMTAG_RELEASE 1002
|
||||
#define RPMTAG_BUILDTIME 1006
|
||||
#define RPMTAG_OS 1021 // string (old version used int?)
|
||||
#define RPMTAG_ARCH 1022 // string (old version used int?)
|
||||
#define RPMTAG_PAYLOADFORMAT 1124
|
||||
#define RPMTAG_PAYLOADCOMPRESSOR 1125
|
||||
// #define RPMTAG_PAYLOADFLAGS 1126
|
||||
|
||||
enum
|
||||
{
|
||||
k_EntryType_NULL,
|
||||
k_EntryType_CHAR,
|
||||
k_EntryType_INT8,
|
||||
k_EntryType_INT16,
|
||||
k_EntryType_INT32,
|
||||
k_EntryType_INT64,
|
||||
k_EntryType_STRING,
|
||||
k_EntryType_BIN,
|
||||
k_EntryType_STRING_ARRAY,
|
||||
k_EntryType_I18NSTRING
|
||||
};
|
||||
|
||||
static const char *k_CPUs[] =
|
||||
{
|
||||
"noarch"
|
||||
, "i386"
|
||||
, "alpha"
|
||||
, "sparc"
|
||||
, "mips"
|
||||
, "ppc"
|
||||
, "m68k"
|
||||
, "sgi"
|
||||
, "rs6000"
|
||||
, "ia64"
|
||||
, "sparc64" // 10 ???
|
||||
, "mipsel"
|
||||
, "arm"
|
||||
, "m68kmint"
|
||||
, "s390"
|
||||
, "s390x"
|
||||
, "ppc64"
|
||||
, "sh"
|
||||
, "xtensa"
|
||||
, "aarch64" // 19
|
||||
};
|
||||
|
||||
static const char *k_OS[] =
|
||||
{
|
||||
"0"
|
||||
, "Linux"
|
||||
, "Irix"
|
||||
, "solaris"
|
||||
, "SunOS"
|
||||
, "AmigaOS" // AIX
|
||||
, "HP-UX"
|
||||
, "osf"
|
||||
, "FreeBSD"
|
||||
, "SCO_SV"
|
||||
, "Irix64"
|
||||
, "NextStep"
|
||||
, "bsdi"
|
||||
, "machten"
|
||||
, "cygwin32-NT"
|
||||
, "cygwin32-95"
|
||||
, "MP_RAS"
|
||||
, "MiNT"
|
||||
, "OS/390"
|
||||
, "VM/ESA"
|
||||
, "Linux/390" // "Linux/ESA"
|
||||
, "Darwin" // "MacOSX" 21
|
||||
};
|
||||
|
||||
const UInt32 kLeadSize = 96;
|
||||
struct CLead
|
||||
{
|
||||
unsigned char Magic[4];
|
||||
unsigned char Major; // not supported ver1, only support 2,3 and lator
|
||||
unsigned char Major;
|
||||
unsigned char Minor;
|
||||
UInt16 Type;
|
||||
UInt16 ArchNum;
|
||||
char Name[66];
|
||||
UInt16 OSNum;
|
||||
UInt16 Cpu;
|
||||
UInt16 Os;
|
||||
UInt16 SignatureType;
|
||||
char Reserved[16]; // pad to 96 bytes -- 8 byte aligned
|
||||
bool MagicCheck() const
|
||||
{ return Magic[0] == 0xed && Magic[1] == 0xab && Magic[2] == 0xee && Magic[3] == 0xdb; };
|
||||
char Name[kNameSize];
|
||||
// char Reserved[16];
|
||||
|
||||
void Parse(const Byte *p)
|
||||
{
|
||||
Major = p[4];
|
||||
Minor = p[5];
|
||||
Type = Get16(p + 6);
|
||||
Cpu= Get16(p + 8);
|
||||
memcpy(Name, p + 10, kNameSize);
|
||||
p += 10 + kNameSize;
|
||||
Os = Get16(p);
|
||||
SignatureType = Get16(p + 2);
|
||||
}
|
||||
|
||||
bool IsSupported() const { return Major >= 3 && Type <= 1; }
|
||||
};
|
||||
|
||||
struct CEntry
|
||||
{
|
||||
UInt32 Tag;
|
||||
UInt32 Type;
|
||||
UInt32 Offset;
|
||||
UInt32 Count;
|
||||
|
||||
const UInt32 kEntryInfoSize = 16;
|
||||
/*
|
||||
struct CEntryInfo
|
||||
{
|
||||
int Tag;
|
||||
int Type;
|
||||
int Offset; // Offset from beginning of data segment, only defined on disk
|
||||
int Count;
|
||||
void Parse(const Byte *p)
|
||||
{
|
||||
Tag = Get32(p + 0);
|
||||
Type = Get32(p + 4);
|
||||
Offset = Get32(p + 8);
|
||||
Count = Get32(p + 12);
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
// case: SignatureType == RPMSIG_HEADERSIG
|
||||
const UInt32 kCSigHeaderSigSize = 16;
|
||||
struct CSigHeaderSig
|
||||
{
|
||||
unsigned char Magic[4];
|
||||
UInt32 Reserved;
|
||||
UInt32 IndexLen; // count of index entries
|
||||
UInt32 DataLen; // number of bytes
|
||||
bool MagicCheck()
|
||||
{ return Magic[0] == 0x8e && Magic[1] == 0xad && Magic[2] == 0xe8 && Magic[3] == 0x01; };
|
||||
UInt32 GetLostHeaderLen()
|
||||
{ return IndexLen * kEntryInfoSize + DataLen; };
|
||||
};
|
||||
|
||||
static HRESULT RedSigHeaderSig(IInStream *inStream, CSigHeaderSig &h)
|
||||
{
|
||||
char dat[kCSigHeaderSigSize];
|
||||
char *cur = dat;
|
||||
RINOK(ReadStream_FALSE(inStream, dat, kCSigHeaderSigSize));
|
||||
memcpy(h.Magic, cur, 4);
|
||||
cur += 4;
|
||||
cur += 4;
|
||||
h.IndexLen = Get32(cur);
|
||||
cur += 4;
|
||||
h.DataLen = Get32(cur);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT OpenArchive(IInStream *inStream)
|
||||
{
|
||||
UInt64 pos;
|
||||
char leadData[kLeadSize];
|
||||
char *cur = leadData;
|
||||
CLead lead;
|
||||
RINOK(ReadStream_FALSE(inStream, leadData, kLeadSize));
|
||||
memcpy(lead.Magic, cur, 4);
|
||||
cur += 4;
|
||||
lead.Major = *cur++;
|
||||
lead.Minor = *cur++;
|
||||
lead.Type = Get16(cur);
|
||||
cur += 2;
|
||||
lead.ArchNum = Get16(cur);
|
||||
cur += 2;
|
||||
memcpy(lead.Name, cur, sizeof(lead.Name));
|
||||
cur += sizeof(lead.Name);
|
||||
lead.OSNum = Get16(cur);
|
||||
cur += 2;
|
||||
lead.SignatureType = Get16(cur);
|
||||
cur += 2;
|
||||
|
||||
if (!lead.MagicCheck() || lead.Major < 3)
|
||||
return S_FALSE;
|
||||
|
||||
CSigHeaderSig sigHeader, header;
|
||||
if (lead.SignatureType == RPMSIG_NONE)
|
||||
{
|
||||
;
|
||||
}
|
||||
else if (lead.SignatureType == RPMSIG_PGP262_1024)
|
||||
{
|
||||
UInt64 pos;
|
||||
RINOK(inStream->Seek(256, STREAM_SEEK_CUR, &pos));
|
||||
}
|
||||
else if (lead.SignatureType == RPMSIG_HEADERSIG)
|
||||
{
|
||||
RINOK(RedSigHeaderSig(inStream, sigHeader));
|
||||
if (!sigHeader.MagicCheck())
|
||||
return S_FALSE;
|
||||
UInt32 len = sigHeader.GetLostHeaderLen();
|
||||
RINOK(inStream->Seek(len, STREAM_SEEK_CUR, &pos));
|
||||
if ((pos % 8) != 0)
|
||||
{
|
||||
RINOK(inStream->Seek((pos / 8 + 1) * 8 - pos,
|
||||
STREAM_SEEK_CUR, &pos));
|
||||
}
|
||||
}
|
||||
else
|
||||
return S_FALSE;
|
||||
|
||||
RINOK(RedSigHeaderSig(inStream, header));
|
||||
if (!header.MagicCheck())
|
||||
return S_FALSE;
|
||||
int headerLen = header.GetLostHeaderLen();
|
||||
if (headerLen == -1)
|
||||
return S_FALSE;
|
||||
RINOK(inStream->Seek(headerLen, STREAM_SEEK_CUR, &pos));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
@@ -155,55 +175,554 @@ class CHandler:
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IInStream> _stream;
|
||||
UInt64 _pos;
|
||||
|
||||
UInt64 _headersSize; // is equal to start offset of payload data
|
||||
UInt64 _payloadSize;
|
||||
UInt64 _size;
|
||||
Byte _sig[4];
|
||||
// _size = _payloadSize, if (_payloadSize_Defined)
|
||||
// _size = (fileSize - _headersSize), if (!_payloadSize_Defined)
|
||||
UInt64 _phySize; // _headersSize + _payloadSize, if (_phySize_Defined)
|
||||
UInt32 _headerPlusPayload_Size;
|
||||
UInt32 _buildTime;
|
||||
|
||||
bool _payloadSize_Defined;
|
||||
bool _phySize_Defined;
|
||||
bool _headerPlusPayload_Size_Defined;
|
||||
bool _time_Defined;
|
||||
|
||||
Byte _payloadSig[6]; // start data of payload
|
||||
|
||||
AString _name; // p7zip
|
||||
AString _version; // 9.20.1
|
||||
AString _release; // 8.1.1
|
||||
AString _arch; // x86_64
|
||||
AString _os; // linux
|
||||
|
||||
AString _format; // cpio
|
||||
AString _compressor; // xz, gzip, bzip2
|
||||
|
||||
CLead _lead;
|
||||
|
||||
#ifdef _SHOW_RPM_METADATA
|
||||
AString _metadata;
|
||||
#endif
|
||||
|
||||
void SetTime(NCOM::CPropVariant &prop) const
|
||||
{
|
||||
if (_time_Defined && _buildTime != 0)
|
||||
{
|
||||
FILETIME ft;
|
||||
if (NTime::UnixTime64ToFileTime(_buildTime, ft))
|
||||
prop = ft;
|
||||
}
|
||||
}
|
||||
|
||||
void SetStringProp(const AString &s, NCOM::CPropVariant &prop) const
|
||||
{
|
||||
UString us;
|
||||
if (!ConvertUTF8ToUnicode(s, us))
|
||||
us = GetUnicodeString(s);
|
||||
if (!us.IsEmpty())
|
||||
prop = us;
|
||||
}
|
||||
|
||||
void AddCPU(AString &s) const;
|
||||
AString GetBaseName() const;
|
||||
void AddSubFileExtension(AString &res) const;
|
||||
|
||||
HRESULT ReadHeader(ISequentialInStream *stream, bool isMainHeader);
|
||||
HRESULT Open2(ISequentialInStream *stream);
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
|
||||
INTERFACE_IInArchive(;)
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
|
||||
};
|
||||
|
||||
STATPROPSTG kProps[] =
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidSize, VT_UI8}
|
||||
kpidHeadersSize,
|
||||
kpidCpu,
|
||||
kpidHostOS,
|
||||
kpidCTime
|
||||
#ifdef _SHOW_RPM_METADATA
|
||||
, kpidComment
|
||||
#endif
|
||||
};
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
kpidPath,
|
||||
kpidSize,
|
||||
kpidCTime
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps_NO_Table
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
void CHandler::AddCPU(AString &s) const
|
||||
{
|
||||
if (!_arch.IsEmpty())
|
||||
s += _arch;
|
||||
else
|
||||
{
|
||||
if (_lead.Type == kRpmType_Bin)
|
||||
{
|
||||
char temp[16];
|
||||
const char *p;
|
||||
if (_lead.Cpu < ARRAY_SIZE(k_CPUs))
|
||||
p = k_CPUs[_lead.Cpu];
|
||||
else
|
||||
{
|
||||
ConvertUInt32ToString(_lead.Cpu, temp);
|
||||
p = temp;
|
||||
}
|
||||
s += p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AString CHandler::GetBaseName() const
|
||||
{
|
||||
AString s;
|
||||
if (!_name.IsEmpty())
|
||||
{
|
||||
s = _name;
|
||||
if (!_version.IsEmpty())
|
||||
{
|
||||
s += '-';
|
||||
s += _version;
|
||||
}
|
||||
if (!_release.IsEmpty())
|
||||
{
|
||||
s += '-';
|
||||
s += _release;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char *p = s.GetBuffer(kNameSize);
|
||||
memcpy(p, _lead.Name, kNameSize);
|
||||
p[kNameSize] = 0;
|
||||
s.ReleaseBuffer();
|
||||
}
|
||||
|
||||
s += '.';
|
||||
if (_lead.Type == kRpmType_Src)
|
||||
s += "src";
|
||||
else
|
||||
AddCPU(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
void CHandler::AddSubFileExtension(AString &res) const
|
||||
{
|
||||
if (!_format.IsEmpty())
|
||||
res += _format;
|
||||
else
|
||||
res += "cpio";
|
||||
res += '.';
|
||||
|
||||
const char *s;
|
||||
|
||||
if (!_compressor.IsEmpty())
|
||||
{
|
||||
s = _compressor;
|
||||
if (_compressor == "bzip2")
|
||||
s = "bz2";
|
||||
else if (_compressor == "gzip")
|
||||
s = "gz";
|
||||
}
|
||||
else
|
||||
{
|
||||
const Byte *p = _payloadSig;
|
||||
if (p[0] == 0x1F && p[1] == 0x8B)
|
||||
s = "gz";
|
||||
else if (p[0] == 0xFD && p[1] == '7' && p[2] == 'z' && p[3] == 'X' && p[4] == 'Z' && p[5] == 0)
|
||||
s = "xz";
|
||||
else if (p[0] == 'B' && p[1] == 'Z' && p[2] == 'h' && p[3] >= '1' && p[3] <= '9')
|
||||
s = "bz2";
|
||||
else
|
||||
s = "lzma";
|
||||
}
|
||||
|
||||
res += s;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
switch(propID) { case kpidMainSubfile: prop = (UInt32)0; break; }
|
||||
switch (propID)
|
||||
{
|
||||
case kpidMainSubfile: prop = (UInt32)0; break;
|
||||
|
||||
case kpidHeadersSize: prop = _headersSize; break;
|
||||
case kpidPhySize: if (_phySize_Defined) prop = _phySize; break;
|
||||
|
||||
case kpidMTime:
|
||||
case kpidCTime:
|
||||
SetTime(prop);
|
||||
break;
|
||||
|
||||
case kpidCpu:
|
||||
{
|
||||
AString s;
|
||||
AddCPU(s);
|
||||
/*
|
||||
if (_lead.Type == kRpmType_Src)
|
||||
s = "src";
|
||||
*/
|
||||
SetStringProp(s, prop);
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidHostOS:
|
||||
{
|
||||
if (!_os.IsEmpty())
|
||||
SetStringProp(_os, prop);
|
||||
else
|
||||
{
|
||||
char temp[16];
|
||||
const char *p;
|
||||
if (_lead.Os < ARRAY_SIZE(k_OS))
|
||||
p = k_OS[_lead.Os];
|
||||
else
|
||||
{
|
||||
ConvertUInt32ToString(_lead.Os, temp);
|
||||
p = temp;
|
||||
}
|
||||
prop = p;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef _SHOW_RPM_METADATA
|
||||
case kpidComment: SetStringProp(_metadata, prop); break;
|
||||
#endif
|
||||
|
||||
case kpidName:
|
||||
{
|
||||
AString s = GetBaseName();
|
||||
s += ".rpm";
|
||||
SetStringProp(s, prop);
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidSize:
|
||||
case kpidPackSize:
|
||||
prop = _size;
|
||||
break;
|
||||
|
||||
case kpidMTime:
|
||||
case kpidCTime:
|
||||
SetTime(prop);
|
||||
break;
|
||||
|
||||
case kpidPath:
|
||||
{
|
||||
AString s = GetBaseName();
|
||||
s += '.';
|
||||
AddSubFileExtension(s);
|
||||
SetStringProp(s, prop);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
case kpidExtension:
|
||||
{
|
||||
prop = GetSubFileExtension();
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback * /* openArchiveCallback */)
|
||||
#ifdef _SHOW_RPM_METADATA
|
||||
static inline char GetHex(unsigned value)
|
||||
{
|
||||
return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
|
||||
}
|
||||
#endif
|
||||
|
||||
HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
|
||||
{
|
||||
UInt32 numEntries;
|
||||
UInt32 dataLen;
|
||||
{
|
||||
char buf[k_HeaderSig_Size];
|
||||
RINOK(ReadStream_FALSE(stream, buf, k_HeaderSig_Size));
|
||||
if (Get32(buf) != 0x8EADE801) // buf[3] = 0x01 - is version
|
||||
return S_FALSE;
|
||||
// reserved = Get32(buf + 4);
|
||||
numEntries = Get32(buf + 8);
|
||||
dataLen = Get32(buf + 12);
|
||||
if (numEntries >= 1 << 24)
|
||||
return S_FALSE;
|
||||
}
|
||||
size_t indexSize = (size_t)numEntries * k_Entry_Size;
|
||||
size_t headerSize = indexSize + dataLen;
|
||||
if (headerSize < dataLen)
|
||||
return S_FALSE;
|
||||
CByteBuffer buffer(headerSize);
|
||||
RINOK(ReadStream_FALSE(stream, buffer, headerSize));
|
||||
|
||||
for (UInt32 i = 0; i < numEntries; i++)
|
||||
{
|
||||
CEntry entry;
|
||||
|
||||
entry.Parse(buffer + (size_t)i * k_Entry_Size);
|
||||
if (entry.Offset > dataLen)
|
||||
return S_FALSE;
|
||||
|
||||
const Byte *p = buffer + indexSize + entry.Offset;
|
||||
size_t rem = dataLen - entry.Offset;
|
||||
|
||||
if (!isMainHeader)
|
||||
{
|
||||
if (entry.Tag == RPMSIGTAG_SIZE &&
|
||||
entry.Type == k_EntryType_INT32)
|
||||
{
|
||||
if (rem < 4 || entry.Count != 1)
|
||||
return S_FALSE;
|
||||
_headerPlusPayload_Size = Get32(p);
|
||||
_headerPlusPayload_Size_Defined = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _SHOW_RPM_METADATA
|
||||
{
|
||||
char temp[16];
|
||||
ConvertUInt32ToString(entry.Tag, temp);
|
||||
|
||||
_metadata += temp;
|
||||
_metadata += ": ";
|
||||
}
|
||||
#endif
|
||||
|
||||
if (entry.Type == k_EntryType_STRING)
|
||||
{
|
||||
if (entry.Count != 1)
|
||||
return S_FALSE;
|
||||
size_t j;
|
||||
for (j = 0; j < rem && p[j] != 0; j++);
|
||||
if (j == rem)
|
||||
return S_FALSE;
|
||||
AString s = (const char *)p;
|
||||
switch (entry.Tag)
|
||||
{
|
||||
case RPMTAG_NAME: _name = s; break;
|
||||
case RPMTAG_VERSION: _version = s; break;
|
||||
case RPMTAG_RELEASE: _release = s; break;
|
||||
case RPMTAG_ARCH: _arch = s; break;
|
||||
case RPMTAG_OS: _os = s; break;
|
||||
case RPMTAG_PAYLOADFORMAT: _format = s; break;
|
||||
case RPMTAG_PAYLOADCOMPRESSOR: _compressor = s; break;
|
||||
}
|
||||
|
||||
#ifdef _SHOW_RPM_METADATA
|
||||
_metadata += s;
|
||||
#endif
|
||||
}
|
||||
else if (entry.Type == k_EntryType_INT32)
|
||||
{
|
||||
if (rem / 4 < entry.Count)
|
||||
return S_FALSE;
|
||||
if (entry.Tag == RPMTAG_BUILDTIME)
|
||||
{
|
||||
if (entry.Count != 1)
|
||||
return S_FALSE;
|
||||
_buildTime = Get32(p);
|
||||
_time_Defined = true;
|
||||
}
|
||||
|
||||
#ifdef _SHOW_RPM_METADATA
|
||||
for (UInt32 t = 0; t < entry.Count; t++)
|
||||
{
|
||||
if (t != 0)
|
||||
_metadata += ' ';
|
||||
char temp[16];
|
||||
ConvertUInt32ToString(Get32(p + t * 4), temp);
|
||||
_metadata += temp;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _SHOW_RPM_METADATA
|
||||
|
||||
else if (
|
||||
entry.Type == k_EntryType_STRING_ARRAY ||
|
||||
entry.Type == k_EntryType_I18NSTRING)
|
||||
{
|
||||
const Byte *p2 = p;
|
||||
size_t rem2 = rem;
|
||||
for (UInt32 t = 0; t < entry.Count; t++)
|
||||
{
|
||||
if (rem2 == 0)
|
||||
return S_FALSE;
|
||||
if (t != 0)
|
||||
_metadata += '\n';
|
||||
size_t j;
|
||||
for (j = 0; j < rem2 && p2[j] != 0; j++);
|
||||
if (j == rem2)
|
||||
return S_FALSE;
|
||||
_metadata += (const char *)p2;
|
||||
j++;
|
||||
p2 += j;
|
||||
rem2 -= j;
|
||||
}
|
||||
}
|
||||
else if (entry.Type == k_EntryType_INT16)
|
||||
{
|
||||
if (rem / 2 < entry.Count)
|
||||
return S_FALSE;
|
||||
for (UInt32 t = 0; t < entry.Count; t++)
|
||||
{
|
||||
if (t != 0)
|
||||
_metadata += ' ';
|
||||
char temp[16];
|
||||
ConvertUInt32ToString(Get16(p + t * 2), temp);
|
||||
_metadata += temp;
|
||||
}
|
||||
}
|
||||
else if (entry.Type == k_EntryType_BIN)
|
||||
{
|
||||
if (rem < entry.Count)
|
||||
return S_FALSE;
|
||||
for (UInt32 t = 0; t < entry.Count; t++)
|
||||
{
|
||||
const unsigned b = p[t];
|
||||
_metadata += GetHex((b >> 4) & 0xF);
|
||||
_metadata += GetHex(b & 0xF);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// p = p;
|
||||
}
|
||||
_metadata += '\n';
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
headerSize += k_HeaderSig_Size;
|
||||
_headersSize += headerSize;
|
||||
if (isMainHeader && _headerPlusPayload_Size_Defined)
|
||||
{
|
||||
if (_headerPlusPayload_Size < headerSize)
|
||||
return S_FALSE;
|
||||
_payloadSize = _headerPlusPayload_Size - headerSize;
|
||||
_size = _payloadSize;
|
||||
_phySize = _headersSize + _payloadSize;
|
||||
_payloadSize_Defined = true;
|
||||
_phySize_Defined = true;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CHandler::Open2(ISequentialInStream *stream)
|
||||
{
|
||||
{
|
||||
Byte buf[kLeadSize];
|
||||
RINOK(ReadStream_FALSE(stream, buf, kLeadSize));
|
||||
if (Get32(buf) != 0xEDABEEDB)
|
||||
return S_FALSE;
|
||||
_lead.Parse(buf);
|
||||
if (!_lead.IsSupported())
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
_headersSize = kLeadSize;
|
||||
|
||||
if (_lead.SignatureType == RPMSIG_NONE)
|
||||
{
|
||||
;
|
||||
}
|
||||
else if (_lead.SignatureType == RPMSIG_PGP262_1024)
|
||||
{
|
||||
Byte temp[256];
|
||||
RINOK(ReadStream_FALSE(stream, temp, sizeof(temp)));
|
||||
}
|
||||
else if (_lead.SignatureType == RPMSIG_HEADERSIG)
|
||||
{
|
||||
RINOK(ReadHeader(stream, false));
|
||||
unsigned pos = (unsigned)_headersSize & 7;
|
||||
if (pos != 0)
|
||||
{
|
||||
Byte temp[8];
|
||||
unsigned num = 8 - pos;
|
||||
RINOK(ReadStream_FALSE(stream, temp, num));
|
||||
_headersSize += num;
|
||||
}
|
||||
}
|
||||
else
|
||||
return S_FALSE;
|
||||
|
||||
return ReadHeader(stream, true);
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
try
|
||||
{
|
||||
Close();
|
||||
if (OpenArchive(inStream) != S_OK)
|
||||
return S_FALSE;
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_pos));
|
||||
RINOK(ReadStream_FALSE(inStream, _sig, sizeof(_sig) / sizeof(_sig[0])));
|
||||
UInt64 endPosition;
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPosition));
|
||||
_size = endPosition - _pos;
|
||||
RINOK(Open2(inStream));
|
||||
|
||||
// start of payload is allowed to be unaligned
|
||||
RINOK(ReadStream_FALSE(inStream, _payloadSig, sizeof(_payloadSig)));
|
||||
|
||||
if (!_payloadSize_Defined)
|
||||
{
|
||||
UInt64 endPos;
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos));
|
||||
_size = endPos - _headersSize;
|
||||
}
|
||||
_stream = inStream;
|
||||
return S_OK;
|
||||
}
|
||||
catch(...) { return S_FALSE; }
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_headersSize = 0;
|
||||
_payloadSize = 0;
|
||||
_size = 0;
|
||||
_phySize = 0;
|
||||
_headerPlusPayload_Size = 0;
|
||||
|
||||
_payloadSize_Defined = false;
|
||||
_phySize_Defined = false;
|
||||
_headerPlusPayload_Size_Defined = false;
|
||||
_time_Defined = false;
|
||||
|
||||
_name.Empty();
|
||||
_version.Empty();
|
||||
_release.Empty();
|
||||
_arch.Empty();
|
||||
_os.Empty();
|
||||
|
||||
_format.Empty();
|
||||
_compressor.Empty();
|
||||
|
||||
#ifdef _SHOW_RPM_METADATA
|
||||
_metadata.Empty();
|
||||
#endif
|
||||
|
||||
_stream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
@@ -214,45 +733,17 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
{
|
||||
case kpidSize:
|
||||
case kpidPackSize:
|
||||
prop = _size;
|
||||
break;
|
||||
case kpidExtension:
|
||||
{
|
||||
char s[32];
|
||||
MyStringCopy(s, "cpio.");
|
||||
const char *ext;
|
||||
if (_sig[0] == 0x1F && _sig[1] == 0x8B)
|
||||
ext = "gz";
|
||||
else if (_sig[0] == 'B' && _sig[1] == 'Z' && _sig[2] == 'h')
|
||||
ext = "bz2";
|
||||
else
|
||||
ext = "lzma";
|
||||
MyStringCopy(s + MyStringLen(s), ext);
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
|
||||
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
|
||||
return E_INVALIDARG;
|
||||
|
||||
RINOK(extractCallback->SetTotal(_size));
|
||||
|
||||
CMyComPtr<ISequentialOutStream> outStream;
|
||||
Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
@@ -262,30 +753,38 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
return S_OK;
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
|
||||
CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
|
||||
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
|
||||
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
RINOK(_stream->Seek(_pos, STREAM_SEEK_SET, NULL));
|
||||
RINOK(copyCoder->Code(_stream, outStream, NULL, NULL, progress));
|
||||
RINOK(_stream->Seek(_headersSize, STREAM_SEEK_SET, NULL));
|
||||
RINOK(copyCoder->Code(_stream, outStream, NULL, &_size, progress));
|
||||
outStream.Release();
|
||||
return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK);
|
||||
Int32 opRes = NExtract::NOperationResult::kOK;
|
||||
if (copyCoderSpec->TotalSize < _size)
|
||||
opRes = NExtract::NOperationResult::kUnexpectedEnd;
|
||||
return extractCallback->SetOperationResult(opRes);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
return CreateLimitedInStream(_stream, _pos, _size, stream);
|
||||
return CreateLimitedInStream(_stream, _headersSize, _size, stream);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static IInArchive *CreateArc() { return new NArchive::NRpm::CHandler; }
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ L"Rpm", L"rpm", 0, 0xEB, { 0xED, 0xAB, 0xEE, 0xDB}, 4, false, CreateArc, 0 };
|
||||
{ "Rpm", "rpm", 0, 0xEB,
|
||||
4, { 0xED, 0xAB, 0xEE, 0xDB},
|
||||
0,
|
||||
0,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Rpm)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user