This patch adds backward-compatibility support for the --xattrs option. Since the main release has never had xattr support, the trunk doesn't need this code. If you want to make rsync 3.0.x communicate with an older (patched) release, use this. To use this patch, run these commands for a successful build: patch -p1 MAX_FULL_DATUM) { + if (datum_len > MAX_FULL_DATUM && protocol_version >= 30) { /* For large datums, we store a flag and a checksum. */ name_offset = 1 + MAX_DIGEST_LEN; sum_init(checksum_seed); @@ -297,7 +299,7 @@ static int find_matching_xattr(item_list || rxas1[j].datum_len != rxas2[j].datum_len || strcmp(rxas1[j].name, rxas2[j].name)) break; - if (rxas1[j].datum_len > MAX_FULL_DATUM) { + if (rxas1[j].datum_len > MAX_FULL_DATUM && protocol_version >= 30) { if (memcmp(rxas1[j].datum + 1, rxas2[j].datum + 1, MAX_DIGEST_LEN) != 0) @@ -334,34 +336,43 @@ int send_xattr(statx *sxp, int f) { int ndx = find_matching_xattr(sxp->xattr); - /* Send 0 (-1 + 1) to indicate that literal xattr data follows. */ - write_varint(f, ndx + 1); + if (protocol_version < 30) { + if (ndx < 0) + write_byte(f, 'X'); + else { + write_byte(f, 'x'); + write_int(f, ndx); + } + } else { + /* Send 0 (-1 + 1) to indicate that literal xattr data follows. */ + write_varint(f, ndx + 1); + } if (ndx < 0) { rsync_xa *rxa; int count = sxp->xattr->count; - write_varint(f, count); + write_varint30(f, count); for (rxa = sxp->xattr->items; count--; rxa++) { #ifdef HAVE_LINUX_XATTRS - write_varint(f, rxa->name_len); - write_varint(f, rxa->datum_len); + write_varint30(f, rxa->name_len); + write_varint30(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_varint30(f, rxa->name_len - RPRE_LEN); + write_varint30(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); + write_varint30(f, rxa->name_len + UPRE_LEN); + write_varint30(f, rxa->datum_len); write_buf(f, USER_PREFIX, UPRE_LEN); write_buf(f, rxa->name, rxa->name_len); } #endif - if (rxa->datum_len > MAX_FULL_DATUM) + if (rxa->datum_len > MAX_FULL_DATUM && protocol_version >= 30) write_buf(f, rxa->datum + 1, MAX_DIGEST_LEN); else write_buf(f, rxa->datum, rxa->datum_len); @@ -411,7 +422,7 @@ int xattr_diff(struct file_struct *file, cmp = rec_cnt ? strcmp(snd_rxa->name, rec_rxa->name) : -1; if (cmp > 0) same = 0; - else if (snd_rxa->datum_len > MAX_FULL_DATUM) { + else if (snd_rxa->datum_len > MAX_FULL_DATUM && protocol_version >= 30) { same = cmp == 0 && snd_rxa->datum_len == rec_rxa->datum_len && memcmp(snd_rxa->datum + 1, rec_rxa->datum + 1, MAX_DIGEST_LEN) == 0; @@ -454,6 +465,9 @@ void send_xattr_request(const char *fnam int j, cnt, prior_req = -1; rsync_xa *rxa; + if (protocol_version < 30) + return; + lst += F_XATTR(file); cnt = lst->count; for (rxa = lst->items, j = 0; j < cnt; rxa++, j++) { @@ -525,6 +539,9 @@ void recv_xattr_request(struct file_stru rsync_xa *rxa; int rel_pos, cnt; + if (protocol_version < 30) + return; + if (F_XATTR(file) < 0) { rprintf(FERROR, "recv_xattr_request: internal data error!\n"); exit_cleanup(RERR_STREAMIO); @@ -571,7 +588,22 @@ void receive_xattr(struct file_struct *f { static item_list temp_xattr = EMPTY_ITEM_LIST; int count; - int ndx = read_varint(f); + int ndx; + + if (protocol_version >= 30) + ndx = read_varint(f); + else { + int tag = read_byte(f); + if (tag == 'x') + ndx = read_int(f) + 1; + else if (tag == 'X') + ndx = 0; + else { + rprintf(FERROR, "receive_xattr: unknown extended attribute" + " type tag (%02x) for %s\n", tag, f_name(file, NULL)); + exit_cleanup(RERR_STREAMIO); + } + } if (ndx < 0 || (size_t)ndx > rsync_xal_l.count) { rprintf(FERROR, "receive_xattr: xa index %d out of" @@ -584,7 +616,7 @@ void receive_xattr(struct file_struct *f return; } - if ((count = read_varint(f)) != 0) { + if ((count = read_varint30(f)) != 0) { (void)EXPAND_ITEM_LIST(&temp_xattr, rsync_xa, count); temp_xattr.count = 0; } @@ -592,9 +624,10 @@ void receive_xattr(struct file_struct *f while (count--) { char *ptr, *name; rsync_xa *rxa; - size_t name_len = read_varint(f); - size_t datum_len = read_varint(f); - size_t dget_len = datum_len > MAX_FULL_DATUM ? 1 + MAX_DIGEST_LEN : datum_len; + size_t name_len = read_varint30(f); + size_t datum_len = read_varint30(f); + size_t dget_len = datum_len > MAX_FULL_DATUM && protocol_version >= 30 + ? 1 + MAX_DIGEST_LEN : datum_len; size_t extra_len = MIGHT_NEED_RPRE ? RPRE_LEN : 0; if (dget_len + extra_len < dget_len) out_of_memory("receive_xattr"); /* overflow */