static void changed (guestfs_h *g1, struct file *file1, guestfs_h *g2, struct file *file2, int st, int cst) { /* Did file content change? */ if (cst != 0 || (is_reg (file1->stat->st_mode) && is_reg (file2->stat->st_mode) && (file1->stat->st_mtime_sec != file2->stat->st_mtime_sec || file1->stat->st_ctime_sec != file2->stat->st_ctime_sec || file1->stat->st_size != file2->stat->st_size))) { output_start_line (); output_string ("="); output_file (g1, file1); output_end_line (); if (!csv) { /* Display file changes. */ output_flush (); diff (file1, g1, file2, g2); } } /* Did just stats change? */ else if (st != 0) { output_start_line (); output_string ("-"); output_file (g1, file1); output_end_line (); output_start_line (); output_string ("+"); output_file (g2, file2); output_end_line (); /* Display stats fields that changed. */ output_start_line (); output_string ("#"); output_string ("changed:"); #define COMPARE_STAT(n) \ if (file1->stat->n != file2->stat->n) output_string (#n) COMPARE_STAT (st_dev); COMPARE_STAT (st_ino); COMPARE_STAT (st_mode); COMPARE_STAT (st_nlink); COMPARE_STAT (st_uid); COMPARE_STAT (st_gid); COMPARE_STAT (st_rdev); COMPARE_STAT (st_size); COMPARE_STAT (st_blksize); COMPARE_STAT (st_blocks); COMPARE_STAT (st_atime_sec); COMPARE_STAT (st_mtime_sec); COMPARE_STAT (st_ctime_sec); #undef COMPARE_STAT if (guestfs_compare_xattr_list (file1->xattrs, file2->xattrs)) output_string ("xattrs"); output_end_line (); } }
static void added (guestfs_h *g, struct file *file) { output_start_line (); output_string ("+"); output_file (g, file); output_end_line (); }
/* This is the function which is called to display all files and * directories, and it's where the magic happens. We are called with * full stat and extended attributes for each file, so there is no * penalty for displaying anything in those structures. However if we * need other things (eg. checksum) we may have to go back to the * appliance and then there can be a very large penalty. */ static int show_file (const char *dir, const char *name, const struct guestfs_stat *stat, const struct guestfs_xattr_list *xattrs, void *unused) { const char *filetype; CLEANUP_FREE char *path = NULL, *csum = NULL, *link = NULL; /* Display the basic fields. */ output_start_line (); if (is_reg (stat->mode)) filetype = "-"; else if (is_dir (stat->mode)) filetype = "d"; else if (is_chr (stat->mode)) filetype = "c"; else if (is_blk (stat->mode)) filetype = "b"; else if (is_fifo (stat->mode)) filetype = "p"; else if (is_lnk (stat->mode)) filetype = "l"; else if (is_sock (stat->mode)) filetype = "s"; else filetype = "u"; output_string (filetype); output_int64_perms (stat->mode & 07777); output_int64_size (stat->size); /* Display extra fields when enabled. */ if (enable_uids) { output_int64_uid (stat->uid); output_int64_uid (stat->gid); } if (enable_times) { output_int64_time (stat->atime); output_int64_time (stat->mtime); output_int64_time (stat->ctime); } if (enable_extra_stats) { output_int64_dev (stat->dev); output_int64 (stat->ino); output_int64 (stat->nlink); output_int64_dev (stat->rdev); output_int64 (stat->blocks); } /* Disabled for now -- user would definitely want these to be interpreted. if (enable_xattrs) output_xattrs (xattrs); */ path = full_path (dir, name); if (checksum && is_reg (stat->mode)) { csum = guestfs_checksum (g, checksum, path); if (!csum) exit (EXIT_FAILURE); output_string (csum); } output_string (path); if (is_lnk (stat->mode)) /* XXX Fix this for NTFS. */ link = guestfs_readlink (g, path); if (link) output_string_link (link); output_end_line (); return 0; }