summaryrefslogtreecommitdiffstats
path: root/src/timedate/timedated.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/timedate/timedated.c')
-rw-r--r--src/timedate/timedated.c76
1 files changed, 44 insertions, 32 deletions
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index c7be30f..e3b4367 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -22,6 +22,7 @@
#include "clock-util.h"
#include "conf-files.h"
#include "constants.h"
+#include "daemon-util.h"
#include "fd-util.h"
#include "fileio-label.h"
#include "fileio.h"
@@ -45,6 +46,7 @@
#define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n"
#define UNIT_LIST_DIRS (const char* const*) CONF_PATHS_STRV("systemd/ntp-units.d")
+#define SET_NTP_IN_FLIGHT_MAX 16
typedef struct UnitStatusInfo {
char *name;
@@ -61,6 +63,7 @@ typedef struct Context {
bool local_rtc;
Hashmap *polkit_registry;
sd_bus_message *cache;
+ Set *set_ntp_calls;
sd_bus_slot *slot_job_removed;
@@ -119,8 +122,9 @@ static void context_clear(Context *c) {
assert(c);
free(c->zone);
- bus_verify_polkit_async_registry_free(c->polkit_registry);
+ hashmap_free(c->polkit_registry);
sd_bus_message_unref(c->cache);
+ set_free(c->set_ntp_calls);
sd_bus_slot_unref(c->slot_job_removed);
@@ -461,11 +465,19 @@ static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *er
n += !!u->path;
if (n == 0) {
+ sd_bus_message *cm;
+
c->slot_job_removed = sd_bus_slot_unref(c->slot_job_removed);
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
"/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP",
NULL);
+ while ((cm = set_steal_first(c->set_ntp_calls))) {
+ r = sd_bus_reply_method_return(cm, NULL);
+ if (r < 0)
+ log_debug_errno(r, "Failed to reply to SetNTP method call, ignoring: %m");
+ sd_bus_message_unref(cm);
+ }
}
return 0;
@@ -584,6 +596,8 @@ static int property_get_rtc_time(
log_warning("/dev/rtc is busy. Is somebody keeping it open continuously? That's not a good idea... Returning a bogus RTC timestamp.");
else if (r == -ENOENT)
log_debug("/dev/rtc not found.");
+ else if (r == -ENODATA)
+ log_debug("/dev/rtc has no valid time, power loss probably occurred?");
else if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to read RTC: %m");
else
@@ -665,13 +679,12 @@ static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error *
if (streq_ptr(z, c->zone))
return sd_bus_reply_method_return(m, NULL);
- r = bus_verify_polkit_async(
+ r = bus_verify_polkit_async_full(
m,
- CAP_SYS_TIME,
"org.freedesktop.timedate1.set-timezone",
- NULL,
- interactive,
- UID_INVALID,
+ /* details= */ NULL,
+ /* good_user= */ UID_INVALID,
+ interactive ? POLKIT_ALLOW_INTERACTIVE : 0,
&c->polkit_registry,
error);
if (r < 0)
@@ -740,13 +753,12 @@ static int method_set_local_rtc(sd_bus_message *m, void *userdata, sd_bus_error
if (lrtc == c->local_rtc && !fix_system)
return sd_bus_reply_method_return(m, NULL);
- r = bus_verify_polkit_async(
+ r = bus_verify_polkit_async_full(
m,
- CAP_SYS_TIME,
"org.freedesktop.timedate1.set-local-rtc",
- NULL,
- interactive,
- UID_INVALID,
+ /* details= */ NULL,
+ /* good_user= */ UID_INVALID,
+ interactive ? POLKIT_ALLOW_INTERACTIVE : 0,
&c->polkit_registry,
error);
if (r < 0)
@@ -860,13 +872,12 @@ static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *erro
} else
timespec_store(&ts, (usec_t) utc);
- r = bus_verify_polkit_async(
+ r = bus_verify_polkit_async_full(
m,
- CAP_SYS_TIME,
"org.freedesktop.timedate1.set-time",
- NULL,
- interactive,
- UID_INVALID,
+ /* details= */ NULL,
+ /* good_user= */ UID_INVALID,
+ interactive ? POLKIT_ALLOW_INTERACTIVE : 0,
&c->polkit_registry,
error);
if (r < 0)
@@ -924,13 +935,12 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error
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(
+ r = bus_verify_polkit_async_full(
m,
- CAP_SYS_TIME,
"org.freedesktop.timedate1.set-ntp",
- NULL,
- interactive,
- UID_INVALID,
+ /* details= */ NULL,
+ /* good_user= */ UID_INVALID,
+ interactive ? POLKIT_ALLOW_INTERACTIVE : 0,
&c->polkit_registry,
error);
if (r < 0)
@@ -942,6 +952,9 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error
LIST_FOREACH(units, u, c->units)
u->path = mfree(u->path);
+ if (set_size(c->set_ntp_calls) >= SET_NTP_IN_FLIGHT_MAX)
+ return sd_bus_error_set_errnof(error, EAGAIN, "Too many calls in flight.");
+
if (!c->slot_job_removed) {
r = bus_match_signal_async(
bus,
@@ -996,11 +1009,12 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error
c->slot_job_removed = TAKE_PTR(slot);
if (selected)
- log_info("Set NTP to enabled (%s).", selected->name);
+ log_info("Set NTP to be enabled (%s).", selected->name);
else
- log_info("Set NTP to disabled.");
+ log_info("Set NTP to be disabled.");
- return sd_bus_reply_method_return(m, NULL);
+ /* Asynchronous reply to m in match_job_removed() */
+ return set_ensure_consume(&c->set_ntp_calls, &bus_message_hash_ops, sd_bus_message_ref(m));
}
static int method_list_timezones(sd_bus_message *m, void *userdata, sd_bus_error *error) {
@@ -1122,21 +1136,15 @@ static int run(int argc, char *argv[]) {
umask(0022);
- assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
-
r = sd_event_default(&event);
if (r < 0)
return log_error_errno(r, "Failed to allocate event loop: %m");
(void) sd_event_set_watchdog(event, true);
- r = sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to install SIGINT handler: %m");
-
- r = sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
+ r = sd_event_set_signal_exit(event, true);
if (r < 0)
- return log_error_errno(r, "Failed to install SIGTERM handler: %m");
+ return log_error_errno(r, "Failed to install SIGINT/SIGTERM handlers: %m");
r = connect_bus(&context, event, &bus);
if (r < 0)
@@ -1152,6 +1160,10 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return r;
+ r = sd_notify(false, NOTIFY_READY);
+ if (r < 0)
+ log_warning_errno(r, "Failed to send readiness notification, ignoring: %m");
+
r = bus_event_loop_with_idle(event, bus, "org.freedesktop.timedate1", DEFAULT_EXIT_USEC, NULL, NULL);
if (r < 0)
return log_error_errno(r, "Failed to run event loop: %m");