After applying this patch and running configure, you MUST run this
command before "make":

    make proto


--- orig/flist.c	2006-01-25 17:15:12
+++ flist.c	2006-01-25 17:46:37
@@ -50,6 +50,7 @@ extern int preserve_perms;
 extern int preserve_devices;
 extern int preserve_uid;
 extern int preserve_gid;
+extern int preserve_atimes;
 extern int relative_paths;
 extern int implied_dirs;
 extern int copy_links;
@@ -83,7 +84,13 @@ void init_flist(void)
 	struct file_struct f;
 
 	/* Figure out how big the file_struct is without trailing padding */
-	file_struct_len = offsetof(struct file_struct, flags) + sizeof f.flags;
+	if (preserve_atimes)
+		file_struct_len = offsetof(struct file_struct, fl4g5);
+	else
+		file_struct_len = offsetof(struct file_struct, atime);
+	/* The "flags" uchar is no longer accessed directly, so I
+	 * mangled the name to fl4g5 as a reminder. */
+	file_struct_len += sizeof f.fl4g5;
 	checksum_len = protocol_version < 21 ? 2 : MD4_SUM_LENGTH;
 }
 
@@ -139,16 +146,18 @@ static void list_file_entry(struct file_
 
 #ifdef SUPPORT_LINKS
 	if (preserve_links && S_ISLNK(f->mode)) {
-		rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
+		rprintf(FINFO, "%s %11.0f %s %s %s -> %s\n",
 			perms,
 			(double)f->length, timestring(f->modtime),
+			preserve_atimes ? timestring(f->atime) : "",
 			f_name(f, NULL), f->u.link);
 	} else
 #endif
 	{
-		rprintf(FINFO, "%s %11.0f %s %s\n",
+		rprintf(FINFO, "%s %11.0f %s %s %s\n",
 			perms,
 			(double)f->length, timestring(f->modtime),
+			preserve_atimes ? timestring(f->atime) : "",
 			f_name(f, NULL));
 	}
 }
@@ -310,6 +319,7 @@ static void send_file_entry(struct file_
 {
 	unsigned short flags;
 	static time_t modtime;
+	static time_t atime;
 	static mode_t mode;
 	static int64 dev;
 	static dev_t rdev;
@@ -325,7 +335,7 @@ static void send_file_entry(struct file_
 
 	if (!file) {
 		write_byte(f, 0);
-		modtime = 0, mode = 0;
+		modtime = 0, atime = 0, mode = 0;
 		dev = 0, rdev = makedev(0, 0);
 		rdev_major = 0;
 		uid = 0, gid = 0;
@@ -337,7 +347,7 @@ static void send_file_entry(struct file_
 
 	f_name(file, fname);
 
-	flags = file->flags & XMIT_TOP_DIR;
+	flags = FFLAGS(file) & XMIT_TOP_DIR;
 
 	if (file->mode == mode)
 		flags |= XMIT_SAME_MODE;
@@ -374,6 +384,12 @@ static void send_file_entry(struct file_
 		flags |= XMIT_SAME_TIME;
 	else
 		modtime = file->modtime;
+	if (preserve_atimes && !S_ISDIR(mode)) {
+		if (file->atime == atime)
+			flags |= XMIT_SAME_ATIME;
+		else
+			atime = file->atime;
+	}
 
 #ifdef SUPPORT_HARD_LINKS
 	if (file->link_u.idev) {
@@ -427,6 +443,8 @@ static void send_file_entry(struct file_
 		write_int(f, modtime);
 	if (!(flags & XMIT_SAME_MODE))
 		write_int(f, to_wire_mode(mode));
+	if (preserve_atimes && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
+		write_int(f, atime);
 	if (preserve_uid && !(flags & XMIT_SAME_UID)) {
 		if (!numeric_ids)
 			add_uid(uid);
@@ -494,6 +512,7 @@ static struct file_struct *receive_file_
 					      unsigned short flags, int f)
 {
 	static time_t modtime;
+	static time_t atime;
 	static mode_t mode;
 	static int64 dev;
 	static dev_t rdev;
@@ -512,7 +531,7 @@ static struct file_struct *receive_file_
 	struct file_struct *file;
 
 	if (!flist) {
-		modtime = 0, mode = 0;
+		modtime = 0, atime = 0, mode = 0;
 		dev = 0, rdev = makedev(0, 0);
 		rdev_major = 0;
 		uid = 0, gid = 0;
@@ -568,6 +587,8 @@ static struct file_struct *receive_file_
 		modtime = (time_t)read_int(f);
 	if (!(flags & XMIT_SAME_MODE))
 		mode = from_wire_mode(read_int(f));
+	if (preserve_atimes && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
+		atime = (time_t)read_int(f);
 
 	if (chmod_modes && !S_ISLNK(mode))
 		mode = tweak_mode(mode, chmod_modes);
@@ -624,6 +645,8 @@ static struct file_struct *receive_file_
 	file->mode = mode;
 	file->uid = uid;
 	file->gid = gid;
+	if (preserve_atimes)
+		file->atime = atime;
 
 	if (dirname_len) {
 		file->dirname = lastdir = bp;
@@ -649,12 +672,12 @@ static struct file_struct *receive_file_
 			    && lastname[del_hier_name_len-1] == '.'
 			    && lastname[del_hier_name_len-2] == '/')
 				del_hier_name_len -= 2;
-			file->flags |= FLAG_TOP_DIR | FLAG_DEL_HERE;
+			FFLAGS(file) |= FLAG_TOP_DIR | FLAG_DEL_HERE;
 		} else if (in_del_hier) {
 			if (!relative_paths || !del_hier_name_len
 			 || (l1 >= del_hier_name_len
 			  && lastname[del_hier_name_len] == '/'))
-				file->flags |= FLAG_DEL_HERE;
+				FFLAGS(file) |= FLAG_DEL_HERE;
 			else
 				in_del_hier = 0;
 		}
@@ -875,12 +898,14 @@ struct file_struct *make_file(char *fnam
 	memset(bp, 0, file_struct_len);
 	bp += file_struct_len;
 
-	file->flags = flags;
+	FFLAGS(file) = flags;
 	file->modtime = st.st_mtime;
 	file->length = st.st_size;
 	file->mode = st.st_mode;
 	file->uid = st.st_uid;
 	file->gid = st.st_gid;
+	if (preserve_atimes)
+		file->atime = st.st_atime;
 
 #ifdef SUPPORT_HARD_LINKS
 	if (flist && flist->hlink_pool) {
@@ -992,7 +1017,7 @@ static void send_if_directory(int f, str
 	char is_dot_dir = fbuf[ol-1] == '.' && (ol == 1 || fbuf[ol-2] == '/');
 
 	if (S_ISDIR(file->mode)
-	    && !(file->flags & FLAG_MOUNT_POINT) && f_name(file, fbuf)) {
+	    && !(FFLAGS(file) & FLAG_MOUNT_POINT) && f_name(file, fbuf)) {
 		void *save_filters;
 		unsigned int len = strlen(fbuf);
 		if (len > 1 && fbuf[len-1] == '/')
@@ -1570,8 +1595,9 @@ static void clean_flist(struct file_list
 			}
 			/* Make sure that if we unduplicate '.', that we don't
 			 * lose track of a user-specified top directory. */
-			flist->files[keep]->flags |= flist->files[drop]->flags
-						   & (FLAG_TOP_DIR|FLAG_DEL_HERE);
+			FFLAGS(flist->files[keep])
+			    |= FFLAGS(flist->files[drop])
+			     & (FLAG_TOP_DIR|FLAG_DEL_HERE);
 
 			clear_file(drop, flist);
 
@@ -1633,7 +1659,7 @@ static void output_flist(struct file_lis
 			file->dirname ? file->dirname : "",
 			file->dirname ? "/" : "", NS(file->basename),
 			S_ISDIR(file->mode) ? "/" : "", (int)file->mode,
-			(double)file->length, uidbuf, gidbuf, file->flags);
+			(double)file->length, uidbuf, gidbuf, FFLAGS(file));
 	}
 }
 
--- orig/generator.c	2006-01-25 17:15:12
+++ generator.c	2006-01-26 09:15:22
@@ -43,6 +43,7 @@ extern int preserve_perms;
 extern int preserve_uid;
 extern int preserve_gid;
 extern int preserve_times;
+extern int preserve_atimes;
 extern int omit_dir_times;
 extern int delete_before;
 extern int delete_during;
@@ -89,6 +90,7 @@ extern dev_t filesystem_dev;
 extern char *backup_dir;
 extern char *backup_suffix;
 extern int backup_suffix_len;
+extern unsigned int file_struct_len;
 extern struct file_list *the_file_list;
 extern struct filter_list_struct server_filter_list;
 
@@ -183,7 +185,7 @@ static int delete_item(char *fname, int 
 	for (j = dirlist->count; j--; ) {
 		struct file_struct *fp = dirlist->files[j];
 
-		if (fp->flags & FLAG_MOUNT_POINT)
+		if (FFLAGS(fp) & FLAG_MOUNT_POINT)
 			continue;
 
 		strlcpy(p, fp->basename, remainder);
@@ -261,7 +263,7 @@ static void delete_in_dir(struct file_li
 	filt_array[cur_depth] = push_local_filters(fbuf, dlen);
 
 	if (one_file_system) {
-		if (file->flags & FLAG_TOP_DIR)
+		if (FFLAGS(file) & FLAG_TOP_DIR)
 			filesystem_dev = stp->st_dev;
 		else if (filesystem_dev != stp->st_dev)
 			return;
@@ -273,7 +275,7 @@ static void delete_in_dir(struct file_li
 	 * from the filesystem. */
 	for (i = dirlist->count; i--; ) {
 		struct file_struct *fp = dirlist->files[i];
-		if (!fp->basename || fp->flags & FLAG_MOUNT_POINT)
+		if (!fp->basename || FFLAGS(fp) & FLAG_MOUNT_POINT)
 			continue;
 		if (flist_find(flist, fp) < 0) {
 			int mode = fp->mode;
@@ -300,11 +302,11 @@ static void do_delete_pass(struct file_l
 	for (j = 0; j < flist->count; j++) {
 		struct file_struct *file = flist->files[j];
 
-		if (!(file->flags & FLAG_DEL_HERE))
+		if (!(FFLAGS(file) & FLAG_DEL_HERE))
 			continue;
 
 		f_name(file, fbuf);
-		if (verbose > 1 && file->flags & FLAG_TOP_DIR)
+		if (verbose > 1 && FFLAGS(file) & FLAG_TOP_DIR)
 			rprintf(FINFO, "deleting in %s\n", fbuf);
 
 		if (link_stat(fbuf, &st, keep_dirlinks) < 0
@@ -346,8 +348,11 @@ void itemize(struct file_struct *file, i
 			iflags |= ITEM_REPORT_SIZE;
 		if ((iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !keep_time
 		     && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
-		    || (keep_time && cmp_modtime(file->modtime, st->st_mtime) != 0))
+		    || (keep_time && cmp_time(file->modtime, st->st_mtime) != 0))
 			iflags |= ITEM_REPORT_TIME;
+		if (preserve_atimes && !S_ISDIR(file->mode) && !S_ISLNK(file->mode)
+		 && cmp_time(file->atime, st->st_atime) != 0)
+			iflags |= ITEM_REPORT_ATIME;
 		if (preserve_perms
 		 && (file->mode & CHMOD_BITS) != (st->st_mode & CHMOD_BITS))
 			iflags |= ITEM_REPORT_PERMS;
@@ -396,7 +401,7 @@ int unchanged_file(char *fn, struct file
 	if (ignore_times)
 		return 0;
 
-	return cmp_modtime(st->st_mtime, file->modtime) == 0;
+	return cmp_time(st->st_mtime, file->modtime) == 0;
 }
 
 
@@ -550,13 +555,13 @@ static int find_fuzzy(struct file_struct
 		uint32 dist;
 
 		if (!S_ISREG(fp->mode) || !fp->length
-		    || fp->flags & FLAG_NO_FUZZY)
+		    || FFLAGS(fp) & FLAG_NO_FUZZY)
 			continue;
 
 		name = fp->basename;
 
 		if (fp->length == file->length
-		    && cmp_modtime(fp->modtime, file->modtime) == 0) {
+		    && cmp_time(fp->modtime, file->modtime) == 0) {
 			if (verbose > 4) {
 				rprintf(FINFO,
 					"fuzzy size/modtime match for %s\n",
@@ -632,7 +637,7 @@ static int try_dests_reg(struct file_str
 			if (!unchanged_attrs(file, stp))
 				continue;
 			if ((always_checksum || ignore_times)
-			 && cmp_modtime(stp->st_mtime, file->modtime))
+			 && cmp_time(stp->st_mtime, file->modtime))
 				continue;
 			best_match = j;
 			match_level = 3;
@@ -659,6 +664,8 @@ static int try_dests_reg(struct file_str
 					  itemizing && verbose > 1,
 					  code) < 0)
 				goto try_a_copy;
+			if (preserve_atimes)
+				set_perms(fname, file, stp, 0);
 			if (preserve_hard_links && file->link_u.links)
 				hard_link_cluster(file, ndx, itemizing, code);
 		} else if (itemizing)
@@ -894,7 +901,7 @@ static void recv_generator(char *fname, 
 		    && verbose && code && f_out != -1)
 			rprintf(code, "%s/\n", fname);
 		if (delete_during && f_out != -1 && !phase && dry_run < 2
-		    && (file->flags & FLAG_DEL_HERE))
+		    && (FFLAGS(file) & FLAG_DEL_HERE))
 			delete_in_dir(the_file_list, fname, file, &st);
 		return;
 	}
@@ -1071,7 +1078,7 @@ static void recv_generator(char *fname, 
 	}
 
 	if (update_only && statret == 0
-	    && cmp_modtime(st.st_mtime, file->modtime) > 0) {
+	    && cmp_time(st.st_mtime, file->modtime) > 0) {
 		if (verbose > 1)
 			rprintf(FINFO, "%s is newer\n", fname);
 		return;
@@ -1174,7 +1181,7 @@ static void recv_generator(char *fname, 
 	if (fuzzy_basis) {
 		int j = flist_find(fuzzy_dirlist, file);
 		if (j >= 0) /* don't use changing file as future fuzzy basis */
-			fuzzy_dirlist->files[j]->flags |= FLAG_NO_FUZZY;
+			FFLAGS(fuzzy_dirlist->files[j]) |= FLAG_NO_FUZZY;
 	}
 
 	/* open the file */
--- orig/hlink.c	2006-01-14 20:27:09
+++ hlink.c	2006-01-24 19:17:58
@@ -26,6 +26,7 @@ extern int link_dest;
 extern int make_backups;
 extern int log_format_has_i;
 extern char *basis_dir[];
+extern unsigned int file_struct_len;
 extern struct file_list *the_file_list;
 
 #ifdef SUPPORT_HARD_LINKS
@@ -86,10 +87,10 @@ static void link_idev_data(void)
 			FPTR(cur)->link_u.links = pool_talloc(hlink_pool,
 			    struct hlink, 1, "hlink_list");
 
-			FPTR(head)->flags |= FLAG_HLINK_TOL;
+			FFLAGS(FPTR(head)) |= FLAG_HLINK_TOL;
 			FPTR(cur)->F_HLINDEX = to;
 			FPTR(cur)->F_NEXT = head;
-			FPTR(cur)->flags |= FLAG_HLINK_EOL;
+			FFLAGS(FPTR(cur)) |= FLAG_HLINK_EOL;
 			hlink_list[to++] = head;
 		} else
 			FPTR(cur)->link_u.links = NULL;
@@ -175,7 +176,7 @@ int hard_link_check(struct file_struct *
 {
 #ifdef SUPPORT_HARD_LINKS
 	int head;
-	if (skip && !(file->flags & FLAG_HLINK_EOL))
+	if (skip && !(FFLAGS(file) & FLAG_HLINK_EOL))
 		head = hlink_list[file->F_HLINDEX] = file->F_NEXT;
 	else
 		head = hlink_list[file->F_HLINDEX];
@@ -270,8 +271,8 @@ void hard_link_cluster(struct file_struc
 	file->F_HLINDEX = FINISHED_LINK;
 	if (link_stat(f_name(file, hlink1), &st1, 0) < 0)
 		return;
-	if (!(file->flags & FLAG_HLINK_TOL)) {
-		while (!(file->flags & FLAG_HLINK_EOL)) {
+	if (!(FFLAGS(file) & FLAG_HLINK_TOL)) {
+		while (!(FFLAGS(file) & FLAG_HLINK_EOL)) {
 			ndx = file->F_NEXT;
 			file = FPTR(ndx);
 		}
@@ -286,6 +287,6 @@ void hard_link_cluster(struct file_struc
 		maybe_hard_link(file, ndx, hlink2, statret, &st2,
 				hlink1, &st1, itemizing, code);
 		file->F_HLINDEX = FINISHED_LINK;
-	} while (!(file->flags & FLAG_HLINK_EOL));
+	} while (!(FFLAGS(file) & FLAG_HLINK_EOL));
 #endif
 }
--- orig/log.c	2006-01-24 22:24:32
+++ log.c	2006-01-24 22:50:01
@@ -38,6 +38,7 @@ extern int module_id;
 extern int msg_fd_out;
 extern int protocol_version;
 extern int preserve_times;
+extern int preserve_atimes;
 extern int log_format_has_i;
 extern int log_format_has_o_or_i;
 extern int daemon_log_format_has_o_or_i;
@@ -542,10 +543,12 @@ static void log_formatted(enum logcode c
 			n[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
 			n[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
 			     : !preserve_times || S_ISLNK(file->mode) ? 'T' : 't';
-			n[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
-			n[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
-			n[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
-			n[8] = '\0';
+			n[5] = !(iflags & ITEM_REPORT_ATIME) ? '.'
+			     : S_ISLNK(file->mode) ? 'U' : 'u';
+			n[6] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
+			n[7] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
+			n[8] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
+			n[9] = '\0';
 
 			if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) {
 				char ch = iflags & ITEM_IS_NEW ? '+' : '?';
--- orig/options.c	2006-01-23 18:48:23
+++ options.c	2006-01-24 22:53:18
@@ -50,6 +50,7 @@ int preserve_uid = 0;
 int preserve_gid = 0;
 int preserve_times = 0;
 int omit_dir_times = 0;
+int preserve_atimes = 0;
 int update_only = 0;
 int cvs_exclude = 0;
 int dry_run = 0;
@@ -291,8 +292,9 @@ void usage(enum logcode F)
   rprintf(F," -o, --owner                 preserve owner (root only)\n");
   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," -O, --omit-dir-times        omit directories when preserving times\n");
+  rprintf(F," -t, --times                 preserve modify times\n");
+  rprintf(F," -O, --omit-dir-times        omit directories when preserving modify times\n");
+  rprintf(F," -U, --atimes                preserve access (use) times\n");
   rprintf(F,"     --chmod=CHMOD           change destination permissions\n");
   rprintf(F," -S, --sparse                handle sparse files efficiently\n");
   rprintf(F," -n, --dry-run               show what would have been transferred\n");
@@ -400,6 +402,9 @@ static struct poptOption long_options[] 
   {"times",           't', POPT_ARG_VAL,    &preserve_times, 1, 0, 0 },
   {"no-times",         0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
   {"no-t",             0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
+  {"atimes",          'U', POPT_ARG_VAL,    &preserve_atimes, 1, 0, 0 },
+  {"no-atimes",        0,  POPT_ARG_VAL,    &preserve_atimes, 0, 0, 0 },
+  {"no-k",             0,  POPT_ARG_VAL,    &preserve_atimes, 0, 0, 0 },
   {"omit-dir-times",  'O', POPT_ARG_VAL,    &omit_dir_times, 2, 0, 0 },
   {"modify-window",    0,  POPT_ARG_INT,    &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
   {"owner",           'o', POPT_ARG_VAL,    &preserve_uid, 1, 0, 0 },
@@ -1468,6 +1473,8 @@ void server_options(char **args,int *arg
 		argstr[x++] = 'D';
 	if (preserve_times)
 		argstr[x++] = 't';
+	if (preserve_atimes)
+		argstr[x++] = 'U';
 	if (omit_dir_times == 2 && am_sender)
 		argstr[x++] = 'O';
 	if (preserve_perms)
--- orig/rsync.c	2006-01-25 17:15:12
+++ rsync.c	2006-01-26 09:19:43
@@ -27,6 +27,7 @@ extern int dry_run;
 extern int daemon_log_format_has_i;
 extern int preserve_times;
 extern int omit_dir_times;
+extern int preserve_atimes;
 extern int am_root;
 extern int am_server;
 extern int am_sender;
@@ -56,6 +57,7 @@ int set_perms(char *fname,struct file_st
 	int updated = 0;
 	STRUCT_STAT st2;
 	int change_uid, change_gid;
+	time_t atime, mtime;
 
 	if (!st) {
 		if (dry_run)
@@ -68,18 +70,33 @@ int set_perms(char *fname,struct file_st
 		st = &st2;
 	}
 
+	/* This code must be the first update in the function due to
+	 * how it uses the "updated" variable. */
 	if (!preserve_times || (S_ISDIR(st->st_mode) && omit_dir_times))
 		flags |= PERMS_SKIP_MTIME;
+	if (!preserve_atimes || S_ISDIR(st->st_mode))
+		flags |= PERMS_SKIP_ATIME;
 	if (!(flags & PERMS_SKIP_MTIME)
-	    && cmp_modtime(st->st_mtime, file->modtime) != 0) {
-		int ret = set_modtime(fname, file->modtime, st->st_mode);
+	    && cmp_time(st->st_mtime, file->modtime) != 0) {
+		mtime = file->modtime;
+		updated = 1;
+	} else
+		mtime = st->st_mtime;
+	if (!(flags & PERMS_SKIP_ATIME)
+	    && cmp_time(st->st_atime, file->atime) != 0) {
+		atime = file->atime;
+		updated = 1;
+	} else
+		atime = st->st_atime;
+	if (updated) {
+		int ret = set_times(fname, mtime, atime, st->st_mode);
 		if (ret < 0) {
 			rsyserr(FERROR, errno, "failed to set times on %s",
 				full_fname(fname));
 			return 0;
 		}
-		if (ret == 0) /* ret == 1 if symlink could not be set */
-			updated = 1;
+		if (ret > 0) /* ret == 1 if symlink could not be set */
+			updated = 0;
 	}
 
 	change_uid = am_root && preserve_uid && st->st_uid != file->uid;
--- orig/rsync.h	2006-01-25 17:34:58
+++ rsync.h	2006-01-24 22:38:08
@@ -54,6 +54,7 @@
 #define XMIT_HAS_IDEV_DATA (1<<9)
 #define XMIT_SAME_DEV (1<<10)
 #define XMIT_RDEV_MINOR_IS_SMALL (1<<11)
+#define XMIT_SAME_ATIME (1<<12)
 
 /* These flags are used in the live flist data. */
 
@@ -119,6 +120,7 @@
 
 #define PERMS_REPORT		(1<<0)
 #define PERMS_SKIP_MTIME	(1<<1)
+#define PERMS_SKIP_ATIME	(1<<2)
 
 #define FULL_FLUSH	1
 #define NORMAL_FLUSH	0
@@ -135,6 +137,7 @@
 #define FNAMECMP_FUZZY		0x83
 
 /* For use by the itemize_changes code */
+#define ITEM_REPORT_ATIME (1<<0)
 #define ITEM_REPORT_CHECKSUM (1<<1)
 #define ITEM_REPORT_SIZE (1<<2)
 #define ITEM_REPORT_TIME (1<<3)
@@ -520,9 +523,12 @@ struct file_struct {
 	uid_t uid;
 	gid_t gid;
 	mode_t mode;
-	uchar flags;	/* this item MUST remain last */
+	time_t atime;   /* this MUST be second to last */
+	uchar fl4g5;	/* this item MUST remain last */
 };
 
+#define FFLAGS(f) ((uchar*)(f))[file_struct_len-1]
+
 /*
  * Start the flist array at FLIST_START entries and grow it
  * by doubling until FLIST_LINEAR then grow by FLIST_LINEAR
--- orig/rsync.yo	2006-01-24 22:19:58
+++ rsync.yo	2006-01-24 22:54:23
@@ -319,8 +319,9 @@ to the detailed description below for a 
  -o, --owner                 preserve owner (root only)
  -g, --group                 preserve group
  -D, --devices               preserve devices (root only)
- -t, --times                 preserve times
- -O, --omit-dir-times        omit directories when preserving times
+ -t, --times                 preserve modify times
+ -O, --omit-dir-times        omit directories when preserving mod-times
+ -U, --atimes                preserve access (use) times
      --chmod=CHMOD           change destination permissions
  -S, --sparse                handle sparse files efficiently
  -n, --dry-run               show what would have been transferred
@@ -711,6 +712,12 @@ it is preserving modification times (see
 the directories on the receiving side, it is a good idea to use bf(-O).
 This option is inferred if you use bf(--backup) without bf(--backup-dir).
 
+dit(bf(-U, --atimes)) This tells rsync to set the access (use) times of the
+destination files to the same value as the source files.  Note that the
+reading of the source file may update the atime of the source files, so
+repeated rsync runs with --atimes may be needed if you want to force the
+access-time values to be 100% identical on the two systems.
+
 dit(bf(--chmod)) This options tells rsync to apply the listed "chmod" pattern
 to the permission of the files on the destination.  In addition to the normal
 parsing rules specified in the chmod manpage, you can specify an item that
@@ -1219,9 +1226,13 @@ quote(itemize(
   by the file transfer.
   it() A bf(t) means the modification time is different and is being updated
   to the sender's value (requires bf(--times)).  An alternate value of bf(T)
-  means that the time will be set to the transfer time, which happens
+  means that the modify time will be set to the transfer time, which happens
   anytime a symlink is transferred, or when a file or device is transferred
   without bf(--times).
+  it() A bf(u) means the access (use) time is different and is being updated to
+  the sender's value (requires bf(--atimes)).  An alternate value of bf(U)
+  means that the access time will be set to the transfer time, which happens
+  anytime a symlink is transferred.
   it() A bf(p) means the permissions are different and are being updated to
   the sender's value (requires bf(--perms)).
   it() An bf(o) means the owner is different and is being updated to the
--- orig/sender.c	2006-01-14 20:27:10
+++ sender.c	2006-01-24 18:10:23
@@ -38,6 +38,7 @@ extern int do_progress;
 extern int inplace;
 extern int batch_fd;
 extern int write_batch;
+extern unsigned int file_struct_len;
 extern struct stats stats;
 extern struct file_list *the_file_list;
 extern char *log_format;
@@ -126,7 +127,7 @@ void successful_send(int ndx)
 
 	file = the_file_list->files[ndx];
 	/* The generator might tell us about symlinks we didn't send. */
-	if (!(file->flags & FLAG_SENT) && !S_ISLNK(file->mode))
+	if (!(FFLAGS(file) & FLAG_SENT) && !S_ISLNK(file->mode))
 		return;
 	if (file->dir.root) {
 		offset = stringjoin(fname, sizeof fname,
@@ -370,7 +371,7 @@ void send_files(struct file_list *flist,
 			rprintf(FINFO, "sender finished %s\n", fname);
 
 		/* Flag that we actually sent this entry. */
-		file->flags |= FLAG_SENT;
+		FFLAGS(file) |= FLAG_SENT;
 	}
 	make_backups = save_make_backups;
 
--- orig/testsuite/atimes.test	2006-01-24 22:54:53
+++ testsuite/atimes.test	2006-01-24 22:54:53
@@ -0,0 +1,19 @@
+#! /bin/sh
+
+# Test rsync copying atimes
+
+. "$suitedir/rsync.fns"
+
+set -x
+
+mkdir "$fromdir"
+
+touch "$fromdir/foo"
+touch -a -t 200102031717.42 "$fromdir/foo"
+
+TLS_ARGS=--atime
+
+checkit "$RSYNC -rtUgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
+
+# The script would have aborted on error, so getting here means we've won.
+exit 0
--- orig/testsuite/devices.test	2006-01-24 22:24:32
+++ testsuite/devices.test	2006-01-24 22:32:30
@@ -55,14 +55,14 @@ touch -r "$fromdir/block" "$fromdir/bloc
 $RSYNC -ai "$fromdir/block" "$todir/block2" \
     | tee "$outfile"
 cat <<EOT >"$chkfile"
-cD++++++ block
+cD+++++++ block
 EOT
 diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
 
 $RSYNC -ai "$fromdir/block2" "$todir/block" \
     | tee "$outfile"
 cat <<EOT >"$chkfile"
-cD++++++ block2
+cD+++++++ block2
 EOT
 diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
 
@@ -71,7 +71,7 @@ sleep 1
 $RSYNC -Di "$fromdir/block3" "$todir/block" \
     | tee "$outfile"
 cat <<EOT >"$chkfile"
-cD..T... block3
+cD..T.... block3
 EOT
 diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
 
@@ -79,15 +79,15 @@ $RSYNC -aiHvv "$fromdir/" "$todir/" \
     | tee "$outfile"
 filter_outfile
 cat <<EOT >"$chkfile"
-.d..t... ./
-cD..t... block
-cD...... block2
-cD++++++ block3
-hD++++++ block2.5 => block3
-cD++++++ char
-cD++++++ char2
-cD++++++ char3
-cD++++++ fifo
+.d..t.... ./
+cD..t.... block
+cD....... block2
+cD+++++++ block3
+hD+++++++ block2.5 => block3
+cD+++++++ char
+cD+++++++ char2
+cD+++++++ char3
+cD+++++++ fifo
 EOT
 if test ! -b "$fromdir/block2.5"; then
     sed -e '/block2\.5/d' \
--- orig/testsuite/itemize.test	2006-01-24 22:24:32
+++ testsuite/itemize.test	2006-01-24 22:32:03
@@ -44,14 +44,14 @@ ln "$fromdir/foo/config1" "$fromdir/foo/
 $RSYNC -iplr "$fromdir/" "$todir/" \
     | tee "$outfile"
 cat <<EOT >"$chkfile"
-cd++++++ bar/
-cd++++++ bar/baz/
->f++++++ bar/baz/rsync
-cd++++++ foo/
->f++++++ foo/config1
->f++++++ foo/config2
->f++++++ foo/extra
-cL++++++ foo/sym -> ../bar/baz/rsync
+cd+++++++ bar/
+cd+++++++ bar/baz/
+>f+++++++ bar/baz/rsync
+cd+++++++ foo/
+>f+++++++ foo/config1
+>f+++++++ foo/config2
+>f+++++++ foo/extra
+cL+++++++ foo/sym -> ../bar/baz/rsync
 EOT
 diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
 
@@ -63,10 +63,10 @@ chmod 601 "$fromdir/foo/config2"
 $RSYNC -iplrH "$fromdir/" "$todir/" \
     | tee "$outfile"
 cat <<EOT >"$chkfile"
->f..T... bar/baz/rsync
->f..T... foo/config1
->f.sTp.. foo/config2
-hf..T... foo/extra => foo/config1
+>f..T.... bar/baz/rsync
+>f..T.... foo/config1
+>f.sT.p.. foo/config2
+hf..T.... foo/extra => foo/config1
 EOT
 diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
 
@@ -83,11 +83,11 @@ chmod 777 "$todir/bar/baz/rsync"
 $RSYNC -iplrtc "$fromdir/" "$todir/" \
     | tee "$outfile"
 cat <<EOT >"$chkfile"
-.f..tp.. bar/baz/rsync
-.d..t... foo/
-.f..t... foo/config1
->fcstp.. foo/config2
-cL..T... foo/sym -> ../bar/baz/rsync
+.f..t.p.. bar/baz/rsync
+.d..t.... foo/
+.f..t.... foo/config1
+>fcst.p.. foo/config2
+cL..T.... foo/sym -> ../bar/baz/rsync
 EOT
 diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
 
@@ -112,15 +112,15 @@ $RSYNC -ivvplrtH "$fromdir/" "$todir/" \
     | tee "$outfile"
 filter_outfile
 cat <<EOT >"$chkfile"
-.d       ./
-.d       bar/
-.d       bar/baz/
-.f...p.. bar/baz/rsync
-.d       foo/
-.f       foo/config1
->f..t... foo/config2
-hf       foo/extra
-.L       foo/sym -> ../bar/baz/rsync
+.d        ./
+.d        bar/
+.d        bar/baz/
+.f....p.. bar/baz/rsync
+.d        foo/
+.f        foo/config1
+>f..t.... foo/config2
+hf        foo/extra
+.L        foo/sym -> ../bar/baz/rsync
 EOT
 diff $diffopt "$chkfile" "$outfile" || test_fail "test 5 failed"
 
@@ -139,8 +139,8 @@ touch "$todir/foo/config2"
 $RSYNC -iplrtH "$fromdir/" "$todir/" \
     | tee "$outfile"
 cat <<EOT >"$chkfile"
-.f...p.. foo/config1
->f..t... foo/config2
+.f....p.. foo/config1
+>f..t.... foo/config2
 EOT
 diff $diffopt "$chkfile" "$outfile" || test_fail "test 7 failed"
 
@@ -149,15 +149,15 @@ $RSYNC -ivvplrtH --copy-dest="$lddir" "$
     | tee "$outfile"
 filter_outfile
 cat <<EOT >"$chkfile"
-.d..t... ./
-cd++++++ bar/
-cd++++++ bar/baz/
-cf       bar/baz/rsync
-cd++++++ foo/
-cf       foo/config1
-cf       foo/config2
-hf       foo/extra => foo/config1
-cL..T... foo/sym -> ../bar/baz/rsync
+.d..t.... ./
+cd+++++++ bar/
+cd+++++++ bar/baz/
+cf        bar/baz/rsync
+cd+++++++ foo/
+cf        foo/config1
+cf        foo/config2
+hf        foo/extra => foo/config1
+cL..T.... foo/sym -> ../bar/baz/rsync
 EOT
 diff $diffopt "$chkfile" "$outfile" || test_fail "test 8 failed"
 
@@ -165,11 +165,11 @@ rm -rf "$todir"
 $RSYNC -iplrtH --copy-dest="$lddir" "$fromdir/" "$todir/" \
     | tee "$outfile"
 cat <<EOT >"$chkfile"
-.d..t... ./
-cd++++++ bar/
-cd++++++ bar/baz/
-cd++++++ foo/
-hf       foo/extra => foo/config1
+.d..t.... ./
+cd+++++++ bar/
+cd+++++++ bar/baz/
+cd+++++++ foo/
+hf        foo/extra => foo/config1
 EOT
 diff $diffopt "$chkfile" "$outfile" || test_fail "test 9 failed"
 
@@ -196,15 +196,15 @@ $RSYNC -ivvplrtH --link-dest="$lddir" "$
     | tee "$outfile"
 filter_outfile
 cat <<EOT >"$chkfile"
-.d..t... ./
-cd++++++ bar/
-cd++++++ bar/baz/
-hf       bar/baz/rsync
-cd++++++ foo/
-hf       foo/config1
-hf       foo/config2
-hf       foo/extra => foo/config1
-hL       foo/sym -> ../bar/baz/rsync
+.d..t.... ./
+cd+++++++ bar/
+cd+++++++ bar/baz/
+hf        bar/baz/rsync
+cd+++++++ foo/
+hf        foo/config1
+hf        foo/config2
+hf        foo/extra => foo/config1
+hL        foo/sym -> ../bar/baz/rsync
 EOT
 diff $diffopt "$chkfile" "$outfile" || test_fail "test 11 failed"
 
@@ -212,10 +212,10 @@ rm -rf "$todir"
 $RSYNC -iplrtH --link-dest="$lddir" "$fromdir/" "$todir/" \
     | tee "$outfile"
 cat <<EOT >"$chkfile"
-.d..t... ./
-cd++++++ bar/
-cd++++++ bar/baz/
-cd++++++ foo/
+.d..t.... ./
+cd+++++++ bar/
+cd+++++++ bar/baz/
+cd+++++++ foo/
 EOT
 diff $diffopt "$chkfile" "$outfile" || test_fail "test 12 failed"
 
@@ -243,14 +243,14 @@ filter_outfile
 # TODO fix really-old problem when combining -H with --compare-dest:
 # missing output for foo/extra hard-link (and it might not be updated)!
 cat <<EOT >"$chkfile"
-.d..t... ./
-cd++++++ bar/
-cd++++++ bar/baz/
-.f       bar/baz/rsync
-cd++++++ foo/
-.f       foo/config1
-.f       foo/config2
-.L       foo/sym -> ../bar/baz/rsync
+.d..t.... ./
+cd+++++++ bar/
+cd+++++++ bar/baz/
+.f        bar/baz/rsync
+cd+++++++ foo/
+.f        foo/config1
+.f        foo/config2
+.L        foo/sym -> ../bar/baz/rsync
 EOT
 diff $diffopt "$chkfile" "$outfile" || test_fail "test 14 failed"
 
@@ -258,10 +258,10 @@ rm -rf "$todir"
 $RSYNC -iplrtH --compare-dest="$lddir" "$fromdir/" "$todir/" \
     | tee "$outfile"
 cat <<EOT >"$chkfile"
-.d..t... ./
-cd++++++ bar/
-cd++++++ bar/baz/
-cd++++++ foo/
+.d..t.... ./
+cd+++++++ bar/
+cd+++++++ bar/baz/
+cd+++++++ foo/
 EOT
 diff $diffopt "$chkfile" "$outfile" || test_fail "test 15 failed"
 
--- orig/testsuite/rsync.fns	2005-06-10 21:33:28
+++ testsuite/rsync.fns	2005-07-28 00:41:20
@@ -50,7 +50,7 @@ printmsg() {
 
 
 rsync_ls_lR() {
-    find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls"
+    find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls" $TLS_ARGS
 }
 
 rsync_getgroups() { 
@@ -158,6 +158,10 @@ checkit() {
     # We can just write everything to stdout/stderr, because the
     # wrapper hides it unless there is a problem.
 
+    if test x$TLS_ARGS = x--atime; then
+	( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
+    fi
+
     echo "Running: \"$1\""  
     eval "$1" 
     status=$?
@@ -165,10 +169,13 @@ checkit() {
 	failed="YES";
     fi
 
+    if test x$TLS_ARGS != x--atime; then
+	( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
+    fi
+
     echo "-------------"
     echo "check how the directory listings compare with diff:"
     echo ""
-    ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
     ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
     diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
 
--- orig/tls.c	2005-09-24 17:40:31
+++ tls.c	2005-03-23 17:49:48
@@ -39,6 +39,7 @@
 
 
 #include "rsync.h"
+#include "popt.h"
 
 #define PROGRAM "tls"
 
@@ -48,6 +49,7 @@ int read_only = 1;
 int list_only = 0;
 int preserve_perms = 0;
 
+static int display_atime = 0;
 
 static void failed(char const *what, char const *where)
 {
@@ -56,14 +58,29 @@ static void failed(char const *what, cha
 	exit(1);
 }
 
+static void storetime(char *dest, time_t t)
+{
+	if (t) {
+		struct tm *mt = gmtime(&t);
 
+		sprintf(dest, "%04d-%02d-%02d %02d:%02d:%02d ",
+			(int)mt->tm_year + 1900,
+			(int)mt->tm_mon + 1,
+			(int)mt->tm_mday,
+			(int)mt->tm_hour,
+			(int)mt->tm_min,
+			(int)mt->tm_sec);
+	} else {
+		strcpy(dest, "                    ");
+	}
+}	
 
 static void list_file(const char *fname)
 {
 	STRUCT_STAT buf;
 	char permbuf[PERMSTRING_SIZE];
-	struct tm *mt;
-	char datebuf[50];
+	char mtimebuf[50];
+	char atimebuf[50];
 	char linkbuf[4096];
 
 	if (do_lstat(fname, &buf) < 0)
@@ -96,19 +113,8 @@ static void list_file(const char *fname)
 
 	permstring(permbuf, buf.st_mode);
 
-	if (buf.st_mtime) {
-		mt = gmtime(&buf.st_mtime);
-
-		sprintf(datebuf, "%04d-%02d-%02d %02d:%02d:%02d",
-			(int)mt->tm_year + 1900,
-			(int)mt->tm_mon + 1,
-			(int)mt->tm_mday,
-			(int)mt->tm_hour,
-			(int)mt->tm_min,
-			(int)mt->tm_sec);
-	} else {
-		strcpy(datebuf, "                   ");
-	}
+	storetime(mtimebuf, buf.st_mtime);
+	storetime(atimebuf, buf.st_atime);
 
 	/* TODO: Perhaps escape special characters in fname? */
 
@@ -119,24 +125,55 @@ static void list_file(const char *fname)
 		    (long)minor(buf.st_rdev));
 	} else /* NB: use double for size since it might not fit in a long. */
 		printf("%12.0f", (double)buf.st_size);
-	printf(" %6ld.%-6ld %6ld %s %s%s\n",
+	printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
 	       (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
-	       datebuf, fname, linkbuf);
+ 	       mtimebuf, display_atime && !S_ISDIR(buf.st_mode) ? atimebuf : "",
+	       fname, linkbuf);
 }
 
+static struct poptOption long_options[] = {
+  /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
+  {"atime",           'u', POPT_ARG_NONE,   &display_atime, 0,   0, 0},
+  {"help",            'h', POPT_ARG_NONE,   0,              'h', 0, 0},
+  {0,0,0,0,0,0,0}
+};
+
+static void tls_usage(int ret)
+{
+	fprintf(stderr, "usage: " PROGRAM " [--atime | -u] DIR ...\n"
+	    "Trivial file listing program for portably checking rsync\n");
+	exit(ret);
+}
 
 int
 main(int argc, char *argv[])
 {
-	if (argc < 2) {
-		fprintf(stderr, "usage: " PROGRAM " DIR ...\n"
-			"Trivial file listing program for portably checking rsync\n");
-		return 1;
+	poptContext pc;
+	const char **extra_args;
+	int opt;
+
+	pc = poptGetContext(PROGRAM, argc, (const char **)argv,
+			    long_options, 0);
+	while ((opt = poptGetNextOpt(pc)) != -1) {
+		switch (opt) {
+		case 'h':
+			tls_usage(0);
+		default:
+			fprintf(stderr,
+			        "%s: %s\n",
+				poptBadOption(pc, POPT_BADOPTION_NOALIAS),
+				poptStrerror(opt));
+			tls_usage(1);
+		}
 	}
 
-	for (argv++; *argv; argv++) {
-		list_file(*argv);
-	}
+	extra_args = poptGetArgs(pc);
+	if (*extra_args == NULL)
+		tls_usage(1);
+
+	for (; *extra_args; extra_args++)
+		list_file(*extra_args);
+	poptFreeContext(pc);
 
 	return 0;
 }
--- orig/util.c	2006-01-20 00:12:48
+++ util.c	2006-01-14 08:20:29
@@ -130,7 +130,7 @@ void overflow_exit(char *str)
 
 
 
-int set_modtime(char *fname, time_t modtime, mode_t mode)
+int set_times(char *fname, time_t modtime, time_t atime, mode_t mode)
 {
 #if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
 	if (S_ISLNK(mode))
@@ -138,9 +138,13 @@ int set_modtime(char *fname, time_t modt
 #endif
 
 	if (verbose > 2) {
-		rprintf(FINFO, "set modtime of %s to (%ld) %s",
+		char mtimebuf[200];
+
+		strlcpy(mtimebuf, timestring(modtime), sizeof mtimebuf);
+		rprintf(FINFO,
+			"set modtime, atime of %s to (%ld) %s, (%ld) %s\n",
 			fname, (long)modtime,
-			asctime(localtime(&modtime)));
+			mtimebuf, (long)atime, timestring(atime));
 	}
 
 	if (dry_run)
@@ -149,7 +153,7 @@ int set_modtime(char *fname, time_t modt
 	{
 #ifdef HAVE_UTIMES
 		struct timeval t[2];
-		t[0].tv_sec = time(NULL);
+		t[0].tv_sec = atime;
 		t[0].tv_usec = 0;
 		t[1].tv_sec = modtime;
 		t[1].tv_usec = 0;
@@ -160,12 +164,12 @@ int set_modtime(char *fname, time_t modt
 		return utimes(fname, t);
 #elif defined HAVE_UTIMBUF
 		struct utimbuf tbuf;
-		tbuf.actime = time(NULL);
+		tbuf.actime = atime;
 		tbuf.modtime = modtime;
 		return utime(fname,&tbuf);
 #elif defined HAVE_UTIME
 		time_t t[2];
-		t[0] = time(NULL);
+		t[0] = atime;
 		t[1] = modtime;
 		return utime(fname,t);
 #else
@@ -1175,8 +1179,8 @@ int msleep(int t)
 
 
 /**
- * Determine if two file modification times are equivalent (either
- * exact or in the modification timestamp window established by
+ * Determine if two file  times are equivalent (either
+ * exact or in the timestamp window established by
  * --modify-window).
  *
  * @retval 0 if the times should be treated as the same
@@ -1185,7 +1189,7 @@ int msleep(int t)
  *
  * @retval -1 if the 2nd is later
  **/
-int cmp_modtime(time_t file1, time_t file2)
+int cmp_time(time_t file1, time_t file2)
 {
 	if (file2 > file1) {
 		if (file2 - file1 <= modify_window)
