chiark / gitweb /
journalctl: use _COMM= match for scripts
[elogind.git] / src / core / device.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
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
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
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
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <sys/epoll.h>
24 #include <libudev.h>
25
26 #include "unit.h"
27 #include "device.h"
28 #include "strv.h"
29 #include "log.h"
30 #include "unit-name.h"
31 #include "dbus-device.h"
32 #include "def.h"
33 #include "path-util.h"
34
35 static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
36         [DEVICE_DEAD] = UNIT_INACTIVE,
37         [DEVICE_PLUGGED] = UNIT_ACTIVE
38 };
39
40 static void device_unset_sysfs(Device *d) {
41         Device *first;
42
43         assert(d);
44
45         if (!d->sysfs)
46                 return;
47
48         /* Remove this unit from the chain of devices which share the
49          * same sysfs path. */
50         first = hashmap_get(UNIT(d)->manager->devices_by_sysfs, d->sysfs);
51         LIST_REMOVE(Device, same_sysfs, first, d);
52
53         if (first)
54                 hashmap_remove_and_replace(UNIT(d)->manager->devices_by_sysfs, d->sysfs, first->sysfs, first);
55         else
56                 hashmap_remove(UNIT(d)->manager->devices_by_sysfs, d->sysfs);
57
58         free(d->sysfs);
59         d->sysfs = NULL;
60 }
61
62 static void device_init(Unit *u) {
63         Device *d = DEVICE(u);
64
65         assert(d);
66         assert(UNIT(d)->load_state == UNIT_STUB);
67
68         /* In contrast to all other unit types we timeout jobs waiting
69          * for devices by default. This is because they otherwise wait
70          * indefinitely for plugged in devices, something which cannot
71          * happen for the other units since their operations time out
72          * anyway. */
73         UNIT(d)->job_timeout = DEFAULT_TIMEOUT_USEC;
74
75         UNIT(d)->ignore_on_isolate = true;
76         UNIT(d)->ignore_on_snapshot = true;
77 }
78
79 static void device_done(Unit *u) {
80         Device *d = DEVICE(u);
81
82         assert(d);
83
84         device_unset_sysfs(d);
85 }
86
87 static void device_set_state(Device *d, DeviceState state) {
88         DeviceState old_state;
89         assert(d);
90
91         old_state = d->state;
92         d->state = state;
93
94         if (state != old_state)
95                 log_debug_unit(UNIT(d)->id,
96                                "%s changed %s -> %s", UNIT(d)->id,
97                                device_state_to_string(old_state),
98                                device_state_to_string(state));
99
100         unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], true);
101 }
102
103 static 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)
110                 device_set_state(d, DEVICE_PLUGGED);
111
112         return 0;
113 }
114
115 static void device_dump(Unit *u, FILE *f, const char *prefix) {
116         Device *d = DEVICE(u);
117
118         assert(d);
119
120         fprintf(f,
121                 "%sDevice State: %s\n"
122                 "%sSysfs Path: %s\n",
123                 prefix, device_state_to_string(d->state),
124                 prefix, strna(d->sysfs));
125 }
126
127 _pure_ static UnitActiveState device_active_state(Unit *u) {
128         assert(u);
129
130         return state_translation_table[DEVICE(u)->state];
131 }
132
133 _pure_ static const char *device_sub_state_to_string(Unit *u) {
134         assert(u);
135
136         return device_state_to_string(DEVICE(u)->state);
137 }
138
139 static int device_add_escaped_name(Unit *u, const char *dn) {
140         char *e;
141         int r;
142
143         assert(u);
144         assert(dn);
145         assert(dn[0] == '/');
146
147         e = unit_name_from_path(dn, ".device");
148         if (!e)
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
160 static 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
169         e = unit_name_from_path(dn, ".device");
170         if (!e)
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
184 static int device_update_unit(Manager *m, struct udev_device *dev, const char *path, bool main) {
185         const char *sysfs, *model;
186         Unit *u = NULL;
187         int r;
188         bool delete;
189
190         assert(m);
191
192         if (!(sysfs = udev_device_get_syspath(dev)))
193                 return -ENOMEM;
194
195         if ((r = device_find_escape_name(m, path, &u)) < 0)
196                 return r;
197
198         if (u && DEVICE(u)->sysfs && !path_equal(DEVICE(u)->sysfs, sysfs))
199                 return -EEXIST;
200
201         if (!u) {
202                 delete = true;
203
204                 u = unit_new(m, sizeof(Device));
205                 if (!u)
206                         return -ENOMEM;
207
208                 r = device_add_escaped_name(u, path);
209                 if (r < 0)
210                         goto fail;
211
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
223                 if (!(DEVICE(u)->sysfs = strdup(sysfs))) {
224                         r = -ENOMEM;
225                         goto fail;
226                 }
227
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                         }
233
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)
238                         goto fail;
239         }
240
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;
245         } else
246                 if ((r = unit_set_description(u, path)) < 0)
247                         goto fail;
248
249         if (main) {
250                 /* The additional systemd udev properties we only
251                  * interpret for the main object */
252                 const char *wants, *alias;
253
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;
265                                         goto fail;
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 {
272                                         device_update_unit(m, dev, e, false);
273                                         free(e);
274                                 }
275                         }
276                 }
277
278                 wants = udev_device_get_property_value(dev, "SYSTEMD_WANTS");
279                 if (wants) {
280                         char *state, *w;
281                         size_t l;
282
283                         FOREACH_WORD_QUOTED(w, l, wants, state) {
284                                 char *e, *n;
285
286                                 e = strndup(w, l);
287                                 if (!e) {
288                                         r = -ENOMEM;
289                                         goto fail;
290                                 }
291                                 n = unit_name_mangle(e);
292                                 if (!n) {
293                                         r = -ENOMEM;
294                                         goto fail;
295                                 }
296                                 free(e);
297
298                                 r = unit_add_dependency_by_name(u, UNIT_WANTS, n, NULL, true);
299                                 free(n);
300                                 if (r < 0)
301                                         goto fail;
302                         }
303                 }
304         }
305
306         unit_add_to_dbus_queue(u);
307         return 0;
308
309 fail:
310         log_warning("Failed to load device unit: %s", strerror(-r));
311
312         if (delete && u)
313                 unit_free(u);
314
315         return r;
316 }
317
318 static int device_process_new_device(Manager *m, struct udev_device *dev, bool update_state) {
319         const char *sysfs, *dn;
320         struct udev_list_entry *item = NULL, *first = NULL;
321         int r;
322
323         assert(m);
324
325         if (!(sysfs = udev_device_get_syspath(dev)))
326                 return -ENOMEM;
327
328         /* Add the main unit named after the sysfs path */
329         r = device_update_unit(m, dev, sysfs, true);
330         if (r < 0)
331                 return r;
332
333         /* Add an additional unit for the device node */
334         if ((dn = udev_device_get_devnode(dev)))
335                 device_update_unit(m, dev, dn, false);
336
337         /* Add additional units for all symlinks */
338         first = udev_device_get_devlinks_list_entry(dev);
339         udev_list_entry_foreach(item, first) {
340                 const char *p;
341                 struct stat st;
342
343                 /* Don't bother with the /dev/block links */
344                 p = udev_list_entry_get_name(item);
345
346                 if (path_startswith(p, "/dev/block/") ||
347                     path_startswith(p, "/dev/char/"))
348                         continue;
349
350                 /* Verify that the symlink in the FS actually belongs
351                  * to this device. This is useful to deal with
352                  * conflicting devices, e.g. when two disks want the
353                  * same /dev/disk/by-label/xxx link because they have
354                  * the same label. We want to make sure that the same
355                  * device that won the symlink wins in systemd, so we
356                  * check the device node major/minor*/
357                 if (stat(p, &st) >= 0)
358                         if ((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) ||
359                             st.st_rdev != udev_device_get_devnum(dev))
360                                 continue;
361
362                 device_update_unit(m, dev, p, false);
363         }
364
365         if (update_state) {
366                 Device *d, *l;
367
368                 manager_dispatch_load_queue(m);
369
370                 l = hashmap_get(m->devices_by_sysfs, sysfs);
371                 LIST_FOREACH(same_sysfs, d, l)
372                         device_set_state(d, DEVICE_PLUGGED);
373         }
374
375         return 0;
376 }
377
378 static int device_process_path(Manager *m, const char *path, bool update_state) {
379         int r;
380         struct udev_device *dev;
381
382         assert(m);
383         assert(path);
384
385         if (!(dev = udev_device_new_from_syspath(m->udev, path))) {
386                 log_warning("Failed to get udev device object from udev for path %s.", path);
387                 return -ENOMEM;
388         }
389
390         r = device_process_new_device(m, dev, update_state);
391         udev_device_unref(dev);
392         return r;
393 }
394
395 static int device_process_removed_device(Manager *m, struct udev_device *dev) {
396         const char *sysfs;
397         Device *d;
398
399         assert(m);
400         assert(dev);
401
402         if (!(sysfs = udev_device_get_syspath(dev)))
403                 return -ENOMEM;
404
405         /* Remove all units of this sysfs path */
406         while ((d = hashmap_get(m->devices_by_sysfs, sysfs))) {
407                 device_unset_sysfs(d);
408                 device_set_state(d, DEVICE_DEAD);
409         }
410
411         return 0;
412 }
413
414 static Unit *device_following(Unit *u) {
415         Device *d = DEVICE(u);
416         Device *other, *first = NULL;
417
418         assert(d);
419
420         if (startswith(u->id, "sys-"))
421                 return NULL;
422
423         /* Make everybody follow the unit that's named after the sysfs path */
424         for (other = d->same_sysfs_next; other; other = other->same_sysfs_next)
425                 if (startswith(UNIT(other)->id, "sys-"))
426                         return UNIT(other);
427
428         for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev) {
429                 if (startswith(UNIT(other)->id, "sys-"))
430                         return UNIT(other);
431
432                 first = other;
433         }
434
435         return UNIT(first);
436 }
437
438 static int device_following_set(Unit *u, Set **_s) {
439         Device *d = DEVICE(u);
440         Device *other;
441         Set *s;
442         int r;
443
444         assert(d);
445         assert(_s);
446
447         if (!d->same_sysfs_prev && !d->same_sysfs_next) {
448                 *_s = NULL;
449                 return 0;
450         }
451
452         if (!(s = set_new(NULL, NULL)))
453                 return -ENOMEM;
454
455         for (other = d->same_sysfs_next; other; other = other->same_sysfs_next)
456                 if ((r = set_put(s, other)) < 0)
457                         goto fail;
458
459         for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev)
460                 if ((r = set_put(s, other)) < 0)
461                         goto fail;
462
463         *_s = s;
464         return 1;
465
466 fail:
467         set_free(s);
468         return r;
469 }
470
471 static void device_shutdown(Manager *m) {
472         assert(m);
473
474         if (m->udev_monitor) {
475                 udev_monitor_unref(m->udev_monitor);
476                 m->udev_monitor = NULL;
477         }
478
479         if (m->udev) {
480                 udev_unref(m->udev);
481                 m->udev = NULL;
482         }
483
484         hashmap_free(m->devices_by_sysfs);
485         m->devices_by_sysfs = NULL;
486 }
487
488 static int device_enumerate(Manager *m) {
489         int r;
490         struct udev_enumerate *e = NULL;
491         struct udev_list_entry *item = NULL, *first = NULL;
492
493         assert(m);
494
495         if (!m->udev) {
496                 struct epoll_event ev;
497
498                 if (!(m->udev = udev_new()))
499                         return -ENOMEM;
500
501                 if (!(m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev"))) {
502                         r = -ENOMEM;
503                         goto fail;
504                 }
505
506                 /* This will fail if we are unprivileged, but that
507                  * should not matter much, as user instances won't run
508                  * during boot. */
509                 udev_monitor_set_receive_buffer_size(m->udev_monitor, 128*1024*1024);
510
511                 if (udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd") < 0) {
512                         r = -ENOMEM;
513                         goto fail;
514                 }
515
516                 if (udev_monitor_enable_receiving(m->udev_monitor) < 0) {
517                         r = -EIO;
518                         goto fail;
519                 }
520
521                 m->udev_watch.type = WATCH_UDEV;
522                 m->udev_watch.fd = udev_monitor_get_fd(m->udev_monitor);
523
524                 zero(ev);
525                 ev.events = EPOLLIN;
526                 ev.data.ptr = &m->udev_watch;
527
528                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_watch.fd, &ev) < 0)
529                         return -errno;
530         }
531
532         if (!(e = udev_enumerate_new(m->udev))) {
533                 r = -ENOMEM;
534                 goto fail;
535         }
536         if (udev_enumerate_add_match_tag(e, "systemd") < 0) {
537                 r = -EIO;
538                 goto fail;
539         }
540
541         if (udev_enumerate_scan_devices(e) < 0) {
542                 r = -EIO;
543                 goto fail;
544         }
545
546         first = udev_enumerate_get_list_entry(e);
547         udev_list_entry_foreach(item, first)
548                 device_process_path(m, udev_list_entry_get_name(item), false);
549
550         udev_enumerate_unref(e);
551         return 0;
552
553 fail:
554         if (e)
555                 udev_enumerate_unref(e);
556
557         device_shutdown(m);
558         return r;
559 }
560
561 void device_fd_event(Manager *m, int events) {
562         struct udev_device *dev;
563         int r;
564         const char *action, *ready;
565
566         assert(m);
567
568         if (events != EPOLLIN) {
569                 static RATELIMIT_DEFINE(limit, 10*USEC_PER_SEC, 5);
570
571                 if (!ratelimit_test(&limit))
572                         log_error("Failed to get udev event: %m");
573                 if (!(events & EPOLLIN))
574                         return;
575         }
576
577         if (!(dev = udev_monitor_receive_device(m->udev_monitor))) {
578                 /*
579                  * libudev might filter-out devices which pass the bloom filter,
580                  * so getting NULL here is not necessarily an error
581                  */
582                 return;
583         }
584
585         if (!(action = udev_device_get_action(dev))) {
586                 log_error("Failed to get udev action string.");
587                 goto fail;
588         }
589
590         ready = udev_device_get_property_value(dev, "SYSTEMD_READY");
591
592         if (streq(action, "remove") || (ready && parse_boolean(ready) == 0)) {
593                 if ((r = device_process_removed_device(m, dev)) < 0) {
594                         log_error("Failed to process udev device event: %s", strerror(-r));
595                         goto fail;
596                 }
597         } else {
598                 if ((r = device_process_new_device(m, dev, true)) < 0) {
599                         log_error("Failed to process udev device event: %s", strerror(-r));
600                         goto fail;
601                 }
602         }
603
604 fail:
605         udev_device_unref(dev);
606 }
607
608 static const char* const device_state_table[_DEVICE_STATE_MAX] = {
609         [DEVICE_DEAD] = "dead",
610         [DEVICE_PLUGGED] = "plugged"
611 };
612
613 DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
614
615 const UnitVTable device_vtable = {
616         .object_size = sizeof(Device),
617         .sections =
618                 "Unit\0"
619                 "Device\0"
620                 "Install\0",
621
622         .no_instances = true,
623
624         .init = device_init,
625
626         .load = unit_load_fragment_and_dropin_optional,
627         .done = device_done,
628         .coldplug = device_coldplug,
629
630         .dump = device_dump,
631
632         .active_state = device_active_state,
633         .sub_state_to_string = device_sub_state_to_string,
634
635         .bus_interface = "org.freedesktop.systemd1.Device",
636         .bus_message_handler = bus_device_message_handler,
637         .bus_invalidating_properties =  bus_device_invalidating_properties,
638
639         .following = device_following,
640         .following_set = device_following_set,
641
642         .enumerate = device_enumerate,
643         .shutdown = device_shutdown,
644
645         .status_message_formats = {
646                 .starting_stopping = {
647                         [0] = "Expecting device %s...",
648                 },
649                 .finished_start_job = {
650                         [JOB_DONE]       = "Found device %s.",
651                         [JOB_TIMEOUT]    = "Timed out waiting for device %s.",
652                 },
653         },
654 };