Skip to content

Commit bb16db1

Browse files
committed
Send the uid/gid 0 name since not all systems use 0 for root.
1 parent d6f0342 commit bb16db1

File tree

4 files changed

+46
-37
lines changed

4 files changed

+46
-37
lines changed

compat.c

+5
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ int want_xattr_optim = 0;
7373
int proper_seed_order = 0;
7474
int inplace_partial = 0;
7575
int do_negotiated_strings = 0;
76+
int xmit_id0_names = 0;
7677

7778
/* These index values are for the file-list's extra-attribute array. */
7879
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 = {
109110
#define CF_CHKSUM_SEED_FIX (1<<5)
110111
#define CF_INPLACE_PARTIAL_DIR (1<<6)
111112
#define CF_VARINT_FLIST_FLAGS (1<<7)
113+
#define CF_ID0_NAMES (1<<8)
112114

113115
static const char *client_info;
114116

@@ -694,6 +696,8 @@ void setup_protocol(int f_out,int f_in)
694696
compat_flags |= CF_CHKSUM_SEED_FIX;
695697
if (local_server || strchr(client_info, 'I') != NULL)
696698
compat_flags |= CF_INPLACE_PARTIAL_DIR;
699+
if (local_server || strchr(client_info, 'u') != NULL)
700+
compat_flags |= CF_ID0_NAMES;
697701
if (local_server || strchr(client_info, 'v') != NULL) {
698702
do_negotiated_strings = 1;
699703
compat_flags |= CF_VARINT_FLIST_FLAGS;
@@ -714,6 +718,7 @@ void setup_protocol(int f_out,int f_in)
714718
want_xattr_optim = protocol_version >= 31 && !(compat_flags & CF_AVOID_XATTR_OPTIM);
715719
proper_seed_order = compat_flags & CF_CHKSUM_SEED_FIX ? 1 : 0;
716720
xfer_flags_as_varint = compat_flags & CF_VARINT_FLIST_FLAGS ? 1 : 0;
721+
xmit_id0_names = compat_flags & CF_ID0_NAMES ? 1 : 0;
717722
if (am_sender) {
718723
receiver_symlink_times = am_server
719724
? strchr(client_info, 'L') != NULL

flist.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2412,7 +2412,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
24122412
file_old_total += flist->used;
24132413

24142414
if (numeric_ids <= 0 && !inc_recurse)
2415-
send_id_list(f);
2415+
send_id_lists(f);
24162416

24172417
/* send the io_error flag */
24182418
if (protocol_version < 30)

options.c

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

uidlist.c

+39-36
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ extern int preserve_uid;
3333
extern int preserve_gid;
3434
extern int preserve_acls;
3535
extern int numeric_ids;
36+
extern int xmit_id0_names;
3637
extern gid_t our_gid;
3738
extern char *usermap;
3839
extern char *groupmap;
@@ -295,9 +296,6 @@ const char *add_uid(uid_t uid)
295296
struct idlist *node;
296297
union name_or_id noiu;
297298

298-
if (uid == 0) /* don't map root */
299-
return NULL;
300-
301299
for (list = uidlist; list; list = list->next) {
302300
if (list->id == uid)
303301
return NULL;
@@ -315,9 +313,6 @@ const char *add_gid(gid_t gid)
315313
struct idlist *node;
316314
union name_or_id noiu;
317315

318-
if (gid == 0) /* don't map root */
319-
return NULL;
320-
321316
for (list = gidlist; list; list = list->next) {
322317
if (list->id == gid)
323318
return NULL;
@@ -328,40 +323,43 @@ const char *add_gid(gid_t gid)
328323
return node->u.name;
329324
}
330325

331-
/* send a complete uid/gid mapping to the peer */
332-
void send_id_list(int f)
326+
static void send_one_name(int f, id_t id, const char *name)
333327
{
334-
struct idlist *list;
328+
int len = strlen(name);
329+
if (len > 255) /* Impossible? */
330+
len = 255;
335331

336-
if (preserve_uid || preserve_acls) {
337-
int len;
338-
/* we send sequences of uid/byte-length/name */
339-
for (list = uidlist; list; list = list->next) {
340-
if (!list->u.name)
341-
continue;
342-
len = strlen(list->u.name);
343-
write_varint30(f, list->id);
344-
write_byte(f, len);
345-
write_buf(f, list->u.name, len);
346-
}
332+
write_varint30(f, id);
333+
write_byte(f, len);
334+
write_buf(f, name, len);
335+
}
347336

348-
/* terminate the uid list with a 0 uid. We explicitly exclude
349-
* 0 from the list */
350-
write_varint30(f, 0);
337+
static void send_one_list(int f, struct idlist *idlist, int usernames)
338+
{
339+
struct idlist *list;
340+
341+
/* we send sequences of id/byte-len/name */
342+
for (list = idlist; list; list = list->next) {
343+
if (list->id && list->u.name)
344+
send_one_name(f, list->id, list->u.name);
351345
}
352346

353-
if (preserve_gid || preserve_acls) {
354-
int len;
355-
for (list = gidlist; list; list = list->next) {
356-
if (!list->u.name)
357-
continue;
358-
len = strlen(list->u.name);
359-
write_varint30(f, list->id);
360-
write_byte(f, len);
361-
write_buf(f, list->u.name, len);
362-
}
347+
/* Terminate the uid list with 0 (which was excluded above).
348+
* A modern rsync also sends the name of id 0. */
349+
if (xmit_id0_names)
350+
send_one_name(f, 0, usernames ? uid_to_user(0) : gid_to_group(0));
351+
else
363352
write_varint30(f, 0);
364-
}
353+
}
354+
355+
/* send a complete uid/gid mapping to the peer */
356+
void send_id_lists(int f)
357+
{
358+
if (preserve_uid || preserve_acls)
359+
send_one_list(f, uidlist, 1);
360+
361+
if (preserve_gid || preserve_acls)
362+
send_one_list(f, gidlist, 0);
365363
}
366364

367365
uid_t recv_user_name(int f, uid_t uid)
@@ -405,12 +403,16 @@ void recv_id_list(int f, struct file_list *flist)
405403
/* read the uid list */
406404
while ((id = read_varint30(f)) != 0)
407405
recv_user_name(f, id);
406+
if (xmit_id0_names)
407+
recv_user_name(f, 0);
408408
}
409409

410410
if ((preserve_gid || preserve_acls) && numeric_ids <= 0) {
411411
/* read the gid list */
412412
while ((id = read_varint30(f)) != 0)
413413
recv_group_name(f, id, NULL);
414+
if (xmit_id0_names)
415+
recv_group_name(f, 0, NULL);
414416
}
415417

416418
/* Now convert all the uids/gids from sender values to our values. */
@@ -502,8 +504,9 @@ void parse_name_map(char *map, BOOL usernames)
502504
*--cp = '\0'; /* replace comma */
503505
}
504506

505-
/* The 0 user/group doesn't get its name sent, so add it explicitly. */
506-
recv_add_id(idlist_ptr, *idmap_ptr, 0, numeric_ids ? NULL : usernames ? uid_to_user(0) : gid_to_group(0));
507+
/* If the sender isn't going to xmit the id0 name, we assume it's "root". */
508+
if (!xmit_id0_names)
509+
recv_add_id(idlist_ptr, *idmap_ptr, 0, numeric_ids ? NULL : "root");
507510
}
508511

509512
#ifdef HAVE_GETGROUPLIST

0 commit comments

Comments
 (0)