Fixed failing hunks.
[rsync/rsync-patches.git] / atimes.diff
CommitLineData
03019e41 1To use this patch, run these commands for a successful build:
8a529471 2
03019e41 3 patch -p1 <patches/atimes.diff
27e96866
WD
4 ./prepare-source
5 ./configure (optional if already run)
6 make
8a529471 7
a2dabe5e 8TODO: need to fix this to handle 64-bit time_t values!
8a529471 9
fdf967c7
WD
10--- old/compat.c
11+++ new/compat.c
898a2112
WD
12@@ -43,6 +43,7 @@ extern int prune_empty_dirs;
13 extern int protocol_version;
14 extern int preserve_uid;
15 extern int preserve_gid;
16+extern int preserve_atimes;
17 extern int preserve_acls;
18 extern int preserve_xattrs;
19 extern int preserve_hard_links;
20@@ -57,7 +58,7 @@ extern char *dest_option;
21 extern struct filter_list_struct filter_list;
22
23 /* These index values are for the file-list's extra-attribute array. */
24-int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx;
25+int uid_ndx, gid_ndx, atimes_ndx, acls_ndx, xattrs_ndx;
26
27 /* The server makes sure that if either side only supports a pre-release
28 * version of a protocol, that both sides must speak a compatible version
29@@ -98,6 +99,8 @@ void setup_protocol(int f_out,int f_in)
30 uid_ndx = ++file_extra_cnt;
fdf967c7 31 if (preserve_gid)
898a2112 32 gid_ndx = ++file_extra_cnt;
fdf967c7 33+ if (preserve_atimes)
898a2112 34+ atimes_ndx = ++file_extra_cnt;
4306c620 35 if (preserve_acls && !am_sender)
898a2112 36 acls_ndx = ++file_extra_cnt;
5795bf59 37 if (preserve_xattrs)
9a7eef96
WD
38--- old/flist.c
39+++ new/flist.c
6cbbe66d 40@@ -52,6 +52,7 @@ extern int preserve_devices;
4a65fe72 41 extern int preserve_specials;
898a2112
WD
42 extern int uid_ndx;
43 extern int gid_ndx;
44+extern int atimes_ndx;
81c32ffd 45 extern int relative_paths;
a5e0f697 46 extern int implied_dirs;
7e27b6c0 47 extern int file_extra_cnt;
6cbbe66d 48@@ -158,6 +159,7 @@ void show_flist_stats(void)
672ad041
WD
49 static void list_file_entry(struct file_struct *f)
50 {
51 char permbuf[PERMSTRING_SIZE];
898a2112 52+ time_t atime = atimes_ndx ? F_ATIME(f) : 0;
1aa236e1 53 double len;
1cb60481 54
1aa236e1 55 if (!F_IS_ACTIVE(f)) {
6cbbe66d 56@@ -172,14 +174,16 @@ static void list_file_entry(struct file_
43581f16 57
09fb8f03 58 #ifdef SUPPORT_LINKS
43581f16
WD
59 if (preserve_links && S_ISLNK(f->mode)) {
60- rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
61+ rprintf(FINFO, "%s %11.0f %s %s %s -> %s\n",
1aa236e1 62 permbuf, len, timestring(f->modtime),
898a2112 63+ atimes_ndx ? timestring(atime) : "",
70891d26 64 f_name(f, NULL), F_SYMLINK(f));
43581f16
WD
65 } else
66 #endif
896c61d0 67 {
43581f16
WD
68- rprintf(FINFO, "%s %11.0f %s %s\n",
69+ rprintf(FINFO, "%s %11.0f %s %s %s\n",
1aa236e1 70 permbuf, len, timestring(f->modtime),
898a2112 71+ atimes_ndx ? timestring(atime) : "",
bd68c3c2 72 f_name(f, NULL));
896c61d0 73 }
43581f16 74 }
898a2112 75@@ -347,6 +351,7 @@ int push_pathname(const char *dir, int l
fc068916 76 static void send_file_entry(int f, struct file_struct *file, int ndx)
43581f16 77 {
43581f16
WD
78 static time_t modtime;
79+ static time_t atime;
80 static mode_t mode;
ba50e96c 81 static int64 dev;
43581f16 82 static dev_t rdev;
898a2112 83@@ -442,6 +447,13 @@ static void send_file_entry(int f, struc
43581f16
WD
84 flags |= XMIT_SAME_TIME;
85 else
86 modtime = file->modtime;
898a2112 87+ if (atimes_ndx && !S_ISDIR(mode)) {
70891d26 88+ time_t file_atime = F_ATIME(file);
672ad041 89+ if (file_atime == atime)
43581f16
WD
90+ flags |= XMIT_SAME_ATIME;
91+ else
672ad041 92+ atime = file_atime;
43581f16
WD
93+ }
94
09fb8f03 95 #ifdef SUPPORT_HARD_LINKS
fdf967c7 96 if (tmp_dev != 0) {
898a2112 97@@ -513,6 +525,8 @@ static void send_file_entry(int f, struc
a2dabe5e 98 }
43581f16
WD
99 if (!(flags & XMIT_SAME_MODE))
100 write_int(f, to_wire_mode(mode));
898a2112 101+ if (atimes_ndx && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
a2dabe5e 102+ write_varlong(f, atime, 4);
898a2112 103 if (uid_ndx && !(flags & XMIT_SAME_UID)) {
caf38d8d
WD
104 if (protocol_version < 30)
105 write_int(f, uid);
898a2112 106@@ -599,7 +613,7 @@ static void send_file_entry(int f, struc
70891d26 107 static struct file_struct *recv_file_entry(struct file_list *flist,
761f1b71 108 int xflags, int f)
43581f16 109 {
a2dabe5e
WD
110- static int64 modtime;
111+ static int64 modtime, atime;
43581f16 112 static mode_t mode;
ba50e96c 113 static int64 dev;
43581f16 114 static dev_t rdev;
898a2112 115@@ -735,6 +749,16 @@ static struct file_struct *recv_file_ent
a2dabe5e 116 }
761f1b71 117 if (!(xflags & XMIT_SAME_MODE))
43581f16 118 mode = from_wire_mode(read_int(f));
898a2112 119+ if (atimes_ndx && !S_ISDIR(mode) && !(xflags & XMIT_SAME_ATIME)) {
a2dabe5e
WD
120+ atime = read_varlong(f, 4);
121+#if SIZEOF_TIME_T < SIZEOF_INT64
122+ if ((atime > INT_MAX || atime < INT_MIN) && !am_generator) {
123+ rprintf(FERROR,
124+ "Access time value of %s truncated on receiver.\n",
125+ lastname);
126+ }
127+#endif
128+ }
43581f16 129
1cb60481
WD
130 if (chmod_modes && !S_ISLNK(mode))
131 mode = tweak_mode(mode, chmod_modes);
898a2112 132@@ -863,6 +887,8 @@ static struct file_struct *recv_file_ent
fc068916 133 F_GROUP(file) = gid;
761f1b71
WD
134 file->flags |= gid_flags;
135 }
898a2112 136+ if (atimes_ndx)
a2dabe5e 137+ F_ATIME(file) = (time_t)atime;
58b399b9
WD
138 #ifdef ICONV_OPTION
139 if (ic_ndx)
140 F_NDX(file) = flist->count + flist->ndx_start;
898a2112 141@@ -1182,6 +1208,8 @@ struct file_struct *make_file(const char
fc068916 142 F_OWNER(file) = st.st_uid;
898a2112 143 if (gid_ndx)
fc068916 144 F_GROUP(file) = st.st_gid;
898a2112 145+ if (atimes_ndx)
70891d26 146+ F_ATIME(file) = st.st_atime;
1cb60481 147
fc068916
WD
148 if (basename != thisname)
149 file->dirname = lastdir;
9a7eef96
WD
150--- old/generator.c
151+++ new/generator.c
898a2112
WD
152@@ -43,6 +43,7 @@ extern int preserve_specials;
153 extern int preserve_hard_links;
154 extern int preserve_perms;
81c32ffd 155 extern int preserve_times;
81c32ffd 156+extern int preserve_atimes;
55602791 157 extern int omit_dir_times;
898a2112
WD
158 extern int uid_ndx;
159 extern int gid_ndx;
58b399b9 160@@ -563,6 +564,9 @@ void itemize(const char *fnamecmp, struc
9a70b743 161 && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
4306c620 162 || (keep_time && cmp_time(file->modtime, sxp->st.st_mtime) != 0))
f20eb450 163 iflags |= ITEM_REPORT_TIME;
55602791 164+ if (preserve_atimes && !S_ISDIR(file->mode) && !S_ISLNK(file->mode)
85a65b82 165+ && cmp_time(F_ATIME(file), sxp->st.st_atime) != 0)
55602791 166+ iflags |= ITEM_REPORT_ATIME;
4306c620 167 if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
f20eb450 168 iflags |= ITEM_REPORT_PERMS;
898a2112 169 if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
58b399b9 170@@ -880,6 +884,8 @@ static int try_dests_reg(struct file_str
8aec0853
WD
171 if (link_dest) {
172 if (!hard_link_one(file, fname, cmpbuf, 1))
8a04c9a7
WD
173 goto try_a_copy;
174+ if (preserve_atimes)
97669ae9 175+ set_file_attrs(fname, file, sxp, NULL, 0);
1aa236e1 176 if (preserve_hard_links && F_IS_HLINKED(file))
4306c620 177 finish_hard_link(file, fname, &sxp->st, itemizing, code, j);
8aec0853 178 if (itemizing && (verbose > 1 || stdout_format_has_i > 1)) {
6cbbe66d 179@@ -1749,7 +1755,7 @@ static void touch_up_dirs(struct file_li
85a65b82
WD
180 if (!(file->mode & S_IWUSR))
181 do_chmod(fname, file->mode);
182 if (need_retouch_dir_times)
183- set_modtime(fname, file->modtime, file->mode);
184+ set_times(fname, file->modtime, file->modtime, file->mode);
6cbbe66d 185 if (allowed_lull && !(counter % lull_mod))
85a65b82 186 maybe_send_keepalive();
6cbbe66d 187 else if (!(counter & 0xFF))
9a7eef96
WD
188--- old/log.c
189+++ new/log.c
898a2112 190@@ -631,7 +631,8 @@ static void log_formatted(enum logcode c
fb11cdd7
WD
191 c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
192 c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
193 c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
4306c620 194- c[8] = !(iflags & ITEM_REPORT_ATIME) ? '.' : 'u';
fb11cdd7 195+ c[8] = !(iflags & ITEM_REPORT_ATIME) ? '.'
55602791 196+ : S_ISLNK(file->mode) ? 'U' : 'u';
4306c620
WD
197 c[9] = !(iflags & ITEM_REPORT_ACL) ? '.' : 'a';
198 c[10] = !(iflags & ITEM_REPORT_XATTR) ? '.' : 'x';
199 c[11] = '\0';
9a7eef96
WD
200--- old/options.c
201+++ new/options.c
5795bf59 202@@ -56,6 +56,7 @@ int preserve_uid = 0;
43581f16
WD
203 int preserve_gid = 0;
204 int preserve_times = 0;
9a21ad72 205 int omit_dir_times = 0;
81c32ffd 206+int preserve_atimes = 0;
43581f16
WD
207 int update_only = 0;
208 int cvs_exclude = 0;
209 int dry_run = 0;
6cbbe66d 210@@ -335,8 +336,9 @@ void usage(enum logcode F)
4a65fe72
WD
211 rprintf(F," --devices preserve device files (super-user only)\n");
212 rprintf(F," --specials preserve special files\n");
213 rprintf(F," -D same as --devices --specials\n");
81c32ffd
WD
214- rprintf(F," -t, --times preserve times\n");
215- rprintf(F," -O, --omit-dir-times omit directories when preserving times\n");
216+ rprintf(F," -t, --times preserve modify times\n");
217+ rprintf(F," -O, --omit-dir-times omit directories when preserving modify times\n");
12b04b40 218+ rprintf(F," -U, --atimes preserve access (last-used) times\n");
4a65fe72 219 rprintf(F," --super receiver attempts super-user activities\n");
12b04b40
WD
220 #ifdef SUPPORT_XATTRS
221 rprintf(F," --fake-super store/recover privileged attrs using xattrs\n");
6cbbe66d 222@@ -471,6 +473,9 @@ static struct poptOption long_options[]
489b0a72
WD
223 {"times", 't', POPT_ARG_VAL, &preserve_times, 1, 0, 0 },
224 {"no-times", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
225 {"no-t", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
55602791 226+ {"atimes", 'U', POPT_ARG_VAL, &preserve_atimes, 1, 0, 0 },
489b0a72 227+ {"no-atimes", 0, POPT_ARG_VAL, &preserve_atimes, 0, 0, 0 },
70891d26 228+ {"no-U", 0, POPT_ARG_VAL, &preserve_atimes, 0, 0, 0 },
52f25864 229 {"omit-dir-times", 'O', POPT_ARG_VAL, &omit_dir_times, 2, 0, 0 },
489b0a72 230 {"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
4a65fe72 231 {"super", 0, POPT_ARG_VAL, &am_root, 2, 0, 0 },
6cbbe66d 232@@ -1668,6 +1673,8 @@ void server_options(char **args,int *arg
43581f16
WD
233 argstr[x++] = 'D';
234 if (preserve_times)
235 argstr[x++] = 't';
81c32ffd 236+ if (preserve_atimes)
55602791 237+ argstr[x++] = 'U';
43581f16 238 if (preserve_perms)
4a65fe72
WD
239 argstr[x++] = 'p';
240 else if (preserve_executability && am_sender)
9a7eef96
WD
241--- old/rsync.c
242+++ new/rsync.c
58b399b9 243@@ -32,6 +32,7 @@ extern int preserve_acls;
5795bf59 244 extern int preserve_xattrs;
d9a67109 245 extern int preserve_perms;
4a65fe72 246 extern int preserve_executability;
d9a67109 247+extern int preserve_atimes;
43581f16 248 extern int preserve_times;
9a21ad72 249 extern int omit_dir_times;
43581f16 250 extern int am_root;
6cbbe66d 251@@ -275,6 +276,7 @@ int set_file_attrs(const char *fname, st
9a21ad72 252 int updated = 0;
4306c620 253 statx sx2;
9a21ad72
WD
254 int change_uid, change_gid;
255+ time_t atime, mtime;
1ed0b5c9 256 mode_t new_mode = file->mode;
9a21ad72 257
4306c620 258 if (!sxp) {
6cbbe66d 259@@ -312,18 +314,36 @@ int set_file_attrs(const char *fname, st
12b04b40 260 set_stat_xattr(fname, file);
4306c620 261 #endif
9a21ad72 262
8a04c9a7
WD
263+ /* This code must be the first update in the function due to
264+ * how it uses the "updated" variable. */
4306c620 265 if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && omit_dir_times))
4a65fe72 266 flags |= ATTRS_SKIP_MTIME;
4306c620 267+ if (!preserve_atimes || S_ISDIR(sxp->st.st_mode))
4a65fe72
WD
268+ flags |= ATTRS_SKIP_ATIME;
269 if (!(flags & ATTRS_SKIP_MTIME)
4306c620
WD
270 && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
271- int ret = set_modtime(fname, file->modtime, sxp->st.st_mode);
9a21ad72 272+ mtime = file->modtime;
9e355bf1 273+ updated = 1;
9a21ad72 274+ } else
4306c620 275+ mtime = sxp->st.st_mtime;
672ad041 276+ if (!(flags & ATTRS_SKIP_ATIME)) {
70891d26 277+ time_t file_atime = F_ATIME(file);
4306c620 278+ if (cmp_time(sxp->st.st_atime, file_atime) != 0) {
672ad041
WD
279+ atime = file_atime;
280+ updated = 1;
281+ } else
4306c620 282+ atime = sxp->st.st_atime;
81c32ffd 283+ } else
4306c620 284+ atime = sxp->st.st_atime;
9e355bf1 285+ if (updated) {
4306c620 286+ int ret = set_times(fname, mtime, atime, sxp->st.st_mode);
9e355bf1
WD
287 if (ret < 0) {
288 rsyserr(FERROR, errno, "failed to set times on %s",
289 full_fname(fname));
4306c620 290 goto cleanup;
9e355bf1
WD
291 }
292- if (ret == 0) /* ret == 1 if symlink could not be set */
293- updated = 1;
294+ if (ret > 0) /* ret == 1 if symlink could not be set */
295+ updated = 0;
43581f16
WD
296 }
297
898a2112 298 change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
9a7eef96
WD
299--- old/rsync.h
300+++ new/rsync.h
4306c620 301@@ -56,6 +56,7 @@
caf38d8d
WD
302 #define XMIT_RDEV_MINOR_8_pre30 (1<<11) /* protocols 28 - 29 */
303 #define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - NOW */
304 #define XMIT_HLINK_FIRST (1<<12) /* protocols 30 - NOW */
305+#define XMIT_SAME_ATIME (1<<13) /* protocols ?? - NOW */
43581f16
WD
306
307 /* These flags are used in the live flist data. */
308
761f1b71 309@@ -143,6 +144,7 @@
8a529471 310
4a65fe72
WD
311 #define ATTRS_REPORT (1<<0)
312 #define ATTRS_SKIP_MTIME (1<<1)
313+#define ATTRS_SKIP_ATIME (1<<2)
8a529471
WD
314
315 #define FULL_FLUSH 1
316 #define NORMAL_FLUSH 0
58b399b9 317@@ -582,6 +584,7 @@ struct file_struct {
5795bf59 318 extern int file_extra_cnt;
898a2112
WD
319 extern int uid_ndx;
320 extern int gid_ndx;
321+extern int atimes_ndx;
322 extern int acls_ndx;
323 extern int xattrs_ndx;
fdf967c7 324
898a2112 325@@ -616,6 +619,7 @@ extern int xattrs_ndx;
1aa236e1 326 /* When the associated option is on, all entries will have these present: */
898a2112
WD
327 #define F_OWNER(f) REQ_EXTRA(f, uid_ndx)->unum
328 #define F_GROUP(f) REQ_EXTRA(f, gid_ndx)->unum
329+#define F_ATIME(f) REQ_EXTRA(f, atimes_ndx)->unum
330 #define F_ACL(f) REQ_EXTRA(f, acls_ndx)->num
331 #define F_XATTR(f) REQ_EXTRA(f, xattrs_ndx)->num
58b399b9 332 #define F_NDX(f) REQ_EXTRA(f, ic_ndx)->num
9a7eef96
WD
333--- old/rsync.yo
334+++ new/rsync.yo
761f1b71 335@@ -336,8 +336,9 @@ to the detailed description below for a
4a65fe72
WD
336 --devices preserve device files (super-user only)
337 --specials preserve special files
338 -D same as --devices --specials
81c32ffd 339- -t, --times preserve times
610969d1 340- -O, --omit-dir-times omit directories when preserving times
81c32ffd 341+ -t, --times preserve modify times
610969d1 342+ -O, --omit-dir-times omit directories when preserving mod-times
55602791 343+ -U, --atimes preserve access (use) times
4a65fe72 344 --super receiver attempts super-user activities
12b04b40 345 --fake-super store/recover privileged attrs using xattrs
43581f16 346 -S, --sparse handle sparse files efficiently
761f1b71 347@@ -916,6 +917,12 @@ it is preserving modification times (see
a7219d20 348 the directories on the receiving side, it is a good idea to use bf(-O).
333b8af4 349 This option is inferred if you use bf(--backup) without bf(--backup-dir).
7b675ff5 350
55602791
WD
351+dit(bf(-U, --atimes)) This tells rsync to set the access (use) times of the
352+destination files to the same value as the source files. Note that the
81c32ffd
WD
353+reading of the source file may update the atime of the source files, so
354+repeated rsync runs with --atimes may be needed if you want to force the
355+access-time values to be 100% identical on the two systems.
7b675ff5 356+
4a65fe72
WD
357 dit(bf(--super)) This tells the receiving side to attempt super-user
358 activities even if the receiving rsync wasn't run by the super-user. These
359 activities include: preserving users via the bf(--owner) option, preserving
761f1b71 360@@ -1530,7 +1537,7 @@ quote(itemization(
81c32ffd
WD
361 by the file transfer.
362 it() A bf(t) means the modification time is different and is being updated
363 to the sender's value (requires bf(--times)). An alternate value of bf(T)
364- means that the time will be set to the transfer time, which happens
365+ means that the modify time will be set to the transfer time, which happens
366 anytime a symlink is transferred, or when a file or device is transferred
367 without bf(--times).
ccc3a12c 368 it() A bf(p) means the permissions are different and are being updated to
761f1b71 369@@ -1539,8 +1546,10 @@ quote(itemization(
ccc3a12c
WD
370 sender's value (requires bf(--owner) and super-user privileges).
371 it() A bf(g) means the group is different and is being updated to the
372 sender's value (requires bf(--group) and the authority to set the group).
4306c620
WD
373- it() The bf(u) slot is reserved for reporting update (access) time changes
374- (a feature that is not yet released).
55602791
WD
375+ it() A bf(u) means the access (use) time is different and is being updated to
376+ the sender's value (requires bf(--atimes)). An alternate value of bf(U)
377+ means that the access time will be set to the transfer time, which happens
ccc3a12c 378+ when a symlink or directory is updated.
4306c620
WD
379 it() The bf(a) means that the ACL information changed.
380 it() The bf(x) slot is reserved for reporting extended attribute changes
381 (a feature that is not yet released).
9a7eef96
WD
382--- old/sender.c
383+++ new/sender.c
5795bf59 384@@ -43,6 +43,7 @@ extern int do_progress;
1cb60481
WD
385 extern int inplace;
386 extern int batch_fd;
387 extern int write_batch;
388+extern unsigned int file_struct_len;
389 extern struct stats stats;
fc068916 390 extern struct file_list *cur_flist, *first_flist;
4306c620 391
9a7eef96
WD
392--- old/testsuite/atimes.test
393+++ new/testsuite/atimes.test
13bed3dd
WD
394@@ -0,0 +1,19 @@
395+#! /bin/sh
396+
397+# Test rsync copying atimes
398+
399+. "$suitedir/rsync.fns"
400+
401+set -x
402+
403+mkdir "$fromdir"
404+
405+touch "$fromdir/foo"
406+touch -a -t 200102031717.42 "$fromdir/foo"
407+
408+TLS_ARGS=--atime
409+
55602791 410+checkit "$RSYNC -rtUgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
13bed3dd
WD
411+
412+# The script would have aborted on error, so getting here means we've won.
413+exit 0
9a7eef96
WD
414--- old/testsuite/rsync.fns
415+++ new/testsuite/rsync.fns
58b399b9 416@@ -186,6 +186,10 @@ checkit() {
13bed3dd
WD
417 # We can just write everything to stdout/stderr, because the
418 # wrapper hides it unless there is a problem.
419
81c32ffd
WD
420+ if test x$TLS_ARGS = x--atime; then
421+ ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
422+ fi
13bed3dd
WD
423+
424 echo "Running: \"$1\""
425 eval "$1"
426 status=$?
58b399b9 427@@ -193,10 +197,13 @@ checkit() {
81c32ffd
WD
428 failed="YES";
429 fi
430
431+ if test x$TLS_ARGS != x--atime; then
432+ ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
433+ fi
434+
13bed3dd 435 echo "-------------"
b78a6aba
WD
436 echo "check how the directory listings compare with diff:"
437 echo ""
13bed3dd 438- ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
b78a6aba
WD
439 ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
440 diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
4da25dad 441
9a7eef96
WD
442--- old/tls.c
443+++ new/tls.c
58b399b9
WD
444@@ -98,6 +98,8 @@ static int stat_xattr(const char *fname,
445
446 #endif
43581f16
WD
447
448+static int display_atime = 0;
b3593e7c 449+
fe6407b5
WD
450 static void failed(char const *what, char const *where)
451 {
b3593e7c 452 fprintf(stderr, PROGRAM ": %s %s: %s\n",
58b399b9 453@@ -105,12 +107,29 @@ static void failed(char const *what, cha
fe6407b5 454 exit(1);
43581f16
WD
455 }
456
3f053c45 457+static void storetime(char *dest, time_t t, size_t destsize)
43581f16
WD
458+{
459+ if (t) {
460+ struct tm *mt = gmtime(&t);
b3593e7c 461+
3f053c45
WD
462+ snprintf(dest, destsize,
463+ "%04d-%02d-%02d %02d:%02d:%02d ",
9d95bd65
WD
464+ (int)mt->tm_year + 1900,
465+ (int)mt->tm_mon + 1,
466+ (int)mt->tm_mday,
467+ (int)mt->tm_hour,
468+ (int)mt->tm_min,
469+ (int)mt->tm_sec);
3f053c45
WD
470+ } else
471+ strlcpy(dest, " ", destsize);
b3593e7c
WD
472+}
473+
fe6407b5 474 static void list_file(const char *fname)
43581f16
WD
475 {
476 STRUCT_STAT buf;
477 char permbuf[PERMSTRING_SIZE];
478- struct tm *mt;
479- char datebuf[50];
480+ char mtimebuf[50];
481+ char atimebuf[50];
482 char linkbuf[4096];
483
ba50e96c 484 if (do_lstat(fname, &buf) < 0)
58b399b9 485@@ -147,19 +166,8 @@ static void list_file(const char *fname)
43581f16
WD
486
487 permstring(permbuf, buf.st_mode);
488
489- if (buf.st_mtime) {
490- mt = gmtime(&buf.st_mtime);
491-
3f053c45
WD
492- snprintf(datebuf, sizeof datebuf,
493- "%04d-%02d-%02d %02d:%02d:%02d",
9d95bd65
WD
494- (int)mt->tm_year + 1900,
495- (int)mt->tm_mon + 1,
496- (int)mt->tm_mday,
497- (int)mt->tm_hour,
498- (int)mt->tm_min,
499- (int)mt->tm_sec);
3f053c45
WD
500- } else
501- strlcpy(datebuf, " ", sizeof datebuf);
502+ storetime(mtimebuf, buf.st_mtime, sizeof mtimebuf);
503+ storetime(atimebuf, buf.st_atime, sizeof atimebuf);
43581f16
WD
504
505 /* TODO: Perhaps escape special characters in fname? */
506
58b399b9 507@@ -170,13 +178,15 @@ static void list_file(const char *fname)
43581f16
WD
508 (long)minor(buf.st_rdev));
509 } else /* NB: use double for size since it might not fit in a long. */
510 printf("%12.0f", (double)buf.st_size);
511- printf(" %6ld.%-6ld %6ld %s %s%s\n",
512+ printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
513 (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
514- datebuf, fname, linkbuf);
c0be1af2 515+ mtimebuf, display_atime && !S_ISDIR(buf.st_mode) ? atimebuf : "",
43581f16 516+ fname, linkbuf);
b3593e7c 517 }
43581f16 518
12b04b40
WD
519 static struct poptOption long_options[] = {
520 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
521+ {"atime", 'u', POPT_ARG_NONE, &display_atime, 0, 0, 0},
58b399b9 522 #ifdef SUPPORT_XATTRS
12b04b40 523 {"fake-super", 'f', POPT_ARG_VAL, &am_root, -1, 0, 0 },
58b399b9
WD
524 #endif
525@@ -190,6 +200,7 @@ static void tls_usage(int ret)
12b04b40
WD
526 fprintf(F,"usage: " PROGRAM " [OPTIONS] FILE ...\n");
527 fprintf(F,"Trivial file listing program for portably checking rsync\n");
528 fprintf(F,"\nOptions:\n");
529+ rprintf(F," -U, --atimes display access (last-used) times\n");
58b399b9 530 #ifdef SUPPORT_XATTRS
12b04b40 531 fprintf(F," -f, --fake-super display attributes including fake-super xattrs\n");
58b399b9 532 #endif
9a7eef96
WD
533--- old/util.c
534+++ new/util.c
898a2112 535@@ -121,7 +121,7 @@ NORETURN void overflow_exit(const char *
577db5e2
WD
536 exit_cleanup(RERR_MALLOC);
537 }
43581f16 538
fb11cdd7
WD
539-int set_modtime(const char *fname, time_t modtime, mode_t mode)
540+int set_times(const char *fname, time_t modtime, time_t atime, mode_t mode)
43581f16 541 {
9e355bf1
WD
542 #if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
543 if (S_ISLNK(mode))
898a2112 544@@ -129,9 +129,13 @@ int set_modtime(const char *fname, time_
9e355bf1
WD
545 #endif
546
43581f16
WD
547 if (verbose > 2) {
548- rprintf(FINFO, "set modtime of %s to (%ld) %s",
549+ char mtimebuf[200];
43581f16 550+
125d7fca 551+ strlcpy(mtimebuf, timestring(modtime), sizeof mtimebuf);
43581f16
WD
552+ rprintf(FINFO,
553+ "set modtime, atime of %s to (%ld) %s, (%ld) %s\n",
93ca4d27 554 fname, (long)modtime,
43581f16 555- asctime(localtime(&modtime)));
9e355bf1 556+ mtimebuf, (long)atime, timestring(atime));
43581f16
WD
557 }
558
ba50e96c 559 if (dry_run)
898a2112 560@@ -140,7 +144,7 @@ int set_modtime(const char *fname, time_
43581f16 561 {
9e355bf1
WD
562 #ifdef HAVE_UTIMES
563 struct timeval t[2];
564- t[0].tv_sec = time(NULL);
565+ t[0].tv_sec = atime;
566 t[0].tv_usec = 0;
567 t[1].tv_sec = modtime;
568 t[1].tv_usec = 0;
898a2112 569@@ -153,12 +157,12 @@ int set_modtime(const char *fname, time_
9e355bf1
WD
570 return utimes(fname, t);
571 #elif defined HAVE_UTIMBUF
43581f16
WD
572 struct utimbuf tbuf;
573- tbuf.actime = time(NULL);
574+ tbuf.actime = atime;
575 tbuf.modtime = modtime;
576 return utime(fname,&tbuf);
09fb8f03 577 #elif defined HAVE_UTIME
43581f16
WD
578 time_t t[2];
579- t[0] = time(NULL);
580+ t[0] = atime;
581 t[1] = modtime;
582 return utime(fname,t);
583 #else