+ if (INFO_GTE(FLIST, 2) && !am_server)
+ rprintf(FINFO, " \r");
+}
+
+int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
+{
+#if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
+ if (S_ISLNK(file->mode)) {
+ ;
+ } else
+#endif
+ if (preserve_times && cmp_time(sxp->st.st_mtime, file->modtime) != 0)
+ return 0;
+
+ if (preserve_perms) {
+ if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
+ return 0;
+ } else if (preserve_executability
+ && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
+ return 0;
+
+ if (am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file))
+ return 0;
+
+ if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP) && sxp->st.st_gid != (gid_t)F_GROUP(file))
+ return 0;
+
+#ifdef SUPPORT_ACLS
+ if (preserve_acls && !S_ISLNK(file->mode)) {
+ if (!ACL_READY(*sxp))
+ get_acl(fname, sxp);
+ if (set_acl(NULL, file, sxp) == 0)
+ return 0;
+ }
+#endif
+#ifdef SUPPORT_XATTRS
+ if (preserve_xattrs) {
+ if (!XATTR_READY(*sxp))
+ get_xattr(fname, sxp);
+ if (xattr_diff(file, sxp, 0))
+ return 0;
+ }
+#endif
+
+ return 1;
+}
+
+void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret,
+ stat_x *sxp, int32 iflags, uchar fnamecmp_type,
+ const char *xname)
+{
+ if (statret >= 0) { /* A from-dest-dir statret can == 1! */
+ int keep_time = !preserve_times ? 0
+ : S_ISDIR(file->mode) ? preserve_times > 1 :
+#if defined HAVE_LUTIMES && defined HAVE_UTIMES
+ 1;
+#else
+ !S_ISLNK(file->mode);
+#endif
+
+ if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size)
+ iflags |= ITEM_REPORT_SIZE;
+ if (file->flags & FLAG_TIME_FAILED) { /* symlinks only */
+ if (iflags & ITEM_LOCAL_CHANGE)
+ iflags |= symlink_timeset_failed_flags;
+ } else if (keep_time
+ ? cmp_time(file->modtime, sxp->st.st_mtime) != 0
+ : iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !(iflags & ITEM_MATCHED)
+ && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
+ iflags |= ITEM_REPORT_TIME;
+#if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
+ if (S_ISLNK(file->mode)) {
+ ;
+ } else
+#endif
+ if (preserve_perms) {
+ if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
+ iflags |= ITEM_REPORT_PERMS;
+ } else if (preserve_executability
+ && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
+ iflags |= ITEM_REPORT_PERMS;
+ if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
+ iflags |= ITEM_REPORT_OWNER;
+ if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
+ && sxp->st.st_gid != (gid_t)F_GROUP(file))
+ iflags |= ITEM_REPORT_GROUP;
+#ifdef SUPPORT_ACLS
+ if (preserve_acls && !S_ISLNK(file->mode)) {
+ if (!ACL_READY(*sxp))
+ get_acl(fnamecmp, sxp);
+ if (set_acl(NULL, file, sxp) == 0)
+ iflags |= ITEM_REPORT_ACL;
+ }
+#endif
+#ifdef SUPPORT_XATTRS
+ if (preserve_xattrs) {
+ if (!XATTR_READY(*sxp))
+ get_xattr(fnamecmp, sxp);
+ if (xattr_diff(file, sxp, 1))
+ iflags |= ITEM_REPORT_XATTR;
+ }
+#endif
+ } else {
+#ifdef SUPPORT_XATTRS
+ if (preserve_xattrs && xattr_diff(file, NULL, 1))
+ iflags |= ITEM_REPORT_XATTR;
+#endif
+ iflags |= ITEM_IS_NEW;
+ }
+
+ iflags &= 0xffff;
+ if ((iflags & (SIGNIFICANT_ITEM_FLAGS|ITEM_REPORT_XATTR) || INFO_GTE(NAME, 2)
+ || stdout_format_has_i > 1 || (xname && *xname)) && !read_batch) {
+ if (protocol_version >= 29) {
+ if (ndx >= 0)
+ write_ndx(sock_f_out, ndx);
+ write_shortint(sock_f_out, iflags);
+ if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
+ write_byte(sock_f_out, fnamecmp_type);
+ if (iflags & ITEM_XNAME_FOLLOWS)
+ write_vstring(sock_f_out, xname, strlen(xname));
+#ifdef SUPPORT_XATTRS
+ if (preserve_xattrs && !dry_run
+ && iflags & (ITEM_REPORT_XATTR|ITEM_TRANSFER)) {
+ send_xattr_request(NULL, file,
+ iflags & ITEM_REPORT_XATTR ? sock_f_out : -1);
+ }
+#endif
+ } else if (ndx >= 0) {
+ enum logcode code = logfile_format_has_i ? FINFO : FCLIENT;
+ log_item(code, file, &stats, iflags, xname);
+ }
+ }
+}
+
+
+/* Perform our quick-check heuristic for determining if a file is unchanged. */
+int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
+{
+ if (st->st_size != F_LENGTH(file))
+ return 0;
+
+ /* if always checksum is set then we use the checksum instead
+ of the file time to determine whether to sync */
+ if (always_checksum > 0 && S_ISREG(st->st_mode)) {
+ char sum[MAX_DIGEST_LEN];
+ file_checksum(fn, sum, st->st_size);
+ return memcmp(sum, F_SUM(file), checksum_len) == 0;
+ }
+
+ if (size_only > 0)
+ return 1;
+
+ if (ignore_times)
+ return 0;
+
+ return cmp_time(st->st_mtime, file->modtime) == 0;
+}
+
+
+/*
+ * set (initialize) the size entries in the per-file sum_struct
+ * calculating dynamic block and checksum sizes.
+ *
+ * This is only called from generate_and_send_sums() but is a separate
+ * function to encapsulate the logic.