]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-libudev.c
tree-wide: drop redundant _cleanup_ macros (#8810)
[thirdparty/systemd.git] / src / test / test-libudev.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
1298001e
KS
2/***
3 This file is part of systemd.
4
5 Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
1298001e 6***/
33a5cc29 7
b2d9e4f2 8#include <getopt.h>
07630cea 9#include <stdio.h>
f2fd4d27 10#include <sys/epoll.h>
07630cea 11#include <unistd.h>
ba6929f6 12
33a5cc29 13#include "libudev.h"
b4bbcaa9 14
cc4c1d22
ZJS
15#include "fd-util.h"
16#include "log.h"
d054f0a4 17#include "stdio-util.h"
07630cea 18#include "string-util.h"
1ca208fb 19#include "udev-util.h"
33502ffe 20#include "util.h"
33a5cc29 21
f168c273 22static void print_device(struct udev_device *device) {
912541b0
KS
23 const char *str;
24 dev_t devnum;
25 int count;
26 struct udev_list_entry *list_entry;
27
cc4c1d22 28 log_info("*** device: %p ***", device);
912541b0
KS
29 str = udev_device_get_action(device);
30 if (str != NULL)
cc4c1d22 31 log_info("action: '%s'", str);
912541b0
KS
32
33 str = udev_device_get_syspath(device);
cc4c1d22 34 log_info("syspath: '%s'", str);
912541b0
KS
35
36 str = udev_device_get_sysname(device);
cc4c1d22 37 log_info("sysname: '%s'", str);
912541b0
KS
38
39 str = udev_device_get_sysnum(device);
40 if (str != NULL)
cc4c1d22 41 log_info("sysnum: '%s'", str);
912541b0
KS
42
43 str = udev_device_get_devpath(device);
cc4c1d22 44 log_info("devpath: '%s'", str);
912541b0
KS
45
46 str = udev_device_get_subsystem(device);
47 if (str != NULL)
cc4c1d22 48 log_info("subsystem: '%s'", str);
912541b0
KS
49
50 str = udev_device_get_devtype(device);
51 if (str != NULL)
cc4c1d22 52 log_info("devtype: '%s'", str);
912541b0
KS
53
54 str = udev_device_get_driver(device);
55 if (str != NULL)
cc4c1d22 56 log_info("driver: '%s'", str);
912541b0
KS
57
58 str = udev_device_get_devnode(device);
59 if (str != NULL)
cc4c1d22 60 log_info("devname: '%s'", str);
912541b0
KS
61
62 devnum = udev_device_get_devnum(device);
63 if (major(devnum) > 0)
cc4c1d22 64 log_info("devnum: %u:%u", major(devnum), minor(devnum));
912541b0
KS
65
66 count = 0;
67 udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) {
cc4c1d22 68 log_info("link: '%s'", udev_list_entry_get_name(list_entry));
912541b0
KS
69 count++;
70 }
71 if (count > 0)
cc4c1d22 72 log_info("found %i links", count);
912541b0
KS
73
74 count = 0;
75 udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device)) {
cc4c1d22 76 log_info("property: '%s=%s'",
912541b0
KS
77 udev_list_entry_get_name(list_entry),
78 udev_list_entry_get_value(list_entry));
79 count++;
80 }
81 if (count > 0)
cc4c1d22 82 log_info("found %i properties", count);
912541b0
KS
83
84 str = udev_device_get_property_value(device, "MAJOR");
85 if (str != NULL)
cc4c1d22 86 log_info("MAJOR: '%s'", str);
912541b0
KS
87
88 str = udev_device_get_sysattr_value(device, "dev");
89 if (str != NULL)
cc4c1d22 90 log_info("attr{dev}: '%s'", str);
ba6929f6
KS
91}
92
cc4c1d22 93static void test_device(struct udev *udev, const char *syspath) {
8e766630 94 _cleanup_(udev_device_unrefp) struct udev_device *device;
912541b0 95
cc4c1d22 96 log_info("looking at device: %s", syspath);
912541b0 97 device = udev_device_new_from_syspath(udev, syspath);
cc4c1d22
ZJS
98 if (device == NULL)
99 log_warning_errno(errno, "udev_device_new_from_syspath: %m");
100 else
101 print_device(device);
33a5cc29
KS
102}
103
cc4c1d22 104static void test_device_parents(struct udev *udev, const char *syspath) {
8e766630 105 _cleanup_(udev_device_unrefp) struct udev_device *device;
912541b0
KS
106 struct udev_device *device_parent;
107
cc4c1d22 108 log_info("looking at device: %s", syspath);
912541b0
KS
109 device = udev_device_new_from_syspath(udev, syspath);
110 if (device == NULL)
cc4c1d22 111 return;
912541b0 112
cc4c1d22 113 log_info("looking at parents");
912541b0
KS
114 device_parent = device;
115 do {
116 print_device(device_parent);
117 device_parent = udev_device_get_parent(device_parent);
118 } while (device_parent != NULL);
119
cc4c1d22 120 log_info("looking at parents again");
912541b0
KS
121 device_parent = device;
122 do {
123 print_device(device_parent);
124 device_parent = udev_device_get_parent(device_parent);
125 } while (device_parent != NULL);
4ad3a37f
KS
126}
127
cc4c1d22 128static void test_device_devnum(struct udev *udev) {
912541b0 129 dev_t devnum = makedev(1, 3);
8e766630 130 _cleanup_(udev_device_unrefp) struct udev_device *device;
912541b0 131
cc4c1d22 132 log_info("looking up device: %u:%u", major(devnum), minor(devnum));
912541b0
KS
133 device = udev_device_new_from_devnum(udev, 'c', devnum);
134 if (device == NULL)
cc4c1d22
ZJS
135 log_warning_errno(errno, "udev_device_new_from_devnum: %m");
136 else
137 print_device(device);
4c9dff47
KS
138}
139
cc4c1d22 140static void test_device_subsys_name(struct udev *udev, const char *subsys, const char *dev) {
8e766630 141 _cleanup_(udev_device_unrefp) struct udev_device *device;
912541b0 142
cc4c1d22
ZJS
143 log_info("looking up device: '%s:%s'", subsys, dev);
144 device = udev_device_new_from_subsystem_sysname(udev, subsys, dev);
912541b0 145 if (device == NULL)
cc4c1d22
ZJS
146 log_warning_errno(errno, "udev_device_new_from_subsystem_sysname: %m");
147 else
148 print_device(device);
90d80c2e
KS
149}
150
f168c273 151static int test_enumerate_print_list(struct udev_enumerate *enumerate) {
912541b0
KS
152 struct udev_list_entry *list_entry;
153 int count = 0;
154
155 udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
156 struct udev_device *device;
157
158 device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
159 udev_list_entry_get_name(list_entry));
160 if (device != NULL) {
cc4c1d22
ZJS
161 log_info("device: '%s' (%s)",
162 udev_device_get_syspath(device),
163 udev_device_get_subsystem(device));
912541b0
KS
164 udev_device_unref(device);
165 count++;
166 }
167 }
cc4c1d22 168 log_info("found %i devices", count);
912541b0 169 return count;
ba6929f6
KS
170}
171
cc4c1d22 172static void test_monitor(struct udev *udev) {
8e766630 173 _cleanup_(udev_monitor_unrefp) struct udev_monitor *udev_monitor;
cc4c1d22
ZJS
174 _cleanup_close_ int fd_ep;
175 int fd_udev;
176 struct epoll_event ep_udev = {
177 .events = EPOLLIN,
178 }, ep_stdin = {
179 .events = EPOLLIN,
180 .data.fd = STDIN_FILENO,
181 };
912541b0
KS
182
183 fd_ep = epoll_create1(EPOLL_CLOEXEC);
cc4c1d22 184 assert_se(fd_ep >= 0);
912541b0
KS
185
186 udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
cc4c1d22 187 assert_se(udev_monitor != NULL);
912541b0 188
cc4c1d22
ZJS
189 fd_udev = udev_monitor_get_fd(udev_monitor);
190 ep_udev.data.fd = fd_udev;
912541b0 191
cc4c1d22
ZJS
192 assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "block", NULL) >= 0);
193 assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL) >= 0);
194 assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device") >= 0);
912541b0 195
cc4c1d22 196 assert_se(udev_monitor_enable_receiving(udev_monitor) >= 0);
912541b0 197
cc4c1d22
ZJS
198 assert_se(epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) >= 0);
199 assert_se(epoll_ctl(fd_ep, EPOLL_CTL_ADD, STDIN_FILENO, &ep_stdin) >= 0);
912541b0
KS
200
201 for (;;) {
202 int fdcount;
203 struct epoll_event ev[4];
204 struct udev_device *device;
205 int i;
206
207 printf("waiting for events from udev, press ENTER to exit\n");
cc4c1d22 208 fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), -1);
912541b0
KS
209 printf("epoll fd count: %i\n", fdcount);
210
211 for (i = 0; i < fdcount; i++) {
212 if (ev[i].data.fd == fd_udev && ev[i].events & EPOLLIN) {
213 device = udev_monitor_receive_device(udev_monitor);
214 if (device == NULL) {
215 printf("no device from socket\n");
216 continue;
217 }
218 print_device(device);
219 udev_device_unref(device);
220 } else if (ev[i].data.fd == STDIN_FILENO && ev[i].events & EPOLLIN) {
221 printf("exiting loop\n");
cc4c1d22 222 return;
912541b0
KS
223 }
224 }
225 }
33a5cc29
KS
226}
227
cc4c1d22 228static void test_queue(struct udev *udev) {
912541b0 229 struct udev_queue *udev_queue;
cc4c1d22 230 bool empty;
912541b0
KS
231
232 udev_queue = udev_queue_new(udev);
cc4c1d22 233 assert_se(udev_queue);
912541b0 234
cc4c1d22
ZJS
235 empty = udev_queue_get_queue_is_empty(udev_queue);
236 log_info("queue is %s", empty ? "empty" : "not empty");
912541b0 237 udev_queue_unref(udev_queue);
64ccdf82
KS
238}
239
f168c273 240static int test_enumerate(struct udev *udev, const char *subsystem) {
912541b0 241 struct udev_enumerate *udev_enumerate;
c0c6a4fc 242 int r;
912541b0 243
cc4c1d22 244 log_info("enumerate '%s'", subsystem == NULL ? "<all>" : subsystem);
912541b0
KS
245 udev_enumerate = udev_enumerate_new(udev);
246 if (udev_enumerate == NULL)
247 return -1;
248 udev_enumerate_add_match_subsystem(udev_enumerate, subsystem);
249 udev_enumerate_scan_devices(udev_enumerate);
250 test_enumerate_print_list(udev_enumerate);
251 udev_enumerate_unref(udev_enumerate);
252
cc4c1d22 253 log_info("enumerate 'net' + duplicated scan + null + zero");
912541b0
KS
254 udev_enumerate = udev_enumerate_new(udev);
255 if (udev_enumerate == NULL)
256 return -1;
257 udev_enumerate_add_match_subsystem(udev_enumerate, "net");
258 udev_enumerate_scan_devices(udev_enumerate);
259 udev_enumerate_scan_devices(udev_enumerate);
260 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero");
261 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null");
262 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero");
263 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null");
264 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero");
265 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null");
266 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null");
267 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero");
268 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero");
269 udev_enumerate_scan_devices(udev_enumerate);
270 test_enumerate_print_list(udev_enumerate);
271 udev_enumerate_unref(udev_enumerate);
272
cc4c1d22 273 log_info("enumerate 'block'");
912541b0
KS
274 udev_enumerate = udev_enumerate_new(udev);
275 if (udev_enumerate == NULL)
276 return -1;
277 udev_enumerate_add_match_subsystem(udev_enumerate,"block");
c0c6a4fc 278 r = udev_enumerate_add_match_is_initialized(udev_enumerate);
86ff9f11
TA
279 if (r < 0) {
280 udev_enumerate_unref(udev_enumerate);
c0c6a4fc 281 return r;
86ff9f11 282 }
912541b0
KS
283 udev_enumerate_scan_devices(udev_enumerate);
284 test_enumerate_print_list(udev_enumerate);
285 udev_enumerate_unref(udev_enumerate);
286
cc4c1d22 287 log_info("enumerate 'not block'");
912541b0
KS
288 udev_enumerate = udev_enumerate_new(udev);
289 if (udev_enumerate == NULL)
290 return -1;
291 udev_enumerate_add_nomatch_subsystem(udev_enumerate, "block");
292 udev_enumerate_scan_devices(udev_enumerate);
293 test_enumerate_print_list(udev_enumerate);
294 udev_enumerate_unref(udev_enumerate);
295
cc4c1d22 296 log_info("enumerate 'pci, mem, vc'");
912541b0
KS
297 udev_enumerate = udev_enumerate_new(udev);
298 if (udev_enumerate == NULL)
299 return -1;
300 udev_enumerate_add_match_subsystem(udev_enumerate, "pci");
301 udev_enumerate_add_match_subsystem(udev_enumerate, "mem");
302 udev_enumerate_add_match_subsystem(udev_enumerate, "vc");
303 udev_enumerate_scan_devices(udev_enumerate);
304 test_enumerate_print_list(udev_enumerate);
305 udev_enumerate_unref(udev_enumerate);
306
cc4c1d22 307 log_info("enumerate 'subsystem'");
912541b0
KS
308 udev_enumerate = udev_enumerate_new(udev);
309 if (udev_enumerate == NULL)
310 return -1;
311 udev_enumerate_scan_subsystems(udev_enumerate);
312 test_enumerate_print_list(udev_enumerate);
313 udev_enumerate_unref(udev_enumerate);
314
cc4c1d22 315 log_info("enumerate 'property IF_FS_*=filesystem'");
912541b0
KS
316 udev_enumerate = udev_enumerate_new(udev);
317 if (udev_enumerate == NULL)
318 return -1;
319 udev_enumerate_add_match_property(udev_enumerate, "ID_FS*", "filesystem");
320 udev_enumerate_scan_devices(udev_enumerate);
321 test_enumerate_print_list(udev_enumerate);
322 udev_enumerate_unref(udev_enumerate);
323 return 0;
90d80c2e
KS
324}
325
872c8faa 326static void test_hwdb(struct udev *udev, const char *modalias) {
960787ae 327 struct udev_hwdb *hwdb;
2001208c
KS
328 struct udev_list_entry *entry;
329
330 hwdb = udev_hwdb_new(udev);
331
332 udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, modalias, 0))
cc4c1d22 333 log_info("'%s'='%s'", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry));
2001208c
KS
334
335 hwdb = udev_hwdb_unref(hwdb);
bdf7026e 336 assert_se(hwdb == NULL);
2001208c
KS
337}
338
f168c273 339int main(int argc, char *argv[]) {
8e766630 340 _cleanup_(udev_unrefp) struct udev *udev = NULL;
301a9c67 341 bool arg_monitor = false;
912541b0 342 static const struct option options[] = {
cc4c1d22 343 { "syspath", required_argument, NULL, 'p' },
912541b0 344 { "subsystem", required_argument, NULL, 's' },
cc4c1d22
ZJS
345 { "debug", no_argument, NULL, 'd' },
346 { "help", no_argument, NULL, 'h' },
347 { "version", no_argument, NULL, 'V' },
301a9c67 348 { "monitor", no_argument, NULL, 'm' },
912541b0
KS
349 {}
350 };
351 const char *syspath = "/devices/virtual/mem/null";
352 const char *subsystem = NULL;
601185b4 353 int c;
912541b0
KS
354
355 udev = udev_new();
cc4c1d22 356 log_info("context: %p", udev);
912541b0 357 if (udev == NULL) {
cc4c1d22 358 log_info("no context");
912541b0
KS
359 return 1;
360 }
912541b0 361
63547675 362 while ((c = getopt_long(argc, argv, "p:s:dhVm", options, NULL)) >= 0)
601185b4 363 switch (c) {
912541b0 364
912541b0
KS
365 case 'p':
366 syspath = optarg;
367 break;
601185b4 368
912541b0
KS
369 case 's':
370 subsystem = optarg;
371 break;
601185b4 372
912541b0 373 case 'd':
25e773ee
KS
374 if (log_get_max_level() < LOG_INFO)
375 log_set_max_level(LOG_INFO);
912541b0 376 break;
601185b4 377
912541b0
KS
378 case 'h':
379 printf("--debug --syspath= --subsystem= --help\n");
cc4c1d22 380 return EXIT_SUCCESS;
601185b4 381
912541b0 382 case 'V':
948aaa7c 383 printf("%s\n", PACKAGE_VERSION);
cc4c1d22 384 return EXIT_SUCCESS;
601185b4 385
301a9c67
ZJS
386 case 'm':
387 arg_monitor = true;
388 break;
389
601185b4 390 case '?':
cc4c1d22 391 return EXIT_FAILURE;
601185b4
ZJS
392
393 default:
394 assert_not_reached("Unhandled option code.");
912541b0 395 }
601185b4 396
912541b0 397 /* add sys path if needed */
cc4c1d22
ZJS
398 if (!startswith(syspath, "/sys"))
399 syspath = strjoina("/sys/", syspath);
912541b0
KS
400
401 test_device(udev, syspath);
402 test_device_devnum(udev);
cc4c1d22
ZJS
403 test_device_subsys_name(udev, "block", "sda");
404 test_device_subsys_name(udev, "subsystem", "pci");
405 test_device_subsys_name(udev, "drivers", "scsi:sd");
406 test_device_subsys_name(udev, "module", "printk");
407
912541b0
KS
408 test_device_parents(udev, syspath);
409
410 test_enumerate(udev, subsystem);
411
412 test_queue(udev);
413
2001208c
KS
414 test_hwdb(udev, "usb:v0D50p0011*");
415
301a9c67
ZJS
416 if (arg_monitor)
417 test_monitor(udev);
cc4c1d22
ZJS
418
419 return EXIT_SUCCESS;
33a5cc29 420}