Commit | Line | Data |
---|---|---|
409bd73e WD |
1 | This adds a --usermap and a --groupmap option. See the man page for |
2 | more details. | |
4122278d | 3 | |
409bd73e WD |
4 | To use this patch, run these commands for a successful build: |
5 | ||
6 | patch -p1 <patches/usermap.diff | |
7 | ./configure (optional if already run) | |
8 | make | |
4122278d WD |
9 | |
10 | --- old/flist.c | |
11 | +++ new/flist.c | |
c8a8b4a7 | 12 | @@ -63,6 +63,8 @@ extern int copy_links; |
4122278d WD |
13 | extern int copy_unsafe_links; |
14 | extern int protocol_version; | |
15 | extern int sanitize_paths; | |
16 | +extern char *usermap; | |
17 | +extern char *groupmap; | |
18 | extern struct stats stats; | |
c8a8b4a7 | 19 | extern char *filesfrom_host; |
4122278d | 20 | |
c8a8b4a7 | 21 | @@ -733,7 +735,7 @@ static struct file_struct *recv_file_ent |
409bd73e | 22 | uid = (uid_t)read_varint(f); |
6a189d36 | 23 | if (xflags & XMIT_USER_NAME_FOLLOWS) |
409bd73e WD |
24 | uid = recv_user_name(f, uid); |
25 | - else if (inc_recurse && am_root && !numeric_ids) | |
f62e6e48 | 26 | + else if (inc_recurse && am_root && (!numeric_ids || usermap)) |
409bd73e WD |
27 | uid = match_uid(uid); |
28 | } | |
29 | } | |
c8a8b4a7 | 30 | @@ -745,7 +747,7 @@ static struct file_struct *recv_file_ent |
761f1b71 | 31 | gid_flags = 0; |
6a189d36 | 32 | if (xflags & XMIT_GROUP_NAME_FOLLOWS) |
761f1b71 | 33 | gid = recv_group_name(f, gid, &gid_flags); |
409bd73e | 34 | - else if (inc_recurse && (!am_root || !numeric_ids)) |
f62e6e48 | 35 | + else if (inc_recurse && (!am_root || !numeric_ids || groupmap)) |
761f1b71 | 36 | gid = match_gid(gid, &gid_flags); |
409bd73e WD |
37 | } |
38 | } | |
c8a8b4a7 | 39 | @@ -2045,8 +2047,13 @@ struct file_list *recv_file_list(int f) |
4122278d WD |
40 | int dstart, flags; |
41 | int64 start_read; | |
42 | ||
43 | - if (!first_flist) | |
44 | + if (!first_flist) { | |
45 | rprintf(FLOG, "receiving file list\n"); | |
46 | + if (usermap) | |
47 | + parse_name_map(usermap, 1); | |
48 | + if (groupmap) | |
49 | + parse_name_map(groupmap, 0); | |
50 | + } | |
51 | if (show_filelist_p()) | |
52 | start_filelist_progress("receiving file list"); | |
53 | else if (inc_recurse && verbose && !am_server && !first_flist) | |
54 | --- old/options.c | |
55 | +++ new/options.c | |
c8a8b4a7 | 56 | @@ -164,6 +164,8 @@ char *rsync_path = RSYNC_PATH; |
4122278d WD |
57 | char *backup_dir = NULL; |
58 | char backup_dir_buf[MAXPATHLEN]; | |
59 | char *sockopts = NULL; | |
60 | +char *usermap = NULL; | |
61 | +char *groupmap = NULL; | |
62 | int rsync_port = 0; | |
63 | int compare_dest = 0; | |
64 | int copy_dest = 0; | |
c8a8b4a7 | 65 | @@ -377,6 +379,8 @@ void usage(enum logcode F) |
4122278d WD |
66 | rprintf(F," --delay-updates put all updated files into place at transfer's end\n"); |
67 | rprintf(F," -m, --prune-empty-dirs prune empty directory chains from the file-list\n"); | |
68 | rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n"); | |
69 | + rprintf(F," --usermap=STRING custom username mapping\n"); | |
70 | + rprintf(F," --groupmap=STRING custom groupname mapping\n"); | |
71 | rprintf(F," --timeout=TIME set I/O timeout in seconds\n"); | |
72 | rprintf(F," -I, --ignore-times don't skip files that match in size and mod-time\n"); | |
73 | rprintf(F," --size-only skip files that match in size\n"); | |
c8a8b4a7 WD |
74 | @@ -601,6 +605,8 @@ static struct poptOption long_options[] |
75 | {"no-s", 0, POPT_ARG_VAL, &protect_args, 0, 0, 0}, | |
6cbbe66d WD |
76 | {"numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 1, 0, 0 }, |
77 | {"no-numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 0, 0, 0 }, | |
4122278d WD |
78 | + {"usermap", 0, POPT_ARG_STRING, &usermap, 0, 0, 0 }, |
79 | + {"groupmap", 0, POPT_ARG_STRING, &groupmap, 0, 0, 0 }, | |
80 | {"timeout", 0, POPT_ARG_INT, &io_timeout, 0, 0, 0 }, | |
6cbbe66d | 81 | {"no-timeout", 0, POPT_ARG_VAL, &io_timeout, 0, 0, 0 }, |
4122278d | 82 | {"rsh", 'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 }, |
c8a8b4a7 WD |
83 | @@ -1935,6 +1941,18 @@ void server_options(char **args, int *ar |
84 | args[ac++] = "--no-i-r"; | |
4122278d WD |
85 | |
86 | if (am_sender) { | |
87 | + if (usermap) { | |
f62e6e48 | 88 | + if (asprintf(&arg, "--usermap=%s", usermap) < 0) |
4122278d WD |
89 | + goto oom; |
90 | + args[ac++] = arg; | |
91 | + } | |
92 | + | |
93 | + if (groupmap) { | |
f62e6e48 | 94 | + if (asprintf(&arg, "--groupmap=%s", groupmap) < 0) |
4122278d WD |
95 | + goto oom; |
96 | + args[ac++] = arg; | |
97 | + } | |
98 | + | |
99 | if (ignore_existing) | |
100 | args[ac++] = "--ignore-existing"; | |
101 | ||
102 | --- old/rsync.yo | |
103 | +++ new/rsync.yo | |
c8a8b4a7 | 104 | @@ -379,6 +379,8 @@ to the detailed description below for a |
4122278d WD |
105 | --delay-updates put all updated files into place at end |
106 | -m, --prune-empty-dirs prune empty directory chains from file-list | |
107 | --numeric-ids don't map uid/gid values by user/group name | |
108 | + --usermap=STRING custom username mapping | |
109 | + --groupmap=STRING custom groupname mapping | |
110 | --timeout=TIME set I/O timeout in seconds | |
111 | -I, --ignore-times don't skip files that match size and time | |
112 | --size-only skip files that match in size | |
c8a8b4a7 | 113 | @@ -1553,6 +1555,46 @@ from the source system is used instead. |
4122278d WD |
114 | the chroot setting affects rsync's ability to look up the names of the |
115 | users and groups and what you can do about it. | |
116 | ||
117 | +dit(bf(--usermap=STRING, --groupmap=STRING)) These options allow you to | |
409bd73e WD |
118 | +specify users and groups that should be mapped to other values by the |
119 | +receiving side. The bf(STRING) is one or more bf(FROM):bf(TO) pairs of | |
120 | +values separated by commas. Any matching bf(FROM) value from the sender is | |
121 | +replaced with a bf(TO) value from the receiver. You may specify usernames | |
122 | +or user IDs for the bf(FROM) and bf(TO) values, and the bf(FROM) value may | |
123 | +also be a wild-card string, which will be matched against the sender's | |
f62e6e48 | 124 | +names (wild-cards do NOT match against ID numbers). For example: |
409bd73e | 125 | + |
f62e6e48 | 126 | +verb( --usermap=0:bin,wayne:admin,*:nobody --groupmap=usr:1,1:usr) |
409bd73e WD |
127 | + |
128 | +The first match in the list is the one that is used. You should not use | |
129 | +multiple options of the same type, but instead include all the user | |
130 | +mappings you need separated by commas to a single bf(--usermap) option, | |
131 | +and likewise for groups with the bf(--groupmap) option. | |
4122278d | 132 | + |
9405aad3 | 133 | +Note that the sender's name for the 0 user and group are not transmitted |
409bd73e WD |
134 | +to the receiver, so you should either match these values using a 0, or use |
135 | +the names in effect on the receiving side. All other bf(FROM) names match | |
9405aad3 WD |
136 | +those in use on the sending side. All bf(TO) names match those in use on |
137 | +the receiving side. | |
4122278d | 138 | + |
9405aad3 WD |
139 | +Any IDs that do not have name on the sending side are treaded as having an |
140 | +empty name for the purpose of matching. This allows them to be matched via | |
141 | +a "*" as well as an empty name mapping. For instance: | |
142 | + | |
143 | +verb( --usermap=:nobody --groupmap=*:nobody) | |
144 | + | |
145 | +When the bf(--numeric-ids) option is used,the sender does not send any | |
146 | +names, so all the IDs are treaded as having an empty name. This means that | |
147 | +you will need to specify numeric bf(FROM) values if you want to map these | |
148 | +nameless IDs to different values. | |
4122278d | 149 | + |
409bd73e WD |
150 | +For the bf(--usermap) option to have any effect, the bf(-o) (bf(--owner)) |
151 | +option must be used (or implied), and the receiver will need to be running | |
9405aad3 | 152 | +as a super-user (see also the bf(--fake-super) option). For the bf(--groupmap) |
409bd73e WD |
153 | +option to have any effect, the bf(-g) (bf(--groups)) option must be used |
154 | +(or implied), and the receiver will need to have permissions to set that | |
155 | +group. | |
4122278d WD |
156 | + |
157 | dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum I/O | |
158 | timeout in seconds. If no data is transferred for the specified time | |
159 | then rsync will exit. The default is 0, which means no timeout. | |
160 | --- old/uidlist.c | |
161 | +++ new/uidlist.c | |
c82285d5 WD |
162 | @@ -24,6 +24,7 @@ |
163 | * are special. */ | |
164 | ||
165 | #include "rsync.h" | |
166 | +#include "ifuncs.h" | |
167 | #include "io.h" | |
168 | ||
169 | extern int verbose; | |
170 | @@ -32,6 +33,8 @@ extern int preserve_uid; | |
4122278d WD |
171 | extern int preserve_gid; |
172 | extern int preserve_acls; | |
173 | extern int numeric_ids; | |
409bd73e WD |
174 | +extern char *usermap; |
175 | +extern char *groupmap; | |
4122278d | 176 | |
6a189d36 WD |
177 | #ifdef HAVE_GETGROUPS |
178 | # ifndef GETGROUPS_T | |
c82285d5 | 179 | @@ -41,6 +44,9 @@ extern int numeric_ids; |
6a189d36 WD |
180 | |
181 | #define GID_NONE ((gid_t)-1) | |
182 | ||
183 | +#define NFLAGS_WILD_NAME_MATCH (1<<0) | |
184 | +#define NFLAGS_NAME_MATCH (1<<1) | |
185 | + | |
4122278d WD |
186 | struct idlist { |
187 | struct idlist *next; | |
4122278d | 188 | char *name; |
c82285d5 | 189 | @@ -48,8 +54,8 @@ struct idlist { |
6a189d36 | 190 | uint16 flags; |
4122278d WD |
191 | }; |
192 | ||
193 | -static struct idlist *uidlist; | |
194 | -static struct idlist *gidlist; | |
195 | +static struct idlist *uidlist, *uidmap; | |
196 | +static struct idlist *gidlist, *gidmap; | |
197 | ||
6a189d36 WD |
198 | static struct idlist *add_to_list(struct idlist **root, id_t id, char *name, |
199 | id_t id2, uint16 flags) | |
c82285d5 | 200 | @@ -84,22 +90,6 @@ static char *gid_to_name(gid_t gid) |
9405aad3 WD |
201 | return NULL; |
202 | } | |
203 | ||
204 | -static uid_t map_uid(uid_t id, char *name) | |
205 | -{ | |
206 | - uid_t uid; | |
207 | - if (id != 0 && name_to_uid(name, &uid)) | |
208 | - return uid; | |
209 | - return id; | |
210 | -} | |
211 | - | |
212 | -static gid_t map_gid(gid_t id, char *name) | |
213 | -{ | |
214 | - gid_t gid; | |
215 | - if (id != 0 && name_to_gid(name, &gid)) | |
216 | - return gid; | |
217 | - return id; | |
218 | -} | |
219 | - | |
220 | static int is_in_group(gid_t gid) | |
221 | { | |
222 | #ifdef HAVE_GETGROUPS | |
c82285d5 | 223 | @@ -159,34 +149,49 @@ static int is_in_group(gid_t gid) |
9405aad3 WD |
224 | #endif |
225 | } | |
226 | ||
227 | -/* Add a uid to the list of uids. Only called on receiving side. */ | |
6a189d36 | 228 | -static struct idlist *recv_add_uid(uid_t id, char *name) |
9405aad3 | 229 | +/* Add a uid/gid to its list of ids. Only called on receiving side. */ |
6a189d36 | 230 | +static struct idlist *recv_add_id(struct idlist **idmap_ptr, id_t id, char *name) |
4122278d WD |
231 | { |
232 | - uid_t id2 = name ? map_uid(id, name) : id; | |
233 | struct idlist *node; | |
6a189d36 | 234 | + id_t id2; |
409bd73e | 235 | |
6a189d36 | 236 | - node = add_to_list(&uidlist, id, name, id2, 0); |
409bd73e WD |
237 | + if (!name) |
238 | + name = ""; | |
4122278d | 239 | |
9405aad3 | 240 | - if (verbose > 3) { |
6a189d36 WD |
241 | - rprintf(FINFO, "uid %u(%s) maps to %u\n", |
242 | - (unsigned)id, name ? name : "", (unsigned)id2); | |
9405aad3 | 243 | + for (node = *idmap_ptr; node; node = node->next) { |
6a189d36 | 244 | + if (node->flags & NFLAGS_WILD_NAME_MATCH) { |
409bd73e WD |
245 | + if (!wildmatch(node->name, name)) |
246 | + continue; | |
6a189d36 | 247 | + } else if (node->flags & NFLAGS_NAME_MATCH) { |
409bd73e WD |
248 | + if (strcmp(node->name, name) != 0) |
249 | + continue; | |
6a189d36 | 250 | + } else { |
9405aad3 | 251 | + if (node->id != id) |
409bd73e | 252 | + continue; |
4122278d | 253 | + } |
409bd73e | 254 | + break; |
9405aad3 | 255 | } |
409bd73e WD |
256 | + if (node) |
257 | + id2 = node->id2; | |
9405aad3 WD |
258 | + else if (*name && id) { |
259 | + if (idmap_ptr == &uidmap) { | |
260 | + uid_t uid; | |
6a189d36 | 261 | + id2 = name_to_uid(name, &uid) ? uid : id; |
9405aad3 WD |
262 | + } else { |
263 | + gid_t gid; | |
6a189d36 | 264 | + id2 = name_to_gid(name, &gid) ? gid : id; |
9405aad3 WD |
265 | + } |
266 | + } else | |
409bd73e | 267 | + id2 = id; |
4122278d | 268 | |
6a189d36 | 269 | - return node; |
9405aad3 WD |
270 | -} |
271 | - | |
272 | -/* Add a gid to the list of gids. Only called on receiving side. */ | |
6a189d36 | 273 | -static struct idlist *recv_add_gid(gid_t id, char *name) |
9405aad3 WD |
274 | -{ |
275 | - gid_t id2 = name ? map_gid(id, name) : id; | |
276 | - struct idlist *node; | |
277 | - | |
6a189d36 WD |
278 | - node = add_to_list(&gidlist, id, name, id2, |
279 | - !am_root && !is_in_group(id2) ? FLAG_SKIP_GROUP : 0); | |
280 | + node = add_to_list(idmap_ptr, id, *name ? name : NULL, id2, | |
281 | + !am_root && idmap_ptr == &gidmap | |
282 | + && !is_in_group(id2) ? FLAG_SKIP_GROUP : 0); | |
409bd73e WD |
283 | |
284 | if (verbose > 3) { | |
6a189d36 WD |
285 | - rprintf(FINFO, "gid %u(%s) maps to %u\n", |
286 | - (unsigned)id, name ? name : "", (unsigned)id2); | |
287 | + rprintf(FINFO, "%sid %u(%s) maps to %u\n", | |
288 | + idmap_ptr == &uidmap ? "u" : "g", | |
289 | + (unsigned)id, name, (unsigned)id2); | |
409bd73e WD |
290 | } |
291 | ||
6a189d36 | 292 | return node; |
c82285d5 | 293 | @@ -195,12 +200,9 @@ static struct idlist *recv_add_gid(gid_t |
409bd73e WD |
294 | /* this function is a definate candidate for a faster algorithm */ |
295 | uid_t match_uid(uid_t uid) | |
296 | { | |
297 | - static uid_t last_in, last_out; | |
298 | + static uid_t last_in = -1, last_out = -1; | |
4122278d WD |
299 | struct idlist *list; |
300 | ||
301 | - if (uid == 0) | |
302 | - return 0; | |
303 | - | |
304 | if (uid == last_in) | |
305 | return last_out; | |
306 | ||
c82285d5 | 307 | @@ -208,10 +210,13 @@ uid_t match_uid(uid_t uid) |
6a189d36 WD |
308 | |
309 | for (list = uidlist; list; list = list->next) { | |
310 | if (list->id == uid) | |
311 | - return last_out = list->id2; | |
312 | + break; | |
409bd73e | 313 | } |
4122278d | 314 | |
409bd73e | 315 | - return last_out = uid; |
6a189d36 WD |
316 | + if (!list) |
317 | + list = recv_add_id(&uidmap, uid, NULL); | |
318 | + | |
319 | + return last_out = list->id2; | |
409bd73e | 320 | } |
4122278d | 321 | |
6a189d36 | 322 | gid_t match_gid(gid_t gid, uint16 *flags_ptr) |
c82285d5 | 323 | @@ -227,7 +232,7 @@ gid_t match_gid(gid_t gid, uint16 *flags |
761f1b71 WD |
324 | break; |
325 | } | |
326 | if (!list) | |
8f1c03c8 WD |
327 | - list = recv_add_gid(gid, NULL); |
328 | + list = recv_add_id(&gidmap, gid, NULL); | |
761f1b71 | 329 | last = list; |
9405aad3 WD |
330 | } |
331 | ||
c82285d5 | 332 | @@ -316,7 +321,7 @@ uid_t recv_user_name(int f, uid_t uid) |
9405aad3 WD |
333 | if (!name) |
334 | out_of_memory("recv_user_name"); | |
335 | read_sbuf(f, name, len); | |
6a189d36 WD |
336 | - node = recv_add_uid(uid, name); /* node keeps name's memory */ |
337 | + node = recv_add_id(&uidmap, uid, name); /* node keeps name's memory */ | |
338 | return node->id2; | |
9405aad3 WD |
339 | } |
340 | ||
c82285d5 | 341 | @@ -328,7 +333,7 @@ gid_t recv_group_name(int f, gid_t gid, |
9405aad3 WD |
342 | if (!name) |
343 | out_of_memory("recv_group_name"); | |
344 | read_sbuf(f, name, len); | |
6a189d36 WD |
345 | - node = recv_add_gid(gid, name); /* node keeps name's memory */ |
346 | + node = recv_add_id(&gidmap, gid, name); /* node keeps name's memory */ | |
347 | if (flags_ptr && node->flags & FLAG_SKIP_GROUP) | |
348 | *flags_ptr |= FLAG_SKIP_GROUP; | |
349 | return node->id2; | |
c82285d5 | 350 | @@ -355,17 +360,96 @@ void recv_id_list(int f, struct file_lis |
4122278d | 351 | |
409bd73e WD |
352 | /* Now convert all the uids/gids from sender values to our values. */ |
353 | #ifdef SUPPORT_ACLS | |
354 | - if (preserve_acls && !numeric_ids) | |
6a189d36 | 355 | + if (preserve_acls && (!numeric_ids || usermap || groupmap)) |
409bd73e WD |
356 | match_acl_ids(); |
357 | #endif | |
358 | - if (am_root && preserve_uid && !numeric_ids) { | |
359 | + if (am_root && preserve_uid && (!numeric_ids || usermap)) { | |
9c85142a | 360 | for (i = 0; i < flist->used; i++) |
6a189d36 | 361 | F_OWNER(flist->files[i]) = match_uid(F_OWNER(flist->files[i])); |
409bd73e WD |
362 | } |
363 | - if (preserve_gid && (!am_root || !numeric_ids)) { | |
364 | + if (preserve_gid && (!am_root || !numeric_ids || groupmap)) { | |
9c85142a | 365 | for (i = 0; i < flist->used; i++) { |
6a189d36 WD |
366 | F_GROUP(flist->files[i]) = match_gid(F_GROUP(flist->files[i]), |
367 | &flist->files[i]->flags); | |
368 | } | |
4122278d WD |
369 | } |
370 | } | |
371 | + | |
372 | +void parse_name_map(char *map, int usernames) | |
373 | +{ | |
9405aad3 WD |
374 | + struct idlist **idmap_ptr = usernames ? &uidmap : &gidmap; |
375 | + struct idlist **idlist_ptr = usernames ? &uidlist : &gidlist; | |
4122278d | 376 | + char *colon, *end, *cp = map + strlen(map); |
6a189d36 WD |
377 | + id_t id1, id2; |
378 | + uint16 flags; | |
4122278d WD |
379 | + |
380 | + while (1) { | |
381 | + end = cp; | |
382 | + while (cp > map && cp[-1] != ',') cp--; | |
383 | + if (!(colon = strchr(cp, ':'))) { | |
384 | + rprintf(FERROR, "No colon found in --%smap: %s\n", | |
385 | + usernames ? "user" : "group", cp); | |
386 | + exit_cleanup(RERR_SYNTAX); | |
387 | + } | |
388 | + *colon = '\0'; | |
389 | + | |
390 | + if (isDigit(cp)) { | |
391 | + if (strspn(cp, "0123456789") != (size_t)(colon - cp)) { | |
392 | + bad_number: | |
393 | + rprintf(FERROR, "Invalid number in --%smap: %s\n", | |
394 | + usernames ? "user" : "group", cp); | |
395 | + exit_cleanup(RERR_SYNTAX); | |
396 | + } | |
6a189d36 | 397 | + flags = 0; |
4122278d | 398 | + id1 = atoi(cp); |
6a189d36 WD |
399 | + } else if (strpbrk(cp, "*[?")) { |
400 | + flags = NFLAGS_WILD_NAME_MATCH; | |
401 | + id1 = 0; | |
402 | + } else { | |
403 | + flags = NFLAGS_NAME_MATCH; | |
404 | + id1 = 0; | |
405 | + } | |
4122278d WD |
406 | + |
407 | + if (isDigit(colon+1)) { | |
408 | + if (strspn(colon+1, "0123456789") != (size_t)(end - colon - 1)) { | |
409 | + cp = colon+1; | |
410 | + goto bad_number; | |
411 | + } | |
412 | + id2 = atoi(colon+1); | |
413 | + } else { | |
414 | + if (usernames) { | |
415 | + uid_t uid; | |
9405aad3 WD |
416 | + if (!name_to_uid(colon+1, &uid)) { |
417 | + bad_name: | |
418 | + rprintf(FERROR, | |
419 | + "Invalid name in --%smap: %s\n", | |
420 | + usernames ? "user" : "group", | |
421 | + colon+1); | |
422 | + exit_cleanup(RERR_SYNTAX); | |
423 | + } | |
6a189d36 | 424 | + id2 = uid; |
4122278d WD |
425 | + } else { |
426 | + gid_t gid; | |
9405aad3 WD |
427 | + if (!name_to_gid(colon+1, &gid)) |
428 | + goto bad_name; | |
6a189d36 | 429 | + id2 = gid; |
4122278d WD |
430 | + } |
431 | + } | |
432 | + | |
6a189d36 WD |
433 | + add_to_list(idmap_ptr, id1, flags ? cp : NULL, id2, flags); |
434 | + if (numeric_ids && !flags) | |
435 | + add_to_list(idlist_ptr, id1, NULL, id2, flags); | |
4122278d WD |
436 | + |
437 | + if (cp == map) | |
438 | + break; | |
439 | + | |
440 | + *--cp = '\0'; /* replace comma */ | |
441 | + } | |
409bd73e | 442 | + |
6a189d36 | 443 | + /* The 0 user/group doesn't get its name sent, or add it explicitly. */ |
9405aad3 WD |
444 | + if (numeric_ids) |
445 | + cp = NULL; | |
446 | + else | |
447 | + cp = usernames ? uid_to_name(0) : gid_to_name(0); | |
448 | + recv_add_id(idmap_ptr, 0, cp); | |
4122278d | 449 | +} |