This patch makes rsync talk an xattr protocol that is compatible with
[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,46 @@ 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 +                       write_int(f, ndx);
88 +               }
89 +       } else {
90 +               /* Send 0 (-1 + 1) to indicate that literal xattr data follows. */
91 +               write_abbrevint(f, ndx + 1);
92 +       }
93  
94         if (ndx < 0) {
95                 rsync_xa *rxa;
96                 int count = sxp->xattr->count;
97 -               write_abbrevint(f, count);
98 +               if (protocol_version >= 30)
99 +                       write_abbrevint(f, count);
100 +               else {
101 +                       write_byte(f, 'X');
102 +                       write_int(f, count);
103 +               }
104                 for (rxa = sxp->xattr->items; count--; rxa++) {
105  #ifdef HAVE_LINUX_XATTRS
106 -                       write_abbrevint(f, rxa->name_len);
107 -                       write_abbrevint(f, rxa->datum_len);
108 +                       write_abbrevint30(f, rxa->name_len);
109 +                       write_abbrevint30(f, rxa->datum_len);
110                         write_buf(f, rxa->name, rxa->name_len);
111  #else
112                         /* We strip the rsync prefix from disguised namespaces
113                          * and put everything else in the user namespace. */
114                         if (HAS_PREFIX(rxa->name, RSYNC_PREFIX)
115                          && rxa->name[RPRE_LEN] != '%') {
116 -                               write_abbrevint(f, rxa->name_len - RPRE_LEN);
117 -                               write_abbrevint(f, rxa->datum_len);
118 +                               write_abbrevint30(f, rxa->name_len - RPRE_LEN);
119 +                               write_abbrevint30(f, rxa->datum_len);
120                                 write_buf(f, rxa->name + RPRE_LEN, rxa->name_len - RPRE_LEN);
121                         } else {
122 -                               write_abbrevint(f, rxa->name_len + UPRE_LEN);
123 -                               write_abbrevint(f, rxa->datum_len);
124 +                               write_abbrevint30(f, rxa->name_len + UPRE_LEN);
125 +                               write_abbrevint30(f, rxa->datum_len);
126                                 write_buf(f, USER_PREFIX, UPRE_LEN);
127                                 write_buf(f, rxa->name, rxa->name_len);
128                         }
129  #endif
130 -                       if (rxa->datum_len > MAX_FULL_DATUM)
131 +                       if (rxa->datum_len > MAX_FULL_DATUM && protocol_version >= 30)
132                                 write_buf(f, rxa->datum + 1, MAX_DIGEST_LEN);
133                         else
134                                 write_buf(f, rxa->datum, rxa->datum_len);
135 @@ -392,7 +406,7 @@ int xattr_diff(struct file_struct *file,
136                 cmp = rec_cnt ? strcmp(snd_rxa->name, rec_rxa->name) : -1;
137                 if (cmp > 0)
138                         same = 0;
139 -               else if (snd_rxa->datum_len > MAX_FULL_DATUM) {
140 +               else if (snd_rxa->datum_len > MAX_FULL_DATUM && protocol_version >= 30) {
141                         same = cmp == 0 && snd_rxa->datum_len == rec_rxa->datum_len
142                             && memcmp(snd_rxa->datum + 1, rec_rxa->datum + 1,
143                                       MAX_DIGEST_LEN) == 0;
144 @@ -435,6 +449,9 @@ void send_xattr_request(const char *fnam
145         int j, cnt, prior_req = -1;
146         rsync_xa *rxa;
147  
148 +       if (protocol_version < 30)
149 +               return;
150 +
151         lst += F_XATTR(file);
152         cnt = lst->count;
153         for (rxa = lst->items, j = 0; j < cnt; rxa++, j++) {
154 @@ -506,6 +523,9 @@ void recv_xattr_request(struct file_stru
155         rsync_xa *rxa;
156         int rel_pos, cnt;
157  
158 +       if (protocol_version < 30)
159 +               return;
160 +
161         if (F_XATTR(file) < 0) {
162                 rprintf(FERROR, "recv_xattr_request: internal data error!\n");
163                 exit_cleanup(RERR_STREAMIO);
164 @@ -552,7 +572,22 @@ void receive_xattr(struct file_struct *f
165  {
166         static item_list temp_xattr = EMPTY_ITEM_LIST;
167         int count;
168 -       int ndx = read_abbrevint(f);
169 +       int ndx;
170 +
171 +       if (protocol_version >= 30)
172 +               ndx = read_abbrevint(f);
173 +       else {
174 +               int tag = read_byte(f);
175 +               if (tag == 'x')
176 +                       ndx = read_int(f) + 1;
177 +               else if (tag == 'X')
178 +                       ndx = 0;
179 +               else {
180 +                       rprintf(FERROR, "receive_xattr: unknown extended attribute"
181 +                               " type tag (%02x) for %s\n", tag, f_name(file, NULL));
182 +                       exit_cleanup(RERR_STREAMIO);
183 +               }
184 +       }
185  
186         if (ndx < 0 || (size_t)ndx > rsync_xal_l.count) {
187                 rprintf(FERROR, "receive_xattr: xa index %d out of"
188 @@ -565,7 +600,7 @@ void receive_xattr(struct file_struct *f
189                 return;
190         }
191         
192 -       if ((count = read_abbrevint(f)) != 0) {
193 +       if ((count = read_abbrevint30(f)) != 0) {
194                 (void)EXPAND_ITEM_LIST(&temp_xattr, rsync_xa, count);
195                 temp_xattr.count = 0;
196         }
197 @@ -573,9 +608,10 @@ void receive_xattr(struct file_struct *f
198         while (count--) {
199                 char *ptr, *name;
200                 rsync_xa *rxa;
201 -               size_t name_len = read_abbrevint(f);
202 -               size_t datum_len = read_abbrevint(f);
203 -               size_t dget_len = datum_len > MAX_FULL_DATUM ? 1 + MAX_DIGEST_LEN : datum_len;
204 +               size_t name_len = read_abbrevint30(f);
205 +               size_t datum_len = read_abbrevint30(f);
206 +               size_t dget_len = datum_len > MAX_FULL_DATUM && protocol_version >= 30
207 +                               ? 1 + MAX_DIGEST_LEN : datum_len;
208  #ifdef HAVE_LINUX_XATTRS
209                 size_t extra_len = 0;
210  #else