Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

uidlist.c

Go to the documentation of this file.
00001 /* 
00002    Copyright (C) Andrew Tridgell 1996
00003    Copyright (C) Paul Mackerras 1996
00004    
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 2 of the License, or
00008    (at your option) any later version.
00009    
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014    
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software
00017    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 */
00019 
00020 /* handle the mapping of uid/gid and user/group names between systems.
00021    If the source username/group does not exist on the target then use
00022    the numeric ids. Never do any mapping for uid=0 or gid=0 as these
00023    are special.
00024 */
00025 
00026 #include "rsync.h"
00027 
00028 extern int preserve_uid;
00029 extern int preserve_gid;
00030 extern int numeric_ids;
00031 extern int am_root;
00032 
00033 struct idlist {
00034         struct idlist *next;
00035         int id, id2;
00036         char *name;
00037 };
00038 
00039 static struct idlist *uidlist;
00040 static struct idlist *gidlist;
00041 
00042 static struct idlist *add_list(int id, char *name)
00043 {
00044         struct idlist *list = (struct idlist *)malloc(sizeof(list[0]));
00045         if (!list) out_of_memory("add_list");
00046         list->next = NULL;
00047         list->name = strdup(name);
00048         if (!list->name) out_of_memory("add_list");
00049         list->id = (int)id;
00050         return list;
00051 }
00052 
00053 
00054 
00055 /* turn a uid into a user name */
00056 static char *uid_to_name(uid_t uid)
00057 {
00058         struct passwd *pass = getpwuid(uid);
00059         if (pass) return(pass->pw_name);
00060         return NULL;
00061 }
00062 
00063 /* turn a gid into a group name */
00064 static char *gid_to_name(gid_t gid)
00065 {
00066         struct group *grp = getgrgid(gid);
00067         if (grp) return(grp->gr_name);
00068         return NULL;
00069 }
00070 
00071 static int map_uid(int id, char *name)
00072 {
00073         uid_t uid;
00074         if (name_to_uid(name, &uid) && uid != 0)
00075                 return uid;
00076         return id;
00077 }
00078 
00079 static int map_gid(int id, char *name)
00080 {
00081         gid_t gid;
00082         if (name_to_gid(name, &gid) && gid != 0)
00083                 return gid;
00084         return id;
00085 }
00086 
00087 /* this function is a definate candidate for a faster algorithm */
00088 static uid_t match_uid(uid_t uid)
00089 {
00090         static uid_t last_in, last_out;
00091         struct idlist *list = uidlist;
00092 
00093         if (uid == last_in) return last_out;
00094 
00095         last_in = uid;
00096 
00097         while (list) {
00098                 if (list->id == (int)uid) {
00099                         last_out = (uid_t)list->id2;
00100                         return last_out;
00101                 }
00102                 list = list->next;
00103         }
00104         
00105         last_out = uid;
00106         return last_out;
00107 }
00108 
00109 static gid_t match_gid(gid_t gid)
00110 {
00111         static gid_t last_in, last_out;
00112         struct idlist *list = gidlist;
00113 
00114         if (gid == last_in) return last_out;
00115 
00116         last_in = gid;
00117 
00118         while (list) {
00119                 if (list->id == (int)gid) {
00120                         last_out = (gid_t)list->id2;
00121                         return last_out;
00122                 }
00123                 list = list->next;
00124         }
00125         
00126         if (am_root)
00127                 last_out = gid;
00128         else
00129                 last_out = (gid_t) -1;
00130         return last_out;
00131 }
00132 
00133 /* add a uid to the list of uids */
00134 void add_uid(uid_t uid)
00135 {
00136         struct idlist *list = uidlist;
00137         char *name;
00138 
00139         if (numeric_ids) return;
00140 
00141         /* don't map root */
00142         if (uid==0) return;
00143 
00144         if (!list) {
00145                 if (!(name = uid_to_name(uid))) return;
00146                 uidlist = add_list((int)uid, name);
00147                 return;
00148         }
00149 
00150         while (list->next) {
00151                 if (list->id == (int)uid) return;
00152                 list = list->next;
00153         }
00154 
00155         if (list->id == (int)uid) return;
00156 
00157         if (!(name = uid_to_name(uid))) return;
00158 
00159         list->next = add_list((int)uid, name);
00160 }
00161 
00162 /* add a gid to the list of gids */
00163 void add_gid(gid_t gid)
00164 {
00165         struct idlist *list = gidlist;
00166         char *name;
00167 
00168         if (numeric_ids) return;
00169 
00170         /* don't map root */
00171         if (gid==0) return;
00172 
00173         if (!list) {
00174                 if (!(name = gid_to_name(gid))) return;
00175                 gidlist = add_list((int)gid, name);
00176                 return;
00177         }
00178 
00179         while (list->next) {
00180                 if (list->id == (int)gid) return;
00181                 list = list->next;
00182         }
00183 
00184         if (list->id == (int)gid) return;
00185 
00186         if (!(name = gid_to_name(gid))) return;
00187 
00188         list->next = add_list((int)gid, name);
00189 }
00190 
00191 
00192 /* send a complete uid/gid mapping to the peer */
00193 void send_uid_list(int f)
00194 {
00195         struct idlist *list;
00196 
00197         if (numeric_ids) return;
00198 
00199         if (preserve_uid) {
00200                 /* we send sequences of uid/byte-length/name */
00201                 list = uidlist;
00202                 while (list) {
00203                         int len = strlen(list->name);
00204                         write_int(f, list->id);
00205                         write_byte(f, len);
00206                         write_buf(f, list->name, len);
00207                         list = list->next;
00208                 }
00209 
00210                 /* terminate the uid list with a 0 uid. We explicitly exclude
00211                    0 from the list */
00212                 write_int(f, 0);
00213         }
00214 
00215         if (preserve_gid) {
00216                 list = gidlist;
00217                 while (list) {
00218                         int len = strlen(list->name);
00219                         write_int(f, list->id);
00220                         write_byte(f, len);
00221                         write_buf(f, list->name, len);
00222                         list = list->next;
00223                 }
00224                 write_int(f, 0);
00225         }
00226 }
00227 
00228 /* recv a complete uid/gid mapping from the peer and map the uid/gid
00229    in the file list to local names */
00230 void recv_uid_list(int f, struct file_list *flist)
00231 {
00232         int id, i;
00233         char *name;
00234         struct idlist *list;
00235 
00236         if (numeric_ids) return;
00237 
00238         if (preserve_uid) {
00239                 /* read the uid list */
00240                 list = uidlist;
00241                 id = read_int(f);
00242                 while (id != 0) {
00243                         int len = read_byte(f);
00244                         name = (char *)malloc(len+1);
00245                         if (!name) out_of_memory("recv_uid_list");
00246                         read_sbuf(f, name, len);
00247                         if (!list) {
00248                                 uidlist = add_list(id, name);
00249                                 list = uidlist;
00250                         } else {
00251                                 list->next = add_list(id, name);
00252                                 list = list->next;
00253                         }
00254                         list->id2 = map_uid(id, name);
00255                         free(name);
00256                         id = read_int(f);
00257                 }
00258         }
00259 
00260 
00261         if (preserve_gid) {
00262                 /* and the gid list */
00263                 list = gidlist;
00264                 id = read_int(f);
00265                 while (id != 0) {
00266                         int len = read_byte(f);
00267                         name = (char *)malloc(len+1);
00268                         if (!name) out_of_memory("recv_uid_list");
00269                         read_sbuf(f, name, len);
00270                         if (!list) {
00271                                 gidlist = add_list(id, name);
00272                                 list = gidlist;
00273                         } else {
00274                                 list->next = add_list(id, name);
00275                                 list = list->next;
00276                         }
00277                         list->id2 = map_gid(id, name);
00278                         free(name);
00279                         id = read_int(f);
00280                 }
00281         }
00282 
00283         if (!(am_root && preserve_uid) && !preserve_gid) return;
00284 
00285         /* now convert the uid/gid of all files in the list to the mapped
00286            uid/gid */
00287         for (i=0;i<flist->count;i++) {
00288                 if (am_root && preserve_uid && flist->files[i]->uid != 0) {
00289                         flist->files[i]->uid = match_uid(flist->files[i]->uid);
00290                 }
00291                 if (preserve_gid && flist->files[i]->gid != 0) {
00292                         flist->files[i]->gid = match_gid(flist->files[i]->gid);
00293                 }
00294         }
00295 }

Generated on Tue Apr 16 12:37:37 2002 for rsync by doxygen1.2.15