1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
12 static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
13 [DEVICE_DEAD] = UNIT_INACTIVE,
14 [DEVICE_AVAILABLE] = UNIT_ACTIVE
17 static const char* const state_string_table[_DEVICE_STATE_MAX] = {
18 [DEVICE_DEAD] = "dead",
19 [DEVICE_AVAILABLE] = "available"
22 static void device_done(Unit *u) {
23 Device *d = DEVICE(u);
29 static void device_set_state(Device *d, DeviceState state) {
30 DeviceState old_state;
36 log_debug("%s changed %s → %s", unit_id(UNIT(d)), state_string_table[old_state], state_string_table[state]);
38 unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state]);
41 static int device_coldplug(Unit *u) {
42 Device *d = DEVICE(u);
45 assert(d->state == DEVICE_DEAD);
48 device_set_state(d, DEVICE_AVAILABLE);
53 static void device_dump(Unit *u, FILE *f, const char *prefix) {
54 Device *d = DEVICE(u);
59 "%sDevice State: %s\n"
61 prefix, state_string_table[d->state],
62 prefix, strna(d->sysfs));
65 static UnitActiveState device_active_state(Unit *u) {
68 return state_translation_table[DEVICE(u)->state];
71 static int device_add_escaped_name(Unit *u, const char *prefix, const char *dn, bool make_id) {
79 if (!(e = unit_name_escape_path(prefix, dn+1, ".device")))
82 r = unit_add_name(u, e);
84 if (r >= 0 && make_id)
89 if (r < 0 && r != -EEXIST)
95 static int device_process_new_device(Manager *m, struct udev_device *dev, bool update_state) {
96 const char *dn, *names, *wants, *sysfs;
102 struct udev_list_entry *item = NULL, *first = NULL;
106 /* Check whether this entry is even relevant for us. */
107 dn = udev_device_get_devnode(dev);
108 names = udev_device_get_property_value(dev, "SYSTEMD_NAMES");
109 wants = udev_device_get_property_value(dev, "SYSTEMD_WANTS");
111 if (!dn && !names && !wants)
114 /* Ok, seems kinda interesting. Now, let's see if this one
117 if (!(sysfs = udev_device_get_syspath(dev)))
120 assert(sysfs[0] == '/');
121 if (!(e = unit_name_escape_path("sysfs-", sysfs+1, ".device")))
124 if (!(u = manager_get_unit(m, e))) {
129 if (!(u = unit_new(m))) {
134 r = unit_add_name(u, e);
140 if (!(DEVICE(u)->sysfs = strdup(sysfs))) {
145 if ((model = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE")) ||
146 (model = udev_device_get_property_value(dev, "ID_MODEL")))
147 if ((r = unit_set_description(u, model)) < 0)
150 unit_add_to_load_queue(u);
157 if ((r = device_add_escaped_name(u, "node-", dn, true)) < 0)
160 first = udev_device_get_devlinks_list_entry(dev);
161 udev_list_entry_foreach(item, first)
162 if ((r = device_add_escaped_name(u, "node-", udev_list_entry_get_name(item), false)) < 0)
166 FOREACH_WORD(w, l, names, state) {
167 if (!(e = strndup(w, l)))
170 r = unit_add_name(u, e);
173 if (r < 0 && r != -EEXIST)
179 FOREACH_WORD(w, l, wants, state) {
180 if (!(e = strndup(w, l)))
183 r = unit_add_dependency_by_name(u, UNIT_WANTS, e);
192 manager_dispatch_load_queue(u->meta.manager);
193 device_set_state(DEVICE(u), DEVICE_AVAILABLE);
204 static int device_process_path(Manager *m, const char *path, bool update_state) {
206 struct udev_device *dev;
211 if (!(dev = udev_device_new_from_syspath(m->udev, path))) {
212 log_warning("Failed to get udev device object from udev for path %s.", path);
216 r = device_process_new_device(m, dev, update_state);
217 udev_device_unref(dev);
221 static int device_process_removed_device(Manager *m, struct udev_device *dev) {
230 if (!(sysfs = udev_device_get_syspath(dev)))
233 assert(sysfs[0] == '/');
234 if (!(e = unit_name_escape_path("sysfs-", sysfs+1, ".device")))
237 u = manager_get_unit(m, e);
247 device_set_state(d, DEVICE_DEAD);
251 static void device_shutdown(Manager *m) {
255 udev_monitor_unref(m->udev_monitor);
261 static int device_enumerate(Manager *m) {
262 struct epoll_event ev;
264 struct udev_enumerate *e = NULL;
265 struct udev_list_entry *item = NULL, *first = NULL;
269 if (!(m->udev = udev_new()))
272 if (!(m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev"))) {
277 if (udev_monitor_enable_receiving(m->udev_monitor) < 0) {
282 m->udev_watch.type = WATCH_UDEV;
283 m->udev_watch.fd = udev_monitor_get_fd(m->udev_monitor);
287 ev.data.ptr = &m->udev_watch;
289 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_watch.fd, &ev) < 0)
292 if (!(e = udev_enumerate_new(m->udev))) {
297 if (udev_enumerate_scan_devices(e) < 0) {
302 first = udev_enumerate_get_list_entry(e);
303 udev_list_entry_foreach(item, first)
304 device_process_path(m, udev_list_entry_get_name(item), false);
306 udev_enumerate_unref(e);
311 udev_enumerate_unref(e);
317 void device_fd_event(Manager *m, int events) {
318 struct udev_device *dev;
323 assert(events == EPOLLIN);
325 log_debug("got udev event");
327 if (!(dev = udev_monitor_receive_device(m->udev_monitor))) {
328 log_error("Failed to receive device.");
332 if (!(action = udev_device_get_action(dev))) {
333 log_error("Failed to get udev action string.");
337 if (streq(action, "remove")) {
338 if ((r = device_process_removed_device(m, dev)) < 0) {
339 log_error("Failed to process udev device event: %s", strerror(-r));
343 if ((r = device_process_new_device(m, dev, true)) < 0) {
344 log_error("Failed to process udev device event: %s", strerror(-r));
350 udev_device_unref(dev);
353 const UnitVTable device_vtable = {
356 .init = unit_load_fragment_and_dropin,
358 .coldplug = device_coldplug,
362 .active_state = device_active_state,
364 .enumerate = device_enumerate,
365 .shutdown = device_shutdown