Use the new diff-dependency feature to make the patch depend on
[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
8cec1ead 8+++ batch.c 30 Jun 2004 00:06:21 -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);
7628f156 18--- flist.c 18 Jun 2004 16:29:21 -0000 1.231
8cec1ead 19+++ flist.c 30 Jun 2004 00:06:21 -0000
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
WD
27 extern int delete_excluded;
28@@ -144,17 +145,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
7628f156 50@@ -335,6 +336,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;
7628f156 58@@ -350,7 +352,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;
7628f156 67@@ -399,6 +401,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) {
7628f156 80@@ -454,6 +462,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);
7628f156
WD
89@@ -527,6 +537,7 @@ void receive_file_entry(struct file_stru
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;
7628f156 97@@ -543,7 +554,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;
7628f156 106@@ -598,6 +609,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);
7628f156 115@@ -648,6 +661,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;
7628f156 123@@ -867,6 +881,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;
8cec1ead
WD
131--- generator.c 29 Jun 2004 19:19:00 -0000 1.92
132+++ generator.c 30 Jun 2004 00:06:21 -0000
133@@ -99,7 +99,7 @@ static int skip_file(char *fname, struct
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
8cec1ead 142@@ -484,7 +484,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;
8cec1ead
WD
151--- options.c 20 Jun 2004 19:47:05 -0000 1.157
152+++ options.c 30 Jun 2004 00:06:21 -0000
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;
125d7fca 161@@ -245,6 +246,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");
125d7fca 169@@ -352,6 +354,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 },
f3e2725a 177@@ -841,6 +844,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)
7628f156 186--- rsync.c 11 Jun 2004 07:40:45 -0000 1.141
8cec1ead 187+++ rsync.c 30 Jun 2004 00:06:22 -0000
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;
7b675ff5
WD
196@@ -143,17 +144,31 @@ int set_perms(char *fname,struct file_st
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;
7d2d2057 232--- rsync.h 16 May 2004 07:28:24 -0000 1.204
8cec1ead 233+++ rsync.h 30 Jun 2004 00:06:22 -0000
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;
125d7fca 258--- rsync.yo 5 Jun 2004 16:16:30 -0000 1.171
8cec1ead 259+++ rsync.yo 30 Jun 2004 00:06:23 -0000
125d7fca 260@@ -300,6 +300,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
125d7fca 268@@ -552,6 +553,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
fe6407b5 280--- tls.c 15 May 2004 19:09:42 -0000 1.20
8cec1ead 281+++ tls.c 30 Jun 2004 00:06:23 -0000
43581f16
WD
282@@ -39,6 +39,7 @@
283
284
285 #include "rsync.h"
286+#include "popt.h"
287
288 #define PROGRAM "tls"
289
290@@ -48,6 +49,7 @@ int read_only = 1;
291 int list_only = 0;
292 int preserve_perms = 0;
293
294+static int display_atime = 0;
295
fe6407b5
WD
296 static void failed(char const *what, char const *where)
297 {
298@@ -56,14 +58,29 @@ static void failed(char const *what, cha
299 exit(1);
43581f16
WD
300 }
301
302+static void storetime(char *dest, time_t t)
303+{
304+ if (t) {
305+ struct tm *mt = gmtime(&t);
306
307+ sprintf(dest, "%04d-%02d-%02d %02d:%02d:%02d ",
308+ mt->tm_year + 1900,
309+ mt->tm_mon + 1,
310+ mt->tm_mday,
311+ mt->tm_hour,
312+ mt->tm_min,
313+ mt->tm_sec);
314+ } else {
315+ strcpy(dest, " ");
316+ }
317+}
318
fe6407b5 319 static void list_file(const char *fname)
43581f16
WD
320 {
321 STRUCT_STAT buf;
322 char permbuf[PERMSTRING_SIZE];
323- struct tm *mt;
324- char datebuf[50];
325+ char mtimebuf[50];
326+ char atimebuf[50];
327 char linkbuf[4096];
328
329 if (do_lstat(fname, &buf) == -1)
fe6407b5 330@@ -96,19 +113,8 @@ static void list_file(const char *fname)
43581f16
WD
331
332 permstring(permbuf, buf.st_mode);
333
334- if (buf.st_mtime) {
335- mt = gmtime(&buf.st_mtime);
336-
337- sprintf(datebuf, "%04d-%02d-%02d %02d:%02d:%02d",
338- mt->tm_year + 1900,
339- mt->tm_mon + 1,
340- mt->tm_mday,
341- mt->tm_hour,
342- mt->tm_min,
343- mt->tm_sec);
344- } else {
345- strcpy(datebuf, " ");
346- }
347+ storetime(mtimebuf, buf.st_mtime);
348+ storetime(atimebuf, buf.st_atime);
349
350 /* TODO: Perhaps escape special characters in fname? */
351
fe6407b5 352@@ -119,24 +125,55 @@ static void list_file(const char *fname)
43581f16
WD
353 (long)minor(buf.st_rdev));
354 } else /* NB: use double for size since it might not fit in a long. */
355 printf("%12.0f", (double)buf.st_size);
356- printf(" %6ld.%-6ld %6ld %s %s%s\n",
357+ printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
358 (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
359- datebuf, fname, linkbuf);
360+ mtimebuf, display_atime ? atimebuf : "",
361+ fname, linkbuf);
362 }
363
364+static struct poptOption long_options[] = {
365+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
366+ {"atime", 'u', POPT_ARG_NONE, &display_atime, 0, 0, 0},
367+ {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0},
368+ {0,0,0,0,0,0,0}
369+};
370+
371+static void tls_usage(int ret)
372+{
373+ fprintf(stderr, "usage: " PROGRAM " [--atime | -u] DIR ...\n"
374+ "Trivial file listing program for portably checking rsync\n");
375+ exit(ret);
376+}
377
378 int
379 main(int argc, char *argv[])
380 {
381- if (argc < 2) {
fe6407b5
WD
382- fprintf(stderr, "usage: " PROGRAM " DIR ...\n"
383- "Trivial file listing program for portably checking rsync\n");
43581f16
WD
384- return 1;
385+ poptContext pc;
386+ const char **extra_args;
387+ int opt;
388+
389+ pc = poptGetContext(PROGRAM, argc, (const char **)argv,
390+ long_options, 0);
391+ while ((opt = poptGetNextOpt(pc)) != -1) {
392+ switch (opt) {
393+ case 'h':
394+ tls_usage(0);
395+ default:
396+ fprintf(stderr,
397+ "%s: %s\n",
398+ poptBadOption(pc, POPT_BADOPTION_NOALIAS),
399+ poptStrerror(opt));
400+ tls_usage(1);
401+ }
402 }
403
404- for (argv++; *argv; argv++) {
fe6407b5 405- list_file(*argv);
43581f16
WD
406- }
407+ extra_args = poptGetArgs(pc);
408+ if (*extra_args == NULL)
409+ tls_usage(1);
410+
411+ for (; *extra_args; extra_args++)
412+ list_file(*extra_args);
413+ poptFreeContext(pc);
414
415 return 0;
416 }
896c61d0 417--- util.c 9 Jun 2004 21:51:07 -0000 1.149
8cec1ead 418+++ util.c 30 Jun 2004 00:06:23 -0000
7b675ff5 419@@ -127,31 +127,39 @@ void overflow(char *str)
43581f16
WD
420
421
422
423-int set_modtime(char *fname, time_t modtime)
424+int set_times(char *fname, time_t modtime, time_t atime)
425 {
43581f16
WD
426 if (dry_run)
427 return 0;
428
429 if (verbose > 2) {
430- rprintf(FINFO, "set modtime of %s to (%ld) %s",
431+ char mtimebuf[200];
432+ char atimebuf[200];
433+
125d7fca
WD
434+ strlcpy(mtimebuf, timestring(modtime), sizeof mtimebuf);
435+ strlcpy(atimebuf, timestring(atime), sizeof atimebuf);
43581f16
WD
436+
437+ rprintf(FINFO,
438+ "set modtime, atime of %s to (%ld) %s, (%ld) %s\n",
125d7fca 439 fname, (long)modtime,
43581f16
WD
440- asctime(localtime(&modtime)));
441+ mtimebuf,
125d7fca 442+ (long)atime, atimebuf);
43581f16
WD
443 }
444
445 {
446 #ifdef HAVE_UTIMBUF
447 struct utimbuf tbuf;
448- tbuf.actime = time(NULL);
449+ tbuf.actime = atime;
450 tbuf.modtime = modtime;
451 return utime(fname,&tbuf);
452 #elif defined(HAVE_UTIME)
453 time_t t[2];
454- t[0] = time(NULL);
455+ t[0] = atime;
456 t[1] = modtime;
457 return utime(fname,t);
458 #else
459 struct timeval t[2];
460- t[0].tv_sec = time(NULL);
461+ t[0].tv_sec = atime;
462 t[0].tv_usec = 0;
463 t[1].tv_sec = modtime;
464 t[1].tv_usec = 0;
896c61d0 465@@ -1078,8 +1086,8 @@ int msleep(int t)
43581f16
WD
466
467
468 /**
469- * Determine if two file modification times are equivalent (either
470- * exact or in the modification timestamp window established by
471+ * Determine if two file times are equivalent (either
472+ * exact or in the timestamp window established by
473 * --modify-window).
474 *
475 * @retval 0 if the times should be treated as the same
896c61d0 476@@ -1088,7 +1096,7 @@ int msleep(int t)
43581f16
WD
477 *
478 * @retval -1 if the 2nd is later
479 **/
480-int cmp_modtime(time_t file1, time_t file2)
481+int cmp_time(time_t file1, time_t file2)
482 {
7b675ff5
WD
483 if (file2 > file1) {
484 if (file2 - file1 <= modify_window)
43581f16 485--- /dev/null 1 Jan 1970 00:00:00 -0000
8cec1ead 486+++ testsuite/copy-atimes.test 30 Jun 2004 00:06:23 -0000
7d2d2057 487@@ -0,0 +1,19 @@
43581f16
WD
488+#! /bin/sh
489+
490+# Test rsync copying atimes
491+
7d2d2057 492+. "$suitedir/rsync.fns"
43581f16
WD
493+
494+set -x
495+
43581f16
WD
496+mkdir "$fromdir"
497+
498+touch "$fromdir/foo"
499+touch -a -t 200102031717.42 "$fromdir/foo"
500+
501+TLS_ARGS=--atime
502+
503+checkit "$RSYNC -rtAgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
504+
505+# The script would have aborted on error, so getting here means we've won.
506+exit 0
8cec1ead
WD
507--- testsuite/rsync.fns 24 Jun 2004 04:46:02 -0000 1.61
508+++ testsuite/rsync.fns 30 Jun 2004 00:06:23 -0000
7d2d2057 509@@ -50,7 +50,7 @@ printmsg() {
43581f16
WD
510
511
512 rsync_ls_lR() {
513- find "$@" -print | sort | xargs "$TOOLDIR/tls"
514+ find "$@" -print | sort | xargs "$TOOLDIR/tls" $TLS_ARGS
515 }
516
517 rsync_getgroups() {
7d2d2057 518@@ -150,6 +150,8 @@ checkit() {
43581f16
WD
519 # We can just write everything to stdout/stderr, because the
520 # wrapper hides it unless there is a problem.
521
7d2d2057 522+ ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
43581f16
WD
523+
524 echo "Running: \"$1\""
525 eval "$1"
526 status=$?
7d2d2057 527@@ -158,6 +160,12 @@ checkit() {
43581f16
WD
528 fi
529
530 echo "-------------"
531+ echo "check how the directory listings compare with diff:"
532+ echo ""
7d2d2057
WD
533+ ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
534+ diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
43581f16
WD
535+
536+ echo "-------------"
537 echo "check how the files compare with diff:"
538 echo ""
539 for f in `cd "$2"; find . -type f -print `
7d2d2057 540@@ -165,12 +173,6 @@ checkit() {
43581f16
WD
541 diff $diffopt "$2"/"$f" "$3"/"$f" || failed=YES
542 done
543
544- echo "-------------"
545- echo "check how the directory listings compare with diff:"
546- echo ""
7d2d2057
WD
547- ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
548- ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
549- diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
550 if [ -z "$failed" ] ; then
43581f16
WD
551 return 0
552 else