Ignore:
Timestamp:
Nov 1, 2011, 9:29:51 PM (13 years ago)
Author:
katerina
Message:

Patch for ticket #265 (inotify). Handling of added subdirectories and file list rescan.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/sh_fInotify.c

    r372 r373  
    4242sh_watches sh_file_watches = SH_INOTIFY_INITIALIZER;
    4343
     44#if defined(HAVE_SYS_INOTIFY_H)
     45
    4446static sh_watches sh_file_missing = SH_INOTIFY_INITIALIZER;
    45 
    46 #if defined(HAVE_SYS_INOTIFY_H)
    4747
    4848#include <sys/inotify.h>
     
    111111static int sh_fInotify_process(struct inotify_event * event);
    112112static int sh_fInotify_report(struct inotify_event * event, char * filename,
    113                               int class, unsigned long check_mask, int ftype);
     113                              int class, unsigned long check_mask, int ftype, int rdepth);
    114114
    115115int sh_fInotify_init(struct mod_type * arg)
     
    205205           return SH_MOD_FAILED;
    206206        }
    207  
    208     }
     207     }
    209208
    210209  /* Re-scan 'dormant' list of sh_file_missing.
     
    218217    {
    219218      count = 0; /* Re-expand glob patterns to discover added files. */
     219      sh.flag.inotify |= SH_INOTIFY_INSCAN;
    220220      sh_files_check_globFilePatterns();
     221      sh.flag.inotify &= ~SH_INOTIFY_INSCAN;
     222      sh.flag.inotify |= SH_INOTIFY_NEEDINIT;
    221223    }
    222224
     
    224226    {
    225227      count2 = 0; /* Update baseline database. */
    226       if (sh.flag.checkSum == SH_CHECK_CHECK &&
    227           sh.flag.update == S_TRUE)
     228      if (sh.flag.checkSum == SH_CHECK_CHECK && sh.flag.update == S_TRUE)
    228229        sh_hash_writeout ();
    229230    }
     
    314315  int    class;
    315316  int    type;
     317  int    rdepth;
    316318  unsigned long check_mask;
    317319  int    retval;
     
    334336
    335337  while (NULL != (filename = sh_inotify_pop_dormant(&sh_file_watches,
    336                                                     &class, &check_mask, &type)))
     338                                                    &class, &check_mask,
     339                                                    &type, &rdepth)))
    337340    {
    338341      retval = sh_inotify_add_watch(filename, &sh_file_watches, &errnum,
    339                                     class, check_mask, type);
     342                                    class, check_mask, type, rdepth);
    340343
    341344      if (retval < 0)
     
    375378}
    376379
     380static void sh_fInotify_logmask(struct inotify_event * event)
     381{
     382  char dbgbuf[256];
     383 
     384  sl_strlcpy (dbgbuf, "inotify mask: ", sizeof(dbgbuf));
     385 
     386  if (event->mask & IN_ACCESS) sl_strlcat(dbgbuf, "IN_ACCESS ", sizeof(dbgbuf));
     387  if (event->mask & IN_ATTRIB) sl_strlcat(dbgbuf, "IN_ATTRIB ", sizeof(dbgbuf));
     388  if (event->mask & IN_CLOSE_WRITE) sl_strlcat(dbgbuf, "IN_CLOSE_WRITE ", sizeof(dbgbuf));
     389  if (event->mask & IN_CLOSE_NOWRITE) sl_strlcat(dbgbuf, "IN_CLOSE_NOWRITE ", sizeof(dbgbuf));
     390  if (event->mask & IN_CREATE) sl_strlcat(dbgbuf, "IN_CREATE ", sizeof(dbgbuf));
     391  if (event->mask & IN_DELETE) sl_strlcat(dbgbuf, "IN_DELETE ", sizeof(dbgbuf));
     392  if (event->mask & IN_DELETE_SELF) sl_strlcat(dbgbuf, "IN_DELETE_SELF ", sizeof(dbgbuf));
     393  if (event->mask & IN_MODIFY) sl_strlcat(dbgbuf, "IN_MODIFY ", sizeof(dbgbuf));
     394  if (event->mask & IN_MOVE_SELF) sl_strlcat(dbgbuf, "IN_MOVE_SELF ", sizeof(dbgbuf));
     395  if (event->mask & IN_MOVED_FROM) sl_strlcat(dbgbuf, "IN_MOVED_FROM ", sizeof(dbgbuf));
     396  if (event->mask & IN_MOVED_TO) sl_strlcat(dbgbuf, "IN_MOVED_TO ", sizeof(dbgbuf));
     397  if (event->mask & IN_OPEN) sl_strlcat(dbgbuf, "IN_OPEN ", sizeof(dbgbuf));
     398  if (event->mask & IN_IGNORED) sl_strlcat(dbgbuf, "IN_IGNORED ", sizeof(dbgbuf));
     399  if (event->mask & IN_ISDIR) sl_strlcat(dbgbuf, "IN_ISDIR ", sizeof(dbgbuf));
     400  if (event->mask & IN_Q_OVERFLOW) sl_strlcat(dbgbuf, "IN_Q_OVERFLOW ", sizeof(dbgbuf));
     401  if (event->mask & IN_UNMOUNT) sl_strlcat(dbgbuf, "IN_UNMOUNT ", sizeof(dbgbuf));
     402 
     403  /* fprintf(stderr, "FIXME: %s\n", dbgbuf); */
     404 
     405  SH_MUTEX_LOCK(mutex_thread_nolog);
     406  sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN,
     407                  dbgbuf, _("sh_fInotify_process"));
     408  SH_MUTEX_UNLOCK(mutex_thread_nolog);
     409}
     410
    377411static int sh_fInotify_process(struct inotify_event * event)
    378412{
    379413  int class;
    380414  int ftype;
     415  int rdepth;
    381416  unsigned long check_mask;
    382417  char * filename;
     
    385420  if (flag_err_debug == SL_TRUE)
    386421    {
    387       char dbgbuf[256];
    388 
    389       sl_strlcpy (dbgbuf, "inotify mask: ", sizeof(dbgbuf));
    390 
    391       if (event->mask & IN_ACCESS) sl_strlcat(dbgbuf, "IN_ACCESS ", sizeof(dbgbuf));
    392       if (event->mask & IN_ATTRIB) sl_strlcat(dbgbuf, "IN_ATTRIB ", sizeof(dbgbuf));
    393       if (event->mask & IN_CLOSE_WRITE) sl_strlcat(dbgbuf, "IN_CLOSE_WRITE ", sizeof(dbgbuf));
    394       if (event->mask & IN_CLOSE_NOWRITE) sl_strlcat(dbgbuf, "IN_CLOSE_NOWRITE ", sizeof(dbgbuf));
    395       if (event->mask & IN_CREATE) sl_strlcat(dbgbuf, "IN_CREATE ", sizeof(dbgbuf));
    396       if (event->mask & IN_DELETE) sl_strlcat(dbgbuf, "IN_DELETE ", sizeof(dbgbuf));
    397       if (event->mask & IN_DELETE_SELF) sl_strlcat(dbgbuf, "IN_DELETE_SELF ", sizeof(dbgbuf));
    398       if (event->mask & IN_MODIFY) sl_strlcat(dbgbuf, "IN_MODIFY ", sizeof(dbgbuf));
    399       if (event->mask & IN_MOVE_SELF) sl_strlcat(dbgbuf, "IN_MOVE_SELF ", sizeof(dbgbuf));
    400       if (event->mask & IN_MOVED_FROM) sl_strlcat(dbgbuf, "IN_MOVED_FROM ", sizeof(dbgbuf));
    401       if (event->mask & IN_MOVED_TO) sl_strlcat(dbgbuf, "IN_MOVED_TO ", sizeof(dbgbuf));
    402       if (event->mask & IN_OPEN) sl_strlcat(dbgbuf, "IN_OPEN ", sizeof(dbgbuf));
    403       if (event->mask & IN_IGNORED) sl_strlcat(dbgbuf, "IN_IGNORED ", sizeof(dbgbuf));
    404       if (event->mask & IN_ISDIR) sl_strlcat(dbgbuf, "IN_ISDIR ", sizeof(dbgbuf));
    405       if (event->mask & IN_Q_OVERFLOW) sl_strlcat(dbgbuf, "IN_Q_OVERFLOW ", sizeof(dbgbuf));
    406       if (event->mask & IN_UNMOUNT) sl_strlcat(dbgbuf, "IN_UNMOUNT ", sizeof(dbgbuf));
    407 
    408       SH_MUTEX_LOCK(mutex_thread_nolog);
    409       sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN,
    410                       dbgbuf, _("sh_fInotify_process"));
    411       SH_MUTEX_UNLOCK(mutex_thread_nolog);
    412     }
    413 
     422      sh_fInotify_logmask(event);
     423    }
    414424
    415425  if (event->wd >= 0)
    416426    {
    417427      filename = sh_inotify_search_item(&sh_file_watches, event->wd,
    418                                         &class, &check_mask, &ftype);
     428                                        &class, &check_mask, &ftype, &rdepth);
    419429
    420430      if (filename)
    421431        {
    422           sh_fInotify_report(event, filename, class, check_mask, ftype);
    423 
     432          sh_fInotify_report(event, filename, class, check_mask, ftype, rdepth);
    424433          SH_FREE(filename);
    425434        }
     
    435444          SH_MUTEX_LOCK(mutex_thread_nolog);
    436445          sh_error_handle((-1), FIL__, __LINE__, event->wd, MSG_E_SUBGEN,
    437                           _("Watch removed: internal error - file path unknown"),
     446                          _("Watch removed: file path unknown"),
    438447                          _("sh_fInotify_process"));
    439448          SH_MUTEX_UNLOCK(mutex_thread_nolog);
     
    444453      sh.flag.inotify |= SH_INOTIFY_DOSCAN;
    445454      sh.flag.inotify |= SH_INOTIFY_NEEDINIT;
     455      SH_MUTEX_LOCK(mutex_thread_nolog);
     456      sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, event->wd, MSG_E_SUBGEN,
     457                      _("Inotify queue overflow"),
     458                      _("sh_fInotify_process"));
     459      SH_MUTEX_UNLOCK(mutex_thread_nolog);
    446460      return 1;
    447461    }
     
    481495}
    482496
    483 static int sh_fInotify_report(struct inotify_event * event, char * filename,
    484                               int class, unsigned long check_mask, int ftype)
    485 {
    486   char * fullpath = NULL;
    487   char * path;
     497static int sh_fInotify_report_change (struct inotify_event * event,
     498                                      char * path, char * filename,
     499                                      int class, unsigned long check_mask, int ftype)
     500{
    488501  int    reported;
    489 
    490   if (event->len > 0)
    491     {
    492       fullpath = sh_util_strconcat(filename, "/", event->name, NULL);
    493       path = fullpath;
     502  int ret = sh_files_search_file(path, &class, &check_mask, &reported);
     503
     504  if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
     505    {
     506      ; /* do nothing, watch was for directory monitored as file only */
    494507    }
    495508  else
    496509    {
    497       path = filename;
    498     }
    499 
    500   if ( (event->mask & (IN_ATTRIB|IN_MODIFY)) != 0)
    501     {
    502       int ret = sh_files_search_file(path, &class, &check_mask, &reported);
    503 
     510      sh_files_filecheck (class, check_mask, filename,
     511                          (event->len > 0) ? event->name : NULL,
     512                          &reported, 0);
     513    }
     514  return 0;
     515}
     516
     517
     518static int sh_fInotify_report_missing (struct inotify_event * event,
     519                                       char * path,
     520                                       int class, unsigned long check_mask, int ftype)
     521{
     522  int    reported;
     523  int isdir = (event->mask & IN_ISDIR);
     524  int level = (class == SH_LEVEL_ALLIGNORE) ?
     525    ShDFLevel[class] :
     526    ShDFLevel[(isdir == 0) ? SH_ERR_T_FILE : SH_ERR_T_DIR];
     527
     528  if (S_FALSE == sh_ignore_chk_del(path))
     529    {
     530      if (0 != hashreport_missing(path, level))
     531        {
     532          int ret = sh_files_search_file(path, &class, &check_mask, &reported);
     533         
     534          if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
     535            {
     536              ; /* do nothing, watch was for directory monitored as file only */
     537            }
     538          else
     539            {
     540              /* Removal of a directory triggers:
     541               * (1) IN_DELETE IN_ISDIR
     542               * (2) IN_DELETE_SELF
     543               */
     544              if ((event->mask & IN_DELETE_SELF) == 0)
     545                sh_fInotify_report_miss(path, level);
     546            }
     547        }
     548    }
     549
     550#ifndef REPLACE_OLD
     551  sh_hash_set_visited_true(path);
     552#else
     553  sh_hash_set_missing(path);
     554#endif
     555  if (sh.flag.reportonce == S_TRUE)
     556    sh_files_set_file_reported(path);
     557
     558  /* Move to 'dormant' list, if not file within directory.
     559   */
     560  if (event->len == 0)
     561    sh_inotify_rm_watch(&sh_file_watches, &sh_file_missing, event->wd);
     562
     563  return 0;
     564}
     565
     566static int sh_fInotify_report_added (struct inotify_event * event,
     567                                     char * path, char * filename,
     568                                     int class, unsigned long check_mask,
     569                                     int ftype, int rdepth)
     570{
     571  if (S_FALSE == sh_ignore_chk_new(path))
     572    {
     573      int reported;
     574      int ret;
     575      int retD = 0;
     576      int rdepthD = rdepth;
     577     
     578      sh_files_clear_file_reported(path);
     579         
     580      ret = sh_files_search_file(path, &class, &check_mask, &reported);
     581     
    504582      if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
    505583        {
    506           ; /* do nothing */
     584          ; /* do nothing, watch was for directory monitored as file only */
    507585        }
    508586      else
    509587        {
     588          int classD = class;
     589          int reportedD = reported;
     590          unsigned long check_maskD = check_mask;
     591         
     592          if (event->mask & IN_ISDIR)
     593            {
     594              retD = sh_files_search_dir(path, &classD, &check_maskD,
     595                                         &reportedD, &rdepthD);
     596              if (retD != 0)
     597                {
     598                  if (ret == 0)
     599                    {
     600                      class      = classD;
     601                      check_mask = check_maskD;
     602                    }
     603                }
     604            }
     605         
    510606          sh_files_filecheck (class, check_mask, filename,
    511607                              (event->len > 0) ? event->name : NULL,
    512608                              &reported, 0);
    513         }
     609         
     610          if (event->mask & IN_ISDIR)
     611            {
     612              sh.flag.inotify |= SH_INOTIFY_INSCAN;
     613              sh_files_checkdir (classD, check_maskD, rdepthD,
     614                                 path, (event->len > 0) ? event->name : NULL);
     615              sh.flag.inotify &= ~SH_INOTIFY_INSCAN;
     616              sh.flag.inotify |= SH_INOTIFY_NEEDINIT;
     617              sh_dirs_reset  ();
     618              sh_files_reset ();
     619            }
     620         
     621        }
     622     
     623      if (SH_FFLAG_REPORTED_SET(reported))
     624        sh_files_set_file_reported(path);
     625     
     626      if ((ret != 0) || (event->mask & IN_ISDIR))
     627        {
     628          sh_inotify_add_watch(path, &sh_file_watches, &ret,
     629                               class, check_mask,
     630                               (event->mask & IN_ISDIR)?SH_INOTIFY_DIR:SH_INOTIFY_FILE,
     631                               rdepthD);
     632        }
     633    }
     634  return 0;
     635}
     636
     637static int sh_fInotify_report(struct inotify_event * event, char * filename,
     638                              int class, unsigned long check_mask, int ftype, int rdepth)
     639{
     640  char * fullpath = NULL;
     641  char * path;
     642
     643  if (event->len > 0)
     644    {
     645      fullpath = sh_util_strconcat(filename, "/", event->name, NULL);
     646      path = fullpath;
     647    }
     648  else
     649    {
     650      path = filename;
     651    }
     652
     653  if ( (event->mask & (IN_ATTRIB|IN_MODIFY)) != 0)
     654    {
     655      sh_fInotify_report_change (event, path, filename,
     656                                 class, check_mask, ftype);
    514657    }
    515658  else if ((event->mask & (IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF|IN_MOVED_FROM)) != 0)
    516659    {
    517       int isdir = (event->mask & IN_ISDIR);
    518       int level = (class == SH_LEVEL_ALLIGNORE) ?
    519         ShDFLevel[class] :
    520         ShDFLevel[(isdir == 0) ? SH_ERR_T_FILE : SH_ERR_T_DIR];
    521 
    522       if (S_FALSE == sh_ignore_chk_del(path))
    523         {
    524           if (0 != hashreport_missing(path, level))
    525             {
    526               int ret = sh_files_search_file(path, &class, &check_mask, &reported);
    527 
    528               if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
    529                 {
    530                   ; /* do nothing */
    531                 }
    532               else
    533                 {
    534                   sh_fInotify_report_miss(path, level);
    535                 }
    536             }
    537         }
    538 
    539 #ifndef REPLACE_OLD
    540       sh_hash_set_visited_true(path);
    541 #else
    542       sh_hash_set_missing(path);
     660      sh_fInotify_report_missing (event, path,
     661                                  class, check_mask, ftype);
     662   }
     663  else if((event->mask & (IN_CREATE|IN_MOVED_TO)) != 0)
     664    {
     665      sh_fInotify_report_added (event, path, filename,
     666                                class, check_mask,
     667                                ftype, rdepth);
     668    }
     669
     670  if (fullpath)
     671    SH_FREE(fullpath);
     672
     673  return 0;
     674}
     675
     676
    543677#endif
    544       if (sh.flag.reportonce == S_TRUE)
    545         sh_files_set_file_reported(path);
    546 
    547       /* Move to 'dormant' list, if not file within directory.
    548        */
    549       if (event->len == 0)
    550         sh_inotify_rm_watch(&sh_file_watches, &sh_file_missing, event->wd);
    551     }
    552   else if((event->mask & (IN_CREATE|IN_MOVED_TO)) != 0)
    553     {
    554       if (S_FALSE == sh_ignore_chk_new(path))
    555         {
    556           int ret;
    557 
    558           sh_files_clear_file_reported(path);
    559          
    560           ret = sh_files_search_file(path, &class, &check_mask, &reported);
    561          
    562           if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
    563             {
    564               ; /* do nothing */
    565             }
    566           else
    567             {
    568               sh_files_filecheck (class, check_mask, filename,
    569                                   (event->len > 0) ? event->name : NULL,
    570                                   &reported, 0);
    571             }
    572 
    573           if (SH_FFLAG_REPORTED_SET(reported))
    574             sh_files_set_file_reported(path);
    575 
    576           if (ret != 0)
    577             {
    578               sh_inotify_add_watch(path, &sh_file_watches, &ret,
    579                                    class, check_mask, SH_INOTIFY_FILE);
    580             }
    581         }
    582     }
    583 
    584   return 0;
    585 }
    586 
    587678
    588679#endif
    589 
    590 #endif
Note: See TracChangeset for help on using the changeset viewer.