f27e238c0f0d135a13248c4d58229ae98636f034
[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        2005-04-09 18:00:28
8 +++ batch.c     2004-07-03 20:15:41
9 @@ -208,6 +208,8 @@ void show_flist(int index, struct file_s
10                 rprintf(FINFO, "flist->flags=%#x\n", fptr[i]->flags);
11                 rprintf(FINFO, "flist->modtime=%#lx\n",
12                         (long unsigned) fptr[i]->modtime);
13 +               rprintf(FINFO, "flist->atime=%#lx\n",
14 +                       (long unsigned) fptr[i]->atime);
15                 rprintf(FINFO, "flist->length=%.0f\n",
16                         (double) fptr[i]->length);
17                 rprintf(FINFO, "flist->mode=%#o\n", (int) fptr[i]->mode);
18 --- orig/flist.c        2005-09-17 21:48:45
19 +++ flist.c     2005-07-28 00:16:34
20 @@ -50,6 +50,7 @@ extern int preserve_perms;
21  extern int preserve_devices;
22  extern int preserve_uid;
23  extern int preserve_gid;
24 +extern int preserve_atimes;
25  extern int relative_paths;
26  extern int implied_dirs;
27  extern int copy_links;
28 @@ -141,16 +142,18 @@ static void list_file_entry(struct file_
29  
30  #ifdef SUPPORT_LINKS
31         if (preserve_links && S_ISLNK(f->mode)) {
32 -               rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
33 +               rprintf(FINFO, "%s %11.0f %s %s %s -> %s\n",
34                         perms,
35                         (double)f->length, timestring(f->modtime),
36 +                       timestring(f->atime),
37                         safe_fname(f_name(f)), safe_fname(f->u.link));
38         } else
39  #endif
40         {
41 -               rprintf(FINFO, "%s %11.0f %s %s\n",
42 +               rprintf(FINFO, "%s %11.0f %s %s %s\n",
43                         perms,
44                         (double)f->length, timestring(f->modtime),
45 +                       timestring(f->atime),
46                         safe_fname(f_name(f)));
47         }
48  }
49 @@ -314,6 +317,7 @@ void send_file_entry(struct file_struct 
50  {
51         unsigned short flags;
52         static time_t modtime;
53 +       static time_t atime;
54         static mode_t mode;
55         static int64 dev;
56         static dev_t rdev;
57 @@ -329,7 +333,7 @@ void send_file_entry(struct file_struct 
58  
59         if (!file) {
60                 write_byte(f, 0);
61 -               modtime = 0, mode = 0;
62 +               modtime = 0, atime = 0, mode = 0;
63                 dev = 0, rdev = makedev(0, 0);
64                 rdev_major = 0;
65                 uid = 0, gid = 0;
66 @@ -378,6 +382,12 @@ void send_file_entry(struct file_struct 
67                 flags |= XMIT_SAME_TIME;
68         else
69                 modtime = file->modtime;
70 +       if (preserve_atimes && !S_ISDIR(mode)) {
71 +               if (file->atime == atime)
72 +                       flags |= XMIT_SAME_ATIME;
73 +               else
74 +                       atime = file->atime;
75 +       }
76  
77  #ifdef SUPPORT_HARD_LINKS
78         if (file->link_u.idev) {
79 @@ -433,6 +443,8 @@ void send_file_entry(struct file_struct 
80                 write_int(f, modtime);
81         if (!(flags & XMIT_SAME_MODE))
82                 write_int(f, to_wire_mode(mode));
83 +       if (preserve_atimes && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
84 +               write_int(f, atime);
85         if (preserve_uid && !(flags & XMIT_SAME_UID)) {
86                 if (!numeric_ids)
87                         add_uid(uid);
88 @@ -503,6 +515,7 @@ static struct file_struct *receive_file_
89                                               unsigned short flags, int f)
90  {
91         static time_t modtime;
92 +       static time_t atime;
93         static mode_t mode;
94         static int64 dev;
95         static dev_t rdev;
96 @@ -521,7 +534,7 @@ static struct file_struct *receive_file_
97         struct file_struct *file;
98  
99         if (!flist) {
100 -               modtime = 0, mode = 0;
101 +               modtime = 0, atime = 0, mode = 0;
102                 dev = 0, rdev = makedev(0, 0);
103                 rdev_major = 0;
104                 uid = 0, gid = 0;
105 @@ -577,6 +590,8 @@ static struct file_struct *receive_file_
106                 modtime = (time_t)read_int(f);
107         if (!(flags & XMIT_SAME_MODE))
108                 mode = from_wire_mode(read_int(f));
109 +       if (preserve_atimes && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
110 +               atime = (time_t)read_int(f);
111  
112         if (preserve_uid && !(flags & XMIT_SAME_UID))
113                 uid = (uid_t)read_int(f);
114 @@ -627,6 +642,7 @@ static struct file_struct *receive_file_
115  
116         file->flags = 0;
117         file->modtime = modtime;
118 +       file->atime = atime;
119         file->length = file_length;
120         file->mode = mode;
121         file->uid = uid;
122 @@ -876,6 +892,7 @@ skip_filters:
123  
124         file->flags = flags;
125         file->modtime = st.st_mtime;
126 +       file->atime = st.st_atime;
127         file->length = st.st_size;
128         file->mode = st.st_mode;
129         file->uid = st.st_uid;
130 --- orig/generator.c    2005-09-15 18:09:14
131 +++ generator.c 2005-07-28 00:14:43
132 @@ -44,6 +44,7 @@ extern int preserve_uid;
133  extern int preserve_gid;
134  extern int preserve_times;
135  extern int omit_dir_times;
136 +extern int preserve_atimes;
137  extern int delete_before;
138  extern int delete_during;
139  extern int delete_after;
140 @@ -324,9 +325,21 @@ void itemize(struct file_struct *file, i
141                             : S_ISDIR(file->mode) ? !omit_dir_times
142                             : !S_ISLNK(file->mode);
143  
144 +                       if (iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !keep_time
145 +                            && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname)) {
146 +                               iflags |= ITEM_REPORT_TIME;
147 +                               if (!preserve_atimes && !S_ISDIR(file->mode))
148 +                                       iflags |= ITEM_REPORT_ATIME;
149 +                       } else {
150 +                               if (keep_time && cmp_time(file->modtime, st->st_mtime) != 0)
151 +                                       iflags |= ITEM_REPORT_TIME;
152 +                               if (preserve_atimes && !S_ISDIR(file->mode)
153 +                                && cmp_time(file->atime, st->st_atime) != 0)
154 +                                       iflags |= ITEM_REPORT_ATIME;
155 +                       }
156                         if ((iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !keep_time
157                              && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
158 -                           || (keep_time && cmp_modtime(file->modtime, st->st_mtime) != 0))
159 +                           || (keep_time && cmp_time(file->modtime, st->st_mtime) != 0))
160                                 iflags |= ITEM_REPORT_TIME;
161                         if (preserve_perms
162                          && (file->mode & CHMOD_BITS) != (st->st_mode & CHMOD_BITS))
163 @@ -378,7 +391,7 @@ static int unchanged_file(char *fn, stru
164         if (ignore_times)
165                 return 0;
166  
167 -       return cmp_modtime(st->st_mtime, file->modtime) == 0;
168 +       return cmp_time(st->st_mtime, file->modtime) == 0;
169  }
170  
171  
172 @@ -538,7 +551,7 @@ static int find_fuzzy(struct file_struct
173                 name = fp->basename;
174  
175                 if (fp->length == file->length
176 -                   && cmp_modtime(fp->modtime, file->modtime) == 0) {
177 +                   && cmp_time(fp->modtime, file->modtime) == 0) {
178                         if (verbose > 4) {
179                                 rprintf(FINFO,
180                                         "fuzzy size/modtime match for %s\n",
181 @@ -881,7 +894,7 @@ static void recv_generator(char *fname, 
182         }
183  
184         if (update_only && statret == 0
185 -           && cmp_modtime(st.st_mtime, file->modtime) > 0) {
186 +           && cmp_time(st.st_mtime, file->modtime) > 0) {
187                 if (verbose > 1)
188                         rprintf(FINFO, "%s is newer\n", safe_fname(fname));
189                 return;
190 --- orig/log.c  2005-06-10 21:33:28
191 +++ log.c       2005-07-28 00:22:30
192 @@ -38,6 +38,7 @@ extern int module_id;
193  extern int msg_fd_out;
194  extern int protocol_version;
195  extern int preserve_times;
196 +extern int preserve_atimes;
197  extern int log_format_has_o_or_i;
198  extern int daemon_log_format_has_o_or_i;
199  extern char *auth_user;
200 @@ -501,11 +502,14 @@ static void log_formatted(enum logcode c
201                         n[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
202                              : !preserve_times || IS_DEVICE(file->mode)
203                                                || S_ISLNK(file->mode) ? 'T' : 't';
204 -                       n[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
205 -                       n[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
206 -                       n[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
207 -                       n[8] = !(iflags & ITEM_REPORT_XATTRS) ? '.' : 'a';
208 -                       n[9] = '\0';
209 +                       n[5] = !(iflags & ITEM_REPORT_ATIME) ? '.'
210 +                            : !preserve_atimes || IS_DEVICE(file->mode)
211 +                                               || S_ISLNK(file->mode) ? 'A' : 'a';
212 +                       n[6] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
213 +                       n[7] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
214 +                       n[8] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
215 +                       n[9] = !(iflags & ITEM_REPORT_XATTRS) ? '.' : 'a';
216 +                       n[10] = '\0';
217  
218                         if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) {
219                                 char ch = iflags & ITEM_IS_NEW ? '+' : '?';
220 --- orig/options.c      2005-09-24 17:40:31
221 +++ options.c   2005-08-27 21:16:51
222 @@ -49,6 +49,7 @@ int preserve_uid = 0;
223  int preserve_gid = 0;
224  int preserve_times = 0;
225  int omit_dir_times = 0;
226 +int preserve_atimes = 0;
227  int update_only = 0;
228  int cvs_exclude = 0;
229  int dry_run = 0;
230 @@ -286,8 +287,9 @@ void usage(enum logcode F)
231    rprintf(F," -o, --owner                 preserve owner (root only)\n");
232    rprintf(F," -g, --group                 preserve group\n");
233    rprintf(F," -D, --devices               preserve devices (root only)\n");
234 -  rprintf(F," -t, --times                 preserve times\n");
235 -  rprintf(F," -O, --omit-dir-times        omit directories when preserving times\n");
236 +  rprintf(F," -t, --times                 preserve modify times\n");
237 +  rprintf(F," -O, --omit-dir-times        omit directories when preserving modify times\n");
238 +  rprintf(F," -A, --atimes                preserve access times\n");
239    rprintf(F," -S, --sparse                handle sparse files efficiently\n");
240    rprintf(F," -n, --dry-run               show what would have been transferred\n");
241    rprintf(F," -W, --whole-file            copy files whole (without rsync algorithm)\n");
242 @@ -388,6 +390,9 @@ static struct poptOption long_options[] 
243    {"times",           't', POPT_ARG_VAL,    &preserve_times, 1, 0, 0 },
244    {"no-times",         0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
245    {"no-t",             0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
246 +  {"atimes",          'A', POPT_ARG_VAL,    &preserve_atimes, 1, 0, 0 },
247 +  {"no-atimes",        0,  POPT_ARG_VAL,    &preserve_atimes, 0, 0, 0 },
248 +  {"no-A",             0,  POPT_ARG_VAL,    &preserve_atimes, 0, 0, 0 },
249    {"omit-dir-times",  'O', POPT_ARG_VAL,    &omit_dir_times, 2, 0, 0 },
250    {"modify-window",    0,  POPT_ARG_INT,    &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
251    {"owner",           'o', POPT_ARG_VAL,    &preserve_uid, 1, 0, 0 },
252 @@ -1356,6 +1361,8 @@ void server_options(char **args,int *arg
253                 argstr[x++] = 'D';
254         if (preserve_times)
255                 argstr[x++] = 't';
256 +       if (preserve_atimes)
257 +               argstr[x++] = 'A';
258         if (omit_dir_times == 2 && am_sender)
259                 argstr[x++] = 'O';
260         if (preserve_perms)
261 --- orig/rsync.c        2005-07-27 23:31:12
262 +++ rsync.c     2005-07-28 00:17:37
263 @@ -27,6 +27,7 @@ extern int dry_run;
264  extern int daemon_log_format_has_i;
265  extern int preserve_times;
266  extern int omit_dir_times;
267 +extern int preserve_atimes;
268  extern int am_root;
269  extern int am_server;
270  extern int am_sender;
271 @@ -56,6 +57,7 @@ int set_perms(char *fname,struct file_st
272         int updated = 0;
273         STRUCT_STAT st2;
274         int change_uid, change_gid;
275 +       time_t atime, mtime;
276  
277         if (!st) {
278                 if (dry_run)
279 @@ -70,16 +72,29 @@ int set_perms(char *fname,struct file_st
280  
281         if (!preserve_times || (S_ISDIR(st->st_mode) && omit_dir_times))
282                 flags |= PERMS_SKIP_MTIME;
283 +       if (!preserve_atimes || S_ISDIR(st->st_mode))
284 +               flags |= PERMS_SKIP_ATIME;
285         if (!(flags & PERMS_SKIP_MTIME)
286 -           && cmp_modtime(st->st_mtime, file->modtime) != 0) {
287 -               int ret = set_modtime(fname, file->modtime, st->st_mode);
288 +           && cmp_time(st->st_mtime, file->modtime) != 0) {
289 +               mtime = file->modtime;
290 +               updated = 1;
291 +       } else
292 +               mtime = st->st_mtime;
293 +       if (!(flags & PERMS_SKIP_ATIME)
294 +           && cmp_time(st->st_atime, file->atime) != 0) {
295 +               atime = file->atime;
296 +               updated = 1;
297 +       } else
298 +               atime = st->st_atime;
299 +       if (updated) {
300 +               int ret = set_times(fname, mtime, atime, st->st_mode);
301                 if (ret < 0) {
302                         rsyserr(FERROR, errno, "failed to set times on %s",
303                                 full_fname(fname));
304                         return 0;
305                 }
306 -               if (ret == 0) /* ret == 1 if symlink could not be set */
307 -                       updated = 1;
308 +               if (ret > 0) /* ret == 1 if symlink could not be set */
309 +                       updated = 0;
310         }
311  
312         change_uid = am_root && preserve_uid && st->st_uid != file->uid;
313 --- orig/rsync.h        2005-09-24 17:40:31
314 +++ rsync.h     2005-07-28 00:04:51
315 @@ -54,6 +54,7 @@
316  #define XMIT_HAS_IDEV_DATA (1<<9)
317  #define XMIT_SAME_DEV (1<<10)
318  #define XMIT_RDEV_MINOR_IS_SMALL (1<<11)
319 +#define XMIT_SAME_ATIME (1<<12)
320  
321  /* These flags are used in the live flist data. */
322  
323 @@ -118,6 +119,7 @@
324  
325  #define PERMS_REPORT           (1<<0)
326  #define PERMS_SKIP_MTIME       (1<<1)
327 +#define PERMS_SKIP_ATIME       (1<<2)
328  
329  #define FULL_FLUSH     1
330  #define NORMAL_FLUSH   0
331 @@ -139,6 +141,7 @@
332  #define DEL_TERSE              (1<<3)
333  
334  /* For use by the itemize_changes code */
335 +#define ITEM_REPORT_ATIME (1<<0)
336  #define ITEM_REPORT_CHECKSUM (1<<1)
337  #define ITEM_REPORT_SIZE (1<<2)
338  #define ITEM_REPORT_TIME (1<<3)
339 @@ -521,6 +524,7 @@ struct file_struct {
340                 struct hlink *links;
341         } link_u;
342         time_t modtime;
343 +       time_t atime;
344         uid_t uid;
345         gid_t gid;
346         mode_t mode;
347 --- orig/rsync.yo       2005-09-24 17:40:31
348 +++ rsync.yo    2005-07-28 01:04:09
349 @@ -319,8 +319,9 @@ to the detailed description below for a 
350   -o, --owner                 preserve owner (root only)
351   -g, --group                 preserve group
352   -D, --devices               preserve devices (root only)
353 - -t, --times                 preserve times
354 + -t, --times                 preserve modify times
355   -O, --omit-dir-times        omit directories when preserving times
356 + -A, --atimes                preserve access times
357   -S, --sparse                handle sparse files efficiently
358   -n, --dry-run               show what would have been transferred
359   -W, --whole-file            copy files whole (without rsync algorithm)
360 @@ -695,6 +696,12 @@ it is preserving modification times (see
361  the directories on the receiving side, it is a good idea to use bf(-O).
362  This option is inferred if you use bf(--backup) without bf(--backup-dir).
363  
364 +dit(bf(-A, --atimes)) This tells rsync to set the access times of the
365 +destination files to the same value as the source files.  Note that the
366 +reading of the source file may update the atime of the source files, so
367 +repeated rsync runs with --atimes may be needed if you want to force the
368 +access-time values to be 100% identical on the two systems.
369 +
370  dit(bf(-n, --dry-run)) This tells rsync to not do any file transfers,
371  instead it will just report the actions it would have taken.
372  
373 @@ -1104,7 +1111,7 @@ changes that are being made to each file
374  This is exactly the same as specifying bf(--log-format='%i %n%L').
375  
376  The "%i" escape has a cryptic output that is 9 letters long.  The general
377 -format is like the string bf(UXcstpoga)), where bf(U) is replaced by the
378 +format is like the string bf(UXcstapogx)), where bf(U) is replaced by the
379  kind of update being done, bf(X) is replaced by the file-type, and the
380  other letters represent attributes that may be output if they are being
381  modified.
382 @@ -1143,17 +1150,22 @@ quote(itemize(
383    by the file transfer.
384    it() A bf(t) means the modification time is different and is being updated
385    to the sender's value (requires bf(--times)).  An alternate value of bf(T)
386 -  means that the time will be set to the transfer time, which happens
387 +  means that the modify time will be set to the transfer time, which happens
388    anytime a symlink is transferred, or when a file or device is transferred
389    without bf(--times).
390 +  it() A bf(a) means the access time is different and is being updated to
391 +  the sender's value (requires bf(--atimes)).  An alternate value of bf(A)
392 +  means that the access time  will be set to the transfer time, which happens
393 +  anytime a symlink is transferred, or when a file or device is transferred
394 +  without bf(--atimes).
395    it() A bf(p) means the permissions are different and are being updated to
396    the sender's value (requires bf(--perms)).
397    it() An bf(o) means the owner is different and is being updated to the
398    sender's value (requires bf(--owner) and root privileges).
399    it() A bf(g) means the group is different and is being updated to the
400    sender's value (requires bf(--group) and the authority to set the group).
401 -  it() The bf(a) is reserved for a future enhanced version that supports
402 -  extended file attributes, such as ACLs.
403 +  it() The bf(x) is reserved for a future enhanced version that supports
404 +  extended file attributes.
405  ))
406  
407  One other output is possible:  when deleting files, the "%i" will output
408 --- orig/testsuite/atimes.test  2004-06-30 00:06:23
409 +++ testsuite/atimes.test       2004-06-30 00:06:23
410 @@ -0,0 +1,19 @@
411 +#! /bin/sh
412 +
413 +# Test rsync copying atimes
414 +
415 +. "$suitedir/rsync.fns"
416 +
417 +set -x
418 +
419 +mkdir "$fromdir"
420 +
421 +touch "$fromdir/foo"
422 +touch -a -t 200102031717.42 "$fromdir/foo"
423 +
424 +TLS_ARGS=--atime
425 +
426 +checkit "$RSYNC -rtAgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
427 +
428 +# The script would have aborted on error, so getting here means we've won.
429 +exit 0
430 --- orig/testsuite/itemize.test 2005-07-07 20:35:48
431 +++ testsuite/itemize.test      2005-07-28 00:29:54
432 @@ -44,14 +44,14 @@ ln "$fromdir/foo/config1" "$fromdir/foo/
433  $RSYNC -iplr "$fromdir/" "$todir/" \
434      | tee "$outfile"
435  cat <<EOT >"$chkfile"
436 -cd+++++++ bar/
437 -cd+++++++ bar/baz/
438 ->f+++++++ bar/baz/rsync
439 -cd+++++++ foo/
440 ->f+++++++ foo/config1
441 ->f+++++++ foo/config2
442 ->f+++++++ foo/extra
443 -cL+++++++ foo/sym -> ../bar/baz/rsync
444 +cd++++++++ bar/
445 +cd++++++++ bar/baz/
446 +>f++++++++ bar/baz/rsync
447 +cd++++++++ foo/
448 +>f++++++++ foo/config1
449 +>f++++++++ foo/config2
450 +>f++++++++ foo/extra
451 +cL++++++++ foo/sym -> ../bar/baz/rsync
452  EOT
453  diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
454  
455 @@ -63,10 +63,10 @@ chmod 601 "$fromdir/foo/config2"
456  $RSYNC -iplrH "$fromdir/" "$todir/" \
457      | tee "$outfile"
458  cat <<EOT >"$chkfile"
459 ->f..T.... bar/baz/rsync
460 ->f..T.... foo/config1
461 ->f.sTp... foo/config2
462 -hf..T.... foo/extra => foo/config1
463 +>f..TA.... bar/baz/rsync
464 +>f..TA.... foo/config1
465 +>f.sTAp... foo/config2
466 +hf..TA.... foo/extra => foo/config1
467  EOT
468  diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
469  
470 @@ -83,11 +83,11 @@ chmod 777 "$todir/bar/baz/rsync"
471  $RSYNC -iplrtc "$fromdir/" "$todir/" \
472      | tee "$outfile"
473  cat <<EOT >"$chkfile"
474 -.f..tp... bar/baz/rsync
475 -.d..t.... foo/
476 -.f..t.... foo/config1
477 ->fcstp... foo/config2
478 -cL..T.... foo/sym -> ../bar/baz/rsync
479 +.f..t.p... bar/baz/rsync
480 +.d..t..... foo/
481 +.f..t..... foo/config1
482 +>fcst.p... foo/config2
483 +cL..TA.... foo/sym -> ../bar/baz/rsync
484  EOT
485  diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
486  
487 @@ -112,15 +112,15 @@ $RSYNC -ivvplrtH "$fromdir/" "$todir/" \
488      | tee "$outfile"
489  filter_outfile
490  cat <<EOT >"$chkfile"
491 -.d        ./
492 -.d        bar/
493 -.d        bar/baz/
494 -.f...p... bar/baz/rsync
495 -.d        foo/
496 -.f        foo/config1
497 ->f..t.... foo/config2
498 -hf        foo/extra
499 -.L        foo/sym -> ../bar/baz/rsync
500 +.d         ./
501 +.d         bar/
502 +.d         bar/baz/
503 +.f....p... bar/baz/rsync
504 +.d         foo/
505 +.f         foo/config1
506 +>f..t..... foo/config2
507 +hf         foo/extra
508 +.L         foo/sym -> ../bar/baz/rsync
509  EOT
510  diff $diffopt "$chkfile" "$outfile" || test_fail "test 5 failed"
511  
512 @@ -139,8 +139,8 @@ touch "$todir/foo/config2"
513  $RSYNC -iplrtH "$fromdir/" "$todir/" \
514      | tee "$outfile"
515  cat <<EOT >"$chkfile"
516 -.f...p... foo/config1
517 ->f..t.... foo/config2
518 +.f....p... foo/config1
519 +>f..t..... foo/config2
520  EOT
521  diff $diffopt "$chkfile" "$outfile" || test_fail "test 7 failed"
522  
523 @@ -149,15 +149,15 @@ $RSYNC -ivvplrtH --copy-dest="$lddir" "$
524      | tee "$outfile"
525  filter_outfile
526  cat <<EOT >"$chkfile"
527 -.d..t.... ./
528 -cd+++++++ bar/
529 -cd+++++++ bar/baz/
530 -cf....... bar/baz/rsync
531 -cd+++++++ foo/
532 -cf....... foo/config1
533 -cf....... foo/config2
534 -hf+++++++ foo/extra => foo/config1
535 -cL+++++++ foo/sym -> ../bar/baz/rsync
536 +.d..t..... ./
537 +cd++++++++ bar/
538 +cd++++++++ bar/baz/
539 +cf........ bar/baz/rsync
540 +cd++++++++ foo/
541 +cf........ foo/config1
542 +cf........ foo/config2
543 +hf++++++++ foo/extra => foo/config1
544 +cL++++++++ foo/sym -> ../bar/baz/rsync
545  EOT
546  diff $diffopt "$chkfile" "$outfile" || test_fail "test 8 failed"
547  
548 @@ -165,12 +165,12 @@ rm -rf "$todir"
549  $RSYNC -iplrtH --link-dest="$lddir" "$fromdir/" "$todir/" \
550      | tee "$outfile"
551  cat <<EOT >"$chkfile"
552 -.d..t.... ./
553 -cd+++++++ bar/
554 -cd+++++++ bar/baz/
555 -cd+++++++ foo/
556 -hf+++++++ foo/extra => foo/config1
557 -cL+++++++ foo/sym -> ../bar/baz/rsync
558 +.d..t..... ./
559 +cd++++++++ bar/
560 +cd++++++++ bar/baz/
561 +cd++++++++ foo/
562 +hf++++++++ foo/extra => foo/config1
563 +cL++++++++ foo/sym -> ../bar/baz/rsync
564  EOT
565  diff $diffopt "$chkfile" "$outfile" || test_fail "test 9 failed"
566  
567 --- orig/testsuite/rsync.fns    2005-06-10 21:33:28
568 +++ testsuite/rsync.fns 2005-07-28 00:41:20
569 @@ -50,7 +50,7 @@ printmsg() {
570  
571  
572  rsync_ls_lR() {
573 -    find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls"
574 +    find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls" $TLS_ARGS
575  }
576  
577  rsync_getgroups() { 
578 @@ -158,6 +158,10 @@ checkit() {
579      # We can just write everything to stdout/stderr, because the
580      # wrapper hides it unless there is a problem.
581  
582 +    if test x$TLS_ARGS = x--atime; then
583 +       ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
584 +    fi
585 +
586      echo "Running: \"$1\""  
587      eval "$1" 
588      status=$?
589 @@ -165,10 +169,13 @@ checkit() {
590         failed="YES";
591      fi
592  
593 +    if test x$TLS_ARGS != x--atime; then
594 +       ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
595 +    fi
596 +
597      echo "-------------"
598      echo "check how the directory listings compare with diff:"
599      echo ""
600 -    ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
601      ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
602      diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
603  
604 --- orig/tls.c  2005-09-24 17:40:31
605 +++ tls.c       2005-03-23 17:49:48
606 @@ -39,6 +39,7 @@
607  
608  
609  #include "rsync.h"
610 +#include "popt.h"
611  
612  #define PROGRAM "tls"
613  
614 @@ -48,6 +49,7 @@ int read_only = 1;
615  int list_only = 0;
616  int preserve_perms = 0;
617  
618 +static int display_atime = 0;
619  
620  static void failed(char const *what, char const *where)
621  {
622 @@ -56,14 +58,29 @@ static void failed(char const *what, cha
623         exit(1);
624  }
625  
626 +static void storetime(char *dest, time_t t)
627 +{
628 +       if (t) {
629 +               struct tm *mt = gmtime(&t);
630  
631 +               sprintf(dest, "%04d-%02d-%02d %02d:%02d:%02d ",
632 +                       (int)mt->tm_year + 1900,
633 +                       (int)mt->tm_mon + 1,
634 +                       (int)mt->tm_mday,
635 +                       (int)mt->tm_hour,
636 +                       (int)mt->tm_min,
637 +                       (int)mt->tm_sec);
638 +       } else {
639 +               strcpy(dest, "                    ");
640 +       }
641 +}      
642  
643  static void list_file(const char *fname)
644  {
645         STRUCT_STAT buf;
646         char permbuf[PERMSTRING_SIZE];
647 -       struct tm *mt;
648 -       char datebuf[50];
649 +       char mtimebuf[50];
650 +       char atimebuf[50];
651         char linkbuf[4096];
652  
653         if (do_lstat(fname, &buf) < 0)
654 @@ -96,19 +113,8 @@ static void list_file(const char *fname)
655  
656         permstring(permbuf, buf.st_mode);
657  
658 -       if (buf.st_mtime) {
659 -               mt = gmtime(&buf.st_mtime);
660 -
661 -               sprintf(datebuf, "%04d-%02d-%02d %02d:%02d:%02d",
662 -                       (int)mt->tm_year + 1900,
663 -                       (int)mt->tm_mon + 1,
664 -                       (int)mt->tm_mday,
665 -                       (int)mt->tm_hour,
666 -                       (int)mt->tm_min,
667 -                       (int)mt->tm_sec);
668 -       } else {
669 -               strcpy(datebuf, "                   ");
670 -       }
671 +       storetime(mtimebuf, buf.st_mtime);
672 +       storetime(atimebuf, buf.st_atime);
673  
674         /* TODO: Perhaps escape special characters in fname? */
675  
676 @@ -119,24 +125,55 @@ static void list_file(const char *fname)
677                     (long)minor(buf.st_rdev));
678         } else /* NB: use double for size since it might not fit in a long. */
679                 printf("%12.0f", (double)buf.st_size);
680 -       printf(" %6ld.%-6ld %6ld %s %s%s\n",
681 +       printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
682                (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
683 -              datebuf, fname, linkbuf);
684 +              mtimebuf, display_atime && !S_ISDIR(buf.st_mode) ? atimebuf : "",
685 +              fname, linkbuf);
686  }
687  
688 +static struct poptOption long_options[] = {
689 +  /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
690 +  {"atime",           'u', POPT_ARG_NONE,   &display_atime, 0,   0, 0},
691 +  {"help",            'h', POPT_ARG_NONE,   0,              'h', 0, 0},
692 +  {0,0,0,0,0,0,0}
693 +};
694 +
695 +static void tls_usage(int ret)
696 +{
697 +       fprintf(stderr, "usage: " PROGRAM " [--atime | -u] DIR ...\n"
698 +           "Trivial file listing program for portably checking rsync\n");
699 +       exit(ret);
700 +}
701  
702  int
703  main(int argc, char *argv[])
704  {
705 -       if (argc < 2) {
706 -               fprintf(stderr, "usage: " PROGRAM " DIR ...\n"
707 -                       "Trivial file listing program for portably checking rsync\n");
708 -               return 1;
709 +       poptContext pc;
710 +       const char **extra_args;
711 +       int opt;
712 +
713 +       pc = poptGetContext(PROGRAM, argc, (const char **)argv,
714 +                           long_options, 0);
715 +       while ((opt = poptGetNextOpt(pc)) != -1) {
716 +               switch (opt) {
717 +               case 'h':
718 +                       tls_usage(0);
719 +               default:
720 +                       fprintf(stderr,
721 +                               "%s: %s\n",
722 +                               poptBadOption(pc, POPT_BADOPTION_NOALIAS),
723 +                               poptStrerror(opt));
724 +                       tls_usage(1);
725 +               }
726         }
727  
728 -       for (argv++; *argv; argv++) {
729 -               list_file(*argv);
730 -       }
731 +       extra_args = poptGetArgs(pc);
732 +       if (*extra_args == NULL)
733 +               tls_usage(1);
734 +
735 +       for (; *extra_args; extra_args++)
736 +               list_file(*extra_args);
737 +       poptFreeContext(pc);
738  
739         return 0;
740  }
741 --- orig/util.c 2005-08-17 06:45:08
742 +++ util.c      2005-07-27 23:37:27
743 @@ -128,7 +128,7 @@ void overflow_exit(char *str)
744  
745  
746  
747 -int set_modtime(char *fname, time_t modtime, mode_t mode)
748 +int set_times(char *fname, time_t modtime, time_t atime, mode_t mode)
749  {
750  #if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
751         if (S_ISLNK(mode))
752 @@ -136,9 +136,13 @@ int set_modtime(char *fname, time_t modt
753  #endif
754  
755         if (verbose > 2) {
756 -               rprintf(FINFO, "set modtime of %s to (%ld) %s",
757 +               char mtimebuf[200];
758 +
759 +               strlcpy(mtimebuf, timestring(modtime), sizeof mtimebuf);
760 +               rprintf(FINFO,
761 +                       "set modtime, atime of %s to (%ld) %s, (%ld) %s\n",
762                         safe_fname(fname), (long)modtime,
763 -                       asctime(localtime(&modtime)));
764 +                       mtimebuf, (long)atime, timestring(atime));
765         }
766  
767         if (dry_run)
768 @@ -147,7 +151,7 @@ int set_modtime(char *fname, time_t modt
769         {
770  #ifdef HAVE_UTIMES
771                 struct timeval t[2];
772 -               t[0].tv_sec = time(NULL);
773 +               t[0].tv_sec = atime;
774                 t[0].tv_usec = 0;
775                 t[1].tv_sec = modtime;
776                 t[1].tv_usec = 0;
777 @@ -158,12 +162,12 @@ int set_modtime(char *fname, time_t modt
778                 return utimes(fname, t);
779  #elif defined HAVE_UTIMBUF
780                 struct utimbuf tbuf;
781 -               tbuf.actime = time(NULL);
782 +               tbuf.actime = atime;
783                 tbuf.modtime = modtime;
784                 return utime(fname,&tbuf);
785  #elif defined HAVE_UTIME
786                 time_t t[2];
787 -               t[0] = time(NULL);
788 +               t[0] = atime;
789                 t[1] = modtime;
790                 return utime(fname,t);
791  #else
792 @@ -1166,8 +1170,8 @@ int msleep(int t)
793  
794  
795  /**
796 - * Determine if two file modification times are equivalent (either
797 - * exact or in the modification timestamp window established by
798 + * Determine if two file  times are equivalent (either
799 + * exact or in the timestamp window established by
800   * --modify-window).
801   *
802   * @retval 0 if the times should be treated as the same
803 @@ -1176,7 +1180,7 @@ int msleep(int t)
804   *
805   * @retval -1 if the 2nd is later
806   **/
807 -int cmp_modtime(time_t file1, time_t file2)
808 +int cmp_time(time_t file1, time_t file2)
809  {
810         if (file2 > file1) {
811                 if (file2 - file1 <= modify_window)