mirror of
https://github.com/systemd/systemd.git
synced 2024-12-23 21:35:11 +03:00
Merge pull request #8615 from yuwata/fix-1329
timedated: support multiple NTP services
This commit is contained in:
commit
2c75088094
@ -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>
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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),
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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) },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user