From: Wayne Davison Date: Sat, 7 Apr 2007 08:15:24 +0000 (+0000) Subject: Fixed the sending of new files with long xattrs. X-Git-Url: https://mattmccutchen.net/rsync/rsync-patches.git/commitdiff_plain/77a7a0f0b45a1983e0a1181002efab13f1ad3919 Fixed the sending of new files with long xattrs. --- diff --git a/xattrs.diff b/xattrs.diff index feda8b5..d17ea9a 100644 --- a/xattrs.diff +++ b/xattrs.diff @@ -277,7 +277,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! statx *sxp, int32 iflags, uchar fnamecmp_type, const char *xname) { -@@ -562,16 +571,24 @@ void itemize(const char *fname, struct f +@@ -562,16 +571,29 @@ void itemize(const char *fname, struct f #ifdef SUPPORT_ACLS if (preserve_acls && !S_ISLNK(file->mode)) { if (!ACL_READY(*sxp)) @@ -287,6 +287,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! iflags |= ITEM_REPORT_ACL; } #endif +- } else +#ifdef SUPPORT_XATTRS + if (preserve_xattrs) { + if (!XATTR_READY(*sxp)) @@ -295,8 +296,13 @@ CAUTION: this patch has been recently reworked, and needs more testing! + iflags |= ITEM_REPORT_XATTR; + } +#endif - } else ++ } else { ++#ifdef SUPPORT_XATTRS ++ if (preserve_xattrs && xattr_diff(file, NULL, 1)) ++ iflags |= ITEM_REPORT_XATTR; ++#endif iflags |= ITEM_IS_NEW; ++ } iflags &= 0xffff; - if ((iflags & SIGNIFICANT_ITEM_FLAGS || verbose > 1 @@ -304,7 +310,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! || stdout_format_has_i > 1 || (xname && *xname)) && !read_batch) { if (protocol_version >= 29) { if (ndx >= 0) -@@ -581,6 +598,10 @@ void itemize(const char *fname, struct f +@@ -581,6 +603,10 @@ void itemize(const char *fname, struct f write_byte(sock_f_out, fnamecmp_type); if (iflags & ITEM_XNAME_FOLLOWS) write_vstring(sock_f_out, xname, strlen(xname)); @@ -315,7 +321,7 @@ 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); -@@ -855,14 +876,14 @@ static int try_dests_reg(struct file_str +@@ -855,14 +881,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)) { @@ -332,7 +338,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! 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 +@@ -879,9 +905,13 @@ static int try_dests_reg(struct file_str } return -1; } @@ -348,7 +354,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! if (maybe_ATTRS_REPORT && ((!itemizing && verbose && match_level == 2) || (verbose > 1 && match_level == 3))) { -@@ -1029,7 +1054,7 @@ static int try_dests_non(struct file_str +@@ -1029,7 +1059,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; @@ -357,7 +363,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! } if (verbose > 1 && maybe_ATTRS_REPORT) { rprintf(FCLIENT, "%s%s is uptodate\n", -@@ -1112,6 +1137,9 @@ static void recv_generator(char *fname, +@@ -1112,6 +1142,9 @@ static void recv_generator(char *fname, #ifdef SUPPORT_ACLS sx.acc_acl = sx.def_acl = NULL; #endif @@ -367,7 +373,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 +1252,7 @@ static void recv_generator(char *fname, +@@ -1224,7 +1257,7 @@ static void recv_generator(char *fname, goto cleanup; } } @@ -376,7 +382,7 @@ 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) -@@ -1278,9 +1306,9 @@ static void recv_generator(char *fname, +@@ -1278,9 +1311,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. */ @@ -387,7 +393,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) finish_hard_link(file, fname, &sx.st, itemizing, code, -1); -@@ -1317,7 +1345,7 @@ static void recv_generator(char *fname, +@@ -1317,7 +1350,7 @@ static void recv_generator(char *fname, rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed", full_fname(fname), sl); } else { @@ -396,7 +402,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! if (itemizing) { itemize(fname, file, ndx, statret, &sx, ITEM_LOCAL_CHANGE, 0, NULL); -@@ -1357,9 +1385,9 @@ static void recv_generator(char *fname, +@@ -1357,9 +1390,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. */ @@ -407,7 +413,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) finish_hard_link(file, fname, &sx.st, itemizing, code, -1); -@@ -1399,7 +1427,7 @@ static void recv_generator(char *fname, +@@ -1399,7 +1432,7 @@ static void recv_generator(char *fname, rsyserr(FERROR, errno, "mknod %s failed", full_fname(fname)); } else { @@ -416,7 +422,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! if (itemizing) { itemize(fname, file, ndx, statret, &sx, ITEM_LOCAL_CHANGE, 0, NULL); -@@ -1529,9 +1557,9 @@ static void recv_generator(char *fname, +@@ -1529,9 +1562,9 @@ static void recv_generator(char *fname, do_unlink(partialptr); handle_partial_dir(partialptr, PDIR_DELETE); } @@ -427,7 +433,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) finish_hard_link(file, fname, &sx.st, itemizing, code, -1); -@@ -1636,6 +1664,10 @@ static void recv_generator(char *fname, +@@ -1636,6 +1669,10 @@ static void recv_generator(char *fname, if (preserve_acls) free_acl(&real_sx); #endif @@ -438,7 +444,7 @@ CAUTION: this patch has been recently reworked, and needs more testing! } if (!do_xfers) { -@@ -1657,7 +1689,7 @@ static void recv_generator(char *fname, +@@ -1657,7 +1694,7 @@ static void recv_generator(char *fname, if (f_copy >= 0) { close(f_copy); @@ -447,7 +453,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 +1704,10 @@ static void recv_generator(char *fname, +@@ -1672,6 +1709,10 @@ static void recv_generator(char *fname, if (preserve_acls) free_acl(&sx); #endif @@ -1120,7 +1126,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,76 @@ +@@ -0,0 +1,90 @@ +#! /bin/sh + +# This program is distributable under the terms of the GNU GPL (see @@ -1136,6 +1142,19 @@ CAUTION: this patch has been recently reworked, and needs more testing! +*protocol=29*) test_skipped "xattr support requires protocol 30" ;; +esac + ++xset() { ++ xnam="$1" ++ xval="$2" ++ shift 2 ++ setfattr -n "$xnam" -v "$xval" "${@}" ++ #xattr -s "$xnam" "$xval" "${@}" ++} ++ ++xls() { ++ getfattr -d "${@}" ++ #xattr -l "${@}" ++} ++ +makepath "$fromdir/foo" +echo something >"$fromdir/file1" +echo else >"$fromdir/file2" @@ -1149,57 +1168,58 @@ CAUTION: this patch has been recently reworked, and needs more testing! + +cd "$fromdir" + -+setfattr -n user.short -v 'this is short' file1 2>/dev/null || test_skipped "Unable to set an xattr" -+setfattr -n user.long -v 'this is a long attribute that will be truncated in the initial data send' file1 -+setfattr -n user.good -v 'this is good' file1 -+setfattr -n user.nice -v 'this is nice' file1 ++xset user.short 'this is short' file1 2>/dev/null || test_skipped "Unable to set an xattr" ++xset user.long 'this is a long attribute that will be truncated in the initial data send' file1 ++xset user.good 'this is good' file1 ++xset user.nice 'this is nice' file1 + -+setfattr -n user.foo -v foo file2 -+setfattr -n user.bar -v bar file2 ++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 + -+setfattr -n user.foo -v 'new foo' foo/file3 -+setfattr -n user.bar -v 'new bar' foo/file3 -+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 ++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 + -+setfattr -n user.short -v 'old short' "$chkdir/file1" -+setfattr -n user.extra -v 'remove me' "$chkdir/file1" ++xset user.short 'old short' "$chkdir/file1" ++xset user.extra '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" ++xset user.foo 'old foo' "$chkdir/foo/file3" ++xset user.equal 'this long attribute should remain the same and not need to be transferred' "$chkdir/foo/file3" + -+getfattr -d $files >"$scratchdir/xattrs.txt" ++xls $files >"$scratchdir/xattrs.txt" + +# OK, let's try a simple xattr copy. +checkit "$RSYNC -avX . \"$chkdir/\"" "$fromdir" "$chkdir" + +cd "$chkdir" -+getfattr -d $files | diff $diffopt "$scratchdir/xattrs.txt" - ++xls $files | diff $diffopt "$scratchdir/xattrs.txt" - + +cd "$fromdir" + +checkit "$RSYNC -aiX --copy-dest=../chk . ../to" "$fromdir" "$todir" + +cd "$todir" -+getfattr -d $files | diff $diffopt "$scratchdir/xattrs.txt" - ++xls $files | diff $diffopt "$scratchdir/xattrs.txt" - + +cd "$fromdir" -+setfattr -n user.nice -v 'this is nice, but different' file1 ++xset user.nice 'this is nice, but different' file1 + -+getfattr -d $files >"$scratchdir/xattrs.txt" ++xls $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" - ++xls $files | diff $diffopt "$scratchdir/xattrs.txt" - + +# The script would have aborted on error, so getting here means we've won. +exit 0 --- old/xattrs.c +++ new/xattrs.c -@@ -0,0 +1,775 @@ +@@ -0,0 +1,771 @@ +/* + * Extended Attribute support for rsync. + * Written by Jay Fenlason, vaguely based on the ACLs patch. @@ -1319,39 +1339,33 @@ CAUTION: this patch has been recently reworked, and needs more testing! + list_len = -1; + errno = ERANGE; + } -+ if (list_len < 0) { -+ if (errno == ENOTSUP) -+ return 0; -+ if (errno == ERANGE) { -+ list_len = sys_llistxattr(fname, NULL, 0); -+ if (list_len < 0) { -+ rsyserr(FERROR, errno, -+ "get_xattr_names: llistxattr(\"%s\",0) failed", -+ fname); -+ return -1; -+ } -+ if (namebuf_len) -+ free(namebuf); -+ namebuf_len = list_len + 1024; -+ namebuf = new_array(char, namebuf_len); -+ if (!namebuf) -+ out_of_memory("get_xattr_names"); -+ list_len = sys_llistxattr(fname, namebuf, namebuf_len); -+ if (list_len < 0) { -+ rsyserr(FERROR, errno, -+ "get_xattr_names: llistxattr(\"%s\",%ld) failed", -+ fname, (long)namebuf_len); -+ return -1; -+ } -+ } else { ++ if (list_len >= 0) ++ return list_len; ++ if (errno == ENOTSUP) ++ return 0; ++ if (errno == ERANGE) { ++ list_len = sys_llistxattr(fname, NULL, 0); ++ if (list_len < 0) { + rsyserr(FERROR, errno, -+ "get_xattr_names: llistxattr(\"%s\",%ld) failed", -+ fname, (long)namebuf_len); ++ "get_xattr_names: llistxattr(\"%s\",0) failed", ++ fname); + return -1; + } ++ if (namebuf_len) ++ free(namebuf); ++ namebuf_len = list_len + 1024; ++ namebuf = new_array(char, namebuf_len); ++ if (!namebuf) ++ out_of_memory("get_xattr_names"); ++ list_len = sys_llistxattr(fname, namebuf, namebuf_len); ++ if (list_len >= 0) ++ return list_len; + } + -+ return list_len; ++ rsyserr(FERROR, errno, ++ "get_xattr_names: llistxattr(\"%s\",%ld) failed", ++ fname, (long)namebuf_len); ++ return -1; +} + +/* On entry, the *len_ptr parameter contains the size of the extra space we @@ -1404,7 +1418,9 @@ CAUTION: this patch has been recently reworked, and needs more testing! + ssize_t list_len, name_len; + size_t datum_len, name_offset; + char *name, *ptr; ++#ifdef HAVE_LINUX_XATTRS + int user_only = am_sender ? 0 : !am_root; ++#endif + + /* This puts the name list into the "namebuf" buffer. */ + if ((list_len = get_xattr_names(fname)) < 0) @@ -1570,12 +1586,12 @@ CAUTION: this patch has been recently reworked, and needs more testing! + int snd_cnt, rec_cnt; + int cmp, same, xattrs_equal = 1; + -+ if (!XATTR_READY(*sxp)) { -+ rec_rxa = NULL; -+ rec_cnt = 0; -+ } else { ++ if (sxp && XATTR_READY(*sxp)) { + rec_rxa = sxp->xattr->items; + rec_cnt = sxp->xattr->count; ++ } else { ++ rec_rxa = NULL; ++ rec_cnt = 0; + } + + if (F_XATTR(file) >= 0)