diff options
Diffstat (limited to 'src/timedate/timedated.c')
-rw-r--r-- | src/timedate/timedated.c | 76 |
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"); |