1 After applying this patch and running configure, you MUST run this
7 --- orig/batch.c 2004-08-02 05:02:24
8 +++ batch.c 2004-07-03 20:15:41
9 @@ -184,6 +184,8 @@ void show_flist(int index, struct file_s
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);
18 --- orig/flist.c 2004-09-21 09:40:27
19 +++ flist.c 2004-07-03 20:15:41
20 @@ -59,6 +59,7 @@ extern int relative_paths;
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 extern int delete_excluded;
28 @@ -143,17 +144,17 @@ static void list_file_entry(struct file_
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",
35 (double)f->length, timestring(f->modtime),
36 - f_name(f), f->u.link);
37 + timestring(f->atime), f_name(f), f->u.link);
41 - rprintf(FINFO, "%s %11.0f %s %s\n",
42 + rprintf(FINFO, "%s %11.0f %s %s %s\n",
44 (double)f->length, timestring(f->modtime),
46 + timestring(f->atime), f_name(f));
50 @@ -334,6 +335,7 @@ void send_file_entry(struct file_struct
53 static time_t modtime;
54 + static time_t atime;
58 @@ -349,7 +351,7 @@ void send_file_entry(struct file_struct
62 - modtime = 0, mode = 0;
63 + modtime = 0, atime = 0, mode = 0;
64 dev = 0, rdev = makedev(0, 0);
67 @@ -398,6 +400,12 @@ void send_file_entry(struct file_struct
68 flags |= XMIT_SAME_TIME;
70 modtime = file->modtime;
71 + if (copy_atimes && !S_ISDIR(mode)) {
72 + if (file->atime == atime)
73 + flags |= XMIT_SAME_ATIME;
75 + atime = file->atime;
78 #if SUPPORT_HARD_LINKS
79 if (file->link_u.idev) {
80 @@ -453,6 +461,8 @@ void send_file_entry(struct file_struct
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)) {
89 @@ -526,6 +536,7 @@ void receive_file_entry(struct file_stru
90 struct file_list *flist, int f)
92 static time_t modtime;
93 + static time_t atime;
97 @@ -542,7 +553,7 @@ void receive_file_entry(struct file_stru
98 struct file_struct *file;
101 - modtime = 0, mode = 0;
102 + modtime = 0, atime = 0, mode = 0;
103 dev = 0, rdev = makedev(0, 0);
106 @@ -597,6 +608,8 @@ void receive_file_entry(struct file_stru
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);
113 if (preserve_uid && !(flags & XMIT_SAME_UID))
114 uid = (uid_t)read_int(f);
115 @@ -647,6 +660,7 @@ void receive_file_entry(struct file_stru
117 file->flags = flags & XMIT_TOP_DIR ? FLAG_TOP_DIR : 0;
118 file->modtime = modtime;
119 + file->atime = atime;
120 file->length = file_length;
123 @@ -868,6 +882,7 @@ skip_excludes:
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;
131 --- orig/generator.c 2004-09-20 19:50:13
132 +++ generator.c 2004-07-03 20:15:41
133 @@ -92,7 +92,7 @@ static int skip_file(char *fname, struct
137 - return cmp_modtime(st->st_mtime, file->modtime) == 0;
138 + return cmp_time(st->st_mtime, file->modtime) == 0;
142 @@ -484,7 +484,7 @@ static void recv_generator(char *fname,
145 if (update_only && fnamecmp == fname
146 - && cmp_modtime(st.st_mtime, file->modtime) > 0) {
147 + && cmp_time(st.st_mtime, file->modtime) > 0) {
149 rprintf(FINFO, "%s is newer\n", safe_fname(fname));
151 --- orig/options.c 2004-09-20 05:10:48
152 +++ options.c 2004-07-03 20:15:41
153 @@ -48,6 +48,7 @@ int preserve_devices = 0;
154 int preserve_uid = 0;
155 int preserve_gid = 0;
156 int preserve_times = 0;
157 +int copy_atimes = 0;
161 @@ -253,6 +254,7 @@ void usage(enum logcode F)
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");
169 @@ -362,6 +364,7 @@ static struct poptOption long_options[]
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, ©_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 },
177 @@ -946,6 +949,8 @@ void server_options(char **args,int *arg
186 --- orig/rsync.c 2004-09-07 21:45:30
187 +++ rsync.c 2004-08-13 08:17:28
191 extern int preserve_times;
192 +extern int copy_atimes;
194 extern int am_sender;
195 extern int am_generator;
196 @@ -145,17 +146,32 @@ 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)))
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))
205 + != (PERMS_SKIP_MTIME|PERMS_SKIP_ATIME)) {
206 + time_t atime, mtime;
208 + if (!(flags & PERMS_SKIP_ATIME)
209 + && cmp_time(st->st_atime, file->atime) != 0) {
210 + atime = file->atime;
213 + atime = st->st_atime;
214 + if (!(flags & PERMS_SKIP_MTIME)
215 + && cmp_time(st->st_mtime, file->modtime) != 0) {
216 + mtime = file->modtime;
219 + mtime = st->st_mtime;
220 /* don't complain about not setting times on directories
221 * because some filesystems can't do it */
222 - if (set_modtime(fname,file->modtime) != 0 &&
223 + if (updated && set_times(fname, mtime, atime) != 0 &&
224 !S_ISDIR(st->st_mode)) {
225 rsyserr(FERROR, errno, "failed to set times on %s",
232 change_uid = am_root && preserve_uid && st->st_uid != file->uid;
233 --- orig/rsync.h 2004-08-03 15:41:32
234 +++ rsync.h 2004-07-03 20:15:41
236 #define XMIT_HAS_IDEV_DATA (1<<9)
237 #define XMIT_SAME_DEV (1<<10)
238 #define XMIT_RDEV_MINOR_IS_SMALL (1<<11)
239 +#define XMIT_SAME_ATIME (1<<12)
241 /* These flags are used in the live flist data. */
245 #define PERMS_REPORT (1<<0)
246 #define PERMS_SKIP_MTIME (1<<1)
247 +#define PERMS_SKIP_ATIME (1<<2)
250 #define NORMAL_FLUSH 0
251 @@ -425,6 +427,7 @@ struct file_struct {
259 --- orig/rsync.yo 2004-09-20 05:10:48
260 +++ rsync.yo 2004-07-03 20:15:41
261 @@ -330,6 +330,7 @@ verb(
262 -g, --group preserve group
263 -D, --devices preserve devices (root only)
264 -t, --times preserve times
265 + -A, --copy-atimes copy access times
266 -S, --sparse handle sparse files efficiently
267 -n, --dry-run show what would have been transferred
268 -W, --whole-file copy whole files, no incremental checks
269 @@ -603,6 +604,11 @@ cause the next transfer to behave as if
270 updated (though the rsync algorithm will make the update fairly efficient
271 if the files haven't actually changed, you're much better off using -t).
273 +dit(bf(-A, --copy-atimes)) This tells rsync to transfer access times
274 +along with the files and update them on the remote system. Note that
275 +reading the source file may update the atime and hence repeated rsync
276 +copies with --copy-atimes may copy files unnecessarily.
278 dit(bf(-n, --dry-run)) This tells rsync to not do any file transfers,
279 instead it will just report the actions it would have taken.
281 --- orig/testsuite/copy-atimes.test 2004-06-30 00:06:23
282 +++ testsuite/copy-atimes.test 2004-06-30 00:06:23
286 +# Test rsync copying atimes
288 +. "$suitedir/rsync.fns"
294 +touch "$fromdir/foo"
295 +touch -a -t 200102031717.42 "$fromdir/foo"
299 +checkit "$RSYNC -rtAgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
301 +# The script would have aborted on error, so getting here means we've won.
303 --- orig/testsuite/rsync.fns 2004-09-18 01:49:34
304 +++ testsuite/rsync.fns 2004-07-03 20:15:41
305 @@ -50,7 +50,7 @@ printmsg() {
309 - find "$@" -print | sort | xargs "$TOOLDIR/tls"
310 + find "$@" -print | sort | xargs "$TOOLDIR/tls" $TLS_ARGS
314 @@ -158,6 +158,8 @@ checkit() {
315 # We can just write everything to stdout/stderr, because the
316 # wrapper hides it unless there is a problem.
318 + ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
320 echo "Running: \"$1\""
323 @@ -166,6 +168,12 @@ checkit() {
327 + echo "check how the directory listings compare with diff:"
329 + ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
330 + diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
332 + echo "-------------"
333 echo "check how the files compare with diff:"
335 for f in `cd "$2"; find . -type f -print `
336 @@ -173,12 +181,6 @@ checkit() {
337 diff $diffopt "$2"/"$f" "$3"/"$f" || failed=YES
340 - echo "-------------"
341 - echo "check how the directory listings compare with diff:"
343 - ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
344 - ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
345 - diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
346 if [ -z "$failed" ] ; then
349 --- orig/tls.c 2004-05-15 20:10:13
350 +++ tls.c 2004-07-03 20:15:41
357 #define PROGRAM "tls"
359 @@ -48,6 +49,7 @@ int read_only = 1;
361 int preserve_perms = 0;
363 +static int display_atime = 0;
365 static void failed(char const *what, char const *where)
367 @@ -56,14 +58,29 @@ static void failed(char const *what, cha
371 +static void storetime(char *dest, time_t t)
374 + struct tm *mt = gmtime(&t);
376 + sprintf(dest, "%04d-%02d-%02d %02d:%02d:%02d ",
377 + mt->tm_year + 1900,
388 static void list_file(const char *fname)
391 char permbuf[PERMSTRING_SIZE];
398 if (do_lstat(fname, &buf) == -1)
399 @@ -96,19 +113,8 @@ static void list_file(const char *fname)
401 permstring(permbuf, buf.st_mode);
403 - if (buf.st_mtime) {
404 - mt = gmtime(&buf.st_mtime);
406 - sprintf(datebuf, "%04d-%02d-%02d %02d:%02d:%02d",
407 - mt->tm_year + 1900,
414 - strcpy(datebuf, " ");
416 + storetime(mtimebuf, buf.st_mtime);
417 + storetime(atimebuf, buf.st_atime);
419 /* TODO: Perhaps escape special characters in fname? */
421 @@ -119,24 +125,55 @@ static void list_file(const char *fname)
422 (long)minor(buf.st_rdev));
423 } else /* NB: use double for size since it might not fit in a long. */
424 printf("%12.0f", (double)buf.st_size);
425 - printf(" %6ld.%-6ld %6ld %s %s%s\n",
426 + printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
427 (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
428 - datebuf, fname, linkbuf);
429 + mtimebuf, display_atime ? atimebuf : "",
433 +static struct poptOption long_options[] = {
434 + /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
435 + {"atime", 'u', POPT_ARG_NONE, &display_atime, 0, 0, 0},
436 + {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0},
440 +static void tls_usage(int ret)
442 + fprintf(stderr, "usage: " PROGRAM " [--atime | -u] DIR ...\n"
443 + "Trivial file listing program for portably checking rsync\n");
448 main(int argc, char *argv[])
451 - fprintf(stderr, "usage: " PROGRAM " DIR ...\n"
452 - "Trivial file listing program for portably checking rsync\n");
455 + const char **extra_args;
458 + pc = poptGetContext(PROGRAM, argc, (const char **)argv,
460 + while ((opt = poptGetNextOpt(pc)) != -1) {
467 + poptBadOption(pc, POPT_BADOPTION_NOALIAS),
468 + poptStrerror(opt));
473 - for (argv++; *argv; argv++) {
476 + extra_args = poptGetArgs(pc);
477 + if (*extra_args == NULL)
480 + for (; *extra_args; extra_args++)
481 + list_file(*extra_args);
482 + poptFreeContext(pc);
486 --- orig/util.c 2004-09-07 21:45:30
487 +++ util.c 2004-07-03 20:15:41
488 @@ -128,31 +128,39 @@ void overflow(char *str)
492 -int set_modtime(char *fname, time_t modtime)
493 +int set_times(char *fname, time_t modtime, time_t atime)
499 - rprintf(FINFO, "set modtime of %s to (%ld) %s",
500 + char mtimebuf[200];
501 + char atimebuf[200];
503 + strlcpy(mtimebuf, timestring(modtime), sizeof mtimebuf);
504 + strlcpy(atimebuf, timestring(atime), sizeof atimebuf);
507 + "set modtime, atime of %s to (%ld) %s, (%ld) %s\n",
508 fname, (long)modtime,
509 - asctime(localtime(&modtime)));
511 + (long)atime, atimebuf);
517 - tbuf.actime = time(NULL);
518 + tbuf.actime = atime;
519 tbuf.modtime = modtime;
520 return utime(fname,&tbuf);
521 #elif defined(HAVE_UTIME)
526 return utime(fname,t);
529 - t[0].tv_sec = time(NULL);
530 + t[0].tv_sec = atime;
532 t[1].tv_sec = modtime;
534 @@ -1142,8 +1150,8 @@ int msleep(int t)
538 - * Determine if two file modification times are equivalent (either
539 - * exact or in the modification timestamp window established by
540 + * Determine if two file times are equivalent (either
541 + * exact or in the timestamp window established by
544 * @retval 0 if the times should be treated as the same
545 @@ -1152,7 +1160,7 @@ int msleep(int t)
547 * @retval -1 if the 2nd is later
549 -int cmp_modtime(time_t file1, time_t file2)
550 +int cmp_time(time_t file1, time_t file2)
553 if (file2 - file1 <= modify_window)