]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
virt: make virtualization enum a named type
authorLennart Poettering <lennart@poettering.net>
Mon, 4 Apr 2022 09:19:44 +0000 (11:19 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 4 Apr 2022 09:36:26 +0000 (11:36 +0200)
These days we have a mechanism for safely returning errnos in enum
types, via definining -ERRNO_MAX as one special enu value. Let's use
that for Virtualization.

No change in behaviour, just some typesafety improvement.

src/basic/virt.c
src/basic/virt.h
src/core/dbus-manager.c
src/detect-virt/detect-virt.c
src/hostname/hostnamed.c
src/shared/condition.c
src/test/test-architecture.c
src/test/test-barrier.c

index 9bef46c9d1a589918531f43adbe8b2e56ea672b6..d3ac64c7e15daaf2906b23d033102d623201c59f 100644 (file)
@@ -28,14 +28,14 @@ enum {
       SMBIOS_VM_BIT_UNKNOWN,
 };
 
-static int detect_vm_cpuid(void) {
+static Virtualization detect_vm_cpuid(void) {
 
         /* CPUID is an x86 specific interface. */
 #if defined(__i386__) || defined(__x86_64__)
 
         static const struct {
                 const char sig[13];
-                int id;
+                Virtualization id;
         } vm_table[] = {
                 { "XenVMMXenVMM", VIRTUALIZATION_XEN       },
                 { "KVMKVMKVM",    VIRTUALIZATION_KVM       }, /* qemu with KVM */
@@ -92,7 +92,7 @@ static int detect_vm_cpuid(void) {
         return VIRTUALIZATION_NONE;
 }
 
-static int detect_vm_device_tree(void) {
+static Virtualization detect_vm_device_tree(void) {
 #if defined(__arm__) || defined(__aarch64__) || defined(__powerpc__) || defined(__powerpc64__)
         _cleanup_free_ char *hvtype = NULL;
         int r;
@@ -142,7 +142,7 @@ static int detect_vm_device_tree(void) {
 }
 
 #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch64)
-static int detect_vm_dmi_vendor(void) {
+static Virtualization detect_vm_dmi_vendor(void) {
         static const char *const dmi_vendors[] = {
                 "/sys/class/dmi/id/product_name", /* Test this before sys_vendor to detect KVM over QEMU */
                 "/sys/class/dmi/id/sys_vendor",
@@ -153,7 +153,7 @@ static int detect_vm_dmi_vendor(void) {
 
         static const struct {
                 const char *vendor;
-                int id;
+                Virtualization id;
         } dmi_vendor_table[] = {
                 { "KVM",                 VIRTUALIZATION_KVM       },
                 { "Amazon EC2",          VIRTUALIZATION_AMAZON    },
@@ -230,7 +230,7 @@ static int detect_vm_smbios(void) {
 }
 #endif /* defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch64) */
 
-static int detect_vm_dmi(void) {
+static Virtualization detect_vm_dmi(void) {
 #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch64)
 
         int r;
@@ -332,7 +332,7 @@ static int detect_vm_xen_dom0(void) {
         }
 }
 
-static int detect_vm_xen(void) {
+static Virtualization detect_vm_xen(void) {
         /* The presence of /proc/xen indicates some form of a Xen domain
            The check for Dom0 is handled outside this function */
         if (access("/proc/xen", F_OK) < 0) {
@@ -343,7 +343,7 @@ static int detect_vm_xen(void) {
         return VIRTUALIZATION_XEN;
 }
 
-static int detect_vm_hypervisor(void) {
+static Virtualization detect_vm_hypervisor(void) {
         _cleanup_free_ char *hvtype = NULL;
         int r;
 
@@ -361,7 +361,7 @@ static int detect_vm_hypervisor(void) {
                 return VIRTUALIZATION_VM_OTHER;
 }
 
-static int detect_vm_uml(void) {
+static Virtualization detect_vm_uml(void) {
         _cleanup_fclose_ FILE *f = NULL;
         int r;
 
@@ -400,7 +400,7 @@ static int detect_vm_uml(void) {
         return VIRTUALIZATION_NONE;
 }
 
-static int detect_vm_zvm(void) {
+static Virtualization detect_vm_zvm(void) {
 
 #if defined(__s390__)
         _cleanup_free_ char *t = NULL;
@@ -424,10 +424,11 @@ static int detect_vm_zvm(void) {
 }
 
 /* Returns a short identifier for the various VM implementations */
-int detect_vm(void) {
-        static thread_local int cached_found = _VIRTUALIZATION_INVALID;
+Virtualization detect_vm(void) {
+        static thread_local Virtualization cached_found = _VIRTUALIZATION_INVALID;
         bool other = false;
-        int r, dmi, xen_dom0 = 0;
+        int xen_dom0 = 0;
+        Virtualization v, dmi;
 
         if (cached_found >= 0)
                 return cached_found;
@@ -446,22 +447,22 @@ int detect_vm(void) {
 
         dmi = detect_vm_dmi();
         if (IN_SET(dmi, VIRTUALIZATION_ORACLE, VIRTUALIZATION_XEN, VIRTUALIZATION_AMAZON)) {
-                r = dmi;
+                v = dmi;
                 goto finish;
         }
 
         /* Detect UML */
-        r = detect_vm_uml();
-        if (r < 0)
-                return r;
-        if (r != VIRTUALIZATION_NONE)
+        v = detect_vm_uml();
+        if (v < 0)
+                return v;
+        if (v != VIRTUALIZATION_NONE)
                 goto finish;
 
         /* Detect Xen */
-        r = detect_vm_xen();
-        if (r < 0)
-                return r;
-        if (r == VIRTUALIZATION_XEN) {
+        v = detect_vm_xen();
+        if (v < 0)
+                return v;
+        if (v == VIRTUALIZATION_XEN) {
                  /* If we are Dom0, then we expect to not report as a VM. However, as we might be nested
                   * inside another hypervisor which can be detected via the CPUID check, wait to report this
                   * until after the CPUID check. */
@@ -471,17 +472,17 @@ int detect_vm(void) {
                 if (xen_dom0 == 0)
                         goto finish;
 
-                r = VIRTUALIZATION_NONE;
-        } else if (r != VIRTUALIZATION_NONE)
+                v = VIRTUALIZATION_NONE;
+        } else if (v != VIRTUALIZATION_NONE)
                 assert_not_reached();
 
         /* Detect from CPUID */
-        r = detect_vm_cpuid();
-        if (r < 0)
-                return r;
-        if (r == VIRTUALIZATION_VM_OTHER)
+        v = detect_vm_cpuid();
+        if (v < 0)
+                return v;
+        if (v == VIRTUALIZATION_VM_OTHER)
                 other = true;
-        else if (r != VIRTUALIZATION_NONE)
+        else if (v != VIRTUALIZATION_NONE)
                 goto finish;
 
         /* If we are in Dom0 and have not yet finished, finish with the result of detect_vm_cpuid */
@@ -494,38 +495,38 @@ int detect_vm(void) {
         if (dmi == VIRTUALIZATION_VM_OTHER)
                 other = true;
         else if (dmi != VIRTUALIZATION_NONE) {
-                r = dmi;
+                v = dmi;
                 goto finish;
         }
 
         /* Check high-level hypervisor sysfs file */
-        r = detect_vm_hypervisor();
-        if (r < 0)
-                return r;
-        if (r == VIRTUALIZATION_VM_OTHER)
+        v = detect_vm_hypervisor();
+        if (v < 0)
+                return v;
+        if (v == VIRTUALIZATION_VM_OTHER)
                 other = true;
-        else if (r != VIRTUALIZATION_NONE)
+        else if (v != VIRTUALIZATION_NONE)
                 goto finish;
 
-        r = detect_vm_device_tree();
-        if (r < 0)
-                return r;
-        if (r == VIRTUALIZATION_VM_OTHER)
+        v = detect_vm_device_tree();
+        if (v < 0)
+                return v;
+        if (v == VIRTUALIZATION_VM_OTHER)
                 other = true;
-        else if (r != VIRTUALIZATION_NONE)
+        else if (v != VIRTUALIZATION_NONE)
                 goto finish;
 
-        r = detect_vm_zvm();
-        if (r < 0)
-                return r;
+        v = detect_vm_zvm();
+        if (v < 0)
+                return v;
 
 finish:
-        if (r == VIRTUALIZATION_NONE && other)
-                r = VIRTUALIZATION_VM_OTHER;
+        if (v == VIRTUALIZATION_NONE && other)
+                v = VIRTUALIZATION_VM_OTHER;
 
-        cached_found = r;
-        log_debug("Found VM virtualization %s", virtualization_to_string(r));
-        return r;
+        cached_found = v;
+        log_debug("Found VM virtualization %s", virtualization_to_string(v));
+        return v;
 }
 
 static const char *const container_table[_VIRTUALIZATION_MAX] = {
@@ -608,12 +609,12 @@ static int running_in_cgroupns(void) {
         }
 }
 
-static int detect_container_files(void) {
+static Virtualization detect_container_files(void) {
         unsigned i;
 
         static const struct {
                 const char *file_path;
-                int id;
+                Virtualization id;
         } container_file_table[] = {
                 /* https://github.com/containers/podman/issues/6192 */
                 /* https://github.com/containers/podman/issues/3586#issuecomment-661918679 */
@@ -636,10 +637,11 @@ static int detect_container_files(void) {
         return VIRTUALIZATION_NONE;
 }
 
-int detect_container(void) {
-        static thread_local int cached_found = _VIRTUALIZATION_INVALID;
+Virtualization detect_container(void) {
+        static thread_local Virtualization cached_found = _VIRTUALIZATION_INVALID;
         _cleanup_free_ char *m = NULL, *o = NULL, *p = NULL;
         const char *e = NULL;
+        Virtualization v;
         int r;
 
         if (cached_found >= 0)
@@ -651,7 +653,7 @@ int detect_container(void) {
                         log_debug_errno(errno, "Failed to check if /proc/vz exists, ignoring: %m");
         } else if (access("/proc/bc", F_OK) < 0) {
                 if (errno == ENOENT) {
-                        r = VIRTUALIZATION_OPENVZ;
+                        v = VIRTUALIZATION_OPENVZ;
                         goto finish;
                 }
 
@@ -663,7 +665,7 @@ int detect_container(void) {
         if (r < 0)
                 log_debug_errno(r, "Failed to read /proc/sys/kernel/osrelease, ignoring: %m");
         else if (strstr(o, "Microsoft") || strstr(o, "WSL")) {
-                r = VIRTUALIZATION_WSL;
+                v = VIRTUALIZATION_WSL;
                 goto finish;
         }
 
@@ -688,7 +690,7 @@ int detect_container(void) {
                         if (r < 0)
                                 log_debug_errno(r, "Failed to read %s, ignoring: %m", pf);
                         else if (startswith(ptrace_comm, "proot")) {
-                                r = VIRTUALIZATION_PROOT;
+                                v = VIRTUALIZATION_PROOT;
                                 goto finish;
                         }
                 }
@@ -715,7 +717,7 @@ int detect_container(void) {
                 if (!e)
                         goto check_files;
                 if (isempty(e)) {
-                        r = VIRTUALIZATION_NONE;
+                        v = VIRTUALIZATION_NONE;
                         goto finish;
                 }
 
@@ -746,49 +748,51 @@ check_files:
          * for other specific container managers, otherwise we risk mistaking another
          * container manager for Docker: the /.dockerenv file could inadvertently end up
          * in a file system image. */
-        r = detect_container_files();
-        if (r)
+        v = detect_container_files();
+        if (v < 0)
+                return v;
+        if (v != VIRTUALIZATION_NONE)
                 goto finish;
 
         r = running_in_cgroupns();
         if (r > 0) {
-                r = VIRTUALIZATION_CONTAINER_OTHER;
+                v = VIRTUALIZATION_CONTAINER_OTHER;
                 goto finish;
         }
         if (r < 0)
                 log_debug_errno(r, "Failed to detect cgroup namespace: %m");
 
         /* If none of that worked, give up, assume no container manager. */
-        r = VIRTUALIZATION_NONE;
+        v = VIRTUALIZATION_NONE;
         goto finish;
 
 translate_name:
         if (streq(e, "oci")) {
                 /* Some images hardcode container=oci, but OCI is not a specific container manager.
                  * Try to detect one based on well-known files. */
-                r = detect_container_files();
-                if (!r)
-                        r = VIRTUALIZATION_CONTAINER_OTHER;
+                v = detect_container_files();
+                if (v != VIRTUALIZATION_NONE)
+                        v = VIRTUALIZATION_CONTAINER_OTHER;
                 goto finish;
         }
-        r = container_from_string(e);
-        if (r < 0)
-                r = VIRTUALIZATION_CONTAINER_OTHER;
+        v = container_from_string(e);
+        if (v < 0)
+                v = VIRTUALIZATION_CONTAINER_OTHER;
 
 finish:
-        log_debug("Found container virtualization %s.", virtualization_to_string(r));
-        cached_found = r;
-        return r;
+        log_debug("Found container virtualization %s.", virtualization_to_string(v));
+        cached_found = v;
+        return v;
 }
 
-int detect_virtualization(void) {
-        int r;
+Virtualization detect_virtualization(void) {
+        int v;
 
-        r = detect_container();
-        if (r == 0)
-                r = detect_vm();
+        v = detect_container();
+        if (v != VIRTUALIZATION_NONE)
+                return v;
 
-        return r;
+        return detect_vm();
 }
 
 static int userns_has_mapping(const char *name) {
@@ -1025,4 +1029,4 @@ static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
         [VIRTUALIZATION_CONTAINER_OTHER] = "container-other",
 };
 
-DEFINE_STRING_TABLE_LOOKUP(virtualization, int);
+DEFINE_STRING_TABLE_LOOKUP(virtualization, Virtualization);
index 1eafbe2cbecfc92bbc730430f39b5a6423a8a581..6da08b4af141fe9f3aabec9b2314499d9f48d757 100644 (file)
@@ -3,9 +3,10 @@
 
 #include <stdbool.h>
 
+#include "errno-list.h"
 #include "macro.h"
 
-enum {
+typedef enum Virtualization {
         VIRTUALIZATION_NONE = 0,
 
         VIRTUALIZATION_VM_FIRST,
@@ -43,23 +44,24 @@ enum {
 
         _VIRTUALIZATION_MAX,
         _VIRTUALIZATION_INVALID = -EINVAL,
-};
+        _VIRTUALIZATION_ERRNO_MAX = -ERRNO_MAX, /* ensure full range of errno fits into this enum */
+} Virtualization;
 
-static inline bool VIRTUALIZATION_IS_VM(int x) {
+static inline bool VIRTUALIZATION_IS_VM(Virtualization x) {
         return x >= VIRTUALIZATION_VM_FIRST && x <= VIRTUALIZATION_VM_LAST;
 }
 
-static inline bool VIRTUALIZATION_IS_CONTAINER(int x) {
+static inline bool VIRTUALIZATION_IS_CONTAINER(Virtualization x) {
         return x >= VIRTUALIZATION_CONTAINER_FIRST && x <= VIRTUALIZATION_CONTAINER_LAST;
 }
 
-int detect_vm(void);
-int detect_container(void);
-int detect_virtualization(void);
+Virtualization detect_vm(void);
+Virtualization detect_container(void);
+Virtualization detect_virtualization(void);
 
 int running_in_userns(void);
 int running_in_chroot(void);
 
-const char *virtualization_to_string(int v) _const_;
-int virtualization_from_string(const char *s) _pure_;
+const char *virtualization_to_string(Virtualization v) _const_;
+Virtualization virtualization_from_string(const char *s) _pure_;
 bool has_cpu_with_flag(const char *flag);
index 6bf4e6bf762f6a86f4b3a470e948e96cc1af9293..156071f168158d5928701f994da0c95371c5261d 100644 (file)
@@ -71,7 +71,7 @@ static int property_get_virtualization(
                 void *userdata,
                 sd_bus_error *error) {
 
-        int v;
+        Virtualization v;
 
         assert(bus);
         assert(reply);
index d284fcbe82abac98460c8b6211d2e88873836147..af2a58b78d4f0b27a0f4af00f91d3d96ed1da629 100644 (file)
@@ -102,7 +102,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_LIST:
-                        DUMP_STRING_TABLE(virtualization, int, _VIRTUALIZATION_MAX);
+                        DUMP_STRING_TABLE(virtualization, Virtualization, _VIRTUALIZATION_MAX);
                         return 0;
 
                 case '?':
@@ -121,6 +121,7 @@ static int parse_argv(int argc, char *argv[]) {
 }
 
 static int run(int argc, char *argv[]) {
+        Virtualization v;
         int r;
 
         /* This is mostly intended to be used for scripts which want
@@ -135,15 +136,15 @@ static int run(int argc, char *argv[]) {
 
         switch (arg_mode) {
         case ONLY_VM:
-                r = detect_vm();
-                if (r < 0)
-                        return log_error_errno(r, "Failed to check for VM: %m");
+                v = detect_vm();
+                if (v < 0)
+                        return log_error_errno(v, "Failed to check for VM: %m");
                 break;
 
         case ONLY_CONTAINER:
-                r = detect_container();
-                if (r < 0)
-                        return log_error_errno(r, "Failed to check for container: %m");
+                v = detect_container();
+                if (v < 0)
+                        return log_error_errno(v, "Failed to check for container: %m");
                 break;
 
         case ONLY_CHROOT:
@@ -160,16 +161,16 @@ static int run(int argc, char *argv[]) {
 
         case ANY_VIRTUALIZATION:
         default:
-                r = detect_virtualization();
-                if (r < 0)
-                        return log_error_errno(r, "Failed to check for virtualization: %m");
+                v = detect_virtualization();
+                if (v < 0)
+                        return log_error_errno(v, "Failed to check for virtualization: %m");
                 break;
         }
 
         if (!arg_quiet)
-                puts(virtualization_to_string(r));
+                puts(virtualization_to_string(v));
 
-        return r == VIRTUALIZATION_NONE;
+        return v == VIRTUALIZATION_NONE;
 }
 
 DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);
index 6c69818230782fb4169b6cd84dd4a70c04402bf3..b855b411121736b60261fd83d172a584d41496c3 100644 (file)
@@ -261,8 +261,9 @@ static bool valid_deployment(const char *deployment) {
 static const char* fallback_chassis(void) {
         const char *chassis;
         _cleanup_free_ char *type = NULL;
+        Virtualization v;
         unsigned t;
-        int v, r;
+        int r;
 
         v = detect_virtualization();
         if (v < 0)
index 8165513cc97b82d5e3838ed6ce072d1114f43a1c..ea334bfeb75ffc55e6c2749c000587ce4102a930 100644 (file)
@@ -459,7 +459,8 @@ static int condition_test_group(Condition *c, char **env) {
 }
 
 static int condition_test_virtualization(Condition *c, char **env) {
-        int b, v;
+        Virtualization v;
+        int b;
 
         assert(c);
         assert(c->parameter);
@@ -475,7 +476,7 @@ static int condition_test_virtualization(Condition *c, char **env) {
         /* First, compare with yes/no */
         b = parse_boolean(c->parameter);
         if (b >= 0)
-                return b == !!v;
+                return b == (v != VIRTUALIZATION_NONE);
 
         /* Then, compare categorization */
         if (streq(c->parameter, "vm"))
index 798c95c0e91ac3197ab2b0471615ee6bf0664ef0..6455e5c2fa7e0e5276c9963b55597aa0166ac8ca 100644 (file)
@@ -1,14 +1,16 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include "architecture.h"
+#include "errno-util.h"
 #include "log.h"
 #include "tests.h"
 #include "util.h"
 #include "virt.h"
 
 int main(int argc, char *argv[]) {
-        int a, v;
+        Virtualization v;
         const char *p;
+        int a;
 
         test_setup_logging(LOG_INFO);
 
@@ -20,7 +22,7 @@ int main(int argc, char *argv[]) {
         assert_se(architecture_from_string(architecture_to_string(1)) == 1);
 
         v = detect_virtualization();
-        if (IN_SET(v, -EPERM, -EACCES))
+        if (v < 0 && ERRNO_IS_PRIVILEGE(v))
                 return log_tests_skipped("Cannot detect virtualization");
 
         assert_se(v >= 0);
index bbd7e2bddb907db999a6682c4e6001015148f6c2..50ceb3a35595783f693150aadbd98a414c425f87 100644 (file)
 #include <unistd.h>
 
 #include "barrier.h"
-#include "util.h"
+#include "errno-util.h"
 #include "tests.h"
-#include "virt.h"
 #include "time-util.h"
+#include "util.h"
+#include "virt.h"
 
 /* 20ms to test deadlocks; All timings use multiples of this constant as
  * alarm/sleep timers. If this timeout is too small for slow machines to perform
@@ -434,8 +435,8 @@ static int intro(void) {
          * false-positives in CIs.
          */
 
-        int v = detect_virtualization();
-        if (IN_SET(v, -EPERM, -EACCES))
+        Virtualization v = detect_virtualization();
+        if (v < 0 && ERRNO_IS_PRIVILEGE(v))
                 return log_tests_skipped("Cannot detect virtualization");
 
         if (v != VIRTUALIZATION_NONE)