Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive/RpmHandler.cpp')
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/RpmHandler.cpp821
1 files changed, 660 insertions, 161 deletions
diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp
index 1d31d451..220bc650 100755..100644
--- a/CPP/7zip/Archive/RpmHandler.cpp
+++ b/CPP/7zip/Archive/RpmHandler.cpp
@@ -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
-const UInt32 kLeadSize = 96;
-struct CLead
+enum
{
- unsigned char Magic[4];
- unsigned char Major; // not supported ver1, only support 2,3 and lator
- unsigned char Minor;
- UInt16 Type;
- UInt16 ArchNum;
- char Name[66];
- UInt16 OSNum;
- 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; };
+ kRpmType_Bin = 0,
+ kRpmType_Src = 1
};
-
-const UInt32 kEntryInfoSize = 16;
-/*
-struct CEntryInfo
+
+// 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
{
- int Tag;
- int Type;
- int Offset; // Offset from beginning of data segment, only defined on disk
- int Count;
+ 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
};
-*/
-// case: SignatureType == RPMSIG_HEADERSIG
-const UInt32 kCSigHeaderSigSize = 16;
-struct CSigHeaderSig
+static const char *k_CPUs[] =
{
- 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; };
+ "noarch"
+ , "i386"
+ , "alpha"
+ , "sparc"
+ , "mips"
+ , "ppc"
+ , "m68k"
+ , "sgi"
+ , "rs6000"
+ , "ia64"
+ , "sparc64" // 10 ???
+ , "mipsel"
+ , "arm"
+ , "m68kmint"
+ , "s390"
+ , "s390x"
+ , "ppc64"
+ , "sh"
+ , "xtensa"
+ , "aarch64" // 19
};
-static HRESULT RedSigHeaderSig(IInStream *inStream, CSigHeaderSig &h)
+static const char *k_OS[] =
{
- 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;
-}
+ "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
+};
-HRESULT OpenArchive(IInStream *inStream)
+struct CLead
{
- 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;
+ unsigned char Major;
+ unsigned char Minor;
+ UInt16 Type;
+ UInt16 Cpu;
+ UInt16 Os;
+ UInt16 SignatureType;
+ char Name[kNameSize];
+ // char Reserved[16];
- CSigHeaderSig sigHeader, header;
- if (lead.SignatureType == RPMSIG_NONE)
- {
- ;
- }
- else if (lead.SignatureType == RPMSIG_PGP262_1024)
+ void Parse(const Byte *p)
{
- UInt64 pos;
- RINOK(inStream->Seek(256, STREAM_SEEK_CUR, &pos));
+ 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);
}
- else if (lead.SignatureType == RPMSIG_HEADERSIG)
+
+ bool IsSupported() const { return Major >= 3 && Type <= 1; }
+};
+
+struct CEntry
+{
+ UInt32 Tag;
+ UInt32 Type;
+ UInt32 Offset;
+ UInt32 Count;
+
+ void Parse(const Byte *p)
{
- 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));
- }
+ Tag = Get32(p + 0);
+ Type = Get32(p + 4);
+ Offset = Get32(p + 8);
+ Count = Get32(p + 12);
}
- 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,104 +175,575 @@ 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
-STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+void CHandler::AddCPU(AString &s) const
{
- NCOM::CPropVariant prop;
- switch(propID) { case kpidMainSubfile: prop = (UInt32)0; break; }
- prop.Detach(value);
- return S_OK;
+ 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;
+ }
+ }
}
-STDMETHODIMP CHandler::Open(IInStream *inStream,
- const UInt64 * /* maxCheckStartPosition */,
- IArchiveOpenCallback * /* openArchiveCallback */)
+AString CHandler::GetBaseName() const
{
- COM_TRY_BEGIN
- try
+ AString s;
+ if (!_name.IsEmpty())
{
- 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;
- _stream = inStream;
- return S_OK;
+ s = _name;
+ if (!_version.IsEmpty())
+ {
+ s += '-';
+ s += _version;
+ }
+ if (!_release.IsEmpty())
+ {
+ s += '-';
+ s += _release;
+ }
}
- catch(...) { return S_FALSE; }
- COM_TRY_END
+ 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;
}
-STDMETHODIMP CHandler::Close()
+void CHandler::AddSubFileExtension(AString &res) const
{
- _stream.Release();
- return S_OK;
+ 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::GetNumberOfItems(UInt32 *numItems)
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
- *numItems = 1;
+ COM_TRY_BEGIN
+ NCOM::CPropVariant prop;
+ 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)
+ 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:
{
- 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;
+ prop = GetSubFileExtension();
break;
}
+ */
}
prop.Detach(value);
return S_OK;
}
+#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
+ {
+ Close();
+ 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;
+ }
+ 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;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = 1;
+ 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)