Commit b769ad6a authored by Wayne Davison's avatar Wayne Davison

Another xattr "internal abbrev" fix for an xattr object that is

shared by multiple files:  handle the case where one file has an
abbreviated item set correctly, but a following item does not.
Also extended testsuite/xattrs.test to verify that this works.
parent 6e59b977
......@@ -945,10 +945,6 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
return -1;
if (itemizing)
itemize(cmpbuf, file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL);
#ifdef SUPPORT_XATTRS
if (preserve_xattrs)
xattr_clear_locals(file);
#endif
if (maybe_ATTRS_REPORT
&& ((!itemizing && verbose && match_level == 2)
|| (verbose > 1 && match_level == 3))) {
......
......@@ -34,18 +34,19 @@ case "`xattr 2>&1`" in
;;
esac
makepath "$fromdir/foo"
makepath "$fromdir/foo/bar"
echo now >"$fromdir/file0"
echo something >"$fromdir/file1"
echo else >"$fromdir/file2"
echo deep >"$fromdir/foo/file3"
echo normal >"$fromdir/file4"
echo deeper >"$fromdir/foo/bar/file5"
makepath "$chkdir/foo"
echo wow >"$chkdir/file1"
cp -p "$fromdir/foo/file3" "$chkdir/foo"
files='foo file0 file1 file2 foo/file3 file4'
files='foo file0 file1 file2 foo/file3 file4 foo/bar/file5'
cd "$fromdir"
......@@ -61,10 +62,10 @@ xset user.foo foo file2
xset user.bar bar file2
xset user.long 'a long attribute for our new file that tests to ensure that this works' file2
xset user.foo 'new foo' foo/file3
xset user.bar 'new bar' foo/file3
xset user.long 'this is also a long attribute that will be truncated in the initial data send' foo/file3
xset user.equal 'this long attribute should remain the same and not need to be transferred' foo/file3
xset user.foo 'new foo' foo/file3 foo/bar/file5
xset user.bar 'new bar' foo/file3 foo/bar/file5
xset user.long 'this is also a long attribute that will be truncated in the initial data send' foo/file3 foo/bar/file5
xset user.equal 'this long attribute should remain the same and not need to be transferred' foo/file3 foo/bar/file5
xset user.short 'old short' "$chkdir/file1"
xset user.extra 'remove me' "$chkdir/file1"
......
......@@ -47,7 +47,6 @@ extern int checksum_seed;
#define XSTATE_ABBREV 0
#define XSTATE_DONE 1
#define XSTATE_TODO 2
#define XSTATE_LOCAL 3
#define USER_PREFIX "user."
#define UPRE_LEN ((int)sizeof USER_PREFIX - 1)
......@@ -472,9 +471,11 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
if (rxa->datum_len <= MAX_FULL_DATUM)
continue;
switch (rxa->datum[0]) {
case XSTATE_LOCAL:
/* Items set locally will get cached by receiver. */
rxa->datum[0] = XSTATE_DONE;
case XSTATE_ABBREV:
/* Items left abbreviated matched the sender's checksum, so
* the receiver will cache the local data for future use. */
if (am_generator)
rxa->datum[0] = XSTATE_DONE;
continue;
case XSTATE_TODO:
break;
......@@ -508,27 +509,6 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
write_byte(f_out, 0); /* end the list */
}
/* Any items set locally by the generator that the receiver doesn't
* get told about get changed back to XSTATE_ABBREV. */
void xattr_clear_locals(struct file_struct *file)
{
item_list *lst = rsync_xal_l.items;
rsync_xa *rxa;
int cnt;
if (F_XATTR(file) < 0)
return;
lst += F_XATTR(file);
cnt = lst->count;
for (rxa = lst->items; cnt--; rxa++) {
if (rxa->datum_len <= MAX_FULL_DATUM)
continue;
if (rxa->datum[0] == XSTATE_LOCAL)
rxa->datum[0] = XSTATE_ABBREV;
}
}
/* When called by the sender, read the request from the generator and mark
* any needed xattrs with a flag that lets us know they need to be sent to
* the receiver. When called by the receiver, reads the sent data and
......@@ -751,8 +731,6 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
sxp->st.st_mtime = (time_t)-1;
if (am_generator) { /* generator items stay abbreviated */
if (rxas[i].datum[0] == XSTATE_ABBREV)
rxas[i].datum[0] = XSTATE_LOCAL;
free(ptr);
continue;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment