Updated.
[rsync/rsync-patches.git] / atimes.diff
CommitLineData
8a529471
WD
1After applying this patch and running configure, you MUST run this
2command before "make":
3
4 make proto
5
6
9be39c35 7--- orig/batch.c 2004-07-15 16:51:50
13bed3dd 8+++ batch.c 2004-07-03 20:15:41
9be39c35 9@@ -63,6 +63,8 @@ void show_flist(int index, struct file_s
43581f16
WD
10 rprintf(FINFO, "flist->flags=%#x\n", fptr[i]->flags);
11 rprintf(FINFO, "flist->modtime=%#lx\n",
12 (long unsigned) fptr[i]->modtime);
13+ rprintf(FINFO, "flist->atime=%#lx\n",
14+ (long unsigned) fptr[i]->atime);
15 rprintf(FINFO, "flist->length=%.0f\n",
16 (double) fptr[i]->length);
17 rprintf(FINFO, "flist->mode=%#o\n", (int) fptr[i]->mode);
9be39c35 18--- orig/flist.c 2004-07-15 02:21:10
13bed3dd 19+++ flist.c 2004-07-03 20:15:41
7628f156 20@@ -58,6 +58,7 @@ extern int relative_paths;
43581f16
WD
21 extern int implied_dirs;
22 extern int copy_links;
23 extern int copy_unsafe_links;
24+extern int copy_atimes;
25 extern int protocol_version;
26 extern int sanitize_paths;
7628f156 27 extern int delete_excluded;
9be39c35 28@@ -141,17 +142,17 @@ static void list_file_entry(struct file_
43581f16
WD
29
30 #if SUPPORT_LINKS
31 if (preserve_links && S_ISLNK(f->mode)) {
32- rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
33+ rprintf(FINFO, "%s %11.0f %s %s %s -> %s\n",
34 perms,
f3e2725a 35 (double)f->length, timestring(f->modtime),
43581f16
WD
36- f_name(f), f->u.link);
37+ timestring(f->atime), f_name(f), f->u.link);
38 } else
39 #endif
896c61d0 40 {
43581f16
WD
41- rprintf(FINFO, "%s %11.0f %s %s\n",
42+ rprintf(FINFO, "%s %11.0f %s %s %s\n",
43 perms,
f3e2725a 44 (double)f->length, timestring(f->modtime),
43581f16
WD
45- f_name(f));
46+ timestring(f->atime), f_name(f));
896c61d0 47 }
43581f16
WD
48 }
49
9be39c35 50@@ -332,6 +333,7 @@ void send_file_entry(struct file_struct
43581f16
WD
51 {
52 unsigned short flags;
53 static time_t modtime;
54+ static time_t atime;
55 static mode_t mode;
56 static uint64 dev;
57 static dev_t rdev;
9be39c35 58@@ -347,7 +349,7 @@ void send_file_entry(struct file_struct
43581f16
WD
59
60 if (!file) {
61 write_byte(f, 0);
62- modtime = 0, mode = 0;
63+ modtime = 0, atime = 0, mode = 0;
64 dev = 0, rdev = makedev(0, 0);
65 rdev_major = 0;
66 uid = 0, gid = 0;
9be39c35 67@@ -396,6 +398,12 @@ void send_file_entry(struct file_struct
43581f16
WD
68 flags |= XMIT_SAME_TIME;
69 else
70 modtime = file->modtime;
71+ if (copy_atimes && !S_ISDIR(mode)) {
72+ if (file->atime == atime)
73+ flags |= XMIT_SAME_ATIME;
74+ else
75+ atime = file->atime;
76+ }
77
78 #if SUPPORT_HARD_LINKS
79 if (file->link_u.idev) {
9be39c35 80@@ -451,6 +459,8 @@ void send_file_entry(struct file_struct
43581f16
WD
81 write_int(f, modtime);
82 if (!(flags & XMIT_SAME_MODE))
83 write_int(f, to_wire_mode(mode));
84+ if (copy_atimes && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
85+ write_int(f, atime);
86 if (preserve_uid && !(flags & XMIT_SAME_UID)) {
87 if (!numeric_ids)
88 add_uid(uid);
9be39c35 89@@ -524,6 +534,7 @@ void receive_file_entry(struct file_stru
7628f156 90 struct file_list *flist, int f)
43581f16
WD
91 {
92 static time_t modtime;
93+ static time_t atime;
94 static mode_t mode;
95 static uint64 dev;
96 static dev_t rdev;
9be39c35 97@@ -540,7 +551,7 @@ void receive_file_entry(struct file_stru
43581f16
WD
98 struct file_struct *file;
99
100 if (!fptr) {
101- modtime = 0, mode = 0;
102+ modtime = 0, atime = 0, mode = 0;
103 dev = 0, rdev = makedev(0, 0);
104 rdev_major = 0;
105 uid = 0, gid = 0;
9be39c35 106@@ -595,6 +606,8 @@ void receive_file_entry(struct file_stru
43581f16
WD
107 modtime = (time_t)read_int(f);
108 if (!(flags & XMIT_SAME_MODE))
109 mode = from_wire_mode(read_int(f));
110+ if (copy_atimes && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
111+ atime = (time_t)read_int(f);
112
113 if (preserve_uid && !(flags & XMIT_SAME_UID))
114 uid = (uid_t)read_int(f);
9be39c35 115@@ -645,6 +658,7 @@ void receive_file_entry(struct file_stru
43581f16
WD
116
117 file->flags = flags & XMIT_TOP_DIR ? FLAG_TOP_DIR : 0;
118 file->modtime = modtime;
119+ file->atime = atime;
120 file->length = file_length;
121 file->mode = mode;
122 file->uid = uid;
9be39c35 123@@ -864,6 +878,7 @@ skip_excludes:
43581f16
WD
124
125 file->flags = flags;
126 file->modtime = st.st_mtime;
127+ file->atime = st.st_atime;
128 file->length = st.st_size;
129 file->mode = st.st_mode;
130 file->uid = st.st_uid;
f6c3b300 131--- orig/generator.c 2004-07-16 19:35:29
13bed3dd 132+++ generator.c 2004-07-03 20:15:41
f6c3b300 133@@ -99,7 +99,7 @@ static int skip_file(char *fname, struct
8cec1ead 134 if (ignore_times)
43581f16 135 return 0;
43581f16 136
8cec1ead
WD
137- return cmp_modtime(st->st_mtime, file->modtime) == 0;
138+ return cmp_time(st->st_mtime, file->modtime) == 0;
43581f16
WD
139 }
140
141
f6c3b300 142@@ -471,7 +471,7 @@ static void recv_generator(char *fname,
43581f16
WD
143 }
144
8cec1ead
WD
145 if (update_only && fnamecmp == fname
146- && cmp_modtime(st.st_mtime, file->modtime) > 0) {
147+ && cmp_time(st.st_mtime, file->modtime) > 0) {
43581f16
WD
148 if (verbose > 1)
149 rprintf(FINFO,"%s is newer\n",fname);
150 return;
f6c3b300 151--- orig/options.c 2004-07-16 20:07:22
13bed3dd 152+++ options.c 2004-07-03 20:15:41
125d7fca 153@@ -48,6 +48,7 @@ int preserve_devices = 0;
43581f16
WD
154 int preserve_uid = 0;
155 int preserve_gid = 0;
156 int preserve_times = 0;
157+int copy_atimes = 0;
158 int update_only = 0;
159 int cvs_exclude = 0;
160 int dry_run = 0;
f6c3b300 161@@ -251,6 +252,7 @@ void usage(enum logcode F)
43581f16
WD
162 rprintf(F," -g, --group preserve group\n");
163 rprintf(F," -D, --devices preserve devices (root only)\n");
164 rprintf(F," -t, --times preserve times\n");
165+ rprintf(F," -A, --copy-atimes copy access times\n");
166 rprintf(F," -S, --sparse handle sparse files efficiently\n");
167 rprintf(F," -n, --dry-run show what would have been transferred\n");
168 rprintf(F," -W, --whole-file copy whole files, no incremental checks\n");
f6c3b300 169@@ -359,6 +361,7 @@ static struct poptOption long_options[]
43581f16
WD
170 {"group", 'g', POPT_ARG_NONE, &preserve_gid, 0, 0, 0 },
171 {"devices", 'D', POPT_ARG_NONE, &preserve_devices, 0, 0, 0 },
172 {"times", 't', POPT_ARG_NONE, &preserve_times, 0, 0, 0 },
173+ {"copy-atimes", 'A', POPT_ARG_NONE, &copy_atimes, 0, 0, 0 },
174 {"checksum", 'c', POPT_ARG_NONE, &always_checksum, 0, 0, 0 },
175 {"verbose", 'v', POPT_ARG_NONE, 0, 'v', 0, 0 },
176 {"quiet", 'q', POPT_ARG_NONE, 0, 'q', 0, 0 },
f6c3b300 177@@ -875,6 +878,8 @@ void server_options(char **args,int *arg
43581f16
WD
178 argstr[x++] = 'D';
179 if (preserve_times)
180 argstr[x++] = 't';
181+ if (copy_atimes)
182+ argstr[x++] = 'A';
183 if (preserve_perms)
184 argstr[x++] = 'p';
185 if (recurse)
f6c3b300 186--- orig/rsync.c 2004-07-16 20:07:23
13bed3dd 187+++ rsync.c 2004-07-03 20:15:41
43581f16
WD
188@@ -25,6 +25,7 @@
189 extern int verbose;
190 extern int dry_run;
191 extern int preserve_times;
192+extern int copy_atimes;
193 extern int am_root;
43581f16 194 extern int am_sender;
8a529471 195 extern int am_generator;
f6c3b300 196@@ -144,17 +145,31 @@ int set_perms(char *fname,struct file_st
7b675ff5
WD
197 if (!preserve_times || S_ISLNK(st->st_mode)
198 || (make_backups && !backup_dir && S_ISDIR(st->st_mode)))
8a529471
WD
199 flags |= PERMS_SKIP_MTIME;
200- if (!(flags & PERMS_SKIP_MTIME)
201- && cmp_modtime(st->st_mtime, file->modtime) != 0) {
202+ if (!copy_atimes || S_ISLNK(st->st_mode) || S_ISDIR(st->st_mode))
203+ flags |= PERMS_SKIP_ATIME;
204+ if (!(flags & (PERMS_SKIP_MTIME|PERMS_SKIP_ATIME))) {
43581f16
WD
205+ time_t atime, mtime;
206+
8a529471 207+ if (!(flags & PERMS_SKIP_ATIME)
43581f16
WD
208+ && cmp_time(st->st_atime, file->atime) != 0) {
209+ atime = file->atime;
210+ updated = 1;
211+ } else
212+ atime = st->st_atime;
8a529471
WD
213+ if (!(flags & PERMS_SKIP_MTIME)
214+ && cmp_time(st->st_mtime, file->modtime) != 0) {
43581f16
WD
215+ mtime = file->modtime;
216+ updated = 1;
217+ } else
218+ mtime = st->st_mtime;
219 /* don't complain about not setting times on directories
220 * because some filesystems can't do it */
221- if (set_modtime(fname,file->modtime) != 0 &&
222+ if (updated && set_times(fname, mtime, atime) != 0 &&
223 !S_ISDIR(st->st_mode)) {
fe6407b5
WD
224 rsyserr(FERROR, errno, "failed to set times on %s",
225 full_fname(fname));
43581f16
WD
226 return 0;
227 }
228- updated = 1;
229 }
230
231 change_uid = am_root && preserve_uid && st->st_uid != file->uid;
f6c3b300 232--- orig/rsync.h 2004-07-16 20:07:23
13bed3dd 233+++ rsync.h 2004-07-03 20:15:41
43581f16
WD
234@@ -54,6 +54,7 @@
235 #define XMIT_HAS_IDEV_DATA (1<<9)
236 #define XMIT_SAME_DEV (1<<10)
237 #define XMIT_RDEV_MINOR_IS_SMALL (1<<11)
238+#define XMIT_SAME_ATIME (1<<12)
239
240 /* These flags are used in the live flist data. */
241
8a529471
WD
242@@ -111,6 +112,7 @@
243
244 #define PERMS_REPORT (1<<0)
245 #define PERMS_SKIP_MTIME (1<<1)
246+#define PERMS_SKIP_ATIME (1<<2)
247
248 #define FULL_FLUSH 1
249 #define NORMAL_FLUSH 0
250@@ -422,6 +424,7 @@ struct file_struct {
43581f16
WD
251 struct hlink *links;
252 } link_u;
253 time_t modtime;
254+ time_t atime;
255 uid_t uid;
256 gid_t gid;
257 mode_t mode;
f6c3b300 258--- orig/rsync.yo 2004-07-16 20:07:23
13bed3dd 259+++ rsync.yo 2004-07-03 20:15:41
f6c3b300 260@@ -301,6 +301,7 @@ verb(
43581f16
WD
261 -g, --group preserve group
262 -D, --devices preserve devices (root only)
263 -t, --times preserve times
264+ -A, --copy-atimes copy access times
265 -S, --sparse handle sparse files efficiently
266 -n, --dry-run show what would have been transferred
267 -W, --whole-file copy whole files, no incremental checks
f6c3b300 268@@ -564,6 +565,11 @@ cause the next transfer to behave as if
43581f16
WD
269 their checksums compared and show up in log messages even if they haven't
270 changed.
7b675ff5 271
43581f16
WD
272+dit(bf(-A, --copy-atimes)) This tells rsync to transfer access times
273+along with the files and update them on the remote system. Note that
274+reading the source file may update the atime and hence repeated rsync
275+copies with --copy-atimes may copy files unnecessarily.
7b675ff5 276+
43581f16
WD
277 dit(bf(-n, --dry-run)) This tells rsync to not do any file transfers,
278 instead it will just report the actions it would have taken.
7b675ff5 279
13bed3dd
WD
280--- orig/testsuite/copy-atimes.test 2004-06-30 00:06:23
281+++ testsuite/copy-atimes.test 2004-06-30 00:06:23
282@@ -0,0 +1,19 @@
283+#! /bin/sh
284+
285+# Test rsync copying atimes
286+
287+. "$suitedir/rsync.fns"
288+
289+set -x
290+
291+mkdir "$fromdir"
292+
293+touch "$fromdir/foo"
294+touch -a -t 200102031717.42 "$fromdir/foo"
295+
296+TLS_ARGS=--atime
297+
298+checkit "$RSYNC -rtAgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
299+
300+# The script would have aborted on error, so getting here means we've won.
301+exit 0
302--- orig/testsuite/rsync.fns 2004-06-28 21:08:14
303+++ testsuite/rsync.fns 2004-07-03 20:15:41
304@@ -50,7 +50,7 @@ printmsg() {
305
306
307 rsync_ls_lR() {
308- find "$@" -print | sort | xargs "$TOOLDIR/tls"
309+ find "$@" -print | sort | xargs "$TOOLDIR/tls" $TLS_ARGS
310 }
311
312 rsync_getgroups() {
313@@ -150,6 +150,8 @@ checkit() {
314 # We can just write everything to stdout/stderr, because the
315 # wrapper hides it unless there is a problem.
316
317+ ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
318+
319 echo "Running: \"$1\""
320 eval "$1"
321 status=$?
322@@ -158,6 +160,12 @@ checkit() {
323 fi
324
325 echo "-------------"
326+ echo "check how the directory listings compare with diff:"
327+ echo ""
328+ ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
329+ diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
330+
331+ echo "-------------"
332 echo "check how the files compare with diff:"
333 echo ""
334 for f in `cd "$2"; find . -type f -print `
335@@ -165,12 +173,6 @@ checkit() {
336 diff $diffopt "$2"/"$f" "$3"/"$f" || failed=YES
337 done
338
339- echo "-------------"
340- echo "check how the directory listings compare with diff:"
341- echo ""
342- ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
343- ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
344- diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
345 if [ -z "$failed" ] ; then
346 return 0
347 else
348--- orig/tls.c 2004-05-15 20:10:13
349+++ tls.c 2004-07-03 20:15:41
43581f16
WD
350@@ -39,6 +39,7 @@
351
352
353 #include "rsync.h"
354+#include "popt.h"
355
356 #define PROGRAM "tls"
357
358@@ -48,6 +49,7 @@ int read_only = 1;
359 int list_only = 0;
360 int preserve_perms = 0;
361
362+static int display_atime = 0;
363
fe6407b5
WD
364 static void failed(char const *what, char const *where)
365 {
366@@ -56,14 +58,29 @@ static void failed(char const *what, cha
367 exit(1);
43581f16
WD
368 }
369
370+static void storetime(char *dest, time_t t)
371+{
372+ if (t) {
373+ struct tm *mt = gmtime(&t);
374
375+ sprintf(dest, "%04d-%02d-%02d %02d:%02d:%02d ",
376+ mt->tm_year + 1900,
377+ mt->tm_mon + 1,
378+ mt->tm_mday,
379+ mt->tm_hour,
380+ mt->tm_min,
381+ mt->tm_sec);
382+ } else {
383+ strcpy(dest, " ");
384+ }
385+}
386
fe6407b5 387 static void list_file(const char *fname)
43581f16
WD
388 {
389 STRUCT_STAT buf;
390 char permbuf[PERMSTRING_SIZE];
391- struct tm *mt;
392- char datebuf[50];
393+ char mtimebuf[50];
394+ char atimebuf[50];
395 char linkbuf[4096];
396
397 if (do_lstat(fname, &buf) == -1)
fe6407b5 398@@ -96,19 +113,8 @@ static void list_file(const char *fname)
43581f16
WD
399
400 permstring(permbuf, buf.st_mode);
401
402- if (buf.st_mtime) {
403- mt = gmtime(&buf.st_mtime);
404-
405- sprintf(datebuf, "%04d-%02d-%02d %02d:%02d:%02d",
406- mt->tm_year + 1900,
407- mt->tm_mon + 1,
408- mt->tm_mday,
409- mt->tm_hour,
410- mt->tm_min,
411- mt->tm_sec);
412- } else {
413- strcpy(datebuf, " ");
414- }
415+ storetime(mtimebuf, buf.st_mtime);
416+ storetime(atimebuf, buf.st_atime);
417
418 /* TODO: Perhaps escape special characters in fname? */
419
fe6407b5 420@@ -119,24 +125,55 @@ static void list_file(const char *fname)
43581f16
WD
421 (long)minor(buf.st_rdev));
422 } else /* NB: use double for size since it might not fit in a long. */
423 printf("%12.0f", (double)buf.st_size);
424- printf(" %6ld.%-6ld %6ld %s %s%s\n",
425+ printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
426 (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
427- datebuf, fname, linkbuf);
428+ mtimebuf, display_atime ? atimebuf : "",
429+ fname, linkbuf);
430 }
431
432+static struct poptOption long_options[] = {
433+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
434+ {"atime", 'u', POPT_ARG_NONE, &display_atime, 0, 0, 0},
435+ {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0},
436+ {0,0,0,0,0,0,0}
437+};
438+
439+static void tls_usage(int ret)
440+{
441+ fprintf(stderr, "usage: " PROGRAM " [--atime | -u] DIR ...\n"
442+ "Trivial file listing program for portably checking rsync\n");
443+ exit(ret);
444+}
445
446 int
447 main(int argc, char *argv[])
448 {
449- if (argc < 2) {
fe6407b5
WD
450- fprintf(stderr, "usage: " PROGRAM " DIR ...\n"
451- "Trivial file listing program for portably checking rsync\n");
43581f16
WD
452- return 1;
453+ poptContext pc;
454+ const char **extra_args;
455+ int opt;
456+
457+ pc = poptGetContext(PROGRAM, argc, (const char **)argv,
458+ long_options, 0);
459+ while ((opt = poptGetNextOpt(pc)) != -1) {
460+ switch (opt) {
461+ case 'h':
462+ tls_usage(0);
463+ default:
464+ fprintf(stderr,
465+ "%s: %s\n",
466+ poptBadOption(pc, POPT_BADOPTION_NOALIAS),
467+ poptStrerror(opt));
468+ tls_usage(1);
469+ }
470 }
471
472- for (argv++; *argv; argv++) {
fe6407b5 473- list_file(*argv);
43581f16
WD
474- }
475+ extra_args = poptGetArgs(pc);
476+ if (*extra_args == NULL)
477+ tls_usage(1);
478+
479+ for (; *extra_args; extra_args++)
480+ list_file(*extra_args);
481+ poptFreeContext(pc);
482
483 return 0;
484 }
13bed3dd
WD
485--- orig/util.c 2004-06-09 21:54:47
486+++ util.c 2004-07-03 20:15:41
7b675ff5 487@@ -127,31 +127,39 @@ void overflow(char *str)
43581f16
WD
488
489
490
491-int set_modtime(char *fname, time_t modtime)
492+int set_times(char *fname, time_t modtime, time_t atime)
493 {
43581f16
WD
494 if (dry_run)
495 return 0;
496
497 if (verbose > 2) {
498- rprintf(FINFO, "set modtime of %s to (%ld) %s",
499+ char mtimebuf[200];
500+ char atimebuf[200];
501+
125d7fca
WD
502+ strlcpy(mtimebuf, timestring(modtime), sizeof mtimebuf);
503+ strlcpy(atimebuf, timestring(atime), sizeof atimebuf);
43581f16
WD
504+
505+ rprintf(FINFO,
506+ "set modtime, atime of %s to (%ld) %s, (%ld) %s\n",
125d7fca 507 fname, (long)modtime,
43581f16
WD
508- asctime(localtime(&modtime)));
509+ mtimebuf,
125d7fca 510+ (long)atime, atimebuf);
43581f16
WD
511 }
512
513 {
514 #ifdef HAVE_UTIMBUF
515 struct utimbuf tbuf;
516- tbuf.actime = time(NULL);
517+ tbuf.actime = atime;
518 tbuf.modtime = modtime;
519 return utime(fname,&tbuf);
520 #elif defined(HAVE_UTIME)
521 time_t t[2];
522- t[0] = time(NULL);
523+ t[0] = atime;
524 t[1] = modtime;
525 return utime(fname,t);
526 #else
527 struct timeval t[2];
528- t[0].tv_sec = time(NULL);
529+ t[0].tv_sec = atime;
530 t[0].tv_usec = 0;
531 t[1].tv_sec = modtime;
532 t[1].tv_usec = 0;
896c61d0 533@@ -1078,8 +1086,8 @@ int msleep(int t)
43581f16
WD
534
535
536 /**
537- * Determine if two file modification times are equivalent (either
538- * exact or in the modification timestamp window established by
539+ * Determine if two file times are equivalent (either
540+ * exact or in the timestamp window established by
541 * --modify-window).
542 *
543 * @retval 0 if the times should be treated as the same
896c61d0 544@@ -1088,7 +1096,7 @@ int msleep(int t)
43581f16
WD
545 *
546 * @retval -1 if the 2nd is later
547 **/
548-int cmp_modtime(time_t file1, time_t file2)
549+int cmp_time(time_t file1, time_t file2)
550 {
7b675ff5
WD
551 if (file2 > file1) {
552 if (file2 - file1 <= modify_window)