Make rpmlead opaque, add methods to deal with it
authorPanu Matilainen <pmatilai@redhat.com>
Sat, 1 Dec 2007 16:31:09 +0000 (18:31 +0200)
committerPanu Matilainen <pmatilai@redhat.com>
Sat, 1 Dec 2007 16:31:09 +0000 (18:31 +0200)
- 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

build/pack.c
lib/package.c
lib/psm.c
lib/rpmchecksig.c
lib/rpmlead.c
lib/rpmlead.h
lib/signature.c

index ca394c7..a6e57cb 100644 (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));
index 1539dac..dcd50a3 100644 (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);
-    if (rc != RPMRC_OK)
-       goto exit;
+    l = rpmLeadNew();
 
-    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;
+    if ((rc = rpmLeadRead(fd, l)) == RPMRC_OK) {
+       rc = rpmLeadCheck(l, fn);
     }
+    l = rpmLeadFree(l);
+
+    if (rc != RPMRC_OK)
+       goto exit;
 
     /* 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,
index f32b3c2..b131890 100644 (file)
--- a/lib/psm.c
+++ b/lib/psm.c
@@ -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);
index 30db9f8..4d38e9d 100644 (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);
-           goto exit;
-           break;
-       case 2:
-           rpmlog(RPMLOG_ERR, _("%s: Can't re-sign v2 packaging\n"), rpm);
+
+       if (rc != RPMRC_OK) {
+           lead = rpmLeadFree(lead);
            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,
index bf1007f..f4cffd5 100644 (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! */
+};
+
+rpmlead rpmLeadNew(void)
+{
+    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);
 
-rpmRC writeLead(FD_t fd, const struct rpmlead *lead)
+    return l;
+}
+
+rpmlead rpmLeadFree(rpmlead lead)
 {
-    struct rpmlead l;
+    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;
 }
index 62b2710..7593cf0 100644 (file)
@@ -19,25 +19,29 @@ extern "C" {
 
 #define RPMLEAD_SIZE 96         /*!< Don't rely on sizeof(struct) */
 
+typedef struct rpmlead_s * rpmlead;
+
+#include <rpmlib.h>
+
 /** \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.
+ * Initialize a lead structure
+ * @return             Pointer to empty lead structure
  */
-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! */
-} ;
+rpmlead rpmLeadNew(void);
 
-#include <rpmlib.h>
+/** \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.
@@ -45,7 +49,7 @@ char reserved[16];    /*!< Pad to 96 bytes -- 8 byte aligned! */
  * @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
 }
index 5cd1ba3..81df8fb 100644 (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);