--- /dev/null
+#! /bin/sh
+
+# This program is distributable under the terms of the GNU GPL (see
+# COPYING).
+
+# Test the --tweak, --no-tweak, and --no-tweak-hlinked options.
+
+. $srcdir/testsuite/rsync.fns
+
+# Replacement for [ a -ef b ] that doesn't follow symlinks.
+samefile() {
+ inum1=`ls -di "$1" | sed 's/ .*$//'`
+ inum2=`ls -di "$2" | sed 's/ .*$//'`
+ [ "$inum1" = "$inum2" ]
+}
+
+chkfile="$scratchdir/rsync.chk"
+outfile="$scratchdir/rsync.out"
+
+makepath "$fromdir"
+
+# usage: testit OPTION FTYPE ATTR
+testit() {
+ option="$1"
+ ftype=$2
+ attr=$3
+ testid="$option $ftype $attr"
+ echo "Running test: ($testid)"
+
+ # Prepare the destination directory:
+ # file1: attr different from source
+ # file2: attr different from source, hard-linked with file2hl
+ # file3: attr same as source, hard-linked with file3hl
+ extraopt=''
+ rm -rf "$todir"
+ $RSYNC -a "$fromdir/" "$todir/"
+ case "$ftype,$attr" in
+ *,p)
+ chmod 700 "$todir/file1" "$todir/file2"
+ icode='...p.....'
+ ;;
+ L,t)
+ # Grab the new symlinks.
+ $RSYNC -a "$scratchdir/newlinks/" "$todir/"
+ icode='..t......'
+ ;;
+ *,t)
+ touch -d @1194208678 "$todir/file1" "$todir/file2"
+ # Make sure unchanged_attrs signals a difference in mtime.
+ extraopt='--checksum'
+ icode='..t......'
+ ;;
+ t_symlink)
+ esac
+ ln "$todir/file2" "$todir/file2hl"
+ ln "$todir/file3" "$todir/file3hl"
+
+ # Determine the expected results.
+ case "$option" in
+ ''|*--tweak)
+ # Tweak both files, tweaking through to file2hl.
+ a1='.'
+ a2='.'
+ changes_f2hl=1
+ ;;
+ --no-tweak-hlinked)
+ # Tweak file1 and recreate file2, breaking the link to file2hl.
+ a1='.'
+ a2='c'
+ changes_f2hl=''
+ ;;
+ --no-tweak)
+ # Recreate both file1 and file2, breaking the link to file2hl.
+ a1='c'
+ a2='c'
+ changes_f2hl=''
+ ;;
+ esac
+ if [ "$ftype" = L ]; then
+ ltgt=' -> foo'
+ else
+ ltgt=''
+ fi
+ cat >"$chkfile" <<EOCHK
+$a1$ftype$icode file1$ltgt
+$a2$ftype$icode file2$ltgt
+EOCHK
+
+ $RSYNC -a -i --omit-dir-times $option $extraopt "$fromdir/" "$todir/" | tee "$outfile"
+ diff $diffopt "$chkfile" "$outfile" || test_fail "itemize mismatch for test ($testid)"
+
+ if [ $changes_f2hl ]; then
+ samefile "$todir/file2" "$todir/file2hl" || test_fail "rsync should not have broken the file2 hard link"
+ if [ $attr = p ]; then
+ check_perms "$todir/file2hl" rw------- "test ($testid)"
+ fi
+ else
+ ! samefile "$todir/file2" "$todir/file2hl" || test_fail "rsync should have broken the file2 hard link"
+ if [ $attr = p ]; then
+ check_perms "$todir/file2hl" rwx------ "test ($testid)"
+ fi
+ fi
+
+ # Nothing should ever happen to file3.
+ samefile "$todir/file3" "$todir/file3hl" || test_fail "rsync should not have broken the file3 hard link"
+}
+
+# REGULAR FILES
+echo data >"$fromdir/file1"
+echo data >"$fromdir/file2"
+echo data >"$fromdir/file3"
+chmod 600 "$fromdir/file1" "$fromdir/file2" "$fromdir/file3"
+for o in '' '--no-tweak --tweak' '--no-tweak-hlinked' '--no-tweak'; do
+ for a in p t; do
+ testit "$o" f $a
+ done
+done
+
+# SYMLINKS
+rm -f "$fromdir/file1" "$fromdir/file2" "$fromdir/file3"
+if config_test CAN_HARDLINK_SYMLINK && config_test HAVE_LUTIMES; then
+ ln -s foo "$fromdir/file1"
+ ln -s foo "$fromdir/file2"
+ ln -s foo "$fromdir/file3"
+ # Since we don't have `touch -h', sleep once and make some newer
+ # symlinks that each test can copy into the destination directory.
+ sleep 1
+ makepath "$scratchdir/newlinks"
+ ln -s foo "$scratchdir/newlinks/file1"
+ ln -s foo "$scratchdir/newlinks/file2"
+ for o in '' '--no-tweak --tweak' '--no-tweak-hlinked' '--no-tweak'; do
+ # For symlinks, we test only times, not permissions.
+ testit "$o" L t
+ done
+fi
+
+# SPECIAL FILES
+rm -f "$fromdir/file1" "$fromdir/file2" "$fromdir/file3"
+if config_test CAN_HARDLINK_SPECIAL \
+ && mkfifo "$fromdir/file1" "$fromdir/file2" "$fromdir/file3"; then
+ chmod 600 "$fromdir/file1" "$fromdir/file2" "$fromdir/file3"
+ for o in '' '--no-tweak --tweak' '--no-tweak-hlinked' '--no-tweak'; do
+ for a in p t; do
+ testit "$o" S $a
+ done
+ done
+fi
+
+# The script would have aborted on error, so getting here means we've won.
+exit 0