Subject: bug#34683: regression in file tree walker

From: Mike Gulick <[email-masked]>
Date: Thu, 28 Feb 2019 10:32:37 -0500

Hi,

I was testing the tip of the idutils, and I saw that a bunch of files
were getting left out of my idutils database.  I also see a bunch of
warnings about files being the same but different.  E.g.

$ ./src/mkid -m libidu/id-lang.map -o test_db.ID /usr/include/
./mkid: warning: `/usr/include/wireless.h' and `/usr/include/pugiconfig.hpp' are the same file, but yield different scans!
./mkid: warning: `/usr/include/c++/8.2.1/ext/pb_ds/detail/pairing_heap_/insert_fn_imps.hpp' and `/usr/include/sodium.h' are the same file, but yield different scans!
./mkid: warning: `/usr/include/c++/8.2.1/ext/pb_ds/detail/rb_tree_map_/split_join_fn_imps.hpp' and `/usr/include/neaacdec.h' are the same file, but yield different scans!
./mkid: warning: `/usr/include/c++/8.2.1/ext/pb_ds/detail/rb_tree_map_/traits.hpp' and `/usr/include/faad.h' are the same file, but yield different scans!
./mkid: warning: `/usr/include/c++/8.2.1/ext/pb_ds/detail/splay_tree_/info_fn_imps.hpp' and `/usr/include/git2.h' are the same file, but yield different scans!
./mkid: warning: `/usr/include/guile/2.0/readline.h' and `/usr/include/c++/8.2.1/ext/pb_ds/detail/cc_hash_table_map_/insert_no_store_hash_fn_imps.hpp' are the same file, but yield different scans!
...

The issue seems to be in the last commit that changes
dev_ino_hash_compare.  This function is returning 1 (true) when the
dev_ino structs are identical and 0 (false) when different.  However
the hash table expects traditional comparator behavior (i.e. x - y).
The following patch fixes the issue for me.

Thanks,
Mike

--

diff --git a/libidu/walker.c b/libidu/walker.c
index b6a6109..e43f3f5 100644
--- a/libidu/walker.c
+++ b/libidu/walker.c
@@ -1141,9 +1141,16 @@ DEV_INO_HASH_DEFUN(dev_ino_hash_2, xform_NOT)
 static int
 dev_ino_hash_compare (void const *xv, void const *yv)
 {
+  int result;
   struct dev_ino const *x = xv;
   struct dev_ino const *y = yv;
-  return x->di_ino == y->di_ino && x->di_dev == y->di_dev;
+
+  result = (x->di_ino > y->di_ino) - (x->di_ino < y->di_ino);
+  if (result)
+    return result;
+
+  result = (x->di_dev > y->di_dev) - (x->di_dev < y->di_dev);
+  return result;
 }
 
 #endif