samba-bugs at samba.org
2016-Jul-25 22:52 UTC
[Bug 12036] New: Multiple --link-dest, --copy-dest, or --compare-dest flags produce incorrect behavior
https://bugzilla.samba.org/show_bug.cgi?id=12036
Bug ID: 12036
Summary: Multiple --link-dest, --copy-dest, or --compare-dest
flags produce incorrect behavior
Product: rsync
Version: 3.1.2
Hardware: All
OS: Linux
Status: NEW
Severity: normal
Priority: P5
Component: core
Assignee: wayned at samba.org
Reporter: ckuehl at ocf.berkeley.edu
QA Contact: rsync-qa at samba.org
Created attachment 12288
--> https://bugzilla.samba.org/attachment.cgi?id=12288&action=edit
reproduction
We have observed what seems like incorrect behavior when using a command like
this:
rsync -avc --link-dest=../copy_dest/good --link-dest=../copy_dest/bad src/
dest
with a directory stucture that looks like this:
.
├── copy_dest
│ ├── bad
│ │ └── file # contains different content from src, but same
attributes (e.g. mtime)
│ └── good
│ └── file # contains same content as src, but different
attributes (e.g. mtime)
└── src
└── file
Using the command above, we see that "bad/file" is hard-linked into
"dest",
even though it is different from "file" in src.
I've attached repro.sh which reliably reproduces this for me on the latest
version of rsync.
--
You are receiving this mail because:
You are the QA Contact for the bug.
samba-bugs at samba.org
2016-Jul-25 22:53 UTC
[Bug 12036] Multiple --link-dest, --copy-dest, or --compare-dest flags produce incorrect behavior
https://bugzilla.samba.org/show_bug.cgi?id=12036
--- Comment #1 from Chris Kuehl <ckuehl at ocf.berkeley.edu> ---
Looking through the code, this sticks out to me:
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;
do {
pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
if (link_stat(cmpbuf, &sxp->st, 0) < 0 ||
!S_ISREG(sxp->st.st_mode))
continue;
switch (match_level) {
case 0:
best_match = j;
match_level = 1;
/* FALL THROUGH */
case 1:
if (!unchanged_file(cmpbuf, file, &sxp->st))
continue;
best_match = j;
match_level = 2;
/* FALL THROUGH */
case 2:
if (!unchanged_attrs(cmpbuf, file, sxp)) {
free_stat_x(sxp);
continue;
}
best_match = j;
match_level = 3;
break;
}
break;
} while (basis_dir[++j] != NULL);
It looks to me like on the first iteration of the loop, we match all the way
through to "match_level = 2" with the file from
"copy_dest/good", which has the
same content. The mtime doesn't match, though, so we break there.
On the second iteration of the loop, "match_level" is still 2, and we
only
compare the attributes with the file from "copy_dest/bad" (never the
content).
We then break from the loop and link the wrong file into dest.
I've attached my attempt at a patch to correct this.
--
You are receiving this mail because:
You are the QA Contact for the bug.
samba-bugs at samba.org
2016-Jul-25 22:54 UTC
[Bug 12036] Multiple --link-dest, --copy-dest, or --compare-dest flags produce incorrect behavior
https://bugzilla.samba.org/show_bug.cgi?id=12036 --- Comment #2 from Chris Kuehl <ckuehl at ocf.berkeley.edu> --- Created attachment 12289 --> https://bugzilla.samba.org/attachment.cgi?id=12289&action=edit proposed patch -- You are receiving this mail because: You are the QA Contact for the bug.