This commit introduces calculateIdentity function. The function
calculates identity as a hash of significant package tags, and writes it
to the package header. Tag is significant unless it is insignificant.
Insignificant tags are those tags that are not relevant to result of
package build, e.g. that contain some information of build host, or
value of that is based on randomness, etc. Insignificant tags are
filtered by tag blacklist with help of identityFilterTag function.
---
 build/misc.c          | 45 +++++++++++++++++++++++++++++++++++++++++++++
 build/rpmbuild_misc.h |  8 ++++++++
 lib/header.c          | 45 +++++++++++++++++++++++++++++++++++++++++++--
 lib/header.h          |  3 ++-
 lib/rpmtag.h          |  2 +-
 5 files changed, 99 insertions(+), 4 deletions(-)

diff --git a/build/misc.c b/build/misc.c
index 06fd110..499f6d9 100644
--- a/build/misc.c
+++ b/build/misc.c
@@ -6,7 +6,11 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <rpm/rpmstring.h>
+#include <rpm/rpmlog.h>
 #include "build/rpmbuild_misc.h"
+#include "lib/header.h"
+#include "rpmio/rpmio_internal.h"
+#include "lib/signature.h"
 #include "debug.h"
 
 #define BUF_CHUNK 1024
@@ -101,3 +105,44 @@ uint32_t parseUnsignedNum(const char * line, uint32_t * 
res)
 
     return 0;
 }
+
+int calculateIdentity(Header *hdr)
+{
+    int rc = 0;
+
+    Header header;
+    const char * name;
+    const char * identity = NULL;
+    FD_t identityfd = NULL;
+
+    header = headerLink(*hdr);
+    hdr = headerFree(*hdr);
+
+    headerNVR(header, &name, NULL, NULL);
+
+    if ((identityfd = rpmMkTempFile(NULL, NULL)) == NULL) {
+       rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n"));
+       return 1;
+    }
+
+    fdInitDigest(identityfd, PGPHASHALGO_SHA1, 0);
+    if (headerWrite(identityfd, header, HEADER_MAGIC_IDENTITY) || 
Fflush(identityfd)) {
+       rc = 1;
+       rpmlog(RPMLOG_ERR, _("Unable to write header to calculate package 
identity\n"));
+    }
+
+    fdFiniDigest(identityfd, PGPHASHALGO_SHA1, (void **)&identity, NULL, 1);
+    (void) Fclose(identityfd);
+
+    if (rc)
+       return rc;
+
+    if (identity) {
+       rpmlog(RPMLOG_INFO, "Identity of %s is %s\n", name, identity);
+       headerAddEntry(header, RPMTAG_IDENTITY, RPM_STRING_TYPE, identity, 1);
+       identity = _free(identity);
+    }
+
+exit:
+    return rc;
+}
diff --git a/build/rpmbuild_misc.h b/build/rpmbuild_misc.h
index 843dfea..e783378 100644
--- a/build/rpmbuild_misc.h
+++ b/build/rpmbuild_misc.h
@@ -63,6 +63,14 @@ void appendStringBufAux(StringBuf sb, const char * s, int 
nl);
 RPM_GNUC_INTERNAL
 uint32_t parseUnsignedNum(const char * line, uint32_t * res);
 
+/** \ingroup rpmbuild
+ * Calculate package identity.
+ * @param h             header
+ * @return              0 on success
+ */
+int calculateIdentity(Header *h)
+        /*@modifies header @*/;
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/header.c b/lib/header.c
index b3a2324..5a02b6a 100644
--- a/lib/header.c
+++ b/lib/header.c
@@ -577,7 +577,37 @@ static int regionSwab(indexEntry entry, int il, int dl,
     return dl;
 }
 
-void * headerExport(Header h, unsigned int *bsize)
+/* filter tags that are not considered by identity calculation */
+static int identityFilterTag(rpmTagVal tag)
+{
+    int ret = 0;
+
+    switch(tag) {
+    case RPMTAG_ARCH:
+    case RPMTAG_ARCHIVESIZE:
+    case RPMTAG_BUILDHOST:
+    case RPMTAG_BUILDTIME:
+    case RPMTAG_COOKIE:
+    case RPMTAG_DISTRIBUTION:
+    case RPMTAG_DISTTAG:
+    case RPMTAG_DISTURL:
+    case RPMTAG_HEADERIMMUTABLE:
+    case RPMTAG_IDENTITY:
+    case RPMTAG_SHA1HEADER:
+    case RPMTAG_SIGLEMD5_1:
+    case RPMTAG_SIGLEMD5_2:
+    case RPMTAG_SIGMD5:
+    case RPMTAG_SIGSIZE:
+       ret = 1;
+       break;
+    default:
+       break;
+    }
+
+    return ret;
+}
+
+static void * headerExportInternal(Header h, unsigned int *bsize, int 
is_identity)
 {
     int32_t * ei = NULL;
     entryInfo pe;
@@ -598,6 +628,9 @@ void * headerExport(Header h, unsigned int *bsize)
     /* Compute (il,dl) for all tags, including those deleted in region. */
     drlen = ndribbles = 0;
     for (i = 0, entry = h->index; i < h->indexUsed; i++, entry++) {
+       if (is_identity && identityFilterTag(entry->info.tag))
+               continue;
+
        if (ENTRY_IS_REGION(entry)) {
            int32_t rdl = -entry->info.offset;  /* negative offset */
            int32_t ril = rdl/sizeof(*pe);
@@ -656,6 +689,9 @@ void * headerExport(Header h, unsigned int *bsize)
     dataStart = te = (char *) (pe + il);
 
     for (i = 0, entry = h->index; i < h->indexUsed; i++, entry++) {
+       if (is_identity && identityFilterTag(entry->info.tag))
+               continue;
+
        const char * src;
        unsigned char *t;
        int count;
@@ -799,6 +835,11 @@ errxit:
     return NULL;
 }
 
+void * headerExport(Header h, unsigned int *bsize)
+{
+    return headerExportInternal(h, bsize, 0);
+}
+
 void * headerUnload(Header h)
 {
     return headerExport(h, NULL);
@@ -1029,7 +1070,7 @@ int headerWrite(FD_t fd, Header h, int magicp)
 {
     ssize_t nb;
     unsigned int length;
-    void * uh = headerExport(h, &length);
+    void * uh = headerExportInternal(h, &length, magicp == 
HEADER_MAGIC_IDENTITY);
 
     if (uh == NULL)
        return 1;
diff --git a/lib/header.h b/lib/header.h
index a616dee..adaa01e 100644
--- a/lib/header.h
+++ b/lib/header.h
@@ -31,7 +31,8 @@ extern const unsigned char rpm_header_magic[8];
  */
 enum hMagic {
     HEADER_MAGIC_NO            = 0,
-    HEADER_MAGIC_YES           = 1
+    HEADER_MAGIC_YES           = 1,
+    HEADER_MAGIC_IDENTITY      = 2
 };
 
 /** \ingroup header
diff --git a/lib/rpmtag.h b/lib/rpmtag.h
index 973a6b6..fd2b7fe 100644
--- a/lib/rpmtag.h
+++ b/lib/rpmtag.h
@@ -371,7 +371,7 @@ typedef enum rpmTag_e {
     RPMTAG_PAYLOADDIGEST       = 5092, /* s[] */
     RPMTAG_PAYLOADDIGESTALGO   = 5093, /* i */
     RPMTAG_AUTOINSTALLED       = 5094, /* i reservation (unimplemented) */
-    RPMTAG_IDENTITY            = 5095, /* s reservation (unimplemented) */
+    RPMTAG_IDENTITY            = 5095, /* s */
 
     RPMTAG_FIRSTFREE_TAG       /*!< internal */
 } rpmTag;
-- 
2.10.4

_______________________________________________
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint

Reply via email to