LCOV - code coverage report
Current view: top level - udev - udevadm-monitor.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 137 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0+ */
       2             : 
       3             : #include <errno.h>
       4             : #include <getopt.h>
       5             : #include <signal.h>
       6             : 
       7             : #include "sd-device.h"
       8             : #include "sd-event.h"
       9             : 
      10             : #include "alloc-util.h"
      11             : #include "device-monitor-private.h"
      12             : #include "device-private.h"
      13             : #include "device-util.h"
      14             : #include "fd-util.h"
      15             : #include "format-util.h"
      16             : #include "hashmap.h"
      17             : #include "set.h"
      18             : #include "signal-util.h"
      19             : #include "string-util.h"
      20             : #include "udevadm.h"
      21             : #include "virt.h"
      22             : #include "time-util.h"
      23             : 
      24             : static bool arg_show_property = false;
      25             : static bool arg_print_kernel = false;
      26             : static bool arg_print_udev = false;
      27             : static Set *arg_tag_filter = NULL;
      28             : static Hashmap *arg_subsystem_filter = NULL;
      29             : 
      30           0 : static int device_monitor_handler(sd_device_monitor *monitor, sd_device *device, void *userdata) {
      31           0 :         DeviceAction action = _DEVICE_ACTION_INVALID;
      32           0 :         const char *devpath = NULL, *subsystem = NULL;
      33           0 :         MonitorNetlinkGroup group = PTR_TO_INT(userdata);
      34             :         struct timespec ts;
      35             : 
      36           0 :         assert(device);
      37           0 :         assert(IN_SET(group, MONITOR_GROUP_UDEV, MONITOR_GROUP_KERNEL));
      38             : 
      39           0 :         (void) device_get_action(device, &action);
      40           0 :         (void) sd_device_get_devpath(device, &devpath);
      41           0 :         (void) sd_device_get_subsystem(device, &subsystem);
      42             : 
      43           0 :         assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
      44             : 
      45           0 :         printf("%-6s[%"PRI_TIME".%06"PRI_NSEC"] %-8s %s (%s)\n",
      46             :                group == MONITOR_GROUP_UDEV ? "UDEV" : "KERNEL",
      47           0 :                ts.tv_sec, (nsec_t)ts.tv_nsec/1000,
      48             :                strna(device_action_to_string(action)),
      49             :                devpath, subsystem);
      50             : 
      51           0 :         if (arg_show_property) {
      52             :                 const char *key, *value;
      53             : 
      54           0 :                 FOREACH_DEVICE_PROPERTY(device, key, value)
      55           0 :                         printf("%s=%s\n", key, value);
      56             : 
      57           0 :                 printf("\n");
      58             :         }
      59             : 
      60           0 :         return 0;
      61             : }
      62             : 
      63           0 : static int setup_monitor(MonitorNetlinkGroup sender, sd_event *event, sd_device_monitor **ret) {
      64           0 :         _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
      65             :         const char *subsystem, *devtype, *tag;
      66             :         Iterator i;
      67             :         int r;
      68             : 
      69           0 :         r = device_monitor_new_full(&monitor, sender, -1);
      70           0 :         if (r < 0)
      71           0 :                 return log_error_errno(r, "Failed to create netlink socket: %m");
      72             : 
      73           0 :         (void) sd_device_monitor_set_receive_buffer_size(monitor, 128*1024*1024);
      74             : 
      75           0 :         r = sd_device_monitor_attach_event(monitor, event);
      76           0 :         if (r < 0)
      77           0 :                 return log_error_errno(r, "Failed to attach event: %m");
      78             : 
      79           0 :         HASHMAP_FOREACH_KEY(devtype, subsystem, arg_subsystem_filter, i) {
      80           0 :                 r = sd_device_monitor_filter_add_match_subsystem_devtype(monitor, subsystem, devtype);
      81           0 :                 if (r < 0)
      82           0 :                         return log_error_errno(r, "Failed to apply subsystem filter '%s%s%s': %m",
      83             :                                                subsystem, devtype ? "/" : "", strempty(devtype));
      84             :         }
      85             : 
      86           0 :         SET_FOREACH(tag, arg_tag_filter, i) {
      87           0 :                 r = sd_device_monitor_filter_add_match_tag(monitor, tag);
      88           0 :                 if (r < 0)
      89           0 :                         return log_error_errno(r, "Failed to apply tag filter '%s': %m", tag);
      90             :         }
      91             : 
      92           0 :         r = sd_device_monitor_start(monitor, device_monitor_handler, INT_TO_PTR(sender));
      93           0 :         if (r < 0)
      94           0 :                 return log_error_errno(r, "Failed to start device monitor: %m");
      95             : 
      96           0 :         (void) sd_event_source_set_description(sd_device_monitor_get_event_source(monitor),
      97             :                                                sender == MONITOR_GROUP_UDEV ? "device-monitor-udev" : "device-monitor-kernel");
      98             : 
      99           0 :         *ret = TAKE_PTR(monitor);
     100           0 :         return 0;
     101             : }
     102             : 
     103           0 : static int help(void) {
     104           0 :         printf("%s monitor [OPTIONS]\n\n"
     105             :                "Listen to kernel and udev events.\n\n"
     106             :                "  -h --help                                Show this help\n"
     107             :                "  -V --version                             Show package version\n"
     108             :                "  -p --property                            Print the event properties\n"
     109             :                "  -k --kernel                              Print kernel uevents\n"
     110             :                "  -u --udev                                Print udev events\n"
     111             :                "  -s --subsystem-match=SUBSYSTEM[/DEVTYPE] Filter events by subsystem\n"
     112             :                "  -t --tag-match=TAG                       Filter events by tag\n"
     113             :                , program_invocation_short_name);
     114             : 
     115           0 :         return 0;
     116             : }
     117             : 
     118           0 : static int parse_argv(int argc, char *argv[]) {
     119             :         static const struct option options[] = {
     120             :                 { "property",        no_argument,       NULL, 'p' },
     121             :                 { "environment",     no_argument,       NULL, 'e' }, /* alias for -p */
     122             :                 { "kernel",          no_argument,       NULL, 'k' },
     123             :                 { "udev",            no_argument,       NULL, 'u' },
     124             :                 { "subsystem-match", required_argument, NULL, 's' },
     125             :                 { "tag-match",       required_argument, NULL, 't' },
     126             :                 { "version",         no_argument,       NULL, 'V' },
     127             :                 { "help",            no_argument,       NULL, 'h' },
     128             :                 {}
     129             :         };
     130             : 
     131             :         int r, c;
     132             : 
     133           0 :         while ((c = getopt_long(argc, argv, "pekus:t:Vh", options, NULL)) >= 0)
     134           0 :                 switch (c) {
     135           0 :                 case 'p':
     136             :                 case 'e':
     137           0 :                         arg_show_property = true;
     138           0 :                         break;
     139           0 :                 case 'k':
     140           0 :                         arg_print_kernel = true;
     141           0 :                         break;
     142           0 :                 case 'u':
     143           0 :                         arg_print_udev = true;
     144           0 :                         break;
     145           0 :                 case 's': {
     146           0 :                         _cleanup_free_ char *subsystem = NULL, *devtype = NULL;
     147             :                         const char *slash;
     148             : 
     149           0 :                         slash = strchr(optarg, '/');
     150           0 :                         if (slash) {
     151           0 :                                 devtype = strdup(slash + 1);
     152           0 :                                 if (!devtype)
     153           0 :                                         return -ENOMEM;
     154             : 
     155           0 :                                 subsystem = strndup(optarg, slash - optarg);
     156             :                         } else
     157           0 :                                 subsystem = strdup(optarg);
     158             : 
     159           0 :                         if (!subsystem)
     160           0 :                                 return -ENOMEM;
     161             : 
     162           0 :                         r = hashmap_ensure_allocated(&arg_subsystem_filter, NULL);
     163           0 :                         if (r < 0)
     164           0 :                                 return r;
     165             : 
     166           0 :                         r = hashmap_put(arg_subsystem_filter, subsystem, devtype);
     167           0 :                         if (r < 0)
     168           0 :                                 return r;
     169             : 
     170           0 :                         subsystem = devtype = NULL;
     171           0 :                         break;
     172             :                 }
     173           0 :                 case 't': {
     174           0 :                         _cleanup_free_ char *tag = NULL;
     175             : 
     176           0 :                         r = set_ensure_allocated(&arg_tag_filter, &string_hash_ops);
     177           0 :                         if (r < 0)
     178           0 :                                 return r;
     179             : 
     180           0 :                         tag = strdup(optarg);
     181           0 :                         if (!tag)
     182           0 :                                 return -ENOMEM;
     183             : 
     184           0 :                         r = set_put(arg_tag_filter, tag);
     185           0 :                         if (r < 0)
     186           0 :                                 return r;
     187             : 
     188           0 :                         tag = NULL;
     189           0 :                         break;
     190             :                 }
     191           0 :                 case 'V':
     192           0 :                         return print_version();
     193           0 :                 case 'h':
     194           0 :                         return help();
     195           0 :                 case '?':
     196           0 :                         return -EINVAL;
     197           0 :                 default:
     198           0 :                         assert_not_reached("Unknown option.");
     199             :                 }
     200             : 
     201           0 :         if (!arg_print_kernel && !arg_print_udev) {
     202           0 :                 arg_print_kernel = true;
     203           0 :                 arg_print_udev = true;
     204             :         }
     205             : 
     206           0 :         return 1;
     207             : }
     208             : 
     209           0 : int monitor_main(int argc, char *argv[], void *userdata) {
     210           0 :         _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *kernel_monitor = NULL, *udev_monitor = NULL;
     211           0 :         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
     212             :         int r;
     213             : 
     214           0 :         r = parse_argv(argc, argv);
     215           0 :         if (r <= 0)
     216           0 :                 goto finalize;
     217             : 
     218           0 :         if (running_in_chroot() > 0) {
     219           0 :                 log_info("Running in chroot, ignoring request.");
     220           0 :                 return 0;
     221             :         }
     222             : 
     223             :         /* Callers are expecting to see events as they happen: Line buffering */
     224           0 :         setlinebuf(stdout);
     225             : 
     226           0 :         r = sd_event_default(&event);
     227           0 :         if (r < 0) {
     228           0 :                 log_error_errno(r, "Failed to initialize event: %m");
     229           0 :                 goto finalize;
     230             :         }
     231             : 
     232           0 :         assert_se(sigprocmask_many(SIG_UNBLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
     233           0 :         (void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
     234           0 :         (void) sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
     235             : 
     236           0 :         printf("monitor will print the received events for:\n");
     237           0 :         if (arg_print_udev) {
     238           0 :                 r = setup_monitor(MONITOR_GROUP_UDEV, event, &udev_monitor);
     239           0 :                 if (r < 0)
     240           0 :                         goto finalize;
     241             : 
     242           0 :                 printf("UDEV - the event which udev sends out after rule processing\n");
     243             :         }
     244             : 
     245           0 :         if (arg_print_kernel) {
     246           0 :                 r = setup_monitor(MONITOR_GROUP_KERNEL, event, &kernel_monitor);
     247           0 :                 if (r < 0)
     248           0 :                         goto finalize;
     249             : 
     250           0 :                 printf("KERNEL - the kernel uevent\n");
     251             :         }
     252           0 :         printf("\n");
     253             : 
     254           0 :         r = sd_event_loop(event);
     255           0 :         if (r < 0) {
     256           0 :                 log_error_errno(r, "Failed to run event loop: %m");
     257           0 :                 goto finalize;
     258             :         }
     259             : 
     260           0 :         r = 0;
     261             : 
     262           0 : finalize:
     263           0 :         hashmap_free_free_free(arg_subsystem_filter);
     264           0 :         set_free_free(arg_tag_filter);
     265             : 
     266           0 :         return r;
     267             : }

Generated by: LCOV version 1.14