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