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/>.
29 #include <sys/epoll.h>
32 #include "udev-util.h"
35 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
37 static void print_device(struct udev_device *device) {
41 struct udev_list_entry *list_entry;
43 printf("*** device: %p ***\n", device);
44 str = udev_device_get_action(device);
46 printf("action: '%s'\n", str);
48 str = udev_device_get_syspath(device);
49 printf("syspath: '%s'\n", str);
51 str = udev_device_get_sysname(device);
52 printf("sysname: '%s'\n", str);
54 str = udev_device_get_sysnum(device);
56 printf("sysnum: '%s'\n", str);
58 str = udev_device_get_devpath(device);
59 printf("devpath: '%s'\n", str);
61 str = udev_device_get_subsystem(device);
63 printf("subsystem: '%s'\n", str);
65 str = udev_device_get_devtype(device);
67 printf("devtype: '%s'\n", str);
69 str = udev_device_get_driver(device);
71 printf("driver: '%s'\n", str);
73 str = udev_device_get_devnode(device);
75 printf("devname: '%s'\n", str);
77 devnum = udev_device_get_devnum(device);
78 if (major(devnum) > 0)
79 printf("devnum: %u:%u\n", major(devnum), minor(devnum));
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));
87 printf("found %i links\n", count);
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));
97 printf("found %i properties\n", count);
99 str = udev_device_get_property_value(device, "MAJOR");
101 printf("MAJOR: '%s'\n", str);
103 str = udev_device_get_sysattr_value(device, "dev");
105 printf("attr{dev}: '%s'\n", str);
110 static int test_device(struct udev *udev, const char *syspath) {
111 _cleanup_udev_device_unref_ struct udev_device *device;
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");
119 print_device(device);
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;
128 printf("looking at device: %s\n", syspath);
129 device = udev_device_new_from_syspath(udev, syspath);
133 printf("looking at parents\n");
134 device_parent = device;
136 print_device(device_parent);
137 device_parent = udev_device_get_parent(device_parent);
138 } while (device_parent != NULL);
140 printf("looking at parents again\n");
141 device_parent = device;
143 print_device(device_parent);
144 device_parent = udev_device_get_parent(device_parent);
145 } while (device_parent != NULL);
150 static int test_device_devnum(struct udev *udev) {
151 dev_t devnum = makedev(1, 3);
152 struct udev_device *device;
154 printf("looking up device: %u:%u\n", major(devnum), minor(devnum));
155 device = udev_device_new_from_devnum(udev, 'c', devnum);
158 print_device(device);
159 udev_device_unref(device);
163 static int test_device_subsys_name(struct udev *udev) {
164 struct udev_device *device;
166 printf("looking up device: 'block':'sda'\n");
167 device = udev_device_new_from_subsystem_sysname(udev, "block", "sda");
170 print_device(device);
171 udev_device_unref(device);
173 printf("looking up device: 'subsystem':'pci'\n");
174 device = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci");
177 print_device(device);
178 udev_device_unref(device);
180 printf("looking up device: 'drivers':'scsi:sd'\n");
181 device = udev_device_new_from_subsystem_sysname(udev, "drivers", "scsi:sd");
184 print_device(device);
185 udev_device_unref(device);
187 printf("looking up device: 'module':'printk'\n");
188 device = udev_device_new_from_subsystem_sysname(udev, "module", "printk");
191 print_device(device);
192 udev_device_unref(device);
196 static int test_enumerate_print_list(struct udev_enumerate *enumerate) {
197 struct udev_list_entry *list_entry;
200 udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
201 struct udev_device *device;
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);
213 printf("found %i devices\n\n", count);
217 static int test_monitor(struct udev *udev) {
218 struct udev_monitor *udev_monitor = NULL;
221 struct epoll_event ep_udev, ep_stdin;
223 fd_ep = epoll_create1(EPOLL_CLOEXEC);
225 printf("error creating epoll fd: %m\n");
229 udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
230 if (udev_monitor == NULL) {
231 printf("no socket\n");
234 fd_udev = udev_monitor_get_fd(udev_monitor);
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");
243 if (udev_monitor_enable_receiving(udev_monitor) < 0) {
244 printf("bind failed\n");
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");
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");
266 struct epoll_event ev[4];
267 struct udev_device *device;
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);
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");
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");
292 udev_monitor_unref(udev_monitor);
296 static int test_queue(struct udev *udev) {
297 struct udev_queue *udev_queue;
299 udev_queue = udev_queue_new(udev);
300 if (udev_queue == NULL)
303 if (udev_queue_get_queue_is_empty(udev_queue))
304 printf("queue is empty\n");
306 udev_queue_unref(udev_queue);
310 static int test_enumerate(struct udev *udev, const char *subsystem) {
311 struct udev_enumerate *udev_enumerate;
313 printf("enumerate '%s'\n", subsystem == NULL ? "<all>" : subsystem);
314 udev_enumerate = udev_enumerate_new(udev);
315 if (udev_enumerate == NULL)
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);
322 printf("enumerate 'net' + duplicated scan + null + zero\n");
323 udev_enumerate = udev_enumerate_new(udev);
324 if (udev_enumerate == NULL)
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);
342 printf("enumerate 'block'\n");
343 udev_enumerate = udev_enumerate_new(udev);
344 if (udev_enumerate == NULL)
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);
352 printf("enumerate 'not block'\n");
353 udev_enumerate = udev_enumerate_new(udev);
354 if (udev_enumerate == NULL)
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);
361 printf("enumerate 'pci, mem, vc'\n");
362 udev_enumerate = udev_enumerate_new(udev);
363 if (udev_enumerate == NULL)
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);
372 printf("enumerate 'subsystem'\n");
373 udev_enumerate = udev_enumerate_new(udev);
374 if (udev_enumerate == NULL)
376 udev_enumerate_scan_subsystems(udev_enumerate);
377 test_enumerate_print_list(udev_enumerate);
378 udev_enumerate_unref(udev_enumerate);
380 printf("enumerate 'property IF_FS_*=filesystem'\n");
381 udev_enumerate = udev_enumerate_new(udev);
382 if (udev_enumerate == NULL)
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);
391 static void test_hwdb(struct udev *udev, const char *modalias) {
392 struct udev_hwdb *hwdb;
393 struct udev_list_entry *entry;
395 hwdb = udev_hwdb_new(udev);
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));
401 hwdb = udev_hwdb_unref(hwdb);
402 assert_se(hwdb == NULL);
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' },
415 const char *syspath = "/devices/virtual/mem/null";
416 const char *subsystem = NULL;
421 printf("context: %p\n", udev);
423 printf("no context\n");
427 while ((c = getopt_long(argc, argv, "p:s:dhV", options, NULL)) >= 0)
439 if (log_get_max_level() < LOG_INFO)
440 log_set_max_level(LOG_INFO);
444 printf("--debug --syspath= --subsystem= --help\n");
448 printf("%s\n", VERSION);
455 assert_not_reached("Unhandled option code.");
459 /* add sys path if needed */
460 if (!startswith(syspath, "/sys")) {
461 snprintf(path, sizeof(path), "/sys/%s", syspath);
465 test_device(udev, syspath);
466 test_device_devnum(udev);
467 test_device_subsys_name(udev);
468 test_device_parents(udev, syspath);
470 test_enumerate(udev, subsystem);
474 test_hwdb(udev, "usb:v0D50p0011*");