X-Git-Url: https://mattmccutchen.net/rsync/rsync-patches.git/blobdiff_plain/4122278ddc1b8056d0168bf80a0205485ee49cfb..60a0edfe51f742c5689b8d19d52c8bad795e77c2:/usermap.diff diff --git a/usermap.diff b/usermap.diff index 3f04d26..03c233b 100644 --- a/usermap.diff +++ b/usermap.diff @@ -1,19 +1,42 @@ -This adds a --usermap and a --groupmap option. +This adds a --usermap and a --groupmap option. See the man page for +more details. -TODO: make this work when --numeric-ids was specified. +To use this patch, run these commands for a successful build: + + patch -p1 next) { -+ switch (list->id) { -+ case -2: -+ if (!wildmatch(list->name, name)) -+ continue; -+ break; -+ case -1: -+ if (strcmp(list->name, name) != 0) -+ continue; -+ break; -+ default: -+ if (list->id != (int)id) -+ continue; -+ break; -+ } -+ id2 = list->id2; -+ break; -+ } -+ if (!list) -+ id2 = id ? map_uid(id, name) : 0; /* don't map root */ -+ } else -+ id2 = id; ++ id_t id2; - node = add_to_list(&uidlist, (int)id, name, (int)id2); +- node = add_to_list(&uidlist, id, name, id2, 0); ++ if (!name) ++ name = ""; -@@ -174,8 +200,33 @@ static uid_t recv_add_uid(uid_t id, char - /* Add a gid to the list of gids. Only called on receiving side. */ - static gid_t recv_add_gid(gid_t id, char *name) - { -- gid_t id2 = name ? map_gid(id, name) : id; - struct idlist *node; -+ gid_t id2; -+ -+ if (name) { -+ struct idlist *list; -+ for (list = gidmap; list; list = list->next) { -+ switch (list->id) { -+ case -2: -+ if (!wildmatch(list->name, name)) -+ continue; -+ break; -+ case -1: -+ if (strcmp(list->name, name) != 0) -+ continue; -+ break; -+ default: -+ if (list->id != (int)id) -+ continue; -+ break; -+ } -+ id2 = list->id2; -+ break; +- if (verbose > 3) { +- rprintf(FINFO, "uid %u(%s) maps to %u\n", +- (unsigned)id, name ? name : "", (unsigned)id2); ++ for (node = *idmap_ptr; node; node = node->next) { ++ if (node->flags & NFLAGS_WILD_NAME_MATCH) { ++ if (!wildmatch(node->name, name)) ++ continue; ++ } else if (node->flags & NFLAGS_NAME_MATCH) { ++ if (strcmp(node->name, name) != 0) ++ continue; ++ } else { ++ if (node->id != id) ++ continue; ++ } ++ break; + } ++ if (node) ++ id2 = node->id2; ++ else if (*name && id) { ++ if (idmap_ptr == &uidmap) { ++ uid_t uid; ++ id2 = name_to_uid(name, &uid) ? uid : id; ++ } else { ++ gid_t gid; ++ id2 = name_to_gid(name, &gid) ? gid : id; + } -+ if (!list) -+ id2 = id ? map_gid(id, name) : 0; /* don't map root */ + } else -+ id2 = id; ++ id2 = id; + +- return node; +-} +- +-/* Add a gid to the list of gids. Only called on receiving side. */ +-static struct idlist *recv_add_gid(gid_t id, char *name) +-{ +- gid_t id2 = name ? map_gid(id, name) : id; +- struct idlist *node; +- +- node = add_to_list(&gidlist, id, name, id2, +- !am_root && !is_in_group(id2) ? FLAG_SKIP_GROUP : 0); ++ node = add_to_list(idmap_ptr, id, *name ? name : NULL, id2, ++ !am_root && idmap_ptr == &gidmap ++ && !is_in_group(id2) ? FLAG_SKIP_GROUP : 0); - if (!am_root && !is_in_group(id2)) - id2 = GID_NONE; -@@ -195,9 +246,6 @@ uid_t match_uid(uid_t uid) - static uid_t last_in, last_out; + if (verbose > 3) { +- rprintf(FINFO, "gid %u(%s) maps to %u\n", +- (unsigned)id, name ? name : "", (unsigned)id2); ++ rprintf(FINFO, "%sid %u(%s) maps to %u\n", ++ idmap_ptr == &uidmap ? "u" : "g", ++ (unsigned)id, name, (unsigned)id2); + } + + return node; +@@ -195,12 +200,9 @@ static struct idlist *recv_add_gid(gid_t + /* this function is a definate candidate for a faster algorithm */ + uid_t match_uid(uid_t uid) + { +- static uid_t last_in, last_out; ++ static uid_t last_in = -1, last_out = -1; struct idlist *list; - if (uid == 0) @@ -218,33 +304,78 @@ TODO: make this work when --numeric-ids was specified. if (uid == last_in) return last_out; -@@ -238,7 +286,7 @@ char *add_uid(uid_t uid) - struct idlist *list; - struct idlist *node; - -- if (uid == 0) /* don't map root */ -+ if (uid == 0 && protocol_version < 30) - return NULL; +@@ -208,10 +210,13 @@ uid_t match_uid(uid_t uid) for (list = uidlist; list; list = list->next) { -@@ -256,7 +304,7 @@ char *add_gid(gid_t gid) - struct idlist *list; - struct idlist *node; + if (list->id == uid) +- return last_out = list->id2; ++ break; + } -- if (gid == 0) /* don't map root */ -+ if (gid == 0 && protocol_version < 30) - return NULL; +- return last_out = uid; ++ if (!list) ++ list = recv_add_id(&uidmap, uid, NULL); ++ ++ return last_out = list->id2; + } - for (list = gidlist; list; list = list->next) { -@@ -356,3 +404,70 @@ void recv_uid_list(int f, struct file_li - F_GROUP(flist->files[i]) = match_gid(F_GID(flist->files[i])); + gid_t match_gid(gid_t gid, uint16 *flags_ptr) +@@ -227,7 +232,7 @@ gid_t match_gid(gid_t gid, uint16 *flags + break; + } + if (!list) +- list = recv_add_gid(gid, NULL); ++ list = recv_add_id(&gidmap, gid, NULL); + last = list; + } + +@@ -316,7 +321,7 @@ uid_t recv_user_name(int f, uid_t uid) + if (!name) + out_of_memory("recv_user_name"); + read_sbuf(f, name, len); +- node = recv_add_uid(uid, name); /* node keeps name's memory */ ++ node = recv_add_id(&uidmap, uid, name); /* node keeps name's memory */ + return node->id2; + } + +@@ -328,7 +333,7 @@ gid_t recv_group_name(int f, gid_t gid, + if (!name) + out_of_memory("recv_group_name"); + read_sbuf(f, name, len); +- node = recv_add_gid(gid, name); /* node keeps name's memory */ ++ node = recv_add_id(&gidmap, gid, name); /* node keeps name's memory */ + if (flags_ptr && node->flags & FLAG_SKIP_GROUP) + *flags_ptr |= FLAG_SKIP_GROUP; + return node->id2; +@@ -355,17 +360,96 @@ void recv_id_list(int f, struct file_lis + + /* Now convert all the uids/gids from sender values to our values. */ + #ifdef SUPPORT_ACLS +- if (preserve_acls && !numeric_ids) ++ if (preserve_acls && (!numeric_ids || usermap || groupmap)) + match_acl_ids(); + #endif +- if (am_root && preserve_uid && !numeric_ids) { ++ if (am_root && preserve_uid && (!numeric_ids || usermap)) { + for (i = 0; i < flist->used; i++) + F_OWNER(flist->files[i]) = match_uid(F_OWNER(flist->files[i])); + } +- if (preserve_gid && (!am_root || !numeric_ids)) { ++ if (preserve_gid && (!am_root || !numeric_ids || groupmap)) { + for (i = 0; i < flist->used; i++) { + F_GROUP(flist->files[i]) = match_gid(F_GROUP(flist->files[i]), + &flist->files[i]->flags); + } } } + +void parse_name_map(char *map, int usernames) +{ ++ struct idlist **idmap_ptr = usernames ? &uidmap : &gidmap; ++ struct idlist **idlist_ptr = usernames ? &uidlist : &gidlist; + char *colon, *end, *cp = map + strlen(map); -+ int id1, id2; ++ id_t id1, id2; ++ uint16 flags; + + while (1) { + end = cp; @@ -263,11 +394,15 @@ TODO: make this work when --numeric-ids was specified. + usernames ? "user" : "group", cp); + exit_cleanup(RERR_SYNTAX); + } ++ flags = 0; + id1 = atoi(cp); -+ } else if (strpbrk(cp, "*[?")) -+ id1 = -2; -+ else -+ id1 = -1; ++ } else if (strpbrk(cp, "*[?")) { ++ flags = NFLAGS_WILD_NAME_MATCH; ++ id1 = 0; ++ } else { ++ flags = NFLAGS_NAME_MATCH; ++ id1 = 0; ++ } + + if (isDigit(colon+1)) { + if (strspn(colon+1, "0123456789") != (size_t)(end - colon - 1)) { @@ -278,32 +413,37 @@ TODO: make this work when --numeric-ids was specified. + } else { + if (usernames) { + uid_t uid; -+ if (name_to_uid(colon+1, &uid)) -+ id2 = (int)uid; -+ else -+ id2 = -1; ++ if (!name_to_uid(colon+1, &uid)) { ++ bad_name: ++ rprintf(FERROR, ++ "Invalid name in --%smap: %s\n", ++ usernames ? "user" : "group", ++ colon+1); ++ exit_cleanup(RERR_SYNTAX); ++ } ++ id2 = uid; + } else { + gid_t gid; -+ if (name_to_gid(colon+1, &gid)) -+ id2 = (int)gid; -+ else -+ id2 = -1; -+ } -+ if (id2 < 0) { -+ rprintf(FERROR, "Invalid name in --%smap: %s\n", -+ usernames ? "user" : "group", colon+1); -+ exit_cleanup(RERR_SYNTAX); ++ if (!name_to_gid(colon+1, &gid)) ++ goto bad_name; ++ id2 = gid; + } + } + -+ if (usernames) -+ add_to_list(&uidmap, id1, id1 < 0 ? cp : NULL, id2); -+ else -+ add_to_list(&gidmap, id1, id1 < 0 ? cp : NULL, id2); ++ add_to_list(idmap_ptr, id1, flags ? cp : NULL, id2, flags); ++ if (numeric_ids && !flags) ++ add_to_list(idlist_ptr, id1, NULL, id2, flags); + + if (cp == map) + break; + + *--cp = '\0'; /* replace comma */ + } ++ ++ /* The 0 user/group doesn't get its name sent, or add it explicitly. */ ++ if (numeric_ids) ++ cp = NULL; ++ else ++ cp = usernames ? uid_to_name(0) : gid_to_name(0); ++ recv_add_id(idmap_ptr, 0, cp); +}