Commit | Line | Data |
---|---|---|
6801e52b WD |
1 | This attempts to accomplish some per-file memory-savings by moving the |
2 | uid+gid items out of the file-list (since their values are common to | |
3 | multiple file-list entries) and replacing them with an index to an | |
4 | array of structures. | |
5 | ||
6 | This only saves 4 bytes per file (not counting the overhead of the array). | |
7 | ||
8 | This probably needs a hashing algorithm to be added if the uid+gid list | |
9 | gets to be really large. | |
10 | ||
03019e41 WD |
11 | To use this patch, run these commands for a successful build: |
12 | ||
13 | patch -p1 <patches/id-pair.diff | |
14 | ./configure (optional if already run) | |
15 | make | |
16 | ||
9a7eef96 WD |
17 | --- old/flist.c |
18 | +++ new/flist.c | |
7cf8a551 WD |
19 | @@ -54,6 +54,7 @@ extern int copy_unsafe_links; |
20 | extern int protocol_version; | |
6801e52b | 21 | extern int sanitize_paths; |
6801e52b WD |
22 | extern struct stats stats; |
23 | +extern struct id_pair *id_pairs; | |
24 | extern struct file_list *the_file_list; | |
25 | ||
26 | extern char curr_dir[MAXPATHLEN]; | |
3f053c45 | 27 | @@ -351,14 +352,14 @@ static void send_file_entry(struct file_ |
6801e52b | 28 | } |
4a65fe72 | 29 | } else if (protocol_version < 28) |
d9f0e41c | 30 | rdev = MAKEDEV(0, 0); |
6801e52b WD |
31 | - if (file->uid == uid) |
32 | + if (id_pairs[file->id_ndx].uid == uid) | |
33 | flags |= XMIT_SAME_UID; | |
34 | else | |
35 | - uid = file->uid; | |
36 | - if (file->gid == gid) | |
37 | + uid = id_pairs[file->id_ndx].uid; | |
38 | + if (id_pairs[file->id_ndx].gid == gid) | |
39 | flags |= XMIT_SAME_GID; | |
40 | else | |
41 | - gid = file->gid; | |
42 | + gid = id_pairs[file->id_ndx].gid; | |
43 | if (file->modtime == modtime) | |
44 | flags |= XMIT_SAME_TIME; | |
45 | else | |
3f053c45 | 46 | @@ -609,8 +610,7 @@ static struct file_struct *receive_file_ |
6801e52b WD |
47 | file->modtime = modtime; |
48 | file->length = file_length; | |
49 | file->mode = mode; | |
50 | - file->uid = uid; | |
51 | - file->gid = gid; | |
52 | + file->id_ndx = id_pair(uid, gid); | |
53 | ||
54 | if (dirname_len) { | |
55 | file->dirname = lastdir = bp; | |
3f053c45 | 56 | @@ -862,8 +862,7 @@ struct file_struct *make_file(char *fnam |
6801e52b WD |
57 | file->modtime = st.st_mtime; |
58 | file->length = st.st_size; | |
59 | file->mode = st.st_mode; | |
60 | - file->uid = st.st_uid; | |
61 | - file->gid = st.st_gid; | |
62 | + file->id_ndx = id_pair(st.st_uid, st.st_gid); | |
63 | ||
64 | #ifdef SUPPORT_HARD_LINKS | |
65 | if (flist && flist->hlink_pool) { | |
3f053c45 | 66 | @@ -931,8 +930,7 @@ struct file_struct *make_file(char *fnam |
6801e52b WD |
67 | file->modtime = st2.st_mtime; |
68 | file->length = st2.st_size; | |
69 | file->mode = st2.st_mode; | |
70 | - file->uid = st2.st_uid; | |
71 | - file->gid = st2.st_gid; | |
72 | + file->id_ndx = id_pair(st2.st_uid, st2.st_gid); | |
73 | file->u.link = NULL; | |
74 | } else | |
75 | file->mode = save_mode; | |
03019e41 | 76 | @@ -1380,7 +1378,7 @@ struct file_list *recv_file_list(int f) |
6801e52b WD |
77 | clean_flist(flist, relative_paths, 1); |
78 | ||
79 | if (f >= 0) { | |
80 | - recv_uid_list(f, flist); | |
81 | + recv_uid_list(f); | |
82 | ||
83 | /* Recv the io_error flag */ | |
84 | if (lp_ignore_errors(module_id) || ignore_errors) | |
03019e41 | 85 | @@ -1696,13 +1694,15 @@ static void output_flist(struct file_lis |
6801e52b WD |
86 | |
87 | for (i = 0; i < flist->count; i++) { | |
88 | file = flist->files[i]; | |
89 | - if ((am_root || am_sender) && preserve_uid) | |
3f053c45 | 90 | - snprintf(uidbuf, sizeof uidbuf, " uid=%ld", (long)file->uid); |
6801e52b WD |
91 | - else |
92 | + if ((am_root || am_sender) && preserve_uid) { | |
3f053c45 | 93 | + snprintf(uidbuf, sizeof uidbuf, " uid=%ld", |
6801e52b WD |
94 | + (long)id_pairs[file->id_ndx].uid); |
95 | + } else | |
96 | *uidbuf = '\0'; | |
97 | - if (preserve_gid && file->gid != GID_NONE) | |
3f053c45 | 98 | - snprintf(gidbuf, sizeof gidbuf, " gid=%ld", (long)file->gid); |
6801e52b WD |
99 | - else |
100 | + if (preserve_gid && id_pairs[file->id_ndx].gid != GID_NONE) { | |
3f053c45 | 101 | + snprintf(gidbuf, sizeof gidbuf, " gid=%ld", |
6801e52b WD |
102 | + (long)id_pairs[file->id_ndx].gid); |
103 | + } else | |
104 | *gidbuf = '\0'; | |
105 | if (!am_sender) | |
3f053c45 | 106 | snprintf(depthbuf, sizeof depthbuf, "%d", file->dir.depth); |
9a7eef96 WD |
107 | --- old/generator.c |
108 | +++ new/generator.c | |
3f053c45 | 109 | @@ -90,6 +90,7 @@ extern dev_t filesystem_dev; |
6801e52b WD |
110 | extern char *backup_dir; |
111 | extern char *backup_suffix; | |
112 | extern int backup_suffix_len; | |
113 | +extern struct id_pair *id_pairs; | |
114 | extern struct file_list *the_file_list; | |
115 | extern struct filter_list_struct server_filter_list; | |
116 | ||
3f053c45 | 117 | @@ -323,10 +324,12 @@ int unchanged_attrs(struct file_struct * |
6801e52b WD |
118 | && (st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) |
119 | return 0; | |
120 | ||
121 | - if (am_root && preserve_uid && st->st_uid != file->uid) | |
122 | + if (am_root && preserve_uid | |
123 | + && st->st_uid != id_pairs[file->id_ndx].uid) | |
124 | return 0; | |
125 | ||
126 | - if (preserve_gid && file->gid != GID_NONE && st->st_gid != file->gid) | |
127 | + if (preserve_gid && id_pairs[file->id_ndx].gid != GID_NONE | |
128 | + && st->st_gid != id_pairs[file->id_ndx].gid) | |
129 | return 0; | |
130 | ||
131 | return 1; | |
3f053c45 | 132 | @@ -339,6 +342,8 @@ void itemize(struct file_struct *file, i |
6801e52b WD |
133 | int keep_time = !preserve_times ? 0 |
134 | : S_ISDIR(file->mode) ? !omit_dir_times | |
135 | : !S_ISLNK(file->mode); | |
136 | + uid_t uid = id_pairs[file->id_ndx].uid; | |
137 | + gid_t gid = id_pairs[file->id_ndx].gid; | |
138 | ||
139 | if (S_ISREG(file->mode) && file->length != st->st_size) | |
140 | iflags |= ITEM_REPORT_SIZE; | |
3f053c45 | 141 | @@ -348,10 +353,10 @@ void itemize(struct file_struct *file, i |
9a7eef96 WD |
142 | iflags |= ITEM_REPORT_TIME; |
143 | if ((file->mode & CHMOD_BITS) != (st->st_mode & CHMOD_BITS)) | |
6801e52b WD |
144 | iflags |= ITEM_REPORT_PERMS; |
145 | - if (preserve_uid && am_root && file->uid != st->st_uid) | |
146 | + if (preserve_uid && am_root && uid != st->st_uid) | |
147 | iflags |= ITEM_REPORT_OWNER; | |
148 | - if (preserve_gid && file->gid != GID_NONE | |
149 | - && st->st_gid != file->gid) | |
150 | + if (preserve_gid && gid != GID_NONE | |
151 | + && st->st_gid != gid) | |
152 | iflags |= ITEM_REPORT_GROUP; | |
153 | } else | |
154 | iflags |= ITEM_IS_NEW; | |
b3d572ad WD |
155 | --- old/log.c |
156 | +++ new/log.c | |
03019e41 | 157 | @@ -46,6 +46,7 @@ extern char *auth_user; |
d9f0e41c | 158 | extern char *stdout_format; |
55c1a3b7 WD |
159 | extern char *logfile_format; |
160 | extern char *logfile_name; | |
d9a67109 | 161 | +extern struct id_pair *id_pairs; |
b3d572ad | 162 | #if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H |
d9a67109 WD |
163 | extern iconv_t ic_chck; |
164 | #endif | |
03019e41 | 165 | @@ -470,16 +471,16 @@ static void log_formatted(enum logcode c |
b3d572ad WD |
166 | case 'U': |
167 | strlcat(fmt, "ld", sizeof fmt); | |
168 | snprintf(buf2, sizeof buf2, fmt, | |
169 | - (long)file->uid); | |
170 | + (long)id_pairs[file->id_ndx].uid); | |
171 | n = buf2; | |
172 | break; | |
173 | case 'G': | |
174 | - if (file->gid == GID_NONE) | |
175 | + if (id_pairs[file->id_ndx].gid == GID_NONE) | |
176 | n = "DEFAULT"; | |
177 | else { | |
178 | strlcat(fmt, "ld", sizeof fmt); | |
179 | snprintf(buf2, sizeof buf2, fmt, | |
180 | - (long)file->gid); | |
181 | + (long)id_pairs[file->id_ndx].gid); | |
182 | n = buf2; | |
183 | } | |
184 | break; | |
9a7eef96 WD |
185 | --- old/rsync.c |
186 | +++ new/rsync.c | |
d9f0e41c | 187 | @@ -49,6 +49,7 @@ extern int keep_dirlinks; |
6801e52b | 188 | extern int make_backups; |
d9a67109 | 189 | extern mode_t orig_umask; |
6801e52b WD |
190 | extern struct stats stats; |
191 | +extern struct id_pair *id_pairs; | |
c769ea2c | 192 | extern struct chmod_mode_struct *daemon_chmod_modes; |
6801e52b | 193 | |
9a7eef96 | 194 | #if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H |
1ed0b5c9 | 195 | @@ -130,6 +131,8 @@ int set_file_attrs(char *fname, struct f |
6801e52b WD |
196 | STRUCT_STAT st2; |
197 | int change_uid, change_gid; | |
1ed0b5c9 | 198 | mode_t new_mode = file->mode; |
6801e52b WD |
199 | + uid_t uid; |
200 | + gid_t gid; | |
201 | ||
202 | if (!st) { | |
203 | if (dry_run) | |
1ed0b5c9 | 204 | @@ -162,9 +165,11 @@ int set_file_attrs(char *fname, struct f |
6801e52b WD |
205 | updated = 1; |
206 | } | |
207 | ||
208 | - change_uid = am_root && preserve_uid && st->st_uid != file->uid; | |
209 | - change_gid = preserve_gid && file->gid != GID_NONE | |
210 | - && st->st_gid != file->gid; | |
211 | + uid = id_pairs[file->id_ndx].uid; | |
212 | + gid = id_pairs[file->id_ndx].gid; | |
213 | + change_uid = am_root && preserve_uid && st->st_uid != uid; | |
214 | + change_gid = preserve_gid && gid != GID_NONE | |
215 | + && st->st_gid != gid; | |
216 | #if !defined HAVE_LCHOWN && !defined CHOWN_MODIFIES_SYMLINK | |
217 | if (S_ISLNK(st->st_mode)) | |
218 | ; | |
1ed0b5c9 | 219 | @@ -176,18 +181,18 @@ int set_file_attrs(char *fname, struct f |
6801e52b WD |
220 | rprintf(FINFO, |
221 | "set uid of %s from %ld to %ld\n", | |
222 | fname, | |
223 | - (long)st->st_uid, (long)file->uid); | |
224 | + (long)st->st_uid, (long)uid); | |
225 | } | |
226 | if (change_gid) { | |
227 | rprintf(FINFO, | |
228 | "set gid of %s from %ld to %ld\n", | |
229 | fname, | |
230 | - (long)st->st_gid, (long)file->gid); | |
231 | + (long)st->st_gid, (long)gid); | |
232 | } | |
233 | } | |
234 | if (do_lchown(fname, | |
235 | - change_uid ? file->uid : st->st_uid, | |
236 | - change_gid ? file->gid : st->st_gid) != 0) { | |
237 | + change_uid ? uid : st->st_uid, | |
238 | + change_gid ? gid : st->st_gid) != 0) { | |
239 | /* shouldn't have attempted to change uid or gid | |
240 | * unless have the privilege */ | |
241 | rsyserr(FERROR, errno, "%s %s failed", | |
9a7eef96 WD |
242 | --- old/rsync.h |
243 | +++ new/rsync.h | |
3f053c45 WD |
244 | @@ -503,6 +503,11 @@ struct hlink { |
245 | unsigned short link_dest_used; | |
6801e52b WD |
246 | }; |
247 | ||
248 | +struct id_pair { | |
249 | + uid_t uid; | |
250 | + gid_t gid; | |
251 | +}; | |
252 | + | |
253 | #define F_DEV link_u.idev->dev | |
254 | #define F_INODE link_u.idev->inode | |
255 | ||
3f053c45 | 256 | @@ -527,8 +532,7 @@ struct file_struct { |
6801e52b WD |
257 | struct hlink *links; |
258 | } link_u; | |
259 | time_t modtime; | |
260 | - uid_t uid; | |
261 | - gid_t gid; | |
262 | + int id_ndx; | |
263 | mode_t mode; | |
264 | uchar flags; /* this item MUST remain last */ | |
265 | }; | |
9a7eef96 WD |
266 | --- old/uidlist.c |
267 | +++ new/uidlist.c | |
7cf8a551 | 268 | @@ -38,6 +38,8 @@ extern int preserve_gid; |
6801e52b WD |
269 | extern int numeric_ids; |
270 | extern int am_root; | |
271 | ||
272 | +struct id_pair *id_pairs; | |
273 | + | |
274 | struct idlist { | |
275 | struct idlist *next; | |
276 | int id, id2; | |
7cf8a551 | 277 | @@ -47,6 +49,8 @@ struct idlist { |
6801e52b WD |
278 | static struct idlist *uidlist; |
279 | static struct idlist *gidlist; | |
280 | ||
281 | +static int pair_cnt = 0, pair_alloc = 0; | |
282 | + | |
283 | static struct idlist *add_to_list(struct idlist **root, int id, char *name, | |
284 | int id2) | |
285 | { | |
3f053c45 | 286 | @@ -306,7 +310,7 @@ void send_uid_list(int f) |
6801e52b WD |
287 | |
288 | /* recv a complete uid/gid mapping from the peer and map the uid/gid | |
289 | * in the file list to local names */ | |
290 | -void recv_uid_list(int f, struct file_list *flist) | |
291 | +void recv_uid_list(int f) | |
292 | { | |
293 | int id, i; | |
294 | char *name; | |
3f053c45 | 295 | @@ -337,11 +341,40 @@ void recv_uid_list(int f, struct file_li |
6801e52b WD |
296 | |
297 | /* Now convert all the uids/gids from sender values to our values. */ | |
298 | if (am_root && preserve_uid && !numeric_ids) { | |
299 | - for (i = 0; i < flist->count; i++) | |
300 | - flist->files[i]->uid = match_uid(flist->files[i]->uid); | |
301 | + for (i = 0; i < pair_cnt; i++) | |
302 | + id_pairs[i].uid = match_uid(id_pairs[i].uid); | |
303 | } | |
304 | if (preserve_gid && (!am_root || !numeric_ids)) { | |
305 | - for (i = 0; i < flist->count; i++) | |
306 | - flist->files[i]->gid = match_gid(flist->files[i]->gid); | |
307 | + for (i = 0; i < pair_cnt; i++) | |
308 | + id_pairs[i].gid = match_gid(id_pairs[i].gid); | |
309 | } | |
310 | } | |
311 | + | |
312 | +int id_pair(uid_t uid, gid_t gid) | |
313 | +{ | |
314 | + static int j = 0; | |
315 | + | |
316 | + if (pair_cnt) { | |
317 | + int start = j; | |
318 | + /* We start our search where we left off because | |
319 | + * the IDs usually come in clumps. */ | |
320 | + do { | |
321 | + if (uid == id_pairs[j].uid && gid == id_pairs[j].gid) | |
322 | + return j; | |
323 | + if (++j == pair_cnt) | |
324 | + j = 0; | |
325 | + } while (j != start); | |
326 | + } | |
327 | + | |
328 | + if (pair_cnt == pair_alloc) { | |
329 | + pair_alloc += 128; | |
330 | + id_pairs = realloc_array(id_pairs, struct id_pair, | |
331 | + pair_alloc); | |
332 | + } | |
333 | + | |
334 | + j = pair_cnt++; | |
335 | + id_pairs[j].uid = uid; | |
336 | + id_pairs[j].gid = gid; | |
337 | + | |
338 | + return j; | |
339 | +} |