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