[Dnsmasq-discuss] [PATCH] Use nanosecond granularity when checking for file changes.

Karl Vogel karl.vogel at gmail.com
Tue Sep 30 12:46:02 BST 2014


On some setups, the resolv.conf file might be updated/changed
within the 1 second granularity that st_mtime provides, therefor
also keep track of the nanoseconds.

NOTE: not all filesystems have nanosecond timestamps, but in that
      case, the nanosecond field will be set to 0 by the kernel.
---
 src/dnsmasq.c |   20 +++++++++++---------
 src/dnsmasq.h |    7 ++++++-
 src/option.c  |    3 ++-
 3 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index f4a89fc..065dd61 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -1288,7 +1288,7 @@ static void poll_resolv(int force, int do_reload, time_t now)
 {
   struct resolvc *res, *latest;
   struct stat statbuf;
-  time_t last_change = 0;
+  struct timespec last_change = { 0 };
   /* There may be more than one possible file. 
      Go through and find the one which changed _last_.
      Warn of any which can't be read. */
@@ -1301,7 +1301,8 @@ static void poll_resolv(int force, int do_reload, time_t now)
       {
 	if (force)
 	  {
-	    res->mtime = 0; 
+	    res->mtime.tv_sec = 0;
+	    res->mtime.tv_nsec = 0;
 	    continue;
 	  }
 
@@ -1309,7 +1310,7 @@ static void poll_resolv(int force, int do_reload, time_t now)
 	  my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
 	res->logged = 1;
 	
-	if (res->mtime != 0)
+	if (res->mtime.tv_sec != 0 && res->mtime.tv_nsec != 0)
 	  { 
 	    /* existing file evaporated, force selection of the latest
 	       file even if its mtime hasn't changed since we last looked */
@@ -1320,12 +1321,12 @@ static void poll_resolv(int force, int do_reload, time_t now)
     else
       {
 	res->logged = 0;
-	if (force || (statbuf.st_mtime != res->mtime))
-          {
-            res->mtime = statbuf.st_mtime;
-	    if (difftime(statbuf.st_mtime, last_change) > 0.0)
+	if (force || timespeccmp(&statbuf.st_mtim, &res->mtime, !=))
+	  {
+	    res->mtime = statbuf.st_mtim;
+	    if (timespeccmp(&statbuf.st_mtim, &last_change, >))
 	      {
-		last_change = statbuf.st_mtime;
+		last_change = statbuf.st_mtim;
 		latest = res;
 	      }
 	  }
@@ -1344,7 +1345,8 @@ static void poll_resolv(int force, int do_reload, time_t now)
 	}
       else 
 	{
-	  latest->mtime = 0;
+	  latest->mtime.tv_sec = 0;
+	  latest->mtime.tv_nsec = 0;
 	  if (!warned)
 	    {
 	      my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index e74b15a..ee8017b 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -136,6 +136,11 @@ extern int capget(cap_user_header_t header, cap_user_data_t data);
 #include <priv.h>
 #endif
 
+#define timespeccmp(a, b, CMP) \
+  (((a)->tv_sec == (b)->tv_sec) ? \
+   ((a)->tv_nsec CMP (b)->tv_nsec) : \
+   ((a)->tv_sec CMP (b)->tv_sec))
+
 /* daemon is function in the C library.... */
 #define daemon dnsmasq_daemon
 
@@ -539,7 +544,7 @@ struct iname {
 struct resolvc {
   struct resolvc *next;
   int is_default, logged;
-  time_t mtime;
+  struct timespec mtime;
   char *name;
 };
 
diff --git a/src/option.c b/src/option.c
index 45d8875..c990a2a 100644
--- a/src/option.c
+++ b/src/option.c
@@ -1625,7 +1625,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
 	    new->next = list;
 	    new->name = name;
 	    new->is_default = 0;
-	    new->mtime = 0;
+	    new->mtime.tv_sec = 0;
+	    new->mtime.tv_nsec = 0;
 	    new->logged = 0;
 	    list = new;
 	  }
-- 
1.7.1




More information about the Dnsmasq-discuss mailing list