mirror of
https://github.com/systemd/systemd
synced 2024-10-15 12:34:37 +00:00
Merge pull request #26158 from poettering/hostnamed-end-of-support
hostnamed/hostnamectl: support os-release END_OF_SUPPORT= field
This commit is contained in:
commit
4476fdd4c2
3
TODO
3
TODO
|
@ -639,9 +639,6 @@ Features:
|
|||
forked-but-not-exec'ed children
|
||||
4. Add varlink API to run transient units based on provided JSON definitions
|
||||
|
||||
* show SUPPORT_END= data in "hostnamectl" output (and thus also expose a prop
|
||||
for this on dbus)
|
||||
|
||||
* Add SUPPORT_END_URL= field to os-release with more *actionable* information
|
||||
what to do if support ended
|
||||
|
||||
|
|
|
@ -82,6 +82,8 @@ node /org/freedesktop/hostname1 {
|
|||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s OperatingSystemCPEName = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly t OperatingSystemSupportEnd = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s HomeURL = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s HardwareVendor = '...';
|
||||
|
@ -102,6 +104,8 @@ node /org/freedesktop/hostname1 {
|
|||
|
||||
<!--method GetHardwareSerial is not documented!-->
|
||||
|
||||
<!--property OperatingSystemSupportEnd is not documented!-->
|
||||
|
||||
<!--property HardwareVendor is not documented!-->
|
||||
|
||||
<!--property HardwareModel is not documented!-->
|
||||
|
@ -166,6 +170,8 @@ node /org/freedesktop/hostname1 {
|
|||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="OperatingSystemCPEName"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="OperatingSystemSupportEnd"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="HomeURL"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="HardwareVendor"/>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "bus-error.h"
|
||||
#include "bus-map-properties.h"
|
||||
#include "format-table.h"
|
||||
#include "os-util.h"
|
||||
#include "sort-util.h"
|
||||
#include "version.h"
|
||||
|
||||
|
@ -283,7 +284,7 @@ static int produce_plot_as_svg(
|
|||
svg("<text x=\"20\" y=\"50\">%s</text>", pretty_times);
|
||||
if (host)
|
||||
svg("<text x=\"20\" y=\"30\">%s %s (%s %s %s) %s %s</text>",
|
||||
isempty(host->os_pretty_name) ? "Linux" : host->os_pretty_name,
|
||||
os_release_pretty_name(host->os_pretty_name, NULL),
|
||||
strempty(host->hostname),
|
||||
strempty(host->kernel_name),
|
||||
strempty(host->kernel_release),
|
||||
|
|
|
@ -336,7 +336,7 @@ int load_extension_release_pairs(const char *root, const char *extension, bool r
|
|||
return load_env_file_pairs(f, p, ret);
|
||||
}
|
||||
|
||||
int os_release_support_ended(const char *support_end, bool quiet) {
|
||||
int os_release_support_ended(const char *support_end, bool quiet, usec_t *ret_eol) {
|
||||
_cleanup_free_ char *_support_end_alloc = NULL;
|
||||
int r;
|
||||
|
||||
|
@ -346,27 +346,38 @@ int os_release_support_ended(const char *support_end, bool quiet) {
|
|||
|
||||
r = parse_os_release(NULL,
|
||||
"SUPPORT_END", &_support_end_alloc);
|
||||
if (r < 0)
|
||||
return log_full_errno((r == -ENOENT || quiet) ? LOG_DEBUG : LOG_WARNING, r,
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return log_full_errno(quiet ? LOG_DEBUG : LOG_WARNING, r,
|
||||
"Failed to read os-release file, ignoring: %m");
|
||||
if (!_support_end_alloc)
|
||||
return false; /* no end date defined */
|
||||
|
||||
support_end = _support_end_alloc;
|
||||
}
|
||||
|
||||
struct tm tm = {};
|
||||
if (isempty(support_end)) /* An empty string is a explicit way to say "no EOL exists" */
|
||||
return false; /* no end date defined */
|
||||
|
||||
struct tm tm = {};
|
||||
const char *k = strptime(support_end, "%Y-%m-%d", &tm);
|
||||
if (!k || *k)
|
||||
return log_full_errno(quiet ? LOG_DEBUG : LOG_WARNING, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Failed to parse SUPPORT_END= in os-release file, ignoring: %m");
|
||||
|
||||
time_t eol = mktime(&tm);
|
||||
time_t eol = timegm(&tm);
|
||||
if (eol == (time_t) -1)
|
||||
return log_full_errno(quiet ? LOG_DEBUG : LOG_WARNING, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Failed to convert SUPPORT_END= in os-release file, ignoring: %m");
|
||||
|
||||
usec_t ts = now(CLOCK_REALTIME);
|
||||
return DIV_ROUND_UP(ts, USEC_PER_SEC) > (usec_t) eol;
|
||||
if (ret_eol)
|
||||
*ret_eol = eol * USEC_PER_SEC;
|
||||
|
||||
return DIV_ROUND_UP(now(CLOCK_REALTIME), USEC_PER_SEC) > (usec_t) eol;
|
||||
}
|
||||
|
||||
const char *os_release_pretty_name(const char *pretty_name, const char *name) {
|
||||
/* Distills a "pretty" name to show from os-release data. First argument is supposed to be the
|
||||
* PRETTY_NAME= field, the second one the NAME= field. This function is trivial, of course, and
|
||||
* exists mostly to ensure we use the same logic wherever possible. */
|
||||
|
||||
return empty_to_null(pretty_name) ?:
|
||||
empty_to_null(name) ?: "Linux";
|
||||
}
|
||||
|
|
|
@ -32,4 +32,6 @@ int load_extension_release_pairs(const char *root, const char *extension, bool r
|
|||
int load_os_release_pairs(const char *root, char ***ret);
|
||||
int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char ***ret);
|
||||
|
||||
int os_release_support_ended(const char *support_end, bool quiet);
|
||||
int os_release_support_ended(const char *support_end, bool quiet, usec_t *ret_eol);
|
||||
|
||||
const char *os_release_pretty_name(const char *pretty_name, const char *name);
|
||||
|
|
|
@ -1371,7 +1371,7 @@ static int os_release_status(void) {
|
|||
return log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
|
||||
"Failed to read os-release file, ignoring: %m");
|
||||
|
||||
const char *label = empty_to_null(pretty_name) ?: empty_to_null(name) ?: "Linux";
|
||||
const char *label = os_release_pretty_name(pretty_name, name);
|
||||
|
||||
if (show_status_on(arg_show_status)) {
|
||||
if (log_get_show_color())
|
||||
|
@ -1385,7 +1385,7 @@ static int os_release_status(void) {
|
|||
label);
|
||||
}
|
||||
|
||||
if (support_end && os_release_support_ended(support_end, false) > 0)
|
||||
if (support_end && os_release_support_ended(support_end, /* quiet */ false, NULL) > 0)
|
||||
/* pretty_name may include the version already, so we'll print the version only if we
|
||||
* have it and we're not using pretty_name. */
|
||||
status_printf(ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL, 0,
|
||||
|
|
|
@ -4547,7 +4547,7 @@ char* manager_taint_string(const Manager *m) {
|
|||
if (clock_is_localtime(NULL) > 0)
|
||||
stage[n++] = "local-hwclock";
|
||||
|
||||
if (os_release_support_ended(NULL, true) > 0)
|
||||
if (os_release_support_ended(NULL, /* quiet= */ true, NULL) > 0)
|
||||
stage[n++] = "support-ended";
|
||||
|
||||
_cleanup_free_ char *destination = NULL;
|
||||
|
|
|
@ -97,7 +97,7 @@ static bool press_any_key(void) {
|
|||
}
|
||||
|
||||
static void print_welcome(void) {
|
||||
_cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
|
||||
_cleanup_free_ char *pretty_name = NULL, *os_name = NULL, *ansi_color = NULL;
|
||||
static bool done = false;
|
||||
const char *pn, *ac;
|
||||
int r;
|
||||
|
@ -111,12 +111,13 @@ static void print_welcome(void) {
|
|||
r = parse_os_release(
|
||||
arg_root,
|
||||
"PRETTY_NAME", &pretty_name,
|
||||
"NAME", &os_name,
|
||||
"ANSI_COLOR", &ansi_color);
|
||||
if (r < 0)
|
||||
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
|
||||
"Failed to read os-release file, ignoring: %m");
|
||||
|
||||
pn = isempty(pretty_name) ? "Linux" : pretty_name;
|
||||
pn = os_release_pretty_name(pretty_name, os_name);
|
||||
ac = isempty(ansi_color) ? "0" : ansi_color;
|
||||
|
||||
if (colors_enabled())
|
||||
|
|
|
@ -47,6 +47,7 @@ typedef struct StatusInfo {
|
|||
const char *kernel_release;
|
||||
const char *os_pretty_name;
|
||||
const char *os_cpe_name;
|
||||
usec_t os_support_end;
|
||||
const char *virtualization;
|
||||
const char *architecture;
|
||||
const char *home_url;
|
||||
|
@ -76,6 +77,23 @@ static const char* chassis_string_to_glyph(const char *chassis) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *os_support_end_color(usec_t n, usec_t eol) {
|
||||
usec_t left;
|
||||
|
||||
/* If the end of support is over, color output in red. If only a month is left, color output in
|
||||
* yellow. If more than a year is left, color green. In between just show in regular color. */
|
||||
|
||||
if (n >= eol)
|
||||
return ANSI_HIGHLIGHT_RED;
|
||||
left = eol - n;
|
||||
if (left < USEC_PER_MONTH)
|
||||
return ANSI_HIGHLIGHT_YELLOW;
|
||||
if (left > USEC_PER_YEAR)
|
||||
return ANSI_HIGHLIGHT_GREEN;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int print_status_info(StatusInfo *i) {
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
sd_id128_t mid = {}, bid = {};
|
||||
|
@ -198,6 +216,19 @@ static int print_status_info(StatusInfo *i) {
|
|||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
if (i->os_support_end != USEC_INFINITY) {
|
||||
usec_t n = now(CLOCK_REALTIME);
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_FIELD, "OS Support End",
|
||||
TABLE_TIMESTAMP_DATE, i->os_support_end,
|
||||
TABLE_FIELD, n < i->os_support_end ? "OS Support Remaining" : "OS Support Expired",
|
||||
TABLE_TIMESPAN_DAY, n < i->os_support_end ? i->os_support_end - n : n - i->os_support_end,
|
||||
TABLE_SET_COLOR, os_support_end_color(n, i->os_support_end));
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
if (!isempty(i->kernel_name) && !isempty(i->kernel_release)) {
|
||||
const char *v;
|
||||
|
||||
|
@ -310,6 +341,7 @@ static int show_all_names(sd_bus *bus) {
|
|||
{ "KernelRelease", "s", NULL, offsetof(StatusInfo, kernel_release) },
|
||||
{ "OperatingSystemPrettyName", "s", NULL, offsetof(StatusInfo, os_pretty_name) },
|
||||
{ "OperatingSystemCPEName", "s", NULL, offsetof(StatusInfo, os_cpe_name) },
|
||||
{ "OperatingSystemSupportEnd", "t", NULL, offsetof(StatusInfo, os_support_end) },
|
||||
{ "HomeURL", "s", NULL, offsetof(StatusInfo, home_url) },
|
||||
{ "HardwareVendor", "s", NULL, offsetof(StatusInfo, hardware_vendor) },
|
||||
{ "HardwareModel", "s", NULL, offsetof(StatusInfo, hardware_model) },
|
||||
|
|
|
@ -59,6 +59,7 @@ typedef enum {
|
|||
PROP_OS_PRETTY_NAME,
|
||||
PROP_OS_CPE_NAME,
|
||||
PROP_OS_HOME_URL,
|
||||
PROP_OS_SUPPORT_END,
|
||||
_PROP_MAX,
|
||||
_PROP_INVALID = -EINVAL,
|
||||
} HostProperty;
|
||||
|
@ -146,6 +147,7 @@ static void context_read_machine_info(Context *c) {
|
|||
}
|
||||
|
||||
static void context_read_os_release(Context *c) {
|
||||
_cleanup_free_ char *os_name = NULL, *os_pretty_name = NULL;
|
||||
struct stat current_stat = {};
|
||||
int r;
|
||||
|
||||
|
@ -159,15 +161,21 @@ static void context_read_os_release(Context *c) {
|
|||
context_reset(c,
|
||||
(UINT64_C(1) << PROP_OS_PRETTY_NAME) |
|
||||
(UINT64_C(1) << PROP_OS_CPE_NAME) |
|
||||
(UINT64_C(1) << PROP_OS_HOME_URL));
|
||||
(UINT64_C(1) << PROP_OS_HOME_URL) |
|
||||
(UINT64_C(1) << PROP_OS_SUPPORT_END));
|
||||
|
||||
r = parse_os_release(NULL,
|
||||
"PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
|
||||
"CPE_NAME", &c->data[PROP_OS_CPE_NAME],
|
||||
"HOME_URL", &c->data[PROP_OS_HOME_URL]);
|
||||
"PRETTY_NAME", &os_pretty_name,
|
||||
"NAME", &os_name,
|
||||
"CPE_NAME", &c->data[PROP_OS_CPE_NAME],
|
||||
"HOME_URL", &c->data[PROP_OS_HOME_URL],
|
||||
"SUPPORT_END", &c->data[PROP_OS_SUPPORT_END]);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
log_warning_errno(r, "Failed to read os-release file, ignoring: %m");
|
||||
|
||||
if (free_and_strdup(&c->data[PROP_OS_PRETTY_NAME], os_release_pretty_name(os_pretty_name, os_name)) < 0)
|
||||
log_oom();
|
||||
|
||||
c->etc_os_release_stat = current_stat;
|
||||
}
|
||||
|
||||
|
@ -881,6 +889,26 @@ static int property_get_os_release_field(
|
|||
return sd_bus_message_append(reply, "s", *(char**) userdata);
|
||||
}
|
||||
|
||||
static int property_get_os_support_end(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Context *c = userdata;
|
||||
usec_t eol = USEC_INFINITY;
|
||||
|
||||
context_read_os_release(c);
|
||||
|
||||
if (c->data[PROP_OS_SUPPORT_END])
|
||||
(void) os_release_support_ended(c->data[PROP_OS_SUPPORT_END], /* quiet= */ false, &eol);
|
||||
|
||||
return sd_bus_message_append(reply, "t", eol);
|
||||
}
|
||||
|
||||
static int property_get_icon_name(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
|
@ -1246,7 +1274,7 @@ static int method_describe(sd_bus_message *m, void *userdata, sd_bus_error *erro
|
|||
_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;
|
||||
usec_t firmware_date = USEC_INFINITY;
|
||||
usec_t firmware_date = USEC_INFINITY, eol = 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;
|
||||
|
@ -1313,6 +1341,9 @@ static int method_describe(sd_bus_message *m, void *userdata, sd_bus_error *erro
|
|||
(void) get_firmware_vendor(&firmware_vendor);
|
||||
(void) get_firmware_date(&firmware_date);
|
||||
|
||||
if (c->data[PROP_OS_SUPPORT_END])
|
||||
(void) os_release_support_ended(c->data[PROP_OS_SUPPORT_END], /* quiet= */ false, &eol);
|
||||
|
||||
r = json_build(&v, JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR("Hostname", JSON_BUILD_STRING(hn)),
|
||||
JSON_BUILD_PAIR("StaticHostname", JSON_BUILD_STRING(c->data[PROP_STATIC_HOSTNAME])),
|
||||
|
@ -1329,6 +1360,7 @@ static int method_describe(sd_bus_message *m, void *userdata, sd_bus_error *erro
|
|||
JSON_BUILD_PAIR("OperatingSystemPrettyName", JSON_BUILD_STRING(c->data[PROP_OS_PRETTY_NAME])),
|
||||
JSON_BUILD_PAIR("OperatingSystemCPEName", JSON_BUILD_STRING(c->data[PROP_OS_CPE_NAME])),
|
||||
JSON_BUILD_PAIR("OperatingSystemHomeURL", JSON_BUILD_STRING(c->data[PROP_OS_HOME_URL])),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("OperatingSystemSupportEnd", eol),
|
||||
JSON_BUILD_PAIR("HardwareVendor", JSON_BUILD_STRING(vendor ?: c->data[PROP_HARDWARE_VENDOR])),
|
||||
JSON_BUILD_PAIR("HardwareModel", JSON_BUILD_STRING(model ?: c->data[PROP_HARDWARE_MODEL])),
|
||||
JSON_BUILD_PAIR("HardwareSerial", JSON_BUILD_STRING(serial)),
|
||||
|
@ -1372,6 +1404,7 @@ static const sd_bus_vtable hostname_vtable[] = {
|
|||
SD_BUS_PROPERTY("KernelVersion", "s", property_get_uname_field, offsetof(struct utsname, version), SD_BUS_VTABLE_ABSOLUTE_OFFSET|SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("OperatingSystemPrettyName", "s", property_get_os_release_field, offsetof(Context, data) + sizeof(char*) * PROP_OS_PRETTY_NAME, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("OperatingSystemCPEName", "s", property_get_os_release_field, offsetof(Context, data) + sizeof(char*) * PROP_OS_CPE_NAME, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("OperatingSystemSupportEnd", "t", property_get_os_support_end, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("HomeURL", "s", property_get_os_release_field, offsetof(Context, data) + sizeof(char*) * PROP_OS_HOME_URL, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("HardwareVendor", "s", property_get_hardware_vendor, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("HardwareModel", "s", property_get_hardware_model, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
|
|
@ -732,7 +732,7 @@ static int request_handler_machine(
|
|||
_cleanup_(MHD_destroy_responsep) struct MHD_Response *response = NULL;
|
||||
RequestMeta *m = ASSERT_PTR(connection_cls);
|
||||
int r;
|
||||
_cleanup_free_ char* hostname = NULL, *os_name = NULL;
|
||||
_cleanup_free_ char* hostname = NULL, *pretty_name = NULL, *os_name = NULL;
|
||||
uint64_t cutoff_from = 0, cutoff_to = 0, usage = 0;
|
||||
sd_id128_t mid, bid;
|
||||
_cleanup_free_ char *v = NULL, *json = NULL;
|
||||
|
@ -763,7 +763,10 @@ static int request_handler_machine(
|
|||
if (r < 0)
|
||||
return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %m");
|
||||
|
||||
(void) parse_os_release(NULL, "PRETTY_NAME", &os_name);
|
||||
(void) parse_os_release(
|
||||
NULL,
|
||||
"PRETTY_NAME", &pretty_name,
|
||||
"NAME=", &os_name);
|
||||
(void) get_virtualization(&v);
|
||||
|
||||
r = asprintf(&json,
|
||||
|
@ -778,7 +781,7 @@ static int request_handler_machine(
|
|||
SD_ID128_FORMAT_VAL(mid),
|
||||
SD_ID128_FORMAT_VAL(bid),
|
||||
hostname_cleanup(hostname),
|
||||
os_name ? os_name : "Linux",
|
||||
os_release_pretty_name(pretty_name, os_name),
|
||||
v ? v : "bare",
|
||||
usage,
|
||||
cutoff_from,
|
||||
|
|
|
@ -300,6 +300,7 @@ static size_t table_data_size(TableDataType type, const void *data) {
|
|||
case TABLE_TIMESTAMP_DATE:
|
||||
case TABLE_TIMESPAN:
|
||||
case TABLE_TIMESPAN_MSEC:
|
||||
case TABLE_TIMESPAN_DAY:
|
||||
return sizeof(usec_t);
|
||||
|
||||
case TABLE_SIZE:
|
||||
|
@ -898,6 +899,7 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) {
|
|||
case TABLE_TIMESTAMP_DATE:
|
||||
case TABLE_TIMESPAN:
|
||||
case TABLE_TIMESPAN_MSEC:
|
||||
case TABLE_TIMESPAN_DAY:
|
||||
buffer.usec = va_arg(ap, usec_t);
|
||||
data = &buffer.usec;
|
||||
break;
|
||||
|
@ -1307,6 +1309,7 @@ static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t
|
|||
|
||||
case TABLE_TIMESPAN:
|
||||
case TABLE_TIMESPAN_MSEC:
|
||||
case TABLE_TIMESPAN_DAY:
|
||||
return CMP(a->timespan, b->timespan);
|
||||
|
||||
case TABLE_SIZE:
|
||||
|
@ -1558,7 +1561,8 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
|
|||
}
|
||||
|
||||
case TABLE_TIMESPAN:
|
||||
case TABLE_TIMESPAN_MSEC: {
|
||||
case TABLE_TIMESPAN_MSEC:
|
||||
case TABLE_TIMESPAN_DAY: {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
|
||||
p = new(char, FORMAT_TIMESPAN_MAX);
|
||||
|
@ -1566,7 +1570,8 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
|
|||
return NULL;
|
||||
|
||||
if (!format_timespan(p, FORMAT_TIMESPAN_MAX, d->timespan,
|
||||
d->type == TABLE_TIMESPAN ? 0 : USEC_PER_MSEC))
|
||||
d->type == TABLE_TIMESPAN ? 0 :
|
||||
d->type == TABLE_TIMESPAN_MSEC ? USEC_PER_MSEC : USEC_PER_DAY))
|
||||
return "-";
|
||||
|
||||
d->formatted = TAKE_PTR(p);
|
||||
|
@ -2592,6 +2597,7 @@ static int table_data_to_json(TableData *d, JsonVariant **ret) {
|
|||
|
||||
case TABLE_TIMESPAN:
|
||||
case TABLE_TIMESPAN_MSEC:
|
||||
case TABLE_TIMESPAN_DAY:
|
||||
if (d->timespan == USEC_INFINITY)
|
||||
return json_variant_new_null(ret);
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ typedef enum TableDataType {
|
|||
TABLE_TIMESTAMP_DATE,
|
||||
TABLE_TIMESPAN,
|
||||
TABLE_TIMESPAN_MSEC,
|
||||
TABLE_TIMESPAN_DAY,
|
||||
TABLE_SIZE,
|
||||
TABLE_BPS,
|
||||
TABLE_INT,
|
||||
|
|
|
@ -75,11 +75,11 @@ TEST(load_os_release_pairs) {
|
|||
TEST(os_release_support_ended) {
|
||||
int r;
|
||||
|
||||
assert_se(os_release_support_ended("1999-01-01", false) == true);
|
||||
assert_se(os_release_support_ended("2037-12-31", false) == false);
|
||||
assert_se(os_release_support_ended("-1-1-1", true) == -EINVAL);
|
||||
assert_se(os_release_support_ended("1999-01-01", false, NULL) == true);
|
||||
assert_se(os_release_support_ended("2037-12-31", false, NULL) == false);
|
||||
assert_se(os_release_support_ended("-1-1-1", true, NULL) == -EINVAL);
|
||||
|
||||
r = os_release_support_ended(NULL, false);
|
||||
r = os_release_support_ended(NULL, false, NULL);
|
||||
if (r < 0)
|
||||
log_info_errno(r, "Failed to check host: %m");
|
||||
else
|
||||
|
|
Loading…
Reference in a new issue