Enhanced the patch to remove the memory penalty when no atimes
[rsync-patches.git] / atimes.diff
1 After applying this patch and running configure, you MUST run this
2 command before "make":
3
4     make proto
5
6
7 --- orig/batch.c        2006-01-14 08:14:29
8 +++ batch.c     2006-01-24 19:18:36
9 @@ -23,6 +23,7 @@ extern int do_compression;
10  extern int def_compress_level;
11  extern int protocol_version;
12  extern char *batch_name;
13 +extern unsigned int file_struct_len;
14  
15  extern struct filter_list_struct filter_list;
16  
17 @@ -222,9 +223,11 @@ void show_flist(int index, struct file_s
18  
19         int i;
20         for (i = 0; i < index; i++) {
21 -               rprintf(FINFO, "flist->flags=%#x\n", fptr[i]->flags);
22 +               rprintf(FINFO, "flist->flags=%#x\n", FFLAGS(fptr[i]));
23                 rprintf(FINFO, "flist->modtime=%#lx\n",
24                         (long unsigned) fptr[i]->modtime);
25 +               rprintf(FINFO, "flist->atime=%#lx\n",
26 +                       (long unsigned) fptr[i]->atime);
27                 rprintf(FINFO, "flist->length=%.0f\n",
28                         (double) fptr[i]->length);
29                 rprintf(FINFO, "flist->mode=%#o\n", (int) fptr[i]->mode);
30 --- orig/flist.c        2006-01-24 19:03:06
31 +++ flist.c     2006-01-24 19:32:19
32 @@ -50,6 +50,7 @@ extern int preserve_perms;
33  extern int preserve_devices;
34  extern int preserve_uid;
35  extern int preserve_gid;
36 +extern int preserve_atimes;
37  extern int relative_paths;
38  extern int implied_dirs;
39  extern int copy_links;
40 @@ -83,7 +84,11 @@ void init_flist(void)
41         struct file_struct f;
42  
43         /* Figure out how big the file_struct is without trailing padding */
44 -       file_struct_len = offsetof(struct file_struct, flags) + sizeof f.flags;
45 +       if (preserve_atimes)
46 +               file_struct_len = offsetof(struct file_struct, flags);
47 +       else
48 +               file_struct_len = offsetof(struct file_struct, atime);
49 +       file_struct_len += sizeof f.flags;
50         checksum_len = protocol_version < 21 ? 2 : MD4_SUM_LENGTH;
51  }
52  
53 @@ -139,16 +144,18 @@ static void list_file_entry(struct file_
54  
55  #ifdef SUPPORT_LINKS
56         if (preserve_links && S_ISLNK(f->mode)) {
57 -               rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
58 +               rprintf(FINFO, "%s %11.0f %s %s %s -> %s\n",
59                         perms,
60                         (double)f->length, timestring(f->modtime),
61 +                       preserve_atimes ? timestring(f->atime) : "",
62                         f_name(f, NULL), f->u.link);
63         } else
64  #endif
65         {
66 -               rprintf(FINFO, "%s %11.0f %s %s\n",
67 +               rprintf(FINFO, "%s %11.0f %s %s %s\n",
68                         perms,
69                         (double)f->length, timestring(f->modtime),
70 +                       preserve_atimes ? timestring(f->atime) : "",
71                         f_name(f, NULL));
72         }
73  }
74 @@ -310,6 +317,7 @@ static void send_file_entry(struct file_
75  {
76         unsigned short flags;
77         static time_t modtime;
78 +       static time_t atime;
79         static mode_t mode;
80         static int64 dev;
81         static dev_t rdev;
82 @@ -325,7 +333,7 @@ static void send_file_entry(struct file_
83  
84         if (!file) {
85                 write_byte(f, 0);
86 -               modtime = 0, mode = 0;
87 +               modtime = 0, atime = 0, mode = 0;
88                 dev = 0, rdev = makedev(0, 0);
89                 rdev_major = 0;
90                 uid = 0, gid = 0;
91 @@ -337,7 +345,7 @@ static void send_file_entry(struct file_
92  
93         f_name(file, fname);
94  
95 -       flags = file->flags & XMIT_TOP_DIR;
96 +       flags = FFLAGS(file) & XMIT_TOP_DIR;
97  
98         if (file->mode == mode)
99                 flags |= XMIT_SAME_MODE;
100 @@ -374,6 +382,12 @@ static void send_file_entry(struct file_
101                 flags |= XMIT_SAME_TIME;
102         else
103                 modtime = file->modtime;
104 +       if (preserve_atimes && !S_ISDIR(mode)) {
105 +               if (file->atime == atime)
106 +                       flags |= XMIT_SAME_ATIME;
107 +               else
108 +                       atime = file->atime;
109 +       }
110  
111  #ifdef SUPPORT_HARD_LINKS
112         if (file->link_u.idev) {
113 @@ -427,6 +441,8 @@ static void send_file_entry(struct file_
114                 write_int(f, modtime);
115         if (!(flags & XMIT_SAME_MODE))
116                 write_int(f, to_wire_mode(mode));
117 +       if (preserve_atimes && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
118 +               write_int(f, atime);
119         if (preserve_uid && !(flags & XMIT_SAME_UID)) {
120                 if (!numeric_ids)
121                         add_uid(uid);
122 @@ -494,6 +510,7 @@ static struct file_struct *receive_file_
123                                               unsigned short flags, int f)
124  {
125         static time_t modtime;
126 +       static time_t atime;
127         static mode_t mode;
128         static int64 dev;
129         static dev_t rdev;
130 @@ -512,7 +529,7 @@ static struct file_struct *receive_file_
131         struct file_struct *file;
132  
133         if (!flist) {
134 -               modtime = 0, mode = 0;
135 +               modtime = 0, atime = 0, mode = 0;
136                 dev = 0, rdev = makedev(0, 0);
137                 rdev_major = 0;
138                 uid = 0, gid = 0;
139 @@ -568,6 +585,8 @@ static struct file_struct *receive_file_
140                 modtime = (time_t)read_int(f);
141         if (!(flags & XMIT_SAME_MODE))
142                 mode = from_wire_mode(read_int(f));
143 +       if (preserve_atimes && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
144 +               atime = (time_t)read_int(f);
145  
146         if (chmod_modes && !S_ISLNK(mode))
147                 mode = tweak_mode(mode, chmod_modes);
148 @@ -623,6 +642,8 @@ static struct file_struct *receive_file_
149         file->length = file_length;
150         file->mode = mode;
151         file->ids = id_pair(uid, gid);
152 +       if (preserve_atimes)
153 +               file->atime = atime;
154  
155         if (dirname_len) {
156                 file->dirname = lastdir = bp;
157 @@ -648,12 +669,12 @@ static struct file_struct *receive_file_
158                             && lastname[del_hier_name_len-1] == '.'
159                             && lastname[del_hier_name_len-2] == '/')
160                                 del_hier_name_len -= 2;
161 -                       file->flags |= FLAG_TOP_DIR | FLAG_DEL_HERE;
162 +                       FFLAGS(file) |= FLAG_TOP_DIR | FLAG_DEL_HERE;
163                 } else if (in_del_hier) {
164                         if (!relative_paths || !del_hier_name_len
165                          || (l1 >= del_hier_name_len
166                           && lastname[del_hier_name_len] == '/'))
167 -                               file->flags |= FLAG_DEL_HERE;
168 +                               FFLAGS(file) |= FLAG_DEL_HERE;
169                         else
170                                 in_del_hier = 0;
171                 }
172 @@ -874,11 +895,13 @@ struct file_struct *make_file(char *fnam
173         memset(bp, 0, file_struct_len);
174         bp += file_struct_len;
175  
176 -       file->flags = flags;
177 +       FFLAGS(file) = flags;
178         file->modtime = st.st_mtime;
179         file->length = st.st_size;
180         file->mode = st.st_mode;
181         file->ids = id_pair(st.st_uid, st.st_gid);
182 +       if (preserve_atimes)
183 +               file->atime = st.st_atime;
184  
185  #ifdef SUPPORT_HARD_LINKS
186         if (flist && flist->hlink_pool) {
187 @@ -989,7 +1012,7 @@ static void send_if_directory(int f, str
188         char is_dot_dir = fbuf[ol-1] == '.' && (ol == 1 || fbuf[ol-2] == '/');
189  
190         if (S_ISDIR(file->mode)
191 -           && !(file->flags & FLAG_MOUNT_POINT) && f_name(file, fbuf)) {
192 +           && !(FFLAGS(file) & FLAG_MOUNT_POINT) && f_name(file, fbuf)) {
193                 void *save_filters;
194                 unsigned int len = strlen(fbuf);
195                 if (len > 1 && fbuf[len-1] == '/')
196 @@ -1567,8 +1590,9 @@ static void clean_flist(struct file_list
197                         }
198                         /* Make sure that if we unduplicate '.', that we don't
199                          * lose track of a user-specified top directory. */
200 -                       flist->files[keep]->flags |= flist->files[drop]->flags
201 -                                                  & (FLAG_TOP_DIR|FLAG_DEL_HERE);
202 +                       FFLAGS(flist->files[keep])
203 +                           |= FFLAGS(flist->files[drop])
204 +                            & (FLAG_TOP_DIR|FLAG_DEL_HERE);
205  
206                         clear_file(drop, flist);
207  
208 @@ -1630,7 +1654,7 @@ static void output_flist(struct file_lis
209                         file->dirname ? file->dirname : "",
210                         file->dirname ? "/" : "", NS(file->basename),
211                         S_ISDIR(file->mode) ? "/" : "", (int)file->mode,
212 -                       (double)file->length, uidbuf, gidbuf, file->flags);
213 +                       (double)file->length, uidbuf, gidbuf, FFLAGS(file));
214         }
215  }
216  
217 --- orig/generator.c    2006-01-24 19:03:07
218 +++ generator.c 2006-01-24 19:19:42
219 @@ -44,6 +44,7 @@ extern int preserve_uid;
220  extern int preserve_gid;
221  extern int preserve_times;
222  extern int omit_dir_times;
223 +extern int preserve_atimes;
224  extern int delete_before;
225  extern int delete_during;
226  extern int delete_after;
227 @@ -89,6 +90,7 @@ extern dev_t filesystem_dev;
228  extern char *backup_dir;
229  extern char *backup_suffix;
230  extern int backup_suffix_len;
231 +extern unsigned int file_struct_len;
232  extern struct file_list *the_file_list;
233  extern struct filter_list_struct server_filter_list;
234  
235 @@ -183,7 +185,7 @@ static int delete_item(char *fname, int 
236         for (j = dirlist->count; j--; ) {
237                 struct file_struct *fp = dirlist->files[j];
238  
239 -               if (fp->flags & FLAG_MOUNT_POINT)
240 +               if (FFLAGS(fp) & FLAG_MOUNT_POINT)
241                         continue;
242  
243                 strlcpy(p, fp->basename, remainder);
244 @@ -261,7 +263,7 @@ static void delete_in_dir(struct file_li
245         filt_array[cur_depth] = push_local_filters(fbuf, dlen);
246  
247         if (one_file_system) {
248 -               if (file->flags & FLAG_TOP_DIR)
249 +               if (FFLAGS(file) & FLAG_TOP_DIR)
250                         filesystem_dev = stp->st_dev;
251                 else if (filesystem_dev != stp->st_dev)
252                         return;
253 @@ -273,7 +275,7 @@ static void delete_in_dir(struct file_li
254          * from the filesystem. */
255         for (i = dirlist->count; i--; ) {
256                 struct file_struct *fp = dirlist->files[i];
257 -               if (!fp->basename || fp->flags & FLAG_MOUNT_POINT)
258 +               if (!fp->basename || FFLAGS(fp) & FLAG_MOUNT_POINT)
259                         continue;
260                 if (flist_find(flist, fp) < 0) {
261                         int mode = fp->mode;
262 @@ -300,11 +302,11 @@ static void do_delete_pass(struct file_l
263         for (j = 0; j < flist->count; j++) {
264                 struct file_struct *file = flist->files[j];
265  
266 -               if (!(file->flags & FLAG_DEL_HERE))
267 +               if (!(FFLAGS(file) & FLAG_DEL_HERE))
268                         continue;
269  
270                 f_name(file, fbuf);
271 -               if (verbose > 1 && file->flags & FLAG_TOP_DIR)
272 +               if (verbose > 1 && FFLAGS(file) & FLAG_TOP_DIR)
273                         rprintf(FINFO, "deleting in %s\n", fbuf);
274  
275                 if (link_stat(fbuf, &st, keep_dirlinks) < 0
276 @@ -344,10 +346,18 @@ void itemize(struct file_struct *file, i
277  
278                 if (S_ISREG(file->mode) && file->length != st->st_size)
279                         iflags |= ITEM_REPORT_SIZE;
280 -               if ((iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !keep_time
281 -                    && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
282 -                   || (keep_time && cmp_modtime(file->modtime, st->st_mtime) != 0))
283 +               if (iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !keep_time
284 +                    && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname)) {
285                         iflags |= ITEM_REPORT_TIME;
286 +                       if (!preserve_atimes && !S_ISDIR(file->mode))
287 +                               iflags |= ITEM_REPORT_ATIME;
288 +               } else {
289 +                       if (keep_time && cmp_time(file->modtime, st->st_mtime) != 0)
290 +                               iflags |= ITEM_REPORT_TIME;
291 +                       if (preserve_atimes && !S_ISDIR(file->mode)
292 +                        && cmp_time(file->atime, st->st_atime) != 0)
293 +                               iflags |= ITEM_REPORT_ATIME;
294 +               }
295                 if (preserve_perms
296                  && (file->mode & CHMOD_BITS) != (st->st_mode & CHMOD_BITS))
297                         iflags |= ITEM_REPORT_PERMS;
298 @@ -396,7 +406,7 @@ int unchanged_file(char *fn, struct file
299         if (ignore_times)
300                 return 0;
301  
302 -       return cmp_modtime(st->st_mtime, file->modtime) == 0;
303 +       return cmp_time(st->st_mtime, file->modtime) == 0;
304  }
305  
306  
307 @@ -550,13 +560,13 @@ static int find_fuzzy(struct file_struct
308                 uint32 dist;
309  
310                 if (!S_ISREG(fp->mode) || !fp->length
311 -                   || fp->flags & FLAG_NO_FUZZY)
312 +                   || FFLAGS(fp) & FLAG_NO_FUZZY)
313                         continue;
314  
315                 name = fp->basename;
316  
317                 if (fp->length == file->length
318 -                   && cmp_modtime(fp->modtime, file->modtime) == 0) {
319 +                   && cmp_time(fp->modtime, file->modtime) == 0) {
320                         if (verbose > 4) {
321                                 rprintf(FINFO,
322                                         "fuzzy size/modtime match for %s\n",
323 @@ -632,7 +642,7 @@ static int try_dests_reg(struct file_str
324                         if (!unchanged_attrs(file, stp))
325                                 continue;
326                         if ((always_checksum || ignore_times)
327 -                        && cmp_modtime(stp->st_mtime, file->modtime))
328 +                        && cmp_time(stp->st_mtime, file->modtime))
329                                 continue;
330                         best_match = j;
331                         match_level = 3;
332 @@ -894,7 +904,7 @@ static void recv_generator(char *fname, 
333                     && verbose && code && f_out != -1)
334                         rprintf(code, "%s/\n", fname);
335                 if (delete_during && f_out != -1 && !phase && dry_run < 2
336 -                   && (file->flags & FLAG_DEL_HERE))
337 +                   && (FFLAGS(file) & FLAG_DEL_HERE))
338                         delete_in_dir(the_file_list, fname, file, &st);
339                 return;
340         }
341 @@ -1071,7 +1081,7 @@ static void recv_generator(char *fname, 
342         }
343  
344         if (update_only && statret == 0
345 -           && cmp_modtime(st.st_mtime, file->modtime) > 0) {
346 +           && cmp_time(st.st_mtime, file->modtime) > 0) {
347                 if (verbose > 1)
348                         rprintf(FINFO, "%s is newer\n", fname);
349                 return;
350 @@ -1174,7 +1184,7 @@ static void recv_generator(char *fname, 
351         if (fuzzy_basis) {
352                 int j = flist_find(fuzzy_dirlist, file);
353                 if (j >= 0) /* don't use changing file as future fuzzy basis */
354 -                       fuzzy_dirlist->files[j]->flags |= FLAG_NO_FUZZY;
355 +                       FFLAGS(fuzzy_dirlist->files[j]) |= FLAG_NO_FUZZY;
356         }
357  
358         /* open the file */
359 --- orig/hlink.c        2006-01-14 20:27:09
360 +++ hlink.c     2006-01-24 19:17:58
361 @@ -26,6 +26,7 @@ extern int link_dest;
362  extern int make_backups;
363  extern int log_format_has_i;
364  extern char *basis_dir[];
365 +extern unsigned int file_struct_len;
366  extern struct file_list *the_file_list;
367  
368  #ifdef SUPPORT_HARD_LINKS
369 @@ -86,10 +87,10 @@ static void link_idev_data(void)
370                         FPTR(cur)->link_u.links = pool_talloc(hlink_pool,
371                             struct hlink, 1, "hlink_list");
372  
373 -                       FPTR(head)->flags |= FLAG_HLINK_TOL;
374 +                       FFLAGS(FPTR(head)) |= FLAG_HLINK_TOL;
375                         FPTR(cur)->F_HLINDEX = to;
376                         FPTR(cur)->F_NEXT = head;
377 -                       FPTR(cur)->flags |= FLAG_HLINK_EOL;
378 +                       FFLAGS(FPTR(cur)) |= FLAG_HLINK_EOL;
379                         hlink_list[to++] = head;
380                 } else
381                         FPTR(cur)->link_u.links = NULL;
382 @@ -175,7 +176,7 @@ int hard_link_check(struct file_struct *
383  {
384  #ifdef SUPPORT_HARD_LINKS
385         int head;
386 -       if (skip && !(file->flags & FLAG_HLINK_EOL))
387 +       if (skip && !(FFLAGS(file) & FLAG_HLINK_EOL))
388                 head = hlink_list[file->F_HLINDEX] = file->F_NEXT;
389         else
390                 head = hlink_list[file->F_HLINDEX];
391 @@ -270,8 +271,8 @@ void hard_link_cluster(struct file_struc
392         file->F_HLINDEX = FINISHED_LINK;
393         if (link_stat(f_name(file, hlink1), &st1, 0) < 0)
394                 return;
395 -       if (!(file->flags & FLAG_HLINK_TOL)) {
396 -               while (!(file->flags & FLAG_HLINK_EOL)) {
397 +       if (!(FFLAGS(file) & FLAG_HLINK_TOL)) {
398 +               while (!(FFLAGS(file) & FLAG_HLINK_EOL)) {
399                         ndx = file->F_NEXT;
400                         file = FPTR(ndx);
401                 }
402 @@ -286,6 +287,6 @@ void hard_link_cluster(struct file_struc
403                 maybe_hard_link(file, ndx, hlink2, statret, &st2,
404                                 hlink1, &st1, itemizing, code);
405                 file->F_HLINDEX = FINISHED_LINK;
406 -       } while (!(file->flags & FLAG_HLINK_EOL));
407 +       } while (!(FFLAGS(file) & FLAG_HLINK_EOL));
408  #endif
409  }
410 --- orig/log.c  2006-01-24 17:00:34
411 +++ log.c       2005-12-15 23:05:44
412 @@ -38,6 +38,7 @@ extern int module_id;
413  extern int msg_fd_out;
414  extern int protocol_version;
415  extern int preserve_times;
416 +extern int preserve_atimes;
417  extern int log_format_has_i;
418  extern int log_format_has_o_or_i;
419  extern int daemon_log_format_has_o_or_i;
420 @@ -543,11 +544,14 @@ static void log_formatted(enum logcode c
421                         n[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
422                              : !preserve_times || IS_DEVICE(file->mode)
423                                                || S_ISLNK(file->mode) ? 'T' : 't';
424 -                       n[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
425 -                       n[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
426 -                       n[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
427 -                       n[8] = !(iflags & ITEM_REPORT_XATTRS) ? '.' : 'a';
428 -                       n[9] = '\0';
429 +                       n[5] = !(iflags & ITEM_REPORT_ATIME) ? '.'
430 +                            : !preserve_atimes || IS_DEVICE(file->mode)
431 +                                               || S_ISLNK(file->mode) ? 'A' : 'a';
432 +                       n[6] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
433 +                       n[7] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
434 +                       n[8] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
435 +                       n[9] = !(iflags & ITEM_REPORT_XATTRS) ? '.' : 'a';
436 +                       n[10] = '\0';
437  
438                         if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) {
439                                 char ch = iflags & ITEM_IS_NEW ? '+' : '?';
440 --- orig/options.c      2006-01-23 18:48:23
441 +++ options.c   2005-11-07 04:32:19
442 @@ -50,6 +50,7 @@ int preserve_uid = 0;
443  int preserve_gid = 0;
444  int preserve_times = 0;
445  int omit_dir_times = 0;
446 +int preserve_atimes = 0;
447  int update_only = 0;
448  int cvs_exclude = 0;
449  int dry_run = 0;
450 @@ -291,8 +292,9 @@ void usage(enum logcode F)
451    rprintf(F," -o, --owner                 preserve owner (root only)\n");
452    rprintf(F," -g, --group                 preserve group\n");
453    rprintf(F," -D, --devices               preserve devices (root only)\n");
454 -  rprintf(F," -t, --times                 preserve times\n");
455 -  rprintf(F," -O, --omit-dir-times        omit directories when preserving times\n");
456 +  rprintf(F," -t, --times                 preserve modify times\n");
457 +  rprintf(F," -O, --omit-dir-times        omit directories when preserving modify times\n");
458 +  rprintf(F," -k, --atimes                preserve (keep) access times\n");
459    rprintf(F,"     --chmod=CHMOD           change destination permissions\n");
460    rprintf(F," -S, --sparse                handle sparse files efficiently\n");
461    rprintf(F," -n, --dry-run               show what would have been transferred\n");
462 @@ -400,6 +402,9 @@ static struct poptOption long_options[] 
463    {"times",           't', POPT_ARG_VAL,    &preserve_times, 1, 0, 0 },
464    {"no-times",         0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
465    {"no-t",             0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
466 +  {"atimes",          'k', POPT_ARG_VAL,    &preserve_atimes, 1, 0, 0 },
467 +  {"no-atimes",        0,  POPT_ARG_VAL,    &preserve_atimes, 0, 0, 0 },
468 +  {"no-k",             0,  POPT_ARG_VAL,    &preserve_atimes, 0, 0, 0 },
469    {"omit-dir-times",  'O', POPT_ARG_VAL,    &omit_dir_times, 2, 0, 0 },
470    {"modify-window",    0,  POPT_ARG_INT,    &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
471    {"owner",           'o', POPT_ARG_VAL,    &preserve_uid, 1, 0, 0 },
472 @@ -1468,6 +1473,8 @@ void server_options(char **args,int *arg
473                 argstr[x++] = 'D';
474         if (preserve_times)
475                 argstr[x++] = 't';
476 +       if (preserve_atimes)
477 +               argstr[x++] = 'k';
478         if (omit_dir_times == 2 && am_sender)
479                 argstr[x++] = 'O';
480         if (preserve_perms)
481 --- orig/rsync.c        2006-01-24 19:03:07
482 +++ rsync.c     2005-07-28 00:17:37
483 @@ -27,6 +27,7 @@ extern int dry_run;
484  extern int daemon_log_format_has_i;
485  extern int preserve_times;
486  extern int omit_dir_times;
487 +extern int preserve_atimes;
488  extern int am_root;
489  extern int am_server;
490  extern int am_sender;
491 @@ -56,6 +57,7 @@ int set_perms(char *fname,struct file_st
492         int updated = 0;
493         STRUCT_STAT st2;
494         int change_uid, change_gid;
495 +       time_t atime, mtime;
496  
497         if (!st) {
498                 if (dry_run)
499 @@ -70,16 +72,29 @@ int set_perms(char *fname,struct file_st
500  
501         if (!preserve_times || (S_ISDIR(st->st_mode) && omit_dir_times))
502                 flags |= PERMS_SKIP_MTIME;
503 +       if (!preserve_atimes || S_ISDIR(st->st_mode))
504 +               flags |= PERMS_SKIP_ATIME;
505         if (!(flags & PERMS_SKIP_MTIME)
506 -           && cmp_modtime(st->st_mtime, file->modtime) != 0) {
507 -               int ret = set_modtime(fname, file->modtime, st->st_mode);
508 +           && cmp_time(st->st_mtime, file->modtime) != 0) {
509 +               mtime = file->modtime;
510 +               updated = 1;
511 +       } else
512 +               mtime = st->st_mtime;
513 +       if (!(flags & PERMS_SKIP_ATIME)
514 +           && cmp_time(st->st_atime, file->atime) != 0) {
515 +               atime = file->atime;
516 +               updated = 1;
517 +       } else
518 +               atime = st->st_atime;
519 +       if (updated) {
520 +               int ret = set_times(fname, mtime, atime, st->st_mode);
521                 if (ret < 0) {
522                         rsyserr(FERROR, errno, "failed to set times on %s",
523                                 full_fname(fname));
524                         return 0;
525                 }
526 -               if (ret == 0) /* ret == 1 if symlink could not be set */
527 -                       updated = 1;
528 +               if (ret > 0) /* ret == 1 if symlink could not be set */
529 +                       updated = 0;
530         }
531  
532         change_uid = am_root && preserve_uid && st->st_uid != file->ids->uid;
533 --- orig/rsync.h        2006-01-24 19:03:07
534 +++ rsync.h     2006-01-24 19:32:22
535 @@ -54,6 +54,7 @@
536  #define XMIT_HAS_IDEV_DATA (1<<9)
537  #define XMIT_SAME_DEV (1<<10)
538  #define XMIT_RDEV_MINOR_IS_SMALL (1<<11)
539 +#define XMIT_SAME_ATIME (1<<12)
540  
541  /* These flags are used in the live flist data. */
542  
543 @@ -119,6 +120,7 @@
544  
545  #define PERMS_REPORT           (1<<0)
546  #define PERMS_SKIP_MTIME       (1<<1)
547 +#define PERMS_SKIP_ATIME       (1<<2)
548  
549  #define FULL_FLUSH     1
550  #define NORMAL_FLUSH   0
551 @@ -135,6 +137,7 @@
552  #define FNAMECMP_FUZZY         0x83
553  
554  /* For use by the itemize_changes code */
555 +#define ITEM_REPORT_ATIME (1<<0)
556  #define ITEM_REPORT_CHECKSUM (1<<1)
557  #define ITEM_REPORT_SIZE (1<<2)
558  #define ITEM_REPORT_TIME (1<<3)
559 @@ -524,9 +527,12 @@ struct file_struct {
560         struct id_pair *ids;
561         time_t modtime;
562         mode_t mode;
563 +       time_t atime;   /* this MUST be second to last */
564         uchar flags;    /* this item MUST remain last */
565  };
566  
567 +#define FFLAGS(f) ((uchar*)(f))[file_struct_len-1]
568 +
569  /*
570   * Start the flist array at FLIST_START entries and grow it
571   * by doubling until FLIST_LINEAR then grow by FLIST_LINEAR
572 --- orig/rsync.yo       2006-01-24 19:03:08
573 +++ rsync.yo    2005-11-07 04:34:55
574 @@ -319,8 +319,9 @@ to the detailed description below for a 
575   -o, --owner                 preserve owner (root only)
576   -g, --group                 preserve group
577   -D, --devices               preserve devices (root only)
578 - -t, --times                 preserve times
579 - -O, --omit-dir-times        omit directories when preserving times
580 + -t, --times                 preserve modify times
581 + -O, --omit-dir-times        omit directories when preserving mod-times
582 + -k, --atimes                preserve access times
583       --chmod=CHMOD           change destination permissions
584   -S, --sparse                handle sparse files efficiently
585   -n, --dry-run               show what would have been transferred
586 @@ -711,6 +712,12 @@ it is preserving modification times (see
587  the directories on the receiving side, it is a good idea to use bf(-O).
588  This option is inferred if you use bf(--backup) without bf(--backup-dir).
589  
590 +dit(bf(-k, --atimes)) This tells rsync to keep the access times of the
591 +destination files the same value as the source files.  Note that the
592 +reading of the source file may update the atime of the source files, so
593 +repeated rsync runs with --atimes may be needed if you want to force the
594 +access-time values to be 100% identical on the two systems.
595 +
596  dit(bf(--chmod)) This options tells rsync to apply the listed "chmod" pattern
597  to the permission of the files on the destination.  In addition to the normal
598  parsing rules specified in the chmod manpage, you can specify an item that
599 @@ -1180,7 +1187,7 @@ with older versions of rsync, but that a
600  verbose messages).
601  
602  The "%i" escape has a cryptic output that is 9 letters long.  The general
603 -format is like the string bf(UXcstpoga)), where bf(U) is replaced by the
604 +format is like the string bf(UXcstapogx)), where bf(U) is replaced by the
605  kind of update being done, bf(X) is replaced by the file-type, and the
606  other letters represent attributes that may be output if they are being
607  modified.
608 @@ -1219,17 +1226,22 @@ quote(itemize(
609    by the file transfer.
610    it() A bf(t) means the modification time is different and is being updated
611    to the sender's value (requires bf(--times)).  An alternate value of bf(T)
612 -  means that the time will be set to the transfer time, which happens
613 +  means that the modify time will be set to the transfer time, which happens
614    anytime a symlink is transferred, or when a file or device is transferred
615    without bf(--times).
616 +  it() A bf(a) means the access time is different and is being updated to
617 +  the sender's value (requires bf(--atimes)).  An alternate value of bf(A)
618 +  means that the access time  will be set to the transfer time, which happens
619 +  anytime a symlink is transferred, or when a file or device is transferred
620 +  without bf(--atimes).
621    it() A bf(p) means the permissions are different and are being updated to
622    the sender's value (requires bf(--perms)).
623    it() An bf(o) means the owner is different and is being updated to the
624    sender's value (requires bf(--owner) and root privileges).
625    it() A bf(g) means the group is different and is being updated to the
626    sender's value (requires bf(--group) and the authority to set the group).
627 -  it() The bf(a) is reserved for a future enhanced version that supports
628 -  extended file attributes, such as ACLs.
629 +  it() The bf(x) is reserved for a future enhanced version that supports
630 +  extended file attributes.
631  ))
632  
633  One other output is possible:  when deleting files, the "%i" will output
634 --- orig/sender.c       2006-01-14 20:27:10
635 +++ sender.c    2006-01-24 18:10:23
636 @@ -38,6 +38,7 @@ extern int do_progress;
637  extern int inplace;
638  extern int batch_fd;
639  extern int write_batch;
640 +extern unsigned int file_struct_len;
641  extern struct stats stats;
642  extern struct file_list *the_file_list;
643  extern char *log_format;
644 @@ -126,7 +127,7 @@ void successful_send(int ndx)
645  
646         file = the_file_list->files[ndx];
647         /* The generator might tell us about symlinks we didn't send. */
648 -       if (!(file->flags & FLAG_SENT) && !S_ISLNK(file->mode))
649 +       if (!(FFLAGS(file) & FLAG_SENT) && !S_ISLNK(file->mode))
650                 return;
651         if (file->dir.root) {
652                 offset = stringjoin(fname, sizeof fname,
653 @@ -370,7 +371,7 @@ void send_files(struct file_list *flist,
654                         rprintf(FINFO, "sender finished %s\n", fname);
655  
656                 /* Flag that we actually sent this entry. */
657 -               file->flags |= FLAG_SENT;
658 +               FFLAGS(file) |= FLAG_SENT;
659         }
660         make_backups = save_make_backups;
661  
662 --- orig/testsuite/atimes.test  2006-01-24 19:30:25
663 +++ testsuite/atimes.test       2006-01-24 19:30:25
664 @@ -0,0 +1,19 @@
665 +#! /bin/sh
666 +
667 +# Test rsync copying atimes
668 +
669 +. "$suitedir/rsync.fns"
670 +
671 +set -x
672 +
673 +mkdir "$fromdir"
674 +
675 +touch "$fromdir/foo"
676 +touch -a -t 200102031717.42 "$fromdir/foo"
677 +
678 +TLS_ARGS=--atime
679 +
680 +checkit "$RSYNC -rtkgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
681 +
682 +# The script would have aborted on error, so getting here means we've won.
683 +exit 0
684 --- orig/testsuite/itemize.test 2005-12-15 23:00:49
685 +++ testsuite/itemize.test      2006-01-24 19:29:18
686 @@ -44,14 +44,14 @@ ln "$fromdir/foo/config1" "$fromdir/foo/
687  $RSYNC -iplr "$fromdir/" "$todir/" \
688      | tee "$outfile"
689  cat <<EOT >"$chkfile"
690 -cd+++++++ bar/
691 -cd+++++++ bar/baz/
692 ->f+++++++ bar/baz/rsync
693 -cd+++++++ foo/
694 ->f+++++++ foo/config1
695 ->f+++++++ foo/config2
696 ->f+++++++ foo/extra
697 -cL+++++++ foo/sym -> ../bar/baz/rsync
698 +cd++++++++ bar/
699 +cd++++++++ bar/baz/
700 +>f++++++++ bar/baz/rsync
701 +cd++++++++ foo/
702 +>f++++++++ foo/config1
703 +>f++++++++ foo/config2
704 +>f++++++++ foo/extra
705 +cL++++++++ foo/sym -> ../bar/baz/rsync
706  EOT
707  diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
708  
709 @@ -63,10 +63,10 @@ chmod 601 "$fromdir/foo/config2"
710  $RSYNC -iplrH "$fromdir/" "$todir/" \
711      | tee "$outfile"
712  cat <<EOT >"$chkfile"
713 ->f..T.... bar/baz/rsync
714 ->f..T.... foo/config1
715 ->f.sTp... foo/config2
716 -hf..T.... foo/extra => foo/config1
717 +>f..TA.... bar/baz/rsync
718 +>f..TA.... foo/config1
719 +>f.sTAp... foo/config2
720 +hf..TA.... foo/extra => foo/config1
721  EOT
722  diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
723  
724 @@ -83,11 +83,11 @@ chmod 777 "$todir/bar/baz/rsync"
725  $RSYNC -iplrtc "$fromdir/" "$todir/" \
726      | tee "$outfile"
727  cat <<EOT >"$chkfile"
728 -.f..tp... bar/baz/rsync
729 -.d..t.... foo/
730 -.f..t.... foo/config1
731 ->fcstp... foo/config2
732 -cL..T.... foo/sym -> ../bar/baz/rsync
733 +.f..t.p... bar/baz/rsync
734 +.d..t..... foo/
735 +.f..t..... foo/config1
736 +>fcst.p... foo/config2
737 +cL..TA.... foo/sym -> ../bar/baz/rsync
738  EOT
739  diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
740  
741 @@ -112,15 +112,15 @@ $RSYNC -ivvplrtH "$fromdir/" "$todir/" \
742      | tee "$outfile"
743  filter_outfile
744  cat <<EOT >"$chkfile"
745 -.d        ./
746 -.d        bar/
747 -.d        bar/baz/
748 -.f...p... bar/baz/rsync
749 -.d        foo/
750 -.f        foo/config1
751 ->f..t.... foo/config2
752 -hf        foo/extra
753 -.L        foo/sym -> ../bar/baz/rsync
754 +.d         ./
755 +.d         bar/
756 +.d         bar/baz/
757 +.f....p... bar/baz/rsync
758 +.d         foo/
759 +.f         foo/config1
760 +>f..t..... foo/config2
761 +hf         foo/extra
762 +.L         foo/sym -> ../bar/baz/rsync
763  EOT
764  diff $diffopt "$chkfile" "$outfile" || test_fail "test 5 failed"
765  
766 @@ -139,8 +139,8 @@ touch "$todir/foo/config2"
767  $RSYNC -iplrtH "$fromdir/" "$todir/" \
768      | tee "$outfile"
769  cat <<EOT >"$chkfile"
770 -.f...p... foo/config1
771 ->f..t.... foo/config2
772 +.f....p... foo/config1
773 +>f..t..... foo/config2
774  EOT
775  diff $diffopt "$chkfile" "$outfile" || test_fail "test 7 failed"
776  
777 @@ -149,15 +149,15 @@ $RSYNC -ivvplrtH --copy-dest="$lddir" "$
778      | tee "$outfile"
779  filter_outfile
780  cat <<EOT >"$chkfile"
781 -.d..t.... ./
782 -cd+++++++ bar/
783 -cd+++++++ bar/baz/
784 -cf        bar/baz/rsync
785 -cd+++++++ foo/
786 -cf        foo/config1
787 -cf        foo/config2
788 -hf        foo/extra => foo/config1
789 -cL..T.... foo/sym -> ../bar/baz/rsync
790 +.d..t..... ./
791 +cd++++++++ bar/
792 +cd++++++++ bar/baz/
793 +cf         bar/baz/rsync
794 +cd++++++++ foo/
795 +cf         foo/config1
796 +cf         foo/config2
797 +hf         foo/extra => foo/config1
798 +cL..TA.... foo/sym -> ../bar/baz/rsync
799  EOT
800  diff $diffopt "$chkfile" "$outfile" || test_fail "test 8 failed"
801  
802 @@ -165,11 +165,11 @@ rm -rf "$todir"
803  $RSYNC -iplrtH --copy-dest="$lddir" "$fromdir/" "$todir/" \
804      | tee "$outfile"
805  cat <<EOT >"$chkfile"
806 -.d..t.... ./
807 -cd+++++++ bar/
808 -cd+++++++ bar/baz/
809 -cd+++++++ foo/
810 -hf        foo/extra => foo/config1
811 +.d..t..... ./
812 +cd++++++++ bar/
813 +cd++++++++ bar/baz/
814 +cd++++++++ foo/
815 +hf         foo/extra => foo/config1
816  EOT
817  diff $diffopt "$chkfile" "$outfile" || test_fail "test 9 failed"
818  
819 @@ -196,15 +196,15 @@ $RSYNC -ivvplrtH --link-dest="$lddir" "$
820      | tee "$outfile"
821  filter_outfile
822  cat <<EOT >"$chkfile"
823 -.d..t.... ./
824 -cd+++++++ bar/
825 -cd+++++++ bar/baz/
826 -hf        bar/baz/rsync
827 -cd+++++++ foo/
828 -hf        foo/config1
829 -hf        foo/config2
830 -hf        foo/extra => foo/config1
831 -hL        foo/sym -> ../bar/baz/rsync
832 +.d..t..... ./
833 +cd++++++++ bar/
834 +cd++++++++ bar/baz/
835 +hf         bar/baz/rsync
836 +cd++++++++ foo/
837 +hf         foo/config1
838 +hf         foo/config2
839 +hf         foo/extra => foo/config1
840 +hL         foo/sym -> ../bar/baz/rsync
841  EOT
842  diff $diffopt "$chkfile" "$outfile" || test_fail "test 11 failed"
843  
844 @@ -212,10 +212,10 @@ rm -rf "$todir"
845  $RSYNC -iplrtH --link-dest="$lddir" "$fromdir/" "$todir/" \
846      | tee "$outfile"
847  cat <<EOT >"$chkfile"
848 -.d..t.... ./
849 -cd+++++++ bar/
850 -cd+++++++ bar/baz/
851 -cd+++++++ foo/
852 +.d..t..... ./
853 +cd++++++++ bar/
854 +cd++++++++ bar/baz/
855 +cd++++++++ foo/
856  EOT
857  diff $diffopt "$chkfile" "$outfile" || test_fail "test 12 failed"
858  
859 @@ -243,14 +243,14 @@ filter_outfile
860  # TODO fix really-old problem when combining -H with --compare-dest:
861  # missing output for foo/extra hard-link (and it might not be updated)!
862  cat <<EOT >"$chkfile"
863 -.d..t.... ./
864 -cd+++++++ bar/
865 -cd+++++++ bar/baz/
866 -.f        bar/baz/rsync
867 -cd+++++++ foo/
868 -.f        foo/config1
869 -.f        foo/config2
870 -.L        foo/sym -> ../bar/baz/rsync
871 +.d..t..... ./
872 +cd++++++++ bar/
873 +cd++++++++ bar/baz/
874 +.f         bar/baz/rsync
875 +cd++++++++ foo/
876 +.f         foo/config1
877 +.f         foo/config2
878 +.L         foo/sym -> ../bar/baz/rsync
879  EOT
880  diff $diffopt "$chkfile" "$outfile" || test_fail "test 14 failed"
881  
882 @@ -258,10 +258,10 @@ rm -rf "$todir"
883  $RSYNC -iplrtH --compare-dest="$lddir" "$fromdir/" "$todir/" \
884      | tee "$outfile"
885  cat <<EOT >"$chkfile"
886 -.d..t.... ./
887 -cd+++++++ bar/
888 -cd+++++++ bar/baz/
889 -cd+++++++ foo/
890 +.d..t..... ./
891 +cd++++++++ bar/
892 +cd++++++++ bar/baz/
893 +cd++++++++ foo/
894  EOT
895  diff $diffopt "$chkfile" "$outfile" || test_fail "test 15 failed"
896  
897 --- orig/testsuite/rsync.fns    2005-06-10 21:33:28
898 +++ testsuite/rsync.fns 2005-07-28 00:41:20
899 @@ -50,7 +50,7 @@ printmsg() {
900  
901  
902  rsync_ls_lR() {
903 -    find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls"
904 +    find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls" $TLS_ARGS
905  }
906  
907  rsync_getgroups() { 
908 @@ -158,6 +158,10 @@ checkit() {
909      # We can just write everything to stdout/stderr, because the
910      # wrapper hides it unless there is a problem.
911  
912 +    if test x$TLS_ARGS = x--atime; then
913 +       ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
914 +    fi
915 +
916      echo "Running: \"$1\""  
917      eval "$1" 
918      status=$?
919 @@ -165,10 +169,13 @@ checkit() {
920         failed="YES";
921      fi
922  
923 +    if test x$TLS_ARGS != x--atime; then
924 +       ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
925 +    fi
926 +
927      echo "-------------"
928      echo "check how the directory listings compare with diff:"
929      echo ""
930 -    ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
931      ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
932      diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
933  
934 --- orig/tls.c  2005-09-24 17:40:31
935 +++ tls.c       2005-03-23 17:49:48
936 @@ -39,6 +39,7 @@
937  
938  
939  #include "rsync.h"
940 +#include "popt.h"
941  
942  #define PROGRAM "tls"
943  
944 @@ -48,6 +49,7 @@ int read_only = 1;
945  int list_only = 0;
946  int preserve_perms = 0;
947  
948 +static int display_atime = 0;
949  
950  static void failed(char const *what, char const *where)
951  {
952 @@ -56,14 +58,29 @@ static void failed(char const *what, cha
953         exit(1);
954  }
955  
956 +static void storetime(char *dest, time_t t)
957 +{
958 +       if (t) {
959 +               struct tm *mt = gmtime(&t);
960  
961 +               sprintf(dest, "%04d-%02d-%02d %02d:%02d:%02d ",
962 +                       (int)mt->tm_year + 1900,
963 +                       (int)mt->tm_mon + 1,
964 +                       (int)mt->tm_mday,
965 +                       (int)mt->tm_hour,
966 +                       (int)mt->tm_min,
967 +                       (int)mt->tm_sec);
968 +       } else {
969 +               strcpy(dest, "                    ");
970 +       }
971 +}      
972  
973  static void list_file(const char *fname)
974  {
975         STRUCT_STAT buf;
976         char permbuf[PERMSTRING_SIZE];
977 -       struct tm *mt;
978 -       char datebuf[50];
979 +       char mtimebuf[50];
980 +       char atimebuf[50];
981         char linkbuf[4096];
982  
983         if (do_lstat(fname, &buf) < 0)
984 @@ -96,19 +113,8 @@ static void list_file(const char *fname)
985  
986         permstring(permbuf, buf.st_mode);
987  
988 -       if (buf.st_mtime) {
989 -               mt = gmtime(&buf.st_mtime);
990 -
991 -               sprintf(datebuf, "%04d-%02d-%02d %02d:%02d:%02d",
992 -                       (int)mt->tm_year + 1900,
993 -                       (int)mt->tm_mon + 1,
994 -                       (int)mt->tm_mday,
995 -                       (int)mt->tm_hour,
996 -                       (int)mt->tm_min,
997 -                       (int)mt->tm_sec);
998 -       } else {
999 -               strcpy(datebuf, "                   ");
1000 -       }
1001 +       storetime(mtimebuf, buf.st_mtime);
1002 +       storetime(atimebuf, buf.st_atime);
1003  
1004         /* TODO: Perhaps escape special characters in fname? */
1005  
1006 @@ -119,24 +125,55 @@ static void list_file(const char *fname)
1007                     (long)minor(buf.st_rdev));
1008         } else /* NB: use double for size since it might not fit in a long. */
1009                 printf("%12.0f", (double)buf.st_size);
1010 -       printf(" %6ld.%-6ld %6ld %s %s%s\n",
1011 +       printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
1012                (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
1013 -              datebuf, fname, linkbuf);
1014 +              mtimebuf, display_atime && !S_ISDIR(buf.st_mode) ? atimebuf : "",
1015 +              fname, linkbuf);
1016  }
1017  
1018 +static struct poptOption long_options[] = {
1019 +  /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
1020 +  {"atime",           'u', POPT_ARG_NONE,   &display_atime, 0,   0, 0},
1021 +  {"help",            'h', POPT_ARG_NONE,   0,              'h', 0, 0},
1022 +  {0,0,0,0,0,0,0}
1023 +};
1024 +
1025 +static void tls_usage(int ret)
1026 +{
1027 +       fprintf(stderr, "usage: " PROGRAM " [--atime | -u] DIR ...\n"
1028 +           "Trivial file listing program for portably checking rsync\n");
1029 +       exit(ret);
1030 +}
1031  
1032  int
1033  main(int argc, char *argv[])
1034  {
1035 -       if (argc < 2) {
1036 -               fprintf(stderr, "usage: " PROGRAM " DIR ...\n"
1037 -                       "Trivial file listing program for portably checking rsync\n");
1038 -               return 1;
1039 +       poptContext pc;
1040 +       const char **extra_args;
1041 +       int opt;
1042 +
1043 +       pc = poptGetContext(PROGRAM, argc, (const char **)argv,
1044 +                           long_options, 0);
1045 +       while ((opt = poptGetNextOpt(pc)) != -1) {
1046 +               switch (opt) {
1047 +               case 'h':
1048 +                       tls_usage(0);
1049 +               default:
1050 +                       fprintf(stderr,
1051 +                               "%s: %s\n",
1052 +                               poptBadOption(pc, POPT_BADOPTION_NOALIAS),
1053 +                               poptStrerror(opt));
1054 +                       tls_usage(1);
1055 +               }
1056         }
1057  
1058 -       for (argv++; *argv; argv++) {
1059 -               list_file(*argv);
1060 -       }
1061 +       extra_args = poptGetArgs(pc);
1062 +       if (*extra_args == NULL)
1063 +               tls_usage(1);
1064 +
1065 +       for (; *extra_args; extra_args++)
1066 +               list_file(*extra_args);
1067 +       poptFreeContext(pc);
1068  
1069         return 0;
1070  }
1071 --- orig/util.c 2006-01-20 00:12:48
1072 +++ util.c      2006-01-14 08:20:29
1073 @@ -130,7 +130,7 @@ void overflow_exit(char *str)
1074  
1075  
1076  
1077 -int set_modtime(char *fname, time_t modtime, mode_t mode)
1078 +int set_times(char *fname, time_t modtime, time_t atime, mode_t mode)
1079  {
1080  #if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
1081         if (S_ISLNK(mode))
1082 @@ -138,9 +138,13 @@ int set_modtime(char *fname, time_t modt
1083  #endif
1084  
1085         if (verbose > 2) {
1086 -               rprintf(FINFO, "set modtime of %s to (%ld) %s",
1087 +               char mtimebuf[200];
1088 +
1089 +               strlcpy(mtimebuf, timestring(modtime), sizeof mtimebuf);
1090 +               rprintf(FINFO,
1091 +                       "set modtime, atime of %s to (%ld) %s, (%ld) %s\n",
1092                         fname, (long)modtime,
1093 -                       asctime(localtime(&modtime)));
1094 +                       mtimebuf, (long)atime, timestring(atime));
1095         }
1096  
1097         if (dry_run)
1098 @@ -149,7 +153,7 @@ int set_modtime(char *fname, time_t modt
1099         {
1100  #ifdef HAVE_UTIMES
1101                 struct timeval t[2];
1102 -               t[0].tv_sec = time(NULL);
1103 +               t[0].tv_sec = atime;
1104                 t[0].tv_usec = 0;
1105                 t[1].tv_sec = modtime;
1106                 t[1].tv_usec = 0;
1107 @@ -160,12 +164,12 @@ int set_modtime(char *fname, time_t modt
1108                 return utimes(fname, t);
1109  #elif defined HAVE_UTIMBUF
1110                 struct utimbuf tbuf;
1111 -               tbuf.actime = time(NULL);
1112 +               tbuf.actime = atime;
1113                 tbuf.modtime = modtime;
1114                 return utime(fname,&tbuf);
1115  #elif defined HAVE_UTIME
1116                 time_t t[2];
1117 -               t[0] = time(NULL);
1118 +               t[0] = atime;
1119                 t[1] = modtime;
1120                 return utime(fname,t);
1121  #else
1122 @@ -1175,8 +1179,8 @@ int msleep(int t)
1123  
1124  
1125  /**
1126 - * Determine if two file modification times are equivalent (either
1127 - * exact or in the modification timestamp window established by
1128 + * Determine if two file  times are equivalent (either
1129 + * exact or in the timestamp window established by
1130   * --modify-window).
1131   *
1132   * @retval 0 if the times should be treated as the same
1133 @@ -1185,7 +1189,7 @@ int msleep(int t)
1134   *
1135   * @retval -1 if the 2nd is later
1136   **/
1137 -int cmp_modtime(time_t file1, time_t file2)
1138 +int cmp_time(time_t file1, time_t file2)
1139  {
1140         if (file2 > file1) {
1141                 if (file2 - file1 <= modify_window)