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
6 This only saves 4 bytes per file (not counting the overhead of the array).
8 This probably needs a hashing algorithm to be added if the uid+gid list
9 gets to be really large.
11 To use this patch, run these commands for a successful build:
13 patch -p1 <patches/id-pair.diff
14 ./configure (optional if already run)
19 @@ -54,6 +54,7 @@ extern int copy_unsafe_links;
20 extern int protocol_version;
21 extern int sanitize_paths;
22 extern struct stats stats;
23 +extern struct id_pair *id_pairs;
24 extern struct file_list *the_file_list;
26 extern char curr_dir[MAXPATHLEN];
27 @@ -351,14 +352,14 @@ static void send_file_entry(struct file_
29 } else if (protocol_version < 28)
31 - if (file->uid == uid)
32 + if (id_pairs[file->id_ndx].uid == uid)
33 flags |= XMIT_SAME_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;
42 + gid = id_pairs[file->id_ndx].gid;
43 if (file->modtime == modtime)
44 flags |= XMIT_SAME_TIME;
46 @@ -609,8 +610,7 @@ static struct file_struct *receive_file_
47 file->modtime = modtime;
48 file->length = file_length;
52 + file->id_ndx = id_pair(uid, gid);
55 file->dirname = lastdir = bp;
56 @@ -862,8 +862,7 @@ struct file_struct *make_file(char *fnam
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);
64 #ifdef SUPPORT_HARD_LINKS
65 if (flist && flist->hlink_pool) {
66 @@ -931,8 +930,7 @@ struct file_struct *make_file(char *fnam
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);
75 file->mode = save_mode;
76 @@ -1380,7 +1378,7 @@ struct file_list *recv_file_list(int f)
77 clean_flist(flist, relative_paths, 1);
80 - recv_uid_list(f, flist);
83 /* Recv the io_error flag */
84 if (lp_ignore_errors(module_id) || ignore_errors)
85 @@ -1696,13 +1694,15 @@ static void output_flist(struct file_lis
87 for (i = 0; i < flist->count; i++) {
88 file = flist->files[i];
89 - if ((am_root || am_sender) && preserve_uid)
90 - snprintf(uidbuf, sizeof uidbuf, " uid=%ld", (long)file->uid);
92 + if ((am_root || am_sender) && preserve_uid) {
93 + snprintf(uidbuf, sizeof uidbuf, " uid=%ld",
94 + (long)id_pairs[file->id_ndx].uid);
97 - if (preserve_gid && file->gid != GID_NONE)
98 - snprintf(gidbuf, sizeof gidbuf, " gid=%ld", (long)file->gid);
100 + if (preserve_gid && id_pairs[file->id_ndx].gid != GID_NONE) {
101 + snprintf(gidbuf, sizeof gidbuf, " gid=%ld",
102 + (long)id_pairs[file->id_ndx].gid);
106 snprintf(depthbuf, sizeof depthbuf, "%d", file->dir.depth);
109 @@ -90,6 +90,7 @@ extern dev_t filesystem_dev;
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;
117 @@ -323,10 +324,12 @@ int unchanged_attrs(struct file_struct *
118 && (st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS))
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)
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)
132 @@ -339,6 +342,8 @@ void itemize(struct file_struct *file, i
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;
139 if (S_ISREG(file->mode) && file->length != st->st_size)
140 iflags |= ITEM_REPORT_SIZE;
141 @@ -348,10 +353,10 @@ void itemize(struct file_struct *file, i
142 iflags |= ITEM_REPORT_TIME;
143 if ((file->mode & CHMOD_BITS) != (st->st_mode & CHMOD_BITS))
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;
154 iflags |= ITEM_IS_NEW;
157 @@ -46,6 +46,7 @@ extern char *auth_user;
158 extern char *stdout_format;
159 extern char *logfile_format;
160 extern char *logfile_name;
161 +extern struct id_pair *id_pairs;
162 #if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
163 extern iconv_t ic_chck;
165 @@ -470,16 +471,16 @@ static void log_formatted(enum logcode c
167 strlcat(fmt, "ld", sizeof fmt);
168 snprintf(buf2, sizeof buf2, fmt,
170 + (long)id_pairs[file->id_ndx].uid);
174 - if (file->gid == GID_NONE)
175 + if (id_pairs[file->id_ndx].gid == GID_NONE)
178 strlcat(fmt, "ld", sizeof fmt);
179 snprintf(buf2, sizeof buf2, fmt,
181 + (long)id_pairs[file->id_ndx].gid);
187 @@ -49,6 +49,7 @@ extern int keep_dirlinks;
188 extern int make_backups;
189 extern mode_t orig_umask;
190 extern struct stats stats;
191 +extern struct id_pair *id_pairs;
192 extern struct chmod_mode_struct *daemon_chmod_modes;
194 #if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
195 @@ -130,6 +131,8 @@ int set_file_attrs(char *fname, struct f
197 int change_uid, change_gid;
198 mode_t new_mode = file->mode;
204 @@ -162,9 +165,11 @@ int set_file_attrs(char *fname, struct f
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))
219 @@ -176,18 +181,18 @@ int set_file_attrs(char *fname, struct f
221 "set uid of %s from %ld to %ld\n",
223 - (long)st->st_uid, (long)file->uid);
224 + (long)st->st_uid, (long)uid);
228 "set gid of %s from %ld to %ld\n",
230 - (long)st->st_gid, (long)file->gid);
231 + (long)st->st_gid, (long)gid);
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",
244 @@ -503,6 +503,11 @@ struct hlink {
245 unsigned short link_dest_used;
253 #define F_DEV link_u.idev->dev
254 #define F_INODE link_u.idev->inode
256 @@ -527,8 +532,7 @@ struct file_struct {
264 uchar flags; /* this item MUST remain last */
268 @@ -38,6 +38,8 @@ extern int preserve_gid;
269 extern int numeric_ids;
272 +struct id_pair *id_pairs;
277 @@ -47,6 +49,8 @@ struct idlist {
278 static struct idlist *uidlist;
279 static struct idlist *gidlist;
281 +static int pair_cnt = 0, pair_alloc = 0;
283 static struct idlist *add_to_list(struct idlist **root, int id, char *name,
286 @@ -306,7 +310,7 @@ void send_uid_list(int f)
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)
295 @@ -337,11 +341,40 @@ void recv_uid_list(int f, struct file_li
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);
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);
312 +int id_pair(uid_t uid, gid_t gid)
318 + /* We start our search where we left off because
319 + * the IDs usually come in clumps. */
321 + if (uid == id_pairs[j].uid && gid == id_pairs[j].gid)
323 + if (++j == pair_cnt)
325 + } while (j != start);
328 + if (pair_cnt == pair_alloc) {
330 + id_pairs = realloc_array(id_pairs, struct id_pair,
335 + id_pairs[j].uid = uid;
336 + id_pairs[j].gid = gid;