LCOV - code coverage report
Current view: top level - udev - udev-watch.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 90 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             :  * Copyright © 2009 Canonical Ltd.
       4             :  * Copyright © 2009 Scott James Remnant <scott@netsplit.com>
       5             :  */
       6             : 
       7             : #include <sys/inotify.h>
       8             : #include <unistd.h>
       9             : 
      10             : #include "alloc-util.h"
      11             : #include "device-private.h"
      12             : #include "device-util.h"
      13             : #include "dirent-util.h"
      14             : #include "fs-util.h"
      15             : #include "mkdir.h"
      16             : #include "stdio-util.h"
      17             : #include "udev-watch.h"
      18             : 
      19             : static int inotify_fd = -1;
      20             : 
      21             : /* inotify descriptor, will be shared with rules directory;
      22             :  * set to cloexec since we need our children to be able to add
      23             :  * watches for us. */
      24           0 : int udev_watch_init(void) {
      25           0 :         inotify_fd = inotify_init1(IN_CLOEXEC);
      26           0 :         if (inotify_fd < 0)
      27           0 :                 return -errno;
      28             : 
      29           0 :         return inotify_fd;
      30             : }
      31             : 
      32             : /* Move any old watches directory out of the way, and then restore the watches. */
      33           0 : int udev_watch_restore(void) {
      34             :         struct dirent *ent;
      35             :         DIR *dir;
      36             :         int r;
      37             : 
      38           0 :         if (inotify_fd < 0)
      39           0 :                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
      40             :                                        "Invalid inotify descriptor.");
      41             : 
      42           0 :         if (rename("/run/udev/watch", "/run/udev/watch.old") < 0) {
      43           0 :                 if (errno != ENOENT)
      44           0 :                         return log_warning_errno(errno, "Failed to move watches directory /run/udev/watch. Old watches will not be restored: %m");
      45             : 
      46           0 :                 return 0;
      47             :         }
      48             : 
      49           0 :         dir = opendir("/run/udev/watch.old");
      50           0 :         if (!dir)
      51           0 :                 return log_warning_errno(errno, "Failed to open old watches directory /run/udev/watch.old. Old watches will not be restored: %m");
      52             : 
      53           0 :         FOREACH_DIRENT_ALL(ent, dir, break) {
      54           0 :                 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
      55           0 :                 _cleanup_free_ char *device = NULL;
      56             : 
      57           0 :                 if (ent->d_name[0] == '.')
      58           0 :                         continue;
      59             : 
      60           0 :                 r = readlinkat_malloc(dirfd(dir), ent->d_name, &device);
      61           0 :                 if (r < 0) {
      62           0 :                         log_debug_errno(r, "Failed to read link '/run/udev/watch.old/%s', ignoring: %m", ent->d_name);
      63           0 :                         goto unlink;
      64             :                 }
      65             : 
      66           0 :                 r = sd_device_new_from_device_id(&dev, device);
      67           0 :                 if (r < 0) {
      68           0 :                         log_debug_errno(r, "Failed to create sd_device object for '%s', ignoring: %m", device);
      69           0 :                         goto unlink;
      70             :                 }
      71             : 
      72           0 :                 log_device_debug(dev, "Restoring old watch");
      73           0 :                 (void) udev_watch_begin(dev);
      74           0 : unlink:
      75           0 :                 (void) unlinkat(dirfd(dir), ent->d_name, 0);
      76             :         }
      77             : 
      78           0 :         (void) closedir(dir);
      79           0 :         (void) rmdir("/run/udev/watch.old");
      80             : 
      81           0 :         return 0;
      82             : }
      83             : 
      84           0 : int udev_watch_begin(sd_device *dev) {
      85             :         char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
      86             :         const char *devnode, *id_filename;
      87             :         int wd, r;
      88             : 
      89           0 :         if (inotify_fd < 0)
      90           0 :                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
      91             :                                        "Invalid inotify descriptor.");
      92             : 
      93           0 :         r = sd_device_get_devname(dev, &devnode);
      94           0 :         if (r < 0)
      95           0 :                 return log_device_error_errno(dev, r, "Failed to get device name: %m");
      96             : 
      97           0 :         log_device_debug(dev, "Adding watch on '%s'", devnode);
      98           0 :         wd = inotify_add_watch(inotify_fd, devnode, IN_CLOSE_WRITE);
      99           0 :         if (wd < 0)
     100           0 :                 return log_device_full(dev,
     101             :                                        errno == ENOENT ? LOG_DEBUG : LOG_ERR,
     102             :                                        errno,
     103             :                                        "Failed to add device '%s' to watch: %m", devnode);
     104             : 
     105           0 :         device_set_watch_handle(dev, wd);
     106             : 
     107           0 :         xsprintf(filename, "/run/udev/watch/%d", wd);
     108           0 :         r = mkdir_parents(filename, 0755);
     109           0 :         if (r < 0)
     110           0 :                 return log_device_error_errno(dev, r, "Failed to create parent directory of '%s': %m", filename);
     111           0 :         (void) unlink(filename);
     112             : 
     113           0 :         r = device_get_id_filename(dev, &id_filename);
     114           0 :         if (r < 0)
     115           0 :                 return log_device_error_errno(dev, r, "Failed to get device id-filename: %m");
     116             : 
     117           0 :         if (symlink(id_filename, filename) < 0)
     118           0 :                 return log_device_error_errno(dev, errno, "Failed to create symlink %s: %m", filename);
     119             : 
     120           0 :         return 0;
     121             : }
     122             : 
     123           0 : int udev_watch_end(sd_device *dev) {
     124             :         char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
     125             :         int wd, r;
     126             : 
     127           0 :         if (inotify_fd < 0)
     128           0 :                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
     129             :                                        "Invalid inotify descriptor.");
     130             : 
     131           0 :         r = device_get_watch_handle(dev, &wd);
     132           0 :         if (r == -ENOENT)
     133           0 :                 return 0;
     134           0 :         if (r < 0)
     135           0 :                 return log_device_debug_errno(dev, r, "Failed to get watch handle, ignoring: %m");
     136             : 
     137           0 :         log_device_debug(dev, "Removing watch");
     138           0 :         (void) inotify_rm_watch(inotify_fd, wd);
     139             : 
     140           0 :         xsprintf(filename, "/run/udev/watch/%d", wd);
     141           0 :         (void) unlink(filename);
     142             : 
     143           0 :         device_set_watch_handle(dev, -1);
     144             : 
     145           0 :         return 0;
     146             : }
     147             : 
     148           0 : int udev_watch_lookup(int wd, sd_device **ret) {
     149             :         char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
     150           0 :         _cleanup_free_ char *device = NULL;
     151             :         int r;
     152             : 
     153           0 :         assert(ret);
     154             : 
     155           0 :         if (inotify_fd < 0)
     156           0 :                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
     157             :                                        "Invalid inotify descriptor.");
     158             : 
     159           0 :         if (wd < 0)
     160           0 :                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
     161             :                                        "Invalid watch handle.");
     162             : 
     163           0 :         xsprintf(filename, "/run/udev/watch/%d", wd);
     164           0 :         r = readlink_malloc(filename, &device);
     165           0 :         if (r == -ENOENT)
     166           0 :                 return 0;
     167           0 :         if (r < 0)
     168           0 :                 return log_debug_errno(r, "Failed to read link '%s': %m", filename);
     169             : 
     170           0 :         r = sd_device_new_from_device_id(ret, device);
     171           0 :         if (r == -ENODEV)
     172           0 :                 return 0;
     173           0 :         if (r < 0)
     174           0 :                 return log_debug_errno(r, "Failed to create sd_device object for '%s': %m", device);
     175             : 
     176           0 :         return 1;
     177             : }

Generated by: LCOV version 1.14