Gabriele Cerami
2015-Jan-06 23:34 UTC
[Libguestfs] [PATCH] virt-diff: add additional ignore options
--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