Fix "could not find xattr #1" errors.
authorWayne Davison <wayned@samba.org>
Sun, 26 Jun 2016 18:46:18 +0000 (11:46 -0700)
committerWayne Davison <wayned@samba.org>
Sun, 26 Jun 2016 19:06:09 +0000 (12:06 -0700)
The abbreviated-xattr code can get requests that are not in the same
order as the xattr list, so we need to support wrap-around scanning
of the available xattrs. Fixes bug 6590.

xattrs.c

index 6a77a0bce3ca070ae5290f3065212fe0ed8706ee..0658afbbb861870859dc816170a2959e4ff54a9e 100644 (file)
--- a/xattrs.c
+++ b/xattrs.c
@@ -611,10 +611,32 @@ int recv_xattr_request(struct file_struct *file, int f_in)
        num = 0;
        while ((rel_pos = read_varint(f_in)) != 0) {
                num += rel_pos;
-               /* Note that the sender-related num values may not be in order on the receiver! */
-               while (cnt && (am_sender ? rxa->num < num : rxa->num != num)) {
-                       rxa++;
-                       cnt--;
+               if (am_sender) {
+                       /* The sender-related num values are only in order on the sender.
+                        * We use that order here to scan foward or backward as needed. */
+                       if (rel_pos < 0) {
+                               while (cnt < (int)lst->count && rxa->num > num) {
+                                       rxa--;
+                                       cnt++;
+                               }
+                       } else {
+                               while (cnt > 1 && rxa->num < num) {
+                                       rxa++;
+                                       cnt--;
+                               }
+                       }
+               } else {
+                       int j;
+                       /* The receiving side has no known num order, so we just scan
+                        * forward (w/wrap) and hope that the next value is near by. */
+                       for (j = lst->count; j > 1 && rxa->num != num; j--) {
+                               if (--cnt)
+                                       rxa++;
+                               else {
+                                       cnt = lst->count;
+                                       rxa = lst->items;
+                               }
+                       }
                }
                if (!cnt || rxa->num != num) {
                        rprintf(FERROR, "[%s] could not find xattr #%d for %s\n",