diff options
Diffstat (limited to 'src/inotify.c')
-rw-r--r-- | src/inotify.c | 119 |
1 files changed, 113 insertions, 6 deletions
diff --git a/src/inotify.c b/src/inotify.c index 8373000..52a30d7 100644 --- a/src/inotify.c +++ b/src/inotify.c @@ -19,6 +19,11 @@ #include <sys/inotify.h> +#ifdef HAVE_DHCP +static void check_for_dhcp_inotify(struct inotify_event *in, time_t now); +#endif + + /* the strategy is to set a inotify on the directories containing resolv files, for any files in the directory which are close-write or moved into the directory. @@ -40,8 +45,6 @@ void inotify_dnsmasq_init() struct resolvc *res; inotify_buffer = safe_malloc(INOTIFY_SZ); - - daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); if (daemon->inotifyfd == -1) @@ -66,6 +69,7 @@ void inotify_dnsmasq_init() { *d = 0; /* make path just directory */ res->wd = inotify_add_watch(daemon->inotifyfd, path, IN_CLOSE_WRITE | IN_MOVED_TO); + res->file = d+1; /* pointer to filename */ *d = '/'; @@ -78,7 +82,7 @@ void inotify_dnsmasq_init() } } -int inotify_check(void) +int inotify_check(time_t now) { int hit = 0; @@ -101,13 +105,116 @@ int inotify_check(void) for (res = daemon->resolv_files; res; res = res->next) if (res->wd == in->wd && in->len != 0 && strcmp(res->file, in->name) == 0) hit = 1; + +#ifdef HAVE_DHCP + if (daemon->dhcp || daemon->doing_dhcp6) + check_for_dhcp_inotify(in, now); +#endif } } - return hit; } -#endif +#ifdef HAVE_DHCP +/* initialisation for dhcp-hostdir. Set inotify watch for each directory, and read pre-existing files */ +void set_dhcp_inotify(void) +{ + struct hostsfile *ah; - + for (ah = daemon->inotify_hosts; ah; ah = ah->next) + { + DIR *dir_stream = NULL; + struct dirent *ent; + struct stat buf; + + if (stat(ah->fname, &buf) == -1 || !(S_ISDIR(buf.st_mode))) + { + my_syslog(LOG_ERR, _("bad directory in dhcp-hostsdir %s"), ah->fname); + continue; + } + + if (!(ah->flags & AH_WD_DONE)) + { + ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO); + ah->flags |= AH_WD_DONE; + } + /* Read contents of dir _after_ calling add_watch, in the ho[e of avoiding + a race which misses files being added as we start */ + if (ah->wd == -1 || !(dir_stream = opendir(ah->fname))) + { + my_syslog(LOG_ERR, _("failed to create inotify for %s"), ah->fname); + continue; + } + + while ((ent = readdir(dir_stream))) + { + size_t lendir = strlen(ah->fname); + size_t lenfile = strlen(ent->d_name); + char *path; + + /* ignore emacs backups and dotfiles */ + if (lenfile == 0 || + ent->d_name[lenfile - 1] == '~' || + (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') || + ent->d_name[0] == '.') + continue; + + if ((path = whine_malloc(lendir + lenfile + 2))) + { + strcpy(path, ah->fname); + strcat(path, "/"); + strcat(path, ent->d_name); + + /* ignore non-regular files */ + if (stat(path, &buf) != -1 && S_ISREG(buf.st_mode)) + option_read_hostsfile(path); + + free(path); + } + } + } +} + +static void check_for_dhcp_inotify(struct inotify_event *in, time_t now) +{ + struct hostsfile *ah; + + /* ignore emacs backups and dotfiles */ + if (in->len == 0 || + in->name[in->len - 1] == '~' || + (in->name[0] == '#' && in->name[in->len - 1] == '#') || + in->name[0] == '.') + return; + + for (ah = daemon->inotify_hosts; ah; ah = ah->next) + if (ah->wd == in->wd) + { + size_t lendir = strlen(ah->fname); + char *path; + + if ((path = whine_malloc(lendir + in->len + 2))) + { + strcpy(path, ah->fname); + strcat(path, "/"); + strcat(path, in->name); + + if (option_read_hostsfile(path)) + { + /* Propogate the consequences of loading a new dhcp-host */ + dhcp_update_configs(daemon->dhcp_conf); + lease_update_from_configs(); + lease_update_file(now); + lease_update_dns(1); + } + + free(path); + } + + return; + } +} + +#endif /* DHCP */ + +#endif /* LINUX_NETWORK */ |