]> git.proxmox.com Git - systemd.git/blame - src/udev/udev-watch.c
New upstream version 249~rc1
[systemd.git] / src / udev / udev-watch.c
CommitLineData
a032b68d 1/* SPDX-License-Identifier: GPL-2.0-or-later */
663996b3 2/*
b012e921
MB
3 * Copyright © 2009 Canonical Ltd.
4 * Copyright © 2009 Scott James Remnant <scott@netsplit.com>
663996b3
MS
5 */
6
663996b3
MS
7#include <sys/inotify.h>
8
6e866b33
MB
9#include "alloc-util.h"
10#include "device-private.h"
11#include "device-util.h"
2897b343 12#include "dirent-util.h"
6e866b33 13#include "fs-util.h"
8b3d4ff0 14#include "parse-util.h"
6e866b33 15#include "udev-watch.h"
663996b3 16
8b3d4ff0 17int udev_watch_restore(int inotify_fd) {
6e866b33
MB
18 struct dirent *ent;
19 DIR *dir;
20 int r;
21
8b3d4ff0
MB
22 /* Move any old watches directory out of the way, and then restore the watches. */
23
24 assert(inotify_fd >= 0);
663996b3 25
6e866b33
MB
26 if (rename("/run/udev/watch", "/run/udev/watch.old") < 0) {
27 if (errno != ENOENT)
8b3d4ff0
MB
28 return log_warning_errno(errno, "Failed to move watches directory /run/udev/watch. "
29 "Old watches will not be restored: %m");
663996b3 30
6e866b33
MB
31 return 0;
32 }
663996b3 33
6e866b33
MB
34 dir = opendir("/run/udev/watch.old");
35 if (!dir)
8b3d4ff0
MB
36 return log_warning_errno(errno, "Failed to open old watches directory /run/udev/watch.old. "
37 "Old watches will not be restored: %m");
663996b3 38
6e866b33
MB
39 FOREACH_DIRENT_ALL(ent, dir, break) {
40 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
8b3d4ff0 41 int wd;
663996b3 42
6e866b33
MB
43 if (ent->d_name[0] == '.')
44 continue;
663996b3 45
8b3d4ff0
MB
46 /* For backward compatibility, read symlink from watch handle to device id, and ignore
47 * the opposite direction symlink. */
48
49 if (safe_atoi(ent->d_name, &wd) < 0)
6e866b33 50 goto unlink;
663996b3 51
8b3d4ff0 52 r = device_new_from_watch_handle_at(&dev, dirfd(dir), wd);
6e866b33 53 if (r < 0) {
8b3d4ff0
MB
54 log_full_errno(r == -ENODEV ? LOG_DEBUG : LOG_WARNING, r,
55 "Failed to create sd_device object from saved watch handle '%s', ignoring: %m",
56 ent->d_name);
6e866b33 57 goto unlink;
663996b3
MS
58 }
59
6e866b33 60 log_device_debug(dev, "Restoring old watch");
8b3d4ff0 61 (void) udev_watch_begin(inotify_fd, dev);
6e866b33
MB
62unlink:
63 (void) unlinkat(dirfd(dir), ent->d_name, 0);
64 }
663996b3 65
6e866b33
MB
66 (void) closedir(dir);
67 (void) rmdir("/run/udev/watch.old");
68
69 return 0;
663996b3
MS
70}
71
8b3d4ff0
MB
72int udev_watch_begin(int inotify_fd, sd_device *dev) {
73 const char *devnode;
6e866b33 74 int wd, r;
663996b3 75
8b3d4ff0
MB
76 assert(inotify_fd >= 0);
77 assert(dev);
6e866b33
MB
78
79 r = sd_device_get_devname(dev, &devnode);
80 if (r < 0)
8b3d4ff0 81 return log_device_debug_errno(dev, r, "Failed to get device name: %m");
6e866b33
MB
82
83 log_device_debug(dev, "Adding watch on '%s'", devnode);
84 wd = inotify_add_watch(inotify_fd, devnode, IN_CLOSE_WRITE);
8b3d4ff0
MB
85 if (wd < 0) {
86 bool ignore = errno == ENOENT;
663996b3 87
8b3d4ff0
MB
88 r = log_device_full_errno(dev, ignore ? LOG_DEBUG : LOG_WARNING, errno,
89 "Failed to add device '%s' to watch%s: %m",
90 devnode, ignore ? ", ignoring" : "");
663996b3 91
8b3d4ff0
MB
92 (void) device_set_watch_handle(dev, -1);
93 return ignore ? 0 : r;
94 }
663996b3 95
8b3d4ff0 96 r = device_set_watch_handle(dev, wd);
6e866b33 97 if (r < 0)
8b3d4ff0 98 return log_device_warning_errno(dev, r, "Failed to save watch handle in /run/udev/watch: %m");
663996b3 99
6e866b33 100 return 0;
663996b3
MS
101}
102
8b3d4ff0
MB
103int udev_watch_end(int inotify_fd, sd_device *dev) {
104 int wd;
6e866b33 105
8b3d4ff0 106 assert(dev);
6e866b33 107
8b3d4ff0 108 /* This may be called by 'udevadm test'. In that case, inotify_fd is not initialized. */
6e866b33 109 if (inotify_fd < 0)
6e866b33 110 return 0;
6e866b33 111
8b3d4ff0 112 if (sd_device_get_devname(dev, NULL) < 0)
6e866b33 113 return 0;
663996b3 114
8b3d4ff0
MB
115 wd = device_get_watch_handle(dev);
116 if (wd < 0)
117 log_device_debug_errno(dev, wd, "Failed to get watch handle, ignoring: %m");
118 else {
119 log_device_debug(dev, "Removing watch");
120 (void) inotify_rm_watch(inotify_fd, wd);
121 }
122 (void) device_set_watch_handle(dev, -1);
123
124 return 0;
663996b3 125}