X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/b66d00853b71bf852a2dcdecb97348a9ec1818ad..1c3344a105f656a45f6b46e1710c3fc4ab862a9a:/uidlist.c diff --git a/uidlist.c b/uidlist.c index 5baf952f..2503d8a8 100644 --- a/uidlist.c +++ b/uidlist.c @@ -1,41 +1,42 @@ /* - Copyright (C) Andrew Tridgell 1996 - Copyright (C) Paul Mackerras 1996 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* handle the mapping of uid/gid and user/group names between systems. - If the source username/group does not exist on the target then use - the numeric IDs. Never do any mapping for uid=0 or gid=0 as these - are special. -*/ + * Handle the mapping of uid/gid and user/group names between systems. + * + * Copyright (C) 1996 Andrew Tridgell + * Copyright (C) 1996 Paul Mackerras + * Copyright (C) 2004-2007 Wayne Davison + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* If the source username/group does not exist on the target then use + * the numeric IDs. Never do any mapping for uid=0 or gid=0 as these + * are special. */ #include "rsync.h" #ifdef HAVE_GETGROUPS -# if !defined(GETGROUPS_T) +# ifndef GETGROUPS_T # define GETGROUPS_T gid_t # endif #endif extern int verbose; +extern int am_root; extern int preserve_uid; extern int preserve_gid; +extern int preserve_acls; extern int numeric_ids; -extern int am_root; struct idlist { struct idlist *next; @@ -78,7 +79,7 @@ static char *gid_to_name(gid_t gid) return NULL; } -static int map_uid(int id, char *name) +static uid_t map_uid(uid_t id, char *name) { uid_t uid; if (id != 0 && name_to_uid(name, &uid)) @@ -86,7 +87,7 @@ static int map_uid(int id, char *name) return id; } -static int map_gid(int id, char *name) +static gid_t map_gid(gid_t id, char *name) { gid_t gid; if (id != 0 && name_to_gid(name, &gid)) @@ -125,12 +126,10 @@ static int is_in_group(gid_t gid) char *gidbuf = new_array(char, ngroups*21+32); if (!gidbuf) out_of_memory("is_in_group"); - sprintf(gidbuf, "process has %d gid%s: ", - ngroups, ngroups == 1? "" : "s"); - pos = strlen(gidbuf); + pos = snprintf(gidbuf, 32, "process has %d gid%s: ", + ngroups, ngroups == 1? "" : "s"); for (n = 0; n < ngroups; n++) { - sprintf(gidbuf+pos, " %d", (int)gidset[n]); - pos += strlen(gidbuf+pos); + pos += snprintf(gidbuf+pos, 21, " %d", (int)gidset[n]); } rprintf(FINFO, "%s\n", gidbuf); free(gidbuf); @@ -156,41 +155,41 @@ static int is_in_group(gid_t gid) } /* Add a uid to the list of uids. Only called on receiving side. */ -static struct idlist *recv_add_uid(int id, char *name) +static uid_t recv_add_uid(uid_t id, char *name) { - int id2 = name ? map_uid(id, name) : id; + uid_t id2 = name ? map_uid(id, name) : id; struct idlist *node; - node = add_to_list(&uidlist, id, name, id2); + node = add_to_list(&uidlist, (int)id, name, (int)id2); if (verbose > 3) { rprintf(FINFO, "uid %d(%s) maps to %d\n", - id, name ? name : "", id2); + (int)id, name ? name : "", (int)id2); } - return node; + return id2; } /* Add a gid to the list of gids. Only called on receiving side. */ -static struct idlist *recv_add_gid(int id, char *name) +static gid_t recv_add_gid(gid_t id, char *name) { - int id2 = name ? map_gid(id, name) : id; + gid_t id2 = name ? map_gid(id, name) : id; struct idlist *node; if (!am_root && !is_in_group(id2)) id2 = GID_NONE; - node = add_to_list(&gidlist, id, name, id2); + node = add_to_list(&gidlist, (int)id, name, (int)id2); if (verbose > 3) { rprintf(FINFO, "gid %d(%s) maps to %d\n", - id, name ? name : "", id2); + (int)id, name ? name : "", (int)id2); } - return node; + return id2; } /* this function is a definate candidate for a faster algorithm */ -static uid_t match_uid(uid_t uid) +uid_t match_uid(uid_t uid) { static uid_t last_in, last_out; struct idlist *list; @@ -211,7 +210,7 @@ static uid_t match_uid(uid_t uid) return last_out = uid; } -static gid_t match_gid(gid_t gid) +gid_t match_gid(gid_t gid) { static gid_t last_in = GID_NONE, last_out = GID_NONE; struct idlist *list; @@ -229,52 +228,51 @@ static gid_t match_gid(gid_t gid) return last_out = (gid_t)list->id2; } - list = recv_add_gid(gid, NULL); - return last_out = list->id2; + return last_out = recv_add_gid(gid, NULL); } /* Add a uid to the list of uids. Only called on sending side. */ -void add_uid(uid_t uid) +char *add_uid(uid_t uid) { struct idlist *list; + struct idlist *node; if (uid == 0) /* don't map root */ - return; + return NULL; for (list = uidlist; list; list = list->next) { if (list->id == (int)uid) - return; + return NULL; } - add_to_list(&uidlist, (int)uid, uid_to_name(uid), 0); + node = add_to_list(&uidlist, (int)uid, uid_to_name(uid), 0); + return node->name; } /* Add a gid to the list of gids. Only called on sending side. */ -void add_gid(gid_t gid) +char *add_gid(gid_t gid) { struct idlist *list; + struct idlist *node; if (gid == 0) /* don't map root */ - return; + return NULL; for (list = gidlist; list; list = list->next) { if (list->id == (int)gid) - return; + return NULL; } - add_to_list(&gidlist, (int)gid, gid_to_name(gid), 0); + node = add_to_list(&gidlist, (int)gid, gid_to_name(gid), 0); + return node->name; } - /* send a complete uid/gid mapping to the peer */ void send_uid_list(int f) { struct idlist *list; - if (numeric_ids) - return; - - if (preserve_uid) { + if (preserve_uid || preserve_acls) { int len; /* we send sequences of uid/byte-length/name */ for (list = uidlist; list; list = list->next) { @@ -291,7 +289,7 @@ void send_uid_list(int f) write_int(f, 0); } - if (preserve_gid) { + if (preserve_gid || preserve_acls) { int len; for (list = gidlist; list; list = list->next) { if (!list->name) @@ -305,46 +303,61 @@ void send_uid_list(int f) } } +uid_t recv_user_name(int f, uid_t uid) +{ + int len = read_byte(f); + char *name = new_array(char, len+1); + if (!name) + out_of_memory("recv_user_name"); + read_sbuf(f, name, len); + return recv_add_uid(uid, name); /* node keeps name's memory */ +} + +gid_t recv_group_name(int f, gid_t gid) +{ + int len = read_byte(f); + char *name = new_array(char, len+1); + if (!name) + out_of_memory("recv_group_name"); + read_sbuf(f, name, len); + return recv_add_gid(gid, name); /* node keeps name's memory */ +} + /* recv a complete uid/gid mapping from the peer and map the uid/gid * in the file list to local names */ void recv_uid_list(int f, struct file_list *flist) { int id, i; - char *name; - if (preserve_uid && !numeric_ids) { + if ((preserve_uid || preserve_acls) && !numeric_ids) { /* read the uid list */ - while ((id = read_int(f)) != 0) { - int len = read_byte(f); - name = new_array(char, len+1); - if (!name) - out_of_memory("recv_uid_list"); - read_sbuf(f, name, len); - recv_add_uid(id, name); /* node keeps name's memory */ - } + while ((id = read_int(f)) != 0) + recv_user_name(f, (uid_t)id); } - - if (preserve_gid && !numeric_ids) { + if ((preserve_gid || preserve_acls) && !numeric_ids) { /* read the gid list */ - while ((id = read_int(f)) != 0) { - int len = read_byte(f); - name = new_array(char, len+1); - if (!name) - out_of_memory("recv_uid_list"); - read_sbuf(f, name, len); - recv_add_gid(id, name); /* node keeps name's memory */ - } + while ((id = read_int(f)) != 0) + recv_group_name(f, (gid_t)id); } - /* now convert the uid/gid of all files in the list to the mapped - * uid/gid */ +#ifdef SUPPORT_ACLS + if (preserve_acls && !numeric_ids) { + id_t *id; + while ((id = next_acl_uid(flist)) != NULL) + *id = match_uid(*id); + while ((id = next_acl_gid(flist)) != NULL) + *id = match_gid(*id); + } +#endif + + /* Now convert all the uids/gids from sender values to our values. */ if (am_root && preserve_uid && !numeric_ids) { for (i = 0; i < flist->count; i++) - flist->files[i]->uid = match_uid(flist->files[i]->uid); + F_OWNER(flist->files[i]) = match_uid(F_UID(flist->files[i])); } if (preserve_gid && (!am_root || !numeric_ids)) { for (i = 0; i < flist->count; i++) - flist->files[i]->gid = match_gid(flist->files[i]->gid); + F_GROUP(flist->files[i]) = match_gid(F_GID(flist->files[i])); } }