summaryrefslogtreecommitdiff
path: root/src/inotify.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/inotify.c')
-rw-r--r--src/inotify.c119
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 */