[Libguestfs] [PATCH] virt-diff: add additional ignore options

Gabriele Cerami gcerami at redhat.com
Tue Jan 6 23:34:50 UTC 2015


--compare-xattrs
--compare-extra-stats
--compare-perms
--compare-uids
--compare-times

to ignore, when set to no, specified files informations when comparing.

The current strategy to disable comparison on file informations is to
flatten data structure so they return the same 0/NULL value on
comparison and be, in fact, ignored to determine if the files differ.
This patch preserve original information on copies. Comparison is still
made on flattened structures, except for xattrs, but preserved
structure are used when showing file informations.
---
 diff/diff.c        | 96 ++++++++++++++++++++++++++++++++++++++++++------------
 diff/virt-diff.pod | 20 ++++++++++++
 2 files changed, 95 insertions(+), 21 deletions(-)

diff --git a/diff/diff.c b/diff/diff.c
index 6a374af..72e95a1 100644
--- a/diff/diff.c
+++ b/diff/diff.c
@@ -58,6 +58,11 @@ const char *libvirt_uri = NULL;
 int inspector = 1;
 
 static int atime = 0;
+static int compare_extra_stats = 1;
+static int compare_perms = 1;
+static int compare_times = 1;
+static int compare_uids = 1;
+static int compare_xattrs = 1;
 static int csv = 0;
 static int dir_links = 0;
 static int dir_times = 0;
@@ -104,6 +109,11 @@ usage (int status)
              "  --atime              Don't ignore access time changes\n"
              "  -A image             Add image from second guest\n"
              "  --checksum[=...]     Use checksum of file content\n"
+             "  --compare-extra-stats (yes|no)   Compare stats (default: yes)\n"
+             "  --compare-perms (yes|no)  Compare permissions (default: yes)\n"
+             "  --compare-times (yes|no)  Compare times (Default: yes)\n"
+             "  --compare-uids  (yes|no)  Compare uid and gid (default: yes)\n"
+             "  --compare-xattrs (yes|no) Compare extended attributes (default: yes)\n"
              "  -c|--connect uri     Specify libvirt URI for -d option\n"
              "  --csv                Comma-Separated Values output\n"
              "  --dir-links          Don't ignore directory nlink changes\n"
@@ -179,6 +189,11 @@ main (int argc, char *argv[])
     { "version", 0, 0, 'V' },
     { "xattr", 0, 0, 0 },
     { "xattrs", 0, 0, 0 },
+    { "compare-extra-stats", 1, 0, 0 },
+    { "compare-perms", 1, 0, 0 },
+    { "compare-times", 1, 0, 0 },
+    { "compare-uids", 1, 0, 0 },
+    { "compare-xattrs", 1, 0, 0 },
     { 0, 0, 0, 0 }
   };
   struct drv *drvs = NULL;      /* First guest. */
@@ -260,6 +275,21 @@ main (int argc, char *argv[])
       } else if (STREQ (long_options[option_index].name, "xattr") ||
                  STREQ (long_options[option_index].name, "xattrs")) {
         enable_xattrs = 1;
+      } else if (STREQ (long_options[option_index].name, "compare-extra-stats")) {
+        if (STREQ (optarg, "no"))
+          compare_extra_stats = 0;
+      } else if (STREQ (long_options[option_index].name, "compare-perms")) {
+        if (STREQ (optarg, "no"))
+          compare_perms = 0;
+      } else if (STREQ (long_options[option_index].name, "compare-times")) {
+        if (STREQ (optarg, "no"))
+          compare_times = 0;
+      } else if (STREQ (long_options[option_index].name, "compare-uids")) {
+        if (STREQ (optarg, "no"))
+          compare_uids = 0;
+      } else if (STREQ (long_options[option_index].name, "compare-xattrs")) {
+        if (STREQ (optarg, "no"))
+          compare_xattrs = 0;
       } else {
         fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
                  program_name, long_options[option_index].name, option_index);
@@ -404,6 +434,8 @@ struct file {
   char *path;
   struct guestfs_statns *stat;
   struct guestfs_xattr_list *xattrs;
+  struct guestfs_statns *stat_orig;
+  struct guestfs_xattr_list *xattrs_orig;
   char *csum;                  /* Checksum. If NULL, use file times and size. */
 };
 
@@ -416,6 +448,8 @@ free_tree (struct tree *t)
     free (t->files[i].path);
     guestfs_free_statns (t->files[i].stat);
     guestfs_free_xattr_list (t->files[i].xattrs);
+    guestfs_free_statns (t->files[i].stat_orig);
+    guestfs_free_xattr_list (t->files[i].xattrs_orig);
     free (t->files[i].csum);
   }
 
@@ -466,6 +500,8 @@ visit_entry (const char *dir, const char *name,
   char *path = NULL, *csum = NULL;
   struct guestfs_statns *stat = NULL;
   struct guestfs_xattr_list *xattrs = NULL;
+  struct guestfs_statns *stat_copy = NULL;
+  struct guestfs_xattr_list *xattrs_copy = NULL;
   size_t i;
 
   path = full_path (dir, name);
@@ -474,16 +510,31 @@ visit_entry (const char *dir, const char *name,
    * free them after we return.
    */
   stat = guestfs_copy_statns (stat_orig);
+  stat_copy = guestfs_copy_statns (stat_orig);
   if (stat == NULL) {
     perror ("guestfs_copy_stat");
     goto error;
   }
+  if (!compare_perms)
+    stat->st_mode &= 0170000;
+
+  if (!compare_extra_stats)
+    stat->st_dev = stat->st_ino = stat->st_nlink = stat->st_rdev =
+      stat->st_blocks = 0;
+
+  if (!compare_uids)
+    stat->st_uid = stat->st_gid = 0;
+
+  if (!compare_times)
+    stat->st_atime_sec = stat->st_mtime_sec = stat->st_ctime_sec =
+      stat->st_atime_nsec = stat->st_mtime_nsec = stat->st_ctime_nsec = 0;
+
   xattrs = guestfs_copy_xattr_list (xattrs_orig);
+  xattrs_copy = guestfs_copy_xattr_list (xattrs_orig);
   if (xattrs == NULL) {
     perror ("guestfs_copy_xattr_list");
     goto error;
   }
-
   if (checksum && is_reg (stat->st_mode)) {
     csum = guestfs_checksum (t->g, checksum, path);
     if (!csum)
@@ -534,6 +585,8 @@ visit_entry (const char *dir, const char *name,
   t->files[i].stat = stat;
   t->files[i].xattrs = xattrs;
   t->files[i].csum = csum;
+  t->files[i].stat_orig = stat_copy;
+  t->files[i].xattrs_orig = xattrs_copy;
 
   return 0;
 
@@ -631,10 +684,11 @@ compare_stats (struct file *file1, struct file *file2)
   if (r != 0)
     return r;
 
-  r = guestfs_compare_xattr_list (file1->xattrs, file2->xattrs);
-  if (r != 0)
-    return r;
-
+  if (compare_xattrs) {
+    r = guestfs_compare_xattr_list (file1->xattrs, file2->xattrs);
+    if (r != 0)
+      return r;
+  }
   return 0;
 }
 
@@ -778,29 +832,29 @@ output_file (guestfs_h *g, struct file *file)
     filetype = "u";
 
   output_string (filetype);
-  output_int64_perms (file->stat->st_mode & 07777);
+  output_int64_perms (file->stat_orig->st_mode & 07777);
 
-  output_int64_size (file->stat->st_size);
+  output_int64_size (file->stat_orig->st_size);
 
   /* Display extra fields when enabled. */
   if (enable_uids) {
-    output_int64_uid (file->stat->st_uid);
-    output_int64_uid (file->stat->st_gid);
+    output_int64_uid (file->stat_orig->st_uid);
+    output_int64_uid (file->stat_orig->st_gid);
   }
 
   if (enable_times) {
     if (atime)
-      output_int64_time (file->stat->st_atime_sec, file->stat->st_atime_nsec);
-    output_int64_time (file->stat->st_mtime_sec, file->stat->st_mtime_nsec);
-    output_int64_time (file->stat->st_ctime_sec, file->stat->st_ctime_nsec);
+      output_int64_time (file->stat_orig->st_atime_sec, file->stat_orig->st_atime_nsec);
+    output_int64_time (file->stat_orig->st_mtime_sec, file->stat_orig->st_mtime_nsec);
+    output_int64_time (file->stat_orig->st_ctime_sec, file->stat_orig->st_ctime_nsec);
   }
 
   if (enable_extra_stats) {
-    output_int64_dev (file->stat->st_dev);
-    output_int64 (file->stat->st_ino);
-    output_int64 (file->stat->st_nlink);
-    output_int64_dev (file->stat->st_rdev);
-    output_int64 (file->stat->st_blocks);
+    output_int64_dev (file->stat_orig->st_dev);
+    output_int64 (file->stat_orig->st_ino);
+    output_int64 (file->stat_orig->st_nlink);
+    output_int64_dev (file->stat_orig->st_rdev);
+    output_int64 (file->stat_orig->st_blocks);
   }
 
   if (file->csum)
@@ -816,10 +870,10 @@ output_file (guestfs_h *g, struct file *file)
   }
 
   if (enable_xattrs) {
-    for (i = 0; i < file->xattrs->len; ++i) {
-      output_string (file->xattrs->val[i].attrname);
-      output_binary (file->xattrs->val[i].attrval,
-                     file->xattrs->val[i].attrval_len);
+    for (i = 0; i < file->xattrs_orig->len; ++i) {
+      output_string (file->xattrs_orig->val[i].attrname);
+      output_binary (file->xattrs_orig->val[i].attrval,
+                     file->xattrs_orig->val[i].attrval_len);
     }
   }
 }
diff --git a/diff/virt-diff.pod b/diff/virt-diff.pod
index e1d67f3..898155d 100644
--- a/diff/virt-diff.pod
+++ b/diff/virt-diff.pod
@@ -214,6 +214,26 @@ Enable tracing of libguestfs API calls.
 
 Display extended attributes.
 
+=item B<--compare-extra-stats (yes|no)>
+
+If set to no, when comparing, do not consider files different if extra stats (like inode number) differ. Default is yes.
+
+=item B<--compare-perms (yes|no)>
+
+If set to no, when comparing, do not consider files different if permissions differ. Default is yes.
+
+=item B<--compare-times (yes|no)>
+
+If set to no, when comparing, do not consider files different if any of the times  differ. Default is yes.
+
+=item B<--compare-uids (yes|no)>
+
+If set to no, when comparing, do not consider files different if uid and gid differ. Default is yes.
+
+=item B<--compare-xattrs (yes|no)>
+
+If set to no, when comparing, do not consider files different if extended attributes differ. Default is yes.
+
 =back
 
 =head1 NOTE ABOUT CSV FORMAT
-- 
1.9.3




More information about the Libguestfs mailing list