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