Simplified the patch a bit.
[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
WD
7
8
9a7eef96
WD
9--- old/flist.c
10+++ new/flist.c
b3593e7c 11@@ -46,6 +46,7 @@ extern int preserve_devices;
4a65fe72 12 extern int preserve_specials;
81c32ffd
WD
13 extern int preserve_uid;
14 extern int preserve_gid;
15+extern int preserve_atimes;
16 extern int relative_paths;
a5e0f697 17 extern int implied_dirs;
672ad041
WD
18 extern int ignore_perishable;
19@@ -127,6 +128,7 @@ void show_flist_stats(void)
20 static void list_file_entry(struct file_struct *f)
21 {
22 char permbuf[PERMSTRING_SIZE];
23+ time_t atime = preserve_atimes ? IVAL(ATIME_PTR(f), 0) : 0;
1cb60481 24
672ad041
WD
25 if (!f->basename) {
26 /* this can happen if duplicate names were removed */
27@@ -137,16 +139,18 @@ static void list_file_entry(struct file_
43581f16 28
09fb8f03 29 #ifdef SUPPORT_LINKS
43581f16
WD
30 if (preserve_links && S_ISLNK(f->mode)) {
31- rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
32+ rprintf(FINFO, "%s %11.0f %s %s %s -> %s\n",
4a65fe72 33 permbuf,
f3e2725a 34 (double)f->length, timestring(f->modtime),
672ad041 35+ preserve_atimes ? timestring(atime) : "",
bd68c3c2 36 f_name(f, NULL), f->u.link);
43581f16
WD
37 } else
38 #endif
896c61d0 39 {
43581f16
WD
40- rprintf(FINFO, "%s %11.0f %s %s\n",
41+ rprintf(FINFO, "%s %11.0f %s %s %s\n",
4a65fe72 42 permbuf,
f3e2725a 43 (double)f->length, timestring(f->modtime),
672ad041 44+ preserve_atimes ? timestring(atime) : "",
bd68c3c2 45 f_name(f, NULL));
896c61d0 46 }
43581f16 47 }
672ad041 48@@ -304,6 +308,7 @@ static void send_file_entry(struct file_
43581f16
WD
49 {
50 unsigned short flags;
51 static time_t modtime;
52+ static time_t atime;
53 static mode_t mode;
ba50e96c 54 static int64 dev;
43581f16 55 static dev_t rdev;
672ad041 56@@ -319,7 +324,7 @@ static void send_file_entry(struct file_
43581f16
WD
57
58 if (!file) {
59 write_byte(f, 0);
60- modtime = 0, mode = 0;
61+ modtime = 0, atime = 0, mode = 0;
d9f0e41c 62 dev = 0, rdev = MAKEDEV(0, 0);
43581f16
WD
63 rdev_major = 0;
64 uid = 0, gid = 0;
672ad041 65@@ -365,6 +370,13 @@ static void send_file_entry(struct file_
43581f16
WD
66 flags |= XMIT_SAME_TIME;
67 else
68 modtime = file->modtime;
81c32ffd 69+ if (preserve_atimes && !S_ISDIR(mode)) {
672ad041
WD
70+ time_t file_atime = IVAL(ATIME_PTR(file), 0);
71+ if (file_atime == atime)
43581f16
WD
72+ flags |= XMIT_SAME_ATIME;
73+ else
672ad041 74+ atime = file_atime;
43581f16
WD
75+ }
76
09fb8f03 77 #ifdef SUPPORT_HARD_LINKS
43581f16 78 if (file->link_u.idev) {
672ad041 79@@ -418,6 +430,8 @@ static void send_file_entry(struct file_
43581f16
WD
80 write_int(f, modtime);
81 if (!(flags & XMIT_SAME_MODE))
82 write_int(f, to_wire_mode(mode));
81c32ffd 83+ if (preserve_atimes && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
43581f16
WD
84+ write_int(f, atime);
85 if (preserve_uid && !(flags & XMIT_SAME_UID)) {
86 if (!numeric_ids)
87 add_uid(uid);
672ad041 88@@ -484,6 +498,7 @@ static struct file_struct *receive_file_
09fb8f03 89 unsigned short flags, int f)
43581f16
WD
90 {
91 static time_t modtime;
92+ static time_t atime;
93 static mode_t mode;
ba50e96c 94 static int64 dev;
43581f16 95 static dev_t rdev;
672ad041
WD
96@@ -497,12 +512,13 @@ static struct file_struct *receive_file_
97 char thisname[MAXPATHLEN];
98 unsigned int l1 = 0, l2 = 0;
99 int alloc_len, basename_len, dirname_len, linkname_len, sum_len;
100+ int atime_len;
101 OFF_T file_length;
102 char *basename, *dirname, *bp;
43581f16
WD
103 struct file_struct *file;
104
a7219d20 105 if (!flist) {
43581f16
WD
106- modtime = 0, mode = 0;
107+ modtime = 0, atime = 0, mode = 0;
d9f0e41c 108 dev = 0, rdev = MAKEDEV(0, 0);
43581f16
WD
109 rdev_major = 0;
110 uid = 0, gid = 0;
672ad041 111@@ -558,6 +574,8 @@ static struct file_struct *receive_file_
43581f16
WD
112 modtime = (time_t)read_int(f);
113 if (!(flags & XMIT_SAME_MODE))
114 mode = from_wire_mode(read_int(f));
81c32ffd 115+ if (preserve_atimes && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
43581f16
WD
116+ atime = (time_t)read_int(f);
117
1cb60481
WD
118 if (chmod_modes && !S_ISLNK(mode))
119 mode = tweak_mode(mode, chmod_modes);
672ad041
WD
120@@ -600,19 +618,23 @@ static struct file_struct *receive_file_
121
122 sum_len = always_checksum && S_ISREG(mode) ? MD4_SUM_LENGTH : 0;
123
124+ atime_len = preserve_atimes ? 4 : 0;
125+
126 alloc_len = file_struct_len + dirname_len + basename_len
127- + linkname_len + sum_len;
128+ + atime_len + linkname_len + sum_len;
129 bp = pool_alloc(flist->file_pool, alloc_len, "receive_file_entry");
130
131 file = (struct file_struct *)bp;
132 memset(bp, 0, file_struct_len);
133- bp += file_struct_len;
134+ bp += file_struct_len + atime_len;
135
136 file->modtime = modtime;
137 file->length = file_length;
43581f16 138 file->mode = mode;
8a04c9a7
WD
139 file->uid = uid;
140 file->gid = gid;
1cb60481 141+ if (preserve_atimes)
672ad041 142+ SIVAL(ATIME_PTR(file), 0, atime);
1cb60481
WD
143
144 if (dirname_len) {
145 file->dirname = lastdir = bp;
672ad041
WD
146@@ -731,6 +753,7 @@ struct file_struct *make_file(char *fnam
147 char thisname[MAXPATHLEN];
148 char linkname[MAXPATHLEN];
149 int alloc_len, basename_len, dirname_len, linkname_len, sum_len;
150+ int atime_len;
151 char *basename, *dirname, *bp;
152
153 if (!flist || !flist->count) /* Ignore lastdir when invalid. */
154@@ -854,8 +877,10 @@ struct file_struct *make_file(char *fnam
155 sum_len = always_checksum && am_sender && S_ISREG(st.st_mode)
156 ? MD4_SUM_LENGTH : 0;
157
158+ atime_len = preserve_atimes ? 4 : 0;
159+
160 alloc_len = file_struct_len + dirname_len + basename_len
161- + linkname_len + sum_len;
162+ + atime_len + linkname_len + sum_len;
163 if (flist)
164 bp = pool_alloc(flist->file_pool, alloc_len, "make_file");
165 else {
166@@ -865,7 +890,7 @@ struct file_struct *make_file(char *fnam
167
168 file = (struct file_struct *)bp;
1cb60481 169 memset(bp, 0, file_struct_len);
672ad041
WD
170- bp += file_struct_len;
171+ bp += file_struct_len + atime_len;
43581f16 172
672ad041 173 file->flags = flags;
43581f16 174 file->modtime = st.st_mtime;
672ad041 175@@ -873,6 +898,8 @@ struct file_struct *make_file(char *fnam
1cb60481 176 file->mode = st.st_mode;
8a04c9a7
WD
177 file->uid = st.st_uid;
178 file->gid = st.st_gid;
1cb60481 179+ if (preserve_atimes)
672ad041 180+ SIVAL(ATIME_PTR(file), 0, st.st_atime);
1cb60481
WD
181
182 #ifdef SUPPORT_HARD_LINKS
183 if (flist && flist->hlink_pool) {
672ad041 184@@ -1595,8 +1622,9 @@ static void clean_flist(struct file_list
1cb60481 185 }
4a65fe72
WD
186 /* Make sure we don't lose track of a user-specified
187 * top directory. */
1cb60481
WD
188- flist->files[keep]->flags |= flist->files[drop]->flags
189- & (FLAG_TOP_DIR|FLAG_DEL_HERE);
672ad041
WD
190+ flist->files[keep]->flags
191+ |= flist->files[drop]->flags
1cb60481
WD
192+ & (FLAG_TOP_DIR|FLAG_DEL_HERE);
193
4a65fe72 194 clear_file(flist->files[drop], flist);
1cb60481 195
9a7eef96
WD
196--- old/generator.c
197+++ new/generator.c
195ca26e 198@@ -43,6 +43,7 @@ extern int preserve_perms;
55602791 199 extern int preserve_uid;
81c32ffd
WD
200 extern int preserve_gid;
201 extern int preserve_times;
81c32ffd 202+extern int preserve_atimes;
55602791 203 extern int omit_dir_times;
4a65fe72 204 extern int delete_mode;
81c32ffd 205 extern int delete_before;
3758a5a5 206@@ -90,6 +91,7 @@ extern dev_t filesystem_dev;
1cb60481
WD
207 extern char *backup_dir;
208 extern char *backup_suffix;
209 extern int backup_suffix_len;
210+extern unsigned int file_struct_len;
211 extern struct file_list *the_file_list;
212 extern struct filter_list_struct server_filter_list;
213
672ad041 214@@ -409,6 +411,9 @@ void itemize(struct file_struct *file, i
9a70b743
WD
215 && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
216 || (keep_time && cmp_time(file->modtime, st->st_mtime) != 0))
f20eb450 217 iflags |= ITEM_REPORT_TIME;
55602791 218+ if (preserve_atimes && !S_ISDIR(file->mode) && !S_ISLNK(file->mode)
672ad041 219+ && cmp_time(IVAL(ATIME_PTR(file), 0), st->st_atime) != 0)
55602791 220+ iflags |= ITEM_REPORT_ATIME;
7a56a8f1 221 if ((file->mode & CHMOD_BITS) != (st->st_mode & CHMOD_BITS))
f20eb450 222 iflags |= ITEM_REPORT_PERMS;
7a56a8f1 223 if (preserve_uid && am_root && file->uid != st->st_uid)
672ad041 224@@ -720,6 +725,8 @@ static int try_dests_reg(struct file_str
9a70b743
WD
225 if (hard_link_one(file, ndx, fname, 0, stp,
226 cmpbuf, 1, i, code) < 0)
8a04c9a7
WD
227 goto try_a_copy;
228+ if (preserve_atimes)
4a65fe72 229+ set_file_attrs(fname, file, stp, 0);
a6f0fb54
WD
230 if (preserve_hard_links && file->link_u.links) {
231 if (dry_run)
232 file->link_u.links->link_dest_used = j + 1;
9a7eef96
WD
233--- old/log.c
234+++ new/log.c
b3593e7c 235@@ -37,6 +37,7 @@ extern int msg_fd_out;
577db5e2 236 extern int allow_8bit_chars;
81c32ffd
WD
237 extern int protocol_version;
238 extern int preserve_times;
239+extern int preserve_atimes;
a859733e
WD
240 extern int stdout_format_has_i;
241 extern int stdout_format_has_o_or_i;
21d7083a
WD
242 extern int logfile_format_has_i;
243@@ -606,7 +607,8 @@ static void log_formatted(enum logcode c
ccc3a12c
WD
244 n[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
245 n[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
246 n[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
247- n[8] = '.';
248+ n[8] = !(iflags & ITEM_REPORT_ATIME) ? '.'
55602791 249+ : S_ISLNK(file->mode) ? 'U' : 'u';
ccc3a12c 250 n[9] = '\0';
81c32ffd
WD
251
252 if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) {
9a7eef96
WD
253--- old/options.c
254+++ new/options.c
b3593e7c 255@@ -55,6 +55,7 @@ int preserve_uid = 0;
43581f16
WD
256 int preserve_gid = 0;
257 int preserve_times = 0;
9a21ad72 258 int omit_dir_times = 0;
81c32ffd 259+int preserve_atimes = 0;
43581f16
WD
260 int update_only = 0;
261 int cvs_exclude = 0;
262 int dry_run = 0;
03019e41 263@@ -311,8 +312,9 @@ void usage(enum logcode F)
4a65fe72
WD
264 rprintf(F," --devices preserve device files (super-user only)\n");
265 rprintf(F," --specials preserve special files\n");
266 rprintf(F," -D same as --devices --specials\n");
81c32ffd
WD
267- rprintf(F," -t, --times preserve times\n");
268- rprintf(F," -O, --omit-dir-times omit directories when preserving times\n");
269+ rprintf(F," -t, --times preserve modify times\n");
270+ rprintf(F," -O, --omit-dir-times omit directories when preserving modify times\n");
55602791 271+ rprintf(F," -U, --atimes preserve access (use) times\n");
4a65fe72 272 rprintf(F," --super receiver attempts super-user activities\n");
43581f16
WD
273 rprintf(F," -S, --sparse handle sparse files efficiently\n");
274 rprintf(F," -n, --dry-run show what would have been transferred\n");
03019e41 275@@ -428,6 +430,9 @@ static struct poptOption long_options[]
489b0a72
WD
276 {"times", 't', POPT_ARG_VAL, &preserve_times, 1, 0, 0 },
277 {"no-times", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
278 {"no-t", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
55602791 279+ {"atimes", 'U', POPT_ARG_VAL, &preserve_atimes, 1, 0, 0 },
489b0a72 280+ {"no-atimes", 0, POPT_ARG_VAL, &preserve_atimes, 0, 0, 0 },
58070e2e 281+ {"no-k", 0, POPT_ARG_VAL, &preserve_atimes, 0, 0, 0 },
52f25864 282 {"omit-dir-times", 'O', POPT_ARG_VAL, &omit_dir_times, 2, 0, 0 },
489b0a72 283 {"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
4a65fe72 284 {"super", 0, POPT_ARG_VAL, &am_root, 2, 0, 0 },
03019e41 285@@ -1538,6 +1543,8 @@ void server_options(char **args,int *arg
43581f16
WD
286 argstr[x++] = 'D';
287 if (preserve_times)
288 argstr[x++] = 't';
81c32ffd 289+ if (preserve_atimes)
55602791 290+ argstr[x++] = 'U';
43581f16 291 if (preserve_perms)
4a65fe72
WD
292 argstr[x++] = 'p';
293 else if (preserve_executability && am_sender)
9a7eef96
WD
294--- old/rsync.c
295+++ new/rsync.c
195ca26e
WD
296@@ -34,6 +34,7 @@ extern int verbose;
297 extern int dry_run;
d9a67109 298 extern int preserve_perms;
4a65fe72 299 extern int preserve_executability;
d9a67109 300+extern int preserve_atimes;
43581f16 301 extern int preserve_times;
9a21ad72 302 extern int omit_dir_times;
43581f16 303 extern int am_root;
672ad041
WD
304@@ -49,6 +50,7 @@ extern int keep_dirlinks;
305 extern int make_backups;
306 extern mode_t orig_umask;
307 extern struct stats stats;
308+extern unsigned int file_struct_len;
309 extern struct chmod_mode_struct *daemon_chmod_modes;
310
311 #if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
312@@ -129,6 +131,7 @@ int set_file_attrs(char *fname, struct f
9a21ad72
WD
313 int updated = 0;
314 STRUCT_STAT st2;
315 int change_uid, change_gid;
316+ time_t atime, mtime;
1ed0b5c9 317 mode_t new_mode = file->mode;
9a21ad72
WD
318
319 if (!st) {
672ad041 320@@ -148,18 +151,36 @@ int set_file_attrs(char *fname, struct f
7a56a8f1 321 }
8a04c9a7 322 }
9a21ad72 323
8a04c9a7
WD
324+ /* This code must be the first update in the function due to
325+ * how it uses the "updated" variable. */
9e355bf1 326 if (!preserve_times || (S_ISDIR(st->st_mode) && omit_dir_times))
4a65fe72 327 flags |= ATTRS_SKIP_MTIME;
81c32ffd 328+ if (!preserve_atimes || S_ISDIR(st->st_mode))
4a65fe72
WD
329+ flags |= ATTRS_SKIP_ATIME;
330 if (!(flags & ATTRS_SKIP_MTIME)
577db5e2 331 && cmp_time(st->st_mtime, file->modtime) != 0) {
9e355bf1 332- int ret = set_modtime(fname, file->modtime, st->st_mode);
9a21ad72 333+ mtime = file->modtime;
9e355bf1 334+ updated = 1;
9a21ad72
WD
335+ } else
336+ mtime = st->st_mtime;
672ad041
WD
337+ if (!(flags & ATTRS_SKIP_ATIME)) {
338+ time_t file_atime = IVAL(ATIME_PTR(file), 0);
339+ if (cmp_time(st->st_atime, file_atime) != 0) {
340+ atime = file_atime;
341+ updated = 1;
342+ } else
343+ atime = st->st_atime;
81c32ffd
WD
344+ } else
345+ atime = st->st_atime;
9e355bf1
WD
346+ if (updated) {
347+ int ret = set_times(fname, mtime, atime, st->st_mode);
348 if (ret < 0) {
349 rsyserr(FERROR, errno, "failed to set times on %s",
350 full_fname(fname));
351 return 0;
352 }
353- if (ret == 0) /* ret == 1 if symlink could not be set */
354- updated = 1;
355+ if (ret > 0) /* ret == 1 if symlink could not be set */
356+ updated = 0;
43581f16
WD
357 }
358
8a04c9a7 359 change_uid = am_root && preserve_uid && st->st_uid != file->uid;
9a7eef96
WD
360--- old/rsync.h
361+++ new/rsync.h
43581f16
WD
362@@ -54,6 +54,7 @@
363 #define XMIT_HAS_IDEV_DATA (1<<9)
364 #define XMIT_SAME_DEV (1<<10)
365 #define XMIT_RDEV_MINOR_IS_SMALL (1<<11)
366+#define XMIT_SAME_ATIME (1<<12)
367
368 /* These flags are used in the live flist data. */
369
195ca26e 370@@ -120,6 +121,7 @@
8a529471 371
4a65fe72
WD
372 #define ATTRS_REPORT (1<<0)
373 #define ATTRS_SKIP_MTIME (1<<1)
374+#define ATTRS_SKIP_ATIME (1<<2)
8a529471
WD
375
376 #define FULL_FLUSH 1
377 #define NORMAL_FLUSH 0
672ad041
WD
378@@ -534,6 +536,8 @@ struct file_struct {
379 uchar flags; /* this item MUST remain last */
1cb60481
WD
380 };
381
672ad041 382+#define ATIME_PTR(f) (((uchar*)(f))+file_struct_len)
1cb60481
WD
383+
384 /*
385 * Start the flist array at FLIST_START entries and grow it
386 * by doubling until FLIST_LINEAR then grow by FLIST_LINEAR
9a7eef96
WD
387--- old/rsync.yo
388+++ new/rsync.yo
03019e41 389@@ -328,8 +328,9 @@ to the detailed description below for a
4a65fe72
WD
390 --devices preserve device files (super-user only)
391 --specials preserve special files
392 -D same as --devices --specials
81c32ffd 393- -t, --times preserve times
610969d1 394- -O, --omit-dir-times omit directories when preserving times
81c32ffd 395+ -t, --times preserve modify times
610969d1 396+ -O, --omit-dir-times omit directories when preserving mod-times
55602791 397+ -U, --atimes preserve access (use) times
4a65fe72 398 --super receiver attempts super-user activities
43581f16
WD
399 -S, --sparse handle sparse files efficiently
400 -n, --dry-run show what would have been transferred
03019e41 401@@ -869,6 +870,12 @@ it is preserving modification times (see
a7219d20 402 the directories on the receiving side, it is a good idea to use bf(-O).
333b8af4 403 This option is inferred if you use bf(--backup) without bf(--backup-dir).
7b675ff5 404
55602791
WD
405+dit(bf(-U, --atimes)) This tells rsync to set the access (use) times of the
406+destination files to the same value as the source files. Note that the
81c32ffd
WD
407+reading of the source file may update the atime of the source files, so
408+repeated rsync runs with --atimes may be needed if you want to force the
409+access-time values to be 100% identical on the two systems.
7b675ff5 410+
4a65fe72
WD
411 dit(bf(--super)) This tells the receiving side to attempt super-user
412 activities even if the receiving rsync wasn't run by the super-user. These
413 activities include: preserving users via the bf(--owner) option, preserving
672ad041 414@@ -1396,7 +1403,7 @@ with older versions of rsync, but that a
4a65fe72
WD
415 verbose messages).
416
ccc3a12c
WD
417 The "%i" escape has a cryptic output that is 9 letters long. The general
418-format is like the string bf(YXcstpogz), where bf(Y) is replaced by the
419+format is like the string bf(YXcstpogu), where bf(Y) is replaced by the
420 type of update being done, bf(X) is replaced by the file-type, and the
4a65fe72
WD
421 other letters represent attributes that may be output if they are being
422 modified.
672ad041 423@@ -1436,7 +1443,7 @@ quote(itemization(
81c32ffd
WD
424 by the file transfer.
425 it() A bf(t) means the modification time is different and is being updated
426 to the sender's value (requires bf(--times)). An alternate value of bf(T)
427- means that the time will be set to the transfer time, which happens
428+ means that the modify time will be set to the transfer time, which happens
429 anytime a symlink is transferred, or when a file or device is transferred
430 without bf(--times).
ccc3a12c 431 it() A bf(p) means the permissions are different and are being updated to
672ad041 432@@ -1445,7 +1452,10 @@ quote(itemization(
ccc3a12c
WD
433 sender's value (requires bf(--owner) and super-user privileges).
434 it() A bf(g) means the group is different and is being updated to the
435 sender's value (requires bf(--group) and the authority to set the group).
436- it() The bf(z) slot is reserved for future use.
55602791
WD
437+ it() A bf(u) means the access (use) time is different and is being updated to
438+ the sender's value (requires bf(--atimes)). An alternate value of bf(U)
439+ means that the access time will be set to the transfer time, which happens
ccc3a12c
WD
440+ when a symlink or directory is updated.
441 ))
442
443 One other output is possible: when deleting files, the "%i" will output
9a7eef96
WD
444--- old/sender.c
445+++ new/sender.c
b3593e7c 446@@ -41,6 +41,7 @@ extern int do_progress;
1cb60481
WD
447 extern int inplace;
448 extern int batch_fd;
449 extern int write_batch;
450+extern unsigned int file_struct_len;
451 extern struct stats stats;
452 extern struct file_list *the_file_list;
a859733e 453 extern char *stdout_format;
9a7eef96
WD
454--- old/testsuite/atimes.test
455+++ new/testsuite/atimes.test
13bed3dd
WD
456@@ -0,0 +1,19 @@
457+#! /bin/sh
458+
459+# Test rsync copying atimes
460+
461+. "$suitedir/rsync.fns"
462+
463+set -x
464+
465+mkdir "$fromdir"
466+
467+touch "$fromdir/foo"
468+touch -a -t 200102031717.42 "$fromdir/foo"
469+
470+TLS_ARGS=--atime
471+
55602791 472+checkit "$RSYNC -rtUgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
13bed3dd
WD
473+
474+# The script would have aborted on error, so getting here means we've won.
475+exit 0
9a7eef96
WD
476--- old/testsuite/rsync.fns
477+++ new/testsuite/rsync.fns
7a56a8f1
WD
478@@ -66,7 +66,7 @@ printmsg() {
479 }
13bed3dd
WD
480
481 rsync_ls_lR() {
b78a6aba
WD
482- find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls"
483+ find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls" $TLS_ARGS
13bed3dd
WD
484 }
485
7a56a8f1
WD
486 check_perms() {
487@@ -184,6 +184,10 @@ checkit() {
13bed3dd
WD
488 # We can just write everything to stdout/stderr, because the
489 # wrapper hides it unless there is a problem.
490
81c32ffd
WD
491+ if test x$TLS_ARGS = x--atime; then
492+ ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
493+ fi
13bed3dd
WD
494+
495 echo "Running: \"$1\""
496 eval "$1"
497 status=$?
7a56a8f1 498@@ -191,10 +195,13 @@ checkit() {
81c32ffd
WD
499 failed="YES";
500 fi
501
502+ if test x$TLS_ARGS != x--atime; then
503+ ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
504+ fi
505+
13bed3dd 506 echo "-------------"
b78a6aba
WD
507 echo "check how the directory listings compare with diff:"
508 echo ""
13bed3dd 509- ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
b78a6aba
WD
510 ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
511 diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
4da25dad 512
9a7eef96
WD
513--- old/tls.c
514+++ new/tls.c
b3593e7c
WD
515@@ -34,6 +34,7 @@
516 * change. */
43581f16
WD
517
518 #include "rsync.h"
519+#include "popt.h"
520
521 #define PROGRAM "tls"
522
b3593e7c 523@@ -43,6 +44,8 @@ int read_only = 1;
43581f16
WD
524 int list_only = 0;
525 int preserve_perms = 0;
526
527+static int display_atime = 0;
b3593e7c 528+
fe6407b5
WD
529 static void failed(char const *what, char const *where)
530 {
b3593e7c
WD
531 fprintf(stderr, PROGRAM ": %s %s: %s\n",
532@@ -50,12 +53,29 @@ static void failed(char const *what, cha
fe6407b5 533 exit(1);
43581f16
WD
534 }
535
3f053c45 536+static void storetime(char *dest, time_t t, size_t destsize)
43581f16
WD
537+{
538+ if (t) {
539+ struct tm *mt = gmtime(&t);
b3593e7c 540+
3f053c45
WD
541+ snprintf(dest, destsize,
542+ "%04d-%02d-%02d %02d:%02d:%02d ",
9d95bd65
WD
543+ (int)mt->tm_year + 1900,
544+ (int)mt->tm_mon + 1,
545+ (int)mt->tm_mday,
546+ (int)mt->tm_hour,
547+ (int)mt->tm_min,
548+ (int)mt->tm_sec);
3f053c45
WD
549+ } else
550+ strlcpy(dest, " ", destsize);
b3593e7c
WD
551+}
552+
fe6407b5 553 static void list_file(const char *fname)
43581f16
WD
554 {
555 STRUCT_STAT buf;
556 char permbuf[PERMSTRING_SIZE];
557- struct tm *mt;
558- char datebuf[50];
559+ char mtimebuf[50];
560+ char atimebuf[50];
561 char linkbuf[4096];
562
ba50e96c 563 if (do_lstat(fname, &buf) < 0)
b3593e7c 564@@ -88,19 +108,8 @@ static void list_file(const char *fname)
43581f16
WD
565
566 permstring(permbuf, buf.st_mode);
567
568- if (buf.st_mtime) {
569- mt = gmtime(&buf.st_mtime);
570-
3f053c45
WD
571- snprintf(datebuf, sizeof datebuf,
572- "%04d-%02d-%02d %02d:%02d:%02d",
9d95bd65
WD
573- (int)mt->tm_year + 1900,
574- (int)mt->tm_mon + 1,
575- (int)mt->tm_mday,
576- (int)mt->tm_hour,
577- (int)mt->tm_min,
578- (int)mt->tm_sec);
3f053c45
WD
579- } else
580- strlcpy(datebuf, " ", sizeof datebuf);
581+ storetime(mtimebuf, buf.st_mtime, sizeof mtimebuf);
582+ storetime(atimebuf, buf.st_atime, sizeof atimebuf);
43581f16
WD
583
584 /* TODO: Perhaps escape special characters in fname? */
585
b3593e7c 586@@ -111,23 +120,55 @@ static void list_file(const char *fname)
43581f16
WD
587 (long)minor(buf.st_rdev));
588 } else /* NB: use double for size since it might not fit in a long. */
589 printf("%12.0f", (double)buf.st_size);
590- printf(" %6ld.%-6ld %6ld %s %s%s\n",
591+ printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
592 (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
593- datebuf, fname, linkbuf);
c0be1af2 594+ mtimebuf, display_atime && !S_ISDIR(buf.st_mode) ? atimebuf : "",
43581f16 595+ fname, linkbuf);
b3593e7c
WD
596+}
597+
43581f16
WD
598+static struct poptOption long_options[] = {
599+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
600+ {"atime", 'u', POPT_ARG_NONE, &display_atime, 0, 0, 0},
601+ {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0},
602+ {0,0,0,0,0,0,0}
603+};
604+
605+static void tls_usage(int ret)
606+{
607+ fprintf(stderr, "usage: " PROGRAM " [--atime | -u] DIR ...\n"
608+ "Trivial file listing program for portably checking rsync\n");
609+ exit(ret);
b3593e7c 610 }
43581f16
WD
611
612 int
613 main(int argc, char *argv[])
614 {
615- if (argc < 2) {
fe6407b5
WD
616- fprintf(stderr, "usage: " PROGRAM " DIR ...\n"
617- "Trivial file listing program for portably checking rsync\n");
43581f16 618- return 1;
03019e41 619- }
43581f16
WD
620+ poptContext pc;
621+ const char **extra_args;
622+ int opt;
03019e41
WD
623
624- for (argv++; *argv; argv++) {
625- list_file(*argv);
43581f16
WD
626+ pc = poptGetContext(PROGRAM, argc, (const char **)argv,
627+ long_options, 0);
628+ while ((opt = poptGetNextOpt(pc)) != -1) {
629+ switch (opt) {
630+ case 'h':
631+ tls_usage(0);
632+ default:
633+ fprintf(stderr,
634+ "%s: %s\n",
635+ poptBadOption(pc, POPT_BADOPTION_NOALIAS),
636+ poptStrerror(opt));
637+ tls_usage(1);
638+ }
639 }
640
43581f16
WD
641+ extra_args = poptGetArgs(pc);
642+ if (*extra_args == NULL)
643+ tls_usage(1);
644+
645+ for (; *extra_args; extra_args++)
646+ list_file(*extra_args);
647+ poptFreeContext(pc);
03019e41 648+
43581f16
WD
649 return 0;
650 }
9a7eef96
WD
651--- old/util.c
652+++ new/util.c
3758a5a5 653@@ -121,7 +121,7 @@ NORETURN void overflow_exit(char *str)
577db5e2
WD
654 exit_cleanup(RERR_MALLOC);
655 }
43581f16 656
9e355bf1
WD
657-int set_modtime(char *fname, time_t modtime, mode_t mode)
658+int set_times(char *fname, time_t modtime, time_t atime, mode_t mode)
43581f16 659 {
9e355bf1
WD
660 #if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
661 if (S_ISLNK(mode))
a859733e 662@@ -129,9 +129,13 @@ int set_modtime(char *fname, time_t modt
9e355bf1
WD
663 #endif
664
43581f16
WD
665 if (verbose > 2) {
666- rprintf(FINFO, "set modtime of %s to (%ld) %s",
667+ char mtimebuf[200];
43581f16 668+
125d7fca 669+ strlcpy(mtimebuf, timestring(modtime), sizeof mtimebuf);
43581f16
WD
670+ rprintf(FINFO,
671+ "set modtime, atime of %s to (%ld) %s, (%ld) %s\n",
93ca4d27 672 fname, (long)modtime,
43581f16 673- asctime(localtime(&modtime)));
9e355bf1 674+ mtimebuf, (long)atime, timestring(atime));
43581f16
WD
675 }
676
ba50e96c 677 if (dry_run)
a859733e 678@@ -140,7 +144,7 @@ int set_modtime(char *fname, time_t modt
43581f16 679 {
9e355bf1
WD
680 #ifdef HAVE_UTIMES
681 struct timeval t[2];
682- t[0].tv_sec = time(NULL);
683+ t[0].tv_sec = atime;
684 t[0].tv_usec = 0;
685 t[1].tv_sec = modtime;
686 t[1].tv_usec = 0;
672ad041 687@@ -153,12 +157,12 @@ int set_modtime(char *fname, time_t modt
9e355bf1
WD
688 return utimes(fname, t);
689 #elif defined HAVE_UTIMBUF
43581f16
WD
690 struct utimbuf tbuf;
691- tbuf.actime = time(NULL);
692+ tbuf.actime = atime;
693 tbuf.modtime = modtime;
694 return utime(fname,&tbuf);
09fb8f03 695 #elif defined HAVE_UTIME
43581f16
WD
696 time_t t[2];
697- t[0] = time(NULL);
698+ t[0] = atime;
699 t[1] = modtime;
700 return utime(fname,t);
701 #else