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 "string-util.h"
29 #include "udev-util.h"
32 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
34 static void print_device(struct udev_device
*device
) {
38 struct udev_list_entry
*list_entry
;
40 printf("*** device: %p ***\n", device
);
41 str
= udev_device_get_action(device
);
43 printf("action: '%s'\n", str
);
45 str
= udev_device_get_syspath(device
);
46 printf("syspath: '%s'\n", str
);
48 str
= udev_device_get_sysname(device
);
49 printf("sysname: '%s'\n", str
);
51 str
= udev_device_get_sysnum(device
);
53 printf("sysnum: '%s'\n", str
);
55 str
= udev_device_get_devpath(device
);
56 printf("devpath: '%s'\n", str
);
58 str
= udev_device_get_subsystem(device
);
60 printf("subsystem: '%s'\n", str
);
62 str
= udev_device_get_devtype(device
);
64 printf("devtype: '%s'\n", str
);
66 str
= udev_device_get_driver(device
);
68 printf("driver: '%s'\n", str
);
70 str
= udev_device_get_devnode(device
);
72 printf("devname: '%s'\n", str
);
74 devnum
= udev_device_get_devnum(device
);
75 if (major(devnum
) > 0)
76 printf("devnum: %u:%u\n", major(devnum
), minor(devnum
));
79 udev_list_entry_foreach(list_entry
, udev_device_get_devlinks_list_entry(device
)) {
80 printf("link: '%s'\n", udev_list_entry_get_name(list_entry
));
84 printf("found %i links\n", count
);
87 udev_list_entry_foreach(list_entry
, udev_device_get_properties_list_entry(device
)) {
88 printf("property: '%s=%s'\n",
89 udev_list_entry_get_name(list_entry
),
90 udev_list_entry_get_value(list_entry
));
94 printf("found %i properties\n", count
);
96 str
= udev_device_get_property_value(device
, "MAJOR");
98 printf("MAJOR: '%s'\n", str
);
100 str
= udev_device_get_sysattr_value(device
, "dev");
102 printf("attr{dev}: '%s'\n", str
);
107 static int test_device(struct udev
*udev
, const char *syspath
) {
108 _cleanup_udev_device_unref_
struct udev_device
*device
;
110 printf("looking at device: %s\n", syspath
);
111 device
= udev_device_new_from_syspath(udev
, syspath
);
112 if (device
== NULL
) {
113 printf("no device found\n");
116 print_device(device
);
121 static int test_device_parents(struct udev
*udev
, const char *syspath
) {
122 _cleanup_udev_device_unref_
struct udev_device
*device
;
123 struct udev_device
*device_parent
;
125 printf("looking at device: %s\n", syspath
);
126 device
= udev_device_new_from_syspath(udev
, syspath
);
130 printf("looking at parents\n");
131 device_parent
= device
;
133 print_device(device_parent
);
134 device_parent
= udev_device_get_parent(device_parent
);
135 } while (device_parent
!= NULL
);
137 printf("looking at parents again\n");
138 device_parent
= device
;
140 print_device(device_parent
);
141 device_parent
= udev_device_get_parent(device_parent
);
142 } while (device_parent
!= NULL
);
147 static int test_device_devnum(struct udev
*udev
) {
148 dev_t devnum
= makedev(1, 3);
149 struct udev_device
*device
;
151 printf("looking up device: %u:%u\n", major(devnum
), minor(devnum
));
152 device
= udev_device_new_from_devnum(udev
, 'c', devnum
);
155 print_device(device
);
156 udev_device_unref(device
);
160 static int test_device_subsys_name(struct udev
*udev
) {
161 struct udev_device
*device
;
163 printf("looking up device: 'block':'sda'\n");
164 device
= udev_device_new_from_subsystem_sysname(udev
, "block", "sda");
167 print_device(device
);
168 udev_device_unref(device
);
170 printf("looking up device: 'subsystem':'pci'\n");
171 device
= udev_device_new_from_subsystem_sysname(udev
, "subsystem", "pci");
174 print_device(device
);
175 udev_device_unref(device
);
177 printf("looking up device: 'drivers':'scsi:sd'\n");
178 device
= udev_device_new_from_subsystem_sysname(udev
, "drivers", "scsi:sd");
181 print_device(device
);
182 udev_device_unref(device
);
184 printf("looking up device: 'module':'printk'\n");
185 device
= udev_device_new_from_subsystem_sysname(udev
, "module", "printk");
188 print_device(device
);
189 udev_device_unref(device
);
193 static int test_enumerate_print_list(struct udev_enumerate
*enumerate
) {
194 struct udev_list_entry
*list_entry
;
197 udev_list_entry_foreach(list_entry
, udev_enumerate_get_list_entry(enumerate
)) {
198 struct udev_device
*device
;
200 device
= udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate
),
201 udev_list_entry_get_name(list_entry
));
202 if (device
!= NULL
) {
203 printf("device: '%s' (%s)\n",
204 udev_device_get_syspath(device
),
205 udev_device_get_subsystem(device
));
206 udev_device_unref(device
);
210 printf("found %i devices\n\n", count
);
214 static int test_monitor(struct udev
*udev
) {
215 struct udev_monitor
*udev_monitor
= NULL
;
218 struct epoll_event ep_udev
, ep_stdin
;
220 fd_ep
= epoll_create1(EPOLL_CLOEXEC
);
222 printf("error creating epoll fd: %m\n");
226 udev_monitor
= udev_monitor_new_from_netlink(udev
, "udev");
227 if (udev_monitor
== NULL
) {
228 printf("no socket\n");
231 fd_udev
= udev_monitor_get_fd(udev_monitor
);
233 if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor
, "block", NULL
) < 0 ||
234 udev_monitor_filter_add_match_subsystem_devtype(udev_monitor
, "tty", NULL
) < 0 ||
235 udev_monitor_filter_add_match_subsystem_devtype(udev_monitor
, "usb", "usb_device") < 0) {
236 printf("filter failed\n");
240 if (udev_monitor_enable_receiving(udev_monitor
) < 0) {
241 printf("bind failed\n");
245 memzero(&ep_udev
, sizeof(struct epoll_event
));
246 ep_udev
.events
= EPOLLIN
;
247 ep_udev
.data
.fd
= fd_udev
;
248 if (epoll_ctl(fd_ep
, EPOLL_CTL_ADD
, fd_udev
, &ep_udev
) < 0) {
249 printf("fail to add fd to epoll: %m\n");
253 memzero(&ep_stdin
, sizeof(struct epoll_event
));
254 ep_stdin
.events
= EPOLLIN
;
255 ep_stdin
.data
.fd
= STDIN_FILENO
;
256 if (epoll_ctl(fd_ep
, EPOLL_CTL_ADD
, STDIN_FILENO
, &ep_stdin
) < 0) {
257 printf("fail to add fd to epoll: %m\n");
263 struct epoll_event ev
[4];
264 struct udev_device
*device
;
267 printf("waiting for events from udev, press ENTER to exit\n");
268 fdcount
= epoll_wait(fd_ep
, ev
, ARRAY_SIZE(ev
), -1);
269 printf("epoll fd count: %i\n", fdcount
);
271 for (i
= 0; i
< fdcount
; i
++) {
272 if (ev
[i
].data
.fd
== fd_udev
&& ev
[i
].events
& EPOLLIN
) {
273 device
= udev_monitor_receive_device(udev_monitor
);
274 if (device
== NULL
) {
275 printf("no device from socket\n");
278 print_device(device
);
279 udev_device_unref(device
);
280 } else if (ev
[i
].data
.fd
== STDIN_FILENO
&& ev
[i
].events
& EPOLLIN
) {
281 printf("exiting loop\n");
289 udev_monitor_unref(udev_monitor
);
293 static int test_queue(struct udev
*udev
) {
294 struct udev_queue
*udev_queue
;
296 udev_queue
= udev_queue_new(udev
);
297 if (udev_queue
== NULL
)
300 if (udev_queue_get_queue_is_empty(udev_queue
))
301 printf("queue is empty\n");
303 udev_queue_unref(udev_queue
);
307 static int test_enumerate(struct udev
*udev
, const char *subsystem
) {
308 struct udev_enumerate
*udev_enumerate
;
311 printf("enumerate '%s'\n", subsystem
== NULL
? "<all>" : subsystem
);
312 udev_enumerate
= udev_enumerate_new(udev
);
313 if (udev_enumerate
== NULL
)
315 udev_enumerate_add_match_subsystem(udev_enumerate
, subsystem
);
316 udev_enumerate_scan_devices(udev_enumerate
);
317 test_enumerate_print_list(udev_enumerate
);
318 udev_enumerate_unref(udev_enumerate
);
320 printf("enumerate 'net' + duplicated scan + null + zero\n");
321 udev_enumerate
= udev_enumerate_new(udev
);
322 if (udev_enumerate
== NULL
)
324 udev_enumerate_add_match_subsystem(udev_enumerate
, "net");
325 udev_enumerate_scan_devices(udev_enumerate
);
326 udev_enumerate_scan_devices(udev_enumerate
);
327 udev_enumerate_add_syspath(udev_enumerate
, "/sys/class/mem/zero");
328 udev_enumerate_add_syspath(udev_enumerate
, "/sys/class/mem/null");
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/null");
334 udev_enumerate_add_syspath(udev_enumerate
, "/sys/class/mem/zero");
335 udev_enumerate_add_syspath(udev_enumerate
, "/sys/class/mem/zero");
336 udev_enumerate_scan_devices(udev_enumerate
);
337 test_enumerate_print_list(udev_enumerate
);
338 udev_enumerate_unref(udev_enumerate
);
340 printf("enumerate 'block'\n");
341 udev_enumerate
= udev_enumerate_new(udev
);
342 if (udev_enumerate
== NULL
)
344 udev_enumerate_add_match_subsystem(udev_enumerate
,"block");
345 r
= udev_enumerate_add_match_is_initialized(udev_enumerate
);
347 udev_enumerate_unref(udev_enumerate
);
350 udev_enumerate_scan_devices(udev_enumerate
);
351 test_enumerate_print_list(udev_enumerate
);
352 udev_enumerate_unref(udev_enumerate
);
354 printf("enumerate 'not block'\n");
355 udev_enumerate
= udev_enumerate_new(udev
);
356 if (udev_enumerate
== NULL
)
358 udev_enumerate_add_nomatch_subsystem(udev_enumerate
, "block");
359 udev_enumerate_scan_devices(udev_enumerate
);
360 test_enumerate_print_list(udev_enumerate
);
361 udev_enumerate_unref(udev_enumerate
);
363 printf("enumerate 'pci, mem, vc'\n");
364 udev_enumerate
= udev_enumerate_new(udev
);
365 if (udev_enumerate
== NULL
)
367 udev_enumerate_add_match_subsystem(udev_enumerate
, "pci");
368 udev_enumerate_add_match_subsystem(udev_enumerate
, "mem");
369 udev_enumerate_add_match_subsystem(udev_enumerate
, "vc");
370 udev_enumerate_scan_devices(udev_enumerate
);
371 test_enumerate_print_list(udev_enumerate
);
372 udev_enumerate_unref(udev_enumerate
);
374 printf("enumerate 'subsystem'\n");
375 udev_enumerate
= udev_enumerate_new(udev
);
376 if (udev_enumerate
== NULL
)
378 udev_enumerate_scan_subsystems(udev_enumerate
);
379 test_enumerate_print_list(udev_enumerate
);
380 udev_enumerate_unref(udev_enumerate
);
382 printf("enumerate 'property IF_FS_*=filesystem'\n");
383 udev_enumerate
= udev_enumerate_new(udev
);
384 if (udev_enumerate
== NULL
)
386 udev_enumerate_add_match_property(udev_enumerate
, "ID_FS*", "filesystem");
387 udev_enumerate_scan_devices(udev_enumerate
);
388 test_enumerate_print_list(udev_enumerate
);
389 udev_enumerate_unref(udev_enumerate
);
393 static void test_hwdb(struct udev
*udev
, const char *modalias
) {
394 struct udev_hwdb
*hwdb
;
395 struct udev_list_entry
*entry
;
397 hwdb
= udev_hwdb_new(udev
);
399 udev_list_entry_foreach(entry
, udev_hwdb_get_properties_list_entry(hwdb
, modalias
, 0))
400 printf("'%s'='%s'\n", udev_list_entry_get_name(entry
), udev_list_entry_get_value(entry
));
403 hwdb
= udev_hwdb_unref(hwdb
);
404 assert_se(hwdb
== NULL
);
407 int main(int argc
, char *argv
[]) {
408 struct udev
*udev
= NULL
;
409 static const struct option options
[] = {
410 { "syspath", required_argument
, NULL
, 'p' },
411 { "subsystem", required_argument
, NULL
, 's' },
412 { "debug", no_argument
, NULL
, 'd' },
413 { "help", no_argument
, NULL
, 'h' },
414 { "version", no_argument
, NULL
, 'V' },
417 const char *syspath
= "/devices/virtual/mem/null";
418 const char *subsystem
= NULL
;
423 printf("context: %p\n", udev
);
425 printf("no context\n");
429 while ((c
= getopt_long(argc
, argv
, "p:s:dhV", options
, NULL
)) >= 0)
441 if (log_get_max_level() < LOG_INFO
)
442 log_set_max_level(LOG_INFO
);
446 printf("--debug --syspath= --subsystem= --help\n");
450 printf("%s\n", VERSION
);
457 assert_not_reached("Unhandled option code.");
461 /* add sys path if needed */
462 if (!startswith(syspath
, "/sys")) {
463 snprintf(path
, sizeof(path
), "/sys/%s", syspath
);
467 test_device(udev
, syspath
);
468 test_device_devnum(udev
);
469 test_device_subsys_name(udev
);
470 test_device_parents(udev
, syspath
);
472 test_enumerate(udev
, subsystem
);
476 test_hwdb(udev
, "usb:v0D50p0011*");