]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-libudev.c
udevd: worker - allow passing NULL to worker_unref()
[thirdparty/systemd.git] / src / test / test-libudev.c
CommitLineData
601185b4 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1298001e
KS
2/***
3 This file is part of systemd.
4
5 Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
33a5cc29 20
33a5cc29 21#include <stdio.h>
ba6929f6 22#include <unistd.h>
b2d9e4f2 23#include <getopt.h>
f2fd4d27 24#include <sys/epoll.h>
ba6929f6 25
33a5cc29 26#include "libudev.h"
1ca208fb 27#include "udev-util.h"
33502ffe 28#include "util.h"
33a5cc29 29
f2fd4d27
KS
30#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
31
f168c273 32static void print_device(struct udev_device *device) {
912541b0
KS
33 const char *str;
34 dev_t devnum;
35 int count;
36 struct udev_list_entry *list_entry;
37
38 printf("*** device: %p ***\n", device);
39 str = udev_device_get_action(device);
40 if (str != NULL)
41 printf("action: '%s'\n", str);
42
43 str = udev_device_get_syspath(device);
44 printf("syspath: '%s'\n", str);
45
46 str = udev_device_get_sysname(device);
47 printf("sysname: '%s'\n", str);
48
49 str = udev_device_get_sysnum(device);
50 if (str != NULL)
51 printf("sysnum: '%s'\n", str);
52
53 str = udev_device_get_devpath(device);
54 printf("devpath: '%s'\n", str);
55
56 str = udev_device_get_subsystem(device);
57 if (str != NULL)
58 printf("subsystem: '%s'\n", str);
59
60 str = udev_device_get_devtype(device);
61 if (str != NULL)
62 printf("devtype: '%s'\n", str);
63
64 str = udev_device_get_driver(device);
65 if (str != NULL)
66 printf("driver: '%s'\n", str);
67
68 str = udev_device_get_devnode(device);
69 if (str != NULL)
70 printf("devname: '%s'\n", str);
71
72 devnum = udev_device_get_devnum(device);
73 if (major(devnum) > 0)
74 printf("devnum: %u:%u\n", major(devnum), minor(devnum));
75
76 count = 0;
77 udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) {
78 printf("link: '%s'\n", udev_list_entry_get_name(list_entry));
79 count++;
80 }
81 if (count > 0)
82 printf("found %i links\n", count);
83
84 count = 0;
85 udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device)) {
86 printf("property: '%s=%s'\n",
87 udev_list_entry_get_name(list_entry),
88 udev_list_entry_get_value(list_entry));
89 count++;
90 }
91 if (count > 0)
92 printf("found %i properties\n", count);
93
94 str = udev_device_get_property_value(device, "MAJOR");
95 if (str != NULL)
96 printf("MAJOR: '%s'\n", str);
97
98 str = udev_device_get_sysattr_value(device, "dev");
99 if (str != NULL)
100 printf("attr{dev}: '%s'\n", str);
101
102 printf("\n");
ba6929f6
KS
103}
104
f168c273 105static int test_device(struct udev *udev, const char *syspath) {
1ca208fb 106 _cleanup_udev_device_unref_ struct udev_device *device;
912541b0
KS
107
108 printf("looking at device: %s\n", syspath);
109 device = udev_device_new_from_syspath(udev, syspath);
110 if (device == NULL) {
111 printf("no device found\n");
112 return -1;
113 }
114 print_device(device);
1ca208fb 115
912541b0 116 return 0;
33a5cc29
KS
117}
118
f168c273 119static int test_device_parents(struct udev *udev, const char *syspath) {
1ca208fb 120 _cleanup_udev_device_unref_ struct udev_device *device;
912541b0
KS
121 struct udev_device *device_parent;
122
123 printf("looking at device: %s\n", syspath);
124 device = udev_device_new_from_syspath(udev, syspath);
125 if (device == NULL)
126 return -1;
127
128 printf("looking at parents\n");
129 device_parent = device;
130 do {
131 print_device(device_parent);
132 device_parent = udev_device_get_parent(device_parent);
133 } while (device_parent != NULL);
134
135 printf("looking at parents again\n");
136 device_parent = device;
137 do {
138 print_device(device_parent);
139 device_parent = udev_device_get_parent(device_parent);
140 } while (device_parent != NULL);
912541b0
KS
141
142 return 0;
4ad3a37f
KS
143}
144
f168c273 145static int test_device_devnum(struct udev *udev) {
912541b0
KS
146 dev_t devnum = makedev(1, 3);
147 struct udev_device *device;
148
149 printf("looking up device: %u:%u\n", major(devnum), minor(devnum));
150 device = udev_device_new_from_devnum(udev, 'c', devnum);
151 if (device == NULL)
152 return -1;
153 print_device(device);
154 udev_device_unref(device);
155 return 0;
4c9dff47
KS
156}
157
f168c273 158static int test_device_subsys_name(struct udev *udev) {
912541b0
KS
159 struct udev_device *device;
160
161 printf("looking up device: 'block':'sda'\n");
162 device = udev_device_new_from_subsystem_sysname(udev, "block", "sda");
163 if (device == NULL)
164 return -1;
165 print_device(device);
166 udev_device_unref(device);
167
168 printf("looking up device: 'subsystem':'pci'\n");
169 device = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci");
170 if (device == NULL)
171 return -1;
172 print_device(device);
173 udev_device_unref(device);
174
175 printf("looking up device: 'drivers':'scsi:sd'\n");
176 device = udev_device_new_from_subsystem_sysname(udev, "drivers", "scsi:sd");
177 if (device == NULL)
178 return -1;
179 print_device(device);
180 udev_device_unref(device);
181
182 printf("looking up device: 'module':'printk'\n");
183 device = udev_device_new_from_subsystem_sysname(udev, "module", "printk");
184 if (device == NULL)
185 return -1;
186 print_device(device);
187 udev_device_unref(device);
188 return 0;
90d80c2e
KS
189}
190
f168c273 191static int test_enumerate_print_list(struct udev_enumerate *enumerate) {
912541b0
KS
192 struct udev_list_entry *list_entry;
193 int count = 0;
194
195 udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
196 struct udev_device *device;
197
198 device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
199 udev_list_entry_get_name(list_entry));
200 if (device != NULL) {
201 printf("device: '%s' (%s)\n",
202 udev_device_get_syspath(device),
203 udev_device_get_subsystem(device));
204 udev_device_unref(device);
205 count++;
206 }
207 }
208 printf("found %i devices\n\n", count);
209 return count;
ba6929f6
KS
210}
211
f168c273 212static int test_monitor(struct udev *udev) {
912541b0
KS
213 struct udev_monitor *udev_monitor = NULL;
214 int fd_ep;
215 int fd_udev = -1;
216 struct epoll_event ep_udev, ep_stdin;
217
218 fd_ep = epoll_create1(EPOLL_CLOEXEC);
219 if (fd_ep < 0) {
220 printf("error creating epoll fd: %m\n");
221 goto out;
222 }
223
224 udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
225 if (udev_monitor == NULL) {
226 printf("no socket\n");
227 goto out;
228 }
229 fd_udev = udev_monitor_get_fd(udev_monitor);
230
231 if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "block", NULL) < 0 ||
232 udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL) < 0 ||
233 udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device") < 0) {
234 printf("filter failed\n");
235 goto out;
236 }
237
238 if (udev_monitor_enable_receiving(udev_monitor) < 0) {
239 printf("bind failed\n");
240 goto out;
241 }
242
29804cc1 243 memzero(&ep_udev, sizeof(struct epoll_event));
912541b0
KS
244 ep_udev.events = EPOLLIN;
245 ep_udev.data.fd = fd_udev;
246 if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0) {
247 printf("fail to add fd to epoll: %m\n");
248 goto out;
249 }
250
29804cc1 251 memzero(&ep_stdin, sizeof(struct epoll_event));
912541b0
KS
252 ep_stdin.events = EPOLLIN;
253 ep_stdin.data.fd = STDIN_FILENO;
254 if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, STDIN_FILENO, &ep_stdin) < 0) {
255 printf("fail to add fd to epoll: %m\n");
256 goto out;
257 }
258
259 for (;;) {
260 int fdcount;
261 struct epoll_event ev[4];
262 struct udev_device *device;
263 int i;
264
265 printf("waiting for events from udev, press ENTER to exit\n");
266 fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), -1);
267 printf("epoll fd count: %i\n", fdcount);
268
269 for (i = 0; i < fdcount; i++) {
270 if (ev[i].data.fd == fd_udev && ev[i].events & EPOLLIN) {
271 device = udev_monitor_receive_device(udev_monitor);
272 if (device == NULL) {
273 printf("no device from socket\n");
274 continue;
275 }
276 print_device(device);
277 udev_device_unref(device);
278 } else if (ev[i].data.fd == STDIN_FILENO && ev[i].events & EPOLLIN) {
279 printf("exiting loop\n");
280 goto out;
281 }
282 }
283 }
f2fd4d27 284out:
912541b0
KS
285 if (fd_ep >= 0)
286 close(fd_ep);
287 udev_monitor_unref(udev_monitor);
288 return 0;
33a5cc29
KS
289}
290
f168c273 291static int test_queue(struct udev *udev) {
912541b0 292 struct udev_queue *udev_queue;
912541b0
KS
293
294 udev_queue = udev_queue_new(udev);
295 if (udev_queue == NULL)
296 return -1;
912541b0
KS
297
298 if (udev_queue_get_queue_is_empty(udev_queue))
299 printf("queue is empty\n");
912541b0 300
912541b0
KS
301 udev_queue_unref(udev_queue);
302 return 0;
64ccdf82
KS
303}
304
f168c273 305static int test_enumerate(struct udev *udev, const char *subsystem) {
912541b0
KS
306 struct udev_enumerate *udev_enumerate;
307
308 printf("enumerate '%s'\n", subsystem == NULL ? "<all>" : subsystem);
309 udev_enumerate = udev_enumerate_new(udev);
310 if (udev_enumerate == NULL)
311 return -1;
312 udev_enumerate_add_match_subsystem(udev_enumerate, subsystem);
313 udev_enumerate_scan_devices(udev_enumerate);
314 test_enumerate_print_list(udev_enumerate);
315 udev_enumerate_unref(udev_enumerate);
316
317 printf("enumerate 'net' + duplicated scan + null + zero\n");
318 udev_enumerate = udev_enumerate_new(udev);
319 if (udev_enumerate == NULL)
320 return -1;
321 udev_enumerate_add_match_subsystem(udev_enumerate, "net");
322 udev_enumerate_scan_devices(udev_enumerate);
323 udev_enumerate_scan_devices(udev_enumerate);
324 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero");
325 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null");
326 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero");
327 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null");
328 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero");
329 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null");
330 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null");
331 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero");
332 udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero");
333 udev_enumerate_scan_devices(udev_enumerate);
334 test_enumerate_print_list(udev_enumerate);
335 udev_enumerate_unref(udev_enumerate);
336
337 printf("enumerate 'block'\n");
338 udev_enumerate = udev_enumerate_new(udev);
339 if (udev_enumerate == NULL)
340 return -1;
341 udev_enumerate_add_match_subsystem(udev_enumerate,"block");
342 udev_enumerate_add_match_is_initialized(udev_enumerate);
343 udev_enumerate_scan_devices(udev_enumerate);
344 test_enumerate_print_list(udev_enumerate);
345 udev_enumerate_unref(udev_enumerate);
346
347 printf("enumerate 'not block'\n");
348 udev_enumerate = udev_enumerate_new(udev);
349 if (udev_enumerate == NULL)
350 return -1;
351 udev_enumerate_add_nomatch_subsystem(udev_enumerate, "block");
352 udev_enumerate_scan_devices(udev_enumerate);
353 test_enumerate_print_list(udev_enumerate);
354 udev_enumerate_unref(udev_enumerate);
355
356 printf("enumerate 'pci, mem, vc'\n");
357 udev_enumerate = udev_enumerate_new(udev);
358 if (udev_enumerate == NULL)
359 return -1;
360 udev_enumerate_add_match_subsystem(udev_enumerate, "pci");
361 udev_enumerate_add_match_subsystem(udev_enumerate, "mem");
362 udev_enumerate_add_match_subsystem(udev_enumerate, "vc");
363 udev_enumerate_scan_devices(udev_enumerate);
364 test_enumerate_print_list(udev_enumerate);
365 udev_enumerate_unref(udev_enumerate);
366
367 printf("enumerate 'subsystem'\n");
368 udev_enumerate = udev_enumerate_new(udev);
369 if (udev_enumerate == NULL)
370 return -1;
371 udev_enumerate_scan_subsystems(udev_enumerate);
372 test_enumerate_print_list(udev_enumerate);
373 udev_enumerate_unref(udev_enumerate);
374
375 printf("enumerate 'property IF_FS_*=filesystem'\n");
376 udev_enumerate = udev_enumerate_new(udev);
377 if (udev_enumerate == NULL)
378 return -1;
379 udev_enumerate_add_match_property(udev_enumerate, "ID_FS*", "filesystem");
380 udev_enumerate_scan_devices(udev_enumerate);
381 test_enumerate_print_list(udev_enumerate);
382 udev_enumerate_unref(udev_enumerate);
383 return 0;
90d80c2e
KS
384}
385
872c8faa 386static void test_hwdb(struct udev *udev, const char *modalias) {
960787ae 387 struct udev_hwdb *hwdb;
2001208c
KS
388 struct udev_list_entry *entry;
389
390 hwdb = udev_hwdb_new(udev);
391
392 udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, modalias, 0))
393 printf("'%s'='%s'\n", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry));
394 printf("\n");
395
396 hwdb = udev_hwdb_unref(hwdb);
bdf7026e 397 assert_se(hwdb == NULL);
2001208c
KS
398}
399
f168c273 400int main(int argc, char *argv[]) {
912541b0
KS
401 struct udev *udev = NULL;
402 static const struct option options[] = {
403 { "syspath", required_argument, NULL, 'p' },
404 { "subsystem", required_argument, NULL, 's' },
405 { "debug", no_argument, NULL, 'd' },
406 { "help", no_argument, NULL, 'h' },
407 { "version", no_argument, NULL, 'V' },
408 {}
409 };
410 const char *syspath = "/devices/virtual/mem/null";
411 const char *subsystem = NULL;
412 char path[1024];
601185b4 413 int c;
912541b0
KS
414
415 udev = udev_new();
416 printf("context: %p\n", udev);
417 if (udev == NULL) {
418 printf("no context\n");
419 return 1;
420 }
912541b0 421
601185b4
ZJS
422 while ((c = getopt_long(argc, argv, "p:s:dhV", options, NULL)) >= 0)
423 switch (c) {
912541b0 424
912541b0
KS
425 case 'p':
426 syspath = optarg;
427 break;
601185b4 428
912541b0
KS
429 case 's':
430 subsystem = optarg;
431 break;
601185b4 432
912541b0 433 case 'd':
25e773ee
KS
434 if (log_get_max_level() < LOG_INFO)
435 log_set_max_level(LOG_INFO);
912541b0 436 break;
601185b4 437
912541b0
KS
438 case 'h':
439 printf("--debug --syspath= --subsystem= --help\n");
440 goto out;
601185b4 441
912541b0
KS
442 case 'V':
443 printf("%s\n", VERSION);
444 goto out;
601185b4
ZJS
445
446 case '?':
912541b0 447 goto out;
601185b4
ZJS
448
449 default:
450 assert_not_reached("Unhandled option code.");
912541b0 451 }
601185b4 452
912541b0 453
912541b0 454 /* add sys path if needed */
33502ffe 455 if (!startswith(syspath, "/sys")) {
6ada823a 456 snprintf(path, sizeof(path), "/sys/%s", syspath);
912541b0
KS
457 syspath = path;
458 }
459
460 test_device(udev, syspath);
461 test_device_devnum(udev);
462 test_device_subsys_name(udev);
463 test_device_parents(udev, syspath);
464
465 test_enumerate(udev, subsystem);
466
467 test_queue(udev);
468
2001208c
KS
469 test_hwdb(udev, "usb:v0D50p0011*");
470
912541b0 471 test_monitor(udev);
b2d9e4f2 472out:
912541b0
KS
473 udev_unref(udev);
474 return 0;
33a5cc29 475}