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.
6 To use this patch, run these commands for a successful build:
8 patch -p1 <patches/acls.diff
9 patch -p1 <patches/xattrs.diff
10 ./configure (optional if already run)
15 @@ -115,13 +115,6 @@ void setup_protocol(int f_out,int f_in)
17 exit_cleanup(RERR_PROTOCOL);
19 - if (preserve_xattrs) {
21 - "--xattrs requires protocol 30 or higher"
22 - " (negotiated %d).\n",
24 - exit_cleanup(RERR_PROTOCOL);
28 if (delete_mode && !(delete_before+delete_during+delete_after)) {
29 --- old/testsuite/xattrs.test
30 +++ new/testsuite/xattrs.test
33 $RSYNC --version | grep ", xattrs" >/dev/null || test_skipped "Rsync is configured without xattr support"
36 -*protocol=29*) test_skipped "xattr support requires protocol 30" ;;
39 case "`xattr 2>&1`" in
49 #include "lib/sysxattrs.h"
52 @@ -31,6 +32,7 @@ extern int am_generator;
55 extern int checksum_seed;
56 +extern int protocol_version;
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)))
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))
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,
78 @@ -315,34 +317,46 @@ int send_xattr(statx *sxp, int f)
80 int ndx = find_matching_xattr(sxp->xattr);
82 - /* Send 0 (-1 + 1) to indicate that literal xattr data follows. */
83 - write_abbrevint(f, ndx + 1);
84 + if (protocol_version < 30) {
90 + /* Send 0 (-1 + 1) to indicate that literal xattr data follows. */
91 + write_abbrevint(f, ndx + 1);
96 int count = sxp->xattr->count;
97 - write_abbrevint(f, count);
98 + if (protocol_version >= 30)
99 + write_abbrevint(f, count);
101 + write_byte(f, 'X');
102 + write_int(f, count);
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);
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);
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);
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);
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;
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;
148 + if (protocol_version < 30)
151 lst += F_XATTR(file);
153 for (rxa = lst->items, j = 0; j < cnt; rxa++, j++) {
154 @@ -506,6 +523,9 @@ void recv_xattr_request(struct file_stru
158 + if (protocol_version < 30)
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
166 static item_list temp_xattr = EMPTY_ITEM_LIST;
168 - int ndx = read_abbrevint(f);
171 + if (protocol_version >= 30)
172 + ndx = read_abbrevint(f);
174 + int tag = read_byte(f);
176 + ndx = read_int(f) + 1;
177 + else if (tag == 'X')
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);
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
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;
197 @@ -573,9 +608,10 @@ void receive_xattr(struct file_struct *f
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;