Bug 11726 - rsync fails to copy directory containing ancestor symlink with --copy-links
rsync fails to copy directory containing ancestor symlink with --copy-links
Status: RESOLVED WONTFIX
Product: rsync
Classification: Unclassified
Component: core
3.1.2
All All
: P5 major
: ---
Assigned To: Wayne Davison
Rsync QA Contact
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2016-02-09 12:45 UTC by cyphar
Modified: 2016-02-11 16:06 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description cyphar 2016-02-09 12:45:03 UTC
If you have a directory created like so:

% mkdir -p from/dir/
% ln -s .. from/dir/loop
% rsync -a --copy-links from to
rsync: readlink_stat("/tmp/from/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop/dir/loop") failed: Too many levels of symbolic links (40)
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1178) [sender=3.1.2]

For a trivial case of infinitely recursive symlinks (in other words when you go through a symlink that takes you to an ancestor), rsync should just declare "that's as far as we need to go here".
Comment 1 cyphar 2016-02-09 13:01:22 UTC
I'm working on writing a patch for this (although this is my first time looking at the rsync codebase, so it might take a while). I'll ping this thread if I'm unable to write one.
Comment 2 cyphar 2016-02-09 18:13:52 UTC
It turns out that this issue also happens even when you don't use --copy-link (albeit a different error):

% rsync -a from to
cannot delete non-empty directory: from/dir/loop
could not make way for new symlink: from/dir/loop
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1178) [sender=3.1.3dev]
Comment 3 Wayne Davison 2016-02-10 04:45:01 UTC
Yes, if you tell rsync to copy the symlinks it does it. If you have one or more looping symlinks then you need to exclude them from the copy or not use --copy-links. As for the other error, you need to use --delete or --force to copy over a non-empty directory, as mentioned in the man page.
Comment 4 cyphar 2016-02-10 04:48:27 UTC
(In reply to Wayne Davison from comment #3)
> Yes, if you tell rsync to copy the symlinks it does it. If you have one or more looping symlinks then you need to exclude them from the copy or not use --copy-links.

That's just patently ridiculous. cp -r doesn't fail when you ask it to copy a directory that has symlink loops because "that's what you asked me to do". It literally just takes doing some fairly trivial checks before adding extra files to file_list (i.e. does the path we're adding resolve to an ancestor of a path we've already seen?).
Comment 5 Wayne Davison 2016-02-11 16:06:49 UTC
Keep in mind that "cp -r" doesn't dereference symlinks -- that takes their -L option (similar to rsync's --copy-links). If someone is copying a file tree and turning symlinks into real files/dirs, they should really know in advance what the symlinks are in order for the copy to be safe. Yes, we could stop looping with some additional checks. It might be worth it to at least not follow '.' and "..".