X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/a685271de33c6d9d39fb1a8855fe214911c774e6..b769ad6a3e7ef871ea0aabd5b033018ba6cdbb90:/xattrs.c diff --git a/xattrs.c b/xattrs.c index 6ab9698b..61d4f607 100644 --- a/xattrs.c +++ b/xattrs.c @@ -47,7 +47,6 @@ extern int checksum_seed; #define XSTATE_ABBREV 0 #define XSTATE_DONE 1 #define XSTATE_TODO 2 -#define XSTATE_LOCAL 3 #define USER_PREFIX "user." #define UPRE_LEN ((int)sizeof USER_PREFIX - 1) @@ -70,6 +69,7 @@ extern int checksum_seed; typedef struct { char *datum, *name; size_t datum_len, name_len; + int num; } rsync_xa; static size_t namebuf_len = 0; @@ -210,14 +210,14 @@ static int rsync_xal_get(const char *fname, item_list *xalp) #ifdef HAVE_LINUX_XATTRS int user_only = am_sender ? 0 : !am_root; #endif + rsync_xa *rxa; + int count; /* This puts the name list into the "namebuf" buffer. */ if ((list_len = get_xattr_names(fname)) < 0) return -1; for (name = namebuf; list_len > 0; name += name_len) { - rsync_xa *rxa; - name_len = strlen(name) + 1; list_len -= name_len; @@ -270,8 +270,12 @@ static int rsync_xal_get(const char *fname, item_list *xalp) rxa->name_len = name_len; rxa->datum_len = datum_len; } - if (xalp->count > 1) - qsort(xalp->items, xalp->count, sizeof (rsync_xa), rsync_xal_compare_names); + count = xalp->count; + rxa = xalp->items; + if (count > 1) + qsort(rxa, count, sizeof (rsync_xa), rsync_xal_compare_names); + for (rxa += count-1; count; count--, rxa--) + rxa->num = count; return 0; } @@ -459,18 +463,19 @@ int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all) void send_xattr_request(const char *fname, struct file_struct *file, int f_out) { item_list *lst = rsync_xal_l.items; - int j, cnt, prior_req = -1; + int cnt, prior_req = 0; rsync_xa *rxa; lst += F_XATTR(file); - cnt = lst->count; - for (rxa = lst->items, j = 0; j < cnt; rxa++, j++) { + for (rxa = lst->items, cnt = lst->count; cnt--; rxa++) { if (rxa->datum_len <= MAX_FULL_DATUM) continue; switch (rxa->datum[0]) { - case XSTATE_LOCAL: - /* Items set locally will get cached by receiver. */ - rxa->datum[0] = XSTATE_DONE; + case XSTATE_ABBREV: + /* Items left abbreviated matched the sender's checksum, so + * the receiver will cache the local data for future use. */ + if (am_generator) + rxa->datum[0] = XSTATE_DONE; continue; case XSTATE_TODO: break; @@ -481,8 +486,8 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out) /* Flag that we handled this abbreviated item. */ rxa->datum[0] = XSTATE_DONE; - write_varint(f_out, j - prior_req); - prior_req = j; + write_varint(f_out, rxa->num - prior_req); + prior_req = rxa->num; if (fname) { size_t len = 0; @@ -504,27 +509,6 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out) write_byte(f_out, 0); /* end the list */ } -/* Any items set locally by the generator that the receiver doesn't - * get told about get changed back to XSTATE_ABBREV. */ -void xattr_clear_locals(struct file_struct *file) -{ - item_list *lst = rsync_xal_l.items; - rsync_xa *rxa; - int cnt; - - if (F_XATTR(file) < 0) - return; - - lst += F_XATTR(file); - cnt = lst->count; - for (rxa = lst->items; cnt--; rxa++) { - if (rxa->datum_len <= MAX_FULL_DATUM) - continue; - if (rxa->datum[0] == XSTATE_LOCAL) - rxa->datum[0] = XSTATE_ABBREV; - } -} - /* When called by the sender, read the request from the generator and mark * any needed xattrs with a flag that lets us know they need to be sent to * the receiver. When called by the receiver, reads the sent data and @@ -534,7 +518,7 @@ int recv_xattr_request(struct file_struct *file, int f_in) item_list *lst = rsync_xal_l.items; char *old_datum, *name; rsync_xa *rxa; - int rel_pos, cnt, got_xattr_data = 0; + int rel_pos, cnt, num, got_xattr_data = 0; if (F_XATTR(file) < 0) { rprintf(FERROR, "recv_xattr_request: internal data error!\n"); @@ -544,13 +528,20 @@ int recv_xattr_request(struct file_struct *file, int f_in) cnt = lst->count; rxa = lst->items; - rxa -= 1; + num = 0; while ((rel_pos = read_varint(f_in)) != 0) { - rxa += rel_pos; - cnt -= rel_pos; - if (cnt < 0 || rxa->datum_len <= MAX_FULL_DATUM - || rxa->datum[0] != XSTATE_ABBREV) { - rprintf(FERROR, "recv_xattr_request: internal abbrev error!\n"); + num += rel_pos; + while (cnt && rxa->num < num) { + rxa++; + cnt--; + } + if (!cnt || rxa->num != num) { + rprintf(FERROR, "[%s] could not find xattr #%d for %s\n", + who_am_i(), num, f_name(file, NULL)); + exit_cleanup(RERR_STREAMIO); + } + if (rxa->datum_len <= MAX_FULL_DATUM || rxa->datum[0] != XSTATE_ABBREV) { + rprintf(FERROR, "[%s] internal abbrev error!\n", who_am_i()); exit_cleanup(RERR_STREAMIO); } @@ -584,7 +575,7 @@ int recv_xattr_request(struct file_struct *file, int f_in) void receive_xattr(struct file_struct *file, int f) { static item_list temp_xattr = EMPTY_ITEM_LIST; - int count; + int count, num; int ndx = read_varint(f); if (ndx < 0 || (size_t)ndx > rsync_xal_l.count) { @@ -603,7 +594,7 @@ void receive_xattr(struct file_struct *file, int f) temp_xattr.count = 0; } - while (count--) { + for (num = 1; num <= count; num++) { char *ptr, *name; rsync_xa *rxa; size_t name_len = read_varint(f); @@ -627,14 +618,14 @@ void receive_xattr(struct file_struct *file, int f) } #ifdef HAVE_LINUX_XATTRS /* Non-root can only save the user namespace. */ - if (am_root <= 0 && !HAS_PREFIX(name, USER_PREFIX)) { - if (!am_root) { - free(ptr); - continue; - } - name -= RPRE_LEN; - name_len += RPRE_LEN; - memcpy(name, RSYNC_PREFIX, RPRE_LEN); + if (am_root <= 0 && !HAS_PREFIX(name, USER_PREFIX)) { + if (!am_root) { + free(ptr); + continue; + } + name -= RPRE_LEN; + name_len += RPRE_LEN; + memcpy(name, RSYNC_PREFIX, RPRE_LEN); } #else /* This OS only has a user namespace, so we either @@ -663,6 +654,7 @@ void receive_xattr(struct file_struct *file, int f) rxa->datum = ptr; rxa->name_len = name_len; rxa->datum_len = datum_len; + rxa->num = num; } ndx = rsync_xal_l.count; /* pre-incremented count */ @@ -739,8 +731,6 @@ static int rsync_xal_set(const char *fname, item_list *xalp, sxp->st.st_mtime = (time_t)-1; if (am_generator) { /* generator items stay abbreviated */ - if (rxas[i].datum[0] == XSTATE_ABBREV) - rxas[i].datum[0] = XSTATE_LOCAL; free(ptr); continue; }