chiark / gitweb /
udev: support multiple entries for ENV{SYSTEMD_ALIAS} and ENV{SYSTEM_WANTS}
authorKay Sievers <kay@vrfy.org>
Mon, 8 Oct 2012 22:16:50 +0000 (00:16 +0200)
committerKay Sievers <kay@vrfy.org>
Mon, 8 Oct 2012 22:16:50 +0000 (00:16 +0200)
rules/99-systemd.rules.in
src/core/device.c
src/udev/udev-rules.c

index a5e43cd..d17bdd9 100644 (file)
@@ -36,16 +36,16 @@ ACTION=="add", SUBSYSTEM=="block", KERNEL=="nbd*", ENV{SYSTEMD_READY}="0"
 #
 # http://cgit.freedesktop.org/systemd/systemd/tree/src/libudev/libudev-enumerate.c#n922
 
-SUBSYSTEM=="net", KERNEL!="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}="/sys/subsystem/net/devices/$name"
-SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_ALIAS}="/sys/subsystem/bluetooth/devices/%k"
+SUBSYSTEM=="net", KERNEL!="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/net/devices/$name"
+SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/bluetooth/devices/%k"
 
-SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_WANTS}="bluetooth.target"
-ENV{ID_SMARTCARD_READER}=="*?", TAG+="systemd", ENV{SYSTEMD_WANTS}="smartcard.target"
-SUBSYSTEM=="sound", KERNEL=="card*", TAG+="systemd", ENV{SYSTEMD_WANTS}="sound.target"
+SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_WANTS}+="bluetooth.target"
+ENV{ID_SMARTCARD_READER}=="*?", TAG+="systemd", ENV{SYSTEMD_WANTS}+="smartcard.target"
+SUBSYSTEM=="sound", KERNEL=="card*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sound.target"
 
-SUBSYSTEM=="printer", TAG+="systemd", ENV{SYSTEMD_WANTS}="printer.target"
-SUBSYSTEM=="usb", KERNEL=="lp*", TAG+="systemd", ENV{SYSTEMD_WANTS}="printer.target"
-SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", TAG+="systemd", ENV{SYSTEMD_WANTS}="printer.target"
+SUBSYSTEM=="printer", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target"
+SUBSYSTEM=="usb", KERNEL=="lp*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target"
+SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target"
 
 # Apply sysctl variables to network devices (and only to those) as they appear.
 
@@ -54,7 +54,7 @@ SUBSYSTEM=="net", KERNEL!="lo", RUN+="@rootlibexecdir@/systemd-sysctl --prefix=/
 # Asynchronously mount file systems implemented by these modules as
 # soon as they are loaded.
 
-SUBSYSTEM=="module", KERNEL=="fuse", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}="sys-fs-fuse-connections.mount"
-SUBSYSTEM=="module", KERNEL=="configfs", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}="sys-kernel-config.mount"
+SUBSYSTEM=="module", KERNEL=="fuse", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sys-fs-fuse-connections.mount"
+SUBSYSTEM=="module", KERNEL=="configfs", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sys-kernel-config.mount"
 
 LABEL="systemd_end"
index 5307341..8121dc9 100644 (file)
@@ -251,30 +251,49 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
                  * interpret for the main object */
                 const char *wants, *alias;
 
-                if ((alias = udev_device_get_property_value(dev, "SYSTEMD_ALIAS"))) {
-                        if (!is_path(alias))
-                                log_warning("SYSTEMD_ALIAS for %s is not a path, ignoring: %s", sysfs, alias);
-                        else {
-                                if ((r = device_add_escaped_name(u, alias)) < 0)
+                alias = udev_device_get_property_value(dev, "SYSTEMD_ALIAS");
+                if (alias) {
+                        char *state, *w;
+                        size_t l;
+
+                        FOREACH_WORD_QUOTED(w, l, alias, state) {
+                                char *e;
+
+                                e = strndup(w, l);
+                                if (!e) {
+                                        r = -ENOMEM;
                                         goto fail;
+                                }
+
+                                if (!is_path(e)) {
+                                        log_warning("SYSTEMD_ALIAS for %s is not a path, ignoring: %s", sysfs, e);
+                                        free(e);
+                                } else {
+
+                                        r = device_add_escaped_name(u, e);
+                                        free(e);
+                                        if (r < 0)
+                                                goto fail;
+                                }
                         }
                 }
 
-                if ((wants = udev_device_get_property_value(dev, "SYSTEMD_WANTS"))) {
+                wants = udev_device_get_property_value(dev, "SYSTEMD_WANTS");
+                if (wants) {
                         char *state, *w;
                         size_t l;
 
                         FOREACH_WORD_QUOTED(w, l, wants, state) {
                                 char *e;
 
-                                if (!(e = strndup(w, l))) {
+                                e = strndup(w, l);
+                                if (!e) {
                                         r = -ENOMEM;
                                         goto fail;
                                 }
 
                                 r = unit_add_dependency_by_name(u, UNIT_WANTS, e, NULL, true);
                                 free(e);
-
                                 if (r < 0)
                                         goto fail;
                         }
index b3b42fe..ee35f46 100644 (file)
@@ -2471,19 +2471,32 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                 case TK_A_ENV: {
                         const char *name = &rules->buf[cur->key.attr_off];
                         char *value = &rules->buf[cur->key.value_off];
+                        char value_new[UTIL_NAME_SIZE];
+                        const char *value_old = NULL;
+                        struct udev_list_entry *entry;
 
-                        if (value[0] != '\0') {
-                                char temp_value[UTIL_NAME_SIZE];
-                                struct udev_list_entry *entry;
-
-                                udev_event_apply_format(event, value, temp_value, sizeof(temp_value));
-                                entry = udev_device_add_property(event->dev, name, temp_value);
-                                /* store in db, skip private keys */
-                                if (name[0] != '.')
-                                        udev_list_entry_set_num(entry, true);
-                        } else {
+                        if (value[0] == '\0') {
+                                if (cur->key.op == OP_ADD)
+                                        break;
                                 udev_device_add_property(event->dev, name, NULL);
+                                break;
                         }
+
+                        if (cur->key.op == OP_ADD)
+                                value_old = udev_device_get_property_value(event->dev, name);
+                        if (value_old) {
+                                char temp[UTIL_NAME_SIZE];
+
+                                /* append value separated by space */
+                                udev_event_apply_format(event, value, temp, sizeof(temp));
+                                util_strscpyl(value_new, sizeof(value_new), value_old, " ", temp, NULL);
+                        } else
+                                udev_event_apply_format(event, value, value_new, sizeof(value_new));
+
+                        entry = udev_device_add_property(event->dev, name, value_new);
+                        /* store in db, skip private keys */
+                        if (name[0] != '.')
+                                udev_list_entry_set_num(entry, true);
                         break;
                 }
                 case TK_A_TAG: {