File: | build-scan/../src/core/path.c |
Warning: | line 249, column 17 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
2 | ||||
3 | #include <errno(*__errno_location ()).h> | |||
4 | #include <sys/epoll.h> | |||
5 | #include <sys/inotify.h> | |||
6 | #include <unistd.h> | |||
7 | ||||
8 | #include "bus-error.h" | |||
9 | #include "bus-util.h" | |||
10 | #include "dbus-path.h" | |||
11 | #include "fd-util.h" | |||
12 | #include "fs-util.h" | |||
13 | #include "glob-util.h" | |||
14 | #include "macro.h" | |||
15 | #include "mkdir.h" | |||
16 | #include "path.h" | |||
17 | #include "special.h" | |||
18 | #include "stat-util.h" | |||
19 | #include "string-table.h" | |||
20 | #include "string-util.h" | |||
21 | #include "unit-name.h" | |||
22 | #include "unit.h" | |||
23 | ||||
24 | static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = { | |||
25 | [PATH_DEAD] = UNIT_INACTIVE, | |||
26 | [PATH_WAITING] = UNIT_ACTIVE, | |||
27 | [PATH_RUNNING] = UNIT_ACTIVE, | |||
28 | [PATH_FAILED] = UNIT_FAILED | |||
29 | }; | |||
30 | ||||
31 | static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); | |||
32 | ||||
33 | int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler) { | |||
34 | ||||
35 | static const int flags_table[_PATH_TYPE_MAX] = { | |||
36 | [PATH_EXISTS] = IN_DELETE_SELF0x00000400|IN_MOVE_SELF0x00000800|IN_ATTRIB0x00000004, | |||
37 | [PATH_EXISTS_GLOB] = IN_DELETE_SELF0x00000400|IN_MOVE_SELF0x00000800|IN_ATTRIB0x00000004, | |||
38 | [PATH_CHANGED] = IN_DELETE_SELF0x00000400|IN_MOVE_SELF0x00000800|IN_ATTRIB0x00000004|IN_CLOSE_WRITE0x00000008|IN_CREATE0x00000100|IN_DELETE0x00000200|IN_MOVED_FROM0x00000040|IN_MOVED_TO0x00000080, | |||
39 | [PATH_MODIFIED] = IN_DELETE_SELF0x00000400|IN_MOVE_SELF0x00000800|IN_ATTRIB0x00000004|IN_CLOSE_WRITE0x00000008|IN_CREATE0x00000100|IN_DELETE0x00000200|IN_MOVED_FROM0x00000040|IN_MOVED_TO0x00000080|IN_MODIFY0x00000002, | |||
40 | [PATH_DIRECTORY_NOT_EMPTY] = IN_DELETE_SELF0x00000400|IN_MOVE_SELF0x00000800|IN_ATTRIB0x00000004|IN_CREATE0x00000100|IN_MOVED_TO0x00000080 | |||
41 | }; | |||
42 | ||||
43 | bool_Bool exists = false0; | |||
44 | char *slash, *oldslash = NULL((void*)0); | |||
45 | int r; | |||
46 | ||||
47 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/path.c", 47, __PRETTY_FUNCTION__ ); } while (0); | |||
48 | assert(s->unit)do { if ((__builtin_expect(!!(!(s->unit)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s->unit"), "../src/core/path.c", 48, __PRETTY_FUNCTION__); } while (0); | |||
49 | assert(handler)do { if ((__builtin_expect(!!(!(handler)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("handler"), "../src/core/path.c", 49, __PRETTY_FUNCTION__ ); } while (0); | |||
50 | ||||
51 | path_spec_unwatch(s); | |||
52 | ||||
53 | s->inotify_fd = inotify_init1(IN_NONBLOCKIN_NONBLOCK|IN_CLOEXECIN_CLOEXEC); | |||
54 | if (s->inotify_fd < 0) { | |||
55 | r = -errno(*__errno_location ()); | |||
56 | goto fail; | |||
57 | } | |||
58 | ||||
59 | r = sd_event_add_io(s->unit->manager->event, &s->event_source, s->inotify_fd, EPOLLINEPOLLIN, handler, s); | |||
60 | if (r < 0) | |||
61 | goto fail; | |||
62 | ||||
63 | (void) sd_event_source_set_description(s->event_source, "path"); | |||
64 | ||||
65 | /* This function assumes the path was passed through path_simplify()! */ | |||
66 | assert(!strstr(s->path, "//"))do { if ((__builtin_expect(!!(!(!strstr(s->path, "//"))),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!strstr(s->path, \"//\")" ), "../src/core/path.c", 66, __PRETTY_FUNCTION__); } while (0 ); | |||
67 | ||||
68 | for (slash = strchr(s->path, '/'); ; slash = strchr(slash+1, '/')) { | |||
69 | char *cut = NULL((void*)0); | |||
70 | int flags; | |||
71 | char tmp; | |||
72 | ||||
73 | if (slash) { | |||
74 | cut = slash + (slash == s->path); | |||
75 | tmp = *cut; | |||
76 | *cut = '\0'; | |||
77 | ||||
78 | flags = IN_MOVE_SELF0x00000800 | IN_DELETE_SELF0x00000400 | IN_ATTRIB0x00000004 | IN_CREATE0x00000100 | IN_MOVED_TO0x00000080; | |||
79 | } else | |||
80 | flags = flags_table[s->type]; | |||
81 | ||||
82 | r = inotify_add_watch(s->inotify_fd, s->path, flags); | |||
83 | if (r < 0) { | |||
84 | if (IN_SET(errno, EACCES, ENOENT)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){13, 2})/sizeof(int)]; switch((*__errno_location ())) { case 13: case 2: _found = 1; break; default: break; } _found; })) { | |||
85 | if (cut) | |||
86 | *cut = tmp; | |||
87 | break; | |||
88 | } | |||
89 | ||||
90 | r = log_warning_errno(errno, "Failed to add watch on %s: %s", s->path, errno == ENOSPC ? "too many watches" : strerror(-r))({ int _level = ((4)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/core/path.c", 90, __func__, "Failed to add watch on %s: %s" , s->path, (*__errno_location ()) == 28 ? "too many watches" : strerror(-r)) : -abs(_e); }); | |||
91 | if (cut) | |||
92 | *cut = tmp; | |||
93 | goto fail; | |||
94 | } else { | |||
95 | exists = true1; | |||
96 | ||||
97 | /* Path exists, we don't need to watch parent too closely. */ | |||
98 | if (oldslash) { | |||
99 | char *cut2 = oldslash + (oldslash == s->path); | |||
100 | char tmp2 = *cut2; | |||
101 | *cut2 = '\0'; | |||
102 | ||||
103 | (void) inotify_add_watch(s->inotify_fd, s->path, IN_MOVE_SELF0x00000800); | |||
104 | /* Error is ignored, the worst can happen is we get spurious events. */ | |||
105 | ||||
106 | *cut2 = tmp2; | |||
107 | } | |||
108 | } | |||
109 | ||||
110 | if (cut) | |||
111 | *cut = tmp; | |||
112 | ||||
113 | if (slash) | |||
114 | oldslash = slash; | |||
115 | else { | |||
116 | /* whole path has been iterated over */ | |||
117 | s->primary_wd = r; | |||
118 | break; | |||
119 | } | |||
120 | } | |||
121 | ||||
122 | if (!exists) { | |||
123 | r = log_error_errno(errno, "Failed to add watch on any of the components of %s: %m", s->path)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/core/path.c", 123, __func__, "Failed to add watch on any of the components of %s: %m" , s->path) : -abs(_e); }); | |||
124 | /* either EACCESS or ENOENT */ | |||
125 | goto fail; | |||
126 | } | |||
127 | ||||
128 | return 0; | |||
129 | ||||
130 | fail: | |||
131 | path_spec_unwatch(s); | |||
132 | return r; | |||
133 | } | |||
134 | ||||
135 | void path_spec_unwatch(PathSpec *s) { | |||
136 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/path.c", 136, __PRETTY_FUNCTION__ ); } while (0); | |||
137 | ||||
138 | s->event_source = sd_event_source_unref(s->event_source); | |||
139 | s->inotify_fd = safe_close(s->inotify_fd); | |||
140 | } | |||
141 | ||||
142 | int path_spec_fd_event(PathSpec *s, uint32_t revents) { | |||
143 | union inotify_event_buffer buffer; | |||
144 | struct inotify_event *e; | |||
145 | ssize_t l; | |||
146 | int r = 0; | |||
147 | ||||
148 | if (revents != EPOLLINEPOLLIN) { | |||
149 | log_error("Got invalid poll event on inotify.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/core/path.c", 149, __func__, "Got invalid poll event on inotify." ) : -abs(_e); }); | |||
150 | return -EINVAL22; | |||
151 | } | |||
152 | ||||
153 | l = read(s->inotify_fd, &buffer, sizeof(buffer)); | |||
154 | if (l < 0) { | |||
155 | if (IN_SET(errno, EAGAIN, EINTR)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){11, 4})/sizeof(int)]; switch((*__errno_location ())) { case 11: case 4: _found = 1; break; default: break; } _found; })) | |||
156 | return 0; | |||
157 | ||||
158 | return log_error_errno(errno, "Failed to read inotify event: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/core/path.c", 158, __func__, "Failed to read inotify event: %m" ) : -abs(_e); }); | |||
159 | } | |||
160 | ||||
161 | FOREACH_INOTIFY_EVENT(e, buffer, l)for ((e) = &buffer.ev; (uint8_t*) (e) < (uint8_t*) (buffer .raw) + (l); (e) = (struct inotify_event*) ((uint8_t*) (e) + sizeof (struct inotify_event) + (e)->len)) { | |||
162 | if (IN_SET(s->type, PATH_CHANGED, PATH_MODIFIED)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){PATH_CHANGED, PATH_MODIFIED})/sizeof(int )]; switch(s->type) { case PATH_CHANGED: case PATH_MODIFIED : _found = 1; break; default: break; } _found; }) && | |||
163 | s->primary_wd == e->wd) | |||
164 | r = 1; | |||
165 | } | |||
166 | ||||
167 | return r; | |||
168 | } | |||
169 | ||||
170 | static bool_Bool path_spec_check_good(PathSpec *s, bool_Bool initial) { | |||
171 | bool_Bool good = false0; | |||
172 | ||||
173 | switch (s->type) { | |||
174 | ||||
175 | case PATH_EXISTS: | |||
176 | good = access(s->path, F_OK0) >= 0; | |||
177 | break; | |||
178 | ||||
179 | case PATH_EXISTS_GLOB: | |||
180 | good = glob_exists(s->path) > 0; | |||
181 | break; | |||
182 | ||||
183 | case PATH_DIRECTORY_NOT_EMPTY: { | |||
184 | int k; | |||
185 | ||||
186 | k = dir_is_empty(s->path); | |||
187 | good = !(k == -ENOENT2 || k > 0); | |||
188 | break; | |||
189 | } | |||
190 | ||||
191 | case PATH_CHANGED: | |||
192 | case PATH_MODIFIED: { | |||
193 | bool_Bool b; | |||
194 | ||||
195 | b = access(s->path, F_OK0) >= 0; | |||
196 | good = !initial && b != s->previous_exists; | |||
197 | s->previous_exists = b; | |||
198 | break; | |||
199 | } | |||
200 | ||||
201 | default: | |||
202 | ; | |||
203 | } | |||
204 | ||||
205 | return good; | |||
206 | } | |||
207 | ||||
208 | static void path_spec_mkdir(PathSpec *s, mode_t mode) { | |||
209 | int r; | |||
210 | ||||
211 | if (IN_SET(s->type, PATH_EXISTS, PATH_EXISTS_GLOB)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){PATH_EXISTS, PATH_EXISTS_GLOB})/sizeof(int )]; switch(s->type) { case PATH_EXISTS: case PATH_EXISTS_GLOB : _found = 1; break; default: break; } _found; })) | |||
212 | return; | |||
213 | ||||
214 | r = mkdir_p_label(s->path, mode); | |||
215 | if (r < 0) | |||
216 | log_warning_errno(r, "mkdir(%s) failed: %m", s->path)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/core/path.c", 216, __func__, "mkdir(%s) failed: %m" , s->path) : -abs(_e); }); | |||
217 | } | |||
218 | ||||
219 | static void path_spec_dump(PathSpec *s, FILE *f, const char *prefix) { | |||
220 | fprintf(f, | |||
221 | "%s%s: %s\n", | |||
222 | prefix, | |||
223 | path_type_to_string(s->type), | |||
224 | s->path); | |||
225 | } | |||
226 | ||||
227 | void path_spec_done(PathSpec *s) { | |||
228 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/path.c", 228, __PRETTY_FUNCTION__ ); } while (0); | |||
229 | assert(s->inotify_fd == -1)do { if ((__builtin_expect(!!(!(s->inotify_fd == -1)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->inotify_fd == -1" ), "../src/core/path.c", 229, __PRETTY_FUNCTION__); } while ( 0); | |||
230 | ||||
231 | free(s->path); | |||
232 | } | |||
233 | ||||
234 | static void path_init(Unit *u) { | |||
235 | Path *p = PATH(u); | |||
236 | ||||
237 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/path.c", 237, __PRETTY_FUNCTION__ ); } while (0); | |||
238 | assert(u->load_state == UNIT_STUB)do { if ((__builtin_expect(!!(!(u->load_state == UNIT_STUB )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("u->load_state == UNIT_STUB" ), "../src/core/path.c", 238, __PRETTY_FUNCTION__); } while ( 0); | |||
239 | ||||
240 | p->directory_mode = 0755; | |||
241 | } | |||
242 | ||||
243 | void path_free_specs(Path *p) { | |||
244 | PathSpec *s; | |||
245 | ||||
246 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 246, __PRETTY_FUNCTION__ ); } while (0); | |||
247 | ||||
248 | while ((s = p->specs)) { | |||
249 | path_spec_unwatch(s); | |||
| ||||
250 | LIST_REMOVE(spec, p->specs, s)do { typeof(*(p->specs)) **_head = &(p->specs), *_item = (s); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("_item"), "../src/core/path.c", 250, __PRETTY_FUNCTION__ ); } while (0); if (_item->spec_next) _item->spec_next-> spec_prev = _item->spec_prev; if (_item->spec_prev) _item ->spec_prev->spec_next = _item->spec_next; else { do { if ((__builtin_expect(!!(!(*_head == _item)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("*_head == _item"), "../src/core/path.c" , 250, __PRETTY_FUNCTION__); } while (0); *_head = _item-> spec_next; } _item->spec_next = _item->spec_prev = ((void *)0); } while (0); | |||
251 | path_spec_done(s); | |||
252 | free(s); | |||
253 | } | |||
254 | } | |||
255 | ||||
256 | static void path_done(Unit *u) { | |||
257 | Path *p = PATH(u); | |||
258 | ||||
259 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 259, __PRETTY_FUNCTION__ ); } while (0); | |||
| ||||
260 | ||||
261 | path_free_specs(p); | |||
262 | } | |||
263 | ||||
264 | static int path_add_mount_dependencies(Path *p) { | |||
265 | PathSpec *s; | |||
266 | int r; | |||
267 | ||||
268 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 268, __PRETTY_FUNCTION__ ); } while (0); | |||
269 | ||||
270 | LIST_FOREACH(spec, s, p->specs)for ((s) = (p->specs); (s); (s) = (s)->spec_next) { | |||
271 | r = unit_require_mounts_for(UNIT(p)({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), s->path, UNIT_DEPENDENCY_FILE); | |||
272 | if (r < 0) | |||
273 | return r; | |||
274 | } | |||
275 | ||||
276 | return 0; | |||
277 | } | |||
278 | ||||
279 | static int path_verify(Path *p) { | |||
280 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 280, __PRETTY_FUNCTION__ ); } while (0); | |||
281 | ||||
282 | if (UNIT(p)({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->load_state != UNIT_LOADED) | |||
283 | return 0; | |||
284 | ||||
285 | if (!p->specs) { | |||
286 | log_unit_error(UNIT(p), "Path unit lacks path setting. Refusing.")({ const Unit *_u = (({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/path.c", 286, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Path unit lacks path setting. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/path.c", 286, __func__, "Path unit lacks path setting. Refusing." ); }); | |||
287 | return -ENOEXEC8; | |||
288 | } | |||
289 | ||||
290 | return 0; | |||
291 | } | |||
292 | ||||
293 | static int path_add_default_dependencies(Path *p) { | |||
294 | int r; | |||
295 | ||||
296 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 296, __PRETTY_FUNCTION__ ); } while (0); | |||
297 | ||||
298 | if (!UNIT(p)({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->default_dependencies) | |||
299 | return 0; | |||
300 | ||||
301 | r = unit_add_dependency_by_name(UNIT(p)({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_BEFORE, SPECIAL_PATHS_TARGET"paths.target", NULL((void*)0), true1, UNIT_DEPENDENCY_DEFAULT); | |||
302 | if (r < 0) | |||
303 | return r; | |||
304 | ||||
305 | if (MANAGER_IS_SYSTEM(UNIT(p)->manager)((({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager)->unit_file_scope == UNIT_FILE_SYSTEM )) { | |||
306 | r = unit_add_two_dependencies_by_name(UNIT(p)({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET"sysinit.target", NULL((void*)0), true1, UNIT_DEPENDENCY_DEFAULT); | |||
307 | if (r < 0) | |||
308 | return r; | |||
309 | } | |||
310 | ||||
311 | return unit_add_two_dependencies_by_name(UNIT(p)({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET"shutdown.target", NULL((void*)0), true1, UNIT_DEPENDENCY_DEFAULT); | |||
312 | } | |||
313 | ||||
314 | static int path_add_trigger_dependencies(Path *p) { | |||
315 | Unit *x; | |||
316 | int r; | |||
317 | ||||
318 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 318, __PRETTY_FUNCTION__ ); } while (0); | |||
319 | ||||
320 | if (!hashmap_isempty(UNIT(p)({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->dependencies[UNIT_TRIGGERS])) | |||
321 | return 0; | |||
322 | ||||
323 | r = unit_load_related_unit(UNIT(p)({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), ".service", &x); | |||
324 | if (r < 0) | |||
325 | return r; | |||
326 | ||||
327 | return unit_add_two_dependencies(UNIT(p)({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_BEFORE, UNIT_TRIGGERS, x, true1, UNIT_DEPENDENCY_IMPLICIT); | |||
328 | } | |||
329 | ||||
330 | static int path_load(Unit *u) { | |||
331 | Path *p = PATH(u); | |||
332 | int r; | |||
333 | ||||
334 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/path.c", 334, __PRETTY_FUNCTION__ ); } while (0); | |||
335 | assert(u->load_state == UNIT_STUB)do { if ((__builtin_expect(!!(!(u->load_state == UNIT_STUB )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("u->load_state == UNIT_STUB" ), "../src/core/path.c", 335, __PRETTY_FUNCTION__); } while ( 0); | |||
336 | ||||
337 | r = unit_load_fragment_and_dropin(u); | |||
338 | if (r < 0) | |||
339 | return r; | |||
340 | ||||
341 | if (u->load_state == UNIT_LOADED) { | |||
342 | ||||
343 | r = path_add_trigger_dependencies(p); | |||
344 | if (r < 0) | |||
345 | return r; | |||
346 | ||||
347 | r = path_add_mount_dependencies(p); | |||
348 | if (r < 0) | |||
349 | return r; | |||
350 | ||||
351 | r = path_add_default_dependencies(p); | |||
352 | if (r < 0) | |||
353 | return r; | |||
354 | } | |||
355 | ||||
356 | return path_verify(p); | |||
357 | } | |||
358 | ||||
359 | static void path_dump(Unit *u, FILE *f, const char *prefix) { | |||
360 | Path *p = PATH(u); | |||
361 | Unit *trigger; | |||
362 | PathSpec *s; | |||
363 | ||||
364 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 364, __PRETTY_FUNCTION__ ); } while (0); | |||
365 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/core/path.c", 365, __PRETTY_FUNCTION__ ); } while (0); | |||
366 | ||||
367 | trigger = UNIT_TRIGGER(u)((Unit*) hashmap_first_key((u)->dependencies[UNIT_TRIGGERS ])); | |||
368 | ||||
369 | fprintf(f, | |||
370 | "%sPath State: %s\n" | |||
371 | "%sResult: %s\n" | |||
372 | "%sUnit: %s\n" | |||
373 | "%sMakeDirectory: %s\n" | |||
374 | "%sDirectoryMode: %04o\n", | |||
375 | prefix, path_state_to_string(p->state), | |||
376 | prefix, path_result_to_string(p->result), | |||
377 | prefix, trigger ? trigger->id : "n/a", | |||
378 | prefix, yes_no(p->make_directory), | |||
379 | prefix, p->directory_mode); | |||
380 | ||||
381 | LIST_FOREACH(spec, s, p->specs)for ((s) = (p->specs); (s); (s) = (s)->spec_next) | |||
382 | path_spec_dump(s, f, prefix); | |||
383 | } | |||
384 | ||||
385 | static void path_unwatch(Path *p) { | |||
386 | PathSpec *s; | |||
387 | ||||
388 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 388, __PRETTY_FUNCTION__ ); } while (0); | |||
389 | ||||
390 | LIST_FOREACH(spec, s, p->specs)for ((s) = (p->specs); (s); (s) = (s)->spec_next) | |||
391 | path_spec_unwatch(s); | |||
392 | } | |||
393 | ||||
394 | static int path_watch(Path *p) { | |||
395 | int r; | |||
396 | PathSpec *s; | |||
397 | ||||
398 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 398, __PRETTY_FUNCTION__ ); } while (0); | |||
399 | ||||
400 | LIST_FOREACH(spec, s, p->specs)for ((s) = (p->specs); (s); (s) = (s)->spec_next) { | |||
401 | r = path_spec_watch(s, path_dispatch_io); | |||
402 | if (r < 0) | |||
403 | return r; | |||
404 | } | |||
405 | ||||
406 | return 0; | |||
407 | } | |||
408 | ||||
409 | static void path_set_state(Path *p, PathState state) { | |||
410 | PathState old_state; | |||
411 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 411, __PRETTY_FUNCTION__ ); } while (0); | |||
412 | ||||
413 | old_state = p->state; | |||
414 | p->state = state; | |||
415 | ||||
416 | if (state != PATH_WAITING && | |||
417 | (state != PATH_RUNNING || p->inotify_triggered)) | |||
418 | path_unwatch(p); | |||
419 | ||||
420 | if (state != old_state) | |||
421 | log_unit_debug(UNIT(p), "Changed %s -> %s", path_state_to_string(old_state), path_state_to_string(state))({ const Unit *_u = (({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/path.c", 421, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Changed %s -> %s", path_state_to_string (old_state), path_state_to_string(state)) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/path.c" , 421, __func__, "Changed %s -> %s", path_state_to_string( old_state), path_state_to_string(state)); }); | |||
422 | ||||
423 | unit_notify(UNIT(p)({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), state_translation_table[old_state], state_translation_table[state], 0); | |||
424 | } | |||
425 | ||||
426 | static void path_enter_waiting(Path *p, bool_Bool initial, bool_Bool recheck); | |||
427 | ||||
428 | static int path_coldplug(Unit *u) { | |||
429 | Path *p = PATH(u); | |||
430 | ||||
431 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 431, __PRETTY_FUNCTION__ ); } while (0); | |||
432 | assert(p->state == PATH_DEAD)do { if ((__builtin_expect(!!(!(p->state == PATH_DEAD)),0) )) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("p->state == PATH_DEAD" ), "../src/core/path.c", 432, __PRETTY_FUNCTION__); } while ( 0); | |||
433 | ||||
434 | if (p->deserialized_state != p->state) { | |||
435 | ||||
436 | if (IN_SET(p->deserialized_state, PATH_WAITING, PATH_RUNNING)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){PATH_WAITING, PATH_RUNNING})/sizeof(int) ]; switch(p->deserialized_state) { case PATH_WAITING: case PATH_RUNNING: _found = 1; break; default: break; } _found; } )) | |||
437 | path_enter_waiting(p, true1, true1); | |||
438 | else | |||
439 | path_set_state(p, p->deserialized_state); | |||
440 | } | |||
441 | ||||
442 | return 0; | |||
443 | } | |||
444 | ||||
445 | static void path_enter_dead(Path *p, PathResult f) { | |||
446 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 446, __PRETTY_FUNCTION__ ); } while (0); | |||
447 | ||||
448 | if (p->result == PATH_SUCCESS) | |||
449 | p->result = f; | |||
450 | ||||
451 | if (p->result == PATH_SUCCESS) | |||
452 | unit_log_success(UNIT(p)({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | |||
453 | else | |||
454 | unit_log_failure(UNIT(p)({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), path_result_to_string(p->result)); | |||
455 | ||||
456 | path_set_state(p, p->result != PATH_SUCCESS ? PATH_FAILED : PATH_DEAD); | |||
457 | } | |||
458 | ||||
459 | static void path_enter_running(Path *p) { | |||
460 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
461 | Unit *trigger; | |||
462 | int r; | |||
463 | ||||
464 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 464, __PRETTY_FUNCTION__ ); } while (0); | |||
465 | ||||
466 | /* Don't start job if we are supposed to go down */ | |||
467 | if (unit_stop_pending(UNIT(p)({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))) | |||
468 | return; | |||
469 | ||||
470 | trigger = UNIT_TRIGGER(UNIT(p))((Unit*) hashmap_first_key((({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->dependencies [UNIT_TRIGGERS])); | |||
471 | if (!trigger) { | |||
472 | log_unit_error(UNIT(p), "Unit to trigger vanished.")({ const Unit *_u = (({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/path.c", 472, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Unit to trigger vanished.") : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))) , 0, "../src/core/path.c", 472, __func__, "Unit to trigger vanished." ); }); | |||
473 | path_enter_dead(p, PATH_FAILURE_RESOURCES); | |||
474 | return; | |||
475 | } | |||
476 | ||||
477 | r = manager_add_job(UNIT(p)({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager, JOB_START, trigger, JOB_REPLACE, NULL((void*)0), &error, NULL((void*)0)); | |||
478 | if (r < 0) | |||
479 | goto fail; | |||
480 | ||||
481 | p->inotify_triggered = false0; | |||
482 | ||||
483 | path_set_state(p, PATH_RUNNING); | |||
484 | path_unwatch(p); | |||
485 | ||||
486 | return; | |||
487 | ||||
488 | fail: | |||
489 | log_unit_warning(UNIT(p), "Failed to queue unit startup job: %s", bus_error_message(&error, r))({ const Unit *_u = (({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/path.c", 489, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to queue unit startup job: %s" , bus_error_message(&error, r)) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), 0, "../src/core/path.c", 489, __func__ , "Failed to queue unit startup job: %s", bus_error_message(& error, r)); }); | |||
490 | path_enter_dead(p, PATH_FAILURE_RESOURCES); | |||
491 | } | |||
492 | ||||
493 | static bool_Bool path_check_good(Path *p, bool_Bool initial) { | |||
494 | PathSpec *s; | |||
495 | bool_Bool good = false0; | |||
496 | ||||
497 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 497, __PRETTY_FUNCTION__ ); } while (0); | |||
498 | ||||
499 | LIST_FOREACH(spec, s, p->specs)for ((s) = (p->specs); (s); (s) = (s)->spec_next) { | |||
500 | good = path_spec_check_good(s, initial); | |||
501 | ||||
502 | if (good) | |||
503 | break; | |||
504 | } | |||
505 | ||||
506 | return good; | |||
507 | } | |||
508 | ||||
509 | static void path_enter_waiting(Path *p, bool_Bool initial, bool_Bool recheck) { | |||
510 | int r; | |||
511 | ||||
512 | if (recheck) | |||
513 | if (path_check_good(p, initial)) { | |||
514 | log_unit_debug(UNIT(p), "Got triggered.")({ const Unit *_u = (({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/path.c", 514, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got triggered.") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/path.c" , 514, __func__, "Got triggered."); }); | |||
515 | path_enter_running(p); | |||
516 | return; | |||
517 | } | |||
518 | ||||
519 | r = path_watch(p); | |||
520 | if (r < 0) | |||
521 | goto fail; | |||
522 | ||||
523 | /* Hmm, so now we have created inotify watches, but the file | |||
524 | * might have appeared/been removed by now, so we must | |||
525 | * recheck */ | |||
526 | ||||
527 | if (recheck) | |||
528 | if (path_check_good(p, false0)) { | |||
529 | log_unit_debug(UNIT(p), "Got triggered.")({ const Unit *_u = (({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/path.c", 529, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got triggered.") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/path.c" , 529, __func__, "Got triggered."); }); | |||
530 | path_enter_running(p); | |||
531 | return; | |||
532 | } | |||
533 | ||||
534 | path_set_state(p, PATH_WAITING); | |||
535 | return; | |||
536 | ||||
537 | fail: | |||
538 | log_unit_warning_errno(UNIT(p), r, "Failed to enter waiting state: %m")({ const Unit *_u = (({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/path.c", 538, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to enter waiting state: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/path.c", 538, __func__, "Failed to enter waiting state: %m" ); }); | |||
539 | path_enter_dead(p, PATH_FAILURE_RESOURCES); | |||
540 | } | |||
541 | ||||
542 | static void path_mkdir(Path *p) { | |||
543 | PathSpec *s; | |||
544 | ||||
545 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 545, __PRETTY_FUNCTION__ ); } while (0); | |||
546 | ||||
547 | if (!p->make_directory) | |||
548 | return; | |||
549 | ||||
550 | LIST_FOREACH(spec, s, p->specs)for ((s) = (p->specs); (s); (s) = (s)->spec_next) | |||
551 | path_spec_mkdir(s, p->directory_mode); | |||
552 | } | |||
553 | ||||
554 | static int path_start(Unit *u) { | |||
555 | Path *p = PATH(u); | |||
556 | Unit *trigger; | |||
557 | int r; | |||
558 | ||||
559 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 559, __PRETTY_FUNCTION__ ); } while (0); | |||
560 | assert(IN_SET(p->state, PATH_DEAD, PATH_FAILED))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){PATH_DEAD, PATH_FAILED})/sizeof(int)]; switch (p->state) { case PATH_DEAD: case PATH_FAILED: _found = 1; break; default: break; } _found; }))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("IN_SET(p->state, PATH_DEAD, PATH_FAILED)" ), "../src/core/path.c", 560, __PRETTY_FUNCTION__); } while ( 0); | |||
561 | ||||
562 | trigger = UNIT_TRIGGER(u)((Unit*) hashmap_first_key((u)->dependencies[UNIT_TRIGGERS ])); | |||
563 | if (!trigger || trigger->load_state != UNIT_LOADED) { | |||
564 | log_unit_error(u, "Refusing to start, unit to trigger not loaded.")({ const Unit *_u = (u); _u ? log_object_internal(3, 0, "../src/core/path.c" , 564, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Refusing to start, unit to trigger not loaded.") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((3))), 0, "../src/core/path.c" , 564, __func__, "Refusing to start, unit to trigger not loaded." ); }); | |||
565 | return -ENOENT2; | |||
566 | } | |||
567 | ||||
568 | r = unit_start_limit_test(u); | |||
569 | if (r < 0) { | |||
570 | path_enter_dead(p, PATH_FAILURE_START_LIMIT_HIT); | |||
571 | return r; | |||
572 | } | |||
573 | ||||
574 | r = unit_acquire_invocation_id(u); | |||
575 | if (r < 0) | |||
576 | return r; | |||
577 | ||||
578 | path_mkdir(p); | |||
579 | ||||
580 | p->result = PATH_SUCCESS; | |||
581 | path_enter_waiting(p, true1, true1); | |||
582 | ||||
583 | return 1; | |||
584 | } | |||
585 | ||||
586 | static int path_stop(Unit *u) { | |||
587 | Path *p = PATH(u); | |||
588 | ||||
589 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 589, __PRETTY_FUNCTION__ ); } while (0); | |||
590 | assert(IN_SET(p->state, PATH_WAITING, PATH_RUNNING))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){PATH_WAITING, PATH_RUNNING})/sizeof(int)]; switch (p->state) { case PATH_WAITING: case PATH_RUNNING: _found = 1; break; default: break; } _found; }))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("IN_SET(p->state, PATH_WAITING, PATH_RUNNING)" ), "../src/core/path.c", 590, __PRETTY_FUNCTION__); } while ( 0); | |||
591 | ||||
592 | path_enter_dead(p, PATH_SUCCESS); | |||
593 | return 1; | |||
594 | } | |||
595 | ||||
596 | static int path_serialize(Unit *u, FILE *f, FDSet *fds) { | |||
597 | Path *p = PATH(u); | |||
598 | ||||
599 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/path.c", 599, __PRETTY_FUNCTION__ ); } while (0); | |||
600 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/core/path.c", 600, __PRETTY_FUNCTION__ ); } while (0); | |||
601 | assert(fds)do { if ((__builtin_expect(!!(!(fds)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fds"), "../src/core/path.c", 601, __PRETTY_FUNCTION__ ); } while (0); | |||
602 | ||||
603 | unit_serialize_item(u, f, "state", path_state_to_string(p->state)); | |||
604 | unit_serialize_item(u, f, "result", path_result_to_string(p->result)); | |||
605 | ||||
606 | return 0; | |||
607 | } | |||
608 | ||||
609 | static int path_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { | |||
610 | Path *p = PATH(u); | |||
611 | ||||
612 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/path.c", 612, __PRETTY_FUNCTION__ ); } while (0); | |||
613 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/core/path.c", 613, __PRETTY_FUNCTION__ ); } while (0); | |||
614 | assert(value)do { if ((__builtin_expect(!!(!(value)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("value"), "../src/core/path.c", 614, __PRETTY_FUNCTION__ ); } while (0); | |||
615 | assert(fds)do { if ((__builtin_expect(!!(!(fds)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fds"), "../src/core/path.c", 615, __PRETTY_FUNCTION__ ); } while (0); | |||
616 | ||||
617 | if (streq(key, "state")(strcmp((key),("state")) == 0)) { | |||
618 | PathState state; | |||
619 | ||||
620 | state = path_state_from_string(value); | |||
621 | if (state < 0) | |||
622 | log_unit_debug(u, "Failed to parse state value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/path.c" , 622, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse state value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/path.c" , 622, __func__, "Failed to parse state value: %s", value); } ); | |||
623 | else | |||
624 | p->deserialized_state = state; | |||
625 | ||||
626 | } else if (streq(key, "result")(strcmp((key),("result")) == 0)) { | |||
627 | PathResult f; | |||
628 | ||||
629 | f = path_result_from_string(value); | |||
630 | if (f < 0) | |||
631 | log_unit_debug(u, "Failed to parse result value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/path.c" , 631, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse result value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/path.c" , 631, __func__, "Failed to parse result value: %s", value); } ); | |||
632 | else if (f != PATH_SUCCESS) | |||
633 | p->result = f; | |||
634 | ||||
635 | } else | |||
636 | log_unit_debug(u, "Unknown serialization key: %s", key)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/path.c" , 636, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Unknown serialization key: %s", key) : log_internal_realm( ((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/path.c" , 636, __func__, "Unknown serialization key: %s", key); }); | |||
637 | ||||
638 | return 0; | |||
639 | } | |||
640 | ||||
641 | _pure___attribute__ ((pure)) static UnitActiveState path_active_state(Unit *u) { | |||
642 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/path.c", 642, __PRETTY_FUNCTION__ ); } while (0); | |||
643 | ||||
644 | return state_translation_table[PATH(u)->state]; | |||
645 | } | |||
646 | ||||
647 | _pure___attribute__ ((pure)) static const char *path_sub_state_to_string(Unit *u) { | |||
648 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/path.c", 648, __PRETTY_FUNCTION__ ); } while (0); | |||
649 | ||||
650 | return path_state_to_string(PATH(u)->state); | |||
651 | } | |||
652 | ||||
653 | static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { | |||
654 | PathSpec *s = userdata; | |||
655 | Path *p; | |||
656 | int changed; | |||
657 | ||||
658 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/path.c", 658, __PRETTY_FUNCTION__ ); } while (0); | |||
659 | assert(s->unit)do { if ((__builtin_expect(!!(!(s->unit)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s->unit"), "../src/core/path.c", 659 , __PRETTY_FUNCTION__); } while (0); | |||
660 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/core/path.c", 660 , __PRETTY_FUNCTION__); } while (0); | |||
661 | ||||
662 | p = PATH(s->unit); | |||
663 | ||||
664 | if (!IN_SET(p->state, PATH_WAITING, PATH_RUNNING)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){PATH_WAITING, PATH_RUNNING})/sizeof(int) ]; switch(p->state) { case PATH_WAITING: case PATH_RUNNING : _found = 1; break; default: break; } _found; })) | |||
665 | return 0; | |||
666 | ||||
667 | /* log_debug("inotify wakeup on %s.", u->id); */ | |||
668 | ||||
669 | LIST_FOREACH(spec, s, p->specs)for ((s) = (p->specs); (s); (s) = (s)->spec_next) | |||
670 | if (path_spec_owns_inotify_fd(s, fd)) | |||
671 | break; | |||
672 | ||||
673 | if (!s) { | |||
674 | log_error("Got event on unknown fd.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/core/path.c", 674, __func__, "Got event on unknown fd." ) : -abs(_e); }); | |||
675 | goto fail; | |||
676 | } | |||
677 | ||||
678 | changed = path_spec_fd_event(s, revents); | |||
679 | if (changed < 0) | |||
680 | goto fail; | |||
681 | ||||
682 | /* If we are already running, then remember that one event was | |||
683 | * dispatched so that we restart the service only if something | |||
684 | * actually changed on disk */ | |||
685 | p->inotify_triggered = true1; | |||
686 | ||||
687 | if (changed) | |||
688 | path_enter_running(p); | |||
689 | else | |||
690 | path_enter_waiting(p, false0, true1); | |||
691 | ||||
692 | return 0; | |||
693 | ||||
694 | fail: | |||
695 | path_enter_dead(p, PATH_FAILURE_RESOURCES); | |||
696 | return 0; | |||
697 | } | |||
698 | ||||
699 | static void path_trigger_notify(Unit *u, Unit *other) { | |||
700 | Path *p = PATH(u); | |||
701 | ||||
702 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/path.c", 702, __PRETTY_FUNCTION__ ); } while (0); | |||
703 | assert(other)do { if ((__builtin_expect(!!(!(other)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("other"), "../src/core/path.c", 703, __PRETTY_FUNCTION__ ); } while (0); | |||
704 | ||||
705 | /* Invoked whenever the unit we trigger changes state or gains | |||
706 | * or loses a job */ | |||
707 | ||||
708 | if (other->load_state != UNIT_LOADED) | |||
709 | return; | |||
710 | ||||
711 | if (p->state == PATH_RUNNING && | |||
712 | UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) { | |||
713 | log_unit_debug(UNIT(p), "Got notified about unit deactivation.")({ const Unit *_u = (({ typeof(p) _u_ = (p); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/path.c", 713, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got notified about unit deactivation." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7 ))), 0, "../src/core/path.c", 713, __func__, "Got notified about unit deactivation." ); }); | |||
714 | ||||
715 | /* Hmm, so inotify was triggered since the | |||
716 | * last activation, so I guess we need to | |||
717 | * recheck what is going on. */ | |||
718 | path_enter_waiting(p, false0, p->inotify_triggered); | |||
719 | } | |||
720 | } | |||
721 | ||||
722 | static void path_reset_failed(Unit *u) { | |||
723 | Path *p = PATH(u); | |||
724 | ||||
725 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/path.c", 725, __PRETTY_FUNCTION__ ); } while (0); | |||
726 | ||||
727 | if (p->state == PATH_FAILED) | |||
728 | path_set_state(p, PATH_DEAD); | |||
729 | ||||
730 | p->result = PATH_SUCCESS; | |||
731 | } | |||
732 | ||||
733 | static const char* const path_type_table[_PATH_TYPE_MAX] = { | |||
734 | [PATH_EXISTS] = "PathExists", | |||
735 | [PATH_EXISTS_GLOB] = "PathExistsGlob", | |||
736 | [PATH_DIRECTORY_NOT_EMPTY] = "DirectoryNotEmpty", | |||
737 | [PATH_CHANGED] = "PathChanged", | |||
738 | [PATH_MODIFIED] = "PathModified", | |||
739 | }; | |||
740 | ||||
741 | DEFINE_STRING_TABLE_LOOKUP(path_type, PathType)const char *path_type_to_string(PathType i) { if (i < 0 || i >= (PathType) __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(path_type_table), typeof(&*(path_type_table))), sizeof (path_type_table)/sizeof((path_type_table)[0]), ((void)0)))) return ((void*)0); return path_type_table[i]; } PathType path_type_from_string (const char *s) { return (PathType) string_table_lookup(path_type_table , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(path_type_table), typeof(&*(path_type_table))), sizeof (path_type_table)/sizeof((path_type_table)[0]), ((void)0))), s ); }; | |||
742 | ||||
743 | static const char* const path_result_table[_PATH_RESULT_MAX] = { | |||
744 | [PATH_SUCCESS] = "success", | |||
745 | [PATH_FAILURE_RESOURCES] = "resources", | |||
746 | [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit", | |||
747 | }; | |||
748 | ||||
749 | DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult)const char *path_result_to_string(PathResult i) { if (i < 0 || i >= (PathResult) __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(path_result_table), typeof (&*(path_result_table))), sizeof(path_result_table)/sizeof ((path_result_table)[0]), ((void)0)))) return ((void*)0); return path_result_table[i]; } PathResult path_result_from_string(const char *s) { return (PathResult) string_table_lookup(path_result_table , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(path_result_table), typeof(&*(path_result_table)) ), sizeof(path_result_table)/sizeof((path_result_table)[0]), ( (void)0))), s); }; | |||
750 | ||||
751 | const UnitVTable path_vtable = { | |||
752 | .object_size = sizeof(Path), | |||
753 | ||||
754 | .sections = | |||
755 | "Unit\0" | |||
756 | "Path\0" | |||
757 | "Install\0", | |||
758 | .private_section = "Path", | |||
759 | ||||
760 | .can_transient = true1, | |||
761 | ||||
762 | .init = path_init, | |||
763 | .done = path_done, | |||
764 | .load = path_load, | |||
765 | ||||
766 | .coldplug = path_coldplug, | |||
767 | ||||
768 | .dump = path_dump, | |||
769 | ||||
770 | .start = path_start, | |||
771 | .stop = path_stop, | |||
772 | ||||
773 | .serialize = path_serialize, | |||
774 | .deserialize_item = path_deserialize_item, | |||
775 | ||||
776 | .active_state = path_active_state, | |||
777 | .sub_state_to_string = path_sub_state_to_string, | |||
778 | ||||
779 | .trigger_notify = path_trigger_notify, | |||
780 | ||||
781 | .reset_failed = path_reset_failed, | |||
782 | ||||
783 | .bus_vtable = bus_path_vtable, | |||
784 | .bus_set_property = bus_path_set_property, | |||
785 | }; |