chiark / gitweb /
systemadm: ignore entry activation on empty string
[elogind.git] / device.c
index f906fd50021dedc822b224bc88a7784167046de5..e67d0a6c2d71e1d2ec83db8e3fcdc854dd2e41e4 100644 (file)
--- a/device.c
+++ b/device.c
 #include "strv.h"
 #include "log.h"
 #include "unit-name.h"
+#include "dbus-device.h"
 
 static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
         [DEVICE_DEAD] = UNIT_INACTIVE,
         [DEVICE_AVAILABLE] = UNIT_ACTIVE
 };
 
-static const char* const state_string_table[_DEVICE_STATE_MAX] = {
-        [DEVICE_DEAD] = "dead",
-        [DEVICE_AVAILABLE] = "available"
-};
-
 static void device_done(Unit *u) {
         Device *d = DEVICE(u);
 
@@ -48,15 +44,6 @@ static void device_done(Unit *u) {
         d->sysfs = NULL;
 }
 
-static void device_init(Unit *u) {
-        Device *d = DEVICE(u);
-
-        assert(d);
-        assert(u->meta.load_state == UNIT_STUB);
-
-        d->state = 0;
-}
-
 static void device_set_state(Device *d, DeviceState state) {
         DeviceState old_state;
         assert(d);
@@ -65,7 +52,10 @@ static void device_set_state(Device *d, DeviceState state) {
         d->state = state;
 
         if (state != old_state)
-                log_debug("%s changed %s → %s", UNIT(d)->meta.id, state_string_table[old_state], state_string_table[state]);
+                log_debug("%s changed %s -> %s",
+                          UNIT(d)->meta.id,
+                          device_state_to_string(old_state),
+                          device_state_to_string(state));
 
         unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state]);
 }
@@ -90,7 +80,7 @@ static void device_dump(Unit *u, FILE *f, const char *prefix) {
         fprintf(f,
                 "%sDevice State: %s\n"
                 "%sSysfs Path: %s\n",
-                prefix, state_string_table[d->state],
+                prefix, device_state_to_string(d->state),
                 prefix, strna(d->sysfs));
 }
 
@@ -103,7 +93,7 @@ static UnitActiveState device_active_state(Unit *u) {
 static const char *device_sub_state_to_string(Unit *u) {
         assert(u);
 
-        return state_string_table[DEVICE(u)->state];
+        return device_state_to_string(DEVICE(u)->state);
 }
 
 static int device_add_escaped_name(Unit *u, const char *dn, bool make_id) {
@@ -114,7 +104,7 @@ static int device_add_escaped_name(Unit *u, const char *dn, bool make_id) {
         assert(dn);
         assert(dn[0] == '/');
 
-        if (!(e = unit_name_build_escape(dn+1, NULL, ".device")))
+        if (!(e = unit_name_from_path(dn, ".device")))
                 return -ENOMEM;
 
         r = unit_add_name(u, e);
@@ -139,7 +129,7 @@ static int device_find_escape_name(Manager *m, const char *dn, Unit **_u) {
         assert(dn[0] == '/');
         assert(_u);
 
-        if (!(e = unit_name_build_escape(dn+1, NULL, ".device")))
+        if (!(e = unit_name_from_path(dn, ".device")))
                 return -ENOMEM;
 
         u = manager_get_unit(m, e);
@@ -154,7 +144,7 @@ static int device_find_escape_name(Manager *m, const char *dn, Unit **_u) {
 }
 
 static int device_process_new_device(Manager *m, struct udev_device *dev, bool update_state) {
-        const char *dn, *names, *wants, *sysfs, *expose, *model;
+        const char *dn, *wants, *sysfs, *expose, *model, *alias;
         Unit *u = NULL;
         int r;
         char *w, *state;
@@ -181,8 +171,16 @@ static int device_process_new_device(Manager *m, struct udev_device *dev, bool u
 
         /* Check whether this entry is even relevant for us. */
         dn = udev_device_get_devnode(dev);
-        names = udev_device_get_property_value(dev, "SYSTEMD_NAMES");
         wants = udev_device_get_property_value(dev, "SYSTEMD_WANTS");
+        alias = udev_device_get_property_value(dev, "SYSTEMD_ALIAS");
+
+        /* We allow exactly one alias to be configured a this time and
+         * it must be a path */
+
+        if (alias && !is_path(alias)) {
+                log_warning("SYSTEMD_ALIAS for %s is not a path, ignoring: %s", sysfs, alias);
+                alias = NULL;
+        }
 
         if ((r = device_find_escape_name(m, sysfs, &u)) < 0)
                 return r;
@@ -202,12 +200,16 @@ static int device_process_new_device(Manager *m, struct udev_device *dev, bool u
                 }
         }
 
+        if (r == 0 && alias)
+                if ((r = device_find_escape_name(m, alias, &u)) < 0)
+                        return r;
+
         /* FIXME: this needs proper merging */
 
         assert((r > 0) == !!u);
 
         /* If this is a different unit, then let's not merge things */
-        if (u && DEVICE(u)->sysfs && !streq(DEVICE(u)->sysfs, sysfs))
+        if (u && DEVICE(u)->sysfs && !path_equal(DEVICE(u)->sysfs, sysfs))
                 u = NULL;
 
         if (!u) {
@@ -229,6 +231,10 @@ static int device_process_new_device(Manager *m, struct udev_device *dev, bool u
                         goto fail;
                 }
 
+        if (alias)
+                if ((r = device_add_escaped_name(u, alias, true)) < 0)
+                        goto fail;
+
         if (dn)
                 if ((r = device_add_escaped_name(u, dn, true)) < 0)
                         goto fail;
@@ -242,30 +248,12 @@ static int device_process_new_device(Manager *m, struct udev_device *dev, bool u
             (model = udev_device_get_property_value(dev, "ID_MODEL"))) {
                 if ((r = unit_set_description(u, model)) < 0)
                         goto fail;
-        } else if (dn)
+        } else if (dn) {
                 if ((r = unit_set_description(u, dn)) < 0)
                         goto fail;
-
-        /* We don't remove names that are gone. But that should be
-         * fine and should probably be fixed only on a configuration
-         * refresh. */
-
-        if (names) {
-                FOREACH_WORD(w, l, names, state) {
-                        char *e;
-
-                        if (!(e = strndup(w, l))) {
-                                r = -ENOMEM;
-                                goto fail;
-                        }
-
-                        r = unit_add_name(u, e);
-                        free(e);
-
-                        if (r < 0 && r != -EEXIST)
-                                goto fail;
-                }
-        }
+        } else
+                if ((r = unit_set_description(u, sysfs)) < 0)
+                        goto fail;
 
         if (wants) {
                 FOREACH_WORD(w, l, wants, state) {
@@ -276,7 +264,7 @@ static int device_process_new_device(Manager *m, struct udev_device *dev, bool u
                                 goto fail;
                         }
 
-                        r = unit_add_dependency_by_name(u, UNIT_WANTS, NULL, e);
+                        r = unit_add_dependency_by_name(u, UNIT_WANTS, NULL, e, true);
                         free(e);
 
                         if (r < 0)
@@ -329,7 +317,7 @@ static int device_process_removed_device(Manager *m, struct udev_device *dev) {
                 return -ENOMEM;
 
         assert(sysfs[0] == '/');
-        if (!(e = unit_name_build_escape(sysfs+1, NULL, ".device")))
+        if (!(e = unit_name_from_path(sysfs, ".device")))
                 return -ENOMEM;
 
         u = manager_get_unit(m, e);
@@ -349,11 +337,15 @@ static int device_process_removed_device(Manager *m, struct udev_device *dev) {
 static void device_shutdown(Manager *m) {
         assert(m);
 
-        if (m->udev_monitor)
+        if (m->udev_monitor) {
                 udev_monitor_unref(m->udev_monitor);
+                m->udev_monitor = NULL;
+        }
 
-        if (m->udev)
+        if (m->udev) {
                 udev_unref(m->udev);
+                m->udev = NULL;
+        }
 }
 
 static int device_enumerate(Manager *m) {
@@ -364,28 +356,30 @@ static int device_enumerate(Manager *m) {
 
         assert(m);
 
-        if (!(m->udev = udev_new()))
-                return -ENOMEM;
+        if (!m->udev) {
+                if (!(m->udev = udev_new()))
+                        return -ENOMEM;
 
-        if (!(m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev"))) {
-                r = -ENOMEM;
-                goto fail;
-        }
+                if (!(m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev"))) {
+                        r = -ENOMEM;
+                        goto fail;
+                }
 
-        if (udev_monitor_enable_receiving(m->udev_monitor) < 0) {
-                r = -EIO;
-                goto fail;
-        }
+                if (udev_monitor_enable_receiving(m->udev_monitor) < 0) {
+                        r = -EIO;
+                        goto fail;
+                }
 
-        m->udev_watch.type = WATCH_UDEV;
-        m->udev_watch.fd = udev_monitor_get_fd(m->udev_monitor);
+                m->udev_watch.type = WATCH_UDEV;
+                m->udev_watch.fd = udev_monitor_get_fd(m->udev_monitor);
 
-        zero(ev);
-        ev.events = EPOLLIN;
-        ev.data.ptr = &m->udev_watch;
+                zero(ev);
+                ev.events = EPOLLIN;
+                ev.data.ptr = &m->udev_watch;
 
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_watch.fd, &ev) < 0)
-                return -errno;
+                if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_watch.fd, &ev) < 0)
+                        return -errno;
+        }
 
         if (!(e = udev_enumerate_new(m->udev))) {
                 r = -ENOMEM;
@@ -446,13 +440,21 @@ fail:
         udev_device_unref(dev);
 }
 
+static const char* const device_state_table[_DEVICE_STATE_MAX] = {
+        [DEVICE_DEAD] = "dead",
+        [DEVICE_AVAILABLE] = "available"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
+
 const UnitVTable device_vtable = {
         .suffix = ".device",
 
         .no_requires = true,
         .no_instances = true,
+        .no_snapshots = true,
+        .no_isolate = true,
 
-        .init = device_init,
         .load = unit_load_fragment_and_dropin_optional,
         .done = device_done,
         .coldplug = device_coldplug,
@@ -462,6 +464,8 @@ const UnitVTable device_vtable = {
         .active_state = device_active_state,
         .sub_state_to_string = device_sub_state_to_string,
 
+        .bus_message_handler = bus_device_message_handler,
+
         .enumerate = device_enumerate,
         .shutdown = device_shutdown
 };