chiark / gitweb /
journald: check session owner UID rather then audit ID when splitting up journal...
[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 static UnitActiveState device_active_state(Unit *u) {
128         assert(u);
129
130         return state_translation_table[DEVICE(u)->state];
131 }
132
133 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;
285
286                                 e = strndup(w, l);
287                                 if (!e) {
288                                         r = -ENOMEM;
289                                         goto fail;
290                                 }
291
292                                 r = unit_add_dependency_by_name(u, UNIT_WANTS, e, NULL, true);
293                                 free(e);
294                                 if (r < 0)
295                                         goto fail;
296                         }
297                 }
298         }
299
300         unit_add_to_dbus_queue(u);
301         return 0;
302
303 fail:
304         log_warning("Failed to load device unit: %s", strerror(-r));
305
306         if (delete && u)
307                 unit_free(u);
308
309         return r;
310 }
311
312 static 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;
332                 struct stat st;
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
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
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
369 static int device_process_path(Manager *m, const char *path, bool update_state) {
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
381         r = device_process_new_device(m, dev, update_state);
382         udev_device_unref(dev);
383         return r;
384 }
385
386 static int device_process_removed_device(Manager *m, struct udev_device *dev) {
387         const char *sysfs;
388         Device *d;
389
390         assert(m);
391         assert(dev);
392
393         if (!(sysfs = udev_device_get_syspath(dev)))
394                 return -ENOMEM;
395
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         }
401
402         return 0;
403 }
404
405 static Unit *device_following(Unit *u) {
406         Device *d = DEVICE(u);
407         Device *other, *first = NULL;
408
409         assert(d);
410
411         if (startswith(u->id, "sys-"))
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)
416                 if (startswith(UNIT(other)->id, "sys-"))
417                         return UNIT(other);
418
419         for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev) {
420                 if (startswith(UNIT(other)->id, "sys-"))
421                         return UNIT(other);
422
423                 first = other;
424         }
425
426         return UNIT(first);
427 }
428
429 static 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
457 fail:
458         set_free(s);
459         return r;
460 }
461
462 static void device_shutdown(Manager *m) {
463         assert(m);
464
465         if (m->udev_monitor) {
466                 udev_monitor_unref(m->udev_monitor);
467                 m->udev_monitor = NULL;
468         }
469
470         if (m->udev) {
471                 udev_unref(m->udev);
472                 m->udev = NULL;
473         }
474
475         hashmap_free(m->devices_by_sysfs);
476         m->devices_by_sysfs = NULL;
477 }
478
479 static int device_enumerate(Manager *m) {
480         struct epoll_event ev;
481         int r;
482         struct udev_enumerate *e = NULL;
483         struct udev_list_entry *item = NULL, *first = NULL;
484
485         assert(m);
486
487         if (!m->udev) {
488                 if (!(m->udev = udev_new()))
489                         return -ENOMEM;
490
491                 if (!(m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev"))) {
492                         r = -ENOMEM;
493                         goto fail;
494                 }
495
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);
500
501                 if (udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd") < 0) {
502                         r = -ENOMEM;
503                         goto fail;
504                 }
505
506                 if (udev_monitor_enable_receiving(m->udev_monitor) < 0) {
507                         r = -EIO;
508                         goto fail;
509                 }
510
511                 m->udev_watch.type = WATCH_UDEV;
512                 m->udev_watch.fd = udev_monitor_get_fd(m->udev_monitor);
513
514                 zero(ev);
515                 ev.events = EPOLLIN;
516                 ev.data.ptr = &m->udev_watch;
517
518                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_watch.fd, &ev) < 0)
519                         return -errno;
520         }
521
522         if (!(e = udev_enumerate_new(m->udev))) {
523                 r = -ENOMEM;
524                 goto fail;
525         }
526         if (udev_enumerate_add_match_tag(e, "systemd") < 0) {
527                 r = -EIO;
528                 goto fail;
529         }
530
531         if (udev_enumerate_scan_devices(e) < 0) {
532                 r = -EIO;
533                 goto fail;
534         }
535
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);
539
540         udev_enumerate_unref(e);
541         return 0;
542
543 fail:
544         if (e)
545                 udev_enumerate_unref(e);
546
547         device_shutdown(m);
548         return r;
549 }
550
551 void device_fd_event(Manager *m, int events) {
552         struct udev_device *dev;
553         int r;
554         const char *action, *ready;
555
556         assert(m);
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");
563                 if (!(events & EPOLLIN))
564                         return;
565         }
566
567         if (!(dev = udev_monitor_receive_device(m->udev_monitor))) {
568                 /*
569                  * libudev might filter-out devices which pass the bloom filter,
570                  * so getting NULL here is not necessarily an error
571                  */
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
580         ready = udev_device_get_property_value(dev, "SYSTEMD_READY");
581
582         if (streq(action, "remove") || (ready && parse_boolean(ready) == 0)) {
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
594 fail:
595         udev_device_unref(dev);
596 }
597
598 static const char* const device_state_table[_DEVICE_STATE_MAX] = {
599         [DEVICE_DEAD] = "dead",
600         [DEVICE_PLUGGED] = "plugged"
601 };
602
603 DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
604
605 const UnitVTable device_vtable = {
606         .object_size = sizeof(Device),
607         .sections =
608                 "Unit\0"
609                 "Device\0"
610                 "Install\0",
611
612         .no_instances = true,
613
614         .init = device_init,
615
616         .load = unit_load_fragment_and_dropin_optional,
617         .done = device_done,
618         .coldplug = device_coldplug,
619
620         .dump = device_dump,
621
622         .active_state = device_active_state,
623         .sub_state_to_string = device_sub_state_to_string,
624
625         .bus_interface = "org.freedesktop.systemd1.Device",
626         .bus_message_handler = bus_device_message_handler,
627         .bus_invalidating_properties =  bus_device_invalidating_properties,
628
629         .following = device_following,
630         .following_set = device_following_set,
631
632         .enumerate = device_enumerate,
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         },
644 };