1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <errno.h>
4 
5 #include "event-source.h"
6 #include "event-util.h"
7 #include "fd-util.h"
8 #include "log.h"
9 #include "string-util.h"
10 
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)11 int event_reset_time(
12                 sd_event *e,
13                 sd_event_source **s,
14                 clockid_t clock,
15                 uint64_t usec,
16                 uint64_t accuracy,
17                 sd_event_time_handler_t callback,
18                 void *userdata,
19                 int64_t priority,
20                 const char *description,
21                 bool force_reset) {
22 
23         bool created = false;
24         int enabled, r;
25         clockid_t c;
26 
27         assert(e);
28         assert(s);
29 
30         if (*s) {
31                 if (!force_reset) {
32                         r = sd_event_source_get_enabled(*s, &enabled);
33                         if (r < 0)
34                                 return log_debug_errno(r, "sd-event: Failed to query whether event source \"%s\" is enabled or not: %m",
35                                                        strna((*s)->description ?: description));
36 
37                         if (enabled != SD_EVENT_OFF)
38                                 return 0;
39                 }
40 
41                 r = sd_event_source_get_time_clock(*s, &c);
42                 if (r < 0)
43                         return log_debug_errno(r, "sd-event: Failed to get clock id of event source \"%s\": %m", strna((*s)->description ?: description));
44 
45                 if (c != clock)
46                         return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
47                                                "sd-event: Current clock id %i of event source \"%s\" is different from specified one %i.",
48                                                (int)c,
49                                                strna((*s)->description ? : description),
50                                                (int)clock);
51 
52                 r = sd_event_source_set_time(*s, usec);
53                 if (r < 0)
54                         return log_debug_errno(r, "sd-event: Failed to set time for event source \"%s\": %m", strna((*s)->description ?: description));
55 
56                 r = sd_event_source_set_time_accuracy(*s, accuracy);
57                 if (r < 0)
58                         return log_debug_errno(r, "sd-event: Failed to set accuracy for event source \"%s\": %m", strna((*s)->description ?: description));
59 
60                 /* callback function is not updated, as we do not have sd_event_source_set_time_callback(). */
61 
62                 (void) sd_event_source_set_userdata(*s, userdata);
63 
64                 r = sd_event_source_set_enabled(*s, SD_EVENT_ONESHOT);
65                 if (r < 0)
66                         return log_debug_errno(r, "sd-event: Failed to enable event source \"%s\": %m", strna((*s)->description ?: description));
67         } else {
68                 r = sd_event_add_time(e, s, clock, usec, accuracy, callback, userdata);
69                 if (r < 0)
70                         return log_debug_errno(r, "sd-event: Failed to create timer event \"%s\": %m", strna(description));
71 
72                 created = true;
73         }
74 
75         r = sd_event_source_set_priority(*s, priority);
76         if (r < 0)
77                 return log_debug_errno(r, "sd-event: Failed to set priority for event source \"%s\": %m", strna((*s)->description ?: description));
78 
79         if (description) {
80                 r = sd_event_source_set_description(*s, description);
81                 if (r < 0)
82                         return log_debug_errno(r, "sd-event: Failed to set description for event source \"%s\": %m", description);
83         }
84 
85         return created;
86 }
87 
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)88 int event_reset_time_relative(
89                 sd_event *e,
90                 sd_event_source **s,
91                 clockid_t clock,
92                 uint64_t usec,
93                 uint64_t accuracy,
94                 sd_event_time_handler_t callback,
95                 void *userdata,
96                 int64_t priority,
97                 const char *description,
98                 bool force_reset) {
99 
100         usec_t usec_now;
101         int r;
102 
103         assert(e);
104 
105         r = sd_event_now(e, clock, &usec_now);
106         if (r < 0)
107                 return log_debug_errno(r, "sd-event: Failed to get the current time: %m");
108 
109         return event_reset_time(e, s, clock, usec_add(usec_now, usec), accuracy, callback, userdata, priority, description, force_reset);
110 }
111 
event_source_disable(sd_event_source * s)112 int event_source_disable(sd_event_source *s) {
113         if (!s)
114                 return 0;
115 
116         return sd_event_source_set_enabled(s, SD_EVENT_OFF);
117 }
118 
event_source_is_enabled(sd_event_source * s)119 int event_source_is_enabled(sd_event_source *s) {
120         if (!s)
121                 return false;
122 
123         return sd_event_source_get_enabled(s, NULL);
124 }
125 
event_add_time_change(sd_event * e,sd_event_source ** ret,sd_event_io_handler_t callback,void * userdata)126 int event_add_time_change(sd_event *e, sd_event_source **ret, sd_event_io_handler_t callback, void *userdata) {
127         _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
128         _cleanup_close_ int fd = -1;
129         int r;
130 
131         assert(e);
132 
133         /* Allocates an IO event source that gets woken up whenever the clock changes. Needs to be recreated on each event */
134 
135         fd = time_change_fd();
136         if (fd < 0)
137                 return fd;
138 
139         r = sd_event_add_io(e, &s, fd, EPOLLIN, callback, userdata);
140         if (r < 0)
141                 return r;
142 
143         r = sd_event_source_set_io_fd_own(s, true);
144         if (r < 0)
145                 return r;
146 
147         TAKE_FD(fd);
148 
149         r = sd_event_source_set_description(s, "time-change");
150         if (r < 0)
151                 return r;
152 
153         if (ret)
154                 *ret = TAKE_PTR(s);
155         else {
156                 r = sd_event_source_set_floating(s, true);
157                 if (r < 0)
158                         return r;
159         }
160 
161         return 0;
162 }
163