Diff for /embedaddon/dnsmasq/src/inotify.c between versions 1.1.1.1 and 1.1.1.3

version 1.1.1.1, 2016/11/02 09:57:01 version 1.1.1.3, 2023/09/27 11:02:07
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
     
    This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
Line 20 Line 20
 #include <sys/inotify.h>  #include <sys/inotify.h>
 #include <sys/param.h> /* For MAXSYMLINKS */  #include <sys/param.h> /* For MAXSYMLINKS */
   
/* the strategy is to set a inotify on the directories containing/* the strategy is to set an inotify on the directories containing
    resolv files, for any files in the directory which are close-write      resolv files, for any files in the directory which are close-write 
    or moved into the directory.     or moved into the directory.
         
Line 104  void inotify_dnsmasq_init() Line 104  void inotify_dnsmasq_init()
   
       strcpy(path, res->name);        strcpy(path, res->name);
   
      /* Follow symlinks until we reach a non-symlink, or a non-existant file. */      /* Follow symlinks until we reach a non-symlink, or a non-existent file. */
       while ((new_path = my_readlink(path)))        while ((new_path = my_readlink(path)))
         {          {
           if (links-- == 0)            if (links-- == 0)
Line 133  void inotify_dnsmasq_init() Line 133  void inotify_dnsmasq_init()
     }      }
 }  }
   
   static struct hostsfile *dyndir_addhosts(struct dyndir *dd, char *path)
   {
     /* Check if this file is already known in dd->files */
     struct hostsfile *ah = NULL;
     for(ah = dd->files; ah; ah = ah->next)
       if(ah && ah->fname && strcmp(path, ah->fname) == 0)
         return ah;
   
     /* Not known, create new hostsfile record for this dyndir */
     struct hostsfile *newah = NULL;
     if(!(newah = whine_malloc(sizeof(struct hostsfile))))
       return NULL;
   
     /* Add this file to the tip of the linked list */
     newah->next = dd->files;
     dd->files = newah;
   
     /* Copy flags, set index and the full file path */
     newah->flags = dd->flags;
     newah->index = daemon->host_index++;
     newah->fname = path;
   
     return newah;
   }
   
   
 /* initialisation for dynamic-dir. Set inotify watch for each directory, and read pre-existing files */  /* initialisation for dynamic-dir. Set inotify watch for each directory, and read pre-existing files */
 void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz)  void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz)
 {  {
  struct hostsfile *ah;  struct dyndir *dd;
  
  for (ah = daemon->dynamic_dirs; ah; ah = ah->next)  for (dd = daemon->dynamic_dirs; dd; dd = dd->next)
     {      {
       DIR *dir_stream = NULL;        DIR *dir_stream = NULL;
       struct dirent *ent;        struct dirent *ent;
       struct stat buf;        struct stat buf;
     
      if (!(ah->flags & flag))      if (!(dd->flags & flag))
         continue;          continue;
 
      if (stat(ah->fname, &buf) == -1 || !(S_ISDIR(buf.st_mode)))      if (stat(dd->dname, &buf) == -1)
         {          {
           my_syslog(LOG_ERR, _("bad dynamic directory %s: %s"),             my_syslog(LOG_ERR, _("bad dynamic directory %s: %s"), 
                    ah->fname, strerror(errno));                    dd->dname, strerror(errno));
           continue;            continue;
         }          }
      
       if (!(ah->flags & AH_WD_DONE))      if (!(S_ISDIR(buf.st_mode)))
         {
           my_syslog(LOG_ERR, _("bad dynamic directory %s: %s"), 
                     dd->dname, _("not a directory"));
           continue;
         }
 
        if (!(dd->flags & AH_WD_DONE))
          {           {
           ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO);           dd->wd = inotify_add_watch(daemon->inotifyfd, dd->dname, IN_CLOSE_WRITE | IN_MOVED_TO | IN_DELETE);
           ah->flags |= AH_WD_DONE;           dd->flags |= AH_WD_DONE;
          }           }
   
        /* Read contents of dir _after_ calling add_watch, in the hope of avoiding         /* Read contents of dir _after_ calling add_watch, in the hope of avoiding
           a race which misses files being added as we start */            a race which misses files being added as we start */
       if (ah->wd == -1 || !(dir_stream = opendir(ah->fname)))       if (dd->wd == -1 || !(dir_stream = opendir(dd->dname)))
          {           {
            my_syslog(LOG_ERR, _("failed to create inotify for %s: %s"),             my_syslog(LOG_ERR, _("failed to create inotify for %s: %s"),
                     ah->fname, strerror(errno));                     dd->dname, strerror(errno));
            continue;             continue;
          }           }
   
        while ((ent = readdir(dir_stream)))         while ((ent = readdir(dir_stream)))
          {           {
           size_t lendir = strlen(ah->fname);           size_t lendir = strlen(dd->dname);
            size_t lenfile = strlen(ent->d_name);             size_t lenfile = strlen(ent->d_name);
            char *path;             char *path;
           
            /* ignore emacs backups and dotfiles */             /* ignore emacs backups and dotfiles */
            if (lenfile == 0 ||              if (lenfile == 0 || 
                ent->d_name[lenfile - 1] == '~' ||                 ent->d_name[lenfile - 1] == '~' ||
                (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||                 (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
                ent->d_name[0] == '.')                 ent->d_name[0] == '.')
              continue;               continue;
           
            if ((path = whine_malloc(lendir + lenfile + 2)))             if ((path = whine_malloc(lendir + lenfile + 2)))
              {               {
               strcpy(path, ah->fname);               struct hostsfile *ah;
 
                strcpy(path, dd->dname);
                strcat(path, "/");                 strcat(path, "/");
                strcat(path, ent->d_name);                 strcat(path, ent->d_name);
   
                  if (!(ah = dyndir_addhosts(dd, path)))
                    {
                      free(path);
                      continue;
                    }
                                 
                /* ignore non-regular files */                 /* ignore non-regular files */
                if (stat(path, &buf) != -1 && S_ISREG(buf.st_mode))                 if (stat(path, &buf) != -1 && S_ISREG(buf.st_mode))
                  {                   {
                   if (ah->flags & AH_HOSTS)                   if (dd->flags & AH_HOSTS)
                      total_size = read_hostsfile(path, ah->index, total_size, rhash, revhashsz);                       total_size = read_hostsfile(path, ah->index, total_size, rhash, revhashsz);
 #ifdef HAVE_DHCP  #ifdef HAVE_DHCP
                   else if (ah->flags & (AH_DHCP_HST | AH_DHCP_OPT))                   else if (dd->flags & (AH_DHCP_HST | AH_DHCP_OPT))
                     option_read_dynfile(path, ah->flags);                     option_read_dynfile(path, dd->flags);
 #endif               #endif             
                  }                   }
   
                free(path);  
              }               }
          }           }
   
Line 211  void set_dynamic_inotify(int flag, int total_size, str Line 249  void set_dynamic_inotify(int flag, int total_size, str
 int inotify_check(time_t now)  int inotify_check(time_t now)
 {  {
   int hit = 0;    int hit = 0;
  struct hostsfile *ah;  struct dyndir *dd;
   
   while (1)    while (1)
     {      {
Line 227  int inotify_check(time_t now) Line 265  int inotify_check(time_t now)
               
       for (p = inotify_buffer; rc - (p - inotify_buffer) >= (int)sizeof(struct inotify_event); p += sizeof(struct inotify_event) + in->len)         for (p = inotify_buffer; rc - (p - inotify_buffer) >= (int)sizeof(struct inotify_event); p += sizeof(struct inotify_event) + in->len) 
         {          {
             size_t namelen;
   
           in = (struct inotify_event*)p;            in = (struct inotify_event*)p;
                       
           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;  
   
           /* ignore emacs backups and dotfiles */            /* ignore emacs backups and dotfiles */
          if (in->len == 0 ||           if (in->len == 0 || (namelen = strlen(in->name)) == 0 ||
              in->name[in->len - 1] == '~' ||              in->name[namelen - 1] == '~' ||
              (in->name[0] == '#' && in->name[in->len - 1] == '#') ||              (in->name[0] == '#' && in->name[namelen - 1] == '#') ||
               in->name[0] == '.')                in->name[0] == '.')
             continue;              continue;
          
          for (ah = daemon->dynamic_dirs; ah; ah = ah->next)          for (res = daemon->resolv_files; res; res = res->next)
            if (ah->wd == in->wd)            if (res->wd == in->wd && strcmp(res->file, in->name) == 0)
               hit = 1;
 
           for (dd = daemon->dynamic_dirs; dd; dd = dd->next)
             if (dd->wd == in->wd)
               {                {
                size_t lendir = strlen(ah->fname);                size_t lendir = strlen(dd->dname);
                 char *path;                  char *path;
                                                
                 if ((path = whine_malloc(lendir + in->len + 2)))                  if ((path = whine_malloc(lendir + in->len + 2)))
                   {                    {
                    strcpy(path, ah->fname);                    struct hostsfile *ah = NULL;
 
                     strcpy(path, dd->dname);
                     strcat(path, "/");                      strcat(path, "/");
                     strcat(path, in->name);                      strcat(path, in->name);
                        
                     my_syslog(LOG_INFO, _("inotify, new or changed file %s"), path);  
   
                    if (ah->flags & AH_HOSTS)                    /* Is this is a deletion event? */
                     if (in->mask & IN_DELETE)
                       my_syslog(LOG_INFO, _("inotify: %s removed"), path);
                     else 
                       my_syslog(LOG_INFO, _("inotify: %s new or modified"), path);
 
                     if (dd->flags & AH_HOSTS)
                       {                        {
                        read_hostsfile(path, ah->index, 0, NULL, 0);                        if ((ah = dyndir_addhosts(dd, path)))
#ifdef HAVE_DHCP 
                        if (daemon->dhcp || daemon->doing_dhcp6)  
                           {                            {
                            /* Propogate the consequences of loading a new dhcp-host */                            const unsigned int removed = cache_remove_uid(ah->index);
                            dhcp_update_configs(daemon->dhcp_conf);                            if (removed > 0)
                            lease_update_from_configs();                               my_syslog(LOG_INFO, _("inotify: flushed %u names read from %s"), removed, path);
                            lease_update_file(now); 
                            lease_update_dns(1);                            /* (Re-)load hostsfile only if this event isn't triggered by deletion */
                          }                            if (!(in->mask & IN_DELETE))
                               read_hostsfile(path, ah->index, 0, NULL, 0);
 #ifdef HAVE_DHCP
                             if (daemon->dhcp || daemon->doing_dhcp6) 
                               {
                                 /* Propagate 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);
                               }
 #endif  #endif
                             }
                       }                        }
 #ifdef HAVE_DHCP  #ifdef HAVE_DHCP
                    else if (ah->flags & AH_DHCP_HST)                    else if (dd->flags & AH_DHCP_HST)
                       {                        {
                         if (option_read_dynfile(path, AH_DHCP_HST))                          if (option_read_dynfile(path, AH_DHCP_HST))
                           {                            {
                            /* Propogate the consequences of loading a new dhcp-host */                            /* Propagate the consequences of loading a new dhcp-host */
                             dhcp_update_configs(daemon->dhcp_conf);                              dhcp_update_configs(daemon->dhcp_conf);
                             lease_update_from_configs();                               lease_update_from_configs(); 
                             lease_update_file(now);                               lease_update_file(now); 
                             lease_update_dns(1);                              lease_update_dns(1);
                           }                            }
                       }                        }
                    else if (ah->flags & AH_DHCP_OPT)                    else if (dd->flags & AH_DHCP_OPT)
                       option_read_dynfile(path, AH_DHCP_OPT);                        option_read_dynfile(path, AH_DHCP_OPT);
 #endif  #endif
                                           
                    free(path);                    if (!ah)
                       free(path);
                   }                    }
               }                }
         }          }
Line 293  int inotify_check(time_t now) Line 349  int inotify_check(time_t now)
 }  }
   
 #endif  /* INOTIFY */  #endif  /* INOTIFY */
     

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>