mirror of
https://github.com/systemd/systemd.git
synced 2024-12-23 21:35:11 +03: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")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly s FirmwareVendor = '...';
|
readonly s FirmwareVendor = '...';
|
||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly s FirmwareDate = '...';
|
readonly t FirmwareDate = ...;
|
||||||
};
|
};
|
||||||
interface org.freedesktop.DBus.Peer { ... };
|
interface org.freedesktop.DBus.Peer { ... };
|
||||||
interface org.freedesktop.DBus.Introspectable { ... };
|
interface org.freedesktop.DBus.Introspectable { ... };
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -52,6 +53,7 @@ typedef struct StatusInfo {
|
|||||||
const char *hardware_vendor;
|
const char *hardware_vendor;
|
||||||
const char *hardware_model;
|
const char *hardware_model;
|
||||||
const char *firmware_version;
|
const char *firmware_version;
|
||||||
|
usec_t firmware_date;
|
||||||
} StatusInfo;
|
} StatusInfo;
|
||||||
|
|
||||||
static const char* chassis_string_to_glyph(const char *chassis) {
|
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);
|
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);
|
r = table_print(table, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return table_log_print_error(r);
|
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) },
|
{ "HardwareVendor", "s", NULL, offsetof(StatusInfo, hardware_vendor) },
|
||||||
{ "HardwareModel", "s", NULL, offsetof(StatusInfo, hardware_model) },
|
{ "HardwareModel", "s", NULL, offsetof(StatusInfo, hardware_model) },
|
||||||
{ "FirmwareVersion", "s", NULL, offsetof(StatusInfo, firmware_version) },
|
{ "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);
|
return get_hardware_firmware_data("bios_vendor", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_firmware_date(char **ret) {
|
static int get_firmware_date(usec_t *ret) {
|
||||||
return get_hardware_firmware_data("bios_date", 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) {
|
static const char* valid_chassis(const char *chassis) {
|
||||||
@ -661,11 +717,11 @@ static int property_get_firmware_date(
|
|||||||
void *userdata,
|
void *userdata,
|
||||||
sd_bus_error *error) {
|
sd_bus_error *error) {
|
||||||
|
|
||||||
_cleanup_free_ char *firmware_date = NULL;
|
usec_t firmware_date = USEC_INFINITY;
|
||||||
|
|
||||||
(void) get_firmware_date(&firmware_date);
|
(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(
|
static int property_get_hostname(
|
||||||
sd_bus *bus,
|
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) {
|
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,
|
_cleanup_free_ char *hn = NULL, *dhn = NULL, *in = NULL, *text = NULL,
|
||||||
*chassis = NULL, *vendor = NULL, *model = NULL, *serial = NULL, *firmware_version = 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_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||||
sd_id128_t product_uuid = SD_ID128_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("HardwareSerial", JSON_BUILD_STRING(serial)),
|
||||||
JSON_BUILD_PAIR("FirmwareVersion", JSON_BUILD_STRING(firmware_version)),
|
JSON_BUILD_PAIR("FirmwareVersion", JSON_BUILD_STRING(firmware_version)),
|
||||||
JSON_BUILD_PAIR("FirmwareVendor", JSON_BUILD_STRING(firmware_vendor)),
|
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_ID128(product_uuid)),
|
||||||
JSON_BUILD_PAIR_CONDITION(sd_id128_is_null(product_uuid), "ProductUUID", JSON_BUILD_NULL)));
|
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("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("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("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_METHOD_WITH_ARGS("SetHostname",
|
||||||
SD_BUS_ARGS("s", hostname, "b", interactive),
|
SD_BUS_ARGS("s", hostname, "b", interactive),
|
||||||
|
@ -89,10 +89,51 @@ test_chassis() {
|
|||||||
fi
|
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
|
: >/failed
|
||||||
|
|
||||||
test_hostname
|
test_hostname
|
||||||
test_chassis
|
test_chassis
|
||||||
|
test_firmware_date
|
||||||
|
|
||||||
touch /testok
|
touch /testok
|
||||||
rm /failed
|
rm /failed
|
||||||
|
Loading…
Reference in New Issue
Block a user