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

version 1.1.1.2, 2021/03/17 00:56:46 version 1.1.1.3, 2023/09/27 11:02:07
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2021 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 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 242  int inotify_check(time_t now) Line 280  int inotify_check(time_t now)
             if (res->wd == in->wd && strcmp(res->file, in->name) == 0)              if (res->wd == in->wd && strcmp(res->file, in->name) == 0)
               hit = 1;                hit = 1;
   
          for (ah = daemon->dynamic_dirs; ah; ah = ah->next)          for (dd = daemon->dynamic_dirs; dd; dd = dd->next)
            if (ah->wd == in->wd)            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)  
                           {                            {
                            /* Propagate 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))
                           {                            {
Line 282  int inotify_check(time_t now) Line 335  int inotify_check(time_t 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 295  int inotify_check(time_t now) Line 349  int inotify_check(time_t now)
 }  }
   
 #endif  /* INOTIFY */  #endif  /* INOTIFY */
     

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


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