1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
3 This file is part of systemd.
5 Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
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.
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.
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/>.
24 #include <sys/epoll.h>
27 #include "udev-util.h"
30 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
32 static void print_device(struct udev_device *device) {
36 struct udev_list_entry *list_entry;
38 printf("*** device: %p ***\n", device);
39 str = udev_device_get_action(device);
41 printf("action: '%s'\n", str);
43 str = udev_device_get_syspath(device);
44 printf("syspath: '%s'\n", str);
46 str = udev_device_get_sysname(device);
47 printf("sysname: '%s'\n", str);
49 str = udev_device_get_sysnum(device);
51 printf("sysnum: '%s'\n", str);
53 str = udev_device_get_devpath(device);
54 printf("devpath: '%s'\n", str);
56 str = udev_device_get_subsystem(device);
58 printf("subsystem: '%s'\n", str);
60 str = udev_device_get_devtype(device);
62 printf("devtype: '%s'\n", str);
64 str = udev_device_get_driver(device);
66 printf("driver: '%s'\n", str);
68 str = udev_device_get_devnode(device);
70 printf("devname: '%s'\n", str);
72 devnum = udev_device_get_devnum(device);
73 if (major(devnum) > 0)
74 printf("devnum: %u:%u\n", major(devnum), minor(devnum));
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));
82 printf("found %i links\n", count);
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));
92 printf("found %i properties\n", count);
94 str = udev_device_get_property_value(device, "MAJOR");
96 printf("MAJOR: '%s'\n", str);
98 str = udev_device_get_sysattr_value(device, "dev");
100 printf("attr{dev}: '%s'\n", str);
105 static int test_device(struct udev *udev, const char *syspath) {
106 _cleanup_udev_device_unref_ struct udev_device *device;
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");
114 print_device(device);
119 static int test_device_parents(struct udev *udev, const char *syspath) {
120 _cleanup_udev_device_unref_ struct udev_device *device;
121 struct udev_device *device_parent;
123 printf("looking at device: %s\n", syspath);
124 device = udev_device_new_from_syspath(udev, syspath);
128 printf("looking at parents\n");
129 device_parent = device;
131 print_device(device_parent);
132 device_parent = udev_device_get_parent(device_parent);
133 } while (device_parent != NULL);
135 printf("looking at parents again\n");
136 device_parent = device;
138 print_device(device_parent);
139 device_parent = udev_device_get_parent(device_parent);
140 } while (device_parent != NULL);
145 static int test_device_devnum(struct udev *udev) {
146 dev_t devnum = makedev(1, 3);
147 struct udev_device *device;
149 printf("looking up device: %u:%u\n", major(devnum), minor(devnum));
150 device = udev_device_new_from_devnum(udev, 'c', devnum);
153 print_device(device);
154 udev_device_unref(device);
158 static int test_device_subsys_name(struct udev *udev) {
159 struct udev_device *device;
161 printf("looking up device: 'block':'sda'\n");
162 device = udev_device_new_from_subsystem_sysname(udev, "block", "sda");
165 print_device(device);
166 udev_device_unref(device);
168 printf("looking up device: 'subsystem':'pci'\n");
169 device = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci");
172 print_device(device);
173 udev_device_unref(device);
175 printf("looking up device: 'drivers':'scsi:sd'\n");
176 device = udev_device_new_from_subsystem_sysname(udev, "drivers", "scsi:sd");
179 print_device(device);
180 udev_device_unref(device);
182 printf("looking up device: 'module':'printk'\n");
183 device = udev_device_new_from_subsystem_sysname(udev, "module", "printk");
186 print_device(device);
187 udev_device_unref(device);
191 static int test_enumerate_print_list(struct udev_enumerate *enumerate) {
192 struct udev_list_entry *list_entry;
195 udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
196 struct udev_device *device;
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);
208 printf("found %i devices\n\n", count);
212 static int test_monitor(struct udev *udev) {
213 struct udev_monitor *udev_monitor = NULL;
216 struct epoll_event ep_udev, ep_stdin;
218 fd_ep = epoll_create1(EPOLL_CLOEXEC);
220 printf("error creating epoll fd: %m\n");
224 udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
225 if (udev_monitor == NULL) {
226 printf("no socket\n");
229 fd_udev = udev_monitor_get_fd(udev_monitor);
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");
238 if (udev_monitor_enable_receiving(udev_monitor) < 0) {
239 printf("bind failed\n");
243 memzero(&ep_udev, sizeof(struct epoll_event));
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");
251 memzero(&ep_stdin, sizeof(struct epoll_event));
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");
261 struct epoll_event ev[4];
262 struct udev_device *device;
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);
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");
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");
287 udev_monitor_unref(udev_monitor);
291 static int test_queue(struct udev *udev) {
292 struct udev_queue *udev_queue;
294 udev_queue = udev_queue_new(udev);
295 if (udev_queue == NULL)
298 if (udev_queue_get_queue_is_empty(udev_queue))
299 printf("queue is empty\n");
301 udev_queue_unref(udev_queue);
305 static int test_enumerate(struct udev *udev, const char *subsystem) {
306 struct udev_enumerate *udev_enumerate;
308 printf("enumerate '%s'\n", subsystem == NULL ? "<all>" : subsystem);
309 udev_enumerate = udev_enumerate_new(udev);
310 if (udev_enumerate == NULL)
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);
317 printf("enumerate 'net' + duplicated scan + null + zero\n");
318 udev_enumerate = udev_enumerate_new(udev);
319 if (udev_enumerate == NULL)
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);
337 printf("enumerate 'block'\n");
338 udev_enumerate = udev_enumerate_new(udev);
339 if (udev_enumerate == NULL)
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);
347 printf("enumerate 'not block'\n");
348 udev_enumerate = udev_enumerate_new(udev);
349 if (udev_enumerate == NULL)
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);
356 printf("enumerate 'pci, mem, vc'\n");
357 udev_enumerate = udev_enumerate_new(udev);
358 if (udev_enumerate == NULL)
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);
367 printf("enumerate 'subsystem'\n");
368 udev_enumerate = udev_enumerate_new(udev);
369 if (udev_enumerate == NULL)
371 udev_enumerate_scan_subsystems(udev_enumerate);
372 test_enumerate_print_list(udev_enumerate);
373 udev_enumerate_unref(udev_enumerate);
375 printf("enumerate 'property IF_FS_*=filesystem'\n");
376 udev_enumerate = udev_enumerate_new(udev);
377 if (udev_enumerate == NULL)
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);
386 static void test_hwdb(struct udev *udev, const char *modalias) {
387 struct udev_hwdb *hwdb;
388 struct udev_list_entry *entry;
390 hwdb = udev_hwdb_new(udev);
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));
396 hwdb = udev_hwdb_unref(hwdb);
397 assert_se(hwdb == NULL);
400 int main(int argc, char *argv[]) {
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' },
410 const char *syspath = "/devices/virtual/mem/null";
411 const char *subsystem = NULL;
416 printf("context: %p\n", udev);
418 printf("no context\n");
422 while ((c = getopt_long(argc, argv, "p:s:dhV", options, NULL)) >= 0)
434 if (log_get_max_level() < LOG_INFO)
435 log_set_max_level(LOG_INFO);
439 printf("--debug --syspath= --subsystem= --help\n");
443 printf("%s\n", VERSION);
450 assert_not_reached("Unhandled option code.");
454 /* add sys path if needed */
455 if (!startswith(syspath, "/sys")) {
456 snprintf(path, sizeof(path), "/sys/%s", syspath);
460 test_device(udev, syspath);
461 test_device_devnum(udev);
462 test_device_subsys_name(udev);
463 test_device_parents(udev, syspath);
465 test_enumerate(udev, subsystem);
469 test_hwdb(udev, "usb:v0D50p0011*");