From: Wayne Davison Date: Mon, 6 Jul 2020 05:51:12 +0000 (-0700) Subject: Send the uid/gid 0 name since not all systems use 0 for root. X-Git-Tag: v3.2.3pre1~129 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bb16db1747e1119e3cbdbcee6d47ecd68def66cc;p=thirdparty%2Frsync.git Send the uid/gid 0 name since not all systems use 0 for root. --- diff --git a/compat.c b/compat.c index 527201ac..4719ef56 100644 --- a/compat.c +++ b/compat.c @@ -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 diff --git a/flist.c b/flist.c index 5970ce54..21c0b31a 100644 --- a/flist.c +++ b/flist.c @@ -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) diff --git a/options.c b/options.c index 956d6e33..5a372ae7 100644 --- a/options.c +++ b/options.c @@ -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 } diff --git a/uidlist.c b/uidlist.c index cf42f103..975636a8 100644 --- a/uidlist.c +++ b/uidlist.c @@ -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) { - 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) @@ -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