Merge pull request #8615 from yuwata/fix-1329

timedated: support multiple NTP services
This commit is contained in:
Lennart Poettering 2018-04-19 16:22:50 +02:00 committed by GitHub
commit 2c75088094
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 372 additions and 132 deletions

View file

@ -61,13 +61,34 @@
<filename>systemd-timedated</filename> provides.</para>
</refsect1>
<refsect1>
<title>Environment</title>
<variablelist class='environment-variables'>
<varlistentry>
<term><varname>$SYSTEMD_TIMEDATED_NTP_SERVICES</varname></term>
<listitem><para>Colon-separated list of unit names of NTP client services.
If not set, then
<citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
is used. See the entries of NTP related commands of
<citerefentry><refentrytitle>timedatectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
for details about this.</para>
<para>Example:
<programlisting>SYSTEMD_TIMEDATED_NTP_SERVICES=ntpd.service:chronyd.service:systemd-timesyncd.service</programlisting>
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>timedatectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>localtime</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>hwclock</refentrytitle><manvolnum>8</manvolnum></citerefentry>
<citerefentry project='man-pages'><refentrytitle>hwclock</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-timesyncd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>

View file

@ -156,28 +156,11 @@
<varlistentry>
<term><command>set-ntp [BOOL]</command></term>
<listitem><para>Takes a boolean argument. Controls whether
network time synchronization is active and enabled (if
available). This enables and starts, or disables and stops the
<filename>systemd-timesyncd.service</filename> unit. It does
not affect the state of any other, unrelated network time
synchronization services that might be installed on the
system. This command is hence mostly equivalent to:
<command>systemctl enable --now
systemd-timesyncd.service</command> and <command>systemctl
disable --now systemd-timesyncd.service</command>, but is
protected by a different access policy.</para>
<para>Note that even if time synchronization is turned off
with this command, another unrelated system service might
still synchronize the clock with the network. Also note that,
strictly speaking,
<filename>systemd-timesyncd.service</filename> does more than
just network time synchronization, as it ensures a monotonic
clock on systems without RTC even if no network is
available. See
<citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for details about this.</para></listitem>
<listitem><para>Takes a boolean argument. Controls whether network time synchronization is active
and enabled (if available). If the argument is true, this enables and starts the first existed
service listed in the environment variable <varname>$SYSTEMD_TIMEDATED_NTP_SERVICES</varname>
of <filename>systemd-timedated.service</filename>. If the argument is false, then this disables and
stops the all services listed in <varname>$SYSTEMD_TIMEDATED_NTP_SERVICES</varname>.</para></listitem>
</varlistentry>
</variablelist>
@ -197,13 +180,13 @@
<title>Examples</title>
<para>Show current settings:
<programlisting>$ timedatectl
Local time: Thu 2017-09-21 16:08:56 CEST
Universal time: Thu 2017-09-21 14:08:56 UTC
RTC time: Thu 2017-09-21 14:08:56
Time zone: Europe/Warsaw (CEST, +0200)
System clock synchronized: yes
systemd-timesyncd.service active: yes
RTC in local TZ: no</programlisting>
Local time: Thu 2017-09-21 16:08:56 CEST
Universal time: Thu 2017-09-21 14:08:56 UTC
RTC time: Thu 2017-09-21 14:08:56
Time zone: Europe/Warsaw (CEST, +0200)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no</programlisting>
</para>
<para>Enable network time synchronization:

View file

@ -59,6 +59,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_BUSY, EBUSY),
SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, EALREADY),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_NTP_SUPPORT, EOPNOTSUPP),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_PROCESS, ESRCH),

View file

@ -55,6 +55,7 @@
#define BUS_ERROR_SESSION_BUSY "org.freedesktop.login1.SessionBusy"
#define BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED "org.freedesktop.timedate1.AutomaticTimeSyncEnabled"
#define BUS_ERROR_NO_NTP_SUPPORT "org.freedesktop.timedate1.NoNTPSupport"
#define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess"

View file

@ -36,19 +36,19 @@ typedef struct StatusInfo {
usec_t rtc_time;
bool rtc_local;
bool ntp_enabled;
bool ntp_capable;
bool ntp_active;
bool ntp_synced;
} StatusInfo;
static void print_status_info(const StatusInfo *i) {
const char *old_tz = NULL, *tz;
bool have_time = false;
char a[LINE_MAX];
struct tm tm;
time_t sec;
bool have_time = false;
const char *old_tz = NULL, *tz;
int r;
size_t n;
int r;
assert(i);
@ -74,13 +74,13 @@ static void print_status_info(const StatusInfo *i) {
if (have_time) {
n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm));
printf(" Local time: %s\n", n > 0 ? a : "n/a");
printf(" Local time: %s\n", n > 0 ? a : "n/a");
n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm));
printf(" Universal time: %s\n", n > 0 ? a : "n/a");
printf(" Universal time: %s\n", n > 0 ? a : "n/a");
} else {
printf(" Local time: %s\n", "n/a");
printf(" Universal time: %s\n", "n/a");
printf(" Local time: %s\n", "n/a");
printf(" Universal time: %s\n", "n/a");
}
if (i->rtc_time > 0) {
@ -88,9 +88,9 @@ static void print_status_info(const StatusInfo *i) {
rtc_sec = (time_t) (i->rtc_time / USEC_PER_SEC);
n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm));
printf(" RTC time: %s\n", n > 0 ? a : "n/a");
printf(" RTC time: %s\n", n > 0 ? a : "n/a");
} else
printf(" RTC time: %s\n", "n/a");
printf(" RTC time: %s\n", "n/a");
if (have_time)
n = strftime(a, sizeof a, "%Z, %z", localtime_r(&sec, &tm));
@ -105,13 +105,13 @@ static void print_status_info(const StatusInfo *i) {
else
tzset();
printf(" Time zone: %s (%s)\n"
" System clock synchronized: %s\n"
"systemd-timesyncd.service active: %s\n"
" RTC in local TZ: %s\n",
printf(" Time zone: %s (%s)\n"
"System clock synchronized: %s\n"
" NTP service: %s\n"
" RTC in local TZ: %s\n",
strna(i->timezone), have_time && n > 0 ? a : "n/a",
yes_no(i->ntp_synced),
i->ntp_capable ? yes_no(i->ntp_enabled) : "n/a",
i->ntp_capable ? (i->ntp_active ? "active" : "inactive") : "n/a",
yes_no(i->rtc_local));
if (i->rtc_local)
@ -127,13 +127,13 @@ static void print_status_info(const StatusInfo *i) {
static int show_status(int argc, char **argv, void *userdata) {
StatusInfo info = {};
static const struct bus_properties_map map[] = {
{ "Timezone", "s", NULL, offsetof(StatusInfo, timezone) },
{ "LocalRTC", "b", NULL, offsetof(StatusInfo, rtc_local) },
{ "NTP", "b", NULL, offsetof(StatusInfo, ntp_enabled) },
{ "Timezone", "s", NULL, offsetof(StatusInfo, timezone) },
{ "LocalRTC", "b", NULL, offsetof(StatusInfo, rtc_local) },
{ "NTP", "b", NULL, offsetof(StatusInfo, ntp_active) },
{ "CanNTP", "b", NULL, offsetof(StatusInfo, ntp_capable) },
{ "NTPSynchronized", "b", NULL, offsetof(StatusInfo, ntp_synced) },
{ "TimeUSec", "t", NULL, offsetof(StatusInfo, time) },
{ "RTCTimeUSec", "t", NULL, offsetof(StatusInfo, rtc_time) },
{ "NTPSynchronized", "b", NULL, offsetof(StatusInfo, ntp_synced) },
{ "TimeUSec", "t", NULL, offsetof(StatusInfo, time) },
{ "RTCTimeUSec", "t", NULL, offsetof(StatusInfo, rtc_time) },
{}
};

View file

@ -21,33 +21,170 @@
#include "def.h"
#include "fileio-label.h"
#include "fs-util.h"
#include "hashmap.h"
#include "list.h"
#include "path-util.h"
#include "selinux-util.h"
#include "string-util.h"
#include "strv.h"
#include "unit-def.h"
#include "unit-name.h"
#include "user-util.h"
#include "util.h"
#define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n"
#define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n"
static BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map timedated_errors[] = {
SD_BUS_ERROR_MAP("org.freedesktop.timedate1.NoNTPSupport", EOPNOTSUPP),
SD_BUS_ERROR_MAP_END
};
typedef struct UnitStatusInfo {
char *name;
char *load_state;
char *unit_file_state;
char *active_state;
LIST_FIELDS(struct UnitStatusInfo, units);
} UnitStatusInfo;
typedef struct Context {
char *zone;
bool local_rtc;
bool can_ntp;
bool use_ntp;
Hashmap *polkit_registry;
LIST_HEAD(UnitStatusInfo, units);
} Context;
static void unit_status_info_clear(UnitStatusInfo *p) {
assert(p);
p->load_state = mfree(p->load_state);
p->unit_file_state = mfree(p->unit_file_state);
p->active_state = mfree(p->active_state);
}
static void unit_status_info_free(UnitStatusInfo *p) {
assert(p);
unit_status_info_clear(p);
free(p->name);
free(p);
}
static void context_free(Context *c) {
UnitStatusInfo *p;
assert(c);
free(c->zone);
bus_verify_polkit_async_registry_free(c->polkit_registry);
while ((p = c->units)) {
LIST_REMOVE(units, c->units, p);
unit_status_info_free(p);
}
}
static int context_add_ntp_service(Context *c, const char *s) {
_cleanup_free_ char *name = NULL;
UnitStatusInfo *u;
if (!unit_name_is_valid(s, UNIT_NAME_PLAIN))
return -EINVAL;
/* Do not add this if it is already listed */
LIST_FOREACH(units, u, c->units)
if (streq(u->name, s))
return 0;
u = new0(UnitStatusInfo, 1);
if (!u)
return -ENOMEM;
u->name = strdup(s);
if (!u->name) {
free(u);
return -ENOMEM;
}
LIST_APPEND(units, c->units, u);
return 0;
}
static int context_parse_ntp_services(Context *c) {
const char *env, *p;
int r;
assert(c);
env = getenv("SYSTEMD_TIMEDATED_NTP_SERVICES");
if (!env) {
r = context_add_ntp_service(c, "systemd-timesyncd.service");
if (r < 0)
log_warning_errno(r, "Failed to add NTP service \"systemd-timesyncd.service\", ignoring: %m");
return 0;
}
for (p = env;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, ":", 0);
if (r == 0)
break;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_error("Invalid syntax, ignoring: %s", env);
break;
}
r = context_add_ntp_service(c, word);
if (r < 0)
log_warning_errno(r, "Failed to add NTP service \"%s\", ignoring: %m", word);
}
return 0;
}
static int context_ntp_service_is_active(Context *c) {
UnitStatusInfo *info;
int count = 0;
assert(c);
/* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
LIST_FOREACH(units, info, c->units)
count += streq_ptr(info->active_state, "active");
return count;
}
static int context_ntp_service_is_enabled(Context *c) {
UnitStatusInfo *info;
int count = 0;
assert(c);
/* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
LIST_FOREACH(units, info, c->units)
count += STRPTR_IN_SET(info->unit_file_state, "enabled", "enabled-runtime");
return count;
}
static int context_ntp_service_exists(Context *c) {
UnitStatusInfo *info;
int count = 0;
assert(c);
/* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
LIST_FOREACH(units, info, c->units)
count += streq_ptr(info->load_state, "loaded");
return count;
}
static int context_read_data(Context *c) {
@ -163,81 +300,95 @@ static int context_write_data_local_rtc(Context *c) {
return write_string_file_atomic_label("/etc/adjtime", w);
}
static int context_read_ntp(Context *c, sd_bus *bus) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
const char *s;
static int context_update_ntp_status(Context *c, sd_bus *bus, sd_bus_message *m) {
static const struct bus_properties_map map[] = {
{ "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
{ "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) },
{ "UnitFileState", "s", NULL, offsetof(UnitStatusInfo, unit_file_state) },
{}
};
static sd_bus_message *_m = NULL;
UnitStatusInfo *u;
int r;
assert(c);
assert(bus);
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"GetUnitFileState",
&error,
&reply,
"s",
"systemd-timesyncd.service");
/* Suppress multiple call of context_update_ntp_status() within single DBus transaction. */
if (m && m == _m)
return 0;
if (r < 0) {
if (sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND) ||
sd_bus_error_has_name(&error, "org.freedesktop.systemd1.LoadFailed") ||
sd_bus_error_has_name(&error, "org.freedesktop.systemd1.NoSuchUnit"))
return 0;
_m = m;
return r;
LIST_FOREACH(units, u, c->units) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ char *path = NULL;
unit_status_info_clear(u);
path = unit_dbus_path_from_name(u->name);
if (!path)
return -ENOMEM;
r = bus_map_all_properties(
bus,
"org.freedesktop.systemd1",
path,
map,
BUS_MAP_STRDUP,
&error,
NULL,
u);
if (r < 0)
return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
}
r = sd_bus_message_read(reply, "s", &s);
if (r < 0)
return r;
c->can_ntp = true;
c->use_ntp = STR_IN_SET(s, "enabled", "enabled-runtime");
return 0;
}
static int context_start_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) {
static int unit_start_or_stop(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *error, bool start) {
int r;
assert(u);
assert(bus);
assert(error);
/* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
if (streq(u->active_state, "active") == start)
return 0;
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
enabled ? "StartUnit" : "StopUnit",
start ? "StartUnit" : "StopUnit",
error,
NULL,
"ss",
"systemd-timesyncd.service",
u->name,
"replace");
if (r < 0) {
if (sd_bus_error_has_name(error, SD_BUS_ERROR_FILE_NOT_FOUND) ||
sd_bus_error_has_name(error, "org.freedesktop.systemd1.LoadFailed") ||
sd_bus_error_has_name(error, "org.freedesktop.systemd1.NoSuchUnit"))
return sd_bus_error_set_const(error, "org.freedesktop.timedate1.NoNTPSupport", "NTP not supported.");
if (r < 0)
return r;
}
return 0;
}
static int context_enable_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) {
static int unit_enable_or_disable(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *error, bool enable) {
int r;
assert(u);
assert(bus);
assert(error);
if (enabled)
/* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
if (streq(u->unit_file_state, "enabled") == enable)
return 0;
if (enable)
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
@ -247,7 +398,7 @@ static int context_enable_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) {
error,
NULL,
"asbb", 1,
"systemd-timesyncd.service",
u->name,
false, true);
else
r = sd_bus_call_method(
@ -259,15 +410,10 @@ static int context_enable_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) {
error,
NULL,
"asb", 1,
"systemd-timesyncd.service",
u->name,
false);
if (r < 0) {
if (sd_bus_error_has_name(error, SD_BUS_ERROR_FILE_NOT_FOUND))
return sd_bus_error_set_const(error, "org.freedesktop.timedate1.NoNTPSupport", "NTP not supported.");
if (r < 0)
return r;
}
r = sd_bus_call_method(
bus,
@ -278,9 +424,8 @@ static int context_enable_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) {
error,
NULL,
NULL);
if (r < 0)
return r;
if (r < 0)
return r;
return 0;
}
@ -337,6 +482,56 @@ static int property_get_ntp_sync(
return sd_bus_message_append(reply, "b", ntp_synced());
}
static int property_get_can_ntp(
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;
int r;
assert(c);
assert(bus);
assert(property);
assert(reply);
assert(error);
r = context_update_ntp_status(c, bus, reply);
if (r < 0)
return r;
return sd_bus_message_append(reply, "b", context_ntp_service_exists(c) > 0);
}
static int property_get_ntp(
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;
int r;
assert(c);
assert(bus);
assert(property);
assert(reply);
assert(error);
r = context_update_ntp_status(c, bus, reply);
if (r < 0)
return r;
return sd_bus_message_append(reply, "b", context_ntp_service_is_active(c) > 0);
}
static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error *error) {
Context *c = userdata;
const char *z;
@ -500,19 +695,23 @@ static int method_set_local_rtc(sd_bus_message *m, void *userdata, sd_bus_error
}
static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *error) {
int relative, interactive;
sd_bus *bus = sd_bus_message_get_bus(m);
int relative, interactive, r;
Context *c = userdata;
int64_t utc;
struct timespec ts;
usec_t start;
struct tm* tm;
int r;
assert(m);
assert(c);
if (c->use_ntp)
return sd_bus_error_setf(error, BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, "Automatic time synchronization is enabled");
r = context_update_ntp_status(c, bus, m);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to update context: %m");
if (context_ntp_service_is_active(c) > 0)
return sd_bus_error_set(error, BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, "Automatic time synchronization is enabled");
/* this only gets used if dbus does not provide a timestamp */
start = now(CLOCK_MONOTONIC);
@ -522,7 +721,7 @@ static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *erro
return r;
if (!relative && utc <= 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid absolute time");
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid absolute time");
if (relative && utc == 0)
return sd_bus_reply_method_return(m, NULL);
@ -535,7 +734,7 @@ static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *erro
if ((utc > 0 && x < n) ||
(utc < 0 && x > n))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Time value overflow");
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Time value overflow");
timespec_store(&ts, x);
} else
@ -586,19 +785,25 @@ static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *erro
}
static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error) {
int enabled, interactive;
sd_bus *bus = sd_bus_message_get_bus(m);
Context *c = userdata;
int r;
UnitStatusInfo *u;
int enable, interactive, q, r;
assert(m);
assert(bus);
assert(c);
r = sd_bus_message_read(m, "bb", &enabled, &interactive);
r = sd_bus_message_read(m, "bb", &enable, &interactive);
if (r < 0)
return r;
if ((bool)enabled == c->use_ntp)
return sd_bus_reply_method_return(m, NULL);
r = context_update_ntp_status(c, bus, m);
if (r < 0)
return r;
if (context_ntp_service_exists(c) <= 0)
return sd_bus_error_set(error, BUS_ERROR_NO_NTP_SUPPORT, "NTP not supported");
r = bus_verify_polkit_async(
m,
@ -614,18 +819,49 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error
if (r == 0)
return 1;
r = context_enable_ntp(sd_bus_message_get_bus(m), error, enabled);
if (!enable)
LIST_FOREACH(units, u, c->units) {
if (!streq(u->load_state, "loaded"))
continue;
q = unit_enable_or_disable(u, bus, error, enable);
if (q < 0)
r = q;
q = unit_start_or_stop(u, bus, error, enable);
if (q < 0)
r = q;
}
else if (context_ntp_service_is_enabled(c) <= 0)
LIST_FOREACH(units, u, c->units) {
if (!streq(u->load_state, "loaded"))
continue;
r = unit_enable_or_disable(u, bus, error, enable);
if (r < 0)
continue;
r = unit_start_or_stop(u, bus, error, enable);
break;
}
else if (context_ntp_service_is_active(c) <= 0)
LIST_FOREACH(units, u, c->units) {
if (!streq(u->load_state, "loaded") ||
!streq(u->unit_file_state, "enabled"))
continue;
r = unit_start_or_stop(u, bus, error, enable);
break;
}
if (r < 0)
return r;
r = context_start_ntp(sd_bus_message_get_bus(m), error, enabled);
if (r < 0)
return r;
log_info("Set NTP to %sd", enable_disable(enable));
c->use_ntp = enabled;
log_info("Set NTP to %sd", enable_disable(enabled));
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL);
(void) sd_bus_emit_properties_changed(bus, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL);
return sd_bus_reply_method_return(m, NULL);
}
@ -634,8 +870,8 @@ static const sd_bus_vtable timedate_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Timezone", "s", NULL, offsetof(Context, zone), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("LocalRTC", "b", bus_property_get_bool, offsetof(Context, local_rtc), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("CanNTP", "b", bus_property_get_bool, offsetof(Context, can_ntp), 0),
SD_BUS_PROPERTY("NTP", "b", bus_property_get_bool, offsetof(Context, use_ntp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("CanNTP", "b", property_get_can_ntp, 0, 0),
SD_BUS_PROPERTY("NTP", "b", property_get_ntp, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("NTPSynchronized", "b", property_get_ntp_sync, 0, 0),
SD_BUS_PROPERTY("TimeUSec", "t", property_get_time, 0, 0),
SD_BUS_PROPERTY("RTCTimeUSec", "t", property_get_rtc_time, 0, 0),
@ -713,11 +949,9 @@ int main(int argc, char *argv[]) {
goto finish;
}
r = context_read_ntp(&context, bus);
if (r < 0) {
log_error_errno(r, "Failed to determine whether NTP is enabled: %m");
r = context_parse_ntp_services(&context);
if (r < 0)
goto finish;
}
r = bus_event_loop_with_idle(event, bus, "org.freedesktop.timedate1", DEFAULT_EXIT_USEC, NULL, NULL);
if (r < 0) {