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); @@ -365,7 +367,7 @@ static int find_matching_xattr(item_list *xalp) || 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) @@ -402,13 +404,22 @@ int send_xattr(int f, stat_x *sxp) { 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++) { size_t name_len = rxa->name_len; const char *name = rxa->name; @@ -427,8 +438,8 @@ int send_xattr(int f, stat_x *sxp) name_len += UPRE_LEN; } #endif - write_varint(f, name_len); - write_varint(f, rxa->datum_len); + write_varint30(f, name_len); + write_varint30(f, rxa->datum_len); #ifndef HAVE_LINUX_XATTRS if (name_len > rxa->name_len) { write_buf(f, USER_PREFIX, UPRE_LEN); @@ -436,7 +447,7 @@ int send_xattr(int f, stat_x *sxp) } #endif write_buf(f, name, name_len); - 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); @@ -486,7 +497,7 @@ int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all) 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; @@ -531,6 +542,9 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out) int cnt, prior_req = 0; rsync_xa *rxa; + if (protocol_version < 30) + return; + lst += F_XATTR(file); for (rxa = lst->items, cnt = lst->count; cnt--; rxa++) { if (rxa->datum_len <= MAX_FULL_DATUM) @@ -587,6 +601,9 @@ int recv_xattr_request(struct file_struct *file, int f_in) rsync_xa *rxa; int rel_pos, cnt, num, got_xattr_data = 0; + if (protocol_version < 30) + return 0; + if (F_XATTR(file) < 0) { rprintf(FERROR, "recv_xattr_request: internal data error!\n"); exit_cleanup(RERR_PROTOCOL); @@ -649,7 +666,22 @@ void receive_xattr(int f, struct file_struct *file) #else int need_sort = 1; #endif - 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" @@ -662,7 +694,7 @@ void receive_xattr(int f, struct file_struct *file) 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; } @@ -670,9 +702,10 @@ void receive_xattr(int f, struct file_struct *file) for (num = 1; num <= count; num++) { 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) || (dget_len + extra_len + name_len < dget_len))