]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udevadm: also support alias .device units to specify devices
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 15 Sep 2020 11:27:13 +0000 (20:27 +0900)
committerLennart Poettering <lennart@poettering.net>
Tue, 20 Oct 2020 08:09:01 +0000 (10:09 +0200)
Previously, .device units generated by SYSTEMD_ALIAS= udev properties
are not supported to specify devices for e.g. 'udevadm info'.

Before:
```
$ udevadm info sys-subsystem-net-devices-enp0s31f6.device
Unknown device "sys-subsystem-net-devices-enp0s31f6.device": No such device
```

After:
```
$ ./udevadm info sys-subsystem-net-devices-enp0s31f6.device
P: /devices/pci0000:00/0000:00:1f.6/net/enp0s31f6
L: 0
E: DEVPATH=/devices/pci0000:00/0000:00:1f.6/net/enp0s31f6
E: INTERFACE=enp0s31f6
E: IFINDEX=2
E: SUBSYSTEM=net
E: USEC_INITIALIZED=25317523
E: ID_NET_NAMING_SCHEME=v245
(snip)
```

src/udev/udevadm-util.c

index 557982b23dfa896b9c5681c17e2edda0110bb936..bc21115ebdd953888368330865ae927714e1149a 100644 (file)
@@ -3,11 +3,73 @@
 #include <errno.h>
 
 #include "alloc-util.h"
+#include "bus-error.h"
+#include "bus-util.h"
 #include "device-private.h"
 #include "path-util.h"
 #include "udevadm-util.h"
 #include "unit-name.h"
 
+static int find_device_from_path(const char *path, sd_device **ret) {
+        if (path_startswith(path, "/sys/"))
+                return sd_device_new_from_syspath(ret, path);
+
+        if (path_startswith(path, "/dev/")) {
+                struct stat st;
+
+                if (stat(path, &st) < 0)
+                        return -errno;
+
+                return device_new_from_stat_rdev(ret, &st);
+        }
+
+        return -EINVAL;
+}
+
+static int find_device_from_unit(const char *unit_name, sd_device **ret) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        _cleanup_free_ char *unit_path = NULL, *syspath = NULL;
+        int r;
+
+        if (!unit_name_is_valid(unit_name, UNIT_NAME_PLAIN))
+                return -EINVAL;
+
+        if (unit_name_to_type(unit_name) != UNIT_DEVICE)
+                return -EINVAL;
+
+        r = bus_connect_system_systemd(&bus);
+        if (r < 0) {
+                _cleanup_free_ char *path = NULL;
+
+                log_debug_errno(r, "Failed to open connection to systemd, using unit name as syspath: %m");
+
+                r = unit_name_to_path(unit_name, &path);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to convert \"%s\" to a device path: %m", unit_name);
+
+                return find_device_from_path(path, ret);
+        }
+
+        unit_path = unit_dbus_path_from_name(unit_name);
+        if (!unit_path)
+                return -ENOMEM;
+
+        r = sd_bus_get_property_string(
+                        bus,
+                        "org.freedesktop.systemd1",
+                        unit_path,
+                        "org.freedesktop.systemd1.Device",
+                        "SysFSPath",
+                        &error,
+                        &syspath);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to get SysFSPath= dbus property for %s: %s",
+                                       unit_name, bus_error_message(&error, r));
+
+        return sd_device_new_from_syspath(ret, syspath);
+}
+
 int find_device(const char *id, const char *prefix, sd_device **ret) {
         _cleanup_free_ char *path = NULL;
         int r;
@@ -24,26 +86,10 @@ int find_device(const char *id, const char *prefix, sd_device **ret) {
         } else {
                 /* In cases where the argument is generic (no prefix specified),
                  * check if the argument looks like a device unit name. */
-                if (unit_name_is_valid(id, UNIT_NAME_PLAIN) &&
-                    unit_name_to_type(id) == UNIT_DEVICE) {
-                        r = unit_name_to_path(id, &path);
-                        if (r < 0)
-                                return log_debug_errno(r, "Failed to convert \"%s\" to a device path: %m", id);
-                        id = path;
-                }
+                r = find_device_from_unit(id, ret);
+                if (r >= 0)
+                        return r;
         }
 
-        if (path_startswith(id, "/sys/"))
-                return sd_device_new_from_syspath(ret, id);
-
-        if (path_startswith(id, "/dev/")) {
-                struct stat st;
-
-                if (stat(id, &st) < 0)
-                        return -errno;
-
-                return device_new_from_stat_rdev(ret, &st);
-        }
-
-        return -EINVAL;
+        return find_device_from_path(id, ret);
 }