From: Wayne Davison Date: Sat, 8 Mar 2008 00:16:29 +0000 (-0800) Subject: Fixed the interaction of --fake-super with --link-dest & --xattrs. X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/commitdiff_plain/d724dd186ed6a2d66fa13a9357ce91e459d39e8c Fixed the interaction of --fake-super with --link-dest & --xattrs. Fixed the munging of non-user namespace xattrs w/--fake-super. Fixed the sorting of received xattrs when name-munging occurs. Added xattr tests to verify that these things stay fixed. --- diff --git a/testsuite/xattrs.test b/testsuite/xattrs.test index 97c5f8d3..66c3e752 100644 --- a/testsuite/xattrs.test +++ b/testsuite/xattrs.test @@ -20,6 +20,7 @@ case "`xattr 2>&1`" in xls() { xattr -l "${@}" } + RUSR='rsync' ;; *) xset() { @@ -31,6 +32,7 @@ case "`xattr 2>&1`" in xls() { getfattr -d "${@}" } + RUSR='user.rsync' ;; esac @@ -65,13 +67,15 @@ xset user.long 'a long attribute for our new file that tests to ensure that this 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 $RUSR.equal 'this long attribute should remain the same and not need to be transferred' foo/file3 foo/bar/file5 +xset $RUSR.equal 'this short' foo/file3 foo/bar/file5 xset user.short 'old short' "$chkdir/file1" xset user.extra 'remove me' "$chkdir/file1" 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" +xset $RUSR.equal 'this long attribute should remain the same and not need to be transferred' "$chkdir/foo/file3" +xset $RUSR.equal 'this short' "$chkdir/foo/file3" xls $files >"$scratchdir/xattrs.txt" @@ -95,10 +99,17 @@ xls $files >"$scratchdir/xattrs.txt" rm -rf "$todir" -checkit "$RSYNC -aiX --link-dest=../chk . ../to" "$chkdir" "$todir" +checkit "$RSYNC -aiX --fake-super --link-dest=../chk . ../to" "$chkdir" "$todir" cd "$todir" xls $files | diff $diffopt "$scratchdir/xattrs.txt" - +sed -n -e '/\.\/file1$/d' -e '/^[^ ]* *[^ ]* *[^ ]* *1 /p' "$scratchdir/ls-to" >"$scratchdir/ls-diff" +if [ -s "$scratchdir/ls-diff" ]; then + echo "Missing hard links on:" + cat "$scratchdir/ls-diff" + exit 1 +fi + # The script would have aborted on error, so getting here means we've won. exit 0 diff --git a/xattrs.c b/xattrs.c index a436572b..53363bde 100644 --- a/xattrs.c +++ b/xattrs.c @@ -62,9 +62,12 @@ extern int checksum_seed; #endif #define RPRE_LEN ((int)sizeof RSYNC_PREFIX - 1) -#define XSTAT_ATTR RSYNC_PREFIX "%stat" -#define XACC_ACL_ATTR RSYNC_PREFIX "%aacl" -#define XDEF_ACL_ATTR RSYNC_PREFIX "%dacl" +#define XSTAT_SUFFIX "stat" +#define XSTAT_ATTR RSYNC_PREFIX "%" XSTAT_SUFFIX +#define XACC_ACL_SUFFIX "aacl" +#define XACC_ACL_ATTR RSYNC_PREFIX "%" XACC_ACL_SUFFIX +#define XDEF_ACL_SUFFIX "dacl" +#define XDEF_ACL_ATTR RSYNC_PREFIX "%" XDEF_ACL_SUFFIX typedef struct { char *datum, *name; @@ -231,7 +234,10 @@ static int rsync_xal_get(const char *fname, item_list *xalp) if (name_len > RPRE_LEN && name[RPRE_LEN] == '%' && HAS_PREFIX(name, RSYNC_PREFIX)) { if ((am_sender && preserve_xattrs < 2) - || (am_root < 0 && strcmp(name, XSTAT_ATTR) == 0)) + || (am_root < 0 + && (strcmp(name+RPRE_LEN+1, XSTAT_SUFFIX) == 0 + || strcmp(name+RPRE_LEN+1, XACC_ACL_SUFFIX) == 0 + || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0))) continue; } @@ -253,14 +259,6 @@ static int rsync_xal_get(const char *fname, item_list *xalp) } else name_offset = datum_len; -#ifdef HAVE_LINUX_XATTRS - if (am_root < 0 && name_len > RPRE_LEN && name[RPRE_LEN] != '%' - && HAS_PREFIX(name, RSYNC_PREFIX)) { - name += RPRE_LEN; - name_len -= RPRE_LEN; - } -#endif - rxa = EXPAND_ITEM_LIST(xalp, rsync_xa, RSYNC_XAL_INITIAL); rxa->name = ptr + name_offset; memcpy(rxa->name, name, name_len); @@ -352,25 +350,33 @@ int send_xattr(stat_x *sxp, int f) int count = sxp->xattr->count; write_varint(f, count); for (rxa = sxp->xattr->items; count--; rxa++) { + int name_len = rxa->name_len; + const char *name = rxa->name; + /* Strip the rsync prefix from disguised namespaces. */ + if ( #ifdef HAVE_LINUX_XATTRS - write_varint(f, rxa->name_len); + am_root < 0 +#endif + && name_len > RPRE_LEN && name[RPRE_LEN] != '%' + && HAS_PREFIX(name, RSYNC_PREFIX)) { + name += RPRE_LEN; + name_len -= RPRE_LEN; + } +#ifndef HAVE_LINUX_XATTRS + else { + /* Put everything else in the user namespace. */ + name_len += UPRE_LEN; + } +#endif + write_varint(f, name_len); write_varint(f, rxa->datum_len); - write_buf(f, rxa->name, rxa->name_len); -#else - /* We strip the rsync prefix from disguised namespaces - * and put everything else in the user namespace. */ - if (HAS_PREFIX(rxa->name, RSYNC_PREFIX) - && rxa->name[RPRE_LEN] != '%') { - write_varint(f, rxa->name_len - RPRE_LEN); - write_varint(f, rxa->datum_len); - write_buf(f, rxa->name + RPRE_LEN, rxa->name_len - RPRE_LEN); - } else { - write_varint(f, rxa->name_len + UPRE_LEN); - write_varint(f, rxa->datum_len); +#ifndef HAVE_LINUX_XATTRS + if (name_len > rxa->name_len) { write_buf(f, USER_PREFIX, UPRE_LEN); - write_buf(f, rxa->name, rxa->name_len); + name_len -= UPRE_LEN; } #endif + write_buf(f, name, name_len); if (rxa->datum_len > MAX_FULL_DATUM) write_buf(f, rxa->datum + 1, MAX_DIGEST_LEN); else @@ -574,6 +580,11 @@ void receive_xattr(struct file_struct *file, int f) { static item_list temp_xattr = EMPTY_ITEM_LIST; int count, num; +#ifdef HAVE_LINUX_XATTRS + int need_sort = 0; +#else + int need_sort = 1; +#endif int ndx = read_varint(f); if (ndx < 0 || (size_t)ndx > rsync_xal_l.count) { @@ -624,6 +635,7 @@ void receive_xattr(struct file_struct *file, int f) name -= RPRE_LEN; name_len += RPRE_LEN; memcpy(name, RSYNC_PREFIX, RPRE_LEN); + need_sort = 1; } #else /* This OS only has a user namespace, so we either @@ -655,6 +667,9 @@ void receive_xattr(struct file_struct *file, int f) rxa->num = num; } + if (need_sort && count > 1) + qsort(temp_xattr.items, count, sizeof (rsync_xa), rsync_xal_compare_names); + ndx = rsync_xal_l.count; /* pre-incremented count */ rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */