summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compat.c4
-rw-r--r--generator.c27
-rw-r--r--log.c24
-rw-r--r--rsync.h5
-rw-r--r--rsync.yo7
-rw-r--r--testsuite/devices.test10
-rw-r--r--testsuite/itemize.test6
7 files changed, 51 insertions, 32 deletions
diff --git a/compat.c b/compat.c
index bdceae54..ef220e2d 100644
--- a/compat.c
+++ b/compat.c
@@ -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());
diff --git a/log.c b/log.c
index f4808384..b5bd9667 100644
--- a/log.c
+++ b/log.c
@@ -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';
diff --git a/rsync.h b/rsync.h
index 5ac914fe..c1225563 100644
--- a/rsync.h
+++ b/rsync.h
@@ -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)
diff --git a/rsync.yo b/rsync.yo
index 34ec99d6..9c3e1d9d 100644
--- a/rsync.yo
+++ b/rsync.yo
@@ -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"