Index: trunk/src/samhain.c
===================================================================
--- trunk/src/samhain.c	(revision 372)
+++ trunk/src/samhain.c	(revision 373)
@@ -2001,4 +2001,5 @@
 	  (flag_check_1 == 1 || flag_check_2 == 1))
 	{
+	  sh.flag.inotify |= SH_INOTIFY_INSCAN;
 	  /* Refresh list files matching glob patterns.
 	   */
@@ -2062,4 +2063,5 @@
 	  flag_check_2 = 0;
 	  check_done   = 1;
+	  sh.flag.inotify &= ~SH_INOTIFY_INSCAN;
 	  sh.flag.inotify &= ~SH_INOTIFY_DOSCAN;
 
Index: trunk/src/sh_audit.c
===================================================================
--- trunk/src/sh_audit.c	(revision 372)
+++ trunk/src/sh_audit.c	(revision 373)
@@ -224,5 +224,5 @@
 }
 
-void sh_audit_mark (char * file)
+void sh_audit_mark (const char * file)
 {
   static int flushRules = 0;
@@ -372,5 +372,5 @@
   return 0;
 }
-void sh_audit_mark (char * file)
+void sh_audit_mark (const char * file)
 {
   (void) file;
Index: trunk/src/sh_fInotify.c
===================================================================
--- trunk/src/sh_fInotify.c	(revision 372)
+++ trunk/src/sh_fInotify.c	(revision 373)
@@ -42,7 +42,7 @@
 sh_watches sh_file_watches = SH_INOTIFY_INITIALIZER;
 
+#if defined(HAVE_SYS_INOTIFY_H) 
+
 static sh_watches sh_file_missing = SH_INOTIFY_INITIALIZER;
-
-#if defined(HAVE_SYS_INOTIFY_H) 
 
 #include <sys/inotify.h>
@@ -111,5 +111,5 @@
 static int sh_fInotify_process(struct inotify_event * event);
 static int sh_fInotify_report(struct inotify_event * event, char * filename,
-			      int class, unsigned long check_mask, int ftype);
+			      int class, unsigned long check_mask, int ftype, int rdepth);
 
 int sh_fInotify_init(struct mod_type * arg)
@@ -205,6 +205,5 @@
 	   return SH_MOD_FAILED;
 	}
- 
-    }
+     }
 
   /* Re-scan 'dormant' list of sh_file_missing. 
@@ -218,5 +217,8 @@
     {
       count = 0; /* Re-expand glob patterns to discover added files. */
+      sh.flag.inotify |= SH_INOTIFY_INSCAN;
       sh_files_check_globFilePatterns();
+      sh.flag.inotify &= ~SH_INOTIFY_INSCAN;
+      sh.flag.inotify |= SH_INOTIFY_NEEDINIT;
     }
 
@@ -224,6 +226,5 @@
     {
       count2 = 0; /* Update baseline database. */
-      if (sh.flag.checkSum == SH_CHECK_CHECK && 
-	  sh.flag.update == S_TRUE)
+      if (sh.flag.checkSum == SH_CHECK_CHECK && sh.flag.update == S_TRUE)
 	sh_hash_writeout ();
     }
@@ -314,4 +315,5 @@
   int    class;
   int    type;
+  int    rdepth;
   unsigned long check_mask;
   int    retval;
@@ -334,8 +336,9 @@
 
   while (NULL != (filename = sh_inotify_pop_dormant(&sh_file_watches, 
-						    &class, &check_mask, &type)))
+						    &class, &check_mask, 
+						    &type, &rdepth)))
     {
       retval = sh_inotify_add_watch(filename, &sh_file_watches, &errnum,
-				    class, check_mask, type);
+				    class, check_mask, type, rdepth);
 
       if (retval < 0)
@@ -375,8 +378,40 @@
 }
 
+static void sh_fInotify_logmask(struct inotify_event * event)
+{
+  char dbgbuf[256];
+  
+  sl_strlcpy (dbgbuf, "inotify mask: ", sizeof(dbgbuf));
+  
+  if (event->mask & IN_ACCESS) sl_strlcat(dbgbuf, "IN_ACCESS ", sizeof(dbgbuf));
+  if (event->mask & IN_ATTRIB) sl_strlcat(dbgbuf, "IN_ATTRIB ", sizeof(dbgbuf));
+  if (event->mask & IN_CLOSE_WRITE) sl_strlcat(dbgbuf, "IN_CLOSE_WRITE ", sizeof(dbgbuf));
+  if (event->mask & IN_CLOSE_NOWRITE) sl_strlcat(dbgbuf, "IN_CLOSE_NOWRITE ", sizeof(dbgbuf));
+  if (event->mask & IN_CREATE) sl_strlcat(dbgbuf, "IN_CREATE ", sizeof(dbgbuf));
+  if (event->mask & IN_DELETE) sl_strlcat(dbgbuf, "IN_DELETE ", sizeof(dbgbuf));
+  if (event->mask & IN_DELETE_SELF) sl_strlcat(dbgbuf, "IN_DELETE_SELF ", sizeof(dbgbuf));
+  if (event->mask & IN_MODIFY) sl_strlcat(dbgbuf, "IN_MODIFY ", sizeof(dbgbuf));
+  if (event->mask & IN_MOVE_SELF) sl_strlcat(dbgbuf, "IN_MOVE_SELF ", sizeof(dbgbuf));
+  if (event->mask & IN_MOVED_FROM) sl_strlcat(dbgbuf, "IN_MOVED_FROM ", sizeof(dbgbuf));
+  if (event->mask & IN_MOVED_TO) sl_strlcat(dbgbuf, "IN_MOVED_TO ", sizeof(dbgbuf));
+  if (event->mask & IN_OPEN) sl_strlcat(dbgbuf, "IN_OPEN ", sizeof(dbgbuf));
+  if (event->mask & IN_IGNORED) sl_strlcat(dbgbuf, "IN_IGNORED ", sizeof(dbgbuf));
+  if (event->mask & IN_ISDIR) sl_strlcat(dbgbuf, "IN_ISDIR ", sizeof(dbgbuf));
+  if (event->mask & IN_Q_OVERFLOW) sl_strlcat(dbgbuf, "IN_Q_OVERFLOW ", sizeof(dbgbuf));
+  if (event->mask & IN_UNMOUNT) sl_strlcat(dbgbuf, "IN_UNMOUNT ", sizeof(dbgbuf));
+  
+  /* fprintf(stderr, "FIXME: %s\n", dbgbuf); */
+  
+  SH_MUTEX_LOCK(mutex_thread_nolog);
+  sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+		  dbgbuf, _("sh_fInotify_process"));
+  SH_MUTEX_UNLOCK(mutex_thread_nolog);
+}
+
 static int sh_fInotify_process(struct inotify_event * event)
 {
   int class;
   int ftype;
+  int rdepth;
   unsigned long check_mask;
   char * filename;
@@ -385,41 +420,15 @@
   if (flag_err_debug == SL_TRUE)
     {
-      char dbgbuf[256];
-
-      sl_strlcpy (dbgbuf, "inotify mask: ", sizeof(dbgbuf));
-
-      if (event->mask & IN_ACCESS) sl_strlcat(dbgbuf, "IN_ACCESS ", sizeof(dbgbuf));
-      if (event->mask & IN_ATTRIB) sl_strlcat(dbgbuf, "IN_ATTRIB ", sizeof(dbgbuf));
-      if (event->mask & IN_CLOSE_WRITE) sl_strlcat(dbgbuf, "IN_CLOSE_WRITE ", sizeof(dbgbuf));
-      if (event->mask & IN_CLOSE_NOWRITE) sl_strlcat(dbgbuf, "IN_CLOSE_NOWRITE ", sizeof(dbgbuf));
-      if (event->mask & IN_CREATE) sl_strlcat(dbgbuf, "IN_CREATE ", sizeof(dbgbuf));
-      if (event->mask & IN_DELETE) sl_strlcat(dbgbuf, "IN_DELETE ", sizeof(dbgbuf));
-      if (event->mask & IN_DELETE_SELF) sl_strlcat(dbgbuf, "IN_DELETE_SELF ", sizeof(dbgbuf));
-      if (event->mask & IN_MODIFY) sl_strlcat(dbgbuf, "IN_MODIFY ", sizeof(dbgbuf));
-      if (event->mask & IN_MOVE_SELF) sl_strlcat(dbgbuf, "IN_MOVE_SELF ", sizeof(dbgbuf));
-      if (event->mask & IN_MOVED_FROM) sl_strlcat(dbgbuf, "IN_MOVED_FROM ", sizeof(dbgbuf));
-      if (event->mask & IN_MOVED_TO) sl_strlcat(dbgbuf, "IN_MOVED_TO ", sizeof(dbgbuf));
-      if (event->mask & IN_OPEN) sl_strlcat(dbgbuf, "IN_OPEN ", sizeof(dbgbuf));
-      if (event->mask & IN_IGNORED) sl_strlcat(dbgbuf, "IN_IGNORED ", sizeof(dbgbuf));
-      if (event->mask & IN_ISDIR) sl_strlcat(dbgbuf, "IN_ISDIR ", sizeof(dbgbuf));
-      if (event->mask & IN_Q_OVERFLOW) sl_strlcat(dbgbuf, "IN_Q_OVERFLOW ", sizeof(dbgbuf));
-      if (event->mask & IN_UNMOUNT) sl_strlcat(dbgbuf, "IN_UNMOUNT ", sizeof(dbgbuf));
-
-      SH_MUTEX_LOCK(mutex_thread_nolog);
-      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
-		      dbgbuf, _("sh_fInotify_process"));
-      SH_MUTEX_UNLOCK(mutex_thread_nolog);
-    }
-
+      sh_fInotify_logmask(event);
+    }
 
   if (event->wd >= 0)
     {
       filename = sh_inotify_search_item(&sh_file_watches, event->wd, 
-					&class, &check_mask, &ftype);
+					&class, &check_mask, &ftype, &rdepth);
 
       if (filename)
 	{
-	  sh_fInotify_report(event, filename, class, check_mask, ftype);
-
+	  sh_fInotify_report(event, filename, class, check_mask, ftype, rdepth);
 	  SH_FREE(filename);
 	}
@@ -435,5 +444,5 @@
 	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle((-1), FIL__, __LINE__, event->wd, MSG_E_SUBGEN, 
-			  _("Watch removed: internal error - file path unknown"), 
+			  _("Watch removed: file path unknown"), 
 			  _("sh_fInotify_process"));
 	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
@@ -444,4 +453,9 @@
       sh.flag.inotify |= SH_INOTIFY_DOSCAN;
       sh.flag.inotify |= SH_INOTIFY_NEEDINIT;
+      SH_MUTEX_LOCK(mutex_thread_nolog);
+      sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, event->wd, MSG_E_SUBGEN, 
+		      _("Inotify queue overflow"), 
+		      _("sh_fInotify_process"));
+      SH_MUTEX_UNLOCK(mutex_thread_nolog);
       return 1;
     }
@@ -481,110 +495,185 @@
 }
 
-static int sh_fInotify_report(struct inotify_event * event, char * filename,
-			      int class, unsigned long check_mask, int ftype)
-{
-  char * fullpath = NULL;
-  char * path;
+static int sh_fInotify_report_change (struct inotify_event * event, 
+				      char * path, char * filename,
+				      int class, unsigned long check_mask, int ftype)
+{
   int    reported;
-
-  if (event->len > 0)
-    {
-      fullpath = sh_util_strconcat(filename, "/", event->name, NULL);
-      path = fullpath;
+  int ret = sh_files_search_file(path, &class, &check_mask, &reported);
+
+  if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
+    {
+      ; /* do nothing, watch was for directory monitored as file only */
     }
   else
     {
-      path = filename;
-    }
-
-  if ( (event->mask & (IN_ATTRIB|IN_MODIFY)) != 0)
-    {
-      int ret = sh_files_search_file(path, &class, &check_mask, &reported);
-
+      sh_files_filecheck (class, check_mask, filename,
+			  (event->len > 0) ? event->name : NULL,
+			  &reported, 0);
+    }
+  return 0;
+}
+
+
+static int sh_fInotify_report_missing (struct inotify_event * event, 
+				       char * path,
+				       int class, unsigned long check_mask, int ftype)
+{
+  int    reported;
+  int isdir = (event->mask & IN_ISDIR);
+  int level = (class == SH_LEVEL_ALLIGNORE) ? 
+    ShDFLevel[class] : 
+    ShDFLevel[(isdir == 0) ? SH_ERR_T_FILE : SH_ERR_T_DIR];
+
+  if (S_FALSE == sh_ignore_chk_del(path))
+    {
+      if (0 != hashreport_missing(path, level))
+	{
+	  int ret = sh_files_search_file(path, &class, &check_mask, &reported);
+	  
+	  if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
+	    {
+	      ; /* do nothing, watch was for directory monitored as file only */
+	    }
+	  else
+	    {
+	      /* Removal of a directory triggers:
+	       * (1) IN_DELETE IN_ISDIR
+	       * (2) IN_DELETE_SELF
+	       */
+	      if ((event->mask & IN_DELETE_SELF) == 0)
+		sh_fInotify_report_miss(path, level);
+	    }
+	}
+    }
+
+#ifndef REPLACE_OLD
+  sh_hash_set_visited_true(path);
+#else
+  sh_hash_set_missing(path);
+#endif
+  if (sh.flag.reportonce == S_TRUE)
+    sh_files_set_file_reported(path);
+
+  /* Move to 'dormant' list, if not file within directory. 
+   */
+  if (event->len == 0)
+    sh_inotify_rm_watch(&sh_file_watches, &sh_file_missing, event->wd);
+
+  return 0;
+}
+
+static int sh_fInotify_report_added (struct inotify_event * event, 
+				     char * path, char * filename,
+				     int class, unsigned long check_mask, 
+				     int ftype, int rdepth)
+{
+  if (S_FALSE == sh_ignore_chk_new(path))
+    {
+      int reported;
+      int ret;
+      int retD = 0;
+      int rdepthD = rdepth;
+      
+      sh_files_clear_file_reported(path);
+	  
+      ret = sh_files_search_file(path, &class, &check_mask, &reported);
+      
       if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
 	{
-	  ; /* do nothing */
+	  ; /* do nothing, watch was for directory monitored as file only */
 	}
       else
 	{
+	  int classD = class;
+	  int reportedD = reported; 
+	  unsigned long check_maskD = check_mask;
+	  
+	  if (event->mask & IN_ISDIR)
+	    {
+	      retD = sh_files_search_dir(path, &classD, &check_maskD, 
+					 &reportedD, &rdepthD);
+	      if (retD != 0)
+		{
+		  if (ret == 0)
+		    {
+		      class      = classD;
+		      check_mask = check_maskD;
+		    }
+		}
+	    }
+	  
 	  sh_files_filecheck (class, check_mask, filename,
 			      (event->len > 0) ? event->name : NULL,
 			      &reported, 0);
-	}
+	  
+	  if (event->mask & IN_ISDIR)
+	    {
+	      sh.flag.inotify |= SH_INOTIFY_INSCAN;
+	      sh_files_checkdir (classD, check_maskD, rdepthD, 
+				 path, (event->len > 0) ? event->name : NULL);
+	      sh.flag.inotify &= ~SH_INOTIFY_INSCAN;
+	      sh.flag.inotify |= SH_INOTIFY_NEEDINIT;
+	      sh_dirs_reset  ();
+	      sh_files_reset ();
+	    }
+	  
+	}
+      
+      if (SH_FFLAG_REPORTED_SET(reported))
+	sh_files_set_file_reported(path);
+      
+      if ((ret != 0) || (event->mask & IN_ISDIR))
+	{
+	  sh_inotify_add_watch(path, &sh_file_watches, &ret,
+			       class, check_mask, 
+			       (event->mask & IN_ISDIR)?SH_INOTIFY_DIR:SH_INOTIFY_FILE, 
+			       rdepthD);
+	}
+    }
+  return 0;
+}
+
+static int sh_fInotify_report(struct inotify_event * event, char * filename,
+			      int class, unsigned long check_mask, int ftype, int rdepth)
+{
+  char * fullpath = NULL;
+  char * path;
+
+  if (event->len > 0)
+    {
+      fullpath = sh_util_strconcat(filename, "/", event->name, NULL);
+      path = fullpath;
+    }
+  else
+    {
+      path = filename;
+    }
+
+  if ( (event->mask & (IN_ATTRIB|IN_MODIFY)) != 0)
+    {
+      sh_fInotify_report_change (event, path, filename,
+				 class, check_mask, ftype);
     }
   else if ((event->mask & (IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF|IN_MOVED_FROM)) != 0)
     {
-      int isdir = (event->mask & IN_ISDIR);
-      int level = (class == SH_LEVEL_ALLIGNORE) ? 
-	ShDFLevel[class] : 
-	ShDFLevel[(isdir == 0) ? SH_ERR_T_FILE : SH_ERR_T_DIR];
-
-      if (S_FALSE == sh_ignore_chk_del(path))
-	{
-	  if (0 != hashreport_missing(path, level))
-	    {
-	      int ret = sh_files_search_file(path, &class, &check_mask, &reported);
-
-	      if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
-		{
-		  ; /* do nothing */
-		}
-	      else
-		{
-		  sh_fInotify_report_miss(path, level);
-		}
-	    }
-	}
-
-#ifndef REPLACE_OLD
-      sh_hash_set_visited_true(path);
-#else
-      sh_hash_set_missing(path);
+      sh_fInotify_report_missing (event, path,
+				  class, check_mask, ftype);
+   }
+  else if((event->mask & (IN_CREATE|IN_MOVED_TO)) != 0)
+    {
+      sh_fInotify_report_added (event, path, filename,
+				class, check_mask, 
+				ftype, rdepth);
+    }
+
+  if (fullpath)
+    SH_FREE(fullpath);
+
+  return 0;
+}
+
+
 #endif
-      if (sh.flag.reportonce == S_TRUE)
-	sh_files_set_file_reported(path);
-
-      /* Move to 'dormant' list, if not file within directory. 
-       */
-      if (event->len == 0)
-	sh_inotify_rm_watch(&sh_file_watches, &sh_file_missing, event->wd);
-    }
-  else if((event->mask & (IN_CREATE|IN_MOVED_TO)) != 0)
-    {
-      if (S_FALSE == sh_ignore_chk_new(path))
-	{
-	  int ret;
-
-	  sh_files_clear_file_reported(path);
-	  
-	  ret = sh_files_search_file(path, &class, &check_mask, &reported);
-	  
-	  if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
-	    {
-	      ; /* do nothing */
-	    }
-	  else
-	    {
-	      sh_files_filecheck (class, check_mask, filename,
-				  (event->len > 0) ? event->name : NULL,
-				  &reported, 0);
-	    }
-
-	  if (SH_FFLAG_REPORTED_SET(reported))
-	    sh_files_set_file_reported(path);
-
-	  if (ret != 0)
-	    {
-	      sh_inotify_add_watch(path, &sh_file_watches, &ret,
-				   class, check_mask, SH_INOTIFY_FILE);
-	    }
-	}
-    }
-
-  return 0;
-}
-
 
 #endif
-
-#endif
Index: trunk/src/sh_files.c
===================================================================
--- trunk/src/sh_files.c	(revision 372)
+++ trunk/src/sh_files.c	(revision 373)
@@ -287,12 +287,11 @@
 SH_MUTEX_STATIC(mutex_zfiles,      PTHREAD_MUTEX_INITIALIZER);
 SH_MUTEX_STATIC(mutex_zglob,       PTHREAD_MUTEX_INITIALIZER);
-
-static int        sh_files_fullpath  (char * testdir, char * d_name, 
+SH_MUTEX_RECURSIVE(mutex_zdirs);
+
+static int        sh_files_fullpath  (const char * testdir, 
+				      const char * d_name, 
 				      char * statpath);
 static int        sh_files_pushdir   (int class, const char * str_s);
 static int        sh_files_pushfile  (int class, const char * str_s);
-static int        sh_files_checkdir  (int class, unsigned long check_mask, 
-				      int rdepth, char * dirName,
-				      char * relativeName);
 
 static long MaxRecursionLevel = 0;
@@ -367,8 +366,9 @@
 	    }
 
-	  if ((sh.flag.inotify & SH_INOTIFY_DOSCAN) != 0)
+	  if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0)
 	    {
 	      sh_inotify_add_watch_later(ptr->name, &sh_file_watches, NULL,
-					 ptr->class, ptr->check_mask, SH_INOTIFY_FILE);
+					 ptr->class, ptr->check_mask, 
+					 SH_INOTIFY_FILE, 0);
 	    }
 
@@ -540,6 +540,12 @@
 int sh_files_setrec ()
 {
+  volatile int ret;
+  SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
+  SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
   sh_files_setrec_int(zdirListOne);
-  return sh_files_setrec_int(zdirListTwo);
+  ret = sh_files_setrec_int(zdirListTwo);
+  SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
+
+  return ret;
 }
 
@@ -555,6 +561,9 @@
 int sh_files_deldirstack ()
 {
+  SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
+  SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
   zdirListOne = sh_files_deldirstack_int(zdirListOne);
   zdirListTwo = sh_files_deldirstack_int(zdirListTwo);
+  SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
   return 0;
 }
@@ -583,4 +592,6 @@
   SL_ENTER(_("sh_dirs_reset"));
 
+  SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
+  SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
   for (ptr = (dirstack_t *) zAVLFirst(&avlcursor1, zdirListOne); ptr;
        ptr = (dirstack_t *) zAVLNext(&avlcursor1))
@@ -590,4 +601,5 @@
        ptr = (dirstack_t *) zAVLNext(&avlcursor2))
     ptr->checked = 0;
+  SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
 
   SL_RET0(_("sh_dirs_reset"));
@@ -896,4 +908,5 @@
   char  * fileName;
   int     ret;
+  int     count = 0;
 
   SL_ENTER(_("sh_files_push_file_int"));
@@ -942,11 +955,25 @@
   else
     {
-      unsigned long mask = sh_files_maskof(class);
-      if (MODI_AUDIT_ENABLED(mask))
+      int           reported;
+      unsigned long check_mask = sh_files_maskof(class);
+
+      if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0)
 	{
-	  sh_audit_mark(new_item_ptr->name);
+	  sh_files_filecheck (class, check_mask, str_s, NULL,
+			      &reported, 0);
+	  if (SH_FFLAG_REPORTED_SET(reported))
+	    sh_files_set_file_reported(str_s);
+	  sh_inotify_add_watch_later(str_s, &sh_file_watches, NULL,
+				     class, check_mask, 
+				     SH_INOTIFY_FILE, 0);
 	}
-    }
-  SL_RETURN(0, _("sh_files_push_file_int"));
+
+      if (MODI_AUDIT_ENABLED(check_mask))
+	{
+	  sh_audit_mark(str_s);
+	}
+      ++count;
+    }
+  SL_RETURN(count, _("sh_files_push_file_int"));
 }
 
@@ -966,5 +993,5 @@
 static zAVLTree * zglobList   = NULL;
 
-static void sh_files_pushglob (int class, int type, const char * p, int rdepth,
+static int sh_files_pushglob (int class, int type, const char * p, int rdepth,
 			       unsigned long check_mask_in, int flag)
 {
@@ -973,4 +1000,5 @@
   glob_t  pglob;
 
+  int     count = 0;
   volatile unsigned long check_mask = check_mask_in;
   
@@ -1024,6 +1052,6 @@
 	  if (type == SH_LIST_FILE)
 	    {
-	      sh_files_push_file_int (class, pglob.gl_pathv[gloop], 
-				      sl_strlen(pglob.gl_pathv[gloop]));
+	      count += sh_files_push_file_int (class, pglob.gl_pathv[gloop], 
+					       sl_strlen(pglob.gl_pathv[gloop]));
 	    }
 	  else
@@ -1031,6 +1059,6 @@
 	      which_dirList = type;
 
-	      sh_files_push_dir_int  (class, pglob.gl_pathv[gloop], 
-				      sl_strlen(pglob.gl_pathv[gloop]), rdepth);
+	      count += sh_files_push_dir_int  (class, pglob.gl_pathv[gloop], 
+					       sl_strlen(pglob.gl_pathv[gloop]), rdepth);
 	    }
 	}
@@ -1071,6 +1099,6 @@
   
   globfree(&pglob);
-  SL_RET0(_("sh_files_pushglob"));
-  return;
+  SL_RETURN(count, _("sh_files_pushglob"));
+  return count;
 }
 
@@ -1283,9 +1311,16 @@
 int sh_files_is_allignore (char * str)
 {
-  if (1 == sh_files_is_allignore_int(str, zdirListOne))
-    return 1;
-  if (NULL == zdirListTwo)
-    return 0;
-  return sh_files_is_allignore_int(str, zdirListTwo);
+  int retval = 0;
+
+  SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
+  SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
+  retval = sh_files_is_allignore_int(str, zdirListOne);
+
+  if (NULL != zdirListTwo && retval == 0)
+    {
+      retval = sh_files_is_allignore_int(str, zdirListTwo);
+    }
+  SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
+  return retval;
 }
 
@@ -1306,4 +1341,6 @@
   sh_dummy_ptr = (void *) &ptr;
   
+  SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
+  SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
   if (which == 1)
     tree = zdirListOne;
@@ -1315,5 +1352,5 @@
     {
       if (sig_urgent > 0) {
-	SL_RETURN(dcount, _("sh_dirs_chk"));
+	goto out;
       }
 
@@ -1330,5 +1367,6 @@
 		{
 		  BREAKEXIT(sh_files_filecheck);
-		  sh_files_filecheck (dst_ptr->class, dst_ptr->check_mask, ptr->name,  
+		  sh_files_filecheck (dst_ptr->class, dst_ptr->check_mask, 
+				      ptr->name,  
 				      NULL,  &status, 0);
 		  dst_ptr->checked = S_TRUE;
@@ -1343,8 +1381,10 @@
 
 	  if (status == S_FALSE)
-	    sh_files_filecheck (ptr->class,  ptr->check_mask, ptr->name,  NULL,  &status, 0);
+	    sh_files_filecheck (ptr->class,  ptr->check_mask, 
+				ptr->name,  NULL,  &status, 0);
 
 	  BREAKEXIT(sh_files_checkdir);
-	  status = sh_files_checkdir (ptr->class, ptr->check_mask, ptr->rdepth, ptr->name, 
+	  status = sh_files_checkdir (ptr->class, ptr->check_mask, 
+				      ptr->rdepth, ptr->name, 
 				      ptr->name);
 
@@ -1410,8 +1450,11 @@
 
       if (sig_urgent > 0) {
-	SL_RETURN(dcount, _("sh_dirs_chk"));
+	goto out;
       }
 
     }
+ out:
+  SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
+
   SL_RETURN(dcount, _("sh_dirs_chk"));
 }
@@ -1508,4 +1551,6 @@
   new_item_ptr->childs_checked = S_FALSE;
 
+  SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
+  SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
   if (which_dirList == SH_LIST_DIR1)
     {
@@ -1532,4 +1577,5 @@
 
   ret = zAVLInsert (tree, new_item_ptr);
+  SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
 
   if (-1 == ret)
@@ -1547,10 +1593,12 @@
       new_item_ptr = NULL;
     }
-
-  if (new_item_ptr && MODI_AUDIT_ENABLED(new_item_ptr->check_mask))
-    {
-      sh_audit_mark(new_item_ptr->name);
-    }
-
+  else
+    {
+      unsigned long mask = sh_files_maskof(class);
+      if (MODI_AUDIT_ENABLED(mask))
+	{
+	  sh_audit_mark(tail);
+	}
+    }
   SL_RETURN(0, _("sh_files_push_dir_int"));
 }
@@ -1808,9 +1856,10 @@
 static void * sh_dummy_dirlist;
 
-/* -- check a single directory and its content
+/* -- Check a single directory and its content. Does not
+ *    check the directory inode itself.
  */
-static int sh_files_checkdir (int iclass, unsigned long check_mask, 
-			      int idepth, char * iname, 
-			      char * relativeName)
+int sh_files_checkdir (int iclass, unsigned long check_mask, 
+		       int idepth, char * iname, 
+		       char * relativeName)
 {
   struct sh_dirent * dirlist;
@@ -1949,8 +1998,8 @@
     }
 
-  if ((sh.flag.inotify & SH_INOTIFY_DOSCAN) != 0)
+  if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0)
     {
       sh_inotify_add_watch_later(iname, &sh_file_watches, &status,
-				 iclass, check_mask, SH_INOTIFY_DIR);
+				 iclass, check_mask, SH_INOTIFY_DIR, idepth);
     }
    
@@ -2069,4 +2118,6 @@
      * is checked with the policy of the parent directory
      */
+    SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
+    SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
     dst_ptr         = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
 
@@ -2099,6 +2150,7 @@
 	  }
       }
-
-    SH_MUTEX_LOCK(mutex_zfiles);
+    SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
+
+    SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
     dst_ptr         = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
 
@@ -2114,6 +2166,14 @@
 	/* not set, hence always FALSE                   */
 	/* cchecked_flag      = dst_ptr->childs_checked; */
+
+	if (checked_flag != S_TRUE)
+	  {
+	    /* -- need to check the file itself --
+	     */
+	    if (sh.flag.reportonce == S_TRUE)
+	      dummy = dst_ptr->is_reported;
+	  }
       }
-    SH_MUTEX_UNLOCK(mutex_zfiles);
+    SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
     
     /* ---- Has been checked already. ----
@@ -2145,6 +2205,8 @@
 	/* -- need to check the file itself --
 	 */
-	if (dst_ptr && sh.flag.reportonce == S_TRUE)
-	  dummy = dst_ptr->is_reported;
+	/* -- moved up -- 
+	 * if (dst_ptr && sh.flag.reportonce == S_TRUE)
+	 *   dummy = dst_ptr->is_reported;
+	 */
 
 	checkit = sh_files_filecheck (file_class_next, file_check_mask_next, 
@@ -2153,10 +2215,19 @@
 				      &dummy, 0);
 
+	
+	SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
+	dst_ptr         = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
+
 	if (dst_ptr && checked_flag == S_FALSE)
 	  dst_ptr->checked = S_TRUE;
+
 	/* Thu Mar  7 15:09:40 CET 2002 Propagate the 'reported' flag
 	 */
 	if (dst_ptr && sh.flag.reportonce == S_TRUE)
 	  dst_ptr->is_reported = dummy;
+
+	if (dst_ptr)
+	  dst_ptr->childs_checked = S_TRUE;
+	SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
       }
     
@@ -2178,4 +2249,6 @@
 	    cchecked_flag = -1;
 	    
+	    SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
+	    SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
 	    tmp_ptr     = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
 
@@ -2212,9 +2285,7 @@
 		  }
 	      }
-	    
-	  if (cchecked_flag == S_FALSE)
+
+	    if (tmp_ptr && cchecked_flag == S_FALSE)
 	      {
-		sh_files_checkdir (class_next, check_mask_next, rdepth_next, tmpcat, 
-				   dirlist->sh_d_name);
 		tmp_ptr->childs_checked = S_TRUE;
 		/*
@@ -2223,7 +2294,18 @@
 		tmp_ptr->checked        = S_TRUE;
 	      }
+	    SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
+
+	    if (cchecked_flag == S_FALSE)
+	      {
+		sh_files_checkdir (class_next, check_mask_next, rdepth_next, 
+				   tmpcat, dirlist->sh_d_name);
+		/*
+		  tmp_ptr->childs_checked = S_TRUE;
+		  tmp_ptr->checked        = S_TRUE;
+		*/
+	      }
 	    else if (checked_flag == -1)
-	      sh_files_checkdir (class_next, check_mask_next, rdepth_next, tmpcat, 
-				 dirlist->sh_d_name);
+	      sh_files_checkdir (class_next, check_mask_next, rdepth_next, 
+				 tmpcat, dirlist->sh_d_name);
 	    
 	  }
@@ -2248,7 +2330,9 @@
     dirlist = dirlist->next;
 
-    if (dst_ptr)
-      dst_ptr->childs_checked = S_TRUE;
-    
+    /* -- moved up, only affects zfileList anyway
+     * if (dst_ptr)
+     *   dst_ptr->childs_checked = S_TRUE;
+     */
+
   } while (dirlist != NULL);
 
@@ -2309,6 +2393,6 @@
 
 ShFileType sh_files_filecheck (int class, unsigned long check_mask,
-			       char * dirName, 
-			       char * infileName,
+			       const char * dirName, 
+			       const char * infileName,
 			       int * reported, 
 			       int rsrcflag)
@@ -2322,5 +2406,5 @@
   char          * tmpdir;
   char          * tmpname;
-  char          * fileName;
+  const char    * fileName;
   struct utimbuf  utime_buf;
   static unsigned int state = 1;
@@ -2546,5 +2630,6 @@
 /* concatenate statpath = testdir"/"d_name
  */
-static int sh_files_fullpath (char * testdir, char * d_name, char * statpath)
+static int sh_files_fullpath (const char * testdir, const char * d_name, 
+			      char * statpath)
 {
   int llen = 0;
@@ -2575,4 +2660,75 @@
  * -----------------------------------
  */
+int sh_files_search_dir(char * name, int * class, 
+			unsigned long *check_mask, int *reported,
+			int * rdepth)
+{
+  int retval = 0;
+#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
+  sh_globstack_t * testPattern;
+  zAVLCursor   cursor;
+#endif
+  dirstack_t * item;
+
+  SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
+  SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
+
+  item = zAVLSearch(zdirListOne, name);
+
+  if (item)
+    {
+      *check_mask = item->check_mask;
+      *class      = item->class;
+      *reported   = item->is_reported;
+      *rdepth     = item->rdepth;
+      item->checked        = S_FALSE;
+      item->childs_checked = S_FALSE;
+      item->is_reported    = S_FALSE;
+      retval = 1;
+      goto out;
+    }
+
+  item = zAVLSearch(zdirListTwo, name);
+
+  if (item)
+    {
+      *check_mask = item->check_mask;
+      *class      = item->class;
+      *reported   = item->is_reported;
+      *rdepth     = item->rdepth;
+      item->checked        = S_FALSE;
+      item->childs_checked = S_FALSE;
+      item->is_reported    = S_FALSE;
+      retval = 1;
+      goto out;
+    }
+
+#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
+  SH_MUTEX_LOCK(mutex_zglob);
+  for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList); 
+       testPattern;
+       testPattern = (sh_globstack_t *) zAVLNext  (&cursor))
+    {
+      if (testPattern->type == SH_LIST_DIR1 || 
+	  testPattern->type == SH_LIST_DIR2)
+	{
+	  if (0 == fnmatch(testPattern->name, name, FNM_PATHNAME|FNM_PERIOD))
+	    {
+	      *check_mask = testPattern->check_mask;
+	      *class      = testPattern->class;
+	      *rdepth     = testPattern->rdepth;
+	      retval = 1;
+	      break;
+	    }
+	
+	}
+    }
+  SH_MUTEX_UNLOCK(mutex_zglob);
+#endif
+ out:
+  SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
+  return retval;
+}
+
 int sh_files_search_file(char * name, int * class, 
 			 unsigned long *check_mask, int *reported)
@@ -2622,5 +2778,5 @@
 }
 
-void sh_files_set_file_reported(char * name)
+void sh_files_set_file_reported(const char * name)
 {
   dirstack_t * item;
@@ -2638,5 +2794,5 @@
 }
 
-void sh_files_clear_file_reported(char * name)
+void sh_files_clear_file_reported(const char * name)
 {
   dirstack_t * item;
@@ -2771,6 +2927,8 @@
 int sh_files_test_setup ()
 {
-  int retval = 0;
-
+  int retval;
+
+  SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
+  SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
   /* Test for modifications allowed in ReadOnly directory
    */  
@@ -2787,11 +2945,6 @@
   if (retval != 0)
     aud_exit(FIL__, __LINE__, EXIT_FAILURE);
-
-
-  /*
-  retval = sh_files_test_double (zfileList,   NULL);
-  if (retval != 0)
-    aud_exit(FIL__, __LINE__, EXIT_FAILURE);
-  */
+  SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
+
   return 0;
 }
Index: trunk/src/sh_inotify.c
===================================================================
--- trunk/src/sh_inotify.c	(revision 372)
+++ trunk/src/sh_inotify.c	(revision 373)
@@ -128,4 +128,5 @@
   short  type;
   int    class;
+  int    rdepth;
   unsigned long check_mask;
   char * file;
@@ -245,5 +246,5 @@
 }
 
-static sh_watch * sh_inotify_create_watch(char * file, int nwatch, int flag)
+static sh_watch * sh_inotify_create_watch(const char * file, int nwatch, int flag)
 {
   sh_watch * this = SH_ALLOC(sizeof(sh_watch));
@@ -356,5 +357,6 @@
 
 char * sh_inotify_pop_dormant(sh_watches * watches, 
-			      int * class, unsigned long * check_mask, int * type)
+			      int * class, unsigned long * check_mask, 
+			      int * type, int * rdepth)
 {
   char * popret = NULL;
@@ -372,8 +374,9 @@
   if (this)
     {
-      *class = this->watch->class;
-      *type  = this->watch->type;
+      *class  = this->watch->class;
+      *type   = this->watch->type;
+      *rdepth = this->watch->rdepth;
       *check_mask = this->watch->check_mask;
-      popret = sh_util_strdup(this->watch->file);
+      popret  = sh_util_strdup(this->watch->file);
 
       watches->dormant_watches = this->next;
@@ -472,7 +475,7 @@
 /* Create an item and put it on the 'dormant' list for later watch creation 
  */
-int sh_inotify_add_watch_later(char * filename, sh_watches * watches, 
+int sh_inotify_add_watch_later(const char * filename, sh_watches * watches, 
 			       int * errnum,
-			       int class, unsigned long check_mask, int type)
+			       int class, unsigned long check_mask, int type, int rdepth)
 {
   sh_watch   * item;
@@ -482,4 +485,5 @@
   item->class      = class;
   item->type       = (short) type;
+  item->rdepth     = (short) rdepth;
   item->check_mask = check_mask;
 
@@ -574,5 +578,5 @@
  */
 int sh_inotify_add_watch(char * filename, sh_watches * watches, int * errnum,
-			 int class, unsigned long check_mask, int type)
+			 int class, unsigned long check_mask, int type, int rdepth)
 {
   volatile int retval = 0;
@@ -618,4 +622,5 @@
 	  item->class      = class;
 	  item->type       = type;
+	  item->rdepth     = rdepth;
 	  item->check_mask = check_mask;
 	  
@@ -646,4 +651,17 @@
 	  ++(watches->count);
 	}
+      else if (type == SH_INOTIFY_DIR) /* watch exists */
+	{
+	  /* This covers the case that a directory has been added,
+	   * but is watched as file at first because it is also
+	   * specified as file in the config.
+	   */
+	  item = zAVLSearch(watches->list_of_watches, &index);
+
+	  if (item && item->type == SH_INOTIFY_FILE)
+	    {
+	      item->type = SH_INOTIFY_DIR;
+	    }
+	}
     }
  retpoint:
@@ -655,5 +673,6 @@
 
 char * sh_inotify_search_item(sh_watches * watches, int watch, 
-			      int * class, unsigned long * check_mask, int * type)
+			      int * class, unsigned long * check_mask, 
+			      int * type, int * rdepth)
 {
   sh_watch * item;
@@ -673,4 +692,5 @@
       *check_mask = item->check_mask;
       *type       = item->type;
+      *rdepth     = item->rdepth;
       sret = sh_util_strdup(item->file);
     }
@@ -710,5 +730,6 @@
       if (filename)
 	{
-	  if (sh_inotify_add_watch(filename, watches, errnum, 0, 0, SH_INOTIFY_FILE) < 0)
+	  if (sh_inotify_add_watch(filename, watches, errnum, 
+				   0, 0, SH_INOTIFY_FILE, 0) < 0)
 	    {
 	      retry_msleep(waitsec, 0);
@@ -841,5 +862,5 @@
 
 int sh_inotify_add_watch(char * filename, sh_watches * watches, int  * errnum,
-			 int class, unsigned long check_mask)
+			 int class, unsigned long check_mask, int type, int rdepth)
 {
   (void) filename;
@@ -847,11 +868,13 @@
   (void) class;
   (void) check_mask;
+  (void) type;
+  (void) rdepth;
   *errnum = 0;
   return 0;
 }
 
-int sh_inotify_add_watch_later(char * filename, sh_watches * watches, 
+int sh_inotify_add_watch_later(const char * filename, sh_watches * watches, 
 			       int  * errnum,
-			       int class, unsigned long check_mask)
+			       int class, unsigned long check_mask, int type, int rdepth)
 {
   (void) filename;
@@ -859,4 +882,6 @@
   (void) class;
   (void) check_mask;
+  (void) type;
+  (void) rdepth;
   *errnum = 0;
   return 0;
@@ -876,12 +901,14 @@
   char * p;
   int class;
+  int type;
+  int rdepth;
   unsigned long check_mask;
   int           nrun = 0;
 
-  sh_watch aw1 = { -1, 0, 1, 1, "a1" };
-  sh_watch aw2 = { -1, 0, 2, 1, "a2" };
-  sh_watch aw3 = {  2, 0, 3, 1, "a3" };
-  sh_watch aw4 = { -1, 0, 4, 1, "a4" };
-  sh_watch aw5 = {  5, 0, 5, 1, "a5" };
+  sh_watch aw1 = { -1, 0, 0, 1, 99, 1, "a1" };
+  sh_watch aw2 = { -1, 0, 0, 2, 99, 1, "a2" };
+  sh_watch aw3 = {  2, 0, 0, 3, 99, 1, "a3" };
+  sh_watch aw4 = { -1, 0, 0, 4, 99, 1, "a4" };
+  sh_watch aw5 = {  5, 0, 0, 5, 99, 1, "a5" };
 
   do {
@@ -971,12 +998,12 @@
     CuAssertIntEquals(tc, count, 5);
     
-    p = sh_inotify_pop_dormant(&twatch, &class, &check_mask);
+    p = sh_inotify_pop_dormant(&twatch, &class, &check_mask, &type, &rdepth);
     CuAssertStrEquals(tc, p, "a5");
     
-    p = sh_inotify_pop_dormant(&twatch, &class, &check_mask);
+    p = sh_inotify_pop_dormant(&twatch, &class, &check_mask, &type, &rdepth);
     CuAssertStrEquals(tc, p, "a3");
     CuAssertIntEquals(tc, class, 3);
     
-    p = sh_inotify_pop_dormant(&twatch, &class, &check_mask);
+    p = sh_inotify_pop_dormant(&twatch, &class, &check_mask, &type, &rdepth);
     CuAssertTrue(tc, NULL == p);
     CuAssertTrue(tc, NULL == twatch.dormant_watches);
Index: trunk/src/sh_unix.c
===================================================================
--- trunk/src/sh_unix.c	(revision 372)
+++ trunk/src/sh_unix.c	(revision 373)
@@ -3590,5 +3590,5 @@
 static void * sh_dummy_tmp2;
 
-int sh_unix_getinfo (int level, char * filename, file_type * theFile, 
+int sh_unix_getinfo (int level, const char * filename, file_type * theFile, 
 		     char * fileHash, int policy)
 {
Index: trunk/src/sh_utils.c
===================================================================
--- trunk/src/sh_utils.c	(revision 372)
+++ trunk/src/sh_utils.c	(revision 373)
@@ -1804,7 +1804,7 @@
 
 
-int sh_util_obscurename (ShErrLevel level, char * name_orig, int flag)
-{
-  unsigned char * name = (unsigned char *) name_orig;
+int sh_util_obscurename (ShErrLevel level, const char * name_orig, int flag)
+{
+  const unsigned char * name = (unsigned char *) name_orig;
   char * safe;
   unsigned int i;
