00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
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
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
00134 void add_uid(uid_t uid)
00135 {
00136 struct idlist *list = uidlist;
00137 char *name;
00138
00139 if (numeric_ids) return;
00140
00141
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
00163 void add_gid(gid_t gid)
00164 {
00165 struct idlist *list = gidlist;
00166 char *name;
00167
00168 if (numeric_ids) return;
00169
00170
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
00193 void send_uid_list(int f)
00194 {
00195 struct idlist *list;
00196
00197 if (numeric_ids) return;
00198
00199 if (preserve_uid) {
00200
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
00211
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
00229
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
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
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
00286
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 }