mirror of
https://github.com/systemd/systemd
synced 2024-09-06 16:56:43 +00:00
hostnamed: expose FirmwareDate as timestamp in dbus
Offer the firmware date as an epoch instead of the literal DMI string. Closes #25679
This commit is contained in:
parent
0bdf70f3fa
commit
ad8858c1f7
|
@ -92,7 +92,7 @@ node /org/freedesktop/hostname1 {
|
|||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s FirmwareVendor = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s FirmwareDate = '...';
|
||||
readonly t FirmwareDate = ...;
|
||||
};
|
||||
interface org.freedesktop.DBus.Peer { ... };
|
||||
interface org.freedesktop.DBus.Introspectable { ... };
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <getopt.h>
|
||||
#include <locale.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -52,6 +53,7 @@ typedef struct StatusInfo {
|
|||
const char *hardware_vendor;
|
||||
const char *hardware_model;
|
||||
const char *firmware_version;
|
||||
usec_t firmware_date;
|
||||
} StatusInfo;
|
||||
|
||||
static const char* chassis_string_to_glyph(const char *chassis) {
|
||||
|
@ -239,6 +241,14 @@ static int print_status_info(StatusInfo *i) {
|
|||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
if (timestamp_is_set(i->firmware_date)) {
|
||||
r = table_add_many(table,
|
||||
TABLE_FIELD, "Firmware Date",
|
||||
TABLE_TIMESTAMP, i->firmware_date);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
r = table_print(table, NULL);
|
||||
if (r < 0)
|
||||
return table_log_print_error(r);
|
||||
|
@ -304,6 +314,7 @@ static int show_all_names(sd_bus *bus) {
|
|||
{ "HardwareVendor", "s", NULL, offsetof(StatusInfo, hardware_vendor) },
|
||||
{ "HardwareModel", "s", NULL, offsetof(StatusInfo, hardware_model) },
|
||||
{ "FirmwareVersion", "s", NULL, offsetof(StatusInfo, firmware_version) },
|
||||
{ "FirmwareDate", "t", NULL, offsetof(StatusInfo, firmware_date) },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -250,8 +250,64 @@ static int get_firmware_vendor(char **ret) {
|
|||
return get_hardware_firmware_data("bios_vendor", ret);
|
||||
}
|
||||
|
||||
static int get_firmware_date(char **ret) {
|
||||
return get_hardware_firmware_data("bios_date", ret);
|
||||
static int get_firmware_date(usec_t *ret) {
|
||||
_cleanup_free_ char *bios_date = NULL, *month = NULL, *day = NULL, *year = NULL;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
r = get_hardware_firmware_data("bios_date", &bios_date);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
*ret = USEC_INFINITY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *p = bios_date;
|
||||
r = extract_many_words(&p, "/", EXTRACT_DONT_COALESCE_SEPARATORS, &month, &day, &year, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r != 3) /* less than three args read? */
|
||||
return -EINVAL;
|
||||
if (!isempty(p)) /* more left in the string? */
|
||||
return -EINVAL;
|
||||
|
||||
unsigned m, d, y;
|
||||
r = safe_atou(month, &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (m < 1 || m > 12)
|
||||
return -EINVAL;
|
||||
m -= 1;
|
||||
|
||||
r = safe_atou(day, &d);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (d < 1 || d > 31)
|
||||
return -EINVAL;
|
||||
|
||||
r = safe_atou(year, &y);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (y < 1970 || y > (unsigned) INT_MAX)
|
||||
return -EINVAL;
|
||||
y -= 1900;
|
||||
|
||||
struct tm tm = {
|
||||
.tm_mday = d,
|
||||
.tm_mon = m,
|
||||
.tm_year = y,
|
||||
};
|
||||
time_t v = timegm(&tm);
|
||||
if (v == (time_t) -1)
|
||||
return -errno;
|
||||
if (tm.tm_mday != (int) d || tm.tm_mon != (int) m || tm.tm_year != (int) y)
|
||||
return -EINVAL; /* date was not normalized? (e.g. "30th of feb") */
|
||||
|
||||
*ret = (usec_t) v * USEC_PER_SEC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* valid_chassis(const char *chassis) {
|
||||
|
@ -661,11 +717,11 @@ static int property_get_firmware_date(
|
|||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
_cleanup_free_ char *firmware_date = NULL;
|
||||
usec_t firmware_date = USEC_INFINITY;
|
||||
|
||||
(void) get_firmware_date(&firmware_date);
|
||||
|
||||
return sd_bus_message_append(reply, "s", firmware_date);
|
||||
return sd_bus_message_append(reply, "t", firmware_date);
|
||||
}
|
||||
static int property_get_hostname(
|
||||
sd_bus *bus,
|
||||
|
@ -1189,7 +1245,8 @@ static int method_get_hardware_serial(sd_bus_message *m, void *userdata, sd_bus_
|
|||
static int method_describe(sd_bus_message *m, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_free_ char *hn = NULL, *dhn = NULL, *in = NULL, *text = NULL,
|
||||
*chassis = NULL, *vendor = NULL, *model = NULL, *serial = NULL, *firmware_version = NULL,
|
||||
*firmware_vendor = NULL, *firmware_date = NULL;
|
||||
*firmware_vendor = NULL;
|
||||
usec_t firmware_date = USEC_INFINITY;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
sd_id128_t product_uuid = SD_ID128_NULL;
|
||||
|
@ -1277,7 +1334,7 @@ static int method_describe(sd_bus_message *m, void *userdata, sd_bus_error *erro
|
|||
JSON_BUILD_PAIR("HardwareSerial", JSON_BUILD_STRING(serial)),
|
||||
JSON_BUILD_PAIR("FirmwareVersion", JSON_BUILD_STRING(firmware_version)),
|
||||
JSON_BUILD_PAIR("FirmwareVendor", JSON_BUILD_STRING(firmware_vendor)),
|
||||
JSON_BUILD_PAIR("FirmwareDate", JSON_BUILD_STRING(firmware_date)),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("FirmwareDate", firmware_date),
|
||||
JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(product_uuid), "ProductUUID", JSON_BUILD_ID128(product_uuid)),
|
||||
JSON_BUILD_PAIR_CONDITION(sd_id128_is_null(product_uuid), "ProductUUID", JSON_BUILD_NULL)));
|
||||
|
||||
|
@ -1320,7 +1377,7 @@ static const sd_bus_vtable hostname_vtable[] = {
|
|||
SD_BUS_PROPERTY("HardwareModel", "s", property_get_hardware_model, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("FirmwareVersion", "s", property_get_firmware_version, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("FirmwareVendor", "s", property_get_firmware_vendor, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("FirmwareDate", "s", property_get_firmware_date, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("FirmwareDate", "t", property_get_firmware_date, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
||||
SD_BUS_METHOD_WITH_ARGS("SetHostname",
|
||||
SD_BUS_ARGS("s", hostname, "b", interactive),
|
||||
|
|
|
@ -89,10 +89,51 @@ test_chassis() {
|
|||
fi
|
||||
}
|
||||
|
||||
restore_sysfs_dmi() {
|
||||
umount /sys/class/dmi/id
|
||||
rm -rf /run/systemd/system/systemd-hostnamed.service.d
|
||||
systemctl daemon-reload
|
||||
systemctl stop systemd-hostnamed
|
||||
}
|
||||
|
||||
test_firmware_date() {
|
||||
# No DMI on s390x or ppc
|
||||
if [[ ! -d /sys/class/dmi/id ]]; then
|
||||
echo "/sys/class/dmi/id not found, skipping firmware date tests."
|
||||
return 0
|
||||
fi
|
||||
|
||||
trap restore_sysfs_dmi RETURN
|
||||
|
||||
# Ignore /sys being mounted as tmpfs
|
||||
mkdir -p /run/systemd/system/systemd-hostnamed.service.d/
|
||||
cat >/run/systemd/system/systemd-hostnamed.service.d/override.conf <<EOF
|
||||
[Service]
|
||||
Environment="SYSTEMD_DEVICE_VERIFY_SYSFS=0"
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
|
||||
mount -t tmpfs none /sys/class/dmi/id
|
||||
echo '1' > /sys/class/dmi/id/uevent
|
||||
|
||||
echo '01/01/2000' > /sys/class/dmi/id/bios_date
|
||||
systemctl stop systemd-hostnamed
|
||||
assert_in '2000-01-01' "$(hostnamectl)"
|
||||
|
||||
echo '2022' > /sys/class/dmi/id/bios_date
|
||||
systemctl stop systemd-hostnamed
|
||||
assert_not_in 'Firmware Date' "$(hostnamectl)"
|
||||
|
||||
echo 'garbage' > /sys/class/dmi/id/bios_date
|
||||
systemctl stop systemd-hostnamed
|
||||
assert_not_in 'Firmware Date' "$(hostnamectl)"
|
||||
}
|
||||
|
||||
: >/failed
|
||||
|
||||
test_hostname
|
||||
test_chassis
|
||||
test_firmware_date
|
||||
|
||||
touch /testok
|
||||
rm /failed
|
||||
|
|
Loading…
Reference in a new issue