]>
git.ipfire.org Git - thirdparty/systemd.git/blob - udev/udev-watch.c
2 * Copyright (C) 2004-2008 Kay Sievers <kay.sievers@vrfy.org>
3 * Copyright (C) 2009 Canonical Ltd.
4 * Copyright (C) 2009 Scott James Remnant <scott@netsplit.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <sys/types.h>
30 #include <sys/inotify.h>
37 /* inotify descriptor, will be shared with rules directory;
38 * set to cloexec since we need our children to be able to add
41 void udev_watch_init(struct udev
*udev
)
43 inotify_fd
= inotify_init();
44 if (inotify_fd
>= 0) {
47 flags
= fcntl(inotify_fd
, F_GETFD
);
52 fcntl(inotify_fd
, F_SETFD
, flags
);
53 } else if (errno
== ENOSYS
)
54 info(udev
, "unable to use inotify, udevd will not monitor rule files changes\n");
56 err(udev
, "inotify_init failed: %m\n");
59 /* move any old watches directory out of the way, and then restore
62 void udev_watch_restore(struct udev
*udev
)
64 char filename
[UTIL_PATH_SIZE
], oldname
[UTIL_PATH_SIZE
];
69 util_strlcpy(oldname
, udev_get_dev_path(udev
), sizeof(oldname
));
70 util_strlcat(oldname
, "/.udev/watch.old", sizeof(oldname
));
72 util_strlcpy(filename
, udev_get_dev_path(udev
), sizeof(filename
));
73 util_strlcat(filename
, "/.udev/watch", sizeof(filename
));
75 if (rename(filename
, oldname
) == 0) {
79 dir
= opendir(oldname
);
81 err(udev
, "unable to open old watches dir '%s', old watches will not be restored: %m", oldname
);
85 while ((ent
= readdir(dir
)) != NULL
) {
86 char path
[UTIL_PATH_SIZE
];
87 char buf
[UTIL_PATH_SIZE
];
89 struct udev_device
*dev
;
91 if (ent
->d_name
[0] < '0' || ent
->d_name
[0] > '9')
94 util_strlcpy(path
, oldname
, sizeof(path
));
95 util_strlcat(path
, "/", sizeof(path
));
96 util_strlcat(path
, ent
->d_name
, sizeof(path
));
98 len
= readlink(path
, buf
, sizeof(buf
));
105 dbg(udev
, "old watch to '%s' found\n", buf
);
106 dev
= udev_device_new_from_syspath(udev
, buf
);
112 info(udev
, "restoring old watch on '%s'\n", udev_device_get_devnode(dev
));
113 udev_watch_begin(udev
, dev
);
115 udev_device_unref(dev
);
122 } else if (errno
!= ENOENT
) {
123 err(udev
, "unable to move watches dir '%s', old watches will not be restored: %m", filename
);
127 static const char *udev_watch_filename(struct udev
*udev
, int wd
)
129 static char filename
[UTIL_PATH_SIZE
];
132 sprintf(str
, "%d", wd
);
133 util_strlcpy(filename
, udev_get_dev_path(udev
), sizeof(filename
));
134 util_strlcat(filename
, "/.udev/watch/", sizeof(filename
));
135 util_strlcat(filename
, str
, sizeof(filename
));
140 void udev_watch_begin(struct udev
*udev
, struct udev_device
*dev
)
142 const char *filename
;
145 if (inotify_fd
< 0 || major(udev_device_get_devnum(dev
)) == 0)
148 info(udev
, "adding watch on '%s'\n", udev_device_get_devnode(dev
));
149 wd
= inotify_add_watch(inotify_fd
, udev_device_get_devnode(dev
), IN_CLOSE_WRITE
);
151 err(udev
, "inotify_add_watch(%d, %s, %o) failed: %m\n",
152 inotify_fd
, udev_device_get_devnode(dev
), IN_CLOSE_WRITE
);
155 filename
= udev_watch_filename(udev
, wd
);
156 util_create_path(udev
, filename
);
158 symlink(udev_device_get_syspath(dev
), filename
);
160 udev_device_set_watch_handle(dev
, wd
);
161 udev_device_update_db(dev
);
164 void udev_watch_end(struct udev
*udev
, struct udev_device
*dev
)
167 const char *filename
;
169 if (inotify_fd
< 0 || major(udev_device_get_devnum(dev
)) == 0)
172 wd
= udev_device_get_watch_handle(dev
);
176 info(udev
, "removing watch on '%s'\n", udev_device_get_devnode(dev
));
177 inotify_rm_watch(inotify_fd
, wd
);
179 filename
= udev_watch_filename(udev
, wd
);
182 udev_device_set_watch_handle(dev
, -1);
183 udev_device_update_db(dev
);
186 struct udev_device
*udev_watch_lookup(struct udev
*udev
, int wd
)
188 const char *filename
;
189 char buf
[UTIL_PATH_SIZE
];
192 if (inotify_fd
< 0 || wd
< 0)
195 filename
= udev_watch_filename(udev
, wd
);
196 len
= readlink(filename
, buf
, sizeof(buf
));
200 return udev_device_new_from_syspath(udev
, buf
);