From 533f11c5292ff68aaaaf08cff3570140bb6d1f1b Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Tue, 14 Sep 2021 16:20:20 +0200 Subject: [PATCH 1/2] basic: nulstr-util: add nulstr_get() returning the matching string Currently `nulstr_contains` returns a boolean, making it difficult to identify which of the input strings matches the "needle". Adding a new `nulstr_get()` function, returning a const pointer to the matching string, eases this process and allows us to directly re-use the result of a call to this function without additional processing or memory allocation. Signed-off-by: Arnaud Ferraris --- src/basic/nulstr-util.c | 8 ++++---- src/basic/nulstr-util.h | 6 +++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/basic/nulstr-util.c b/src/basic/nulstr-util.c index 49fcbb0f03..dbafc8c4c9 100644 --- a/src/basic/nulstr-util.c +++ b/src/basic/nulstr-util.c @@ -3,15 +3,15 @@ #include "nulstr-util.h" #include "string-util.h" -bool nulstr_contains(const char *nulstr, const char *needle) { +const char* nulstr_get(const char *nulstr, const char *needle) { const char *i; if (!nulstr) - return false; + return NULL; NULSTR_FOREACH(i, nulstr) if (streq(i, needle)) - return true; + return i; - return false; + return NULL; } diff --git a/src/basic/nulstr-util.h b/src/basic/nulstr-util.h index ee9b632a64..1d1fbc19c0 100644 --- a/src/basic/nulstr-util.h +++ b/src/basic/nulstr-util.h @@ -10,4 +10,8 @@ #define NULSTR_FOREACH_PAIR(i, j, l) \ for ((i) = (l), (j) = strchr((i), 0)+1; (i) && *(i); (i) = strchr((j), 0)+1, (j) = *(i) ? strchr((i), 0)+1 : (i)) -bool nulstr_contains(const char *nulstr, const char *needle); +const char* nulstr_get(const char *nulstr, const char *needle); + +static inline bool nulstr_contains(const char *nulstr, const char *needle) { + return nulstr_get(nulstr, needle); +} From e6e6ca82515d69c58f4940ec8189f78bb5880eb2 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Tue, 14 Sep 2021 15:40:42 +0200 Subject: [PATCH 2/2] hostnamed: add support for getting the chassis type from device-tree Device-tree based devices can't get the chassis type from DMI or ACPI, and so far need a custom `/etc/machine-info` to set this property right. A new 'chassis-type' toplevel device tree property has recently been approved into the DT specification, making it possible to automate chassis type detection on such devices. This patch therefore falls back to reading this device-tree property if nothing is available through both DMI and ACPI. Signed-off-by: Arnaud Ferraris --- src/hostname/hostnamed.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index 2557d6d807..bcd2449861 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -166,10 +166,10 @@ static void context_read_os_release(Context *c) { c->etc_os_release_stat = current_stat; } -static bool valid_chassis(const char *chassis) { +static const char* valid_chassis(const char *chassis) { assert(chassis); - return nulstr_contains( + return nulstr_get( "vm\0" "container\0" "desktop\0" @@ -190,6 +190,7 @@ static bool valid_deployment(const char *deployment) { } static const char* fallback_chassis(void) { + const char *chassis; char *type; unsigned t; int v, r; @@ -261,14 +262,14 @@ try_acpi: r = read_one_line_file("/sys/firmware/acpi/pm_profile", &type); if (r < 0) { log_debug_errno(r, "Failed read ACPI PM profile, ignoring: %m"); - return NULL; + goto try_devicetree; } r = safe_atou(type, &t); free(type); if (r < 0) { log_debug_errno(r, "Failed parse ACPI PM profile, ignoring: %m"); - return NULL; + goto try_devicetree; } /* We only list the really obvious cases here as the ACPI data is not really super reliable. @@ -300,7 +301,24 @@ try_acpi: log_debug("Unhandled ACPI PM profile 0x%02x, ignoring.", t); } - return NULL; +try_devicetree: + r = read_one_line_file("/sys/firmware/devicetree/base/chassis-type", &type); + if (r < 0) { + log_debug_errno(r, "Failed to read device-tree chassis type, ignoring: %m"); + return NULL; + } + + /* Note that the Devicetree specification uses the very same vocabulary + * of chassis types as we do, hence we do not need to translate these types: + * + * https://github.com/devicetree-org/devicetree-specification/blob/master/source/chapter3-devicenodes.rst */ + chassis = valid_chassis(type); + if (!chassis) + log_debug("Invalid device-tree chassis type '%s', ignoring.", type); + + free(type); + + return chassis; } static char* context_fallback_icon_name(Context *c) {