|  | /* SPDX-License-Identifier: LGPL-2.1-or-later */ | 
|  |  | 
|  | #include <errno.h> | 
|  |  | 
|  | #include "event-source.h" | 
|  | #include "event-util.h" | 
|  | #include "fd-util.h" | 
|  | #include "log.h" | 
|  | #include "string-util.h" | 
|  |  | 
|  | int event_reset_time( | 
|  | sd_event *e, | 
|  | sd_event_source **s, | 
|  | clockid_t clock, | 
|  | uint64_t usec, | 
|  | uint64_t accuracy, | 
|  | sd_event_time_handler_t callback, | 
|  | void *userdata, | 
|  | int64_t priority, | 
|  | const char *description, | 
|  | bool force_reset) { | 
|  |  | 
|  | bool created = false; | 
|  | int enabled, r; | 
|  | clockid_t c; | 
|  |  | 
|  | assert(e); | 
|  | assert(s); | 
|  |  | 
|  | if (*s) { | 
|  | if (!force_reset) { | 
|  | r = sd_event_source_get_enabled(*s, &enabled); | 
|  | if (r < 0) | 
|  | return log_debug_errno(r, "sd-event: Failed to query whether event source \"%s\" is enabled or not: %m", | 
|  | strna((*s)->description ?: description)); | 
|  |  | 
|  | if (enabled != SD_EVENT_OFF) | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | r = sd_event_source_get_time_clock(*s, &c); | 
|  | if (r < 0) | 
|  | return log_debug_errno(r, "sd-event: Failed to get clock id of event source \"%s\": %m", strna((*s)->description ?: description)); | 
|  |  | 
|  | if (c != clock) | 
|  | return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), | 
|  | "sd-event: Current clock id %i of event source \"%s\" is different from specified one %i.", | 
|  | (int)c, | 
|  | strna((*s)->description ? : description), | 
|  | (int)clock); | 
|  |  | 
|  | r = sd_event_source_set_time(*s, usec); | 
|  | if (r < 0) | 
|  | return log_debug_errno(r, "sd-event: Failed to set time for event source \"%s\": %m", strna((*s)->description ?: description)); | 
|  |  | 
|  | r = sd_event_source_set_time_accuracy(*s, accuracy); | 
|  | if (r < 0) | 
|  | return log_debug_errno(r, "sd-event: Failed to set accuracy for event source \"%s\": %m", strna((*s)->description ?: description)); | 
|  |  | 
|  | /* callback function is not updated, as we do not have sd_event_source_set_time_callback(). */ | 
|  |  | 
|  | (void) sd_event_source_set_userdata(*s, userdata); | 
|  |  | 
|  | r = sd_event_source_set_enabled(*s, SD_EVENT_ONESHOT); | 
|  | if (r < 0) | 
|  | return log_debug_errno(r, "sd-event: Failed to enable event source \"%s\": %m", strna((*s)->description ?: description)); | 
|  | } else { | 
|  | r = sd_event_add_time(e, s, clock, usec, accuracy, callback, userdata); | 
|  | if (r < 0) | 
|  | return log_debug_errno(r, "sd-event: Failed to create timer event \"%s\": %m", strna(description)); | 
|  |  | 
|  | created = true; | 
|  | } | 
|  |  | 
|  | r = sd_event_source_set_priority(*s, priority); | 
|  | if (r < 0) | 
|  | return log_debug_errno(r, "sd-event: Failed to set priority for event source \"%s\": %m", strna((*s)->description ?: description)); | 
|  |  | 
|  | if (description) { | 
|  | r = sd_event_source_set_description(*s, description); | 
|  | if (r < 0) | 
|  | return log_debug_errno(r, "sd-event: Failed to set description for event source \"%s\": %m", description); | 
|  | } | 
|  |  | 
|  | return created; | 
|  | } | 
|  |  | 
|  | int event_reset_time_relative( | 
|  | sd_event *e, | 
|  | sd_event_source **s, | 
|  | clockid_t clock, | 
|  | uint64_t usec, | 
|  | uint64_t accuracy, | 
|  | sd_event_time_handler_t callback, | 
|  | void *userdata, | 
|  | int64_t priority, | 
|  | const char *description, | 
|  | bool force_reset) { | 
|  |  | 
|  | usec_t usec_now; | 
|  | int r; | 
|  |  | 
|  | assert(e); | 
|  |  | 
|  | r = sd_event_now(e, clock, &usec_now); | 
|  | if (r < 0) | 
|  | return log_debug_errno(r, "sd-event: Failed to get the current time: %m"); | 
|  |  | 
|  | return event_reset_time(e, s, clock, usec_add(usec_now, usec), accuracy, callback, userdata, priority, description, force_reset); | 
|  | } | 
|  |  | 
|  | int event_add_time_change(sd_event *e, sd_event_source **ret, sd_event_io_handler_t callback, void *userdata) { | 
|  | _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL; | 
|  | _cleanup_close_ int fd = -EBADF; | 
|  | int r; | 
|  |  | 
|  | assert(e); | 
|  |  | 
|  | /* Allocates an IO event source that gets woken up whenever the clock changes. Needs to be recreated on each event */ | 
|  |  | 
|  | fd = time_change_fd(); | 
|  | if (fd < 0) | 
|  | return fd; | 
|  |  | 
|  | r = sd_event_add_io(e, &s, fd, EPOLLIN, callback, userdata); | 
|  | if (r < 0) | 
|  | return r; | 
|  |  | 
|  | r = sd_event_source_set_io_fd_own(s, true); | 
|  | if (r < 0) | 
|  | return r; | 
|  |  | 
|  | TAKE_FD(fd); | 
|  |  | 
|  | r = sd_event_source_set_description(s, "time-change"); | 
|  | if (r < 0) | 
|  | return r; | 
|  |  | 
|  | if (ret) | 
|  | *ret = TAKE_PTR(s); | 
|  | else { | 
|  | r = sd_event_source_set_floating(s, true); | 
|  | if (r < 0) | 
|  | return r; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } |