Fixed the interaction of --fake-super with --link-dest & --xattrs.
authorWayne Davison <wayned@samba.org>
Sat, 8 Mar 2008 00:16:29 +0000 (16:16 -0800)
committerWayne Davison <wayned@samba.org>
Sat, 8 Mar 2008 00:23:21 +0000 (16:23 -0800)
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.

testsuite/xattrs.test
xattrs.c

index 97c5f8d..66c3e75 100644 (file)
@@ -20,6 +20,7 @@ case "`xattr 2>&1`" in
     xls() {
        xattr -l "${@}"
     }
     xls() {
        xattr -l "${@}"
     }
+    RUSR='rsync'
     ;;
 *)
     xset() {
     ;;
 *)
     xset() {
@@ -31,6 +32,7 @@ case "`xattr 2>&1`" in
     xls() {
        getfattr -d "${@}"
     }
     xls() {
        getfattr -d "${@}"
     }
+    RUSR='user.rsync'
     ;;
 esac
 
     ;;
 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.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.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"
 
 
 xls $files >"$scratchdir/xattrs.txt"
 
@@ -95,10 +99,17 @@ xls $files >"$scratchdir/xattrs.txt"
 
 rm -rf "$todir"
 
 
 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" -
 
 
 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
 # The script would have aborted on error, so getting here means we've won.
 exit 0
index a436572..53363bd 100644 (file)
--- a/xattrs.c
+++ b/xattrs.c
@@ -62,9 +62,12 @@ extern int checksum_seed;
 #endif
 #define RPRE_LEN ((int)sizeof RSYNC_PREFIX - 1)
 
 #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;
 
 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)
                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;
                }
 
                                continue;
                }
 
@@ -253,14 +259,6 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
                } else
                        name_offset = datum_len;
 
                } 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);
                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 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
 #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_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, USER_PREFIX, UPRE_LEN);
-                               write_buf(f, rxa->name, rxa->name_len);
+                               name_len -= UPRE_LEN;
                        }
 #endif
                        }
 #endif
+                       write_buf(f, name, name_len);
                        if (rxa->datum_len > MAX_FULL_DATUM)
                                write_buf(f, rxa->datum + 1, MAX_DIGEST_LEN);
                        else
                        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;
 {
        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) {
        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);
                        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
                }
 #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;
        }
 
                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 */
 
        ndx = rsync_xal_l.count; /* pre-incremented count */
        rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */