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