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/>.
23 #include <sys/epoll.h>
28 #include "stdio-util.h"
29 #include "string-util.h"
30 #include "udev-util.h"
33 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
35 static void print_device(struct udev_device
*device
) {
39 struct udev_list_entry
*list_entry
;
41 printf("*** device: %p ***\n", device
);
42 str
= udev_device_get_action(device
);
44 printf("action: '%s'\n", str
);
46 str
= udev_device_get_syspath(device
);
47 printf("syspath: '%s'\n", str
);
49 str
= udev_device_get_sysname(device
);
50 printf("sysname: '%s'\n", str
);
52 str
= udev_device_get_sysnum(device
);
54 printf("sysnum: '%s'\n", str
);
56 str
= udev_device_get_devpath(device
);
57 printf("devpath: '%s'\n", str
);
59 str
= udev_device_get_subsystem(device
);
61 printf("subsystem: '%s'\n", str
);
63 str
= udev_device_get_devtype(device
);
65 printf("devtype: '%s'\n", str
);
67 str
= udev_device_get_driver(device
);
69 printf("driver: '%s'\n", str
);
71 str
= udev_device_get_devnode(device
);
73 printf("devname: '%s'\n", str
);
75 devnum
= udev_device_get_devnum(device
);
76 if (major(devnum
) > 0)
77 printf("devnum: %u:%u\n", major(devnum
), minor(devnum
));
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
));
85 printf("found %i links\n", count
);
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
));
95 printf("found %i properties\n", count
);
97 str
= udev_device_get_property_value(device
, "MAJOR");
99 printf("MAJOR: '%s'\n", str
);
101 str
= udev_device_get_sysattr_value(device
, "dev");
103 printf("attr{dev}: '%s'\n", str
);
108 static int test_device(struct udev
*udev
, const char *syspath
) {
109 _cleanup_udev_device_unref_
struct udev_device
*device
;
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");
117 print_device(device
);
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
;
126 printf("looking at device: %s\n", syspath
);
127 device
= udev_device_new_from_syspath(udev
, syspath
);
131 printf("looking at parents\n");
132 device_parent
= device
;
134 print_device(device_parent
);
135 device_parent
= udev_device_get_parent(device_parent
);
136 } while (device_parent
!= NULL
);
138 printf("looking at parents again\n");
139 device_parent
= device
;
141 print_device(device_parent
);
142 device_parent
= udev_device_get_parent(device_parent
);
143 } while (device_parent
!= NULL
);
148 static int test_device_devnum(struct udev
*udev
) {
149 dev_t devnum
= makedev(1, 3);
150 struct udev_device
*device
;
152 printf("looking up device: %u:%u\n", major(devnum
), minor(devnum
));
153 device
= udev_device_new_from_devnum(udev
, 'c', devnum
);
156 print_device(device
);
157 udev_device_unref(device
);
161 static int test_device_subsys_name(struct udev
*udev
) {
162 struct udev_device
*device
;
164 printf("looking up device: 'block':'sda'\n");
165 device
= udev_device_new_from_subsystem_sysname(udev
, "block", "sda");
168 print_device(device
);
169 udev_device_unref(device
);
171 printf("looking up device: 'subsystem':'pci'\n");
172 device
= udev_device_new_from_subsystem_sysname(udev
, "subsystem", "pci");
175 print_device(device
);
176 udev_device_unref(device
);
178 printf("looking up device: 'drivers':'scsi:sd'\n");
179 device
= udev_device_new_from_subsystem_sysname(udev
, "drivers", "scsi:sd");
182 print_device(device
);
183 udev_device_unref(device
);
185 printf("looking up device: 'module':'printk'\n");
186 device
= udev_device_new_from_subsystem_sysname(udev
, "module", "printk");
189 print_device(device
);
190 udev_device_unref(device
);
194 static int test_enumerate_print_list(struct udev_enumerate
*enumerate
) {
195 struct udev_list_entry
*list_entry
;
198 udev_list_entry_foreach(list_entry
, udev_enumerate_get_list_entry(enumerate
)) {
199 struct udev_device
*device
;
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
);
211 printf("found %i devices\n\n", count
);
215 static int test_monitor(struct udev
*udev
) {
216 struct udev_monitor
*udev_monitor
= NULL
;
219 struct epoll_event ep_udev
, ep_stdin
;
221 fd_ep
= epoll_create1(EPOLL_CLOEXEC
);
223 printf("error creating epoll fd: %m\n");
227 udev_monitor
= udev_monitor_new_from_netlink(udev
, "udev");
228 if (udev_monitor
== NULL
) {
229 printf("no socket\n");
232 fd_udev
= udev_monitor_get_fd(udev_monitor
);
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");
241 if (udev_monitor_enable_receiving(udev_monitor
) < 0) {
242 printf("bind failed\n");
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");
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");
264 struct epoll_event ev
[4];
265 struct udev_device
*device
;
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
);
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");
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");
290 udev_monitor_unref(udev_monitor
);
294 static int test_queue(struct udev
*udev
) {
295 struct udev_queue
*udev_queue
;
297 udev_queue
= udev_queue_new(udev
);
298 if (udev_queue
== NULL
)
301 if (udev_queue_get_queue_is_empty(udev_queue
))
302 printf("queue is empty\n");
304 udev_queue_unref(udev_queue
);
308 static int test_enumerate(struct udev
*udev
, const char *subsystem
) {
309 struct udev_enumerate
*udev_enumerate
;
312 printf("enumerate '%s'\n", subsystem
== NULL
? "<all>" : subsystem
);
313 udev_enumerate
= udev_enumerate_new(udev
);
314 if (udev_enumerate
== NULL
)
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
);
321 printf("enumerate 'net' + duplicated scan + null + zero\n");
322 udev_enumerate
= udev_enumerate_new(udev
);
323 if (udev_enumerate
== NULL
)
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
);
341 printf("enumerate 'block'\n");
342 udev_enumerate
= udev_enumerate_new(udev
);
343 if (udev_enumerate
== NULL
)
345 udev_enumerate_add_match_subsystem(udev_enumerate
,"block");
346 r
= udev_enumerate_add_match_is_initialized(udev_enumerate
);
348 udev_enumerate_unref(udev_enumerate
);
351 udev_enumerate_scan_devices(udev_enumerate
);
352 test_enumerate_print_list(udev_enumerate
);
353 udev_enumerate_unref(udev_enumerate
);
355 printf("enumerate 'not block'\n");
356 udev_enumerate
= udev_enumerate_new(udev
);
357 if (udev_enumerate
== NULL
)
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
);
364 printf("enumerate 'pci, mem, vc'\n");
365 udev_enumerate
= udev_enumerate_new(udev
);
366 if (udev_enumerate
== NULL
)
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
);
375 printf("enumerate 'subsystem'\n");
376 udev_enumerate
= udev_enumerate_new(udev
);
377 if (udev_enumerate
== NULL
)
379 udev_enumerate_scan_subsystems(udev_enumerate
);
380 test_enumerate_print_list(udev_enumerate
);
381 udev_enumerate_unref(udev_enumerate
);
383 printf("enumerate 'property IF_FS_*=filesystem'\n");
384 udev_enumerate
= udev_enumerate_new(udev
);
385 if (udev_enumerate
== NULL
)
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
);
394 static void test_hwdb(struct udev
*udev
, const char *modalias
) {
395 struct udev_hwdb
*hwdb
;
396 struct udev_list_entry
*entry
;
398 hwdb
= udev_hwdb_new(udev
);
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
));
404 hwdb
= udev_hwdb_unref(hwdb
);
405 assert_se(hwdb
== NULL
);
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' },
418 const char *syspath
= "/devices/virtual/mem/null";
419 const char *subsystem
= NULL
;
424 printf("context: %p\n", udev
);
426 printf("no context\n");
430 while ((c
= getopt_long(argc
, argv
, "p:s:dhV", options
, NULL
)) >= 0)
442 if (log_get_max_level() < LOG_INFO
)
443 log_set_max_level(LOG_INFO
);
447 printf("--debug --syspath= --subsystem= --help\n");
451 printf("%s\n", VERSION
);
458 assert_not_reached("Unhandled option code.");
462 /* add sys path if needed */
463 if (!startswith(syspath
, "/sys")) {
464 xsprintf(path
, "/sys/%s", syspath
);
468 test_device(udev
, syspath
);
469 test_device_devnum(udev
);
470 test_device_subsys_name(udev
);
471 test_device_parents(udev
, syspath
);
473 test_enumerate(udev
, subsystem
);
477 test_hwdb(udev
, "usb:v0D50p0011*");