Bug 2395 - problems copying from a dir that includes a symlink in the path
Summary: problems copying from a dir that includes a symlink in the path
Status: CLOSED WORKSFORME
Alias: None
Product: rsync
Classification: Unclassified
Component: core (show other bugs)
Version: 2.6.4
Hardware: All All
: P3 trivial (vote)
Target Milestone: ---
Assignee: Wayne Davison
QA Contact: Rsync QA Contact
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-02-27 15:25 UTC by Dave Yost
Modified: 2005-04-01 11:25 UTC (History)
1 user (show)

See Also:


Attachments
same test script but with bug fixes (2.17 KB, text/plain)
2005-02-27 23:59 UTC, Dave Yost
no flags Details
corrected (2.20 KB, text/plain)
2005-02-28 00:02 UTC, Dave Yost
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Dave Yost 2005-02-27 15:25:07 UTC
I've put together a nightly backup script using rsync, which you can have if you
want.  It basically rsyncs a dir to a dir on the remote machine, where the
remote dir's name is an ISO 8601 timestamp.

Today I tried to enhance this system to get a file from the repository, and
since I use symlinks in the pathnames in the repository, I hit what I consider
to be bugs in rsync.  The attached script demonstrates what I mean.

Basically, if you try to
  rsync a/b .
were a is a symlink, it doesn't work as expected given various combinations of
-R, -l, and -L options.

#!/bin/zsh

# rsync problems with copying from a dir that includes a symlink in the path
# 2005-02-27 Dave@Yost.com

setupSource() {
	rm -rf source/dir source/symlink
	mkdir -p source/dir
	ln -s dir source/s
	ln -s referent source/dir/s
	echo nothing > source/dir/file
}

setupCorrectOutput() {
	rm -rf correct-output
	mkdir  correct-output
	cd     correct-output
	for x in ${opts[@]}
	do
		mkdir dest${x}
		case $x in
		*R*) mkdir -p dest${x}/s
		     case $x in
		     *L*) cp -p ../source/dir/file dest${x}/s/file
		          cp -p ../source/dir/file dest${x}/s/symlink
		          ;;
		     *l*) cp -p ../source/dir/file dest${x}/s/file
		          ln -s referent           dest${x}/s/symlink
		          ;;
		     *)   cp -p ../source/dir/file dest${x}/s/file
		          ;;
		     esac
		     ;;
		*)   case $x in
		     *L*) cp -p ../source/dir/file dest${x}/file
		          cp -p ../source/dir/file dest${x}/symlink
		          ;;
		     *l*)  cp -p ../source/dir/file dest${x}/file
		          ln -s referent           dest${x}/symlink
		          ;;
		     *)   cp -p ../source/dir/file dest${x}/file
		          ;;
		     esac
		     ;;
		esac
	done
	cd ..
}

test() {
	opts=$1
	file=$2
	dest=output/dest${opts}
	rm -rf   $dest
	mkdir -p $dest
	cd source
	echo '###' rsync $opts s/$file ../$dest
	           rsync $opts s/$file ../$dest
	cd ..
	ls -ld $(find $dest) \
	| sed 's,...........................................,  ,'
}

opts=(
	-r
	-rl
	-rLL  # hack for for case-insensitive file systems
	-rR
	-rRl
	-rRLL
)

testGroup() {
	for x in ${opts[@]}
		test $x $1
}

setupSource
setupCorrectOutput
rm -rf output
mkdir  output

testGroup file
testGroup symlink

dodiff() {
	find correct-output -type $1 | sed 's,correct-output/,,' | sed "s,$, $1," >> $c
	find output         -type $1 | sed 's,output/,,'         | sed "s,$, $1," >> $a
}

c=/tmp/dyRsyncBug$$-$1-correct
a=/tmp/dyRsyncBug$$-$1
dodiff f
dodiff l

sort $c > $c-sorted
sort $a > $a-sorted

echo '###' This diff should produce only lines starting with '='
echo '###' diff $1 correct vs actual
/usr/bin/diff       --old-line-format='< %l
'             --unchanged-line-format='= %l
'                   --new-line-format='> %l
'             $c-sorted $a-sorted
Comment 1 Wayne Davison 2005-02-27 15:57:45 UTC
Use --no-implied-dirs to have the path components of an -R source treated as
generic dirs.
Comment 2 Dave Yost 2005-02-27 21:00:21 UTC
(In reply to comment #1)
Using --no-implied-dirs fixes only one of the six failures exhibited by the test
script .
Comment 3 Wayne Davison 2005-02-27 22:47:38 UTC
Everything else is caused by bugs in your test script. (e.g. overwriting the
opts array with the opts scalar, removing the destination dir that holds the
copied file when copying the symlink, creating a symlink named "s" in the source
dir instead of "symlink", creating a symlink to a non-existant file named
"referent" instead of the actual "file", etc.)
Comment 4 Dave Yost 2005-02-27 23:59:58 UTC
Created attachment 992 [details]
same test script but with bug fixes

(In reply to comment #3)
Terribly sorry to bother you with my stupid bugs.  I believe I've now fixed
them all, and there is still a problem with -L.  This fails:
  rsync -L --no-implied-dirs source/s/symlink .
In other words, --no-implied-dirs appears to fix the -l case but not the -L
case.
Comment 5 Dave Yost 2005-02-28 00:02:31 UTC
Created attachment 993 [details]
corrected
Comment 6 Wayne Davison 2005-02-28 11:15:10 UTC
Your script is creating a symlink to a non-existant file, which can't be copied
with -L.  If you change every instance of "referent" to "file", the script will
work fine.
Comment 7 Dave Yost 2005-02-28 13:01:49 UTC
(In reply to comment #6)
I will now go crawl into a hole.