From: Wayne Davison Date: Sat, 31 Mar 2007 17:38:38 +0000 (+0000) Subject: More xattr improvments/fixes, including tests for proper functioning X-Git-Url: https://mattmccutchen.net/rsync/rsync-patches.git/commitdiff_plain/3fbc83e87a0cbf3e0172dd04d9cd5d38dc5a3d85 More xattr improvments/fixes, including tests for proper functioning of --copy-dest and --link-dest. --- diff --git a/xattrs.diff b/xattrs.diff index f4c4401..f816654 100644 --- a/xattrs.diff +++ b/xattrs.diff @@ -256,7 +256,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! extern int preserve_links; extern int preserve_devices; extern int preserve_specials; -@@ -532,6 +533,14 @@ int unchanged_attrs(const char *fname, s +@@ -532,11 +533,19 @@ int unchanged_attrs(const char *fname, s return 0; } #endif @@ -271,14 +271,26 @@ CAUTION: this patch has been recently reworked, and needs more testing! return 1; } -@@ -567,11 +576,19 @@ void itemize(const char *fname, struct f + +-void itemize(const char *fname, struct file_struct *file, int ndx, int statret, ++void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret, + statx *sxp, int32 iflags, uchar fnamecmp_type, + const char *xname) + { +@@ -562,16 +571,24 @@ void itemize(const char *fname, struct f + #ifdef SUPPORT_ACLS + if (preserve_acls && !S_ISLNK(file->mode)) { + if (!ACL_READY(*sxp)) +- get_acl(fname, sxp); ++ get_acl(fnamecmp, sxp); + if (set_acl(NULL, file, sxp) == 0) iflags |= ITEM_REPORT_ACL; } #endif +#ifdef SUPPORT_XATTRS + if (preserve_xattrs) { + if (!XATTR_READY(*sxp)) -+ get_xattr(fname, sxp); ++ get_xattr(fnamecmp, sxp); + if (xattr_diff(file, sxp, 1)) + iflags |= ITEM_REPORT_XATTR; + } @@ -303,16 +315,49 @@ CAUTION: this patch has been recently reworked, and needs more testing! } else if (ndx >= 0) { enum logcode code = logfile_format_has_i ? FINFO : FCLIENT; log_item(code, file, &stats, iflags, xname); -@@ -881,7 +902,7 @@ static int try_dests_reg(struct file_str +@@ -855,14 +876,14 @@ static int try_dests_reg(struct file_str + if (preserve_hard_links && F_IS_HLINKED(file)) + finish_hard_link(file, fname, &sxp->st, itemizing, code, j); + if (itemizing && (verbose > 1 || stdout_format_has_i > 1)) { +- itemize(fname, file, ndx, 1, sxp, ++ itemize(cmpbuf, file, ndx, 1, sxp, + ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, + 0, ""); + } + } else + #endif + if (itemizing) +- itemize(fname, file, ndx, 0, sxp, 0, 0, NULL); ++ itemize(cmpbuf, file, ndx, 0, sxp, 0, 0, NULL); + if (verbose > 1 && maybe_ATTRS_REPORT) + rprintf(FCLIENT, "%s is uptodate\n", fname); + return -2; +@@ -879,9 +900,13 @@ static int try_dests_reg(struct file_str + } + return -1; } ++ set_file_attrs(fname, file, NULL, cmpbuf, 0); if (itemizing) - itemize(fname, file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL); +- itemize(fname, file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL); - set_file_attrs(fname, file, NULL, 0); -+ set_file_attrs(fname, file, NULL, NULL, 0); ++ 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))) { -@@ -1112,6 +1133,9 @@ static void recv_generator(char *fname, +@@ -1029,7 +1054,7 @@ static int try_dests_non(struct file_str + : ITEM_LOCAL_CHANGE + + (match_level == 3 ? ITEM_XNAME_FOLLOWS : 0); + char *lp = match_level == 3 ? "" : NULL; +- itemize(fname, file, ndx, 0, sxp, chg + ITEM_MATCHED, 0, lp); ++ itemize(cmpbuf, file, ndx, 0, sxp, chg + ITEM_MATCHED, 0, lp); + } + if (verbose > 1 && maybe_ATTRS_REPORT) { + rprintf(FCLIENT, "%s%s is uptodate\n", +@@ -1112,6 +1137,9 @@ static void recv_generator(char *fname, #ifdef SUPPORT_ACLS sx.acc_acl = sx.def_acl = NULL; #endif @@ -322,7 +367,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! if (dry_run > 1) { if (fuzzy_dirlist) { flist_free(fuzzy_dirlist); -@@ -1224,7 +1248,7 @@ static void recv_generator(char *fname, +@@ -1224,7 +1252,7 @@ static void recv_generator(char *fname, goto cleanup; } } @@ -331,16 +376,18 @@ CAUTION: this patch has been recently reworked, and needs more testing! && verbose && code != FNONE && f_out != -1) rprintf(code, "%s/\n", fname); if (real_ret != 0 && one_file_system) -@@ -1280,7 +1304,7 @@ static void recv_generator(char *fname, +@@ -1278,9 +1306,9 @@ static void recv_generator(char *fname, + else if ((len = readlink(fname, lnk, MAXPATHLEN-1)) > 0 + && strncmp(lnk, sl, len) == 0 && sl[len] == '\0') { /* The link is pointing to the right place. */ ++ set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT); if (itemizing) itemize(fname, file, ndx, 0, &sx, 0, 0, NULL); - set_file_attrs(fname, file, &sx, maybe_ATTRS_REPORT); -+ set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT); #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) finish_hard_link(file, fname, &sx.st, itemizing, code, -1); -@@ -1317,7 +1341,7 @@ static void recv_generator(char *fname, +@@ -1317,7 +1345,7 @@ static void recv_generator(char *fname, rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed", full_fname(fname), sl); } else { @@ -349,16 +396,18 @@ CAUTION: this patch has been recently reworked, and needs more testing! if (itemizing) { itemize(fname, file, ndx, statret, &sx, ITEM_LOCAL_CHANGE, 0, NULL); -@@ -1359,7 +1383,7 @@ static void recv_generator(char *fname, +@@ -1357,9 +1385,9 @@ static void recv_generator(char *fname, + && BITS_EQUAL(sx.st.st_mode, file->mode, _S_IFMT) + && sx.st.st_rdev == rdev) { /* The device or special file is identical. */ ++ set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT); if (itemizing) itemize(fname, file, ndx, 0, &sx, 0, 0, NULL); - set_file_attrs(fname, file, &sx, maybe_ATTRS_REPORT); -+ set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT); #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) finish_hard_link(file, fname, &sx.st, itemizing, code, -1); -@@ -1399,7 +1423,7 @@ static void recv_generator(char *fname, +@@ -1399,7 +1427,7 @@ static void recv_generator(char *fname, rsyserr(FERROR, errno, "mknod %s failed", full_fname(fname)); } else { @@ -367,16 +416,18 @@ CAUTION: this patch has been recently reworked, and needs more testing! if (itemizing) { itemize(fname, file, ndx, statret, &sx, ITEM_LOCAL_CHANGE, 0, NULL); -@@ -1531,7 +1555,7 @@ static void recv_generator(char *fname, +@@ -1529,9 +1557,9 @@ static void recv_generator(char *fname, + do_unlink(partialptr); + handle_partial_dir(partialptr, PDIR_DELETE); } ++ set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT); if (itemizing) itemize(fnamecmp, file, ndx, statret, &sx, 0, 0, NULL); - set_file_attrs(fname, file, &sx, maybe_ATTRS_REPORT); -+ set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT); #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) finish_hard_link(file, fname, &sx.st, itemizing, code, -1); -@@ -1636,6 +1660,10 @@ static void recv_generator(char *fname, +@@ -1636,6 +1664,10 @@ static void recv_generator(char *fname, if (preserve_acls) free_acl(&real_sx); #endif @@ -387,7 +438,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! } if (!do_xfers) { -@@ -1657,7 +1685,7 @@ static void recv_generator(char *fname, +@@ -1657,7 +1689,7 @@ static void recv_generator(char *fname, if (f_copy >= 0) { close(f_copy); @@ -396,7 +447,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! if (verbose > 1) { rprintf(FINFO, "backed up %s to %s\n", fname, backupptr); -@@ -1672,6 +1700,10 @@ static void recv_generator(char *fname, +@@ -1672,6 +1704,10 @@ static void recv_generator(char *fname, if (preserve_acls) free_acl(&sx); #endif @@ -731,7 +782,15 @@ CAUTION: this patch has been recently reworked, and needs more testing! extern int do_xfers; extern int am_server; extern int do_progress; -@@ -366,8 +367,8 @@ int recv_files(int f_in, char *local_nam +@@ -37,6 +38,7 @@ extern int protocol_version; + extern int relative_paths; + extern int preserve_hard_links; + extern int preserve_perms; ++extern int preserve_xattrs; + extern int basis_dir_cnt; + extern int make_backups; + extern int cleanup_got_literal; +@@ -366,8 +368,8 @@ int recv_files(int f_in, char *local_nam cleanup_disable(); /* This call also sets cur_flist. */ @@ -742,7 +801,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! if (ndx == NDX_DONE) { if (inc_recurse && first_flist) { flist_free(first_flist); -@@ -397,8 +398,17 @@ int recv_files(int f_in, char *local_nam +@@ -397,8 +399,17 @@ int recv_files(int f_in, char *local_nam if (verbose > 2) rprintf(FINFO, "recv_files(%s)\n", fname); @@ -754,13 +813,13 @@ CAUTION: this patch has been recently reworked, and needs more testing! if (!(iflags & ITEM_TRANSFER)) { maybe_log_item(file, iflags, itemizing, xname); +#ifdef SUPPORT_XATTRS -+ if (iflags & ITEM_REPORT_XATTR && !dry_run) ++ if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run) + set_file_attrs(fname, file, NULL, fname, 0); +#endif continue; } if (phase == 2) { -@@ -655,15 +665,15 @@ int recv_files(int f_in, char *local_nam +@@ -655,15 +666,15 @@ int recv_files(int f_in, char *local_nam temp_copy_name = NULL; else temp_copy_name = partialptr; @@ -1050,7 +1109,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! if (verbose > 2) --- old/testsuite/xattrs.test +++ new/testsuite/xattrs.test -@@ -0,0 +1,56 @@ +@@ -0,0 +1,76 @@ +#! /bin/sh + +# This program is distributable under the terms of the GNU GPL (see @@ -1071,9 +1130,9 @@ CAUTION: this patch has been recently reworked, and needs more testing! +echo else >"$fromdir/file2" +echo last >"$fromdir/foo/file3" + -+makepath "$todir/foo" -+echo wow >"$todir/file1" -+cp -p "$fromdir/foo/file3" "$todir/foo" ++makepath "$chkdir/foo" ++echo wow >"$chkdir/file1" ++cp -p "$fromdir/foo/file3" "$chkdir/foo" + +files='foo file1 file2 foo/file3' + @@ -1092,16 +1151,36 @@ CAUTION: this patch has been recently reworked, and needs more testing! +setfattr -n user.long -v 'this is also a long attribute that will be truncated in the initial data send' foo/file3 +setfattr -n user.equal -v 'this long attribute should remain the same and not need to be transferred' foo/file3 + -+setfattr -n user.short -v 'old short' "$todir/file1" -+setfattr -n user.extra -v 'remove me' "$todir/file1" ++setfattr -n user.short -v 'old short' "$chkdir/file1" ++setfattr -n user.extra -v 'remove me' "$chkdir/file1" ++ ++setfattr -n user.foo -v 'old foo' "$chkdir/foo/file3" ++setfattr -n user.equal -v 'this long attribute should remain the same and not need to be transferred' "$chkdir/foo/file3" ++ ++getfattr -d $files >"$scratchdir/xattrs.txt" ++ ++# OK, let's try a simple xattr copy. ++checkit "$RSYNC -avX . \"$chkdir/\"" "$fromdir" "$chkdir" + -+setfattr -n user.foo -v 'old foo' "$todir/foo/file3" -+setfattr -n user.equal -v 'this long attribute should remain the same and not need to be transferred' "$todir/foo/file3" ++cd "$chkdir" ++getfattr -d $files | diff $diffopt "$scratchdir/xattrs.txt" - + -+$RSYNC -avX . "$todir/" ++cd "$fromdir" ++ ++checkit "$RSYNC -aiX --copy-dest=../chk . ../to" "$fromdir" "$todir" ++ ++cd "$todir" ++getfattr -d $files | diff $diffopt "$scratchdir/xattrs.txt" - ++ ++cd "$fromdir" ++setfattr -n user.nice -v 'this is nice, but different' file1 + +getfattr -d $files >"$scratchdir/xattrs.txt" + ++rm -rf "$todir" ++ ++checkit "$RSYNC -aiX --link-dest=../chk . ../to" "$chkdir" "$todir" ++ +cd "$todir" +getfattr -d $files | diff $diffopt "$scratchdir/xattrs.txt" - + @@ -1109,7 +1188,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! +exit 0 --- old/xattrs.c +++ new/xattrs.c -@@ -0,0 +1,713 @@ +@@ -0,0 +1,769 @@ +/* + * Extended Attribute support for rsync. + * Written by Jay Fenlason, vaguely based on the ACLs patch. @@ -1139,6 +1218,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! +extern int dry_run; +extern int am_root; +extern int am_sender; ++extern int am_generator; +extern int read_only; +extern int list_only; +extern int checksum_seed; @@ -1151,6 +1231,13 @@ CAUTION: this patch has been recently reworked, and needs more testing! +#define HAS_PREFIX(str, prfx) (*(str) == *(prfx) \ + && strncmp(str, prfx, sizeof (prfx) - 1) == 0) + ++#define XATTR_ABBREV(x) ((size_t)((x).name - (x).datum) < (x).datum_len) ++ ++#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) +#define SYSTEM_PREFIX "system." @@ -1259,13 +1346,14 @@ CAUTION: this patch has been recently reworked, and needs more testing! +/* On entry, the *len_ptr parameter contains the size of the extra space we + * should allocate when we create a buffer for the data. On exit, it contains + * the length of the datum. */ -+static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr) ++static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr, ++ int no_missing_error) +{ + size_t datum_len = sys_lgetxattr(fname, name, NULL, 0); + char *ptr; + + if (datum_len == (size_t)-1) { -+ if (errno == ENOTSUP) ++ if (errno == ENOTSUP || no_missing_error) + return NULL; + rsyserr(FERROR, errno, + "get_xattr_data: lgetxattr(\"%s\",\"%s\",0) failed", @@ -1326,7 +1414,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! +#endif + + datum_len = name_len; /* Pass extra size to get_xattr_data() */ -+ if (!(ptr = get_xattr_data(fname, name, &datum_len))) ++ if (!(ptr = get_xattr_data(fname, name, &datum_len, 0))) + return -1; + + if (datum_len > MAX_FULL_DATUM) { @@ -1338,7 +1426,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! + + if (!(ptr = new_array(char, name_offset + name_len))) + out_of_memory("rsync_xal_get"); -+ *ptr = 0; ++ *ptr = XSTATE_ABBREV; + sum_end(ptr + 1); + } else + name_offset = datum_len; @@ -1504,8 +1592,8 @@ CAUTION: this patch has been recently reworked, and needs more testing! + && memcmp(snd_rxa->datum + 1, rec_rxa->datum + 1, + MAX_DIGEST_LEN) == 0; + /* Flag unrequested items that we need. */ -+ if (!same && find_all && snd_rxa->datum[0] == 0) -+ snd_rxa->datum[0] = 1; ++ if (!same && find_all && snd_rxa->datum[0] == XSTATE_ABBREV) ++ snd_rxa->datum[0] = XSTATE_TODO; + } else { + same = cmp == 0 && snd_rxa->datum_len == rec_rxa->datum_len + && memcmp(snd_rxa->datum, rec_rxa->datum, @@ -1545,12 +1633,21 @@ CAUTION: this patch has been recently reworked, and needs more testing! + lst += F_XATTR(file); + cnt = lst->count; + for (rxa = lst->items, j = 0; j < cnt; rxa++, j++) { -+ if (rxa->datum_len <= MAX_FULL_DATUM -+ || rxa->datum[0] != 1) ++ 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; ++ continue; ++ case XSTATE_TODO: ++ break; ++ default: ++ continue; ++ } + + /* Flag that we handled this abbreviated item. */ -+ rxa->datum[0] = 2; ++ rxa->datum[0] = XSTATE_DONE; + + write_abbrevint(f_out, j - prior_req); + prior_req = j; @@ -1560,7 +1657,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! + char *ptr; + + /* Re-read the long datum. */ -+ if (!(ptr = get_xattr_data(fname, rxa->name, &len))) ++ if (!(ptr = get_xattr_data(fname, rxa->name, &len, 0))) + continue; + + write_abbrevint(f_out, len); /* length might have changed! */ @@ -1572,6 +1669,27 @@ CAUTION: this patch has been recently reworked, and needs more testing! + 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 @@ -1583,10 +1701,9 @@ CAUTION: this patch has been recently reworked, and needs more testing! + rsync_xa *rxa; + int rel_pos, cnt; + -+ if (F_XATTR(file) >= 0) -+ lst += F_XATTR(file); -+ else ++ if (F_XATTR(file) < 0) + exit_cleanup(RERR_STREAMIO); /* XXX */ ++ lst += F_XATTR(file); + + cnt = lst->count; + rxa = lst->items; @@ -1595,11 +1712,11 @@ CAUTION: this patch has been recently reworked, and needs more testing! + rxa += rel_pos; + cnt -= rel_pos; + if (cnt < 0 || rxa->datum_len <= MAX_FULL_DATUM -+ || rxa->datum[0] != 0) ++ || rxa->datum[0] != XSTATE_ABBREV) + exit_cleanup(RERR_STREAMIO); /* XXX */ + + if (am_sender) { -+ rxa->datum[0] = 1; ++ rxa->datum[0] = XSTATE_TODO; + continue; + } + @@ -1667,7 +1784,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! + if (dget_len == datum_len) + read_buf(f, ptr, dget_len); + else { -+ *ptr = 0; ++ *ptr = XSTATE_ABBREV; + read_buf(f, ptr + 1, MAX_DIGEST_LEN); + } +#ifdef HAVE_LINUX_XATTRS @@ -1725,50 +1842,69 @@ CAUTION: this patch has been recently reworked, and needs more testing! +{ + rsync_xa *rxas = xalp->items; + ssize_t list_len; -+ size_t i; -+ char *name; -+ int name_len, status, ret = 0; ++ size_t i, len; ++ char *name, *ptr, sum[MAX_DIGEST_LEN]; ++ int name_len, ret = 0; + + /* This puts the current name list into the "namebuf" buffer. */ + if ((list_len = get_xattr_names(fname)) < 0) + return -1; + + for (i = 0; i < xalp->count; i++) { -+ if ((size_t)(rxas[i].name - rxas[i].datum) < rxas[i].datum_len) { -+ size_t len = rxas[i].name_len; -+ char *ptr; -+ -+ /* See if fnamecmp version is identical. */ -+ if ((ptr = get_xattr_data(fnamecmp, rxas[i].name, &len)) != NULL -+ && len == rxas[i].datum_len) { -+ char sum[MAX_DIGEST_LEN]; -+ sum_init(checksum_seed); -+ sum_update(ptr, len); -+ sum_end(sum); -+ if (memcmp(sum, rxas[i].datum + 1, MAX_DIGEST_LEN) == 0) { -+ char *name = ptr + len; -+ memcpy(name, rxas[i].name, rxas[i].name_len); -+ rxas[i].name = name; -+ free(rxas[i].datum); -+ rxas[i].datum = ptr; -+ } else -+ len = 0; -+ } else -+ len = 0; -+ if (!len) { ++ name = rxas[i].name; ++ ++ if (XATTR_ABBREV(rxas[i])) { ++ /* See if the fnamecmp version is identical. */ ++ len = name_len = rxas[i].name_len; ++ if ((ptr = get_xattr_data(fnamecmp, name, &len, 1)) == NULL) { ++ still_abbrev: ++ if (am_generator) ++ continue; + rprintf(FERROR, "Missing abbreviated xattr value, %s, for %s\n", + rxas[i].name, full_fname(fname)); + ret = -1; + continue; + } -+ if (fname == fnamecmp) /* value is already set */ ++ if (len != rxas[i].datum_len) { ++ free(ptr); ++ goto still_abbrev; ++ } ++ ++ sum_init(checksum_seed); ++ sum_update(ptr, len); ++ sum_end(sum); ++ if (memcmp(sum, rxas[i].datum + 1, MAX_DIGEST_LEN) != 0) { ++ free(ptr); ++ goto still_abbrev; ++ } ++ ++ if (fname != fnamecmp /* value is already set */ ++ && sys_lsetxattr(fname, name, ptr, len) < 0) { ++ rsyserr(FERROR, errno, ++ "rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed", ++ fname, name); ++ ret = -1; ++ } ++ ++ if (am_generator) { /* generator items stay abbreviated */ ++ if (rxas[i].datum[0] == XSTATE_ABBREV) ++ rxas[i].datum[0] = XSTATE_LOCAL; ++ free(ptr); + continue; ++ } ++ ++ memcpy(ptr + len, name, name_len); ++ free(rxas[i].datum); ++ ++ rxas[i].name = name = ptr + len; ++ rxas[i].datum = ptr; ++ continue; + } -+ status = sys_lsetxattr(fname, rxas[i].name, rxas[i].datum, rxas[i].datum_len); -+ if (status < 0) { ++ ++ if (sys_lsetxattr(fname, name, rxas[i].datum, rxas[i].datum_len) < 0) { + rsyserr(FERROR, errno, + "rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed", -+ fname, rxas[i].name); ++ fname, name); + ret = -1; + } + } @@ -1791,8 +1927,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! + break; + } + if (i == xalp->count) { -+ int status = sys_lremovexattr(fname, name); -+ if (status < 0) { ++ if (sys_lremovexattr(fname, name) < 0) { + rsyserr(FERROR, errno, + "rsync_xal_clear: lremovexattr(\"%s\",\"%s\") failed", + fname, name);