LCOV - code coverage report
Current view: top level - udev - udev-watch.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 90 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 5 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 140 0.0 %

           Branch data     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