propagate atimes with rsync-2.6.6 (fwd)

Christian Konz T3 cjk at ipp.mpg.de
Tue Jan 24 16:46:36 GMT 2006


Dear Martin Pool.

We regularly use rsync for making backups of our file systems but we have
noticed that the atimes are not transferred with the files and are also
always updated on the sender's side. Therefore, we have created a modified
version of rsync based on rsync-2.6.6 protocol version 29 which transfers
the access times with the transferred files and also allows to preserve
the access times on the sending side. The transfer of the atimes is done
by default while the preservation of the source atimes is switched on by
an additional option (-X --atime-preserve). To guarantee compatibility
with previous protocol versions, we have introduced a new protocol version
(30). If the remote protocol version is older than 30, rsync behaves as
before. The changes made to the reference version are small and kept in
accordance with the original style. The affected files are:
	flist.c
	generator.c
	options.c
	proto.h
	rsync.1
	rsync.c
	rsync.h
	rsync3.txt
	sender.c
and	util.c
Please find the corresponding patch attached to this email.
We have thouroughly tested our new protocol under Linux and also compiled
it under Unix (Aix). It works as expected under Linux while some of the
changes were redundant under Unix.
We consider the preservation of the source access times as useful since
this information might be worth being backed-up as well.
We hope our approach will find your attention and would be glad if it were
included in the next update of rsync.
Please let us know about your suggestions for improvements.
Yours truly,

Christian Konz
-------------- next part --------------
diff -uNr rsync-2.6.6/flist.c rsync-2.6.6_patch/flist.c
--- rsync-2.6.6/flist.c	2005-07-07 21:49:14.000000000 +0200
+++ rsync-2.6.6_patch/flist.c	2006-01-07 14:04:38.000000000 +0100
@@ -54,6 +54,7 @@
 extern int implied_dirs;
 extern int copy_links;
 extern int copy_unsafe_links;
+extern int remote_protocol;
 extern int protocol_version;
 extern int sanitize_paths;
 extern int orig_umask;
@@ -314,6 +315,7 @@
 {
 	unsigned short flags;
 	static time_t modtime;
+	static time_t acctime;
 	static mode_t mode;
 	static int64 dev;
 	static dev_t rdev;
@@ -329,7 +331,7 @@
 
 	if (!file) {
 		write_byte(f, 0);
-		modtime = 0, mode = 0;
+		modtime = 0, acctime = 0, mode = 0;
 		dev = 0, rdev = makedev(0, 0);
 		rdev_major = 0;
 		uid = 0, gid = 0;
@@ -379,6 +381,8 @@
 	else
 		modtime = file->modtime;
 
+        acctime = file->acctime;
+
 #ifdef SUPPORT_HARD_LINKS
 	if (file->link_u.idev) {
 		if (file->F_DEV == dev) {
@@ -431,6 +435,8 @@
 	write_longint(f, file->length);
 	if (!(flags & XMIT_SAME_TIME))
 		write_int(f, modtime);
+	if (remote_protocol >= 30)
+		write_int(f, acctime);
 	if (!(flags & XMIT_SAME_MODE))
 		write_int(f, to_wire_mode(mode));
 	if (preserve_uid && !(flags & XMIT_SAME_UID)) {
@@ -506,6 +512,7 @@
 					      unsigned short flags, int f)
 {
 	static time_t modtime;
+	static time_t acctime;
 	static mode_t mode;
 	static int64 dev;
 	static dev_t rdev;
@@ -524,7 +531,7 @@
 	struct file_struct *file;
 
 	if (!flist) {
-		modtime = 0, mode = 0;
+    	        modtime = 0, acctime = 0, mode = 0;
 		dev = 0, rdev = makedev(0, 0);
 		rdev_major = 0;
 		uid = 0, gid = 0;
@@ -578,6 +585,10 @@
 	file_length = read_longint(f);
 	if (!(flags & XMIT_SAME_TIME))
 		modtime = (time_t)read_int(f);
+	if (remote_protocol >= 30)
+		acctime = (time_t)read_int(f);
+	else
+		acctime = time(NULL);
 	if (!(flags & XMIT_SAME_MODE))
 		mode = from_wire_mode(read_int(f));
 
@@ -630,6 +641,7 @@
 
 	file->flags = 0;
 	file->modtime = modtime;
+	file->acctime = acctime;
 	file->length = file_length;
 	file->mode = mode;
 	file->uid = uid;
@@ -882,6 +894,7 @@
 
 	file->flags = flags;
 	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;
diff -uNr rsync-2.6.6/generator.c rsync-2.6.6_patch/generator.c
--- rsync-2.6.6/generator.c	2005-07-28 21:06:03.000000000 +0200
+++ rsync-2.6.6_patch/generator.c	2005-11-25 11:33:33.000000000 +0100
@@ -917,6 +917,13 @@
 						  fnamecmpbuf, 1,
 						  itemizing && verbose > 1,
 						  code) == 0) {
+					if (set_modtime(fname,file->modtime,
+							file->acctime) != 0) {
+						rsyserr(FERROR, errno, 
+							"failed to set times on %s",
+							full_fname(fname));
+						return;
+					}
 					if (preserve_hard_links
 					    && file->link_u.links) {
 						hard_link_cluster(file, ndx,
diff -uNr rsync-2.6.6/options.c rsync-2.6.6_patch/options.c
--- rsync-2.6.6/options.c	2005-05-19 10:52:17.000000000 +0200
+++ rsync-2.6.6_patch/options.c	2006-01-11 15:56:00.000000000 +0100
@@ -48,6 +48,7 @@
 int preserve_uid = 0;
 int preserve_gid = 0;
 int preserve_times = 0;
+int preserve_atime = 0;
 int omit_dir_times = 0;
 int update_only = 0;
 int cvs_exclude = 0;
@@ -286,6 +287,7 @@
   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," -X, --atime-preserve        preserve atimes on SRC\n");   
   rprintf(F," -O, --omit-dir-times        omit directories when preserving times\n");
   rprintf(F," -S, --sparse                handle sparse files efficiently\n");
   rprintf(F," -n, --dry-run               show what would have been transferred\n");
@@ -412,6 +414,7 @@
   {"group",           'g', POPT_ARG_NONE,   &preserve_gid, 0, 0, 0 },
   {"devices",         'D', POPT_ARG_NONE,   &preserve_devices, 0, 0, 0 },
   {"times",           't', POPT_ARG_NONE,   &preserve_times, 0, 0, 0 },
+  {"atime-preserve",  'X', POPT_ARG_NONE,   &preserve_atime, 0, 0, 0 }, 
   {"omit-dir-times",  'O', POPT_ARG_VAL,    &omit_dir_times, 2, 0, 0 },
   {"checksum",        'c', POPT_ARG_NONE,   &always_checksum, 0, 0, 0 },
   {"verbose",         'v', POPT_ARG_NONE,   0, 'v', 0, 0 },
diff -uNr rsync-2.6.6/proto.h rsync-2.6.6_patch/proto.h
--- rsync-2.6.6/proto.h	2005-07-07 21:49:14.000000000 +0200
+++ rsync-2.6.6_patch/proto.h	2005-11-23 23:51:54.000000000 +0100
@@ -266,7 +266,7 @@
 void print_child_argv(char **cmd);
 void out_of_memory(char *str);
 void overflow_exit(char *str);
-int set_modtime(char *fname, time_t modtime);
+int set_modtime(char *fname, time_t modtime, time_t acctime);
 int create_directory_path(char *fname, int base_umask);
 int full_write(int desc, char *ptr, size_t len);
 int copy_file(char *source, char *dest, mode_t mode);
diff -uNr rsync-2.6.6/rsync.1 rsync-2.6.6_patch/rsync.1
--- rsync-2.6.6/rsync.1	2005-07-28 21:31:08.000000000 +0200
+++ rsync-2.6.6_patch/rsync.1	2006-01-11 15:56:09.000000000 +0100
@@ -374,6 +374,7 @@
  -g, --group                 preserve group
  -D, --devices               preserve devices (root only)
  -t, --times                 preserve times
+ -X, --atime-preserve        don't change atimes on source
  -O, --omit-dir-times        omit directories when preserving times
  -S, --sparse                handle sparse files efficiently
  -n, --dry-run               show what would have been transferred
@@ -751,7 +752,11 @@
 modified cannot be effective; in other words, a missing \fB-t\fP or \fB-a\fP will
 cause the next transfer to behave as if it used \fB-I\fP, causing all files to be
 updated (though the rsync algorithm will make the update fairly efficient
-if the files haven\&'t actually changed, you\&'re much better off using \fB-t\fP)\&.
+if the files haven\&'t actually changed, you\&'re much better off using
+\fB-t\fP)\&. The access times are transferred along with the files by default\&.
+.IP 
+.IP "\fB-X, --atime-preserve\fP" 
+This tells rsync to not change the access times of the source files\&.
 .IP 
 .IP "\fB-O, --omit-dir-times\fP" 
 This tells rsync to omit directories when
diff -uNr rsync-2.6.6/rsync3.txt rsync-2.6.6_patch/rsync3.txt
--- rsync-2.6.6/rsync3.txt	2001-09-12 16:35:39.000000000 +0200
+++ rsync-2.6.6_patch/rsync3.txt	2006-01-19 18:20:33.957510912 +0100
@@ -124,10 +124,6 @@
 
   - Scripting support.  
 
-  - Propagate atimes and do not modify them.  This is very ugly on
-    Unix.  It might be better to try to add O_NOATIME to kernels, and
-    call that.
-
   - Unicode.  Probably just use UTF-8 for everything.
 
   - Open authentication system.  Can we use PAM?  Is SASL an adequate
diff -uNr rsync-2.6.6/rsync.c rsync-2.6.6_patch/rsync.c
--- rsync-2.6.6/rsync.c	2005-03-14 18:06:08.000000000 +0100
+++ rsync-2.6.6_patch/rsync.c	2005-11-23 23:53:43.000000000 +0100
@@ -73,7 +73,7 @@
 		flags |= PERMS_SKIP_MTIME;
 	if (!(flags & PERMS_SKIP_MTIME)
 	    && cmp_modtime(st->st_mtime, file->modtime) != 0) {
-		if (set_modtime(fname,file->modtime) != 0) {
+		if (set_modtime(fname,file->modtime,file->acctime) != 0) {
 			rsyserr(FERROR, errno, "failed to set times on %s",
 				full_fname(fname));
 			return 0;
diff -uNr rsync-2.6.6/rsync.h rsync-2.6.6_patch/rsync.h
--- rsync-2.6.6/rsync.h	2005-05-03 19:00:47.000000000 +0200
+++ rsync-2.6.6_patch/rsync.h	2005-11-28 17:59:19.000000000 +0100
@@ -66,7 +66,7 @@
 #define FLAG_HLINK_TOL (1<<4)	/* receiver/generator */
 
 /* update this if you make incompatible changes */
-#define PROTOCOL_VERSION 29
+#define PROTOCOL_VERSION 30
 
 /* We refuse to interoperate with versions that are not in this range.
  * Note that we assume we'll work with later versions: the onus is on
@@ -509,6 +509,7 @@
 		struct hlink *links;
 	} link_u;
 	time_t modtime;
+	time_t acctime;
 	uid_t uid;
 	gid_t gid;
 	mode_t mode;
diff -uNr rsync-2.6.6/sender.c rsync-2.6.6_patch/sender.c
--- rsync-2.6.6/sender.c	2005-05-19 10:52:24.000000000 +0200
+++ rsync-2.6.6_patch/sender.c	2006-01-07 14:28:06.000000000 +0100
@@ -37,6 +37,7 @@
 extern int inplace;
 extern int batch_fd;
 extern int write_batch;
+extern int preserve_atime;
 extern struct stats stats;
 extern struct file_list *the_file_list;
 extern char *log_format;
@@ -357,6 +358,14 @@
 					full_fname(fname));
 			}
 		}
+/* reset original access and modtime if preserve_atime=1 */
+		if (preserve_atime) {
+			if (set_modtime(fname,st.st_mtime,st.st_atime) != 0) {
+				rsyserr(FERROR, errno,
+					"failed to set times on %s",
+					full_fname(fname));
+			}
+		}
 		close(fd);
 
 		free_sums(s);
diff -uNr rsync-2.6.6/util.c rsync-2.6.6_patch/util.c
--- rsync-2.6.6/util.c	2005-07-07 21:49:14.000000000 +0200
+++ rsync-2.6.6_patch/util.c	2005-11-23 23:59:42.000000000 +0100
@@ -128,7 +128,7 @@
 
 
 
-int set_modtime(char *fname, time_t modtime)
+int set_modtime(char *fname, time_t modtime, time_t acctime)
 {
 	if (verbose > 2) {
 		rprintf(FINFO, "set modtime of %s to (%ld) %s",
@@ -142,17 +142,17 @@
 	{
 #ifdef HAVE_UTIMBUF
 		struct utimbuf tbuf;
-		tbuf.actime = time(NULL);
+		tbuf.actime = acctime;
 		tbuf.modtime = modtime;
 		return utime(fname,&tbuf);
 #elif defined HAVE_UTIME
 		time_t t[2];
-		t[0] = time(NULL);
+		t[0] = acctime;
 		t[1] = modtime;
 		return utime(fname,t);
 #else
 		struct timeval t[2];
-		t[0].tv_sec = time(NULL);
+		t[0].tv_sec = acctime;
 		t[0].tv_usec = 0;
 		t[1].tv_sec = modtime;
 		t[1].tv_usec = 0;


More information about the rsync mailing list