summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2021-11-03 11:40:13 +0100
committerJule Anger <janger@samba.org>2022-01-30 10:57:11 +0000
commit1538a574a22c2762ed322ffbf34f63ca872f034b (patch)
tree5233d7c0b8935aad85d5a4571a4135256a358c49
parentf1cbfdc43c8e940c6d2667eccc7545e39be49468 (diff)
downloadsamba-1538a574a22c2762ed322ffbf34f63ca872f034b.tar.gz
lib/util: add dump_data_diff*() helpers
That will make it easy to see the difference between two memory buffers. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14956 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org> (cherry picked from commit b489b7feda19b3c0f0fe2300f2c76d416776355b)
-rw-r--r--lib/util/util.c84
-rw-r--r--lib/util/util.h28
2 files changed, 112 insertions, 0 deletions
diff --git a/lib/util/util.c b/lib/util/util.c
index 38a988331a7..c066406d320 100644
--- a/lib/util/util.c
+++ b/lib/util/util.c
@@ -615,6 +615,90 @@ void dump_data_file(const uint8_t *buf, int len, bool omit_zero_bytes,
}
/**
+ * Write dump of compared binary data to a callback
+ */
+void dump_data_diff_cb(const uint8_t *buf1, size_t len1,
+ const uint8_t *buf2, size_t len2,
+ bool omit_zero_bytes,
+ void (*cb)(const char *buf, void *private_data),
+ void *private_data)
+{
+ size_t len = MAX(len1, len2);
+ size_t i;
+ bool skipped = false;
+
+ for (i=0; i<len; i+=16) {
+ size_t remaining_len = len - i;
+ size_t remaining_len1 = 0;
+ size_t this_len1 = 0;
+ const uint8_t *this_buf1 = NULL;
+ size_t remaining_len2 = 0;
+ size_t this_len2 = 0;
+ const uint8_t *this_buf2 = NULL;
+
+ if (i < len1) {
+ remaining_len1 = len1 - i;
+ this_len1 = MIN(remaining_len1, 16);
+ this_buf1 = &buf1[i];
+ }
+ if (i < len2) {
+ remaining_len2 = len2 - i;
+ this_len2 = MIN(remaining_len2, 16);
+ this_buf2 = &buf2[i];
+ }
+
+ if ((omit_zero_bytes == true) &&
+ (i > 0) && (remaining_len > 16) &&
+ (this_len1 == 16) && all_zero(this_buf1, 16) &&
+ (this_len2 == 16) && all_zero(this_buf2, 16))
+ {
+ if (!skipped) {
+ cb("skipping zero buffer bytes\n",
+ private_data);
+ skipped = true;
+ }
+ continue;
+ }
+
+ skipped = false;
+
+ if ((this_len1 == this_len2) &&
+ (memcmp(this_buf1, this_buf2, this_len1) == 0))
+ {
+ dump_data_block16(" ", i, this_buf1, this_len1,
+ cb, private_data);
+ continue;
+ }
+
+ dump_data_block16("-", i, this_buf1, this_len1,
+ cb, private_data);
+ dump_data_block16("+", i, this_buf2, this_len2,
+ cb, private_data);
+ }
+}
+
+_PUBLIC_ void dump_data_diff(int dbgc_class, int level,
+ bool omit_zero_bytes,
+ const uint8_t *buf1, size_t len1,
+ const uint8_t *buf2, size_t len2)
+{
+ struct debug_channel_level dcl = { dbgc_class, level };
+
+ if (!DEBUGLVLC(dbgc_class, level)) {
+ return;
+ }
+ dump_data_diff_cb(buf1, len1, buf2, len2, true, debugadd_channel_cb, &dcl);
+}
+
+_PUBLIC_ void dump_data_file_diff(FILE *f,
+ bool omit_zero_bytes,
+ const uint8_t *buf1, size_t len1,
+ const uint8_t *buf2, size_t len2)
+{
+ dump_data_diff_cb(buf1, len1, buf2, len2, omit_zero_bytes, fprintf_cb, f);
+}
+
+/**
malloc that aborts with smb_panic on fail or zero size.
**/
diff --git a/lib/util/util.h b/lib/util/util.h
index a7acad56880..072f0486234 100644
--- a/lib/util/util.h
+++ b/lib/util/util.h
@@ -51,4 +51,32 @@ _PUBLIC_ void dump_data(int level, const uint8_t *buf,int len);
*/
_PUBLIC_ void dump_data_dbgc(int dbgc_class, int level, const uint8_t *buf, int len);
+/**
+ * Write dump of compared binary data to a callback
+ */
+void dump_data_diff_cb(const uint8_t *buf1, size_t len1,
+ const uint8_t *buf2, size_t len2,
+ bool omit_zero_bytes,
+ void (*cb)(const char *buf, void *private_data),
+ void *private_data);
+
+/**
+ * Write dump of compared binary data to the log file.
+ *
+ * The data is only written if the log level is at least level for
+ * debug class dbgc_class.
+ */
+_PUBLIC_ void dump_data_diff(int dbgc_class, int level,
+ bool omit_zero_bytes,
+ const uint8_t *buf1, size_t len1,
+ const uint8_t *buf2, size_t len2);
+
+/**
+ * Write dump of compared binary data to the given file handle
+ */
+_PUBLIC_ void dump_data_file_diff(FILE *f,
+ bool omit_zero_bytes,
+ const uint8_t *buf1, size_t len1,
+ const uint8_t *buf2, size_t len2);
+
#endif