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