b11b5f
From efa2cdb699df3e5d5d7180e50f3ebfff74788c5c Mon Sep 17 00:00:00 2001
b11b5f
From: Yu Watanabe <watanabe.yu+github@gmail.com>
b11b5f
Date: Tue, 7 Jan 2020 11:49:39 +0900
b11b5f
Subject: [PATCH] virt: use string table to detect VM or container
b11b5f
b11b5f
(cherry picked from commit 735ea55f5cd87a82757a8911edd80fba799b46ee)
b11b5f
b11b5f
Related: #2117948
b11b5f
---
b11b5f
 src/basic/virt.c | 73 ++++++++++++++++++++++--------------------------
b11b5f
 1 file changed, 33 insertions(+), 40 deletions(-)
b11b5f
b11b5f
diff --git a/src/basic/virt.c b/src/basic/virt.c
b11b5f
index 78c68d66e0..6e4c702051 100644
b11b5f
--- a/src/basic/virt.c
b11b5f
+++ b/src/basic/virt.c
b11b5f
@@ -22,27 +22,26 @@
b11b5f
 #include "string-util.h"
b11b5f
 #include "virt.h"
b11b5f
 
b11b5f
+static const char *const vm_table[_VIRTUALIZATION_MAX] = {
b11b5f
+        [VIRTUALIZATION_XEN]       = "XenVMMXenVMM",
b11b5f
+        [VIRTUALIZATION_KVM]       = "KVMKVMKVM",
b11b5f
+        [VIRTUALIZATION_QEMU]      = "TCGTCGTCGTCG",
b11b5f
+        /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
b11b5f
+        [VIRTUALIZATION_VMWARE]    = "VMwareVMware",
b11b5f
+        /* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs */
b11b5f
+        [VIRTUALIZATION_MICROSOFT] = "Microsoft Hv",
b11b5f
+        /* https://wiki.freebsd.org/bhyve */
b11b5f
+        [VIRTUALIZATION_BHYVE]     = "bhyve bhyve ",
b11b5f
+        [VIRTUALIZATION_QNX]       = "QNXQVMBSQG",
b11b5f
+};
b11b5f
+
b11b5f
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(vm, int);
b11b5f
+
b11b5f
 static int detect_vm_cpuid(void) {
b11b5f
 
b11b5f
         /* CPUID is an x86 specific interface. */
b11b5f
 #if defined(__i386__) || defined(__x86_64__)
b11b5f
 
b11b5f
-        static const struct {
b11b5f
-                const char *cpuid;
b11b5f
-                int id;
b11b5f
-        } cpuid_vendor_table[] = {
b11b5f
-                { "XenVMMXenVMM", VIRTUALIZATION_XEN       },
b11b5f
-                { "KVMKVMKVM",    VIRTUALIZATION_KVM       },
b11b5f
-                { "TCGTCGTCGTCG", VIRTUALIZATION_QEMU      },
b11b5f
-                /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
b11b5f
-                { "VMwareVMware", VIRTUALIZATION_VMWARE    },
b11b5f
-                /* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs */
b11b5f
-                { "Microsoft Hv", VIRTUALIZATION_MICROSOFT },
b11b5f
-                /* https://wiki.freebsd.org/bhyve */
b11b5f
-                { "bhyve bhyve ", VIRTUALIZATION_BHYVE     },
b11b5f
-                { "QNXQVMBSQG",   VIRTUALIZATION_QNX       },
b11b5f
-        };
b11b5f
-
b11b5f
         uint32_t eax, ebx, ecx, edx;
b11b5f
         bool hypervisor;
b11b5f
 
b11b5f
@@ -59,7 +58,7 @@ static int detect_vm_cpuid(void) {
b11b5f
                         uint32_t sig32[3];
b11b5f
                         char text[13];
b11b5f
                 } sig = {};
b11b5f
-                unsigned j;
b11b5f
+                int v;
b11b5f
 
b11b5f
                 /* There is a hypervisor, see what it is */
b11b5f
                 __cpuid(0x40000000U, eax, ebx, ecx, edx);
b11b5f
@@ -70,11 +69,11 @@ static int detect_vm_cpuid(void) {
b11b5f
 
b11b5f
                 log_debug("Virtualization found, CPUID=%s", sig.text);
b11b5f
 
b11b5f
-                for (j = 0; j < ELEMENTSOF(cpuid_vendor_table); j ++)
b11b5f
-                        if (streq(sig.text, cpuid_vendor_table[j].cpuid))
b11b5f
-                                return cpuid_vendor_table[j].id;
b11b5f
+                v = vm_from_string(sig.text);
b11b5f
+                if (v < 0)
b11b5f
+                        return VIRTUALIZATION_VM_OTHER;
b11b5f
 
b11b5f
-                return VIRTUALIZATION_VM_OTHER;
b11b5f
+                return v;
b11b5f
         }
b11b5f
 #endif
b11b5f
         log_debug("No virtualization found in CPUID");
b11b5f
@@ -434,22 +433,20 @@ finish:
b11b5f
         return r;
b11b5f
 }
b11b5f
 
b11b5f
-int detect_container(void) {
b11b5f
-        static const struct {
b11b5f
-                const char *value;
b11b5f
-                int id;
b11b5f
-        } value_table[] = {
b11b5f
-                { "lxc",            VIRTUALIZATION_LXC            },
b11b5f
-                { "lxc-libvirt",    VIRTUALIZATION_LXC_LIBVIRT    },
b11b5f
-                { "systemd-nspawn", VIRTUALIZATION_SYSTEMD_NSPAWN },
b11b5f
-                { "docker",         VIRTUALIZATION_DOCKER         },
b11b5f
-                { "rkt",            VIRTUALIZATION_RKT            },
b11b5f
-        };
b11b5f
+static const char *const container_table[_VIRTUALIZATION_MAX] = {
b11b5f
+        [VIRTUALIZATION_LXC]            = "lxc",
b11b5f
+        [VIRTUALIZATION_LXC_LIBVIRT]    = "lxc-libvirt",
b11b5f
+        [VIRTUALIZATION_SYSTEMD_NSPAWN] = "systemd-nspawn",
b11b5f
+        [VIRTUALIZATION_DOCKER]         = "docker",
b11b5f
+        [VIRTUALIZATION_RKT]            = "rkt",
b11b5f
+};
b11b5f
+
b11b5f
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(container, int);
b11b5f
 
b11b5f
+int detect_container(void) {
b11b5f
         static thread_local int cached_found = _VIRTUALIZATION_INVALID;
b11b5f
         _cleanup_free_ char *m = NULL;
b11b5f
         const char *e = NULL;
b11b5f
-        unsigned j;
b11b5f
         int r;
b11b5f
 
b11b5f
         if (cached_found >= 0)
b11b5f
@@ -522,13 +519,9 @@ int detect_container(void) {
b11b5f
         goto finish;
b11b5f
 
b11b5f
 translate_name:
b11b5f
-        for (j = 0; j < ELEMENTSOF(value_table); j++)
b11b5f
-                if (streq(e, value_table[j].value)) {
b11b5f
-                        r = value_table[j].id;
b11b5f
-                        goto finish;
b11b5f
-                }
b11b5f
-
b11b5f
-        r = VIRTUALIZATION_CONTAINER_OTHER;
b11b5f
+        r = container_from_string(e);
b11b5f
+        if (r < 0)
b11b5f
+                r = VIRTUALIZATION_CONTAINER_OTHER;
b11b5f
 
b11b5f
 finish:
b11b5f
         log_debug("Found container virtualization %s.", virtualization_to_string(r));