Fixes bug 7691.
extern iconv_t ic_send, ic_recv;
#endif
-#ifdef HAVE_UTIMENSAT
-#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
-#define ST_MTIME_NSEC st_mtim.tv_nsec
-#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
-#define ST_MTIME_NSEC st_mtimensec
-#endif
-#endif
-
#define PTR_SIZE (sizeof (struct file_struct *))
int io_error;
#define CAN_CHMOD_SYMLINK 1
#endif
+#ifdef HAVE_UTIMENSAT
+#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+#define ST_MTIME_NSEC st_mtim.tv_nsec
+#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
+#define ST_MTIME_NSEC st_mtimensec
+#endif
+#endif
+
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
side the files (meaning non-directories) that are a part of the transfer
and have been successfully duplicated on the receiving side.
+Note that you should only use this option on source files that are quiescent.
+If you are using this to move files that show up in a particular directory over
+to another host, make sure that the finished files get renamed into the source
+directory, not directly written into it, so that rsync can't possibly transfer
+a file that is not yet fully written. If you can't first write the files into
+a different directory, you should use a naming idiom that lets rsync avoid
+transferring files that are not yet finished (e.g. name the file "foo.new" when
+it is written, rename it to "foo" when it is done, and then use the option
+bf(--exclude='*.new') for the rsync transfer).
+
+Starting with 3.1.0, rsync will skip the sender-side removal (and output an
+error) if the file's size or modify time has not stayed unchanged.
+
dit(bf(--delete)) This tells rsync to delete extraneous files from the
receiving side (ones that aren't on the sending side), but only for the
directories that are being synchronized. You must have asked rsync to
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;
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,
int preserve_executability = 0;
char number_separator;
-#ifdef HAVE_UTIMENSAT
-#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
-#define ST_MTIME_NSEC st_mtim.tv_nsec
-#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
-#define ST_MTIME_NSEC st_mtimensec
-#endif
-#endif
-
#ifdef SUPPORT_XATTRS
#ifdef HAVE_LINUX_XATTRS