A minor tweak to the compatibility code.
[rsync/rsync-patches.git] / xattrs.diff
1 This patch adds backward-compatibility support for the --xattrs option.
2 Since the main release has never had xattr support, the trunk doesn't
3 need this code.  If you want to make rsync 3.0.x communicate with an
4 older (patched) release, use this.
5
6 To use this patch, run these commands for a successful build:
7
8     patch -p1 <patches/acls.diff
9     patch -p1 <patches/xattrs.diff
10     ./configure                         (optional if already run)
11     make
12
13 --- old/compat.c
14 +++ new/compat.c
15 @@ -115,13 +115,6 @@ void setup_protocol(int f_out,int f_in)
16                             protocol_version);
17                         exit_cleanup(RERR_PROTOCOL);
18                 }
19 -               if (preserve_xattrs) {
20 -                       rprintf(FERROR,
21 -                           "--xattrs requires protocol 30 or higher"
22 -                           " (negotiated %d).\n",
23 -                           protocol_version);
24 -                       exit_cleanup(RERR_PROTOCOL);
25 -               }
26         }
27  
28         if (delete_mode && !(delete_before+delete_during+delete_after)) {
29 --- old/testsuite/xattrs.test
30 +++ new/testsuite/xattrs.test
31 @@ -9,10 +9,6 @@
32  
33  $RSYNC --version | grep ", xattrs" >/dev/null || test_skipped "Rsync is configured without xattr support"
34  
35 -case "$RSYNC" in
36 -*protocol=29*) test_skipped "xattr support requires protocol 30" ;;
37 -esac
38 -
39  case "`xattr 2>&1`" in
40  *--list:*)
41      xset() {
42 --- old/xattrs.c
43 +++ new/xattrs.c
44 @@ -20,6 +20,7 @@
45   */
46  
47  #include "rsync.h"
48 +#include "io.h"
49  #include "lib/sysxattrs.h"
50  
51  #ifdef SUPPORT_XATTRS
52 @@ -31,6 +32,7 @@ extern int am_generator;
53  extern int read_only;
54  extern int list_only;
55  extern int checksum_seed;
56 +extern int protocol_version;
57  
58  #define RSYNC_XAL_INITIAL 5
59  #define RSYNC_XAL_LIST_INITIAL 100
60 @@ -222,7 +224,7 @@ static int rsync_xal_get(const char *fna
61                 if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
62                         return -1;
63  
64 -               if (datum_len > MAX_FULL_DATUM) {
65 +               if (datum_len > MAX_FULL_DATUM && protocol_version >= 30) {
66                         /* For large datums, we store a flag and a checksum. */
67                         name_offset = 1 + MAX_DIGEST_LEN;
68                         sum_init(checksum_seed);
69 @@ -278,7 +280,7 @@ static int find_matching_xattr(item_list
70                          || rxas1[j].datum_len != rxas2[j].datum_len
71                          || strcmp(rxas1[j].name, rxas2[j].name))
72                                 break;
73 -                       if (rxas1[j].datum_len > MAX_FULL_DATUM) {
74 +                       if (rxas1[j].datum_len > MAX_FULL_DATUM && protocol_version >= 30) {
75                                 if (memcmp(rxas1[j].datum + 1,
76                                            rxas2[j].datum + 1,
77                                            MAX_DIGEST_LEN) != 0)
78 @@ -315,34 +317,43 @@ int send_xattr(statx *sxp, int f)
79  {
80         int ndx = find_matching_xattr(sxp->xattr);
81  
82 -       /* Send 0 (-1 + 1) to indicate that literal xattr data follows. */
83 -       write_abbrevint(f, ndx + 1);
84 +       if (protocol_version < 30) {
85 +               if (ndx < 0)
86 +                       write_byte(f, 'X');
87 +               else {
88 +                       write_byte(f, 'x');
89 +                       write_int(f, ndx);
90 +               }
91 +       } else {
92 +               /* Send 0 (-1 + 1) to indicate that literal xattr data follows. */
93 +               write_abbrevint(f, ndx + 1);
94 +       }
95  
96         if (ndx < 0) {
97                 rsync_xa *rxa;
98                 int count = sxp->xattr->count;
99 -               write_abbrevint(f, count);
100 +               write_abbrevint30(f, count);
101                 for (rxa = sxp->xattr->items; count--; rxa++) {
102  #ifdef HAVE_LINUX_XATTRS
103 -                       write_abbrevint(f, rxa->name_len);
104 -                       write_abbrevint(f, rxa->datum_len);
105 +                       write_abbrevint30(f, rxa->name_len);
106 +                       write_abbrevint30(f, rxa->datum_len);
107                         write_buf(f, rxa->name, rxa->name_len);
108  #else
109                         /* We strip the rsync prefix from disguised namespaces
110                          * and put everything else in the user namespace. */
111                         if (HAS_PREFIX(rxa->name, RSYNC_PREFIX)
112                          && rxa->name[RPRE_LEN] != '%') {
113 -                               write_abbrevint(f, rxa->name_len - RPRE_LEN);
114 -                               write_abbrevint(f, rxa->datum_len);
115 +                               write_abbrevint30(f, rxa->name_len - RPRE_LEN);
116 +                               write_abbrevint30(f, rxa->datum_len);
117                                 write_buf(f, rxa->name + RPRE_LEN, rxa->name_len - RPRE_LEN);
118                         } else {
119 -                               write_abbrevint(f, rxa->name_len + UPRE_LEN);
120 -                               write_abbrevint(f, rxa->datum_len);
121 +                               write_abbrevint30(f, rxa->name_len + UPRE_LEN);
122 +                               write_abbrevint30(f, rxa->datum_len);
123                                 write_buf(f, USER_PREFIX, UPRE_LEN);
124                                 write_buf(f, rxa->name, rxa->name_len);
125                         }
126  #endif
127 -                       if (rxa->datum_len > MAX_FULL_DATUM)
128 +                       if (rxa->datum_len > MAX_FULL_DATUM && protocol_version >= 30)
129                                 write_buf(f, rxa->datum + 1, MAX_DIGEST_LEN);
130                         else
131                                 write_buf(f, rxa->datum, rxa->datum_len);
132 @@ -392,7 +403,7 @@ int xattr_diff(struct file_struct *file,
133                 cmp = rec_cnt ? strcmp(snd_rxa->name, rec_rxa->name) : -1;
134                 if (cmp > 0)
135                         same = 0;
136 -               else if (snd_rxa->datum_len > MAX_FULL_DATUM) {
137 +               else if (snd_rxa->datum_len > MAX_FULL_DATUM && protocol_version >= 30) {
138                         same = cmp == 0 && snd_rxa->datum_len == rec_rxa->datum_len
139                             && memcmp(snd_rxa->datum + 1, rec_rxa->datum + 1,
140                                       MAX_DIGEST_LEN) == 0;
141 @@ -435,6 +446,9 @@ void send_xattr_request(const char *fnam
142         int j, cnt, prior_req = -1;
143         rsync_xa *rxa;
144  
145 +       if (protocol_version < 30)
146 +               return;
147 +
148         lst += F_XATTR(file);
149         cnt = lst->count;
150         for (rxa = lst->items, j = 0; j < cnt; rxa++, j++) {
151 @@ -506,6 +520,9 @@ void recv_xattr_request(struct file_stru
152         rsync_xa *rxa;
153         int rel_pos, cnt;
154  
155 +       if (protocol_version < 30)
156 +               return;
157 +
158         if (F_XATTR(file) < 0) {
159                 rprintf(FERROR, "recv_xattr_request: internal data error!\n");
160                 exit_cleanup(RERR_STREAMIO);
161 @@ -552,7 +569,22 @@ void receive_xattr(struct file_struct *f
162  {
163         static item_list temp_xattr = EMPTY_ITEM_LIST;
164         int count;
165 -       int ndx = read_abbrevint(f);
166 +       int ndx;
167 +
168 +       if (protocol_version >= 30)
169 +               ndx = read_abbrevint(f);
170 +       else {
171 +               int tag = read_byte(f);
172 +               if (tag == 'x')
173 +                       ndx = read_int(f) + 1;
174 +               else if (tag == 'X')
175 +                       ndx = 0;
176 +               else {
177 +                       rprintf(FERROR, "receive_xattr: unknown extended attribute"
178 +                               " type tag (%02x) for %s\n", tag, f_name(file, NULL));
179 +                       exit_cleanup(RERR_STREAMIO);
180 +               }
181 +       }
182  
183         if (ndx < 0 || (size_t)ndx > rsync_xal_l.count) {
184                 rprintf(FERROR, "receive_xattr: xa index %d out of"
185 @@ -565,7 +597,7 @@ void receive_xattr(struct file_struct *f
186                 return;
187         }
188         
189 -       if ((count = read_abbrevint(f)) != 0) {
190 +       if ((count = read_abbrevint30(f)) != 0) {
191                 (void)EXPAND_ITEM_LIST(&temp_xattr, rsync_xa, count);
192                 temp_xattr.count = 0;
193         }
194 @@ -573,9 +605,10 @@ void receive_xattr(struct file_struct *f
195         while (count--) {
196                 char *ptr, *name;
197                 rsync_xa *rxa;
198 -               size_t name_len = read_abbrevint(f);
199 -               size_t datum_len = read_abbrevint(f);
200 -               size_t dget_len = datum_len > MAX_FULL_DATUM ? 1 + MAX_DIGEST_LEN : datum_len;
201 +               size_t name_len = read_abbrevint30(f);
202 +               size_t datum_len = read_abbrevint30(f);
203 +               size_t dget_len = datum_len > MAX_FULL_DATUM && protocol_version >= 30
204 +                               ? 1 + MAX_DIGEST_LEN : datum_len;
205  #ifdef HAVE_LINUX_XATTRS
206                 size_t extra_len = 0;
207  #else