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