Factor out common logic of unchanged_attrs and itemize into report_ATTR
[rsync/rsync.git] / generator.c
index f2c4233..d5dc85f 100644 (file)
@@ -276,7 +276,6 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
        struct file_list *dirlist;
        char delbuf[MAXPATHLEN];
        int dlen, i;
-       int save_uid_ndx = uid_ndx;
 
        if (!fbuf) {
                change_local_filter_dir(NULL, 0, 0);
@@ -289,7 +288,7 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
        if (allowed_lull)
                maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH);
 
-       if (io_error && !ignore_errors) {
+       if (io_error & IOERR_GENERAL && !ignore_errors) {
                if (already_warned)
                        return;
                rprintf(FINFO,
@@ -308,9 +307,6 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
                        return;
        }
 
-       if (!uid_ndx)
-               uid_ndx = ++file_extra_cnt;
-
        dirlist = get_dirlist(fbuf, dlen, 0);
 
        /* If an item in dirlist is not found in flist, delete it
@@ -330,7 +326,7 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
                 * a delete_item call with a DEL_MAKE_ROOM flag. */
                if (flist_find_ignore_dirness(cur_flist, fp) < 0) {
                        int flags = DEL_RECURSE;
-                       if (!(fp->mode & S_IWUSR) && !am_root && (uid_t)F_OWNER(fp) == our_uid)
+                       if (!(fp->mode & S_IWUSR) && !am_root && fp->flags & FLAG_OWNED_BY_US)
                                flags |= DEL_NO_UID_WRITE;
                        f_name(fp, delbuf);
                        if (delete_during == 2) {
@@ -342,11 +338,6 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
        }
 
        flist_free(dirlist);
-
-       if (!save_uid_ndx) {
-               --file_extra_cnt;
-               uid_ndx = 0;
-       }
 }
 
 /* This deletes any files on the receiving side that are not present on the
@@ -386,13 +377,30 @@ static void do_delete_pass(void)
                rprintf(FINFO, "                    \r");
 }
 
-static inline int time_differs(struct file_struct *file, stat_x *sxp)
+static BOOL preserve_time_of(struct file_struct *file)
+{
+       if (S_ISDIR(file->mode))
+               return preserve_times & PRESERVE_DIR_TIMES;
+       else if (S_ISLNK(file->mode))
+               /* PRESERVE_LINK_TIMES will only be set if CAN_SET_SYMLINK_TIMES. */
+               return preserve_times & PRESERVE_LINK_TIMES;
+       else
+               return preserve_times;
+}
+
+static BOOL report_time(struct file_struct *file, stat_x *sxp)
 {
-       return cmp_time(sxp->st.st_mtime, file->modtime);
+       return preserve_time_of(file) &&
+               cmp_time(sxp->st.st_mtime, file->modtime);
 }
 
-static inline int perms_differ(struct file_struct *file, stat_x *sxp)
+static BOOL report_perms(struct file_struct *file, stat_x *sxp)
 {
+#ifndef CAN_CHMOD_SYMLINK
+       if (S_ISLNK(file->mode))
+               return 0;
+#endif
+
        if (preserve_perms)
                return !BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS);
 
@@ -402,20 +410,34 @@ static inline int perms_differ(struct file_struct *file, stat_x *sxp)
        return 0;
 }
 
-static inline int ownership_differs(struct file_struct *file, stat_x *sxp)
+static BOOL report_owner(struct file_struct *file, stat_x *sxp)
 {
-       if (am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file))
-               return 1;
+#ifndef CAN_CHOWN_SYMLINK
+       if (S_ISLNK(file->mode))
+               return 0;
+#endif
 
-       if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP) && sxp->st.st_gid != (gid_t)F_GROUP(file))
-               return 1;
+       return uid_ndx && am_root && sxp->st.st_uid != (uid_t)F_OWNER(file);
+}
 
-       return 0;
+static BOOL report_group(struct file_struct *file, stat_x *sxp)
+{
+#ifndef CAN_CHOWN_SYMLINK
+       if (S_ISLNK(file->mode))
+               return 0;
+#endif
+
+       return gid_ndx && !(file->flags & FLAG_SKIP_GROUP) && sxp->st.st_gid != (gid_t)F_GROUP(file);
 }
 
 #ifdef SUPPORT_ACLS
-static inline int acls_differ(const char *fname, struct file_struct *file, stat_x *sxp)
+static BOOL report_acls(const char *fname, struct file_struct *file, stat_x *sxp)
 {
+#ifndef CAN_SET_SYMLINK_ACLS /* not currently */
+       if (S_ISLNK(file->mode))
+               return 0;
+#endif
+
        if (preserve_acls) {
                if (!ACL_READY(*sxp))
                        get_acl(fname, sxp);
@@ -428,12 +450,18 @@ static inline int acls_differ(const char *fname, struct file_struct *file, stat_
 #endif
 
 #ifdef SUPPORT_XATTRS
-static inline int xattrs_differ(const char *fname, struct file_struct *file, stat_x *sxp)
+static BOOL report_xattrs(const char *fname, struct file_struct *file, stat_x *sxp,
+                         BOOL mark_needed)
 {
+#ifdef NO_SYMLINK_XATTRS
+       if (S_ISLNK(file->mode))
+               return 0;
+#endif
+
        if (preserve_xattrs) {
                if (!XATTR_READY(*sxp))
                        get_xattr(fname, sxp);
-               if (xattr_diff(file, sxp, 0))
+               if (xattr_diff(file, sxp, mark_needed))
                        return 1;
        }
 
@@ -443,45 +471,17 @@ static inline int xattrs_differ(const char *fname, struct file_struct *file, sta
 
 int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
 {
-       if (S_ISLNK(file->mode)) {
-#ifdef CAN_SET_SYMLINK_TIMES
-               if (preserve_times & PRESERVE_LINK_TIMES && time_differs(file, sxp))
-                       return 0;
-#endif
-#ifdef CAN_CHMOD_SYMLINK
-               if (perms_differ(file, sxp))
-                       return 0;
-#endif
-#ifndef CAN_CHOWN_SYMLINK
-               if (ownership_differs(file, sxp))
-                       return 0;
-#endif
-#if defined SUPPORT_ACLS && 0 /* no current symlink-ACL support */
-               if (acls_differ(fname, file, sxp))
-                       return 0;
-#endif
-#if defined SUPPORT_XATTRS && !defined NO_SYMLINK_XATTRS
-               if (xattrs_differ(fname, file, sxp))
-                       return 0;
-#endif
-       } else {
-               if (preserve_times && time_differs(file, sxp))
-                       return 0;
-               if (perms_differ(file, sxp))
-                       return 0;
-               if (ownership_differs(file, sxp))
-                       return 0;
+       return !(report_time(file, sxp)
+               || report_perms(file, sxp)
+               || report_owner(file, sxp)
+               || report_group(file, sxp)
 #ifdef SUPPORT_ACLS
-               if (acls_differ(fname, file, sxp))
-                       return 0;
+               || report_acls(fname, file, sxp)
 #endif
 #ifdef SUPPORT_XATTRS
-               if (xattrs_differ(fname, file, sxp))
-                       return 0;
+               || report_xattrs(fname, file, sxp, False)
 #endif
-       }
-
-       return 1;
+               );
 }
 
 void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret,
@@ -489,56 +489,33 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
             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 & PRESERVE_DIR_TIMES
-                   : S_ISLNK(file->mode) ? preserve_times & PRESERVE_LINK_TIMES
-                   : 1;
-
                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
+               } else if (preserve_time_of(file)
                 ? 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)))
+               if (report_perms(file, sxp))
                        iflags |= ITEM_REPORT_PERMS;
-               if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
+               if (report_owner(file, sxp))
                        iflags |= ITEM_REPORT_OWNER;
-               if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
-                   && sxp->st.st_gid != (gid_t)F_GROUP(file))
+               if (report_group(file, sxp))
                        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, file->mode))
-                               iflags |= ITEM_REPORT_ACL;
-               }
+               if (report_acls(fnamecmp, file, sxp))
+                       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;
-               }
+               if (report_xattrs(fnamecmp, file, sxp, True))
+                       iflags |= ITEM_REPORT_XATTR;
 #endif
        } else {
 #ifdef SUPPORT_XATTRS
-               if (preserve_xattrs && xattr_diff(file, NULL, 1))
+               if (preserve_xattrs && xattr_diff(file, NULL, True))
                        iflags |= ITEM_REPORT_XATTR;
 #endif
                iflags |= ITEM_IS_NEW;
@@ -558,8 +535,10 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
 #ifdef SUPPORT_XATTRS
                        if (preserve_xattrs && do_xfers
                         && iflags & (ITEM_REPORT_XATTR|ITEM_TRANSFER)) {
-                               send_xattr_request(NULL, file,
-                                       iflags & ITEM_REPORT_XATTR ? sock_f_out : -1);
+                               int fd = iflags & ITEM_REPORT_XATTR
+                                     && (protocol_version < 31 || !BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE))
+                                      ? sock_f_out : -1;
+                               send_xattr_request(NULL, file, fd);
                        }
 #endif
                } else if (ndx >= 0) {
@@ -1185,7 +1164,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                                handle_skipped_hlink(file, itemizing, code, f_out);
 #endif
                        rprintf(FERROR_XFER,
-                               "skipping daemon-excluded %s \"%s\"\n",
+                               "ERROR: daemon refused to receive %s \"%s\"\n",
                                is_dir ? "directory" : "file", fname);
                        if (is_dir)
                                goto skipping_dir_contents;
@@ -1360,6 +1339,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                                goto cleanup;
                        }
                }
+
 #ifdef SUPPORT_XATTRS
                if (preserve_xattrs && statret == 1)
                        copy_xattrs(fnamecmpbuf, fname);