Fixed some itemized logging failures:
authorWayne Davison <wayned@samba.org>
Tue, 11 Mar 2008 04:15:37 +0000 (21:15 -0700)
committerWayne Davison <wayned@samba.org>
Tue, 11 Mar 2008 04:39:01 +0000 (21:39 -0700)
- If a symlink/device/special-file changes its value without any
  attribute changes, the itemized event no longer gets dropped.
- We put a 'c' into the checksum/change field now to indicate when
  a symlink/device/special-file changes its value without changing
  its type.  This lets us properly interpret the --copy-links output
  to know which items are getting copied without changes and which
  are getting created with new content.
- Fixed the 'T' itemized output for a symlink when rsync tries to
  set the right time but fails due to lack of OS/disk support.

compat.c
generator.c
log.c
rsync.h
rsync.yo
testsuite/devices.test
testsuite/itemize.test

index bdceae5..ef220e2 100644 (file)
--- 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;
                        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))
        }
 
        if (need_unsorted_flist && (!am_sender || inc_recurse))
index 9e24f56..1b13d56 100644 (file)
@@ -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 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;
 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 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;
 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
                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);
                    !S_ISLNK(file->mode);
+#endif
 
                if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size)
                        iflags |= ITEM_REPORT_SIZE;
 
                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))
                  && (!(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)) {
                        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
                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);
                }
                        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,
                        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);
                        }
                        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,
                        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);
                        }
                        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)
        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)
                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;
        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());
 
        if (verbose > 2)
                rprintf(FINFO, "generator starting pid=%ld\n", (long)getpid());
diff --git a/log.c b/log.c
index f480838..b5bd966 100644 (file)
--- 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' ? '<' : '>';
                              ? 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';
                        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 5ac914f..c122556 100644 (file)
--- a/rsync.h
+++ b/rsync.h
 
 /* For use by the itemize_changes code */
 #define ITEM_REPORT_ATIME (1<<0)
 
 /* 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)
 #define ITEM_REPORT_TIME (1<<3)
 #define ITEM_REPORT_PERMS (1<<4)
 #define ITEM_REPORT_OWNER (1<<5)
index 34ec99d..9c3e1d9 100644 (file)
--- 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(
 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
   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.
   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
   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
index 6fb1127..a6bfc9e 100644 (file)
@@ -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"
 
 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"
 
     | 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
     | 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"
 $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"
 
 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 ./
 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
 cD$all_plus block3
 hD$all_plus block2.5 => block3
 cD$all_plus char
index 15fd673..7278034 100644 (file)
@@ -96,7 +96,7 @@ cat <<EOT >"$chkfile"
 .d..t.$dots foo/
 .f..t.$dots foo/config1
 >fcstp$dots foo/config2
 .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"
 
 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
     | 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"
     L_sym_dots="cL$sym_dots"
     is_uptodate='-> ../bar/baz/rsync'
     echo "cL$sym_dots foo/sym $is_uptodate" >"$chkfile.extra"