source: trunk/src/sh_fInotify.c@ 546

Last change on this file since 546 was 506, checked in by katerina, 8 years ago

Fix for ticket #401 (directory creation w/inotify).

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