Fixed the sending of new files with long xattrs.
[rsync/rsync-patches.git] / atimes.diff
... / ...
CommitLineData
1To use this patch, run these commands for a successful build:
2
3 patch -p1 <patches/atimes.diff
4 ./prepare-source
5 ./configure (optional if already run)
6 make
7
8
9--- old/compat.c
10+++ new/compat.c
11@@ -62,6 +62,8 @@ void setup_protocol(int f_out,int f_in)
12 preserve_uid = ++file_extra_cnt;
13 if (preserve_gid)
14 preserve_gid = ++file_extra_cnt;
15+ if (preserve_atimes)
16+ preserve_atimes = ++file_extra_cnt;
17 if (preserve_acls && !am_sender)
18 preserve_acls = ++file_extra_cnt;
19
20--- old/flist.c
21+++ new/flist.c
22@@ -49,6 +49,7 @@ extern int preserve_devices;
23 extern int preserve_specials;
24 extern int preserve_uid;
25 extern int preserve_gid;
26+extern int preserve_atimes;
27 extern int relative_paths;
28 extern int implied_dirs;
29 extern int file_extra_cnt;
30@@ -144,6 +145,7 @@ void show_flist_stats(void)
31 static void list_file_entry(struct file_struct *f)
32 {
33 char permbuf[PERMSTRING_SIZE];
34+ time_t atime = preserve_atimes ? F_ATIME(f) : 0;
35 double len;
36
37 if (!F_IS_ACTIVE(f)) {
38@@ -158,14 +160,16 @@ static void list_file_entry(struct file_
39
40 #ifdef SUPPORT_LINKS
41 if (preserve_links && S_ISLNK(f->mode)) {
42- rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
43+ rprintf(FINFO, "%s %11.0f %s %s %s -> %s\n",
44 permbuf, len, timestring(f->modtime),
45+ preserve_atimes ? timestring(atime) : "",
46 f_name(f, NULL), F_SYMLINK(f));
47 } else
48 #endif
49 {
50- rprintf(FINFO, "%s %11.0f %s %s\n",
51+ rprintf(FINFO, "%s %11.0f %s %s %s\n",
52 permbuf, len, timestring(f->modtime),
53+ preserve_atimes ? timestring(atime) : "",
54 f_name(f, NULL));
55 }
56 }
57@@ -349,6 +353,7 @@ int push_flist_dir(const char *dir, int
58 static void send_file_entry(int f, struct file_struct *file, int ndx)
59 {
60 static time_t modtime;
61+ static time_t atime;
62 static mode_t mode;
63 static int64 dev;
64 static dev_t rdev;
65@@ -416,6 +421,13 @@ static void send_file_entry(int f, struc
66 flags |= XMIT_SAME_TIME;
67 else
68 modtime = file->modtime;
69+ if (preserve_atimes && !S_ISDIR(mode)) {
70+ time_t file_atime = F_ATIME(file);
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 (tmp_dev != 0) {
79@@ -483,6 +495,8 @@ static void send_file_entry(int f, struc
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 (protocol_version < 30)
87 write_int(f, uid);
88@@ -569,7 +583,7 @@ static void send_file_entry(int f, struc
89 static struct file_struct *recv_file_entry(struct file_list *flist,
90 int flags, int f)
91 {
92- static time_t modtime;
93+ static time_t modtime, atime;
94 static mode_t mode;
95 static int64 dev;
96 static dev_t rdev;
97@@ -667,6 +681,8 @@ static struct file_struct *recv_file_ent
98 modtime = (time_t)read_int(f);
99 if (!(flags & XMIT_SAME_MODE))
100 mode = from_wire_mode(read_int(f));
101+ if (preserve_atimes && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
102+ atime = (time_t)read_int(f);
103
104 if (chmod_modes && !S_ISLNK(mode))
105 mode = tweak_mode(mode, chmod_modes);
106@@ -791,6 +807,8 @@ static struct file_struct *recv_file_ent
107 F_OWNER(file) = uid;
108 if (preserve_gid)
109 F_GROUP(file) = gid;
110+ if (preserve_atimes)
111+ F_ATIME(file) = atime;
112
113 if (basename != thisname) {
114 file->dirname = lastdir;
115@@ -1096,6 +1114,8 @@ struct file_struct *make_file(const char
116 F_OWNER(file) = st.st_uid;
117 if (preserve_gid)
118 F_GROUP(file) = st.st_gid;
119+ if (preserve_atimes)
120+ F_ATIME(file) = st.st_atime;
121
122 if (basename != thisname)
123 file->dirname = lastdir;
124--- old/generator.c
125+++ new/generator.c
126@@ -44,6 +44,7 @@ extern int preserve_perms;
127 extern int preserve_uid;
128 extern int preserve_gid;
129 extern int preserve_times;
130+extern int preserve_atimes;
131 extern int omit_dir_times;
132 extern int delete_mode;
133 extern int delete_before;
134@@ -552,6 +553,9 @@ void itemize(const char *fname, struct f
135 && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
136 || (keep_time && cmp_time(file->modtime, sxp->st.st_mtime) != 0))
137 iflags |= ITEM_REPORT_TIME;
138+ if (preserve_atimes && !S_ISDIR(file->mode) && !S_ISLNK(file->mode)
139+ && cmp_time(F_ATIME(file), sxp->st.st_atime) != 0)
140+ iflags |= ITEM_REPORT_ATIME;
141 if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
142 iflags |= ITEM_REPORT_PERMS;
143 if (preserve_uid && am_root && F_UID(file) != sxp->st.st_uid)
144@@ -852,6 +856,8 @@ static int try_dests_reg(struct file_str
145 if (link_dest) {
146 if (!hard_link_one(file, fname, cmpbuf, 1))
147 goto try_a_copy;
148+ if (preserve_atimes)
149+ set_file_attrs(fname, file, sxp, 0);
150 if (preserve_hard_links && F_IS_HLINKED(file))
151 finish_hard_link(file, fname, &sxp->st, itemizing, code, j);
152 if (itemizing && (verbose > 1 || stdout_format_has_i > 1)) {
153@@ -1700,7 +1706,7 @@ static void touch_up_dirs(struct file_li
154 if (!(file->mode & S_IWUSR))
155 do_chmod(fname, file->mode);
156 if (need_retouch_dir_times)
157- set_modtime(fname, file->modtime, file->mode);
158+ set_times(fname, file->modtime, file->modtime, file->mode);
159 if (allowed_lull && !(++j % lull_mod))
160 maybe_send_keepalive();
161 else if (!(j % 200))
162--- old/log.c
163+++ new/log.c
164@@ -36,6 +36,7 @@ extern int msg_fd_out;
165 extern int allow_8bit_chars;
166 extern int protocol_version;
167 extern int preserve_times;
168+extern int preserve_atimes;
169 extern int preserve_uid;
170 extern int preserve_gid;
171 extern int stdout_format_has_i;
172@@ -624,7 +625,8 @@ static void log_formatted(enum logcode c
173 c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
174 c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
175 c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
176- c[8] = !(iflags & ITEM_REPORT_ATIME) ? '.' : 'u';
177+ c[8] = !(iflags & ITEM_REPORT_ATIME) ? '.'
178+ : S_ISLNK(file->mode) ? 'U' : 'u';
179 c[9] = !(iflags & ITEM_REPORT_ACL) ? '.' : 'a';
180 c[10] = !(iflags & ITEM_REPORT_XATTR) ? '.' : 'x';
181 c[11] = '\0';
182--- old/options.c
183+++ new/options.c
184@@ -55,6 +55,7 @@ int preserve_uid = 0;
185 int preserve_gid = 0;
186 int preserve_times = 0;
187 int omit_dir_times = 0;
188+int preserve_atimes = 0;
189 int update_only = 0;
190 int cvs_exclude = 0;
191 int dry_run = 0;
192@@ -315,8 +316,9 @@ void usage(enum logcode F)
193 rprintf(F," --devices preserve device files (super-user only)\n");
194 rprintf(F," --specials preserve special files\n");
195 rprintf(F," -D same as --devices --specials\n");
196- rprintf(F," -t, --times preserve times\n");
197- rprintf(F," -O, --omit-dir-times omit directories when preserving times\n");
198+ rprintf(F," -t, --times preserve modify times\n");
199+ rprintf(F," -O, --omit-dir-times omit directories when preserving modify times\n");
200+ rprintf(F," -U, --atimes preserve access (use) times\n");
201 rprintf(F," --super receiver attempts super-user activities\n");
202 rprintf(F," -S, --sparse handle sparse files efficiently\n");
203 rprintf(F," -n, --dry-run show what would have been transferred\n");
204@@ -436,6 +438,9 @@ static struct poptOption long_options[]
205 {"times", 't', POPT_ARG_VAL, &preserve_times, 1, 0, 0 },
206 {"no-times", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
207 {"no-t", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
208+ {"atimes", 'U', POPT_ARG_VAL, &preserve_atimes, 1, 0, 0 },
209+ {"no-atimes", 0, POPT_ARG_VAL, &preserve_atimes, 0, 0, 0 },
210+ {"no-U", 0, POPT_ARG_VAL, &preserve_atimes, 0, 0, 0 },
211 {"omit-dir-times", 'O', POPT_ARG_VAL, &omit_dir_times, 2, 0, 0 },
212 {"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
213 {"super", 0, POPT_ARG_VAL, &am_root, 2, 0, 0 },
214@@ -1577,6 +1582,8 @@ void server_options(char **args,int *arg
215 argstr[x++] = 'D';
216 if (preserve_times)
217 argstr[x++] = 't';
218+ if (preserve_atimes)
219+ argstr[x++] = 'U';
220 if (preserve_perms)
221 argstr[x++] = 'p';
222 else if (preserve_executability && am_sender)
223--- old/rsync.c
224+++ new/rsync.c
225@@ -34,6 +34,7 @@ extern int dry_run;
226 extern int preserve_acls;
227 extern int preserve_perms;
228 extern int preserve_executability;
229+extern int preserve_atimes;
230 extern int preserve_times;
231 extern int omit_dir_times;
232 extern int am_root;
233@@ -234,6 +235,7 @@ int set_file_attrs(char *fname, struct f
234 int updated = 0;
235 statx sx2;
236 int change_uid, change_gid;
237+ time_t atime, mtime;
238 mode_t new_mode = file->mode;
239
240 if (!sxp) {
241@@ -261,18 +263,36 @@ int set_file_attrs(char *fname, struct f
242 get_acl(fname, sxp);
243 #endif
244
245+ /* This code must be the first update in the function due to
246+ * how it uses the "updated" variable. */
247 if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && omit_dir_times))
248 flags |= ATTRS_SKIP_MTIME;
249+ if (!preserve_atimes || S_ISDIR(sxp->st.st_mode))
250+ flags |= ATTRS_SKIP_ATIME;
251 if (!(flags & ATTRS_SKIP_MTIME)
252 && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
253- int ret = set_modtime(fname, file->modtime, sxp->st.st_mode);
254+ mtime = file->modtime;
255+ updated = 1;
256+ } else
257+ mtime = sxp->st.st_mtime;
258+ if (!(flags & ATTRS_SKIP_ATIME)) {
259+ time_t file_atime = F_ATIME(file);
260+ if (cmp_time(sxp->st.st_atime, file_atime) != 0) {
261+ atime = file_atime;
262+ updated = 1;
263+ } else
264+ atime = sxp->st.st_atime;
265+ } else
266+ atime = sxp->st.st_atime;
267+ if (updated) {
268+ int ret = set_times(fname, mtime, atime, sxp->st.st_mode);
269 if (ret < 0) {
270 rsyserr(FERROR, errno, "failed to set times on %s",
271 full_fname(fname));
272 goto cleanup;
273 }
274- if (ret == 0) /* ret == 1 if symlink could not be set */
275- updated = 1;
276+ if (ret > 0) /* ret == 1 if symlink could not be set */
277+ updated = 0;
278 }
279
280 change_uid = am_root && preserve_uid && sxp->st.st_uid != F_UID(file);
281--- old/rsync.h
282+++ new/rsync.h
283@@ -56,6 +56,7 @@
284 #define XMIT_RDEV_MINOR_8_pre30 (1<<11) /* protocols 28 - 29 */
285 #define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - NOW */
286 #define XMIT_HLINK_FIRST (1<<12) /* protocols 30 - NOW */
287+#define XMIT_SAME_ATIME (1<<13) /* protocols ?? - NOW */
288
289 /* These flags are used in the live flist data. */
290
291@@ -136,6 +137,7 @@
292
293 #define ATTRS_REPORT (1<<0)
294 #define ATTRS_SKIP_MTIME (1<<1)
295+#define ATTRS_SKIP_ATIME (1<<2)
296
297 #define FULL_FLUSH 1
298 #define NORMAL_FLUSH 0
299@@ -571,6 +573,7 @@ extern int file_extra_cnt;
300 extern int preserve_uid;
301 extern int preserve_gid;
302 extern int preserve_acls;
303+extern int preserve_atimes;
304
305 #define FILE_STRUCT_LEN (offsetof(struct file_struct, basename))
306 #define EXTRA_LEN (sizeof (union file_extras))
307@@ -603,6 +606,7 @@ extern int preserve_acls;
308 /* When the associated option is on, all entries will have these present: */
309 #define F_OWNER(f) REQ_EXTRA(f, preserve_uid)->unum
310 #define F_GROUP(f) REQ_EXTRA(f, preserve_gid)->unum
311+#define F_ATIME(f) REQ_EXTRA(f, preserve_atimes)->unum
312 #define F_ACL(f) REQ_EXTRA(f, preserve_acls)->unum
313
314 /* These items are per-entry optional and mutally exclusive: */
315--- old/rsync.yo
316+++ new/rsync.yo
317@@ -329,8 +329,9 @@ to the detailed description below for a
318 --devices preserve device files (super-user only)
319 --specials preserve special files
320 -D same as --devices --specials
321- -t, --times preserve times
322- -O, --omit-dir-times omit directories when preserving times
323+ -t, --times preserve modify times
324+ -O, --omit-dir-times omit directories when preserving mod-times
325+ -U, --atimes preserve access (use) times
326 --super receiver attempts super-user activities
327 -S, --sparse handle sparse files efficiently
328 -n, --dry-run show what would have been transferred
329@@ -896,6 +897,12 @@ it is preserving modification times (see
330 the directories on the receiving side, it is a good idea to use bf(-O).
331 This option is inferred if you use bf(--backup) without bf(--backup-dir).
332
333+dit(bf(-U, --atimes)) This tells rsync to set the access (use) times of the
334+destination files to the same value as the source files. Note that the
335+reading of the source file may update the atime of the source files, so
336+repeated rsync runs with --atimes may be needed if you want to force the
337+access-time values to be 100% identical on the two systems.
338+
339 dit(bf(--super)) This tells the receiving side to attempt super-user
340 activities even if the receiving rsync wasn't run by the super-user. These
341 activities include: preserving users via the bf(--owner) option, preserving
342@@ -1482,7 +1489,7 @@ quote(itemization(
343 by the file transfer.
344 it() A bf(t) means the modification time is different and is being updated
345 to the sender's value (requires bf(--times)). An alternate value of bf(T)
346- means that the time will be set to the transfer time, which happens
347+ means that the modify time will be set to the transfer time, which happens
348 anytime a symlink is transferred, or when a file or device is transferred
349 without bf(--times).
350 it() A bf(p) means the permissions are different and are being updated to
351@@ -1491,8 +1498,10 @@ quote(itemization(
352 sender's value (requires bf(--owner) and super-user privileges).
353 it() A bf(g) means the group is different and is being updated to the
354 sender's value (requires bf(--group) and the authority to set the group).
355- it() The bf(u) slot is reserved for reporting update (access) time changes
356- (a feature that is not yet released).
357+ it() A bf(u) means the access (use) time is different and is being updated to
358+ the sender's value (requires bf(--atimes)). An alternate value of bf(U)
359+ means that the access time will be set to the transfer time, which happens
360+ when a symlink or directory is updated.
361 it() The bf(a) means that the ACL information changed.
362 it() The bf(x) slot is reserved for reporting extended attribute changes
363 (a feature that is not yet released).
364--- old/sender.c
365+++ new/sender.c
366@@ -41,6 +41,7 @@ extern int do_progress;
367 extern int inplace;
368 extern int batch_fd;
369 extern int write_batch;
370+extern unsigned int file_struct_len;
371 extern struct stats stats;
372 extern struct file_list *cur_flist, *first_flist;
373
374--- old/testsuite/atimes.test
375+++ new/testsuite/atimes.test
376@@ -0,0 +1,19 @@
377+#! /bin/sh
378+
379+# Test rsync copying atimes
380+
381+. "$suitedir/rsync.fns"
382+
383+set -x
384+
385+mkdir "$fromdir"
386+
387+touch "$fromdir/foo"
388+touch -a -t 200102031717.42 "$fromdir/foo"
389+
390+TLS_ARGS=--atime
391+
392+checkit "$RSYNC -rtUgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
393+
394+# The script would have aborted on error, so getting here means we've won.
395+exit 0
396--- old/testsuite/rsync.fns
397+++ new/testsuite/rsync.fns
398@@ -66,7 +66,7 @@ printmsg() {
399 }
400
401 rsync_ls_lR() {
402- find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls"
403+ find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls" $TLS_ARGS
404 }
405
406 check_perms() {
407@@ -184,6 +184,10 @@ checkit() {
408 # We can just write everything to stdout/stderr, because the
409 # wrapper hides it unless there is a problem.
410
411+ if test x$TLS_ARGS = x--atime; then
412+ ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
413+ fi
414+
415 echo "Running: \"$1\""
416 eval "$1"
417 status=$?
418@@ -191,10 +195,13 @@ checkit() {
419 failed="YES";
420 fi
421
422+ if test x$TLS_ARGS != x--atime; then
423+ ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
424+ fi
425+
426 echo "-------------"
427 echo "check how the directory listings compare with diff:"
428 echo ""
429- ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
430 ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
431 diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
432
433--- old/tls.c
434+++ new/tls.c
435@@ -34,6 +34,7 @@
436 * change. */
437
438 #include "rsync.h"
439+#include "popt.h"
440
441 #define PROGRAM "tls"
442
443@@ -43,6 +44,8 @@ int read_only = 1;
444 int list_only = 0;
445 int preserve_perms = 0;
446
447+static int display_atime = 0;
448+
449 static void failed(char const *what, char const *where)
450 {
451 fprintf(stderr, PROGRAM ": %s %s: %s\n",
452@@ -50,12 +53,29 @@ static void failed(char const *what, cha
453 exit(1);
454 }
455
456+static void storetime(char *dest, time_t t, size_t destsize)
457+{
458+ if (t) {
459+ struct tm *mt = gmtime(&t);
460+
461+ snprintf(dest, destsize,
462+ "%04d-%02d-%02d %02d:%02d:%02d ",
463+ (int)mt->tm_year + 1900,
464+ (int)mt->tm_mon + 1,
465+ (int)mt->tm_mday,
466+ (int)mt->tm_hour,
467+ (int)mt->tm_min,
468+ (int)mt->tm_sec);
469+ } else
470+ strlcpy(dest, " ", destsize);
471+}
472+
473 static void list_file(const char *fname)
474 {
475 STRUCT_STAT buf;
476 char permbuf[PERMSTRING_SIZE];
477- struct tm *mt;
478- char datebuf[50];
479+ char mtimebuf[50];
480+ char atimebuf[50];
481 char linkbuf[4096];
482
483 if (do_lstat(fname, &buf) < 0)
484@@ -88,19 +108,8 @@ static void list_file(const char *fname)
485
486 permstring(permbuf, buf.st_mode);
487
488- if (buf.st_mtime) {
489- mt = gmtime(&buf.st_mtime);
490-
491- snprintf(datebuf, sizeof datebuf,
492- "%04d-%02d-%02d %02d:%02d:%02d",
493- (int)mt->tm_year + 1900,
494- (int)mt->tm_mon + 1,
495- (int)mt->tm_mday,
496- (int)mt->tm_hour,
497- (int)mt->tm_min,
498- (int)mt->tm_sec);
499- } else
500- strlcpy(datebuf, " ", sizeof datebuf);
501+ storetime(mtimebuf, buf.st_mtime, sizeof mtimebuf);
502+ storetime(atimebuf, buf.st_atime, sizeof atimebuf);
503
504 /* TODO: Perhaps escape special characters in fname? */
505
506@@ -111,23 +120,55 @@ static void list_file(const char *fname)
507 (long)minor(buf.st_rdev));
508 } else /* NB: use double for size since it might not fit in a long. */
509 printf("%12.0f", (double)buf.st_size);
510- printf(" %6ld.%-6ld %6ld %s %s%s\n",
511+ printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
512 (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
513- datebuf, fname, linkbuf);
514+ mtimebuf, display_atime && !S_ISDIR(buf.st_mode) ? atimebuf : "",
515+ fname, linkbuf);
516+}
517+
518+static struct poptOption long_options[] = {
519+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
520+ {"atime", 'u', POPT_ARG_NONE, &display_atime, 0, 0, 0},
521+ {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0},
522+ {0,0,0,0,0,0,0}
523+};
524+
525+static void tls_usage(int ret)
526+{
527+ fprintf(stderr, "usage: " PROGRAM " [--atime | -u] FILE ...\n"
528+ "Trivial file listing program for portably checking rsync\n");
529+ exit(ret);
530 }
531
532 int
533 main(int argc, char *argv[])
534 {
535- if (argc < 2) {
536- fprintf(stderr, "usage: " PROGRAM " FILE ...\n"
537- "Trivial file listing program for portably checking rsync\n");
538- return 1;
539- }
540+ poptContext pc;
541+ const char **extra_args;
542+ int opt;
543
544- for (argv++; *argv; argv++) {
545- list_file(*argv);
546+ pc = poptGetContext(PROGRAM, argc, (const char **)argv,
547+ long_options, 0);
548+ while ((opt = poptGetNextOpt(pc)) != -1) {
549+ switch (opt) {
550+ case 'h':
551+ tls_usage(0);
552+ default:
553+ fprintf(stderr,
554+ "%s: %s\n",
555+ poptBadOption(pc, POPT_BADOPTION_NOALIAS),
556+ poptStrerror(opt));
557+ tls_usage(1);
558+ }
559 }
560
561+ extra_args = poptGetArgs(pc);
562+ if (*extra_args == NULL)
563+ tls_usage(1);
564+
565+ for (; *extra_args; extra_args++)
566+ list_file(*extra_args);
567+ poptFreeContext(pc);
568+
569 return 0;
570 }
571--- old/util.c
572+++ new/util.c
573@@ -120,7 +120,7 @@ NORETURN void overflow_exit(const char *
574 exit_cleanup(RERR_MALLOC);
575 }
576
577-int set_modtime(const char *fname, time_t modtime, mode_t mode)
578+int set_times(const char *fname, time_t modtime, time_t atime, mode_t mode)
579 {
580 #if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
581 if (S_ISLNK(mode))
582@@ -128,9 +128,13 @@ int set_modtime(const char *fname, time_
583 #endif
584
585 if (verbose > 2) {
586- rprintf(FINFO, "set modtime of %s to (%ld) %s",
587+ char mtimebuf[200];
588+
589+ strlcpy(mtimebuf, timestring(modtime), sizeof mtimebuf);
590+ rprintf(FINFO,
591+ "set modtime, atime of %s to (%ld) %s, (%ld) %s\n",
592 fname, (long)modtime,
593- asctime(localtime(&modtime)));
594+ mtimebuf, (long)atime, timestring(atime));
595 }
596
597 if (dry_run)
598@@ -139,7 +143,7 @@ int set_modtime(const char *fname, time_
599 {
600 #ifdef HAVE_UTIMES
601 struct timeval t[2];
602- t[0].tv_sec = time(NULL);
603+ t[0].tv_sec = atime;
604 t[0].tv_usec = 0;
605 t[1].tv_sec = modtime;
606 t[1].tv_usec = 0;
607@@ -152,12 +156,12 @@ int set_modtime(const char *fname, time_
608 return utimes(fname, t);
609 #elif defined HAVE_UTIMBUF
610 struct utimbuf tbuf;
611- tbuf.actime = time(NULL);
612+ tbuf.actime = atime;
613 tbuf.modtime = modtime;
614 return utime(fname,&tbuf);
615 #elif defined HAVE_UTIME
616 time_t t[2];
617- t[0] = time(NULL);
618+ t[0] = atime;
619 t[1] = modtime;
620 return utime(fname,t);
621 #else