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