diff options
-rw-r--r-- | compat.c | 4 | ||||
-rw-r--r-- | generator.c | 27 | ||||
-rw-r--r-- | log.c | 24 | ||||
-rw-r--r-- | rsync.h | 5 | ||||
-rw-r--r-- | rsync.yo | 7 | ||||
-rw-r--r-- | testsuite/devices.test | 10 | ||||
-rw-r--r-- | testsuite/itemize.test | 6 |
7 files changed, 51 insertions, 32 deletions
@@ -271,6 +271,10 @@ void setup_protocol(int f_out,int f_in) exit_cleanup(RERR_SYNTAX); } need_messages_from_generator = 1; +#if defined HAVE_LUTIMES && defined HAVE_UTIMES + } else if (!am_sender) { + receiver_symlink_times = 1; +#endif } if (need_unsorted_flist && (!am_sender || inc_recurse)) diff --git a/generator.c b/generator.c index 9e24f564..1b13d56e 100644 --- a/generator.c +++ b/generator.c @@ -27,7 +27,6 @@ extern int dry_run; extern int do_xfers; extern int stdout_format_has_i; extern int logfile_format_has_i; -extern int receiver_symlink_times; extern int am_root; extern int am_server; extern int am_daemon; @@ -111,6 +110,7 @@ static char *deldelay_buf = NULL; static int deldelay_fd = -1; static int lull_mod; static int dir_tweaking; +static int symlink_timeset_failed_flags; static int need_retouch_dir_times; static int need_retouch_dir_perms; static const char *solo_file = NULL; @@ -623,16 +623,20 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre int keep_time = !preserve_times ? 0 : S_ISDIR(file->mode) ? preserve_times > 1 : #if defined HAVE_LUTIMES && defined HAVE_UTIMES - (receiver_symlink_times && !(file->flags & FLAG_TIME_FAILED)) || -#endif + 1; +#else !S_ISLNK(file->mode); +#endif if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size) iflags |= ITEM_REPORT_SIZE; - if ((iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !keep_time - && !(iflags & ITEM_MATCHED) + 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)) - || (keep_time && cmp_time(file->modtime, sxp->st.st_mtime) != 0)) iflags |= ITEM_REPORT_TIME; #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST if (S_ISLNK(file->mode)) { @@ -1159,8 +1163,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx, if (itemizing && stdout_format_has_i && (verbose > 1 || stdout_format_has_i > 1)) { int chg = compare_dest && type != TYPE_DIR ? 0 - : ITEM_LOCAL_CHANGE - + (match_level == 3 ? ITEM_XNAME_FOLLOWS : 0); + : ITEM_LOCAL_CHANGE + (match_level == 3 ? ITEM_XNAME_FOLLOWS : 0); char *lp = match_level == 3 ? "" : NULL; itemize(cmpbuf, file, ndx, 0, sxp, chg + ITEM_MATCHED, 0, lp); } @@ -1538,7 +1541,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, set_file_attrs(fname, file, NULL, NULL, 0); if (itemizing) { itemize(fname, file, ndx, statret, &sx, - ITEM_LOCAL_CHANGE, 0, NULL); + ITEM_LOCAL_CHANGE|ITEM_REPORT_CHANGE, 0, NULL); } if (code != FNONE && verbose) rprintf(code, "%s -> %s\n", fname, sl); @@ -1622,7 +1625,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, set_file_attrs(fname, file, NULL, NULL, 0); if (itemizing) { itemize(fname, file, ndx, statret, &sx, - ITEM_LOCAL_CHANGE, 0, NULL); + ITEM_LOCAL_CHANGE|ITEM_REPORT_CHANGE, 0, NULL); } if (code != FNONE && verbose) rprintf(code, "%s\n", fname); @@ -1865,7 +1868,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (itemizing) { int iflags = ITEM_TRANSFER; if (always_checksum > 0) - iflags |= ITEM_REPORT_CHECKSUM; + iflags |= ITEM_REPORT_CHANGE; if (fnamecmp_type != FNAMECMP_FNAME) iflags |= ITEM_BASIS_TYPE_FOLLOWS; if (fnamecmp_type == FNAMECMP_FUZZY) @@ -2076,6 +2079,8 @@ void generate_files(int f_out, const char *local_name) dir_tweaking = !(list_only || solo_file || dry_run); need_retouch_dir_times = preserve_times > 1; lull_mod = allowed_lull * 5; + symlink_timeset_failed_flags = ITEM_REPORT_TIME + | (protocol_version >= 30 ? ITEM_REPORT_TIMEFAIL : 0 ); if (verbose > 2) rprintf(FINFO, "generator starting pid=%ld\n", (long)getpid()); @@ -632,15 +632,21 @@ static void log_formatted(enum logcode code, const char *format, const char *op, ? iflags & ITEM_XNAME_FOLLOWS ? 'h' : 'c' : !(iflags & ITEM_TRANSFER) ? '.' : !local_server && *op == 's' ? '<' : '>'; - c[1] = S_ISDIR(file->mode) ? 'd' - : IS_SPECIAL(file->mode) ? 'S' - : IS_DEVICE(file->mode) ? 'D' - : S_ISLNK(file->mode) ? 'L' : 'f'; - c[2] = !(iflags & ITEM_REPORT_CHECKSUM) ? '.' : 'c'; - c[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's'; - c[4] = !(iflags & ITEM_REPORT_TIME) ? '.' - : !preserve_times || (!receiver_symlink_times && S_ISLNK(file->mode)) - ? 'T' : 't'; + if (S_ISLNK(file->mode)) { + c[1] = 'L'; + c[3] = '.'; + c[4] = !(iflags & ITEM_REPORT_TIME) ? '.' + : !preserve_times || !receiver_symlink_times + || (iflags & ITEM_REPORT_TIMEFAIL) ? 'T' : 't'; + } else { + c[1] = S_ISDIR(file->mode) ? 'd' + : IS_SPECIAL(file->mode) ? 'S' + : IS_DEVICE(file->mode) ? 'D' : 'f'; + c[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's'; + c[4] = !(iflags & ITEM_REPORT_TIME) ? '.' + : !preserve_times ? 'T' : 't'; + } + c[2] = !(iflags & ITEM_REPORT_CHANGE) ? '.' : 'c'; c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p'; c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o'; c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g'; @@ -166,8 +166,9 @@ /* For use by the itemize_changes code */ #define ITEM_REPORT_ATIME (1<<0) -#define ITEM_REPORT_CHECKSUM (1<<1) -#define ITEM_REPORT_SIZE (1<<2) +#define ITEM_REPORT_CHANGE (1<<1) +#define ITEM_REPORT_SIZE (1<<2) /* regular files only */ +#define ITEM_REPORT_TIMEFAIL (1<<2) /* symlinks only */ #define ITEM_REPORT_TIME (1<<3) #define ITEM_REPORT_PERMS (1<<4) #define ITEM_REPORT_OWNER (1<<5) @@ -1674,8 +1674,9 @@ a "?" (this can happen when talking to an older rsync). The attribute that is associated with each letter is as follows: quote(itemization( - it() A bf(c) means the checksum of the file is different and will be - updated by the file transfer (requires bf(--checksum)). + it() A bf(c) means either that a regular file has a different checksum + (requires bf(--checksum)) or that a symlink, device, or special file has + a changed value. it() A bf(s) means the size of the file is different and will be updated by the file transfer. it() A bf(t) means the modification time is different and is being updated @@ -1683,6 +1684,8 @@ quote(itemization( means that the modification time will be set to the transfer time, which happens when a file/symlink/device is updated without bf(--times) and when a symlink is changed and the receiver can't set its time. + (Note: when using an rsync 3.0.0 client, you might see the bf(s) flag combined + with bf(t) instead of the proper bf(T) flag for this time-setting failure.) it() A bf(p) means the permissions are different and are being updated to the sender's value (requires bf(--perms)). it() An bf(o) means the owner is different and is being updated to the diff --git a/testsuite/devices.test b/testsuite/devices.test index 6fb1127c..a6bfc9ee 100644 --- a/testsuite/devices.test +++ b/testsuite/devices.test @@ -78,14 +78,14 @@ ln "$fromdir/block3" "$fromdir/block2.5" || echo "Skipping hard-linked device te mkfifo "$fromdir/fifo" || mknod "$fromdir/fifo" p || test_skipped "Can't run mkfifo" touch -r "$fromdir/block" "$fromdir/block2" -$RSYNC -ai "$fromdir/block" "$todir/block2" \ +$RSYNC -ait "$fromdir/block" "$todir/block2" \ | tee "$outfile" cat <<EOT >"$chkfile" cD$all_plus block EOT diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed" -$RSYNC -ai "$fromdir/block2" "$todir/block" \ +$RSYNC -ait "$fromdir/block2" "$todir/block" \ | tee "$outfile" cat <<EOT >"$chkfile" cD$all_plus block2 @@ -97,7 +97,7 @@ sleep 1 $RSYNC -Di "$fromdir/block3" "$todir/block" \ | tee "$outfile" cat <<EOT >"$chkfile" -cD..T.$dots block3 +cDc.T.$dots block3 EOT diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed" @@ -106,8 +106,8 @@ $RSYNC -aiHvv "$fromdir/" "$todir/" \ filter_outfile cat <<EOT >"$chkfile" .d..t.$dots ./ -cD..t.$dots block -cD$allspace block2 +cDc.t.$dots block +cDc...$dots block2 cD$all_plus block3 hD$all_plus block2.5 => block3 cD$all_plus char diff --git a/testsuite/itemize.test b/testsuite/itemize.test index 15fd6737..72780345 100644 --- a/testsuite/itemize.test +++ b/testsuite/itemize.test @@ -96,7 +96,7 @@ cat <<EOT >"$chkfile" .d..t.$dots foo/ .f..t.$dots foo/config1 >fcstp$dots foo/config2 -cL.$T.$dots foo/sym -> ../bar/baz/rsync +cLc$T.$dots foo/sym -> ../bar/baz/rsync EOT diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed" @@ -157,8 +157,8 @@ $RSYNC -ivvplrtH --copy-dest=../to "$fromdir/" "$to2dir/" \ | tee "$outfile" filter_outfile case `tail -1 "$outfile"` in -cL..t*) - sym_dots="..t.$dots" +cLc.t*) + sym_dots="c.t.$dots" L_sym_dots="cL$sym_dots" is_uptodate='-> ../bar/baz/rsync' echo "cL$sym_dots foo/sym $is_uptodate" >"$chkfile.extra" |