aboutsummaryrefslogtreecommitdiffstats
path: root/generator.c
diff options
context:
space:
mode:
authorWayne Davison <wayned@samba.org>2013-01-19 09:52:56 -0800
committerWayne Davison <wayned@samba.org>2013-01-19 10:24:46 -0800
commitc03bb3d181b300a30a45e043d5aa075af5e8e3f8 (patch)
tree72de7b4c36cfa82dc4e575bd961968e6f8f8db1d /generator.c
parentcee326436c5f2b41c2f10e4e1176cca0a786a368 (diff)
downloadandroid_external_rsync-c03bb3d181b300a30a45e043d5aa075af5e8e3f8.tar.gz
android_external_rsync-c03bb3d181b300a30a45e043d5aa075af5e8e3f8.tar.bz2
android_external_rsync-c03bb3d181b300a30a45e043d5aa075af5e8e3f8.zip
Further improve non-empty-destination --link-dest behavior:
- Avoid relinking a file that is already linked correctly. - Avoid trashing the stat buffer of an existing file in try_dests_reg().
Diffstat (limited to 'generator.c')
-rw-r--r--generator.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/generator.c b/generator.c
index e7bb90a4..314122c3 100644
--- a/generator.c
+++ b/generator.c
@@ -852,6 +852,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
char *cmpbuf, stat_x *sxp, int find_exact_for_existing,
int itemizing, enum logcode code)
{
+ STRUCT_STAT real_st = sxp->st;
int best_match = -1;
int match_level = 0;
int j = 0;
@@ -893,8 +894,12 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
if (match_level == 3 && !copy_dest) {
if (find_exact_for_existing) {
- if (do_unlink(fname) < 0 && errno != ENOENT)
+ if (link_dest && real_st.st_dev == sxp->st.st_dev && real_st.st_ino == sxp->st.st_ino)
return -1;
+ if (do_unlink(fname) < 0 && errno != ENOENT) {
+ sxp->st = real_st;
+ return -1;
+ }
}
#ifdef SUPPORT_HARD_LINKS
if (link_dest) {
@@ -918,15 +923,20 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
return -2;
}
- if (find_exact_for_existing)
+ if (find_exact_for_existing) {
+ sxp->st = real_st;
return -1;
+ }
if (match_level >= 2) {
#ifdef SUPPORT_HARD_LINKS
try_a_copy: /* Copy the file locally. */
#endif
- if (!dry_run && copy_altdest_file(cmpbuf, fname, file) < 0)
+ if (!dry_run && copy_altdest_file(cmpbuf, fname, file) < 0) {
+ if (find_exact_for_existing) /* Can get here via hard-link failure */
+ sxp->st = real_st;
return -1;
+ }
if (itemizing)
itemize(cmpbuf, file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL);
if (maybe_ATTRS_REPORT