Index: /trunk/docs/Changelog
===================================================================
--- /trunk/docs/Changelog	(revision 456)
+++ /trunk/docs/Changelog	(revision 457)
@@ -10,4 +10,6 @@
 	  overflow check (the required buffer length information for the check
 	  wasn't provided)
+	* Fixed incorrect logic in setting the ALLIGNORE flag (more specific
+	  directory / file directives were ignored)
 
 3.1.1 (01-0-2014):
Index: /trunk/include/sh_files.h
===================================================================
--- /trunk/include/sh_files.h	(revision 456)
+++ /trunk/include/sh_files.h	(revision 457)
@@ -31,4 +31,11 @@
 };
 
+/* Check whether a file is in the config 
+ */
+char * sh_files_findfile(const char * path);
+
+/* Find the most specific directory in the config
+ */
+char * sh_files_find_mostspecific_dir(const char * path);
 
 /* free a directory listing
Index: /trunk/include/zAVLTree.h
===================================================================
--- /trunk/include/zAVLTree.h	(revision 456)
+++ /trunk/include/zAVLTree.h	(revision 457)
@@ -74,5 +74,5 @@
 extern void *zAVLNext (zAVLCursor *avlcursor);
 
-extern char * zAVL_string_get (zAVLTree * tree, char * key);
+extern char * zAVL_string_get (zAVLTree * tree, const char * key);
 /* uses strdup to insert a copy */
 extern int zAVL_string_set (zAVLTree ** tree, const char * key); 
Index: /trunk/src/sh_files.c
===================================================================
--- /trunk/src/sh_files.c	(revision 456)
+++ /trunk/src/sh_files.c	(revision 457)
@@ -521,4 +521,103 @@
 }
 
+static zAVLTree * fileTree = NULL;
+static zAVLTree * dirTree  = NULL;
+
+static void clear_lists()
+{
+  if (fileTree) {
+    zAVL_string_reset(fileTree);
+    fileTree  = NULL;
+  }
+  if (dirTree) {
+    zAVL_string_reset(dirTree);
+    dirTree  = NULL;
+  }
+  return;
+}
+
+static void add_to_filelist(zAVLTree * tree)
+{
+  dirstack_t * ptr;
+  zAVLCursor   avlcursor;
+
+  SL_ENTER(_("add_to_filelist"));
+
+  SH_MUTEX_LOCK(mutex_zfiles);
+  for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr;
+       ptr = (dirstack_t *) zAVLNext(&avlcursor))
+    zAVL_string_set (&fileTree, ptr->name);
+  SH_MUTEX_UNLOCK(mutex_zfiles);
+  SL_RET0(_("add_to_filelist"));
+}
+static void add_to_dirlist(zAVLTree * tree)
+{
+  dirstack_t * ptr;
+  zAVLCursor   avlcursor;
+
+  SL_ENTER(_("add_to_dirlist"));
+
+  SH_MUTEX_LOCK(mutex_zfiles);
+  for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr;
+       ptr = (dirstack_t *) zAVLNext(&avlcursor))
+    zAVL_string_set (&dirTree, ptr->name);
+  SH_MUTEX_UNLOCK(mutex_zfiles);
+  SL_RET0(_("add_to_dirlist"));
+}
+char * sh_files_findfile(const char * path)
+{
+  return zAVL_string_get (fileTree, path);
+}
+static char * intern_find_morespecific_dir(zAVLTree * tree, 
+					   const char * path, size_t * len)
+{
+  dirstack_t * ptr;
+  zAVLCursor   avlcursor;
+  size_t       l_path = strlen(path);
+  size_t       l_name;
+  char *       candidate = NULL;
+  size_t       l_candidate = 0;
+  
+  if (NULL == tree)
+    return NULL;
+
+  SH_MUTEX_LOCK(mutex_zfiles);
+  for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr;
+       ptr = (dirstack_t *) zAVLNext(&avlcursor))
+    {
+      l_name = strlen(ptr->name);
+      if (l_name <= l_path)
+	{
+	  if (0 == strncmp(ptr->name, path, l_name))
+	    {
+	      if ((l_name == l_path) || (path[l_name] == '/'))
+		{
+		  if (!candidate || (l_candidate < l_name))
+		    {
+		      candidate = ptr->name;
+		      l_candidate = l_name;
+		      *len = l_candidate;
+		    }
+		}
+	    }
+	}
+    }
+  SH_MUTEX_UNLOCK(mutex_zfiles);
+  return candidate;
+}
+char * sh_files_find_mostspecific_dir(const char * path)
+{
+  size_t l_one = 0;
+  size_t l_two = 0;
+  char * one;
+  char * two;
+
+  one = intern_find_morespecific_dir(zdirListOne, path, &l_one);
+  two = intern_find_morespecific_dir(zdirListTwo, path, &l_two);
+
+  if      (l_one > l_two) return one;
+  else                    return two;
+}
+
 int sh_files_delfilestack ()
 {
@@ -547,5 +646,8 @@
 	    ptr->rdepth = MaxRecursionLevel;
 	  }
-	if (ptr->rdepth == (-1) && sh.flag.checkSum != SH_CHECK_INIT)
+
+	if ( (ptr->rdepth      == (-1)) && 
+	     (ptr->class       == SH_LEVEL_ALLIGNORE) && 
+	     (sh.flag.checkSum != SH_CHECK_INIT))
 	  hash_remove_tree (ptr->name);
       }
@@ -559,4 +661,8 @@
   SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
   SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
+  clear_lists();
+  add_to_dirlist(zdirListOne);
+  add_to_dirlist(zdirListTwo);
+  add_to_filelist(zfileList);
   sh_files_setrec_int(zdirListOne);
   ret = sh_files_setrec_int(zdirListTwo);
@@ -3014,4 +3120,86 @@
 #include "CuTest.h"
 
+void Test_file_lists (CuTest *tc)
+{
+#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
+
+  extern int hash_remove_tree_test(char * s, char * fullpath, size_t len_s);
+
+  char * test;
+  int ret;
+
+  sh_files_pushfile_ro("/usr/test");
+  sh_files_pushfile_ro("/usr/bin/test");
+  sh_files_pushfile_ro("/usr/bin/foo/test");
+
+  sh_files_pushdir_ro("/usr");
+  sh_files_pushdir_attr("/usr/bin");
+  sh_files_pushdir_ro("/usr/bin/foo");
+
+  add_to_dirlist(zdirListOne);
+  add_to_dirlist(zdirListTwo);
+  add_to_filelist(zfileList);
+
+  test = sh_files_findfile("/usr/tes");
+  CuAssertTrue(tc, test == NULL);
+  test = sh_files_findfile("/usr/test");
+  CuAssertPtrNotNull(tc, test);
+  test = sh_files_findfile("/usr/testi");
+  CuAssertTrue(tc, test == NULL);
+  test = sh_files_findfile("/test");
+  CuAssertTrue(tc, test == NULL);
+
+  test = sh_files_find_mostspecific_dir("/usr/bin/foo/test");
+  CuAssertStrEquals(tc, "/usr/bin/foo", test);
+  test = sh_files_find_mostspecific_dir("/usr/bin/test");
+  CuAssertStrEquals(tc, "/usr/bin", test);
+  test = sh_files_find_mostspecific_dir("/usr/test");
+  CuAssertStrEquals(tc, "/usr", test);
+  test = sh_files_find_mostspecific_dir("/test");
+  CuAssertTrue(tc, test == NULL);
+  test = sh_files_find_mostspecific_dir("/usr/foo/test");
+  CuAssertStrEquals(tc, "/usr", test);
+
+  test = sh_files_find_mostspecific_dir("/usr/bin");
+  CuAssertStrEquals(tc, "/usr/bin", test);
+
+  ret = hash_remove_tree_test("/usr", "/usr/test", strlen("/usr"));
+  CuAssertIntEquals(tc, S_FALSE, ret);
+  ret = hash_remove_tree_test("/usr", "/usr/testi", strlen("/usr"));
+  CuAssertIntEquals(tc, S_TRUE, ret);
+  ret = hash_remove_tree_test("/usr", "/usr/tes", strlen("/usr"));
+  CuAssertIntEquals(tc, S_TRUE, ret);
+
+  ret = hash_remove_tree_test("/usr/bin", "/usr/test", strlen("/usr/bin"));
+  CuAssertIntEquals(tc, S_FALSE, ret);
+  ret = hash_remove_tree_test("/usr/bin", "/usr/testi", strlen("/usr/bin"));
+  CuAssertIntEquals(tc, S_FALSE, ret);
+  ret = hash_remove_tree_test("/usr/bin", "/usr/tes", strlen("/usr/bin"));
+  CuAssertIntEquals(tc, S_FALSE, ret);
+
+  ret = hash_remove_tree_test("/usr/bin", "/usr/bin/test", strlen("/usr/bin"));
+  CuAssertIntEquals(tc, S_FALSE, ret);
+  ret = hash_remove_tree_test("/usr/bin", "/usr/bin/testi", strlen("/usr/bin"));
+  CuAssertIntEquals(tc, S_TRUE, ret);
+  ret = hash_remove_tree_test("/usr/bin", "/usr/bin/tes", strlen("/usr/bin"));
+  CuAssertIntEquals(tc, S_TRUE, ret);
+
+  ret = hash_remove_tree_test("/usr/bin", "/usr/bin", strlen("/usr/bin"));
+  CuAssertIntEquals(tc, S_TRUE, ret);
+  ret = hash_remove_tree_test("/usr", "/usr", strlen("/usr"));
+  CuAssertIntEquals(tc, S_TRUE, ret);
+  ret = hash_remove_tree_test("/usr", "/usrbin", strlen("/usr"));
+  CuAssertIntEquals(tc, S_FALSE, ret);
+  ret = hash_remove_tree_test("/", "/usrbin", strlen("/"));
+  CuAssertIntEquals(tc, S_TRUE, ret);
+  ret = hash_remove_tree_test("/", "/usr", strlen("/"));
+  CuAssertIntEquals(tc, S_FALSE, ret);
+
+#else
+  (void) tc; /* fix compiler warning */
+  return;
+#endif
+}
+
 void Test_file_dequote (CuTest *tc)
 {
Index: /trunk/src/sh_hash.c
===================================================================
--- /trunk/src/sh_hash.c	(revision 456)
+++ /trunk/src/sh_hash.c	(revision 457)
@@ -537,5 +537,14 @@
       SL_RET0(_("hash_unvisited"));
     }
-
+#if 0
+  if (!strcmp(p->fullpath, "/var/lib/synaptic"))
+    {
+      fprintf(stderr, "FIXME: Check for missing files %s\n", p->fullpath);
+      if (SH_FFLAG_VISITED_SET(p->fflags)) fprintf(stderr, "FIXME: visited\n");
+      if (SH_FFLAG_CHECKED_SET(p->fflags)) fprintf(stderr, "FIXME: checked\n");
+      if (SH_FFLAG_REPORTED_SET(p->fflags)) fprintf(stderr, "FIXME: reported\n");
+      if (SH_FFLAG_ALLIGNORE_SET(p->fflags)) fprintf(stderr, "FIXME: allignore\n");
+    }
+#endif
   /* visited   flag not set: not seen; 
    * checked   flag     set: not seen (i.e. missing), and already checked 
@@ -551,6 +560,9 @@
     {
       i = retry_lstat(FIL__, __LINE__, p->fullpath, &buf);
-
-      /* if file does not exist
+#if 0
+      if (!strcmp(p->fullpath, "/var/lib/synaptic"))
+	fprintf(stderr, "FIXME: Check for missing files %s (%d)\n", p->fullpath, i);
+#endif
+     /* if file does not exist
        */
       if (0 != i)
@@ -3817,8 +3829,8 @@
   int         i;
 
-  SL_ENTER(_("sh_hash_compdata"));
+  SL_ENTER(_("hash_full_tree"));
 
   if (IsInit != 1) 
-    SL_RETURN(0, _("sh_hash_compdata"));
+    SL_RETURN(0, _("hash_full_tree"));
 
   SH_MUTEX_LOCK_UNSAFE(mutex_hash);
@@ -3829,12 +3841,65 @@
     }
   SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
-  SL_RETURN (0, _("sh_hash_compdata"));
+  SL_RETURN (0, _("hash_full_tree"));
 } 
 
+#if !defined(SH_CUTEST)
+static 
+#endif
+int hash_remove_tree_test(char * s, char * fullpath, size_t len_s)
+{
+  size_t       len_p;
+  char      *  test;
+
+  len_p = strlen(fullpath);
+  
+  if (len_p >= len_s)
+    {
+      if (0 == strncmp(s, fullpath, len_s)) 
+	{ 
+	  if (len_p > len_s)
+	    {
+	      /* continue if not inside directory;
+	       * len_s > 1 because everything is inside '/' 
+	       */
+	      if ((len_s > 1) && (fullpath[len_s] != '/'))
+		return S_FALSE;
+
+	      test = sh_files_find_mostspecific_dir(fullpath);
+	      
+	      if (test && 0 != strcmp(test, s)) {
+		/* There is a more specific directory, continue */
+		return S_FALSE;
+	      }
+	      
+	      if (NULL == sh_files_findfile(fullpath)) {
+		/* SET_SH_FFLAG_ALLIGNORE(p->fflags); */
+		return S_TRUE;
+	      }
+	    }
+	  else /* len_p == len */
+	    {
+	      /* it is 's' itself, mark and continue 
+	       * unless there is a policy for the inode itself
+	       */
+	      if (NULL == sh_files_findfile(fullpath)) {
+		/* SET_SH_FFLAG_ALLIGNORE(p->fflags); */
+		return S_TRUE;
+	      }
+	      else {
+		return S_FALSE;
+	      }
+	    }
+
+	} /* if path is in tree */
+    } /* if path is possibly in tree */
+  return S_FALSE;
+}
+
 
 int hash_remove_tree (char * s) 
 {
   sh_file_t *  p;
-  size_t       len;
+  size_t       len_s;
   unsigned int i;
 
@@ -3844,5 +3909,5 @@
     SL_RETURN ((-1), _("hash_remove_tree"));
 
-  len = sl_strlen(s);
+  len_s = sl_strlen(s);
 
   if (IsInit != 1) 
@@ -3854,8 +3919,11 @@
       for (p = tab[i]; p; p = p->next)
 	{
-	  if (p->fullpath && 0 == strncmp(s, p->fullpath, len))
-	    { 
-	      SET_SH_FFLAG_ALLIGNORE(p->fflags);
-	    }
+	  if (p->fullpath)
+	    {
+	      /* if (0 == strncmp(s, p->fullpath, len_s)) *//* old */
+	      if (S_TRUE == hash_remove_tree_test(s, p->fullpath, len_s)) 
+		SET_SH_FFLAG_ALLIGNORE(p->fflags);
+	    } /* if path is not null */
+
 	}
     }
Index: /trunk/src/zAVLTree.c
===================================================================
--- /trunk/src/zAVLTree.c	(revision 456)
+++ /trunk/src/zAVLTree.c	(revision 457)
@@ -70,5 +70,5 @@
   return -1;
 }
-char * zAVL_string_get (zAVLTree * tree, char * key)
+char * zAVL_string_get (zAVLTree * tree, const char * key)
 {
   /* zAVLSearch() checks for NULL tree 
