]>
Commit | Line | Data |
---|---|---|
e7145211 | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
d6170d27 | 2 | |
13aca847 YW |
3 | #include <errno.h> |
4 | ||
b753e14a | 5 | #include "alloc-util.h" |
fc9e3b81 YW |
6 | #include "bus-error.h" |
7 | #include "bus-util.h" | |
13aca847 | 8 | #include "device-private.h" |
27458ed6 | 9 | #include "path-util.h" |
d6170d27 | 10 | #include "udevadm-util.h" |
b6854081 | 11 | #include "unit-name.h" |
d6170d27 | 12 | |
fc9e3b81 YW |
13 | static int find_device_from_path(const char *path, sd_device **ret) { |
14 | if (path_startswith(path, "/sys/")) | |
15 | return sd_device_new_from_syspath(ret, path); | |
16 | ||
17 | if (path_startswith(path, "/dev/")) { | |
18 | struct stat st; | |
19 | ||
20 | if (stat(path, &st) < 0) | |
21 | return -errno; | |
22 | ||
23 | return device_new_from_stat_rdev(ret, &st); | |
24 | } | |
25 | ||
26 | return -EINVAL; | |
27 | } | |
28 | ||
29 | static int find_device_from_unit(const char *unit_name, sd_device **ret) { | |
30 | _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; | |
31 | _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; | |
32 | _cleanup_free_ char *unit_path = NULL, *syspath = NULL; | |
33 | int r; | |
34 | ||
35 | if (!unit_name_is_valid(unit_name, UNIT_NAME_PLAIN)) | |
36 | return -EINVAL; | |
37 | ||
38 | if (unit_name_to_type(unit_name) != UNIT_DEVICE) | |
39 | return -EINVAL; | |
40 | ||
41 | r = bus_connect_system_systemd(&bus); | |
42 | if (r < 0) { | |
43 | _cleanup_free_ char *path = NULL; | |
44 | ||
45 | log_debug_errno(r, "Failed to open connection to systemd, using unit name as syspath: %m"); | |
46 | ||
47 | r = unit_name_to_path(unit_name, &path); | |
48 | if (r < 0) | |
49 | return log_debug_errno(r, "Failed to convert \"%s\" to a device path: %m", unit_name); | |
50 | ||
51 | return find_device_from_path(path, ret); | |
52 | } | |
53 | ||
54 | unit_path = unit_dbus_path_from_name(unit_name); | |
55 | if (!unit_path) | |
56 | return -ENOMEM; | |
57 | ||
58 | r = sd_bus_get_property_string( | |
59 | bus, | |
60 | "org.freedesktop.systemd1", | |
61 | unit_path, | |
62 | "org.freedesktop.systemd1.Device", | |
63 | "SysFSPath", | |
64 | &error, | |
65 | &syspath); | |
66 | if (r < 0) | |
67 | return log_debug_errno(r, "Failed to get SysFSPath= dbus property for %s: %s", | |
68 | unit_name, bus_error_message(&error, r)); | |
69 | ||
70 | return sd_device_new_from_syspath(ret, syspath); | |
71 | } | |
72 | ||
13aca847 | 73 | int find_device(const char *id, const char *prefix, sd_device **ret) { |
b6854081 ZJS |
74 | _cleanup_free_ char *path = NULL; |
75 | int r; | |
b753e14a | 76 | |
d6170d27 | 77 | assert(id); |
13aca847 | 78 | assert(ret); |
d6170d27 | 79 | |
b6854081 ZJS |
80 | if (prefix) { |
81 | if (!path_startswith(id, prefix)) { | |
82 | id = path = path_join(prefix, id); | |
83 | if (!path) | |
84 | return -ENOMEM; | |
85 | } | |
86 | } else { | |
87 | /* In cases where the argument is generic (no prefix specified), | |
88 | * check if the argument looks like a device unit name. */ | |
fc9e3b81 YW |
89 | r = find_device_from_unit(id, ret); |
90 | if (r >= 0) | |
91 | return r; | |
b753e14a | 92 | } |
d6170d27 | 93 | |
fc9e3b81 | 94 | return find_device_from_path(id, ret); |
d6170d27 | 95 | } |