Man page: Move the description of --info=progress2 to a better place.
[rsync/rsync.git] / sender.c
index 9861296..ebc8839 100644 (file)
--- a/sender.c
+++ b/sender.c
@@ -42,6 +42,7 @@ extern int make_backups;
 extern int inplace;
 extern int batch_fd;
 extern int write_batch;
+extern int file_old_total;
 extern struct stats stats;
 extern struct file_list *cur_flist, *first_flist, *dir_flist;
 
@@ -62,7 +63,7 @@ static struct sum_struct *receive_sums(int f)
 {
        struct sum_struct *s;
        int32 i;
-       int lull_mod = allowed_lull * 5;
+       int lull_mod = protocol_version >= 31 ? 0 : allowed_lull * 5;
        OFF_T offset = 0;
 
        if (!(s = new(struct sum_struct)))
@@ -103,8 +104,8 @@ static struct sum_struct *receive_sums(int f)
                        s->sums[i].len = s->blength;
                offset += s->sums[i].len;
 
-               if (allowed_lull && !(i % lull_mod))
-                       maybe_send_keepalive();
+               if (lull_mod && !(i % lull_mod))
+                       maybe_send_keepalive(time(NULL), True);
 
                if (DEBUG_GTE(DELTASUM, 3)) {
                        rprintf(FINFO,
@@ -122,8 +123,10 @@ static struct sum_struct *receive_sums(int f)
 void successful_send(int ndx)
 {
        char fname[MAXPATHLEN];
+       char *failed_op;
        struct file_struct *file;
        struct file_list *flist;
+       STRUCT_STAT st;
 
        if (!remove_source_files)
                return;
@@ -134,11 +137,31 @@ void successful_send(int ndx)
                return;
        f_name(file, fname);
 
-       if (do_unlink(fname) == 0) {
+       if (do_lstat(fname, &st) < 0) {
+               failed_op = "re-lstat";
+               goto failed;
+       }
+
+       if (st.st_size != F_LENGTH(file) || st.st_mtime != file->modtime
+#ifdef ST_MTIME_NSEC
+        || (NSEC_BUMP(file) && (uint32)st.ST_MTIME_NSEC != F_MOD_NSEC(file))
+#endif
+       ) {
+               rprintf(FERROR, "ERROR: Skipping sender remove for changed file: %s\n", fname);
+               return;
+       }
+
+       if (do_unlink(fname) < 0) {
+               failed_op = "remove";
+         failed:
+               if (errno == ENOENT)
+                       rprintf(FINFO, "sender file already removed: %s\n", fname);
+               else
+                       rsyserr(FERROR, errno, "sender failed to %s %s", failed_op, fname);
+       } else {
                if (INFO_GTE(REMOVE, 1))
                        rprintf(FINFO, "sender removed %s\n", fname);
-       } else
-               rsyserr(FERROR, errno, "sender failed to remove %s", fname);
+       }
 }
 
 static void write_ndx_and_attrs(int f_out, int ndx, int iflags,
@@ -154,7 +177,8 @@ static void write_ndx_and_attrs(int f_out, int ndx, int iflags,
        if (iflags & ITEM_XNAME_FOLLOWS)
                write_vstring(f_out, buf, len);
 #ifdef SUPPORT_XATTRS
-       if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers)
+       if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers
+        && (protocol_version < 31 || !BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE)))
                send_xattr_request(fname, file, f_out);
 #endif
 }
@@ -197,8 +221,11 @@ void send_files(int f_in, int f_out)
                                end_progress(0);
                        }
                        if (inc_recurse && first_flist) {
+                               file_old_total -= first_flist->used;
                                flist_free(first_flist);
                                if (first_flist) {
+                                       if (first_flist == cur_flist)
+                                               file_old_total = cur_flist->used;
                                        write_ndx(f_out, NDX_DONE);
                                        continue;
                                }
@@ -232,7 +259,8 @@ void send_files(int f_in, int f_out)
                        rprintf(FINFO, "send_files(%d, %s%s%s)\n", ndx, path,slash,fname);
 
 #ifdef SUPPORT_XATTRS
-               if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers)
+               if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers
+                && (protocol_version < 31 || !BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE)))
                        recv_xattr_request(file, f_in);
 #endif
 
@@ -333,7 +361,7 @@ void send_files(int f_in, int f_out)
                        rsyserr(FERROR_XFER, errno, "fstat failed");
                        free_sums(s);
                        close(fd);
-                       exit_cleanup(RERR_PROTOCOL);
+                       exit_cleanup(RERR_FILEIO);
                }
 
                if (st.st_size) {