- Add general /proc/self/auxv parsing to rpmrc for better machine detection
authorPhil Knirsch <pknirsch@redhat.com>
Mon, 16 Apr 2012 17:02:34 +0000 (19:02 +0200)
committerPanu Matilainen <pmatilai@redhat.com>
Tue, 17 Apr 2012 06:25:53 +0000 (09:25 +0300)
Signed-off-by: Panu Matilainen <pmatilai@redhat.com>
lib/rpmrc.c

index 4b6b29a..edb9cd6 100644 (file)
@@ -2,6 +2,12 @@
 
 #include <stdarg.h>
 
+#if defined(__linux__)
+#include <elf.h>
+#include <link.h>
+#endif
+
+
 #if HAVE_SYS_UTSNAME_H
 #include <sys/utsname.h>
 #endif
@@ -73,6 +79,11 @@ struct rpmOption {
     int localize;
 };
 
+static struct rpmat_s {
+    const char *platform;
+    uint64_t hwcap;
+} rpmat;
+
 typedef struct defaultEntry_s {
     char * name;
     char * defName;
@@ -897,6 +908,46 @@ static int is_geode(void)
 }
 #endif
 
+
+#if defined(__linux__)
+/**
+ * Populate rpmat structure with parsed info from /proc/self/auxv
+ */
+static void parse_auxv(void)
+{
+    static int oneshot = 1;
+
+    if (oneshot) {
+       rpmat.platform = "";
+       int fd = open("/proc/self/auxv", O_RDONLY);
+
+       if (fd == -1) {
+           rpmlog(RPMLOG_WARNING,
+                  _("Failed to read auxiliary vector, /proc not mounted?\n"));
+            return;
+       } else {
+           ElfW(auxv_t) auxv;
+           while (read(fd, &auxv, sizeof(auxv)) == sizeof(auxv)) {
+                switch (auxv.a_type)
+                {
+                    case AT_NULL:
+                        break;
+                    case AT_PLATFORM:
+                        rpmat.platform = strdup((char *) auxv.a_un.a_val);
+                        break;
+                    case AT_HWCAP:
+                        rpmat.hwcap = auxv.a_un.a_val;
+                        break;
+                }
+           }
+           close(fd);
+       }
+       oneshot = 0; /* only try once even if it fails */
+    }
+    return;
+}
+#endif
+
 /**
  */
 static void defaultMachine(const char ** arch,
@@ -908,6 +959,11 @@ static void defaultMachine(const char ** arch,
     canonEntry canon;
     int rc;
 
+#if defined(__linux__)
+    /* Populate rpmat struct with hw info */
+    parse_auxv();
+#endif
+
     while (!gotDefaults) {
        if (!rpmPlatform(platform)) {
            char * s = rpmExpand("%{_host_cpu}", NULL);