From 3c061be6aeaec1be793b406fac9f667dc5d1429b Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 4 Mar 2020 11:15:02 +0200
Subject: [PATCH] Use libelf for determining file colors

libmagic strings are notoriously unreliable as the details from version
to version. We link to libelf anyway so we might as well as get the
info straight from the horse's mouth.

Besides being more reliable, this detaches the coloring business from
the hardcoded rpmfcTokens struct and informative-only FILECLASS
contents,
opening the door for other changes in that area.
---
 build/rpmfc.c | 35 +++++++++++++++++++++++++++++------
 1 file changed, 29 insertions(+), 6 deletions(-)

diff --git a/build/rpmfc.c b/build/rpmfc.c
index aaa0dca..0886616 100644
--- a/build/rpmfc.c
+++ b/build/rpmfc.c
@@ -7,6 +7,7 @@
 #include <signal.h>
 #include <magic.h>
 #include <regex.h>
+#include <gelf.h>
 
 #include <rpm/header.h>
 #include <rpm/argv.h>
@@ -595,7 +596,7 @@ exit:
     return rc;
 }
 
-/* Only used for elf coloring and controlling RPMTAG_FILECLASS inclusion now */
+/* Only used for controlling RPMTAG_FILECLASS inclusion now */
 static const struct rpmfcTokens_s rpmfcTokens[] = {
   { "directory",		RPMFC_INCLUDE },
 
@@ -1076,6 +1077,29 @@ static int initAttrs(rpmfc fc)
     return nattrs;
 }
 
+static uint32_t getElfColor(const char *fn)
+{
+    uint32_t color = 0;
+    int fd = open(fn, O_RDONLY);
+    if (fd >= 0) {
+	Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
+	GElf_Ehdr ehdr;
+	if (elf && gelf_getehdr(elf, &ehdr)) {
+	    switch (ehdr.e_ident[EI_CLASS]) {
+	    case ELFCLASS64:
+		color = RPMFC_ELF64;
+		break;
+	    case ELFCLASS32:
+		color = RPMFC_ELF32;
+		break;
+	    }
+	    elf_end(elf);
+	}
+	close(fd);
+    }
+    return color;
+}
+
 rpmRC rpmfcClassify(rpmfc fc, ARGV_t argv, rpm_mode_t * fmode)
 {
     int msflags = MAGIC_CHECK | MAGIC_COMPRESS | MAGIC_NO_CHECK_TOKENS;
@@ -1187,8 +1211,6 @@ rpmRC rpmfcClassify(rpmfc fc, ARGV_t argv, rpm_mode_t * fmode)
 	/* Add attributes based on file type and/or path */
 	rpmfcAttributes(fc, ix, ftype, s);
 
-	fc->fcolor[ix] = fcolor;
-
 	/* Add to file class dictionary and index array */
 	#pragma omp ordered
 	if (fcolor != RPMFC_WHITE && (fcolor & RPMFC_INCLUDE)) {
@@ -1202,6 +1224,10 @@ rpmRC rpmfcClassify(rpmfc fc, ARGV_t argv, rpm_mode_t * fmode)
 	}
 	/* Pool id's start from 1, for headers we want it from 0 */
 	fc->fcdictx[ix] = ftypeId - 1;
+        
+	/* Add ELF colors */
+	if (S_ISREG(mode) && is_executable)
+	    fc->fcolor[ix] = getElfColor(s);
     }
 
     if (ms != NULL)
@@ -1493,9 +1519,6 @@ rpmRC rpmfcGenerateDepends(const rpmSpec spec, Package pkg)
 	goto exit;
 
     /* Add per-file colors(#files) */
-    /* XXX Make sure only primary (i.e. Elf32/Elf64) colors are added. */
-    for (int i = 0; i < fc->nfiles; i++)
-	fc->fcolor[i] &= 0x0f;
     headerPutUint32(pkg->header, RPMTAG_FILECOLORS, fc->fcolor, fc->nfiles);
     
     /* Add classes(#classes) */
-- 
2.27.0

