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