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