static struct udev_rules *rules;
static struct udev_ctrl *udev_ctrl;
static struct udev_monitor *kernel_monitor;
-static int inotify_fd = -1;
static volatile int sigchilds_waiting;
static volatile int udev_exit;
static volatile int reload_config;
/* child */
udev_monitor_unref(kernel_monitor);
udev_ctrl_unref(udev_ctrl);
- if (inotify_fd >= 0)
- close(inotify_fd);
logging_close();
logging_init("udevd-event");
setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY);
udev_ctrl_msg_unref(ctrl_msg);
}
+/* read inotify messages */
+static int handle_inotify(struct udev *udev)
+{
+ int nbytes, pos;
+ char *buf;
+ struct inotify_event *ev;
+
+ if ((ioctl(inotify_fd, FIONREAD, &nbytes) < 0) || (nbytes <= 0))
+ return 0;
+
+ buf = malloc(nbytes);
+ if (buf == NULL) {
+ err(udev, "error getting buffer for inotify, disable watching\n");
+ close(inotify_fd);
+ inotify_fd = -1;
+ return 0;
+ }
+
+ read(inotify_fd, buf, nbytes);
+
+ for (pos = 0, ev = (struct inotify_event *)(buf + pos); pos < nbytes; pos += sizeof(struct inotify_event) + ev->len) {
+ const char *syspath;
+
+ dbg(udev, "inotify event: %x for %d (%s)\n", ev->mask, ev->wd, ev->len ? ev->name : "*");
+
+ syspath = udev_watch_lookup(udev, ev->wd);
+ if (syspath != NULL) {
+ dbg(udev, "inotify event: %x for %s\n", ev->mask, syspath);
+ if (ev->mask & IN_CLOSE_WRITE) {
+ char filename[UTIL_PATH_SIZE];
+ int fd;
+
+ info(udev, "device %s closed, synthesising 'change'\n", syspath);
+ util_strlcpy(filename, syspath, sizeof(filename));
+ util_strlcat(filename, "/uevent", sizeof(filename));
+ fd = open(filename, O_WRONLY);
+ if (fd < 0 || write(fd, "change", 6) < 0)
+ info(udev, "error writing uevent: %m\n");
+ close(fd);
+ }
+ if (ev->mask & IN_IGNORED)
+ udev_watch_end(udev, ev->wd);
+ } else {
+ reload_config = 1;
+ }
+ }
+
+ free (buf);
+ return 0;
+}
+
static void asmlinkage sig_handler(int signum)
{
switch (signum) {
case 'N':
if (strcmp (optarg, "early") == 0) {
resolve_names = 1;
+ } else if (strcmp (optarg, "late") == 0) {
+ resolve_names = 0;
} else if (strcmp (optarg, "never") == 0) {
resolve_names = -1;
} else {
- fprintf(stderr, "resolve-names must be early or never\n");
- err(udev, "resolve-names must be early or never\n");
+ fprintf(stderr, "resolve-names must be early, late or never\n");
+ err(udev, "resolve-names must be early, late or never\n");
goto exit;
}
break;
case 'h':
- printf("Usage: udevd [--help] [--daemon] [--debug-trace] [--debug] [--resolve-names=early|never] [--version]\n");
+ printf("Usage: udevd [--help] [--daemon] [--debug-trace] [--debug] "
+ "[--resolve-names=early|late|never] [--version]\n");
goto exit;
case 'V':
printf("%s\n", VERSION);
memset(&act, 0x00, sizeof(struct sigaction));
act.sa_handler = (void (*)(int)) sig_handler;
sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESTART;
sigaction(SIGINT, &act, NULL);
sigaction(SIGTERM, &act, NULL);
sigaction(SIGCHLD, &act, NULL);
sigaction(SIGHUP, &act, NULL);
/* watch rules directory */
- inotify_fd = inotify_init();
+ udev_watch_init(udev);
if (inotify_fd >= 0) {
if (udev_get_rules_path(udev) != NULL) {
inotify_add_watch(inotify_fd, udev_get_rules_path(udev),
inotify_add_watch(inotify_fd, filename,
IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
}
- } else if (errno == ENOSYS)
- info(udev, "unable to use inotify, udevd will not monitor rule files changes\n");
- else
- err(udev, "inotify_init failed: %m\n");
+
+ udev_watch_restore(udev);
+ }
/* in trace mode run one event after the other */
if (debug_trace) {
}
/* rules directory inotify watch */
- if (inotify_poll && (inotify_poll->revents & POLLIN)) {
- int nbytes;
-
- /* discard all possible events, we can just reload the config */
- if ((ioctl(inotify_fd, FIONREAD, &nbytes) == 0) && nbytes > 0) {
- char *buf;
-
- reload_config = 1;
- buf = malloc(nbytes);
- if (buf == NULL) {
- err(udev, "error getting buffer for inotify, disable watching\n");
- close(inotify_fd);
- inotify_fd = -1;
- }
- read(inotify_fd, buf, nbytes);
- free(buf);
- }
- }
+ if (inotify_poll && (inotify_poll->revents & POLLIN))
+ handle_inotify(udev);
handle_signals:
signal_received = 0;