Fixed length check when excluding XSTAT_ATTR.
[rsync/rsync-patches.git] / id-pair.diff
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
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
17 --- old/flist.c
18 +++ new/flist.c
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;
25  
26  extern char curr_dir[MAXPATHLEN];
27 @@ -351,14 +352,14 @@ static void send_file_entry(struct file_
28                 }
29         } else if (protocol_version < 28)
30                 rdev = MAKEDEV(0, 0);
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
46 @@ -609,8 +610,7 @@ static struct file_struct *receive_file_
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;
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);
63  
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);
73                         file->u.link = NULL;
74                 } else
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);
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)
85 @@ -1696,13 +1694,15 @@ static void output_flist(struct file_lis
86  
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);
91 -               else
92 +               if ((am_root || am_sender) && preserve_uid) {
93 +                       snprintf(uidbuf, sizeof uidbuf, " uid=%ld",
94 +                               (long)id_pairs[file->id_ndx].uid);
95 +               } else
96                         *uidbuf = '\0';
97 -               if (preserve_gid && file->gid != GID_NONE)
98 -                       snprintf(gidbuf, sizeof gidbuf, " gid=%ld", (long)file->gid);
99 -               else
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);
103 +               } else
104                         *gidbuf = '\0';
105                 if (!am_sender)
106                         snprintf(depthbuf, sizeof depthbuf, "%d", file->dir.depth);
107 --- old/generator.c
108 +++ new/generator.c
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;
116  
117 @@ -323,10 +324,12 @@ int unchanged_attrs(struct file_struct *
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;
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;
138  
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;
153         } else
154                 iflags |= ITEM_IS_NEW;
155 --- old/log.c
156 +++ new/log.c
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;
164  #endif
165 @@ -470,16 +471,16 @@ static void log_formatted(enum logcode c
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;
185 --- old/rsync.c
186 +++ new/rsync.c
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;
193  
194  #if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
195 @@ -130,6 +131,8 @@ int set_file_attrs(char *fname, struct f
196         STRUCT_STAT st2;
197         int change_uid, change_gid;
198         mode_t new_mode = file->mode;
199 +       uid_t uid;
200 +       gid_t gid;
201  
202         if (!st) {
203                 if (dry_run)
204 @@ -162,9 +165,11 @@ int set_file_attrs(char *fname, struct f
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                 ;
219 @@ -176,18 +181,18 @@ int set_file_attrs(char *fname, struct f
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",
242 --- old/rsync.h
243 +++ new/rsync.h
244 @@ -503,6 +503,11 @@ struct hlink {
245         unsigned short link_dest_used;
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  
256 @@ -527,8 +532,7 @@ struct file_struct {
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  };
266 --- old/uidlist.c
267 +++ new/uidlist.c
268 @@ -38,6 +38,8 @@ extern int preserve_gid;
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;
277 @@ -47,6 +49,8 @@ struct idlist {
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  {
286 @@ -306,7 +310,7 @@ void send_uid_list(int f)
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;
295 @@ -337,11 +341,40 @@ void recv_uid_list(int f, struct file_li
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 +}