source: trunk/src/sh_fInotify.c @ 481

Last change on this file since 481 was 481, checked in by katerina, 6 years ago

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

File size: 18.4 KB
RevLine 
[368]1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 2011       Rainer Wichmann                                */
3/*                                                                         */
4/*  This program is free software; you can redistribute it                 */
5/*  and/or modify                                                          */
6/*  it under the terms of the GNU General Public License as                */
7/*  published by                                                           */
8/*  the Free Software Foundation; either version 2 of the License, or      */
9/*  (at your option) any later version.                                    */
10/*                                                                         */
11/*  This program is distributed in the hope that it will be useful,        */
12/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
13/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
14/*  GNU General Public License for more details.                           */
15/*                                                                         */
16/*  You should have received a copy of the GNU General Public License      */
17/*  along with this program; if not, write to the Free Software            */
18/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
19
20/***************************************************************************
21 *
22 * This file provides a module for samhain to use inotify for file checking.
23 *
24 */
25
26#include "config_xor.h"
27
28#if (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
29
30#include "samhain.h"
31#include "sh_utils.h"
32#include "sh_modules.h"
33#include "sh_pthread.h"
34#include "sh_inotify.h"
35#include "sh_unix.h"
36#include "sh_hash.h"
[481]37#include "sh_dbIO.h"
[368]38#include "sh_files.h"
39#include "sh_ignore.h"
40
41#define FIL__  _("sh_fInotify.c")
42
43sh_watches sh_file_watches = SH_INOTIFY_INITIALIZER;
44
[373]45#if defined(HAVE_SYS_INOTIFY_H)
46
[368]47static sh_watches sh_file_missing = SH_INOTIFY_INITIALIZER;
48
49#include <sys/inotify.h>
50
51/* --- Configuration ------- */
52
53static int ShfInotifyActive = S_FALSE;
54
55static unsigned long ShfInotifyWatches = 0;
56
57static int sh_fInotify_active(const char *s) 
58{
59  int value;
60   
61  SL_ENTER(_("sh_fInotify_active"));
62  value = sh_util_flagval(s, &ShfInotifyActive);
63  if (value == 0 && ShfInotifyActive != S_FALSE)
64    {
65      sh.flag.inotify |= SH_INOTIFY_USE;
66      sh.flag.inotify |= SH_INOTIFY_DOSCAN;
67      sh.flag.inotify |= SH_INOTIFY_NEEDINIT;
68    }
69  if (value == 0 && ShfInotifyActive == S_FALSE)
70    {
71      sh.flag.inotify = 0;
72    }
73  SL_RETURN((value), _("sh_fInotify_active"));
74}
75
76static int sh_fInotify_watches(const char *s) 
77{
78  int retval = -1;
79  char * foo;
80  unsigned long value;
81   
82  SL_ENTER(_("sh_fInotify_watches"));
83
84  value = strtoul(s, &foo, 0);
85  if (*foo == '\0')
86    {
87      ShfInotifyWatches = (value > 2147483647) ? 2147483647 /* MAX_INT_32 */: value;
88      retval = 0;
89    }
90  SL_RETURN((retval), _("sh_fInotify_watches"));
91}
92 
93 
94sh_rconf sh_fInotify_table[] = {
95    {
96        N_("inotifyactive"),
97        sh_fInotify_active,
98    },
99    {
100        N_("inotifywatches"),
101        sh_fInotify_watches,
102    },
103    {
104        NULL,
105        NULL
106    }
107};
108
109/* --- End Configuration --- */
110
111static int sh_fInotify_init_internal(void);
112static int sh_fInotify_process(struct inotify_event * event);
113static int sh_fInotify_report(struct inotify_event * event, char * filename,
[481]114                              int class, unsigned long check_flags, int ftype, int rdepth);
[368]115
116int sh_fInotify_init(struct mod_type * arg)
117{
118#ifndef HAVE_PTHREAD
119  (void) arg;
120  return SH_MOD_FAILED;
121#else
122
123  if (ShfInotifyActive == S_FALSE)
124    return SH_MOD_FAILED;
125
126  if (sh.flag.checkSum == SH_CHECK_INIT)
127    return SH_MOD_FAILED;
128
129  if (arg != NULL && arg->initval < 0 &&
130      (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
131    {
132      /* Init from main thread */
[433]133      SH_INOTIFY_IFUSED( sh.flag.inotify |= SH_INOTIFY_DOSCAN;   );
134      SH_INOTIFY_IFUSED( sh.flag.inotify |= SH_INOTIFY_NEEDINIT; );
[368]135
136      if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
137        {
138          return SH_MOD_THREAD;
139        }
140      else
141        {
142          sh.flag.inotify = 0;
143          return SH_MOD_FAILED;
144        }
145    }
[371]146  else if (arg != NULL && arg->initval < 0 &&
147      (sh.flag.isdaemon != S_TRUE && sh.flag.loop != S_TRUE))
148    {
149      sh.flag.inotify = 0;
150      return SH_MOD_FAILED;
151    }
[368]152  else if (arg != NULL && arg->initval == SH_MOD_THREAD &&
153           (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
154    {
155      /* Reconfigure from main thread */
156      /* sh_fInotify_init_internal(); */
[433]157      SH_INOTIFY_IFUSED( sh.flag.inotify |= SH_INOTIFY_DOSCAN;   );
158      SH_INOTIFY_IFUSED( sh.flag.inotify |= SH_INOTIFY_NEEDINIT; );
[368]159      return SH_MOD_THREAD;
160    }
161
162  /* Within thread, init */
163  return sh_fInotify_init_internal();
164#endif
165}
166
167int sh_fInotify_run()
168{
169  ssize_t len = -1;
[382]170  char *  buffer;
[372]171  static int count  = 0;
172  static int count2 = 0;
[368]173
174  if (ShfInotifyActive == S_FALSE)
[382]175    {
176      return SH_MOD_FAILED;
177    }
[368]178
179  if ( (sh.flag.inotify & SH_INOTIFY_DOSCAN) ||
180       (sh.flag.inotify & SH_INOTIFY_NEEDINIT))
181    {
182      if (0 != sh_fInotify_init_internal())
[382]183        {
184          return SH_MOD_FAILED;
185        }
[368]186    }
187
[382]188  buffer = SH_ALLOC(16384);
189
[368]190  /* Blocking read from inotify file descriptor.
191   */
[371]192  len = sh_inotify_read_timeout(buffer, 16384, 1);
[368]193 
194  if (len > 0)
195    {
196      struct inotify_event *event;
197      int i = 0;
198     
199      while (i < len) 
200        {
201          event = (struct inotify_event *) &(buffer[i]);
202         
203          sh_fInotify_process(event);
204         
205          i += sizeof (struct inotify_event) + event->len;
206        }
207
208      if ( (sh.flag.inotify & SH_INOTIFY_DOSCAN) ||
209           (sh.flag.inotify & SH_INOTIFY_NEEDINIT))
210        {
211          if (0 != sh_fInotify_init_internal())
[382]212            {
213              SH_FREE(buffer);
214              return SH_MOD_FAILED;
215            }
[368]216        }
[373]217     }
[368]218
219  /* Re-scan 'dormant' list of sh_file_missing.
220   */ 
221  sh_inotify_recheck_watches (&sh_file_watches, &sh_file_missing);
222
[372]223  ++count; 
224  ++count2;
[371]225
226  if (count >= 10)
227    {
[372]228      count = 0; /* Re-expand glob patterns to discover added files. */
[433]229      SH_INOTIFY_IFUSED( sh.flag.inotify |= SH_INOTIFY_INSCAN; );
[371]230      sh_files_check_globFilePatterns();
[433]231      SH_INOTIFY_IFUSED( sh.flag.inotify &= ~SH_INOTIFY_INSCAN;  );
232      SH_INOTIFY_IFUSED( sh.flag.inotify |= SH_INOTIFY_NEEDINIT; );
[371]233    }
234
[372]235  if (count2 >= 300)
236    {
237      count2 = 0; /* Update baseline database. */
[373]238      if (sh.flag.checkSum == SH_CHECK_CHECK && sh.flag.update == S_TRUE)
[481]239        sh_dbIO_writeout_update ();
[372]240    }
241
[382]242  SH_FREE(buffer);
[368]243  return 0;
244}
245
246/* We block in the read() call on the inotify descriptor,
247 * so we always run.
248 */
249int sh_fInotify_timer(time_t tcurrent)
250{
251  (void) tcurrent;
252  return 1;
253}
254
255int sh_fInotify_cleanup()
256{
257  sh_inotify_purge_dormant(&sh_file_watches);
258  sh_inotify_remove(&sh_file_watches);
259  sh_inotify_init(&sh_file_watches);
260  return 0;
261}
262
263int sh_fInotify_reconf()
264{
265  sh.flag.inotify   = 0;
266
267  ShfInotifyWatches = 0;
268  ShfInotifyActive  = 0;
269
270  return sh_fInotify_cleanup();
271}
272
273#define PROC_WATCHES_MAX _("/proc/sys/fs/inotify/max_user_watches")
274
275static void sh_fInotify_set_nwatches()
276{
[376]277  static int fails = 0;
278
279  if (ShfInotifyWatches == 0 || fails == 1)
[368]280    return;
281
282  if (0 == access(PROC_WATCHES_MAX, R_OK|W_OK)) /* flawfinder: ignore */
283    {
284      FILE * fd;
285
286      if (NULL != (fd = fopen(PROC_WATCHES_MAX, "r+")))
287        {
288          char   str[128];
289          char * ret;
290          char * ptr;
291          unsigned long  wn;
292
293          str[0] = '\0';
294          ret = fgets(str, 128, fd);
295          if (ret && *str != '\0')
296            {
297              wn = strtoul(str, &ptr, 0);
298              if (*ptr == '\0' || *ptr == '\n')
299                {
300                  if (wn < ShfInotifyWatches)
301                    {
302                      sl_snprintf(str, sizeof(str), "%lu\n", ShfInotifyWatches);
303                      (void) fseek(fd, 0L, SEEK_SET);
304                      fputs(str, fd);
305                    }
306                  sl_fclose(FIL__, __LINE__, fd);
307                  return;
308                }
309            }
310          sl_fclose(FIL__, __LINE__, fd);
311        }
312    }
313  SH_MUTEX_LOCK(mutex_thread_nolog);
314  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
[371]315                  _("Cannot set max_user_watches"), 
316                  _("sh_fInotify_set_nwatches"));
[368]317  SH_MUTEX_UNLOCK(mutex_thread_nolog);
[376]318  fails = 1;
[368]319  return;
320}
321
322/* The watch fd is thread specific. To have it in the fInotify thread,
323 * the main thread writes a list of files/dirs to watch, and here we
324 * now pop files from the list to add watches for them.
325 */
326static int sh_fInotify_init_internal()
327{
328  char * filename;
329  int    class;
[372]330  int    type;
[373]331  int    rdepth;
[481]332  unsigned long check_flags;
[368]333  int    retval;
334  int    errnum;
335
336  if (ShfInotifyActive == S_FALSE)
337    return SH_MOD_FAILED;
338
339  /* Wait until file scan is finished.
340   */
341  while((sh.flag.inotify & SH_INOTIFY_DOSCAN) != 0)
342    {
343      retry_msleep(1,0);
344
345      if (ShfInotifyActive == S_FALSE)
346        return SH_MOD_FAILED;
347    }
348
349  sh_fInotify_set_nwatches();
350
351  while (NULL != (filename = sh_inotify_pop_dormant(&sh_file_watches, 
[481]352                                                    &class, &check_flags, 
[373]353                                                    &type, &rdepth)))
[368]354    {
355      retval = sh_inotify_add_watch(filename, &sh_file_watches, &errnum,
[481]356                                    class, check_flags, type, rdepth);
[368]357
358      if (retval < 0)
359        {
360          char errbuf[SH_ERRBUF_SIZE];
361
362          sh_error_message(errnum, errbuf, sizeof(errbuf));
363
364          if ((errnum == ENOENT) || (errnum == EEXIST))
365            {
[402]366              /* (1) Did it exist at init ?
367               */
368              if (sh_hash_have_it (filename) >= 0)
369                {
370                  /* (2) Do we want to report on it ?
371                   */
372                  if (S_FALSE == sh_ignore_chk_del(filename))
373                    {
374                      char * epath = sh_util_safe_name (filename);
375
376                      SH_MUTEX_LOCK(mutex_thread_nolog);
[426]377                      sh_error_handle( SH_ERR_ALL /* debug */,
[402]378                                       FIL__, __LINE__, errnum, MSG_E_SUBGPATH, 
379                                       errbuf, _("sh_fInotify_init_internal"), epath);
380                      SH_MUTEX_UNLOCK(mutex_thread_nolog);
381                      SH_FREE(epath);
382                    }
383                }
[368]384            }
385          else
386            {
387              SH_MUTEX_LOCK(mutex_thread_nolog);
388              sh_error_handle((-1), FIL__, __LINE__, errnum, MSG_E_SUBGEN, 
389                               errbuf, _("sh_fInotify_init_internal"));
390              SH_MUTEX_UNLOCK(mutex_thread_nolog);
391            }
392        }
[382]393      SH_FREE(filename);
[368]394    }
395
396  /* Need this because mod_check() may run after
397   * DOSCAN is finished, hence wouldn't call init().
398   */
[433]399  SH_INOTIFY_IFUSED( sh.flag.inotify &= ~SH_INOTIFY_NEEDINIT; );
[368]400
401  return 0;
402}
403
[373]404static void sh_fInotify_logmask(struct inotify_event * event)
405{
406  char dbgbuf[256];
407 
408  sl_strlcpy (dbgbuf, "inotify mask: ", sizeof(dbgbuf));
409 
410  if (event->mask & IN_ACCESS) sl_strlcat(dbgbuf, "IN_ACCESS ", sizeof(dbgbuf));
411  if (event->mask & IN_ATTRIB) sl_strlcat(dbgbuf, "IN_ATTRIB ", sizeof(dbgbuf));
412  if (event->mask & IN_CLOSE_WRITE) sl_strlcat(dbgbuf, "IN_CLOSE_WRITE ", sizeof(dbgbuf));
413  if (event->mask & IN_CLOSE_NOWRITE) sl_strlcat(dbgbuf, "IN_CLOSE_NOWRITE ", sizeof(dbgbuf));
414  if (event->mask & IN_CREATE) sl_strlcat(dbgbuf, "IN_CREATE ", sizeof(dbgbuf));
415  if (event->mask & IN_DELETE) sl_strlcat(dbgbuf, "IN_DELETE ", sizeof(dbgbuf));
416  if (event->mask & IN_DELETE_SELF) sl_strlcat(dbgbuf, "IN_DELETE_SELF ", sizeof(dbgbuf));
417  if (event->mask & IN_MODIFY) sl_strlcat(dbgbuf, "IN_MODIFY ", sizeof(dbgbuf));
418  if (event->mask & IN_MOVE_SELF) sl_strlcat(dbgbuf, "IN_MOVE_SELF ", sizeof(dbgbuf));
419  if (event->mask & IN_MOVED_FROM) sl_strlcat(dbgbuf, "IN_MOVED_FROM ", sizeof(dbgbuf));
420  if (event->mask & IN_MOVED_TO) sl_strlcat(dbgbuf, "IN_MOVED_TO ", sizeof(dbgbuf));
421  if (event->mask & IN_OPEN) sl_strlcat(dbgbuf, "IN_OPEN ", sizeof(dbgbuf));
422  if (event->mask & IN_IGNORED) sl_strlcat(dbgbuf, "IN_IGNORED ", sizeof(dbgbuf));
423  if (event->mask & IN_ISDIR) sl_strlcat(dbgbuf, "IN_ISDIR ", sizeof(dbgbuf));
424  if (event->mask & IN_Q_OVERFLOW) sl_strlcat(dbgbuf, "IN_Q_OVERFLOW ", sizeof(dbgbuf));
425  if (event->mask & IN_UNMOUNT) sl_strlcat(dbgbuf, "IN_UNMOUNT ", sizeof(dbgbuf));
426 
427  SH_MUTEX_LOCK(mutex_thread_nolog);
428  sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
429                  dbgbuf, _("sh_fInotify_process"));
430  SH_MUTEX_UNLOCK(mutex_thread_nolog);
431}
432
[368]433static int sh_fInotify_process(struct inotify_event * event)
434{
435  int class;
[372]436  int ftype;
[373]437  int rdepth;
[481]438  unsigned long check_flags;
[368]439  char * filename;
[371]440  extern int flag_err_debug;
[368]441
[481]442  if (flag_err_debug == S_TRUE)
[371]443    {
[373]444      sh_fInotify_logmask(event);
[371]445    }
446
[368]447  if (event->wd >= 0)
448    {
449      filename = sh_inotify_search_item(&sh_file_watches, event->wd, 
[481]450                                        &class, &check_flags, &ftype, &rdepth);
[368]451
452      if (filename)
453        {
[481]454          sh_fInotify_report(event, filename, class, check_flags, ftype, rdepth);
[368]455          SH_FREE(filename);
456        }
457      else if (sh.flag.inotify & SH_INOTIFY_NEEDINIT)
458        {
459          return 1;
460        }
461      else if ((event->mask & IN_UNMOUNT) == 0 && (event->mask & IN_IGNORED) == 0)
462        {
463          /* Remove watch ? Seems reasonable. */
464          sh_inotify_rm_watch(NULL, NULL, event->wd);
[372]465
[368]466          SH_MUTEX_LOCK(mutex_thread_nolog);
[402]467          sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, event->wd, MSG_E_SUBGEN, 
[373]468                          _("Watch removed: file path unknown"), 
[368]469                          _("sh_fInotify_process"));
470          SH_MUTEX_UNLOCK(mutex_thread_nolog);
471        }
472    }
473  else if ((event->mask & IN_Q_OVERFLOW) != 0)
474    {
[433]475      SH_INOTIFY_IFUSED( sh.flag.inotify |= SH_INOTIFY_DOSCAN;   );
476      SH_INOTIFY_IFUSED( sh.flag.inotify |= SH_INOTIFY_NEEDINIT; );
477
[373]478      SH_MUTEX_LOCK(mutex_thread_nolog);
479      sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, event->wd, MSG_E_SUBGEN, 
480                      _("Inotify queue overflow"), 
481                      _("sh_fInotify_process"));
482      SH_MUTEX_UNLOCK(mutex_thread_nolog);
[368]483      return 1;
484    }
485
486  return 0;
487}
488
[481]489void sh_fInotify_report_add(char * path, int class, unsigned long check_flags)
[368]490{
491  if (S_FALSE == sh_ignore_chk_new(path))
492    {
493      int reported = 0;
494
495      sh_files_clear_file_reported(path);
496     
[481]497      sh_files_search_file(path, &class, &check_flags, &reported);
[368]498     
[481]499      sh_files_filecheck (class, check_flags, path, NULL,
[368]500                          &reported, 0);
501      if (SH_FFLAG_REPORTED_SET(reported))
502        sh_files_set_file_reported(path);
503    }
504  return;
505}
506
507
508static void sh_fInotify_report_miss(char * name, int level)
509{
510  char * tmp = sh_util_safe_name (name);
511
512  SH_MUTEX_LOCK(mutex_thread_nolog);
513  sh_error_handle (level, FIL__, __LINE__, 0, MSG_FI_MISS, tmp);
514  SH_MUTEX_UNLOCK(mutex_thread_nolog);
[405]515  ++sh.statistics.files_report;
[368]516  SH_FREE(tmp);
517  return;
518}
519
[373]520static int sh_fInotify_report_change (struct inotify_event * event, 
521                                      char * path, char * filename,
[481]522                                      int class, unsigned long check_flags, int ftype)
[368]523{
524  int    reported;
[425]525  int ret;
[368]526
[425]527
528  if (S_FALSE == sh_ignore_chk_mod(path))
[368]529    {
[481]530      ret  = sh_files_search_file(path, &class, &check_flags, &reported);
[425]531
532      if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
533        {
534          ; /* do nothing, watch was for directory monitored as file only */
535        }
536      else
537        {
[481]538          sh_files_filecheck (class, check_flags, filename,
[425]539                              (event->len > 0) ? event->name : NULL,
540                              &reported, 0);
541        }
[368]542    }
[373]543  return 0;
544}
[368]545
546
[373]547static int sh_fInotify_report_missing (struct inotify_event * event, 
548                                       char * path,
[481]549                                       int class, unsigned long check_flags, int ftype)
[373]550{
551  int    reported;
552  int isdir = (event->mask & IN_ISDIR);
553  int level = (class == SH_LEVEL_ALLIGNORE) ? 
554    ShDFLevel[class] : 
555    ShDFLevel[(isdir == 0) ? SH_ERR_T_FILE : SH_ERR_T_DIR];
556
557  if (S_FALSE == sh_ignore_chk_del(path))
[368]558    {
[373]559      if (0 != hashreport_missing(path, level))
[368]560        {
[481]561          int ret = sh_files_search_file(path, &class, &check_flags, &reported);
[373]562         
563          if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
[368]564            {
[373]565              ; /* do nothing, watch was for directory monitored as file only */
[368]566            }
[373]567          else
568            {
569              /* Removal of a directory triggers:
570               * (1) IN_DELETE IN_ISDIR
571               * (2) IN_DELETE_SELF
572               */
573              if ((event->mask & IN_DELETE_SELF) == 0)
574                sh_fInotify_report_miss(path, level);
575            }
[368]576        }
[373]577    }
[368]578
[373]579  sh_hash_set_missing(path);
[481]580
[373]581  if (sh.flag.reportonce == S_TRUE)
582    sh_files_set_file_reported(path);
[368]583
[373]584  /* Move to 'dormant' list, if not file within directory.
585   */
586  if (event->len == 0)
587    sh_inotify_rm_watch(&sh_file_watches, &sh_file_missing, event->wd);
588
589  return 0;
590}
591
592static int sh_fInotify_report_added (struct inotify_event * event, 
593                                     char * path, char * filename,
[481]594                                     int class, unsigned long check_flags, 
[373]595                                     int ftype, int rdepth)
596{
597  if (S_FALSE == sh_ignore_chk_new(path))
[368]598    {
[373]599      int reported;
600      int ret;
601      int retD = 0;
602      int rdepthD = rdepth;
603     
604      sh_files_clear_file_reported(path);
605         
[481]606      ret = sh_files_search_file(path, &class, &check_flags, &reported);
[373]607     
608      if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
[368]609        {
[373]610          ; /* do nothing, watch was for directory monitored as file only */
611        }
612      else
613        {
614          int classD = class;
615          int reportedD = reported; 
[481]616          unsigned long check_flagsD = check_flags;
[368]617         
[373]618          if (event->mask & IN_ISDIR)
[372]619            {
[481]620              retD = sh_files_search_dir(path, &classD, &check_flagsD, 
[373]621                                         &reportedD, &rdepthD);
622              if (retD != 0)
623                {
624                  if (ret == 0)
625                    {
626                      class      = classD;
[481]627                      check_flags = check_flagsD;
[373]628                    }
629                }
[372]630            }
[373]631         
[481]632          sh_files_filecheck (class, check_flags, filename,
[373]633                              (event->len > 0) ? event->name : NULL,
634                              &reported, 0);
635         
636          if (event->mask & IN_ISDIR)
[372]637            {
[433]638              SH_INOTIFY_IFUSED( sh.flag.inotify |= SH_INOTIFY_INSCAN;   );
[481]639              sh_files_checkdir (classD, check_flagsD, rdepthD, 
[373]640                                 path, (event->len > 0) ? event->name : NULL);
[433]641              SH_INOTIFY_IFUSED( sh.flag.inotify &= ~SH_INOTIFY_INSCAN;  );
642              SH_INOTIFY_IFUSED( sh.flag.inotify |= SH_INOTIFY_NEEDINIT; );
[373]643              sh_dirs_reset  ();
644              sh_files_reset ();
[372]645            }
[373]646         
647        }
648     
649      if (SH_FFLAG_REPORTED_SET(reported))
650        sh_files_set_file_reported(path);
651     
652      if ((ret != 0) || (event->mask & IN_ISDIR))
653        {
654          sh_inotify_add_watch(path, &sh_file_watches, &ret,
[481]655                               class, check_flags, 
[373]656                               (event->mask & IN_ISDIR)?SH_INOTIFY_DIR:SH_INOTIFY_FILE, 
657                               rdepthD);
658        }
659    }
660  return 0;
661}
[372]662
[373]663static int sh_fInotify_report(struct inotify_event * event, char * filename,
[481]664                              int class, unsigned long check_flags, int ftype, int rdepth)
[373]665{
666  char * fullpath = NULL;
667  char * path;
[371]668
[373]669  if (event->len > 0)
670    {
671      fullpath = sh_util_strconcat(filename, "/", event->name, NULL);
672      path = fullpath;
[368]673    }
[373]674  else
675    {
676      path = filename;
677    }
[368]678
[373]679  if ( (event->mask & (IN_ATTRIB|IN_MODIFY)) != 0)
680    {
681      sh_fInotify_report_change (event, path, filename,
[481]682                                 class, check_flags, ftype);
[373]683    }
684  else if ((event->mask & (IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF|IN_MOVED_FROM)) != 0)
685    {
686      sh_fInotify_report_missing (event, path,
[481]687                                  class, check_flags, ftype);
[373]688   }
689  else if((event->mask & (IN_CREATE|IN_MOVED_TO)) != 0)
690    {
691      sh_fInotify_report_added (event, path, filename,
[481]692                                class, check_flags, 
[373]693                                ftype, rdepth);
694    }
695
696  if (fullpath)
697    SH_FREE(fullpath);
698
[368]699  return 0;
700}
701
702
703#endif
704
705#endif
Note: See TracBrowser for help on using the repository browser.