+
+void parse_name_map(char *map, BOOL usernames)
+{
+ struct idlist **idmap_ptr = usernames ? &uidmap : &gidmap;
+ struct idlist **idlist_ptr = usernames ? &uidlist : &gidlist;
+ char *colon, *end, *name, *cp = map + strlen(map);
+ id_t id1;
+ uint16 flags;
+
+ /* Parse the list in reverse, so the order in the struct is right. */
+ while (1) {
+ end = cp;
+ while (cp > map && cp[-1] != ',') cp--;
+ if (!(colon = strchr(cp, ':'))) {
+ rprintf(FERROR, "No colon found in --%smap: %s\n",
+ usernames ? "user" : "group", cp);
+ exit_cleanup(RERR_SYNTAX);
+ }
+ if (!colon[1]) {
+ rprintf(FERROR, "No name found after colon --%smap: %s\n",
+ usernames ? "user" : "group", cp);
+ exit_cleanup(RERR_SYNTAX);
+ }
+ *colon = '\0';
+
+ if (isDigit(cp)) {
+ char *dash = strchr(cp, '-');
+ if (strspn(cp, "0123456789-") != (size_t)(colon - cp)
+ || (dash && (!dash[1] || strchr(dash+1, '-')))) {
+ rprintf(FERROR, "Invalid number in --%smap: %s\n",
+ usernames ? "user" : "group", cp);
+ exit_cleanup(RERR_SYNTAX);
+ }
+ if (dash)
+ name = (char *)atol(dash+1);
+ else
+ name = (char *)0;
+ flags = 0;
+ id1 = atol(cp);
+ } else if (strpbrk(cp, "*[?")) {
+ flags = NFLAGS_WILD_NAME_MATCH;
+ name = cp;
+ id1 = 0;
+ } else {
+ flags = NFLAGS_NAME_MATCH;
+ name = cp;
+ id1 = 0;
+ }
+
+ if (usernames) {
+ uid_t uid;
+ if (user_to_uid(colon+1, &uid, True))
+ add_to_list(idmap_ptr, id1, name, uid, flags);
+ else {
+ rprintf(FERROR,
+ "Unknown --usermap name on receiver: %s\n",
+ colon+1);
+ }
+ } else {
+ gid_t gid;
+ if (group_to_gid(colon+1, &gid, True))
+ add_to_list(idmap_ptr, id1, name, gid, flags);
+ else {
+ rprintf(FERROR,
+ "Unknown --groupmap name on receiver: %s\n",
+ colon+1);
+ }
+ }
+
+ if (cp == map)
+ break;
+
+ *--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));
+}
+
+#ifdef HAVE_GETGROUPLIST
+const char *getallgroups(uid_t uid, gid_t *gid_list, int *size_ptr)
+{
+ struct passwd *pw;
+ if ((pw = getpwuid(uid)) == NULL)
+ return "getpwuid failed";
+ /* Get all the process's groups, with the pw_gid group first. */
+ if (getgrouplist(pw->pw_name, pw->pw_gid, gid_list, size_ptr) < 0)
+ return "getgrouplist failed";
+ /* Paranoia: is the default group not first in the list? */
+ if (gid_list[0] != pw->pw_gid) {
+ int j;
+ for (j = 0; j < *size_ptr; j++) {
+ if (gid_list[j] == pw->pw_gid) {
+ gid_list[j] = gid_list[0];
+ gid_list[0] = pw->pw_gid;
+ break;
+ }
+ }
+ }
+ return NULL;
+}
+#endif