diff --git a/man/systemd-timedated.service.xml b/man/systemd-timedated.service.xml
index c8d74ddef2..9a37d89a40 100644
--- a/man/systemd-timedated.service.xml
+++ b/man/systemd-timedated.service.xml
@@ -61,13 +61,34 @@
systemd-timedated provides.
+
+ Environment
+
+
+
+ $SYSTEMD_TIMEDATED_NTP_SERVICES
+
+ Colon-separated list of unit names of NTP client services.
+ If not set, then
+ systemd-timesyncd.service8
+ is used. See the entries of NTP related commands of
+ timedatectl1
+ for details about this.
+
+ Example:
+ SYSTEMD_TIMEDATED_NTP_SERVICES=ntpd.service:chronyd.service:systemd-timesyncd.service
+
+
+
+
See Also
systemd1,
timedatectl1,
localtime5,
- hwclock8
+ hwclock8,
+ systemd-timesyncd8
diff --git a/man/timedatectl.xml b/man/timedatectl.xml
index e8d9cb84b9..02b86b6641 100644
--- a/man/timedatectl.xml
+++ b/man/timedatectl.xml
@@ -156,28 +156,11 @@
set-ntp [BOOL]
- Takes a boolean argument. Controls whether
- network time synchronization is active and enabled (if
- available). This enables and starts, or disables and stops the
- systemd-timesyncd.service 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:
- systemctl enable --now
- systemd-timesyncd.service and systemctl
- disable --now systemd-timesyncd.service, but is
- protected by a different access policy.
-
- 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,
- systemd-timesyncd.service does more than
- just network time synchronization, as it ensures a monotonic
- clock on systems without RTC even if no network is
- available. See
- systemd-timesyncd.service8
- for details about this.
+ 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 $SYSTEMD_TIMEDATED_NTP_SERVICES
+ of systemd-timedated.service. If the argument is false, then this disables and
+ stops the all services listed in $SYSTEMD_TIMEDATED_NTP_SERVICES.
@@ -197,13 +180,13 @@
Examples
Show current settings:
$ 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
+ 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
Enable network time synchronization:
diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c
index 4dce12e1c6..9d9765e568 100644
--- a/src/libsystemd/sd-bus/bus-common-errors.c
+++ b/src/libsystemd/sd-bus/bus-common-errors.c
@@ -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),
diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h
index de46c36242..239c96bc1c 100644
--- a/src/libsystemd/sd-bus/bus-common-errors.h
+++ b/src/libsystemd/sd-bus/bus-common-errors.h
@@ -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"
diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
index c096fb5f0d..9a803d1221 100644
--- a/src/timedate/timedatectl.c
+++ b/src/timedate/timedatectl.c
@@ -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) },
{}
};
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index e50ce47b62..f479b0ab7f 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -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) {