Recently I needed to recover a system with a damaged file system. After fsck there were some symlinks broken, pointing to nowhere (or better pointing to an empty file name, it showed up as "filename ->" in "ls -al"). Rsync fails to sync these symlinks, it just breaks with the following message: ERROR: buffer overflow in recv_file_entry Instead I wished either rsync correctly sync'ing these - or if empty symlinks cannot be created it should skip these and issue a warning but not exit with a buffer overflow. Manually deleting the broken symlinks from the source solved this (thus setting this bug to "minor"), but it was much work and I needed to recover rsync several times.
Created attachment 3872 [details] Don't send a symlink with an empty target name This patch should fix the issue by culling a link without a valid target from the file list. I can't create such a link, so I can't test this.
In general, rsync is not designed to cope with corrupt filesystems, but if it handles a file with an empty name, I suppose it should handle this too. I had a slightly different patch: https://mattmccutchen.net/rsync/rsync.git/commitdiff/7c18847f1608618134ffd166d97952177502d998 The place where the code is hooked is a matter of taste; I preferred to catch the invalid data as soon as possible to avoid any potential surprises. On the other hand, the error message definitely needs to be more clearly distinct from the "symlink has no referent" message that can happen with --copy-links. It may not be easy to test the code on a true empty symlink, but I at least saw the code path in action by temporarily hacking readlink_stat to substitute an empty string as the target if the symlink's name began with "z". :)
On second thought, maybe I should let --copy-unsafe-links work on a virtual filesystem where some symlinks appear to have an empty target string but can be followed. More generally, what if readlink returns an error but the symlink can be followed?
Thoughts on comment #3?
The thing I dislike about both my patch and yours is that it stops the receiving side from removing a symlink that shouldn't be there just because it has a 0-length value. Because of this, I moved the check to where it would only affect the sending of the file list to the receiver. I have checked in a fix to prevent a fatal error for a 0-length symlink. As for you comment #3, I am missing what you are driving at. If readlink() doesn't work on a symlink, how can something read the link to follow it?
Looks good. As for comment #3: on Linux, each filesystem implements independent "follow_link" and "readlink" functions, so when you follow a symlink, the filesystem can send you anywhere it likes independent of the return value of readlink. /proc/*/fd/* symlinks for pipes and sockets work this way. Thus, I was wondering how --copy-unsafe-links should handle a symlink that cannot be read (or returns a zero-length target) but can still be followed. Anyone who cares about this corner case can comment on the mailing list.