Fixed failing hunks.
[rsync/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-10-26 16:49:08
8 +++ batch.c     2004-07-03 20:15:41
9 @@ -225,6 +225,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-11-07 04:29:01
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 @@ -138,16 +139,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 @@ -309,6 +312,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 @@ -324,7 +328,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 @@ -373,6 +377,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 @@ -426,6 +436,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 @@ -494,6 +506,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 @@ -512,7 +525,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 @@ -568,6 +581,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 @@ -618,6 +633,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 @@ -866,6 +882,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         if (chmod_modes && am_sender && (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)))
129                 file->mode = tweak_mode(st.st_mode, chmod_modes);
130 --- orig/generator.c    2005-10-30 22:30:28
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 @@ -325,9 +326,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 @@ -379,7 +392,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 @@ -539,7 +552,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 @@ -891,7 +904,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-10-26 16:49:08
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 @@ -503,11 +504,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-11-07 04:29:01
221 +++ options.c   2005-11-07 04:32:19
222 @@ -50,6 +50,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 @@ -292,8 +293,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,"     --chmod=CHMOD           change destination permissions\n");
240    rprintf(F," -S, --sparse                handle sparse files efficiently\n");
241    rprintf(F," -n, --dry-run               show what would have been transferred\n");
242 @@ -397,6 +399,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 @@ -1429,6 +1434,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-10-14 18:45:50
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 @@ -119,6 +120,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 @@ -140,6 +142,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 @@ -522,6 +525,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-11-07 04:29:02
348 +++ rsync.yo    2005-11-07 04:34:55
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 - -O, --omit-dir-times        omit directories when preserving times
355 + -t, --times                 preserve modify times
356 + -O, --omit-dir-times        omit directories when preserving mod-times
357 + -A, --atimes                preserve access times
358       --chmod=CHMOD           change destination permissions
359   -S, --sparse                handle sparse files efficiently
360   -n, --dry-run               show what would have been transferred
361 @@ -698,6 +699,12 @@ it is preserving modification times (see
362  the directories on the receiving side, it is a good idea to use bf(-O).
363  This option is inferred if you use bf(--backup) without bf(--backup-dir).
364  
365 +dit(bf(-A, --atimes)) This tells rsync to set the access times of the
366 +destination files to the same value as the source files.  Note that the
367 +reading of the source file may update the atime of the source files, so
368 +repeated rsync runs with --atimes may be needed if you want to force the
369 +access-time values to be 100% identical on the two systems.
370 +
371  dit(bf(--chmod)) This options tells rsync to apply the listed "chmod" pattern
372  to the permission of the files on the destination.  In addition to the normal
373  parsing rules specified in the chmod manpage, you can specify an item that
374 @@ -1139,7 +1146,7 @@ changes that are being made to each file
375  This is exactly the same as specifying bf(--log-format='%i %n%L').
376  
377  The "%i" escape has a cryptic output that is 9 letters long.  The general
378 -format is like the string bf(UXcstpoga)), where bf(U) is replaced by the
379 +format is like the string bf(UXcstapogx)), where bf(U) is replaced by the
380  kind of update being done, bf(X) is replaced by the file-type, and the
381  other letters represent attributes that may be output if they are being
382  modified.
383 @@ -1178,17 +1185,22 @@ quote(itemize(
384    by the file transfer.
385    it() A bf(t) means the modification time is different and is being updated
386    to the sender's value (requires bf(--times)).  An alternate value of bf(T)
387 -  means that the time will be set to the transfer time, which happens
388 +  means that the modify time will be set to the transfer time, which happens
389    anytime a symlink is transferred, or when a file or device is transferred
390    without bf(--times).
391 +  it() A bf(a) means the access time is different and is being updated to
392 +  the sender's value (requires bf(--atimes)).  An alternate value of bf(A)
393 +  means that the access time  will be set to the transfer time, which happens
394 +  anytime a symlink is transferred, or when a file or device is transferred
395 +  without bf(--atimes).
396    it() A bf(p) means the permissions are different and are being updated to
397    the sender's value (requires bf(--perms)).
398    it() An bf(o) means the owner is different and is being updated to the
399    sender's value (requires bf(--owner) and root privileges).
400    it() A bf(g) means the group is different and is being updated to the
401    sender's value (requires bf(--group) and the authority to set the group).
402 -  it() The bf(a) is reserved for a future enhanced version that supports
403 -  extended file attributes, such as ACLs.
404 +  it() The bf(x) is reserved for a future enhanced version that supports
405 +  extended file attributes.
406  ))
407  
408  One other output is possible:  when deleting files, the "%i" will output
409 --- orig/testsuite/atimes.test  2004-06-30 00:06:23
410 +++ testsuite/atimes.test       2004-06-30 00:06:23
411 @@ -0,0 +1,19 @@
412 +#! /bin/sh
413 +
414 +# Test rsync copying atimes
415 +
416 +. "$suitedir/rsync.fns"
417 +
418 +set -x
419 +
420 +mkdir "$fromdir"
421 +
422 +touch "$fromdir/foo"
423 +touch -a -t 200102031717.42 "$fromdir/foo"
424 +
425 +TLS_ARGS=--atime
426 +
427 +checkit "$RSYNC -rtAgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
428 +
429 +# The script would have aborted on error, so getting here means we've won.
430 +exit 0
431 --- orig/testsuite/itemize.test 2005-07-07 20:35:48
432 +++ testsuite/itemize.test      2005-07-28 00:29:54
433 @@ -44,14 +44,14 @@ ln "$fromdir/foo/config1" "$fromdir/foo/
434  $RSYNC -iplr "$fromdir/" "$todir/" \
435      | tee "$outfile"
436  cat <<EOT >"$chkfile"
437 -cd+++++++ bar/
438 -cd+++++++ bar/baz/
439 ->f+++++++ bar/baz/rsync
440 -cd+++++++ foo/
441 ->f+++++++ foo/config1
442 ->f+++++++ foo/config2
443 ->f+++++++ foo/extra
444 -cL+++++++ foo/sym -> ../bar/baz/rsync
445 +cd++++++++ bar/
446 +cd++++++++ bar/baz/
447 +>f++++++++ bar/baz/rsync
448 +cd++++++++ foo/
449 +>f++++++++ foo/config1
450 +>f++++++++ foo/config2
451 +>f++++++++ foo/extra
452 +cL++++++++ foo/sym -> ../bar/baz/rsync
453  EOT
454  diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
455  
456 @@ -63,10 +63,10 @@ chmod 601 "$fromdir/foo/config2"
457  $RSYNC -iplrH "$fromdir/" "$todir/" \
458      | tee "$outfile"
459  cat <<EOT >"$chkfile"
460 ->f..T.... bar/baz/rsync
461 ->f..T.... foo/config1
462 ->f.sTp... foo/config2
463 -hf..T.... foo/extra => foo/config1
464 +>f..TA.... bar/baz/rsync
465 +>f..TA.... foo/config1
466 +>f.sTAp... foo/config2
467 +hf..TA.... foo/extra => foo/config1
468  EOT
469  diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
470  
471 @@ -83,11 +83,11 @@ chmod 777 "$todir/bar/baz/rsync"
472  $RSYNC -iplrtc "$fromdir/" "$todir/" \
473      | tee "$outfile"
474  cat <<EOT >"$chkfile"
475 -.f..tp... bar/baz/rsync
476 -.d..t.... foo/
477 -.f..t.... foo/config1
478 ->fcstp... foo/config2
479 -cL..T.... foo/sym -> ../bar/baz/rsync
480 +.f..t.p... bar/baz/rsync
481 +.d..t..... foo/
482 +.f..t..... foo/config1
483 +>fcst.p... foo/config2
484 +cL..TA.... foo/sym -> ../bar/baz/rsync
485  EOT
486  diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
487  
488 @@ -112,15 +112,15 @@ $RSYNC -ivvplrtH "$fromdir/" "$todir/" \
489      | tee "$outfile"
490  filter_outfile
491  cat <<EOT >"$chkfile"
492 -.d        ./
493 -.d        bar/
494 -.d        bar/baz/
495 -.f...p... bar/baz/rsync
496 -.d        foo/
497 -.f        foo/config1
498 ->f..t.... foo/config2
499 -hf        foo/extra
500 -.L        foo/sym -> ../bar/baz/rsync
501 +.d         ./
502 +.d         bar/
503 +.d         bar/baz/
504 +.f....p... bar/baz/rsync
505 +.d         foo/
506 +.f         foo/config1
507 +>f..t..... foo/config2
508 +hf         foo/extra
509 +.L         foo/sym -> ../bar/baz/rsync
510  EOT
511  diff $diffopt "$chkfile" "$outfile" || test_fail "test 5 failed"
512  
513 @@ -139,8 +139,8 @@ touch "$todir/foo/config2"
514  $RSYNC -iplrtH "$fromdir/" "$todir/" \
515      | tee "$outfile"
516  cat <<EOT >"$chkfile"
517 -.f...p... foo/config1
518 ->f..t.... foo/config2
519 +.f....p... foo/config1
520 +>f..t..... foo/config2
521  EOT
522  diff $diffopt "$chkfile" "$outfile" || test_fail "test 7 failed"
523  
524 @@ -149,15 +149,15 @@ $RSYNC -ivvplrtH --copy-dest="$lddir" "$
525      | tee "$outfile"
526  filter_outfile
527  cat <<EOT >"$chkfile"
528 -.d..t.... ./
529 -cd+++++++ bar/
530 -cd+++++++ bar/baz/
531 -cf....... bar/baz/rsync
532 -cd+++++++ foo/
533 -cf....... foo/config1
534 -cf....... foo/config2
535 -hf+++++++ foo/extra => foo/config1
536 -cL+++++++ foo/sym -> ../bar/baz/rsync
537 +.d..t..... ./
538 +cd++++++++ bar/
539 +cd++++++++ bar/baz/
540 +cf........ bar/baz/rsync
541 +cd++++++++ foo/
542 +cf........ foo/config1
543 +cf........ foo/config2
544 +hf++++++++ foo/extra => foo/config1
545 +cL++++++++ foo/sym -> ../bar/baz/rsync
546  EOT
547  diff $diffopt "$chkfile" "$outfile" || test_fail "test 8 failed"
548  
549 @@ -165,12 +165,12 @@ rm -rf "$todir"
550  $RSYNC -iplrtH --link-dest="$lddir" "$fromdir/" "$todir/" \
551      | tee "$outfile"
552  cat <<EOT >"$chkfile"
553 -.d..t.... ./
554 -cd+++++++ bar/
555 -cd+++++++ bar/baz/
556 -cd+++++++ foo/
557 -hf+++++++ foo/extra => foo/config1
558 -cL+++++++ foo/sym -> ../bar/baz/rsync
559 +.d..t..... ./
560 +cd++++++++ bar/
561 +cd++++++++ bar/baz/
562 +cd++++++++ foo/
563 +hf++++++++ foo/extra => foo/config1
564 +cL++++++++ foo/sym -> ../bar/baz/rsync
565  EOT
566  diff $diffopt "$chkfile" "$outfile" || test_fail "test 9 failed"
567  
568 --- orig/testsuite/rsync.fns    2005-06-10 21:33:28
569 +++ testsuite/rsync.fns 2005-07-28 00:41:20
570 @@ -50,7 +50,7 @@ printmsg() {
571  
572  
573  rsync_ls_lR() {
574 -    find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls"
575 +    find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls" $TLS_ARGS
576  }
577  
578  rsync_getgroups() { 
579 @@ -158,6 +158,10 @@ checkit() {
580      # We can just write everything to stdout/stderr, because the
581      # wrapper hides it unless there is a problem.
582  
583 +    if test x$TLS_ARGS = x--atime; then
584 +       ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
585 +    fi
586 +
587      echo "Running: \"$1\""  
588      eval "$1" 
589      status=$?
590 @@ -165,10 +169,13 @@ checkit() {
591         failed="YES";
592      fi
593  
594 +    if test x$TLS_ARGS != x--atime; then
595 +       ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
596 +    fi
597 +
598      echo "-------------"
599      echo "check how the directory listings compare with diff:"
600      echo ""
601 -    ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
602      ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
603      diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
604  
605 --- orig/tls.c  2005-09-24 17:40:31
606 +++ tls.c       2005-03-23 17:49:48
607 @@ -39,6 +39,7 @@
608  
609  
610  #include "rsync.h"
611 +#include "popt.h"
612  
613  #define PROGRAM "tls"
614  
615 @@ -48,6 +49,7 @@ int read_only = 1;
616  int list_only = 0;
617  int preserve_perms = 0;
618  
619 +static int display_atime = 0;
620  
621  static void failed(char const *what, char const *where)
622  {
623 @@ -56,14 +58,29 @@ static void failed(char const *what, cha
624         exit(1);
625  }
626  
627 +static void storetime(char *dest, time_t t)
628 +{
629 +       if (t) {
630 +               struct tm *mt = gmtime(&t);
631  
632 +               sprintf(dest, "%04d-%02d-%02d %02d:%02d:%02d ",
633 +                       (int)mt->tm_year + 1900,
634 +                       (int)mt->tm_mon + 1,
635 +                       (int)mt->tm_mday,
636 +                       (int)mt->tm_hour,
637 +                       (int)mt->tm_min,
638 +                       (int)mt->tm_sec);
639 +       } else {
640 +               strcpy(dest, "                    ");
641 +       }
642 +}      
643  
644  static void list_file(const char *fname)
645  {
646         STRUCT_STAT buf;
647         char permbuf[PERMSTRING_SIZE];
648 -       struct tm *mt;
649 -       char datebuf[50];
650 +       char mtimebuf[50];
651 +       char atimebuf[50];
652         char linkbuf[4096];
653  
654         if (do_lstat(fname, &buf) < 0)
655 @@ -96,19 +113,8 @@ static void list_file(const char *fname)
656  
657         permstring(permbuf, buf.st_mode);
658  
659 -       if (buf.st_mtime) {
660 -               mt = gmtime(&buf.st_mtime);
661 -
662 -               sprintf(datebuf, "%04d-%02d-%02d %02d:%02d:%02d",
663 -                       (int)mt->tm_year + 1900,
664 -                       (int)mt->tm_mon + 1,
665 -                       (int)mt->tm_mday,
666 -                       (int)mt->tm_hour,
667 -                       (int)mt->tm_min,
668 -                       (int)mt->tm_sec);
669 -       } else {
670 -               strcpy(datebuf, "                   ");
671 -       }
672 +       storetime(mtimebuf, buf.st_mtime);
673 +       storetime(atimebuf, buf.st_atime);
674  
675         /* TODO: Perhaps escape special characters in fname? */
676  
677 @@ -119,24 +125,55 @@ static void list_file(const char *fname)
678                     (long)minor(buf.st_rdev));
679         } else /* NB: use double for size since it might not fit in a long. */
680                 printf("%12.0f", (double)buf.st_size);
681 -       printf(" %6ld.%-6ld %6ld %s %s%s\n",
682 +       printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
683                (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
684 -              datebuf, fname, linkbuf);
685 +              mtimebuf, display_atime && !S_ISDIR(buf.st_mode) ? atimebuf : "",
686 +              fname, linkbuf);
687  }
688  
689 +static struct poptOption long_options[] = {
690 +  /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
691 +  {"atime",           'u', POPT_ARG_NONE,   &display_atime, 0,   0, 0},
692 +  {"help",            'h', POPT_ARG_NONE,   0,              'h', 0, 0},
693 +  {0,0,0,0,0,0,0}
694 +};
695 +
696 +static void tls_usage(int ret)
697 +{
698 +       fprintf(stderr, "usage: " PROGRAM " [--atime | -u] DIR ...\n"
699 +           "Trivial file listing program for portably checking rsync\n");
700 +       exit(ret);
701 +}
702  
703  int
704  main(int argc, char *argv[])
705  {
706 -       if (argc < 2) {
707 -               fprintf(stderr, "usage: " PROGRAM " DIR ...\n"
708 -                       "Trivial file listing program for portably checking rsync\n");
709 -               return 1;
710 +       poptContext pc;
711 +       const char **extra_args;
712 +       int opt;
713 +
714 +       pc = poptGetContext(PROGRAM, argc, (const char **)argv,
715 +                           long_options, 0);
716 +       while ((opt = poptGetNextOpt(pc)) != -1) {
717 +               switch (opt) {
718 +               case 'h':
719 +                       tls_usage(0);
720 +               default:
721 +                       fprintf(stderr,
722 +                               "%s: %s\n",
723 +                               poptBadOption(pc, POPT_BADOPTION_NOALIAS),
724 +                               poptStrerror(opt));
725 +                       tls_usage(1);
726 +               }
727         }
728  
729 -       for (argv++; *argv; argv++) {
730 -               list_file(*argv);
731 -       }
732 +       extra_args = poptGetArgs(pc);
733 +       if (*extra_args == NULL)
734 +               tls_usage(1);
735 +
736 +       for (; *extra_args; extra_args++)
737 +               list_file(*extra_args);
738 +       poptFreeContext(pc);
739  
740         return 0;
741  }
742 --- orig/util.c 2005-10-16 22:38:40
743 +++ util.c      2005-07-27 23:37:27
744 @@ -129,7 +129,7 @@ void overflow_exit(char *str)
745  
746  
747  
748 -int set_modtime(char *fname, time_t modtime, mode_t mode)
749 +int set_times(char *fname, time_t modtime, time_t atime, mode_t mode)
750  {
751  #if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
752         if (S_ISLNK(mode))
753 @@ -137,9 +137,13 @@ int set_modtime(char *fname, time_t modt
754  #endif
755  
756         if (verbose > 2) {
757 -               rprintf(FINFO, "set modtime of %s to (%ld) %s",
758 +               char mtimebuf[200];
759 +
760 +               strlcpy(mtimebuf, timestring(modtime), sizeof mtimebuf);
761 +               rprintf(FINFO,
762 +                       "set modtime, atime of %s to (%ld) %s, (%ld) %s\n",
763                         safe_fname(fname), (long)modtime,
764 -                       asctime(localtime(&modtime)));
765 +                       mtimebuf, (long)atime, timestring(atime));
766         }
767  
768         if (dry_run)
769 @@ -148,7 +152,7 @@ int set_modtime(char *fname, time_t modt
770         {
771  #ifdef HAVE_UTIMES
772                 struct timeval t[2];
773 -               t[0].tv_sec = time(NULL);
774 +               t[0].tv_sec = atime;
775                 t[0].tv_usec = 0;
776                 t[1].tv_sec = modtime;
777                 t[1].tv_usec = 0;
778 @@ -159,12 +163,12 @@ int set_modtime(char *fname, time_t modt
779                 return utimes(fname, t);
780  #elif defined HAVE_UTIMBUF
781                 struct utimbuf tbuf;
782 -               tbuf.actime = time(NULL);
783 +               tbuf.actime = atime;
784                 tbuf.modtime = modtime;
785                 return utime(fname,&tbuf);
786  #elif defined HAVE_UTIME
787                 time_t t[2];
788 -               t[0] = time(NULL);
789 +               t[0] = atime;
790                 t[1] = modtime;
791                 return utime(fname,t);
792  #else
793 @@ -1171,8 +1175,8 @@ int msleep(int t)
794  
795  
796  /**
797 - * Determine if two file modification times are equivalent (either
798 - * exact or in the modification timestamp window established by
799 + * Determine if two file  times are equivalent (either
800 + * exact or in the timestamp window established by
801   * --modify-window).
802   *
803   * @retval 0 if the times should be treated as the same
804 @@ -1181,7 +1185,7 @@ int msleep(int t)
805   *
806   * @retval -1 if the 2nd is later
807   **/
808 -int cmp_modtime(time_t file1, time_t file2)
809 +int cmp_time(time_t file1, time_t file2)
810  {
811         if (file2 > file1) {
812                 if (file2 - file1 <= modify_window)