X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/58cadc8608fbb2cbc7b74578cd92de4337a4b887..84fa865c0c06445140e8b4a0ab10bc46ce65bbf0:/uidlist.c diff --git a/uidlist.c b/uidlist.c index d8a7af11..c520df32 100644 --- a/uidlist.c +++ b/uidlist.c @@ -25,6 +25,14 @@ #include "rsync.h" +#ifdef GETGROUPS_T +# ifndef NGROUPS_MAX +/* It ought to be defined, but just in case. */ +# define NGROUPS_MAX 32 +# endif +#endif + +extern int verbose; extern int preserve_uid; extern int preserve_gid; extern int numeric_ids; @@ -71,7 +79,7 @@ static char *gid_to_name(gid_t gid) static int map_uid(int id, char *name) { uid_t uid; - if (name_to_uid(name, &uid) && uid != 0) + if (uid != 0 && name_to_uid(name, &uid)) return uid; return id; } @@ -79,7 +87,7 @@ static int map_uid(int id, char *name) static int map_gid(int id, char *name) { gid_t gid; - if (name_to_gid(name, &gid) && gid != 0) + if (gid != 0 && name_to_gid(name, &gid)) return gid; return id; } @@ -90,7 +98,8 @@ static uid_t match_uid(uid_t uid) static uid_t last_in, last_out; struct idlist *list = uidlist; - if (uid == last_in) return last_out; + if (uid == last_in) + return last_out; last_in = uid; @@ -106,12 +115,62 @@ static uid_t match_uid(uid_t uid) return last_out; } +static int is_in_group(gid_t gid) +{ +#ifdef GETGROUPS_T + static gid_t last_in = GID_NONE, last_out; + static int ngroups = -2; + static GETGROUPS_T *gidset; + int n; + + if (gid == last_in) + return last_out; + if (ngroups < -1) { + gid_t mygid = getgid(); + ngroups = getgroups(0, 0); + /* If that didn't work, perhaps 0 isn't treated specially? */ + if (ngroups <= 0) + ngroups = NGROUPS_MAX; + gidset = new_array(GETGROUPS_T, ngroups+1); + if (ngroups > 0) + ngroups = getgroups(ngroups, gidset); + /* The default gid might not be in the list on some systems. */ + for (n = 0; n < ngroups; n++) { + if (gidset[n] == mygid) + break; + } + if (n == ngroups) + gidset[ngroups++] = mygid; + if (verbose > 3) { + for (n = 0; n < ngroups; n++) { + rprintf(FINFO, "process gid %d: %ld\n", + n, (long)gidset[n]); + } + } + } + + last_in = gid; + for (n = 0; n < ngroups; n++) { + if (gidset[n] == gid) + return last_out = 1; + } + return last_out = 0; + +#else + static gid_t mygid = GID_NONE; + if (mygid == GID_NONE) + mygid = getgid(); + return gid == mygid; +#endif +} + static gid_t match_gid(gid_t gid) { - static gid_t last_in, last_out; + static gid_t last_in = GID_NONE, last_out = GID_NONE; struct idlist *list = gidlist; - if (gid == last_in) return last_out; + if (gid == last_in) + return last_out; last_in = gid; @@ -126,7 +185,7 @@ static gid_t match_gid(gid_t gid) if (am_root) last_out = gid; else - last_out = (gid_t) -1; + last_out = GID_NONE; return last_out; } @@ -208,7 +267,7 @@ void send_uid_list(int f) } /* terminate the uid list with a 0 uid. We explicitly exclude - 0 from the list */ + * 0 from the list */ write_int(f, 0); } @@ -226,7 +285,7 @@ void send_uid_list(int f) } /* recv a complete uid/gid mapping from the peer and map the uid/gid - in the file list to local names */ + * in the file list to local names */ void recv_uid_list(int f, struct file_list *flist) { int id, i; @@ -238,8 +297,7 @@ void recv_uid_list(int f, struct file_list *flist) if (preserve_uid) { /* read the uid list */ list = uidlist; - id = read_int(f); - while (id != 0) { + 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"); @@ -253,7 +311,13 @@ void recv_uid_list(int f, struct file_list *flist) } list->id2 = map_uid(id, name); free(name); - id = read_int(f); + } + if (verbose > 3) { + for (list = uidlist; list; list = list->next) { + rprintf(FINFO, "uid %s (%ld) maps to %ld\n", + list->name, (long)list->id, + (long)list->id2); + } } } @@ -261,8 +325,7 @@ void recv_uid_list(int f, struct file_list *flist) if (preserve_gid) { /* and the gid list */ list = gidlist; - id = read_int(f); - while (id != 0) { + 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"); @@ -275,21 +338,27 @@ void recv_uid_list(int f, struct file_list *flist) list = list->next; } list->id2 = map_gid(id, name); + if (!am_root && !is_in_group(list->id2)) + list->id2 = GID_NONE; free(name); - id = read_int(f); + } + if (verbose > 3) { + for (list = gidlist; list; list = list->next) { + rprintf(FINFO, "gid %s (%ld) maps to %ld\n", + list->name, (long)list->id, + (long)list->id2); + } } } if (!(am_root && preserve_uid) && !preserve_gid) return; /* now convert the uid/gid of all files in the list to the mapped - uid/gid */ - for (i=0;icount;i++) { - if (am_root && preserve_uid && flist->files[i]->uid != 0) { + * uid/gid */ + for (i = 0; i < flist->count; i++) { + if (am_root && preserve_uid && flist->files[i]->uid != 0) flist->files[i]->uid = match_uid(flist->files[i]->uid); - } - if (preserve_gid && flist->files[i]->gid != 0) { + if (preserve_gid && (!am_root || flist->files[i]->gid != 0)) flist->files[i]->gid = match_gid(flist->files[i]->gid); - } } }