Make rpmlead opaque, add methods to deal with it

- rename methods to rpmLead*() for easy grepping
- populate lead from header where necessary
- add rpmLeadCheck() method for minimal compatibility checking to get
  rid of duplicate code in several places
- conditionalize lead version on dirtokens
This commit is contained in:
Panu Matilainen 2007-12-01 18:31:09 +02:00
parent 89ecfb96d0
commit 92698df723
7 changed files with 156 additions and 173 deletions

View File

@ -283,7 +283,7 @@ int readRPM(const char *fileName, rpmSpec *specp, struct rpmlead *lead,
}
/* Get copy of lead */
if ((rc = Fread(lead, sizeof(char), sizeof(*lead), fdi)) != sizeof(*lead)) {
if ((rc = Fread(lead, sizeof(char), RPMLEAD_SIZE, fdi)) != RPMLEAD_SIZE) {
rpmlog(RPMLOG_ERR, _("readRPM: read %s: %s\n"),
(fileName ? fileName : "<stdin>"),
Fstrerror(fdi));
@ -347,35 +347,6 @@ int readRPM(const char *fileName, rpmSpec *specp, struct rpmlead *lead,
return 0;
}
#ifdef DYING
static unsigned char header_magic[8] = {
0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
};
#endif
#define RPMPKGVERSION_MIN 30004
#define RPMPKGVERSION_MAX 40003
static int rpmpkg_version = -1;
static int rpmLeadVersion(void)
{
int rpmlead_version;
/* Intitialize packaging version from macro configuration. */
if (rpmpkg_version < 0) {
rpmpkg_version = rpmExpandNumeric("%{_package_version}");
if (rpmpkg_version < RPMPKGVERSION_MIN)
rpmpkg_version = RPMPKGVERSION_MIN;
if (rpmpkg_version > RPMPKGVERSION_MAX)
rpmpkg_version = RPMPKGVERSION_MAX;
}
rpmlead_version = rpmpkg_version / 10000;
if (_noDirTokens || (rpmlead_version < 3 || rpmlead_version > 4))
rpmlead_version = 3;
return rpmlead_version;
}
int writeRPM(Header *hdrp, unsigned char ** pkgidp, const char *fileName,
int type, CSA_t csa, char *passPhrase, const char **cookie)
{
@ -526,35 +497,11 @@ int writeRPM(Header *hdrp, unsigned char ** pkgidp, const char *fileName,
}
/* Write the lead section into the package. */
{ int archnum = -1;
int osnum = -1;
struct rpmlead lead;
if (Fileno(csa->cpioFdIn) < 0) {
#ifndef DYING
rpmGetArchInfo(NULL, &archnum);
rpmGetOsInfo(NULL, &osnum);
#endif
} else if (csa->lead != NULL) {
archnum = csa->lead->archnum;
osnum = csa->lead->osnum;
}
memset(&lead, 0, sizeof(lead));
lead.major = rpmLeadVersion();
lead.minor = 0;
lead.type = type;
lead.archnum = archnum;
lead.osnum = osnum;
lead.signature_type = RPMSIGTYPE_HEADERSIG;
{ const char *name, *version, *release;
(void) headerNVR(h, &name, &version, &release);
sprintf(buf, "%s-%s-%s", name, version, release);
strncpy(lead.name, buf, sizeof(lead.name));
}
if (writeLead(fd, &lead) != RPMRC_OK) {
{
rpmlead lead = rpmLeadFromHeader(h);
int rc = rpmLeadWrite(fd, lead);
lead = rpmLeadFree(lead);
if (rc != RPMRC_OK) {
rc = RPMLOG_ERR;
rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"),
Fstrerror(fd));

View File

@ -677,7 +677,7 @@ rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
pgpDig dig;
char buf[8*BUFSIZ];
ssize_t count;
struct rpmlead * l = alloca(sizeof(*l));
rpmlead l = NULL;
Header sigh = NULL;
int32_t sigtag;
int32_t sigtype;
@ -693,33 +693,19 @@ rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
if (hdrp) *hdrp = NULL;
memset(l, 0, sizeof(*l));
rc = readLead(fd, l);
l = rpmLeadNew();
if ((rc = rpmLeadRead(fd, l)) == RPMRC_OK) {
rc = rpmLeadCheck(l, fn);
}
l = rpmLeadFree(l);
if (rc != RPMRC_OK)
goto exit;
switch (l->major) {
case 1:
rpmlog(RPMLOG_ERR,
_("packaging version 1 is not supported by this version of RPM\n"));
rc = RPMRC_NOTFOUND;
goto exit;
break;
case 2:
case 3:
case 4:
break;
default:
rpmlog(RPMLOG_ERR, _("only packaging with major numbers <= 4 "
"is supported by this version of RPM\n"));
rc = RPMRC_NOTFOUND;
goto exit;
break;
}
/* Read the signature header. */
msg = NULL;
rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
rc = rpmReadSignature(fd, &sigh, RPMSIGTYPE_HEADERSIG, &msg);
switch (rc) {
default:
rpmlog(RPMLOG_ERR, _("%s: rpmReadSignature failed: %s"), fn,

View File

@ -1487,34 +1487,17 @@ assert(psm->mi == NULL);
rc = rpmpsmNext(psm, PSM_RPMIO_FLAGS);
/* Write the lead section into the package. */
{ int archnum = -1;
int osnum = -1;
struct rpmlead lead;
#ifndef DYING
rpmGetArchInfo(NULL, &archnum);
rpmGetOsInfo(NULL, &osnum);
#endif
memset(&lead, 0, sizeof(lead));
/* XXX Set package version conditioned on noDirTokens. */
lead.major = 3;
lead.minor = 0;
lead.type = RPMLEAD_BINARY;
lead.archnum = archnum;
lead.osnum = osnum;
lead.signature_type = RPMSIGTYPE_HEADERSIG;
strncpy(lead.name, rpmteNEVR(psm->te), sizeof(lead.name));
rc = writeLead(psm->fd, &lead);
{
rpmlead lead = rpmLeadFromHeader(psm->oh);
rc = rpmLeadWrite(psm->fd, lead);
lead = rpmLeadFree(lead);
if (rc != RPMRC_OK) {
rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"),
Fstrerror(psm->fd));
break;
}
}
/* Write the signature section into the package. */
/* XXX rpm-4.1 and later has archive size in signature header. */
{ Header sigh = headerRegenSigHeader(fi->h, noArchiveSize);

View File

@ -154,7 +154,7 @@ static int rpmReSign(rpmts ts,
{
FD_t fd = NULL;
FD_t ofd = NULL;
struct rpmlead lead, *l = &lead;
rpmlead lead;
int32_t sigtag;
const char *rpm, *trpm;
const char *sigtarget = NULL;
@ -178,27 +178,19 @@ static int rpmReSign(rpmts ts,
if (manageFile(&fd, &rpm, O_RDONLY, 0))
goto exit;
memset(l, 0, sizeof(*l));
rc = readLead(fd, l);
if (rc != RPMRC_OK) {
rpmlog(RPMLOG_ERR, _("%s: not an rpm package\n"), rpm);
goto exit;
lead = rpmLeadNew();
if ((rc = rpmLeadRead(fd, lead)) == RPMRC_OK) {
rc = rpmLeadCheck(lead, rpm);
}
switch (l->major) {
case 1:
rpmlog(RPMLOG_ERR, _("%s: Can't sign v1 packaging\n"), rpm);
if (rc != RPMRC_OK) {
lead = rpmLeadFree(lead);
goto exit;
break;
case 2:
rpmlog(RPMLOG_ERR, _("%s: Can't re-sign v2 packaging\n"), rpm);
goto exit;
break;
default:
break;
}
msg = NULL;
rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
rc = rpmReadSignature(fd, &sigh, RPMSIGTYPE_HEADERSIG, &msg);
switch (rc) {
default:
rpmlog(RPMLOG_ERR, _("%s: rpmReadSignature failed: %s"), rpm,
@ -338,8 +330,8 @@ static int rpmReSign(rpmts ts,
if (manageFile(&ofd, &trpm, O_WRONLY|O_CREAT|O_TRUNC, 0))
goto exit;
l->signature_type = RPMSIGTYPE_HEADERSIG;
rc = writeLead(ofd, l);
rc = rpmLeadWrite(ofd, lead);
lead = rpmLeadFree(lead);
if (rc != RPMRC_OK) {
rpmlog(RPMLOG_ERR, _("%s: writeLead failed: %s\n"), trpm,
Fstrerror(ofd));
@ -522,7 +514,6 @@ int rpmVerifySignatures(QVA_t qva, rpmts ts, FD_t fd,
const char * fn)
{
int res2, res3;
struct rpmlead lead, *l = &lead;
char result[1024];
char buf[8192], * b;
char missingKeys[7164], * m;
@ -543,25 +534,20 @@ int rpmVerifySignatures(QVA_t qva, rpmts ts, FD_t fd,
int nosignatures = !(qva->qva_flags & VERIFY_SIGNATURE);
{
memset(l, 0, sizeof(*l));
rc = readLead(fd, l);
if (rc != RPMRC_OK) {
rpmlog(RPMLOG_ERR, _("%s: not an rpm package\n"), fn);
rpmlead lead = rpmLeadNew();
if ((rc = rpmLeadRead(fd, lead)) == RPMRC_OK) {
rc = rpmLeadCheck(lead, fn);
}
lead = rpmLeadFree(lead);
if (rc != RPMRC_OK) {
res++;
goto exit;
}
switch (l->major) {
case 1:
rpmlog(RPMLOG_ERR, _("%s: No signature available (v1.0 RPM)\n"), fn);
res++;
goto exit;
break;
default:
break;
}
msg = NULL;
rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
rc = rpmReadSignature(fd, &sigh, RPMSIGTYPE_HEADERSIG, &msg);
switch (rc) {
default:
rpmlog(RPMLOG_ERR, _("%s: rpmReadSignature failed: %s"), fn,

View File

@ -10,6 +10,7 @@
#include "lib/signature.h"
#include "lib/rpmlead.h"
#include "lib/legacy.h"
#include <rpmlog.h>
#include "debug.h"
@ -17,19 +18,74 @@ static unsigned char lead_magic[] = {
RPMLEAD_MAGIC0, RPMLEAD_MAGIC1, RPMLEAD_MAGIC2, RPMLEAD_MAGIC3
};
/* The lead needs to be 8 byte aligned */
/** \ingroup lead
* The lead data structure.
* The lead needs to be 8 byte aligned.
* @deprecated The lead (except for signature_type) is legacy.
* @todo Don't use any information from lead.
*/
struct rpmlead_s {
unsigned char magic[4];
unsigned char major;
unsigned char minor;
short type;
short archnum;
char name[66];
short osnum;
short signature_type; /*!< Signature header type (RPMSIG_HEADERSIG) */
char reserved[16]; /*!< Pad to 96 bytes -- 8 byte aligned! */
};
rpmRC writeLead(FD_t fd, const struct rpmlead *lead)
rpmlead rpmLeadNew(void)
{
struct rpmlead l;
int archnum, osnum;
rpmlead l = calloc(1, sizeof(*l));
rpmGetArchInfo(NULL, &archnum);
rpmGetOsInfo(NULL, &osnum);
l->major = (_noDirTokens ? 4: 3);
l->minor = 0;
l->archnum = archnum;
l->osnum = osnum;
l->signature_type = RPMSIGTYPE_HEADERSIG;
return l;
}
rpmlead rpmLeadFromHeader(Header h)
{
char * nevr;
assert(h != NULL);
rpmlead l = rpmLeadNew();
l->type = !(headerIsEntry(h, RPMTAG_SOURCERPM));
nevr = headerGetNEVR(h, NULL);
strncpy(l->name, nevr, sizeof(l->name));
free(nevr);
return l;
}
rpmlead rpmLeadFree(rpmlead lead)
{
assert(lead != NULL);
free(lead);
return NULL;
}
/* The lead needs to be 8 byte aligned */
rpmRC rpmLeadWrite(FD_t fd, rpmlead lead)
{
struct rpmlead_s l;
assert(lead != NULL);
memcpy(&l, lead, sizeof(l));
memcpy(&l.magic, lead_magic, sizeof(l.magic));
l.type = htons(l.type);
l.archnum = htons(l.archnum);
l.osnum = htons(l.osnum);
l.signature_type = htons(l.signature_type);
l.type = htons(lead->type);
l.archnum = htons(lead->archnum);
l.osnum = htons(lead->osnum);
l.signature_type = htons(lead->signature_type);
if (Fwrite(&l, 1, sizeof(l), fd) != sizeof(l))
return RPMRC_FAIL;
@ -37,8 +93,26 @@ rpmRC writeLead(FD_t fd, const struct rpmlead *lead)
return RPMRC_OK;
}
rpmRC readLead(FD_t fd, struct rpmlead *lead)
rpmRC rpmLeadCheck(rpmlead lead, const char* fn)
{
if (memcmp(lead->magic, lead_magic, sizeof(lead_magic))) {
rpmlog(RPMLOG_ERR, _("%s: not an rpm package\n"), fn);
return RPMRC_NOTFOUND;
}
if (lead->signature_type != RPMSIGTYPE_HEADERSIG) {
rpmlog(RPMLOG_ERR, _("%s: illegal signature type\n"), fn);
return RPMRC_FAIL;
}
if (lead->major < 3 || lead->major > 4) {
rpmlog(RPMLOG_ERR, _("%s: unsupported RPM package (version %d)\n"), fn, lead->major);
return RPMRC_FAIL;
}
return RPMRC_OK;
}
rpmRC rpmLeadRead(FD_t fd, rpmlead lead)
{
assert(lead != NULL);
memset(lead, 0, sizeof(*lead));
/* FIX: remove timed read */
if (timedRead(fd, (char *)lead, sizeof(*lead)) != sizeof(*lead)) {
@ -49,15 +123,10 @@ rpmRC readLead(FD_t fd, struct rpmlead *lead)
}
return RPMRC_NOTFOUND;
}
if (memcmp(lead->magic, lead_magic, sizeof(lead_magic)))
return RPMRC_NOTFOUND;
lead->type = ntohs(lead->type);
lead->archnum = ntohs(lead->archnum);
lead->osnum = ntohs(lead->osnum);
lead->signature_type = ntohs(lead->signature_type);
if (lead->signature_type != RPMSIGTYPE_HEADERSIG)
return RPMRC_NOTFOUND;
return RPMRC_OK;
}

View File

@ -19,33 +19,37 @@ extern "C" {
#define RPMLEAD_SIZE 96 /*!< Don't rely on sizeof(struct) */
/** \ingroup lead
* The lead data structure.
* The lead needs to be 8 byte aligned.
* @deprecated The lead (except for signature_type) is legacy.
* @todo Don't use any information from lead.
*/
struct rpmlead {
unsigned char magic[4];
unsigned char major;
unsigned char minor;
short type;
short archnum;
char name[66];
short osnum;
short signature_type; /*!< Signature header type (RPMSIG_HEADERSIG) */
char reserved[16]; /*!< Pad to 96 bytes -- 8 byte aligned! */
} ;
typedef struct rpmlead_s * rpmlead;
#include <rpmlib.h>
/** \ingroup lead
* Initialize a lead structure
* @return Pointer to empty lead structure
*/
rpmlead rpmLeadNew(void);
/** \ingroup lead
* Initialize a lead structure from header
* param h Header
* @return Pointer to populated lead structure (malloced)
*/
rpmlead rpmLeadFromHeader(Header h);
/** \ingroup lead
* Free a lead structure
* @param lead Pointer to lead structure
* @return NULL always
*/
rpmlead rpmLeadFree(rpmlead lead);
/** \ingroup lead
* Write lead to file handle.
* @param fd file handle
* @param lead package lead
* @return RPMRC_OK on success, RPMRC_FAIL on error
*/
rpmRC writeLead(FD_t fd, const struct rpmlead *lead);
rpmRC rpmLeadWrite(FD_t fd, rpmlead lead);
/** \ingroup lead
* Read lead from file handle.
@ -53,7 +57,15 @@ rpmRC writeLead(FD_t fd, const struct rpmlead *lead);
* @retval lead package lead
* @return RPMRC_OK on success, RPMRC_FAIL/RPMRC_NOTFOUND on error
*/
rpmRC readLead(FD_t fd, struct rpmlead *lead);
rpmRC rpmLeadRead(FD_t fd, rpmlead lead);
/** \ingroup lead
* Check lead for compatibility.
* @param lead Pointer to lead handle
* @param fn File name
* @return RPMRC_OK on success, RPMRC_FAIL/RPMRC_NOTFOUND on error
*/
rpmRC rpmLeadCheck(rpmlead lead, const char* fn);
#ifdef __cplusplus
}

View File

@ -111,14 +111,14 @@ static inline rpmRC printSize(FD_t fd, int siglen, int pad, int datalen)
/* HACK: workaround for davRead wiring. */
if (fdno == 123456789) {
st.st_size = 0;
st.st_size -= sizeof(struct rpmlead)+siglen+pad+datalen;
st.st_size -= RPMLEAD_SIZE+siglen+pad+datalen;
} else if (fstat(fdno, &st) < 0)
return RPMRC_FAIL;
rpmlog(RPMLOG_DEBUG,
_("Expected size: %12d = lead(%d)+sigs(%d)+pad(%d)+data(%d)\n"),
(int)sizeof(struct rpmlead)+siglen+pad+datalen,
(int)sizeof(struct rpmlead), siglen, pad, datalen);
RPMLEAD_SIZE+siglen+pad+datalen,
RPMLEAD_SIZE, siglen, pad, datalen);
rpmlog(RPMLOG_DEBUG,
_(" Actual size: %12d\n"), (int)st.st_size);