Send the uid/gid 0 name since not all systems use 0 for root.

This commit is contained in:
Wayne Davison
2020-07-05 22:51:12 -07:00
parent d6f0342a34
commit bb16db1747
4 changed files with 46 additions and 37 deletions

View File

@@ -73,6 +73,7 @@ int want_xattr_optim = 0;
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;
@@ -109,6 +110,7 @@ struct name_num_obj valid_compressions = {
#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;
@@ -694,6 +696,8 @@ void setup_protocol(int f_out,int f_in)
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;
@@ -714,6 +718,7 @@ void setup_protocol(int f_out,int f_in)
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

View File

@@ -2412,7 +2412,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
file_old_total += flist->used;
if (numeric_ids <= 0 && !inc_recurse)
send_id_list(f);
send_id_lists(f);
/* send the io_error flag */
if (protocol_version < 30)

View File

@@ -2608,6 +2608,7 @@ void server_options(char **args, int *argc_p)
eFlags[x++] = 'C'; /* support checksum seed order fix */
eFlags[x++] = 'I'; /* support inplace_partial behavior */
eFlags[x++] = 'v'; /* use varint for flist & compat flags; negotiate checksum */
eFlags[x++] = 'u'; /* include name of uid 0 & gid 0 in the id map */
/* NOTE: Avoid using 'V' -- it was the high bit of a write_byte() that became write_varint(). */
#undef eFlags
}

View File

@@ -33,6 +33,7 @@ extern int preserve_uid;
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;
@@ -295,9 +296,6 @@ const char *add_uid(uid_t uid)
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;
@@ -315,9 +313,6 @@ const char *add_gid(gid_t gid)
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;
@@ -328,40 +323,43 @@ const char *add_gid(gid_t gid)
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)
{
int len = strlen(name);
if (len > 255) /* Impossible? */
len = 255;
write_varint30(f, id);
write_byte(f, len);
write_buf(f, name, len);
}
static void send_one_list(int f, struct idlist *idlist, int usernames)
{
struct idlist *list;
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);
}
/* terminate the uid list with a 0 uid. We explicitly exclude
* 0 from the list */
write_varint30(f, 0);
/* 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)
@@ -405,12 +403,16 @@ void recv_id_list(int f, struct file_list *flist)
/* 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. */
@@ -502,8 +504,9 @@ void parse_name_map(char *map, BOOL usernames)
*--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