[PATCH] Add --preserve-atime switch to rsync

Gary Fernandez GaryF at livevault.com
Tue Sep 10 20:33:01 EST 2002


In the past there have been discussions about adding a switch to rsync to
preserve the atime on files being copied by rsync. I needed this function
for a project I'm working on and decided to invent it. I've attached the
diffs. Note that this has the limitations describe in previous emails,
namely that preserving atime causes ctime to not be preserved.

*** Patch follows ***

*** backup.c@@/main/original/1 Tue Apr  9 14:02:14 2002
--- backup.c Tue Apr  9 15:21:56 2002
***************
*** 110,116 ****
                                          rprintf(FERROR,"make_bak_dir stat
%s : %s\n",fullpath,strerror(errno));
                                  } else {
                                          st2=&st;
!
set_modtime(fullpath,st2->st_mtime);
 
if(do_lchown(fullpath,st2->st_uid,st2->st_gid)!=0) {
 
rprintf(FERROR,"make_bak_dir chown %s : %s\n",fullpath,strerror(errno));
                                          };
--- 110,117 ----
                                          rprintf(FERROR,"make_bak_dir stat
%s : %s\n",fullpath,strerror(errno));
                                  } else {
                                          st2=&st;
!
set_modtime(fullpath,st2->st_mtime,
!                                                     st2->st_atime);
 
if(do_lchown(fullpath,st2->st_uid,st2->st_gid)!=0) {
 
rprintf(FERROR,"make_bak_dir chown %s : %s\n",fullpath,strerror(errno));
                                          };

*** sender.c@@/main/original/1 Tue Apr  9 14:03:44 2002
--- sender.c Fri Apr 12 11:09:52 2002
***************
*** 26,33 ****
  extern int io_error;
  extern int dry_run;
  extern int am_server;
  
- 
  /*
    receive the checksums for a buffer
    */
--- 26,36 ----
  extern int io_error;
  extern int dry_run;
  extern int am_server;
+ extern int preserve_atime;
  
  /*
    receive the checksums for a buffer
    */
***************
*** 184,189 ****
--- 197,204 ----
  				rprintf(FERROR,"fstat failed :
%s\n",strerror(errno));
  				free_sums(s);
  				close(fd);
+ 				if (preserve_atime)
+ 					set_modtime(fname, file->modtime,
file->acctime);
  				return;
  			}
  	  
***************
*** 266,271 ****
--- 281,288 ----
  		if (!read_batch) { /* dw */
  		    if (buf) unmap_file(buf);
  		    close(fd);
+ 		    if (preserve_atime)
+ 			set_modtime(fname, file->modtime, file->acctime);
  		}
  	  
  		free_sums(s);

*** util.c@@/main/original/1 Tue Apr  9 14:04:04 2002
--- util.c Tue Apr  9 15:22:00 2002
***************
*** 240,246 ****
  
  
  
! int set_modtime(char *fname, time_t modtime)
  {
  	extern int dry_run;
  	if (dry_run)
--- 240,246 ----
  
  
  
! int set_modtime(char *fname,time_t modtime, time_t acctime)
  {
  	extern int dry_run;
  	if (dry_run)
***************
*** 255,271 ****
  	{
  #ifdef HAVE_UTIMBUF
  		struct utimbuf tbuf;  
! 		tbuf.actime = time(NULL);
  		tbuf.modtime = modtime;
  		return utime(fname,&tbuf);
  #elif defined(HAVE_UTIME)
  		time_t t[2];
! 		t[0] = time(NULL);
  		t[1] = modtime;
  		return utime(fname,t);
  #else
  		struct timeval t[2];
! 		t[0].tv_sec = time(NULL);
  		t[0].tv_usec = 0;
  		t[1].tv_sec = modtime;
  		t[1].tv_usec = 0;
--- 255,271 ----
  	{
  #ifdef HAVE_UTIMBUF
  		struct utimbuf tbuf;  
! 		tbuf.actime = acctime;
  		tbuf.modtime = modtime;
  		return utime(fname,&tbuf);
  #elif defined(HAVE_UTIME)
  		time_t t[2];
! 		t[0] = acctime;
  		t[1] = modtime;
  		return utime(fname,t);
  #else
  		struct timeval t[2];
! 		t[0].tv_sec = acctime;
  		t[0].tv_usec = 0;
  		t[1].tv_sec = modtime;
  		t[1].tv_usec = 0;

*** rsync.c@@/main/original/1 Tue Apr  9 14:03:28 2002
--- rsync.c Fri Apr 12 11:00:16 2002
***************
*** 165,171 ****
  	    cmp_modtime(st->st_mtime, file->modtime) != 0) {
  		/* don't complain about not setting times on directories
  		   because some filesystems can't do it */
! 		if (set_modtime(fname,file->modtime) != 0 &&
  		    !S_ISDIR(st->st_mode)) {
  			rprintf(FERROR,"failed to set times on %s : %s\n",
  				fname,strerror(errno));
--- 165,173 ----
  	    cmp_modtime(st->st_mtime, file->modtime) != 0) {
  		/* don't complain about not setting times on directories
  		   because some filesystems can't do it */
! 		time_t now;
! 		now = time(NULL);
! 		if (set_modtime(fname,file->modtime, now) != 0 &&
  		    !S_ISDIR(st->st_mode)) {
  			rprintf(FERROR,"failed to set times on %s : %s\n",
  				fname,strerror(errno));

*** rsync.h@@/main/original/1 Tue Apr  9 14:03:30 2002
--- rsync.h Tue Apr  9 15:22:00 2002
***************
*** 333,338 ****
--- 333,339 ----
  struct file_struct {
  	unsigned flags;
  	time_t modtime;
+ 	time_t acctime;
  	OFF_T length;
  	mode_t mode;
  
*** proto.h@@/main/original/1 Tue Apr  9 14:03:22 2002
--- proto.h Tue Apr  9 15:21:58 2002
***************
*** 233,239 ****
  pid_t local_child(int argc, char **argv,int *f_in,int *f_out);
  void out_of_memory(char *str);
  void overflow(char *str);
! int set_modtime(char *fname, time_t modtime);
  int create_directory_path(char *fname);
  int copy_file(char *source, char *dest, mode_t mode);
  int robust_unlink(char *fname);
--- 233,239 ----
  pid_t local_child(int argc, char **argv,int *f_in,int *f_out);
  void out_of_memory(char *str);
  void overflow(char *str);
! int set_modtime(char *fname,time_t modtime,time_t acctime);
  int create_directory_path(char *fname);
  int copy_file(char *source, char *dest, mode_t mode);
  int robust_unlink(char *fname);

*** options.c@@/main/original/1 Tue Apr  9 14:03:18 2002
--- options.c Tue Apr  9 15:59:10 2002
***************
*** 44,49 ****
--- 44,50 ----
  int preserve_uid = 0;
  int preserve_gid = 0;
  int preserve_times = 0;
+ int preserve_atime = 0;
  int update_only = 0;
  int cvs_exclude = 0;
  int dry_run=0;
***************
*** 220,225 ****
--- 221,227 ----
    rprintf(F," -g, --group                 preserve group\n");
    rprintf(F," -D, --devices               preserve devices (root
only)\n");
    rprintf(F," -t, --times                 preserve times\n");  
+   rprintf(F,"     --preserve-atime        preserve atime for source\n");  
    rprintf(F," -S, --sparse                handle sparse files
efficiently\n");
    rprintf(F," -n, --dry-run               show what would have been
transferred\n");
    rprintf(F," -W, --whole-file            copy whole files, no incremental
checks\n");
***************
*** 287,293 ****
        OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR, 
        OPT_IGNORE_ERRORS, OPT_BWLIMIT, OPT_BLOCKING_IO,
        OPT_NO_BLOCKING_IO, OPT_WHOLE_FILE, OPT_NO_WHOLE_FILE,
!       OPT_MODIFY_WINDOW, OPT_READ_BATCH, OPT_WRITE_BATCH,
OPT_IGNORE_EXISTING};
  
  static struct poptOption long_options[] = {
    /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
--- 289,296 ----
        OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR, 
        OPT_IGNORE_ERRORS, OPT_BWLIMIT, OPT_BLOCKING_IO,
        OPT_NO_BLOCKING_IO, OPT_WHOLE_FILE, OPT_NO_WHOLE_FILE,
!       OPT_MODIFY_WINDOW, OPT_READ_BATCH, OPT_WRITE_BATCH,
OPT_IGNORE_EXISTING,
!       OPT_PRESERVE_ATIME};
  
  static struct poptOption long_options[] = {
    /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
***************
*** 361,366 ****
--- 364,370 ----
    {"hard-links",      'H', POPT_ARG_NONE,   &preserve_hard_links , 0, 0, 0
},
    {"read-batch",       0,  POPT_ARG_STRING, &batch_prefix, OPT_READ_BATCH,
0, 0 },
    {"write-batch",      0,  POPT_ARG_STRING, &batch_prefix,
OPT_WRITE_BATCH, 0, 0 },
+   {"preserve-atime",   0,  POPT_ARG_NONE,   &preserve_atime, 0, 0, 0 },
  #ifdef INET6
    {0,		      '4', POPT_ARG_VAL,    &default_af_hint,   AF_INET , 0,
0 },
    {0,		      '6', POPT_ARG_VAL,    &default_af_hint,   AF_INET6 ,
0, 0 },

*** flist.c@@/main/original/1 Tue Apr  9 14:02:48 2002
--- flist.c Tue Jun 18 09:40:46 2002
***************
*** 706,711 ****
--- 706,712 ----
  	}
  
  	file->modtime = st.st_mtime;
+ 	file->acctime = st.st_atime;
  	file->length = st.st_size;
  	file->mode = st.st_mode;
  	file->uid = st.st_uid;

*** rsync.1@@/main/original/1 Tue Apr  9 14:03:26 2002
--- rsync.1 Fri May 10 09:34:44 2002
***************
*** 311,316 ****
--- 311,317 ----
       --bwlimit=KBPS          limit I/O bandwidth, KBytes per second
       --read-batch=PREFIX     read batch fileset starting with PREFIX
       --write-batch=PREFIX    write batch fileset starting with PREFIX
+      --preserve-atime        preserve atime for source
   -h, --help                  show this help screen
  
  
***************
*** 825,830 ****
--- 826,837 ----
  Apply a previously generated change batch,
  using the fileset whose filenames start with PREFIX\&. See the "BATCH
  MODE" section for details\&.
+ .IP 
+ .IP "\fB--preserve-atime\fP" 
+ Preserve atime while reading source filesystem. This works by reading and
+ resetting the atime for each file accessed. It has the side effect of
+ updating the ctime for the file. This may or may not be the desired
+ behavior; consider this before using.
  .IP 
  .PP 
  .SH "EXCLUDE PATTERNS" 




More information about the rsync mailing list