3b821c1c303d9b59360b2665b091b6ffe5a6e6d2
[rsync-patches.git] / atimes.diff
1 After applying this patch and running configure, you MUST run this
2 command before "make":
3
4     make proto
5
6
7 --- orig/batch.c        2005-03-01 01:22:58
8 +++ batch.c     2004-07-03 20:15:41
9 @@ -202,6 +202,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        2005-02-26 19:27:54
19 +++ flist.c     2005-02-07 21:06:04
20 @@ -56,6 +56,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 orig_umask;
28 @@ -140,16 +141,18 @@ static void list_file_entry(struct file_
29  
30  #ifdef 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 +                       timestring(f->atime),
37                         safe_fname(f_name(f)), safe_fname(f->u.link));
38         } else
39  #endif
40         {
41 -               rprintf(FINFO, "%s %11.0f %s %s\n",
42 +               rprintf(FINFO, "%s %11.0f %s %s %s\n",
43                         perms,
44                         (double)f->length, timestring(f->modtime),
45 +                       timestring(f->atime),
46                         safe_fname(f_name(f)));
47         }
48  }
49 @@ -313,6 +316,7 @@ void send_file_entry(struct file_struct 
50  {
51         unsigned short flags;
52         static time_t modtime;
53 +       static time_t atime;
54         static mode_t mode;
55         static int64 dev;
56         static dev_t rdev;
57 @@ -328,7 +332,7 @@ void send_file_entry(struct file_struct 
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;
66 @@ -377,6 +381,12 @@ void send_file_entry(struct file_struct 
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  #ifdef SUPPORT_HARD_LINKS
78         if (file->link_u.idev) {
79 @@ -432,6 +442,8 @@ void send_file_entry(struct file_struct 
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);
88 @@ -505,6 +517,7 @@ static struct file_struct *receive_file_
89                                               unsigned short flags, int f)
90  {
91         static time_t modtime;
92 +       static time_t atime;
93         static mode_t mode;
94         static int64 dev;
95         static dev_t rdev;
96 @@ -523,7 +536,7 @@ static struct file_struct *receive_file_
97         struct file_struct *file;
98  
99         if (!flist) {
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;
105 @@ -579,6 +592,8 @@ static struct file_struct *receive_file_
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);
114 @@ -629,6 +644,7 @@ static struct file_struct *receive_file_
115  
116         file->flags = 0;
117         file->modtime = modtime;
118 +       file->atime = atime;
119         file->length = file_length;
120         file->mode = mode;
121         file->uid = uid;
122 @@ -878,6 +894,7 @@ skip_filters:
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;
130 --- orig/generator.c    2005-03-03 02:58:55
131 +++ generator.c 2004-11-03 23:02:12
132 @@ -357,7 +357,7 @@ static int unchanged_file(char *fn, stru
133         if (ignore_times)
134                 return 0;
135  
136 -       return cmp_modtime(st->st_mtime, file->modtime) == 0;
137 +       return cmp_time(st->st_mtime, file->modtime) == 0;
138  }
139  
140  
141 @@ -808,7 +808,7 @@ static void recv_generator(char *fname, 
142         }
143  
144         if (update_only && statret == 0
145 -           && cmp_modtime(st.st_mtime, file->modtime) > 0) {
146 +           && cmp_time(st.st_mtime, file->modtime) > 0) {
147                 if (verbose > 1)
148                         rprintf(FINFO, "%s is newer\n", safe_fname(fname));
149                 return;
150 --- orig/options.c      2005-03-02 09:52:06
151 +++ options.c   2005-02-21 10:53:28
152 @@ -50,6 +50,7 @@ int preserve_uid = 0;
153  int preserve_gid = 0;
154  int preserve_times = 0;
155  int omit_dir_times = 0;
156 +int copy_atimes = 0;
157  int update_only = 0;
158  int cvs_exclude = 0;
159  int dry_run = 0;
160 @@ -284,6 +285,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," -O, --omit-dir-times        omit directories when preserving 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 @@ -407,6 +409,7 @@ static struct poptOption long_options[] 
169    {"devices",         'D', POPT_ARG_NONE,   &preserve_devices, 0, 0, 0 },
170    {"times",           't', POPT_ARG_NONE,   &preserve_times, 0, 0, 0 },
171    {"omit-dir-times",  'O', POPT_ARG_VAL,    &omit_dir_times, 2, 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 @@ -1269,6 +1272,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 (omit_dir_times == 2 && am_sender)
183                 argstr[x++] = 'O';
184         if (preserve_perms)
185 --- orig/rsync.c        2005-02-25 18:44:31
186 +++ rsync.c     2005-02-21 10:57:03
187 @@ -27,6 +27,7 @@ extern int dry_run;
188  extern int daemon_log_format_has_i;
189  extern int preserve_times;
190  extern int omit_dir_times;
191 +extern int copy_atimes;
192  extern int am_root;
193  extern int am_server;
194  extern int am_sender;
195 @@ -57,6 +58,7 @@ int set_perms(char *fname,struct file_st
196         int updated = 0;
197         STRUCT_STAT st2;
198         int change_uid, change_gid;
199 +       time_t atime, mtime;
200  
201         if (!st) {
202                 if (dry_run)
203 @@ -69,17 +71,27 @@ int set_perms(char *fname,struct file_st
204                 st = &st2;
205         }
206  
207 +       if (!copy_atimes || S_ISLNK(st->st_mode) || S_ISDIR(st->st_mode))
208 +               flags |= PERMS_SKIP_ATIME;
209         if (!preserve_times || S_ISLNK(st->st_mode)
210          || (S_ISDIR(st->st_mode) && omit_dir_times))
211                 flags |= PERMS_SKIP_MTIME;
212 +       if (!(flags & PERMS_SKIP_ATIME)
213 +           && cmp_time(st->st_atime, file->atime) != 0) {
214 +               atime = file->atime;
215 +               updated = 1;
216 +       } else
217 +               atime = st->st_atime;
218         if (!(flags & PERMS_SKIP_MTIME)
219 -           && cmp_modtime(st->st_mtime, file->modtime) != 0) {
220 -               if (set_modtime(fname,file->modtime) != 0) {
221 -                       rsyserr(FERROR, errno, "failed to set times on %s",
222 -                               full_fname(fname));
223 -                       return 0;
224 -               }
225 +           && cmp_time(st->st_mtime, file->modtime) != 0) {
226 +               mtime = file->modtime;
227                 updated = 1;
228 +       } else
229 +               mtime = st->st_mtime;
230 +       if (updated && set_times(fname, mtime, atime) != 0) {
231 +               rsyserr(FERROR, errno, "failed to set times on %s",
232 +                       full_fname(fname));
233 +               return 0;
234         }
235  
236         change_uid = am_root && preserve_uid && st->st_uid != file->uid;
237 --- orig/rsync.h        2005-03-03 00:14:56
238 +++ rsync.h     2004-07-03 20:15:41
239 @@ -54,6 +54,7 @@
240  #define XMIT_HAS_IDEV_DATA (1<<9)
241  #define XMIT_SAME_DEV (1<<10)
242  #define XMIT_RDEV_MINOR_IS_SMALL (1<<11)
243 +#define XMIT_SAME_ATIME (1<<12)
244  
245  /* These flags are used in the live flist data. */
246  
247 @@ -116,6 +117,7 @@
248  
249  #define PERMS_REPORT           (1<<0)
250  #define PERMS_SKIP_MTIME       (1<<1)
251 +#define PERMS_SKIP_ATIME       (1<<2)
252  
253  #define FULL_FLUSH     1
254  #define NORMAL_FLUSH   0
255 @@ -501,6 +503,7 @@ struct file_struct {
256                 struct hlink *links;
257         } link_u;
258         time_t modtime;
259 +       time_t atime;
260         uid_t uid;
261         gid_t gid;
262         mode_t mode;
263 --- orig/rsync.yo       2005-03-03 02:23:27
264 +++ rsync.yo    2005-01-24 01:57:18
265 @@ -321,6 +321,7 @@ to the detailed description below for a 
266   -D, --devices               preserve devices (root only)
267   -t, --times                 preserve times
268   -O, --omit-dir-times        omit directories when preserving times
269 + -A, --copy-atimes           copy access times
270   -S, --sparse                handle sparse files efficiently
271   -n, --dry-run               show what would have been transferred
272   -W, --whole-file            copy files whole (without rsync algorithm)
273 @@ -653,6 +654,11 @@ it is preserving modification times (see
274  the directories on the receiving side, it is a good idea to use bf(-O).
275  This option is inferred if you use bf(--backup) without bf(--backup-dir).
276  
277 +dit(bf(-A, --copy-atimes)) This tells rsync to transfer access times
278 +along with the files and update them on the remote system.  Note that
279 +reading the source file may update the atime and hence repeated rsync
280 +copies with --copy-atimes may copy files unnecessarily.
281 +
282  dit(bf(-n, --dry-run)) This tells rsync to not do any file transfers,
283  instead it will just report the actions it would have taken.
284  
285 --- orig/testsuite/copy-atimes.test     2004-06-30 00:06:23
286 +++ testsuite/copy-atimes.test  2004-06-30 00:06:23
287 @@ -0,0 +1,19 @@
288 +#! /bin/sh
289 +
290 +# Test rsync copying atimes
291 +
292 +. "$suitedir/rsync.fns"
293 +
294 +set -x
295 +
296 +mkdir "$fromdir"
297 +
298 +touch "$fromdir/foo"
299 +touch -a -t 200102031717.42 "$fromdir/foo"
300 +
301 +TLS_ARGS=--atime
302 +
303 +checkit "$RSYNC -rtAgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
304 +
305 +# The script would have aborted on error, so getting here means we've won.
306 +exit 0
307 --- orig/testsuite/rsync.fns    2005-02-21 07:29:00
308 +++ testsuite/rsync.fns 2005-02-21 07:30:11
309 @@ -50,7 +50,7 @@ printmsg() {
310  
311  
312  rsync_ls_lR() {
313 -    find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls"
314 +    find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls" $TLS_ARGS
315  }
316  
317  rsync_getgroups() { 
318 @@ -158,6 +158,8 @@ checkit() {
319      # We can just write everything to stdout/stderr, because the
320      # wrapper hides it unless there is a problem.
321  
322 +    ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
323 +
324      echo "Running: \"$1\""  
325      eval "$1" 
326      status=$?
327 @@ -168,7 +170,6 @@ checkit() {
328      echo "-------------"
329      echo "check how the directory listings compare with diff:"
330      echo ""
331 -    ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
332      ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
333      diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
334  
335 --- orig/tls.c  2005-01-19 20:11:10
336 +++ tls.c       2004-07-03 20:15:41
337 @@ -39,6 +39,7 @@
338  
339  
340  #include "rsync.h"
341 +#include "popt.h"
342  
343  #define PROGRAM "tls"
344  
345 @@ -48,6 +49,7 @@ int read_only = 1;
346  int list_only = 0;
347  int preserve_perms = 0;
348  
349 +static int display_atime = 0;
350  
351  static void failed(char const *what, char const *where)
352  {
353 @@ -56,14 +58,29 @@ static void failed(char const *what, cha
354         exit(1);
355  }
356  
357 +static void storetime(char *dest, time_t t)
358 +{
359 +       if (t) {
360 +               struct tm *mt = gmtime(&t);
361  
362 +               sprintf(dest, "%04d-%02d-%02d %02d:%02d:%02d ",
363 +                       mt->tm_year + 1900,
364 +                       mt->tm_mon + 1,
365 +                       mt->tm_mday,
366 +                       mt->tm_hour,
367 +                       mt->tm_min,
368 +                       mt->tm_sec);
369 +       } else {
370 +               strcpy(dest, "                    ");
371 +       }
372 +}      
373  
374  static void list_file(const char *fname)
375  {
376         STRUCT_STAT buf;
377         char permbuf[PERMSTRING_SIZE];
378 -       struct tm *mt;
379 -       char datebuf[50];
380 +       char mtimebuf[50];
381 +       char atimebuf[50];
382         char linkbuf[4096];
383  
384         if (do_lstat(fname, &buf) < 0)
385 @@ -96,19 +113,8 @@ static void list_file(const char *fname)
386  
387         permstring(permbuf, buf.st_mode);
388  
389 -       if (buf.st_mtime) {
390 -               mt = gmtime(&buf.st_mtime);
391 -
392 -               sprintf(datebuf, "%04d-%02d-%02d %02d:%02d:%02d",
393 -                       mt->tm_year + 1900,
394 -                       mt->tm_mon + 1,
395 -                       mt->tm_mday,
396 -                       mt->tm_hour,
397 -                       mt->tm_min,
398 -                       mt->tm_sec);
399 -       } else {
400 -               strcpy(datebuf, "                   ");
401 -       }
402 +       storetime(mtimebuf, buf.st_mtime);
403 +       storetime(atimebuf, buf.st_atime);
404  
405         /* TODO: Perhaps escape special characters in fname? */
406  
407 @@ -119,24 +125,55 @@ static void list_file(const char *fname)
408                     (long)minor(buf.st_rdev));
409         } else /* NB: use double for size since it might not fit in a long. */
410                 printf("%12.0f", (double)buf.st_size);
411 -       printf(" %6ld.%-6ld %6ld %s %s%s\n",
412 +       printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
413                (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
414 -              datebuf, fname, linkbuf);
415 +              mtimebuf, display_atime ? atimebuf : "",
416 +              fname, linkbuf);
417  }
418  
419 +static struct poptOption long_options[] = {
420 +  /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
421 +  {"atime",           'u', POPT_ARG_NONE,   &display_atime, 0,   0, 0},
422 +  {"help",            'h', POPT_ARG_NONE,   0,              'h', 0, 0},
423 +  {0,0,0,0,0,0,0}
424 +};
425 +
426 +static void tls_usage(int ret)
427 +{
428 +       fprintf(stderr, "usage: " PROGRAM " [--atime | -u] DIR ...\n"
429 +           "Trivial file listing program for portably checking rsync\n");
430 +       exit(ret);
431 +}
432  
433  int
434  main(int argc, char *argv[])
435  {
436 -       if (argc < 2) {
437 -               fprintf(stderr, "usage: " PROGRAM " DIR ...\n"
438 -                       "Trivial file listing program for portably checking rsync\n");
439 -               return 1;
440 +       poptContext pc;
441 +       const char **extra_args;
442 +       int opt;
443 +
444 +       pc = poptGetContext(PROGRAM, argc, (const char **)argv,
445 +                           long_options, 0);
446 +       while ((opt = poptGetNextOpt(pc)) != -1) {
447 +               switch (opt) {
448 +               case 'h':
449 +                       tls_usage(0);
450 +               default:
451 +                       fprintf(stderr,
452 +                               "%s: %s\n",
453 +                               poptBadOption(pc, POPT_BADOPTION_NOALIAS),
454 +                               poptStrerror(opt));
455 +                       tls_usage(1);
456 +               }
457         }
458  
459 -       for (argv++; *argv; argv++) {
460 -               list_file(*argv);
461 -       }
462 +       extra_args = poptGetArgs(pc);
463 +       if (*extra_args == NULL)
464 +               tls_usage(1);
465 +
466 +       for (; *extra_args; extra_args++)
467 +               list_file(*extra_args);
468 +       poptFreeContext(pc);
469  
470         return 0;
471  }
472 --- orig/util.c 2005-02-23 02:57:27
473 +++ util.c      2005-02-07 21:09:12
474 @@ -128,12 +128,17 @@ void overflow(char *str)
475  
476  
477  
478 -int set_modtime(char *fname, time_t modtime)
479 +int set_times(char *fname, time_t modtime, time_t atime)
480  {
481         if (verbose > 2) {
482 -               rprintf(FINFO, "set modtime of %s to (%ld) %s",
483 +               char mtimebuf[200];
484 +
485 +               strlcpy(mtimebuf, timestring(modtime), sizeof mtimebuf);
486 +               rprintf(FINFO,
487 +                       "set modtime, atime of %s to (%ld) %s, (%ld) %s\n",
488                         safe_fname(fname), (long)modtime,
489 -                       asctime(localtime(&modtime)));
490 +                       mtimebuf,
491 +                       (long)atime, timestring(atime));
492         }
493  
494         if (dry_run)
495 @@ -142,17 +147,17 @@ int set_modtime(char *fname, time_t modt
496         {
497  #ifdef HAVE_UTIMBUF
498                 struct utimbuf tbuf;
499 -               tbuf.actime = time(NULL);
500 +               tbuf.actime = atime;
501                 tbuf.modtime = modtime;
502                 return utime(fname,&tbuf);
503  #elif defined HAVE_UTIME
504                 time_t t[2];
505 -               t[0] = time(NULL);
506 +               t[0] = atime;
507                 t[1] = modtime;
508                 return utime(fname,t);
509  #else
510                 struct timeval t[2];
511 -               t[0].tv_sec = time(NULL);
512 +               t[0].tv_sec = atime;
513                 t[0].tv_usec = 0;
514                 t[1].tv_sec = modtime;
515                 t[1].tv_usec = 0;
516 @@ -1145,8 +1150,8 @@ int msleep(int t)
517  
518  
519  /**
520 - * Determine if two file modification times are equivalent (either
521 - * exact or in the modification timestamp window established by
522 + * Determine if two file  times are equivalent (either
523 + * exact or in the timestamp window established by
524   * --modify-window).
525   *
526   * @retval 0 if the times should be treated as the same
527 @@ -1155,7 +1160,7 @@ int msleep(int t)
528   *
529   * @retval -1 if the 2nd is later
530   **/
531 -int cmp_modtime(time_t file1, time_t file2)
532 +int cmp_time(time_t file1, time_t file2)
533  {
534         if (file2 > file1) {
535                 if (file2 - file1 <= modify_window)