chiark / gitweb /
load-fragment: remove wrong ifdef guard
[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 static void print_device(struct udev_device *device) {
38         const char *str;
39         dev_t devnum;
40         int count;
41         struct udev_list_entry *list_entry;
42
43         printf("*** device: %p ***\n", device);
44         str = udev_device_get_action(device);
45         if (str != NULL)
46                 printf("action:    '%s'\n", str);
47
48         str = udev_device_get_syspath(device);
49         printf("syspath:   '%s'\n", str);
50
51         str = udev_device_get_sysname(device);
52         printf("sysname:   '%s'\n", str);
53
54         str = udev_device_get_sysnum(device);
55         if (str != NULL)
56                 printf("sysnum:    '%s'\n", str);
57
58         str = udev_device_get_devpath(device);
59         printf("devpath:   '%s'\n", str);
60
61         str = udev_device_get_subsystem(device);
62         if (str != NULL)
63                 printf("subsystem: '%s'\n", str);
64
65         str = udev_device_get_devtype(device);
66         if (str != NULL)
67                 printf("devtype:   '%s'\n", str);
68
69         str = udev_device_get_driver(device);
70         if (str != NULL)
71                 printf("driver:    '%s'\n", str);
72
73         str = udev_device_get_devnode(device);
74         if (str != NULL)
75                 printf("devname:   '%s'\n", str);
76
77         devnum = udev_device_get_devnum(device);
78         if (major(devnum) > 0)
79                 printf("devnum:    %u:%u\n", major(devnum), minor(devnum));
80
81         count = 0;
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));
84                 count++;
85         }
86         if (count > 0)
87                 printf("found %i links\n", count);
88
89         count = 0;
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));
94                 count++;
95         }
96         if (count > 0)
97                 printf("found %i properties\n", count);
98
99         str = udev_device_get_property_value(device, "MAJOR");
100         if (str != NULL)
101                 printf("MAJOR: '%s'\n", str);
102
103         str = udev_device_get_sysattr_value(device, "dev");
104         if (str != NULL)
105                 printf("attr{dev}: '%s'\n", str);
106
107         printf("\n");
108 }
109
110 static int test_device(struct udev *udev, const char *syspath) {
111         _cleanup_udev_device_unref_ struct udev_device *device;
112
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");
117                 return -1;
118         }
119         print_device(device);
120
121         return 0;
122 }
123
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;
127
128         printf("looking at device: %s\n", syspath);
129         device = udev_device_new_from_syspath(udev, syspath);
130         if (device == NULL)
131                 return -1;
132
133         printf("looking at parents\n");
134         device_parent = device;
135         do {
136                 print_device(device_parent);
137                 device_parent = udev_device_get_parent(device_parent);
138         } while (device_parent != NULL);
139
140         printf("looking at parents again\n");
141         device_parent = device;
142         do {
143                 print_device(device_parent);
144                 device_parent = udev_device_get_parent(device_parent);
145         } while (device_parent != NULL);
146
147         return 0;
148 }
149
150 static int test_device_devnum(struct udev *udev) {
151         dev_t devnum = makedev(1, 3);
152         struct udev_device *device;
153
154         printf("looking up device: %u:%u\n", major(devnum), minor(devnum));
155         device = udev_device_new_from_devnum(udev, 'c', devnum);
156         if (device == NULL)
157                 return -1;
158         print_device(device);
159         udev_device_unref(device);
160         return 0;
161 }
162
163 static int test_device_subsys_name(struct udev *udev) {
164         struct udev_device *device;
165
166         printf("looking up device: 'block':'sda'\n");
167         device = udev_device_new_from_subsystem_sysname(udev, "block", "sda");
168         if (device == NULL)
169                 return -1;
170         print_device(device);
171         udev_device_unref(device);
172
173         printf("looking up device: 'subsystem':'pci'\n");
174         device = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci");
175         if (device == NULL)
176                 return -1;
177         print_device(device);
178         udev_device_unref(device);
179
180         printf("looking up device: 'drivers':'scsi:sd'\n");
181         device = udev_device_new_from_subsystem_sysname(udev, "drivers", "scsi:sd");
182         if (device == NULL)
183                 return -1;
184         print_device(device);
185         udev_device_unref(device);
186
187         printf("looking up device: 'module':'printk'\n");
188         device = udev_device_new_from_subsystem_sysname(udev, "module", "printk");
189         if (device == NULL)
190                 return -1;
191         print_device(device);
192         udev_device_unref(device);
193         return 0;
194 }
195
196 static int test_enumerate_print_list(struct udev_enumerate *enumerate) {
197         struct udev_list_entry *list_entry;
198         int count = 0;
199
200         udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
201                 struct udev_device *device;
202
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);
210                         count++;
211                 }
212         }
213         printf("found %i devices\n\n", count);
214         return count;
215 }
216
217 static int test_monitor(struct udev *udev) {
218         struct udev_monitor *udev_monitor = NULL;
219         int fd_ep;
220         int fd_udev = -1;
221         struct epoll_event ep_udev, ep_stdin;
222
223         fd_ep = epoll_create1(EPOLL_CLOEXEC);
224         if (fd_ep < 0) {
225                 printf("error creating epoll fd: %m\n");
226                 goto out;
227         }
228
229         udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
230         if (udev_monitor == NULL) {
231                 printf("no socket\n");
232                 goto out;
233         }
234         fd_udev = udev_monitor_get_fd(udev_monitor);
235
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");
240                 goto out;
241         }
242
243         if (udev_monitor_enable_receiving(udev_monitor) < 0) {
244                 printf("bind failed\n");
245                 goto out;
246         }
247
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");
253                 goto out;
254         }
255
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");
261                 goto out;
262         }
263
264         for (;;) {
265                 int fdcount;
266                 struct epoll_event ev[4];
267                 struct udev_device *device;
268                 int i;
269
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);
273
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");
279                                         continue;
280                                 }
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");
285                                 goto out;
286                         }
287                 }
288         }
289 out:
290         if (fd_ep >= 0)
291                 close(fd_ep);
292         udev_monitor_unref(udev_monitor);
293         return 0;
294 }
295
296 static int test_queue(struct udev *udev) {
297         struct udev_queue *udev_queue;
298
299         udev_queue = udev_queue_new(udev);
300         if (udev_queue == NULL)
301                 return -1;
302
303         if (udev_queue_get_queue_is_empty(udev_queue))
304                 printf("queue is empty\n");
305
306         udev_queue_unref(udev_queue);
307         return 0;
308 }
309
310 static int test_enumerate(struct udev *udev, const char *subsystem) {
311         struct udev_enumerate *udev_enumerate;
312
313         printf("enumerate '%s'\n", subsystem == NULL ? "<all>" : subsystem);
314         udev_enumerate = udev_enumerate_new(udev);
315         if (udev_enumerate == NULL)
316                 return -1;
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);
321
322         printf("enumerate 'net' + duplicated scan + null + zero\n");
323         udev_enumerate = udev_enumerate_new(udev);
324         if (udev_enumerate == NULL)
325                 return -1;
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);
341
342         printf("enumerate 'block'\n");
343         udev_enumerate = udev_enumerate_new(udev);
344         if (udev_enumerate == NULL)
345                 return -1;
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);
351
352         printf("enumerate 'not block'\n");
353         udev_enumerate = udev_enumerate_new(udev);
354         if (udev_enumerate == NULL)
355                 return -1;
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);
360
361         printf("enumerate 'pci, mem, vc'\n");
362         udev_enumerate = udev_enumerate_new(udev);
363         if (udev_enumerate == NULL)
364                 return -1;
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);
371
372         printf("enumerate 'subsystem'\n");
373         udev_enumerate = udev_enumerate_new(udev);
374         if (udev_enumerate == NULL)
375                 return -1;
376         udev_enumerate_scan_subsystems(udev_enumerate);
377         test_enumerate_print_list(udev_enumerate);
378         udev_enumerate_unref(udev_enumerate);
379
380         printf("enumerate 'property IF_FS_*=filesystem'\n");
381         udev_enumerate = udev_enumerate_new(udev);
382         if (udev_enumerate == NULL)
383                 return -1;
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);
388         return 0;
389 }
390
391 static void test_hwdb(struct udev *udev, const char *modalias) {
392         struct udev_hwdb *hwdb;
393         struct udev_list_entry *entry;
394
395         hwdb = udev_hwdb_new(udev);
396
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));
399         printf("\n");
400
401         hwdb = udev_hwdb_unref(hwdb);
402         assert_se(hwdb == NULL);
403 }
404
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' },
413                 {}
414         };
415         const char *syspath = "/devices/virtual/mem/null";
416         const char *subsystem = NULL;
417         char path[1024];
418         int c;
419
420         udev = udev_new();
421         printf("context: %p\n", udev);
422         if (udev == NULL) {
423                 printf("no context\n");
424                 return 1;
425         }
426
427         while ((c = getopt_long(argc, argv, "p:s:dhV", options, NULL)) >= 0)
428                 switch (c) {
429
430                 case 'p':
431                         syspath = optarg;
432                         break;
433
434                 case 's':
435                         subsystem = optarg;
436                         break;
437
438                 case 'd':
439                         if (log_get_max_level() < LOG_INFO)
440                                 log_set_max_level(LOG_INFO);
441                         break;
442
443                 case 'h':
444                         printf("--debug --syspath= --subsystem= --help\n");
445                         goto out;
446
447                 case 'V':
448                         printf("%s\n", VERSION);
449                         goto out;
450
451                 case '?':
452                         goto out;
453
454                 default:
455                         assert_not_reached("Unhandled option code.");
456                 }
457
458
459         /* add sys path if needed */
460         if (!startswith(syspath, "/sys")) {
461                 snprintf(path, sizeof(path), "/sys/%s", syspath);
462                 syspath = path;
463         }
464
465         test_device(udev, syspath);
466         test_device_devnum(udev);
467         test_device_subsys_name(udev);
468         test_device_parents(udev, syspath);
469
470         test_enumerate(udev, subsystem);
471
472         test_queue(udev);
473
474         test_hwdb(udev, "usb:v0D50p0011*");
475
476         test_monitor(udev);
477 out:
478         udev_unref(udev);
479         return 0;
480 }