Added a pipe from the generator to the receiver that communicates
what basis file we used to generate the file data (if it was not
the default name).  This optimizes away the basis-file search in
the receiver and makes future options that do more basis-file
searching more efficient (such as the --fuzzy option and the
support for multiple --compare-dest options).

You must run "make proto" before compiling.

--- orig/generator.c	2004-10-06 00:12:16
+++ generator.c	2004-11-03 20:12:24
@@ -254,14 +254,15 @@ static void generate_and_send_sums(int f
  * out.  It might be wrong.
  */
 static void recv_generator(char *fname, struct file_struct *file, int i,
-			   int f_out)
+			   int f_out, int f_out_name)
 {
-	int fd, f_copy;
+	int fd = -1, f_copy = -1;
 	STRUCT_STAT st, partial_st;
-	struct file_struct *back_file;
+	struct file_struct *back_file = NULL;
 	int statret, stat_errno;
-	char *fnamecmp, *partialptr, *backupptr;
+	char *fnamecmp, *partialptr, *backupptr = NULL;
 	char fnamecmpbuf[MAXPATHLEN];
+	uchar fnamecmp_type;
 
 	if (list_only)
 		return;
@@ -421,6 +422,7 @@ static void recv_generator(char *fname, 
 	}
 
 	fnamecmp = fname;
+	fnamecmp_type = FNAMECMP_FNAME;
 
 	if (statret == -1 && compare_dest != NULL) {
 		/* try the file at compare_dest instead */
@@ -437,10 +439,14 @@ static void recv_generator(char *fname, 
 							safe_fname(fname));
 					}
 					fnamecmp = fnamecmpbuf;
+					fnamecmp_type = FNAMECMP_CMPDEST;
 				}
 			} else
 #endif
+			{
 				fnamecmp = fnamecmpbuf;
+				fnamecmp_type = FNAMECMP_CMPDEST;
+			}
 			statret = 0;
 		}
 	}
@@ -463,11 +469,9 @@ static void recv_generator(char *fname, 
 	if (statret == -1) {
 		if (preserve_hard_links && hard_link_check(file, HL_SKIP))
 			return;
-		if (stat_errno == ENOENT) {
-			write_int(f_out,i);
-			if (!dry_run && !read_batch)
-				write_sum_head(f_out, NULL);
-		} else if (verbose > 1) {
+		if (stat_errno == ENOENT)
+			goto notify_others;
+		if (verbose > 1) {
 			rsyserr(FERROR, stat_errno,
 				"recv_generator: failed to stat %s",
 				full_fname(fname));
@@ -475,13 +479,13 @@ static void recv_generator(char *fname, 
 		return;
 	}
 
-	if (opt_ignore_existing && fnamecmp == fname) {
+	if (opt_ignore_existing && fnamecmp_type == FNAMECMP_FNAME) {
 		if (verbose > 1)
 			rprintf(FINFO, "%s exists\n", safe_fname(fname));
 		return;
 	}
 
-	if (update_only && fnamecmp == fname
+	if (update_only && fnamecmp_type == FNAMECMP_FNAME
 	    && cmp_modtime(st.st_mtime, file->modtime) > 0) {
 		if (verbose > 1)
 			rprintf(FINFO, "%s is newer\n", safe_fname(fname));
@@ -489,26 +493,23 @@ static void recv_generator(char *fname, 
 	}
 
 	if (skip_file(fnamecmp, file, &st)) {
-		if (fnamecmp == fname)
+		if (fnamecmp_type == FNAMECMP_FNAME)
 			set_perms(fname, file, &st, PERMS_REPORT);
 		return;
 	}
 
 prepare_to_open:
-	if (dry_run || read_batch) {
-		write_int(f_out,i);
-		return;
-	}
-
-	if (whole_file > 0) {
-		write_int(f_out,i);
-		write_sum_head(f_out, NULL);
-		return;
+	if (dry_run || whole_file > 0) {
+		statret = -1;
+		goto notify_others;
 	}
+	if (read_batch)
+		goto notify_others;
 
 	if (partialptr) {
 		st = partial_st;
 		fnamecmp = partialptr;
+		fnamecmp_type = FNAMECMP_PARTIAL_DIR;
 	}
 
 	/* open the file */
@@ -521,9 +522,8 @@ prepare_to_open:
 		/* pretend the file didn't exist */
 		if (preserve_hard_links && hard_link_check(file, HL_SKIP))
 			return;
-		write_int(f_out,i);
-		write_sum_head(f_out, NULL);
-		return;
+		statret = -1;
+		goto notify_others;
 	}
 
 	if (inplace && make_backups) {
@@ -550,10 +550,7 @@ prepare_to_open:
 			close(fd);
 			return;
 		}
-	} else {
-		backupptr = NULL;
-		back_file = NULL;
-		f_copy = -1;
+		fnamecmp_type = FNAMECMP_BACKUP;
 	}
 
 	if (verbose > 3) {
@@ -564,22 +561,35 @@ prepare_to_open:
 	if (verbose > 2)
 		rprintf(FINFO, "generating and sending sums for %d\n", i);
 
-	write_int(f_out,i);
-	generate_and_send_sums(fd, st.st_size, f_out, f_copy);
-
-	if (f_copy >= 0) {
-		close(f_copy);
-		set_perms(backupptr, back_file, NULL, 0);
-		if (verbose > 1)
-			rprintf(FINFO, "backed up %s to %s\n", fname, backupptr);
-		free(back_file);
-	}
+notify_others:
+	write_int(f_out, i);
+	if (f_out_name >= 0)
+		write_byte(f_out_name, fnamecmp_type);
+
+	if (dry_run || read_batch)
+		return;
+
+	if (statret == 0) {
+		generate_and_send_sums(fd, st.st_size, f_out, f_copy);
+
+		if (f_copy >= 0) {
+			close(f_copy);
+			set_perms(backupptr, back_file, NULL, 0);
+			if (verbose > 1) {
+				rprintf(FINFO, "backed up %s to %s\n",
+					fname, backupptr);
+			}
+			free(back_file);
+		}
 
-	close(fd);
+		close(fd);
+	} else
+		write_sum_head(f_out, NULL);
 }
 
 
-void generate_files(int f_out, struct file_list *flist, char *local_name)
+void generate_files(int f_out, struct file_list *flist, char *local_name,
+		    int f_out_name)
 {
 	int i;
 	int phase = 0;
@@ -620,7 +630,7 @@ void generate_files(int f_out, struct fi
 		}
 
 		recv_generator(local_name ? local_name : f_name_to(file, fbuf),
-			       file, i, f_out);
+			       file, i, f_out, f_out_name);
 	}
 
 	phase++;
@@ -637,7 +647,7 @@ void generate_files(int f_out, struct fi
 	while ((i = get_redo_num()) != -1) {
 		struct file_struct *file = flist->files[i];
 		recv_generator(local_name ? local_name : f_name_to(file, fbuf),
-			       file, i, f_out);
+			       file, i, f_out, f_out_name);
 	}
 
 	phase++;
@@ -656,7 +666,7 @@ void generate_files(int f_out, struct fi
 		if (!file->basename || !S_ISDIR(file->mode))
 			continue;
 		recv_generator(local_name ? local_name : f_name(file),
-			       file, i, -1);
+			       file, i, -1, -1);
 	}
 
 	if (verbose > 2)
--- orig/io.c	2004-08-02 02:44:26
+++ io.c	2004-11-03 19:49:36
@@ -857,6 +857,11 @@ static void writefd_unbuffered(int fd,ch
 			if (msg_fd_in > maxfd)
 				maxfd = msg_fd_in;
 		}
+		if (fd != sock_f_out && iobuf_out_cnt && no_flush == 1) {
+			FD_SET(sock_f_out, &w_fds);
+			if (sock_f_out > maxfd)
+				maxfd = sock_f_out;
+		}
 
 		tv.tv_sec = select_timeout;
 		tv.tv_usec = 0;
@@ -875,8 +880,14 @@ static void writefd_unbuffered(int fd,ch
 		if (msg_fd_in >= 0 && FD_ISSET(msg_fd_in, &r_fds))
 			read_msg_fd();
 
-		if (!FD_ISSET(fd, &w_fds))
+		if (!FD_ISSET(fd, &w_fds)) {
+			if (fd != sock_f_out && iobuf_out_cnt) {
+				no_flush--;
+				io_flush(NORMAL_FLUSH);
+				no_flush++;
+			}
 			continue;
+		}
 
 		n = len - total;
 		if (bwlimit && n > bwlimit_writemax)
--- orig/main.c	2004-10-08 20:16:26
+++ main.c	2004-11-03 16:07:53
@@ -59,6 +59,7 @@ extern int filesfrom_fd;
 extern pid_t cleanup_child_pid;
 extern char *files_from;
 extern char *remote_filesfrom_file;
+extern char *compare_dest;
 extern char *rsync_path;
 extern char *shell_cmd;
 extern char *batch_name;
@@ -461,7 +462,8 @@ static int do_recv(int f_in,int f_out,st
 {
 	int pid;
 	int status = 0;
-	int error_pipe[2];
+	int error_pipe[2], name_pipe[2];
+	BOOL need_name_pipe = compare_dest && !dry_run;
 
 	/* The receiving side mustn't obey this, or an existing symlink that
 	 * points to an identical file won't be replaced by the referent. */
@@ -476,7 +478,8 @@ static int do_recv(int f_in,int f_out,st
 			delete_files(flist);
 	}
 
-	if (fd_pair(error_pipe) < 0) {
+	if (fd_pair(error_pipe) < 0
+	    || (need_name_pipe && fd_pair(name_pipe) < 0)) {
 		rsyserr(FERROR, errno, "pipe failed in do_recv");
 		exit_cleanup(RERR_SOCKETIO);
 	}
@@ -485,6 +488,11 @@ static int do_recv(int f_in,int f_out,st
 
 	if ((pid = do_fork()) == 0) {
 		close(error_pipe[0]);
+		if (need_name_pipe) {
+			close(name_pipe[1]);
+			set_blocking(name_pipe[0]);
+		} else
+			name_pipe[0] = -1;
 		if (f_in != f_out)
 			close(f_out);
 
@@ -494,7 +502,7 @@ static int do_recv(int f_in,int f_out,st
 		/* set place to send errors */
 		set_msg_fd_out(error_pipe[1]);
 
-		recv_files(f_in,flist,local_name);
+		recv_files(f_in, flist, local_name, name_pipe[0]);
 		io_flush(FULL_FLUSH);
 		report(f_in);
 
@@ -513,6 +521,11 @@ static int do_recv(int f_in,int f_out,st
 		stop_write_batch();
 
 	close(error_pipe[1]);
+	if (need_name_pipe) {
+		close(name_pipe[0]);
+		set_nonblocking(name_pipe[1]);
+	} else
+		name_pipe[1] = -1;
 	if (f_in != f_out)
 		close(f_in);
 
@@ -520,7 +533,7 @@ static int do_recv(int f_in,int f_out,st
 
 	set_msg_fd_in(error_pipe[0]);
 
-	generate_files(f_out, flist, local_name);
+	generate_files(f_out, flist, local_name, name_pipe[1]);
 
 	get_redo_num(); /* Read final MSG_DONE and any prior messages. */
 	report(-1);
--- orig/receiver.c	2004-11-03 11:56:04
+++ receiver.c	2004-11-03 20:16:38
@@ -30,6 +30,7 @@ extern int dry_run;
 extern int read_batch;
 extern int batch_gen_fd;
 extern int am_server;
+extern int protocol_version;
 extern int relative_paths;
 extern int keep_dirlinks;
 extern int preserve_hard_links;
@@ -329,7 +330,8 @@ static void discard_receive_data(int f_i
  * main routine for receiver process.
  *
  * Receiver process runs on the same host as the generator process. */
-int recv_files(int f_in, struct file_list *flist, char *local_name)
+int recv_files(int f_in, struct file_list *flist, char *local_name,
+	       int f_in_name)
 {
 	int next_gen_i = -1;
 	int fd1,fd2;
@@ -358,8 +360,13 @@ int recv_files(int f_in, struct file_lis
 		i = read_int(f_in);
 		if (i == -1) {
 			if (read_batch) {
-				if (next_gen_i != flist->count)
-					while (read_int(batch_gen_fd) != -1) {}
+				if (next_gen_i != flist->count) {
+					do {
+						if (f_in_name >= 0
+						    && next_gen_i >= 0)
+							read_byte(f_in_name);
+					} while (read_int(batch_gen_fd) != -1);
+				}
 				next_gen_i = -1;
 			}
 
@@ -407,6 +414,8 @@ int recv_files(int f_in, struct file_lis
 
 		if (read_batch) {
 			while (i > next_gen_i) {
+				if (f_in_name >= 0 && next_gen_i >= 0)
+					read_byte(f_in_name);
 				next_gen_i = read_int(batch_gen_fd);
 				if (next_gen_i == -1)
 					next_gen_i = flist->count;
@@ -417,6 +426,7 @@ int recv_files(int f_in, struct file_lis
 				discard_receive_data(f_in, file->length);
 				continue;
 			}
+			next_gen_i = -1;
 		}
 
 		if (server_exclude_list.head
@@ -426,35 +436,32 @@ int recv_files(int f_in, struct file_lis
 			exit_cleanup(RERR_PROTOCOL);
 		}
 
-		if (partial_dir) {
-			if ((partialptr = partial_dir_fname(fname)) != NULL)
-				fnamecmp = partialptr;
-			else
+		partialptr = partial_dir ? partial_dir_fname(fname) : fname;
+
+		if (f_in_name >= 0) {
+			switch (read_byte(f_in_name)) {
+			case FNAMECMP_FNAME:
 				fnamecmp = fname;
+				break;
+			case FNAMECMP_PARTIAL_DIR:
+				fnamecmp = partialptr ? partialptr : fname;
+				break;
+			case FNAMECMP_BACKUP:
+				fnamecmp = get_backup_name(fname);
+				break;
+			case FNAMECMP_CMPDEST:
+			default:
+				pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
+					 compare_dest, fname);
+				fnamecmp = fnamecmpbuf;
+				break;
+			}
 		} else
-			fnamecmp = partialptr = fname;
-
-		if (inplace && make_backups) {
-			if (!(fnamecmp = get_backup_name(fname)))
-				fnamecmp = partialptr;
-		}
+			fnamecmp = fname;
 
 		/* open the file */
 		fd1 = do_open(fnamecmp, O_RDONLY, 0);
 
-		if (fd1 == -1 && fnamecmp != fname) {
-			fnamecmp = fname;
-			fd1 = do_open(fnamecmp, O_RDONLY, 0);
-		}
-
-		if (fd1 == -1 && compare_dest != NULL) {
-			/* try the file at compare_dest instead */
-			pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
-				 compare_dest, fname);
-			fnamecmp = fnamecmpbuf;
-			fd1 = do_open(fnamecmp, O_RDONLY, 0);
-		}
-
 		if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
 			rsyserr(FERROR, errno, "fstat %s failed",
 				full_fname(fnamecmp));
--- orig/rsync.h	2004-10-09 03:21:56
+++ rsync.h	2004-11-03 20:11:34
@@ -119,6 +119,11 @@
 #define PDIR_CREATE	1
 #define PDIR_DELETE	0
 
+#define FNAMECMP_CMPDEST	0x00
+#define FNAMECMP_FNAME		0x80
+#define FNAMECMP_PARTIAL_DIR	0x81
+#define FNAMECMP_BACKUP 	0x82
+
 
 /* Log-message categories.  FLOG is only used on the daemon side to
  * output messages to the log file. */
