Index: rsync/generator.c
--- rsync/generator.c	25 Jan 2002 10:42:23 -0000	1.32
+++ rsync/generator.c	30 Jan 2002 17:57:49 -0000
@@ -495,7 +495,7 @@
 	if (remote_version >= 13) {
 		/* in newer versions of the protocol the files can cycle through
 		   the system more than once to catch initial checksum errors */
-		for (i=read_int(f_recv); i != -1; i=read_int(f_recv)) {
+		while ((i = io_get_redo_item()) != -1) {
 			struct file_struct *file = flist->files[i];
 			recv_generator(local_name?local_name:f_name(file),
 				       flist,i,f);    
Index: rsync/io.c
--- rsync/io.c	25 Jan 2002 23:01:50 -0000	1.92
+++ rsync/io.c	30 Jan 2002 17:57:49 -0000
@@ -113,6 +113,72 @@
 	io_error_fd = fd;
 }
 
+#define R2GEN_REDO	1
+
+static char *r2gen_flags, r2gen_buf[4];
+static int r2gen_buflen, r2gen_fd = -1, r2gen_file_count;
+static int r2gen_redo_pos, r2gen_redo_item_count, r2gen_redo_eof;
+
+void io_monitor_r2gen_fd(int fd, int flist_file_count)
+{
+	r2gen_fd = fd;
+	if (fd >= 0) {
+		r2gen_flags = (char *)calloc(flist_file_count+1, sizeof (char));
+		if (!r2gen_flags) out_of_memory("io_monitor_r2gen_fd");
+		r2gen_file_count = r2gen_redo_pos = flist_file_count;
+	}
+}
+
+static void read_r2gen_fd(int wait_for_data)
+{
+	if (wait_for_data) {
+		read_loop(r2gen_fd, r2gen_buf + r2gen_buflen, 4 - r2gen_buflen);
+		r2gen_buflen = 4;
+	} else {
+		int n;
+		n = read(r2gen_fd, r2gen_buf + r2gen_buflen, 4 - r2gen_buflen);
+		if (n < 0)
+			return;
+		r2gen_buflen += n;
+	}
+	if (r2gen_buflen == 4) {
+		int32 j = IVAL(r2gen_buf,0);
+		if (j == (int32)0xffffffff)
+			r2gen_redo_eof++;
+		else if (j >= 0 && j <= r2gen_file_count) {
+			if (!(r2gen_flags[j] & R2GEN_REDO)) {
+				r2gen_flags[j] |= R2GEN_REDO;
+				r2gen_redo_item_count++;
+			}
+		}
+		r2gen_buflen = 0;
+	}
+}
+
+int io_get_redo_item(void)
+{
+	int start_pos = r2gen_redo_pos;
+	io_flush();
+	while (!r2gen_redo_item_count) {
+		if (r2gen_redo_eof) {
+			r2gen_redo_eof--;
+			return -1;
+		}
+		read_r2gen_fd(1);
+	}
+	if (start_pos == 0)
+	    start_pos = r2gen_file_count+1;
+	for (r2gen_redo_pos++; r2gen_redo_pos != start_pos; r2gen_redo_pos++) {
+		if (r2gen_redo_pos > r2gen_file_count)
+			r2gen_redo_pos = 0;
+		if (r2gen_flags[r2gen_redo_pos] & R2GEN_REDO) {
+			r2gen_flags[r2gen_redo_pos] &= ~R2GEN_REDO;
+			r2gen_redo_item_count--;
+			return r2gen_redo_pos;
+		}
+	}
+	return -1; /* This is impossible... */
+}
 
 static void whine_about_eof (void)
 {
@@ -169,6 +235,14 @@
 	int n, ret=0;
 
 	io_flush();
+	if (fd == r2gen_fd && len == 4 && (r2gen_redo_item_count || r2gen_redo_eof)) {
+		/* The "background" r2gen-reading code has been active, so
+		 * just pretend we read a -3 (which will be ignored) and
+		 * return (since there may not be any more to read).  The
+		 * caller will make use of the cached value(s). */
+		SIVAL(buf,0,-3);
+		ret = 4;
+	}
 
 	while (ret == 0) {
 		/* until we manage to read *something* */
@@ -179,7 +253,7 @@
 
 		FD_ZERO(&fds);
 		FD_SET(fd, &fds);
-		if (io_error_fd != -1) {
+		if (io_error_fd != -1 && (fd != r2gen_fd || len == 4)) {
 			FD_SET(io_error_fd, &fds);
 			if (io_error_fd > fd) fd_count = io_error_fd+1;
 		}
@@ -204,6 +278,15 @@
 
 		if (io_error_fd != -1 && FD_ISSET(io_error_fd, &fds)) {
 			read_error_fd();
+			if (fd == r2gen_fd) {
+				if (r2gen_redo_item_count || r2gen_redo_eof) {
+					SIVAL(buf,0,-3);
+					buf += 4;
+					len -= 4;
+					ret += 4;
+				}
+				continue;
+			}
 		}
 
 		if (!FD_ISSET(fd, &fds)) continue;
@@ -400,6 +483,11 @@
 			if (io_error_fd > fd_count) 
 				fd_count = io_error_fd;
 		}
+		if (r2gen_fd != -1) {
+			FD_SET(r2gen_fd,&r_fds);
+			if (r2gen_fd > fd_count) 
+				fd_count = r2gen_fd;
+		}
 
 		tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
 		tv.tv_usec = 0;
@@ -422,6 +510,8 @@
 			continue;
 		}
 
+		if (r2gen_fd != -1 && FD_ISSET(r2gen_fd,&r_fds))
+			read_r2gen_fd(0);
 		if (io_error_fd != -1 && FD_ISSET(io_error_fd, &r_fds)) {
 			read_error_fd();
 		}
Index: rsync/main.c
--- rsync/main.c	25 Jan 2002 10:07:41 -0000	1.138
+++ rsync/main.c	30 Jan 2002 17:57:50 -0000
@@ -414,10 +414,12 @@
 	io_start_buffering(f_out);
 
 	io_set_error_fd(error_pipe[0]);
+	io_monitor_r2gen_fd(recv_pipe[0], flist->count);
 
 	generate_files(f_out,flist,local_name,recv_pipe[0]);
 
 	read_int(recv_pipe[0]);
+	io_monitor_r2gen_fd(-1, 0);
 	close(recv_pipe[0]);
 	if (remote_version >= 24) {
 		/* send a final goodbye message */
Index: rsync/proto.h
--- rsync/proto.h	25 Jan 2002 23:07:33 -0000	1.140
+++ rsync/proto.h	30 Jan 2002 17:57:51 -0000
@@ -97,6 +97,8 @@
 int check_hard_link(struct file_struct *file);
 void do_hard_links(void);
 void io_set_error_fd(int fd);
+void io_monitor_r2gen_fd(int fd, int flist_file_count);
+int io_get_redo_item(void);
 int32 read_int(int f);
 int64 read_longint(int f);
 void read_buf(int f,char *buf,size_t len);
