Up thru 3.0.9 transferring symlinks using "-L --remove-source-files" properly transferred the files and removed the symlinks. Beginning with 3.1.0 this no longer works; the files transfer properly but the symlinks on the source server fail to get deleted. This error message is displayed: ERROR: Skipping sender remove for changed file: [transferred file name] I have not been able to find a workaround to this problem, other than downgrading from 3.1.0 back to 3.0.9.
That's weird, as it means that the source symlink must differ in size or modify time from what rsync put into the source file list. However, since that safety check is only really needed for regular files, I've added some code that should avoid this failure for symlinks and devices.
We have found this same problem using rsync 3.1.2. I have downloaded the source code for version 3.1.3, and found the following lines in sender.c: 146 if (S_ISREG(file->mode) /* Symlinks & devices don't need this check: */ 147 && (st.st_size != F_LENGTH(file) || st.st_mtime != file->modtime 148 #ifdef ST_MTIME_NSEC 149 || (NSEC_BUMP(file) && (uint32)st.ST_MTIME_NSEC != F_MOD_NSEC(file)) 150 #endif 151 )) { 152 rprintf(FERROR_XFER, "ERROR: Skipping sender remove for changed file: %s\n", fname); 153 return; 154 } I added some debugging info, compiled and tested, and found out that when trying to retrieve symlinks the "file" pointer refers to the hard file, whereas the "st" register refers to the symlink. Therefore "S_ISREG(file->mode)" will be true, so will be "st.st_size != F_LENGTH(file)" and most likely "st.st_mtime != file->modtime" too. As a result the error gets printed and the symlink is not deleted, as intended. I have tried modifying the first condition and it worked as expected: 146 if (S_ISREG(st.st_mode) /* Symlinks & devices don't need this check: */ Best regards.
Another option that I tried and verified, and that could make more sense, would be to replace 141 if (do_lstat(fname, &st) < 0) { with 141 if (do_stat(fname, &st) < 0) {
In my prior testing I apparently missed that the symlink verification issue was caused by -L (--copy-links). I have amended the change to use do_stat() when --copy-links is enabled.
I embedded the modified sender.c into 3.1.3's original source code, compiled and tested, and I found it to have solved the problem: first I tried uploading a softlink and deleting, then I tried uploading a normal file and deleting. It worked the two times.