]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/device.c
core/execute: use cleanup_strv_free
[thirdparty/systemd.git] / src / core / device.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
5cb5a6ff 2
a7334b09
LP
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
25ac040b 22#include <errno.h>
f94ea366 23#include <sys/epoll.h>
25ac040b
LP
24#include <libudev.h>
25
87f0e418 26#include "unit.h"
5cb5a6ff
LP
27#include "device.h"
28#include "strv.h"
25ac040b 29#include "log.h"
9e2f7c11 30#include "unit-name.h"
4139c1b2 31#include "dbus-device.h"
f6a6225e 32#include "def.h"
9eb977db 33#include "path-util.h"
5cb5a6ff 34
f50e0a01
LP
35static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
36 [DEVICE_DEAD] = UNIT_INACTIVE,
73608ed9 37 [DEVICE_PLUGGED] = UNIT_ACTIVE
f50e0a01
LP
38};
39
8fe914ec
LP
40static void device_unset_sysfs(Device *d) {
41 Device *first;
42
43 assert(d);
44
a7f241db
LP
45 if (!d->sysfs)
46 return;
47
48 /* Remove this unit from the chain of devices which share the
49 * same sysfs path. */
1124fe6f 50 first = hashmap_get(UNIT(d)->manager->devices_by_sysfs, d->sysfs);
a7f241db 51 LIST_REMOVE(Device, same_sysfs, first, d);
8fe914ec 52
a7f241db 53 if (first)
1124fe6f 54 hashmap_remove_and_replace(UNIT(d)->manager->devices_by_sysfs, d->sysfs, first->sysfs, first);
a7f241db 55 else
1124fe6f 56 hashmap_remove(UNIT(d)->manager->devices_by_sysfs, d->sysfs);
a7f241db
LP
57
58 free(d->sysfs);
59 d->sysfs = NULL;
8fe914ec
LP
60}
61
faf919f1
LP
62static void device_init(Unit *u) {
63 Device *d = DEVICE(u);
64
65 assert(d);
1124fe6f 66 assert(UNIT(d)->load_state == UNIT_STUB);
faf919f1 67
8fe914ec
LP
68 /* In contrast to all other unit types we timeout jobs waiting
69 * for devices by default. This is because they otherwise wait
35b8ca3a 70 * indefinitely for plugged in devices, something which cannot
8fe914ec
LP
71 * happen for the other units since their operations time out
72 * anyway. */
1124fe6f 73 UNIT(d)->job_timeout = DEFAULT_TIMEOUT_USEC;
c8f4d764 74
1124fe6f
MS
75 UNIT(d)->ignore_on_isolate = true;
76 UNIT(d)->ignore_on_snapshot = true;
faf919f1
LP
77}
78
87f0e418
LP
79static void device_done(Unit *u) {
80 Device *d = DEVICE(u);
034c6ed7
LP
81
82 assert(d);
e537352b 83
8fe914ec 84 device_unset_sysfs(d);
e537352b
LP
85}
86
f50e0a01
LP
87static void device_set_state(Device *d, DeviceState state) {
88 DeviceState old_state;
89 assert(d);
5cb5a6ff 90
f50e0a01
LP
91 old_state = d->state;
92 d->state = state;
5cb5a6ff 93
e537352b 94 if (state != old_state)
40d50879 95 log_debug("%s changed %s -> %s",
1124fe6f 96 UNIT(d)->id,
a16e1123
LP
97 device_state_to_string(old_state),
98 device_state_to_string(state));
f50e0a01 99
e2f3b44c 100 unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], true);
f50e0a01
LP
101}
102
103static int device_coldplug(Unit *u) {
104 Device *d = DEVICE(u);
105
106 assert(d);
107 assert(d->state == DEVICE_DEAD);
108
109 if (d->sysfs)
73608ed9 110 device_set_state(d, DEVICE_PLUGGED);
f50e0a01
LP
111
112 return 0;
113}
114
115static void device_dump(Unit *u, FILE *f, const char *prefix) {
25ac040b 116 Device *d = DEVICE(u);
5cb5a6ff 117
25ac040b 118 assert(d);
5cb5a6ff
LP
119
120 fprintf(f,
25ac040b
LP
121 "%sDevice State: %s\n"
122 "%sSysfs Path: %s\n",
a16e1123 123 prefix, device_state_to_string(d->state),
f50e0a01
LP
124 prefix, strna(d->sysfs));
125}
126
127static UnitActiveState device_active_state(Unit *u) {
128 assert(u);
129
130 return state_translation_table[DEVICE(u)->state];
25ac040b
LP
131}
132
10a94420
LP
133static const char *device_sub_state_to_string(Unit *u) {
134 assert(u);
135
a16e1123 136 return device_state_to_string(DEVICE(u)->state);
10a94420
LP
137}
138
8fe914ec 139static int device_add_escaped_name(Unit *u, const char *dn) {
25ac040b
LP
140 char *e;
141 int r;
142
143 assert(u);
144 assert(dn);
145 assert(dn[0] == '/');
146
b0193f1c
LP
147 e = unit_name_from_path(dn, ".device");
148 if (!e)
25ac040b
LP
149 return -ENOMEM;
150
151 r = unit_add_name(u, e);
152 free(e);
153
154 if (r < 0 && r != -EEXIST)
155 return r;
156
157 return 0;
158}
159
aab14b13
LP
160static int device_find_escape_name(Manager *m, const char *dn, Unit **_u) {
161 char *e;
162 Unit *u;
163
164 assert(m);
165 assert(dn);
166 assert(dn[0] == '/');
167 assert(_u);
168
b0193f1c
LP
169 e = unit_name_from_path(dn, ".device");
170 if (!e)
aab14b13
LP
171 return -ENOMEM;
172
173 u = manager_get_unit(m, e);
174 free(e);
175
176 if (u) {
177 *_u = u;
178 return 1;
179 }
180
181 return 0;
182}
183
8fe914ec
LP
184static int device_update_unit(Manager *m, struct udev_device *dev, const char *path, bool main) {
185 const char *sysfs, *model;
25ac040b
LP
186 Unit *u = NULL;
187 int r;
25ac040b 188 bool delete;
25ac040b
LP
189
190 assert(m);
191
7f275a9f
LP
192 if (!(sysfs = udev_device_get_syspath(dev)))
193 return -ENOMEM;
194
8fe914ec 195 if ((r = device_find_escape_name(m, path, &u)) < 0)
aab14b13 196 return r;
25ac040b 197
5845b46b 198 if (u && DEVICE(u)->sysfs && !path_equal(DEVICE(u)->sysfs, sysfs))
8fe914ec 199 return -EEXIST;
25ac040b 200
aab14b13
LP
201 if (!u) {
202 delete = true;
203
7d17cfbc
MS
204 u = unit_new(m, sizeof(Device));
205 if (!u)
aab14b13 206 return -ENOMEM;
25ac040b 207
7d17cfbc
MS
208 r = device_add_escaped_name(u, path);
209 if (r < 0)
25ac040b
LP
210 goto fail;
211
ee6cb288
LP
212 unit_add_to_load_queue(u);
213 } else
214 delete = false;
215
216 /* If this was created via some dependency and has not
217 * actually been seen yet ->sysfs will not be
218 * initialized. Hence initialize it if necessary. */
219
220 if (!DEVICE(u)->sysfs) {
221 Device *first;
222
25ac040b
LP
223 if (!(DEVICE(u)->sysfs = strdup(sysfs))) {
224 r = -ENOMEM;
225 goto fail;
226 }
227
8fe914ec
LP
228 if (!m->devices_by_sysfs)
229 if (!(m->devices_by_sysfs = hashmap_new(string_hash_func, string_compare_func))) {
230 r = -ENOMEM;
231 goto fail;
232 }
25ac040b 233
8fe914ec
LP
234 first = hashmap_get(m->devices_by_sysfs, sysfs);
235 LIST_PREPEND(Device, same_sysfs, first, DEVICE(u));
236
237 if ((r = hashmap_replace(m->devices_by_sysfs, DEVICE(u)->sysfs, first)) < 0)
25ac040b 238 goto fail;
ee6cb288 239 }
8fe914ec 240
aab14b13
LP
241 if ((model = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE")) ||
242 (model = udev_device_get_property_value(dev, "ID_MODEL"))) {
243 if ((r = unit_set_description(u, model)) < 0)
244 goto fail;
4e85aff4 245 } else
8fe914ec 246 if ((r = unit_set_description(u, path)) < 0)
4e85aff4 247 goto fail;
aab14b13 248
8fe914ec
LP
249 if (main) {
250 /* The additional systemd udev properties we only
251 * interpret for the main object */
252 const char *wants, *alias;
253
07845c14
KS
254 alias = udev_device_get_property_value(dev, "SYSTEMD_ALIAS");
255 if (alias) {
256 char *state, *w;
257 size_t l;
258
259 FOREACH_WORD_QUOTED(w, l, alias, state) {
260 char *e;
261
262 e = strndup(w, l);
263 if (!e) {
264 r = -ENOMEM;
8fe914ec 265 goto fail;
07845c14
KS
266 }
267
268 if (!is_path(e)) {
269 log_warning("SYSTEMD_ALIAS for %s is not a path, ignoring: %s", sysfs, e);
270 free(e);
271 } else {
22349cee 272 device_update_unit(m, dev, e, false);
07845c14 273 free(e);
07845c14 274 }
b866264a 275 }
8fe914ec 276 }
25ac040b 277
07845c14
KS
278 wants = udev_device_get_property_value(dev, "SYSTEMD_WANTS");
279 if (wants) {
8fe914ec
LP
280 char *state, *w;
281 size_t l;
25ac040b 282
8fe914ec
LP
283 FOREACH_WORD_QUOTED(w, l, wants, state) {
284 char *e;
285
07845c14
KS
286 e = strndup(w, l);
287 if (!e) {
8fe914ec
LP
288 r = -ENOMEM;
289 goto fail;
290 }
291
292 r = unit_add_dependency_by_name(u, UNIT_WANTS, e, NULL, true);
293 free(e);
8fe914ec
LP
294 if (r < 0)
295 goto fail;
296 }
25ac040b 297 }
a7f241db 298 }
f94ea366 299
c1e1601e 300 unit_add_to_dbus_queue(u);
25ac040b
LP
301 return 0;
302
303fail:
ee5f3479
LP
304 log_warning("Failed to load device unit: %s", strerror(-r));
305
25ac040b
LP
306 if (delete && u)
307 unit_free(u);
ee5f3479 308
25ac040b
LP
309 return r;
310}
311
8fe914ec
LP
312static int device_process_new_device(Manager *m, struct udev_device *dev, bool update_state) {
313 const char *sysfs, *dn;
314 struct udev_list_entry *item = NULL, *first = NULL;
315
316 assert(m);
317
318 if (!(sysfs = udev_device_get_syspath(dev)))
319 return -ENOMEM;
320
321 /* Add the main unit named after the sysfs path */
322 device_update_unit(m, dev, sysfs, true);
323
324 /* Add an additional unit for the device node */
325 if ((dn = udev_device_get_devnode(dev)))
326 device_update_unit(m, dev, dn, false);
327
328 /* Add additional units for all symlinks */
329 first = udev_device_get_devlinks_list_entry(dev);
330 udev_list_entry_foreach(item, first) {
331 const char *p;
5845b46b 332 struct stat st;
8fe914ec
LP
333
334 /* Don't bother with the /dev/block links */
335 p = udev_list_entry_get_name(item);
336
337 if (path_startswith(p, "/dev/block/") ||
338 path_startswith(p, "/dev/char/"))
339 continue;
340
5845b46b
LP
341 /* Verify that the symlink in the FS actually belongs
342 * to this device. This is useful to deal with
343 * conflicting devices, e.g. when two disks want the
344 * same /dev/disk/by-label/xxx link because they have
345 * the same label. We want to make sure that the same
346 * device that won the symlink wins in systemd, so we
347 * check the device node major/minor*/
348 if (stat(p, &st) >= 0)
349 if ((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) ||
350 st.st_rdev != udev_device_get_devnum(dev))
351 continue;
352
8fe914ec
LP
353 device_update_unit(m, dev, p, false);
354 }
355
356 if (update_state) {
357 Device *d, *l;
358
359 manager_dispatch_load_queue(m);
360
361 l = hashmap_get(m->devices_by_sysfs, sysfs);
362 LIST_FOREACH(same_sysfs, d, l)
363 device_set_state(d, DEVICE_PLUGGED);
364 }
365
366 return 0;
367}
368
f94ea366 369static int device_process_path(Manager *m, const char *path, bool update_state) {
25ac040b
LP
370 int r;
371 struct udev_device *dev;
372
373 assert(m);
374 assert(path);
375
376 if (!(dev = udev_device_new_from_syspath(m->udev, path))) {
377 log_warning("Failed to get udev device object from udev for path %s.", path);
378 return -ENOMEM;
379 }
380
f94ea366 381 r = device_process_new_device(m, dev, update_state);
25ac040b
LP
382 udev_device_unref(dev);
383 return r;
384}
385
f94ea366
LP
386static int device_process_removed_device(Manager *m, struct udev_device *dev) {
387 const char *sysfs;
f94ea366
LP
388 Device *d;
389
390 assert(m);
391 assert(dev);
392
393 if (!(sysfs = udev_device_get_syspath(dev)))
394 return -ENOMEM;
395
8fe914ec
LP
396 /* Remove all units of this sysfs path */
397 while ((d = hashmap_get(m->devices_by_sysfs, sysfs))) {
398 device_unset_sysfs(d);
399 device_set_state(d, DEVICE_DEAD);
400 }
f94ea366 401
f94ea366
LP
402 return 0;
403}
404
a7f241db
LP
405static Unit *device_following(Unit *u) {
406 Device *d = DEVICE(u);
407 Device *other, *first = NULL;
408
409 assert(d);
410
ac155bb8 411 if (startswith(u->id, "sys-"))
a7f241db
LP
412 return NULL;
413
414 /* Make everybody follow the unit that's named after the sysfs path */
415 for (other = d->same_sysfs_next; other; other = other->same_sysfs_next)
1124fe6f 416 if (startswith(UNIT(other)->id, "sys-"))
a7f241db
LP
417 return UNIT(other);
418
419 for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev) {
1124fe6f 420 if (startswith(UNIT(other)->id, "sys-"))
a7f241db
LP
421 return UNIT(other);
422
423 first = other;
424 }
425
426 return UNIT(first);
427}
428
6210e7fc
LP
429static int device_following_set(Unit *u, Set **_s) {
430 Device *d = DEVICE(u);
431 Device *other;
432 Set *s;
433 int r;
434
435 assert(d);
436 assert(_s);
437
438 if (!d->same_sysfs_prev && !d->same_sysfs_next) {
439 *_s = NULL;
440 return 0;
441 }
442
443 if (!(s = set_new(NULL, NULL)))
444 return -ENOMEM;
445
446 for (other = d->same_sysfs_next; other; other = other->same_sysfs_next)
447 if ((r = set_put(s, other)) < 0)
448 goto fail;
449
450 for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev)
451 if ((r = set_put(s, other)) < 0)
452 goto fail;
453
454 *_s = s;
455 return 1;
456
457fail:
458 set_free(s);
459 return r;
460}
461
25ac040b
LP
462static void device_shutdown(Manager *m) {
463 assert(m);
464
a16e1123 465 if (m->udev_monitor) {
f94ea366 466 udev_monitor_unref(m->udev_monitor);
a16e1123
LP
467 m->udev_monitor = NULL;
468 }
f94ea366 469
a16e1123 470 if (m->udev) {
25ac040b 471 udev_unref(m->udev);
a16e1123
LP
472 m->udev = NULL;
473 }
8fe914ec
LP
474
475 hashmap_free(m->devices_by_sysfs);
476 m->devices_by_sysfs = NULL;
25ac040b
LP
477}
478
479static int device_enumerate(Manager *m) {
f94ea366 480 struct epoll_event ev;
25ac040b
LP
481 int r;
482 struct udev_enumerate *e = NULL;
483 struct udev_list_entry *item = NULL, *first = NULL;
484
485 assert(m);
486
a16e1123
LP
487 if (!m->udev) {
488 if (!(m->udev = udev_new()))
489 return -ENOMEM;
25ac040b 490
a16e1123
LP
491 if (!(m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev"))) {
492 r = -ENOMEM;
493 goto fail;
494 }
f94ea366 495
47ae6e67
LP
496 /* This will fail if we are unprivileged, but that
497 * should not matter much, as user instances won't run
498 * during boot. */
499 udev_monitor_set_receive_buffer_size(m->udev_monitor, 128*1024*1024);
99448c1f 500
e1ce2c27
LP
501 if (udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd") < 0) {
502 r = -ENOMEM;
503 goto fail;
504 }
505
a16e1123
LP
506 if (udev_monitor_enable_receiving(m->udev_monitor) < 0) {
507 r = -EIO;
508 goto fail;
509 }
f94ea366 510
a16e1123
LP
511 m->udev_watch.type = WATCH_UDEV;
512 m->udev_watch.fd = udev_monitor_get_fd(m->udev_monitor);
f94ea366 513
a16e1123
LP
514 zero(ev);
515 ev.events = EPOLLIN;
516 ev.data.ptr = &m->udev_watch;
f94ea366 517
a16e1123
LP
518 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_watch.fd, &ev) < 0)
519 return -errno;
520 }
f94ea366 521
4f2d528d
LP
522 if (!(e = udev_enumerate_new(m->udev))) {
523 r = -ENOMEM;
524 goto fail;
525 }
e1ce2c27
LP
526 if (udev_enumerate_add_match_tag(e, "systemd") < 0) {
527 r = -EIO;
528 goto fail;
529 }
25ac040b 530
4f2d528d
LP
531 if (udev_enumerate_scan_devices(e) < 0) {
532 r = -EIO;
533 goto fail;
534 }
25ac040b 535
4f2d528d
LP
536 first = udev_enumerate_get_list_entry(e);
537 udev_list_entry_foreach(item, first)
538 device_process_path(m, udev_list_entry_get_name(item), false);
25ac040b 539
4f2d528d 540 udev_enumerate_unref(e);
25ac040b
LP
541 return 0;
542
543fail:
544 if (e)
545 udev_enumerate_unref(e);
546
547 device_shutdown(m);
548 return r;
5cb5a6ff
LP
549}
550
f94ea366
LP
551void device_fd_event(Manager *m, int events) {
552 struct udev_device *dev;
553 int r;
2958c886 554 const char *action, *ready;
f94ea366
LP
555
556 assert(m);
99448c1f
KS
557
558 if (events != EPOLLIN) {
559 static RATELIMIT_DEFINE(limit, 10*USEC_PER_SEC, 5);
560
561 if (!ratelimit_test(&limit))
562 log_error("Failed to get udev event: %m");
2e6081f2
KS
563 if (!(events & EPOLLIN))
564 return;
99448c1f 565 }
f94ea366 566
f94ea366 567 if (!(dev = udev_monitor_receive_device(m->udev_monitor))) {
99448c1f
KS
568 /*
569 * libudev might filter-out devices which pass the bloom filter,
35b8ca3a 570 * so getting NULL here is not necessarily an error
99448c1f 571 */
f94ea366
LP
572 return;
573 }
574
575 if (!(action = udev_device_get_action(dev))) {
576 log_error("Failed to get udev action string.");
577 goto fail;
578 }
579
2958c886
LP
580 ready = udev_device_get_property_value(dev, "SYSTEMD_READY");
581
582 if (streq(action, "remove") || (ready && parse_boolean(ready) == 0)) {
f94ea366
LP
583 if ((r = device_process_removed_device(m, dev)) < 0) {
584 log_error("Failed to process udev device event: %s", strerror(-r));
585 goto fail;
586 }
587 } else {
588 if ((r = device_process_new_device(m, dev, true)) < 0) {
589 log_error("Failed to process udev device event: %s", strerror(-r));
590 goto fail;
591 }
592 }
593
594fail:
595 udev_device_unref(dev);
596}
597
a16e1123
LP
598static const char* const device_state_table[_DEVICE_STATE_MAX] = {
599 [DEVICE_DEAD] = "dead",
73608ed9 600 [DEVICE_PLUGGED] = "plugged"
a16e1123
LP
601};
602
603DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
604
87f0e418 605const UnitVTable device_vtable = {
7d17cfbc 606 .object_size = sizeof(Device),
f975e971
LP
607 .sections =
608 "Unit\0"
609 "Device\0"
610 "Install\0",
5cb5a6ff 611
9e2f7c11
LP
612 .no_instances = true,
613
faf919f1
LP
614 .init = device_init,
615
e537352b 616 .load = unit_load_fragment_and_dropin_optional,
034c6ed7 617 .done = device_done,
f50e0a01
LP
618 .coldplug = device_coldplug,
619
5cb5a6ff
LP
620 .dump = device_dump,
621
f50e0a01 622 .active_state = device_active_state,
10a94420 623 .sub_state_to_string = device_sub_state_to_string,
25ac040b 624
c4e2ceae 625 .bus_interface = "org.freedesktop.systemd1.Device",
4139c1b2 626 .bus_message_handler = bus_device_message_handler,
c4e2ceae 627 .bus_invalidating_properties = bus_device_invalidating_properties,
4139c1b2 628
a7f241db 629 .following = device_following,
6210e7fc 630 .following_set = device_following_set,
a7f241db 631
f50e0a01 632 .enumerate = device_enumerate,
c6918296
MS
633 .shutdown = device_shutdown,
634
635 .status_message_formats = {
636 .starting_stopping = {
637 [0] = "Expecting device %s...",
638 },
639 .finished_start_job = {
640 [JOB_DONE] = "Found device %s.",
641 [JOB_TIMEOUT] = "Timed out waiting for device %s.",
642 },
643 },
5cb5a6ff 644};