diff -ru udev-103.orig/udevd.c udev-103/udevd.c --- udev-103.orig/udevd.c 2006-10-20 15:43:35.000000000 +0300 +++ udev-103/udevd.c 2006-12-09 19:42:09.432522000 +0200 @@ -929,6 +929,100 @@ } } +static void check_link(const char *filename) +{ + struct stat stats; + struct stat lstats; + char fn[PATH_SIZE+1]; + char fn2[PATH_SIZE*2+3]; + char *p; + ssize_t sz; + + if (lstat(filename, &lstats) != 0) + { + err("could not read '%s': %s", filename, strerror(errno)); + return; + } + + /* Check if it is a link */ + if (!S_ISLNK(lstats.st_mode)) + return; + + /* Get the destination */ + dbg("found link: %s", filename); + sz=readlink(filename, fn, PATH_SIZE); + if (sz>=PATH_SIZE) + { + err("oversized link destination of '%s'", filename); + return; + } + + fn[sz]=0; + + /* Form the full destination path */ + if (fn[0]=='/') + { + strcpy(fn2, fn); + } else + { + snprintf(fn2, PATH_SIZE*2+2, "%s/%s", udev_rules_filename, fn); + fn2[PATH_SIZE*2+2]=0; + } + + /* Check if destination if a file */ + stat(fn2, &stats); + if (!S_ISREG(stats.st_mode)) + return; + + /* Find the parent directory */ + p=fn2+strlen(fn2); + + while (p>=fn2) + { + if (*p=='/') + { + *p=0; + break; + } + p--; + } + + if (p==fn2) + err("failed to get parrent directory of '%s'", fn2); + + dbg("adding notify for:'%s'", fn2); + inotify_add_watch(inotify_fd, fn2, IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE); +} + +static void start_inotify(void) +{ + struct name_entry *name_loop, *name_tmp; + + /* watch rules directory */ + inotify_fd = inotify_init(); + if (inotify_fd >= 0) + { + inotify_add_watch(inotify_fd, udev_rules_filename, IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE); + } else if (errno == ENOSYS) + { + err("the kernel does not support inotify, udevd can't monitor configuration file changes"); + return; + } else + { + err("inotify_init failed: %s", strerror(errno)); + return; + } + + LIST_HEAD(name_list); + + add_matching_files(&name_list, udev_rules_filename, RULEFILE_SUFFIX); + list_for_each_entry_safe(name_loop, name_tmp, &name_list, node) { + check_link(name_loop->name); + list_del(&name_loop->node); + free(name_loop); + } +} + int main(int argc, char *argv[], char *envp[]) { int retval; @@ -1101,14 +1195,7 @@ sigaction(SIGCHLD, &act, NULL); sigaction(SIGHUP, &act, NULL); - /* watch rules directory */ - inotify_fd = inotify_init(); - if (inotify_fd >= 0) - inotify_add_watch(inotify_fd, udev_rules_filename, IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE); - else if (errno == ENOSYS) - err("the kernel does not support inotify, udevd can't monitor configuration file changes"); - else - err("inotify_init failed: %s", strerror(errno)); + start_inotify(); /* maximum limit of forked childs */ value = getenv("UDEVD_MAX_CHILDS"); @@ -1145,15 +1232,15 @@ if (debug_trace) putenv("DEBUG=1"); - maxfd = udevd_sock; - maxfd = UDEV_MAX(maxfd, uevent_netlink_sock); - maxfd = UDEV_MAX(maxfd, signal_pipe[READ_END]); - maxfd = UDEV_MAX(maxfd, inotify_fd); - while (!udev_exit) { struct udevd_uevent_msg *msg; int fdcount; + maxfd = udevd_sock; + maxfd = UDEV_MAX(maxfd, uevent_netlink_sock); + maxfd = UDEV_MAX(maxfd, signal_pipe[READ_END]); + maxfd = UDEV_MAX(maxfd, inotify_fd); + FD_ZERO(&readfds); FD_SET(signal_pipe[READ_END], &readfds); FD_SET(udevd_sock, &readfds); @@ -1209,6 +1296,12 @@ /* rules changed, set by inotify or a HUP signal */ if (reload_config) { reload_config = 0; + /* Restart inotify to handle possible file changes */ + if (inotify_fd>0) + { + close(inotify_fd); + start_inotify(); + } udev_rules_cleanup(&rules); udev_rules_init(&rules, 1); }