int proper_seed_order = 0;
int inplace_partial = 0;
int do_negotiated_strings = 0;
+int xmit_id0_names = 0;
/* These index values are for the file-list's extra-attribute array. */
int pathname_ndx, depth_ndx, atimes_ndx, uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
#define CF_CHKSUM_SEED_FIX (1<<5)
#define CF_INPLACE_PARTIAL_DIR (1<<6)
#define CF_VARINT_FLIST_FLAGS (1<<7)
+#define CF_ID0_NAMES (1<<8)
static const char *client_info;
compat_flags |= CF_CHKSUM_SEED_FIX;
if (local_server || strchr(client_info, 'I') != NULL)
compat_flags |= CF_INPLACE_PARTIAL_DIR;
+ if (local_server || strchr(client_info, 'u') != NULL)
+ compat_flags |= CF_ID0_NAMES;
if (local_server || strchr(client_info, 'v') != NULL) {
do_negotiated_strings = 1;
compat_flags |= CF_VARINT_FLIST_FLAGS;
want_xattr_optim = protocol_version >= 31 && !(compat_flags & CF_AVOID_XATTR_OPTIM);
proper_seed_order = compat_flags & CF_CHKSUM_SEED_FIX ? 1 : 0;
xfer_flags_as_varint = compat_flags & CF_VARINT_FLIST_FLAGS ? 1 : 0;
+ xmit_id0_names = compat_flags & CF_ID0_NAMES ? 1 : 0;
if (am_sender) {
receiver_symlink_times = am_server
? strchr(client_info, 'L') != NULL
extern int preserve_gid;
extern int preserve_acls;
extern int numeric_ids;
+extern int xmit_id0_names;
extern gid_t our_gid;
extern char *usermap;
extern char *groupmap;
struct idlist *node;
union name_or_id noiu;
- if (uid == 0) /* don't map root */
- return NULL;
-
for (list = uidlist; list; list = list->next) {
if (list->id == uid)
return NULL;
struct idlist *node;
union name_or_id noiu;
- if (gid == 0) /* don't map root */
- return NULL;
-
for (list = gidlist; list; list = list->next) {
if (list->id == gid)
return NULL;
return node->u.name;
}
-/* send a complete uid/gid mapping to the peer */
-void send_id_list(int f)
+static void send_one_name(int f, id_t id, const char *name)
{
- struct idlist *list;
+ int len = strlen(name);
+ if (len > 255) /* Impossible? */
+ len = 255;
- if (preserve_uid || preserve_acls) {
- int len;
- /* we send sequences of uid/byte-length/name */
- for (list = uidlist; list; list = list->next) {
- if (!list->u.name)
- continue;
- len = strlen(list->u.name);
- write_varint30(f, list->id);
- write_byte(f, len);
- write_buf(f, list->u.name, len);
- }
+ write_varint30(f, id);
+ write_byte(f, len);
+ write_buf(f, name, len);
+}
- /* terminate the uid list with a 0 uid. We explicitly exclude
- * 0 from the list */
- write_varint30(f, 0);
+static void send_one_list(int f, struct idlist *idlist, int usernames)
+{
+ struct idlist *list;
+
+ /* we send sequences of id/byte-len/name */
+ for (list = idlist; list; list = list->next) {
+ if (list->id && list->u.name)
+ send_one_name(f, list->id, list->u.name);
}
- if (preserve_gid || preserve_acls) {
- int len;
- for (list = gidlist; list; list = list->next) {
- if (!list->u.name)
- continue;
- len = strlen(list->u.name);
- write_varint30(f, list->id);
- write_byte(f, len);
- write_buf(f, list->u.name, len);
- }
+ /* Terminate the uid list with 0 (which was excluded above).
+ * A modern rsync also sends the name of id 0. */
+ if (xmit_id0_names)
+ send_one_name(f, 0, usernames ? uid_to_user(0) : gid_to_group(0));
+ else
write_varint30(f, 0);
- }
+}
+
+/* send a complete uid/gid mapping to the peer */
+void send_id_lists(int f)
+{
+ if (preserve_uid || preserve_acls)
+ send_one_list(f, uidlist, 1);
+
+ if (preserve_gid || preserve_acls)
+ send_one_list(f, gidlist, 0);
}
uid_t recv_user_name(int f, uid_t uid)
/* read the uid list */
while ((id = read_varint30(f)) != 0)
recv_user_name(f, id);
+ if (xmit_id0_names)
+ recv_user_name(f, 0);
}
if ((preserve_gid || preserve_acls) && numeric_ids <= 0) {
/* read the gid list */
while ((id = read_varint30(f)) != 0)
recv_group_name(f, id, NULL);
+ if (xmit_id0_names)
+ recv_group_name(f, 0, NULL);
}
/* Now convert all the uids/gids from sender values to our values. */
*--cp = '\0'; /* replace comma */
}
- /* The 0 user/group doesn't get its name sent, so add it explicitly. */
- recv_add_id(idlist_ptr, *idmap_ptr, 0, numeric_ids ? NULL : usernames ? uid_to_user(0) : gid_to_group(0));
+ /* If the sender isn't going to xmit the id0 name, we assume it's "root". */
+ if (!xmit_id0_names)
+ recv_add_id(idlist_ptr, *idmap_ptr, 0, numeric_ids ? NULL : "root");
}
#ifdef HAVE_GETGROUPLIST