X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/3f0211b63a6cdc4a2cecfd2a0dffeba172c86a47..a685271de33c6d9d39fb1a8855fe214911c774e6:/xattrs.c diff --git a/xattrs.c b/xattrs.c index 21e30499..6ab9698b 100644 --- a/xattrs.c +++ b/xattrs.c @@ -216,7 +216,7 @@ static int rsync_xal_get(const char *fname, item_list *xalp) return -1; for (name = namebuf; list_len > 0; name += name_len) { - rsync_xa *rxas; + rsync_xa *rxa; name_len = strlen(name) + 1; list_len -= name_len; @@ -230,9 +230,12 @@ static int rsync_xal_get(const char *fname, item_list *xalp) #endif /* No rsync.%FOO attributes are copied w/o 2 -X options. */ - if (preserve_xattrs < 2 && name_len > RPRE_LEN - && name[RPRE_LEN] == '%' && HAS_PREFIX(name, RSYNC_PREFIX)) - continue; + if (name_len > RPRE_LEN && name[RPRE_LEN] == '%' + && HAS_PREFIX(name, RSYNC_PREFIX)) { + if ((am_sender && preserve_xattrs < 2) + || (am_root < 0 && strcmp(name, XSTAT_ATTR) == 0)) + continue; + } datum_len = name_len; /* Pass extra size to get_xattr_data() */ if (!(ptr = get_xattr_data(fname, name, &datum_len, 0))) @@ -253,19 +256,19 @@ static int rsync_xal_get(const char *fname, item_list *xalp) name_offset = datum_len; #ifdef HAVE_LINUX_XATTRS - if (am_root < 0 && name_len > RPRE_LEN + if (am_root < 0 && name_len > RPRE_LEN && name[RPRE_LEN] != '%' && HAS_PREFIX(name, RSYNC_PREFIX)) { name += RPRE_LEN; name_len -= RPRE_LEN; } #endif - rxas = EXPAND_ITEM_LIST(xalp, rsync_xa, RSYNC_XAL_INITIAL); - rxas->name = ptr + name_offset; - memcpy(rxas->name, name, name_len); - rxas->datum = ptr; - rxas->name_len = name_len; - rxas->datum_len = datum_len; + rxa = EXPAND_ITEM_LIST(xalp, rsync_xa, RSYNC_XAL_INITIAL); + rxa->name = ptr + name_offset; + memcpy(rxa->name, name, name_len); + rxa->datum = ptr; + 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); @@ -486,8 +489,11 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out) char *ptr; /* Re-read the long datum. */ - if (!(ptr = get_xattr_data(fname, rxa->name, &len, 0))) + if (!(ptr = get_xattr_data(fname, rxa->name, &len, 0))) { + rprintf(FERROR_XFER, "failed to re-read xattr %s for %s\n", rxa->name, fname); + write_varint(f_out, 0); continue; + } write_varint(f_out, len); /* length might have changed! */ write_buf(f_out, ptr, len); @@ -523,12 +529,12 @@ void xattr_clear_locals(struct file_struct *file) * 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 * stores it in place of its checksum. */ -void recv_xattr_request(struct file_struct *file, int f_in) +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; + int rel_pos, cnt, got_xattr_data = 0; if (F_XATTR(file) < 0) { rprintf(FERROR, "recv_xattr_request: internal data error!\n"); @@ -566,7 +572,10 @@ void recv_xattr_request(struct file_struct *file, int f_in) rxa->name = name; free(old_datum); read_buf(f_in, rxa->datum, rxa->datum_len); + got_xattr_data = 1; } + + return got_xattr_data; } /* ------------------------------------------------------------------------- */ @@ -765,6 +774,9 @@ static int rsync_xal_set(const char *fname, item_list *xalp, : !HAS_PREFIX(name, USER_PREFIX)) continue; #endif + if (am_root < 0 && name_len > RPRE_LEN + && name[RPRE_LEN] == '%' && strcmp(name, XSTAT_ATTR) == 0) + continue; for (i = 0; i < xalp->count; i++) { if (strcmp(name, rxas[i].name) == 0) @@ -881,7 +893,7 @@ int get_stat_xattr(const char *fname, int fd, STRUCT_STAT *fst, STRUCT_STAT *xst return 0; } -int set_stat_xattr(const char *fname, struct file_struct *file) +int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode) { STRUCT_STAT fst, xst; dev_t rdev; @@ -903,7 +915,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file) } fst.st_mode &= (_S_IFMT | CHMOD_BITS); - fmode = file->mode & (_S_IFMT | CHMOD_BITS); + fmode = new_mode & (_S_IFMT | CHMOD_BITS); if (IS_DEVICE(fmode) || IS_SPECIAL(fmode)) { uint32 *devp = F_RDEV_P(file);