[Dnsmasq-discuss] feature: dictionary order import of addn-hosts dirs?

Ed W lists at wildgooses.com
Sun Aug 8 13:02:11 UTC 2021


On 19/07/2021 18:52, Ed W wrote:
> Hi, around 2.82 someone posted a little patch to import the config files in dictionary order, which
> is very useful for situations where you have overlapping definitions. I'm using an addn-hosts stanza
> pointing to a directory and files currently import in a somewhat random order (suppose inode
> order?), which can lead to unexpected reverse host definitions in some cases
>
> Could we have a dictionary order import for add-hosts files please?
>
> Ed W


Hi, I have developed the attached patch without really being sure that this is the best approach. I
would be grateful for some feedback. I have used scandir without understanding if this is portable
across systems that we support with dnsmasq. Also I am trying to copy the existing coding style, but
surely I have failed.

I'm also unclear that it still works as advertised in the case that I don't have inotify enabled?
Any help?

The intent is that I have a few aliases for my local system name. However, the reverse name depends
on the order that the addn-hosts files are read. In any case predictable dictionary order seems like
a nice thing to have for all config files

Thanks


Ed W

-------------- next part --------------
--- a/src/option.c	2021-08-08 11:38:59.736193892 +0000
+++ b/src/option.c	2021-08-08 11:39:05.959267538 +0000
@@ -4819,7 +4819,9 @@
 struct hostsfile *expand_filelist(struct hostsfile *list)
 {
   unsigned int i;
+  int entcnt, n;
   struct hostsfile *ah;
+  struct dirent **namelist;
 
   /* find largest used index */
   for (i = SRC_AH, ah = list; ah; ah = ah->next)
@@ -4839,19 +4841,20 @@
 	struct stat buf;
 	if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
 	  {
-	    DIR *dir_stream;
 	    struct dirent *ent;
 	    
 	    /* don't read this as a file */
 	    ah->flags |= AH_INACTIVE;
 	    
-	    if (!(dir_stream = opendir(ah->fname)))
+	    entcnt = scandir(ah->fname, &namelist, NULL, alphasort);
+	    if (entcnt < 0)
 	      my_syslog(LOG_ERR, _("cannot access directory %s: %s"), 
 			ah->fname, strerror(errno));
 	    else
 	      {
-		while ((ent = readdir(dir_stream)))
+		for (n = 0; n < entcnt; n++)
 		  {
+		    ent = namelist[n];
 		    size_t lendir = strlen(ah->fname);
 		    size_t lenfile = strlen(ent->d_name);
 		    struct hostsfile *ah1;
@@ -4908,8 +4911,8 @@
 		      ah1->flags |= AH_INACTIVE; 
 		    
 		  }
-		closedir(dir_stream);
 	      }
+	      free(namelist);
 	  }
       }
   
--- a/src/inotify.c	2021-08-08 11:38:52.297105848 +0000
+++ b/src/inotify.c	2021-08-08 11:39:05.959267538 +0000
@@ -141,8 +141,9 @@
   
   for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
     {
-      DIR *dir_stream = NULL;
+      struct dirent **namelist;
       struct dirent *ent;
+      int entcnt, n;
       struct stat buf;
      
       if (!(ah->flags & flag))
@@ -163,15 +164,24 @@
 
        /* Read contents of dir _after_ calling add_watch, in the hope of avoiding
 	  a race which misses files being added as we start */
-       if (ah->wd == -1 || !(dir_stream = opendir(ah->fname)))
+       if (ah->wd == -1)
 	 {
 	   my_syslog(LOG_ERR, _("failed to create inotify for %s: %s"),
 		     ah->fname, strerror(errno));
 	   continue;
 	 }
 
-       while ((ent = readdir(dir_stream)))
+       entcnt = scandir(ah->fname, &namelist, NULL, alphasort);
+       if (entcnt < 0)
 	 {
+	   my_syslog(LOG_ERR, _("failed to call scandir for %s: %s"),
+		     ah->fname, strerror(errno));
+	   continue;
+	 }
+
+       for (n = 0; n < entcnt; n++)
+	 {
+	   ent = namelist[n];
 	   size_t lendir = strlen(ah->fname);
 	   size_t lenfile = strlen(ent->d_name);
 	   char *path;
@@ -204,7 +214,7 @@
 	     }
 	 }
 
-       closedir(dir_stream);
+       free(namelist);
     }
 }
 


More information about the Dnsmasq-discuss mailing list