You must run "make proto" after applying this patch.

--- orig/cleanup.c	2004-07-20 21:36:07
+++ cleanup.c	2004-07-23 19:19:47
@@ -24,6 +24,7 @@
 extern int io_error;
 extern int keep_partial;
 extern int log_got_error;
+extern char *partial_dir;
 
 /**
  * Close all open sockets and files, allowing a (somewhat) graceful
@@ -111,7 +112,8 @@ void _exit_cleanup(int code, const char 
 		}
 	}
 
-	if (cleanup_got_literal && cleanup_fname && keep_partial) {
+	if (cleanup_got_literal && cleanup_fname && keep_partial
+	    && (!partial_dir || handle_partial_dir(cleanup_new_fname, 1))) {
 		char *fname = cleanup_fname;
 		cleanup_fname = NULL;
 		if (cleanup_fd_r != -1)
--- orig/generator.c	2004-07-23 17:16:12
+++ generator.c	2004-07-23 19:19:47
@@ -42,6 +42,7 @@ extern int size_only;
 extern int io_timeout;
 extern int protocol_version;
 extern int always_checksum;
+extern char *partial_dir;
 extern char *compare_dest;
 extern int link_dest;
 extern int whole_file;
@@ -411,7 +412,18 @@ static void recv_generator(char *fname, 
 		return;
 	}
 
-	fnamecmp = fname;
+	if (partial_dir) {
+		STRUCT_STAT st2;
+		if (!(fnamecmp = fname_in_partial_dir(fname)))
+			fnamecmp = fname;
+		else if (link_stat(fnamecmp, &st2, 0) == 0
+		    && S_ISREG(st2.st_mode)) {
+			statret = 0;
+			st = st2;
+		} else
+			fnamecmp = fname;
+	} else
+		fnamecmp = fname;
 
 	if (statret == -1 && compare_dest != NULL) {
 		/* try the file at compare_dest instead */
--- orig/options.c	2004-07-23 17:16:13
+++ options.c	2004-07-23 19:19:48
@@ -118,6 +118,7 @@ unsigned int backup_dir_remainder;
 
 char *backup_suffix = NULL;
 char *tmpdir = NULL;
+char *partial_dir = NULL;
 char *compare_dest = NULL;
 char *config_file = NULL;
 char *shell_cmd = NULL;
@@ -268,6 +269,7 @@ void usage(enum logcode F)
   rprintf(F,"     --ignore-errors         delete even if there are I/O errors\n");
   rprintf(F,"     --max-delete=NUM        don't delete more than NUM files\n");
   rprintf(F,"     --partial               keep partially transferred files\n");
+  rprintf(F,"     --partial-dir=DIR       put a partially transferred file into DIR\n");
   rprintf(F,"     --force                 force deletion of directories even if not empty\n");
   rprintf(F,"     --numeric-ids           don't map uid/gid values by user/group name\n");
   rprintf(F,"     --timeout=TIME          set I/O timeout in seconds\n");
@@ -383,6 +385,7 @@ static struct poptOption long_options[] 
   {"stats",            0,  POPT_ARG_NONE,   &do_stats, 0, 0, 0 },
   {"progress",         0,  POPT_ARG_NONE,   &do_progress, 0, 0, 0 },
   {"partial",          0,  POPT_ARG_NONE,   &keep_partial, 0, 0, 0 },
+  {"partial-dir",      0,  POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
   {"ignore-errors",    0,  POPT_ARG_NONE,   &ignore_errors, 0, 0, 0 },
   {"blocking-io",      0,  POPT_ARG_VAL,    &blocking_io, 1, 0, 0 },
   {"no-blocking-io",   0,  POPT_ARG_VAL,    &blocking_io, 0, 0, 0 },
@@ -718,6 +721,8 @@ int parse_arguments(int *argc, const cha
 			(*argv)[i] = alloc_sanitize_path((*argv)[i], NULL);
 		if (tmpdir)
 			tmpdir = alloc_sanitize_path(tmpdir, curr_dir);
+		if (partial_dir)
+			partial_dir = alloc_sanitize_path(partial_dir, curr_dir);
 		if (compare_dest)
 			compare_dest = alloc_sanitize_path(compare_dest, curr_dir);
 		if (backup_dir)
@@ -770,6 +775,11 @@ int parse_arguments(int *argc, const cha
 
 	if (inplace) {
 #if HAVE_FTRUNCATE
+		if (partial_dir) {
+			snprintf(err_buf, sizeof err_buf,
+				 "--inplace cannot be used with --partial-dir\n");
+			return 0;
+		}
 		keep_partial = 0;
 #else
 		snprintf(err_buf, sizeof err_buf,
@@ -777,7 +787,8 @@ int parse_arguments(int *argc, const cha
 			 am_server ? "server" : "client");
 		return 0;
 #endif
-	}
+	} else if (partial_dir)
+		keep_partial = 1;
 
 	if (files_from) {
 		char *colon;
@@ -969,7 +980,10 @@ void server_options(char **args,int *arg
 		args[ac++] = arg;
 	}
 
-	if (keep_partial)
+	if (partial_dir) {
+		args[ac++] = "--partial-dir";
+		args[ac++] = partial_dir;
+	} else if (keep_partial)
 		args[ac++] = "--partial";
 
 	if (force_delete)
--- orig/receiver.c	2004-07-23 17:16:13
+++ receiver.c	2004-07-23 19:19:48
@@ -38,6 +38,7 @@ extern int preserve_perms;
 extern int cvs_exclude;
 extern int io_error;
 extern char *tmpdir;
+extern char *partial_dir;
 extern char *compare_dest;
 extern int make_backups;
 extern int do_progress;
@@ -338,7 +339,7 @@ int recv_files(int f_in, struct file_lis
 	char *fname, fbuf[MAXPATHLEN];
 	char template[MAXPATHLEN];
 	char fnametmp[MAXPATHLEN];
-	char *fnamecmp;
+	char *fnamecmp, *partialptr;
 	char fnamecmpbuf[MAXPATHLEN];
 	struct file_struct *file;
 	struct stats initial_stats;
@@ -406,8 +407,6 @@ int recv_files(int f_in, struct file_lis
 		if (verbose > 2)
 			rprintf(FINFO,"recv_files(%s)\n",fname);
 
-		fnamecmp = fname;
-
 		if (read_batch) {
 			while (i > next_gen_i) {
 				next_gen_i = read_int(batch_gen_fd);
@@ -434,9 +433,22 @@ int recv_files(int f_in, struct file_lis
 			continue;
 		}
 
+		if (partial_dir) {
+			if ((partialptr = fname_in_partial_dir(fname)) != NULL)
+				fnamecmp = partialptr;
+			else
+				fnamecmp = fname;
+		} else
+			fnamecmp = partialptr = 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,
@@ -524,7 +536,8 @@ int recv_files(int f_in, struct file_lis
 				continue;
 			}
 
-			cleanup_set(fnametmp, fname, file, fd1, fd2);
+			if (partialptr)
+				cleanup_set(fnametmp, partialptr, file, fd1, fd2);
 		}
 
 		if (!am_server && verbose)
@@ -544,11 +557,16 @@ int recv_files(int f_in, struct file_lis
 			exit_cleanup(RERR_FILEIO);
 		}
 
-		if (recv_ok || keep_partial || inplace)
+		if (recv_ok || (keep_partial && partialptr) || inplace)
 			finish_transfer(fname, fnametmp, file, recv_ok);
 		else
 			do_unlink(fnametmp);
 
+		if (partialptr != fname && fnamecmp == partialptr) {
+			do_unlink(partialptr);
+			handle_partial_dir(partialptr, 0);
+		}
+
 		cleanup_disable();
 
 		if (!recv_ok) {
--- orig/rsync.yo	2004-07-24 16:52:10
+++ rsync.yo	2004-07-23 19:36:41
@@ -317,6 +317,7 @@ verb(
      --ignore-errors         delete even if there are I/O errors
      --max-delete=NUM        don't delete more than NUM files
      --partial               keep partially transferred files
+     --partial-dir=DIR       put a partially transferred file into DIR
      --force                 force deletion of dirs even if not empty
      --numeric-ids           don't map uid/gid values by user/group name
      --timeout=TIME          set I/O timeout in seconds
@@ -865,6 +866,21 @@ it is more desirable to keep partially t
 --partial option tells rsync to keep the partial file which should
 make a subsequent transfer of the rest of the file much faster.
 
+dit(bf(--partial-dir=DIR)) Turns on --partial mode, but tells rsync to
+put a partially transferred file into DIR instead of writing out the
+file to the destination dir.  Rsync will also use a file found in this
+dir as data to speed up a subsequent transfer.
+
+Rsync will create the dir if it is missing, so feel free to use a
+relative path (such as quote(--partial-dir=.rsync-partial)) if you
+want the file put into a directory relative to the current directory
+in the tree (rsync will also try to remove the DIR if a partial file
+was found and the DIR was specified as a relative path).
+
+If you want to delete files on the destination, be sure to use
+--delete-after instead of --delete or the partial file may be deleted
+before it can be used.
+
 dit(bf(--progress)) This option tells rsync to print information
 showing the progress of the transfer. This gives a bored user
 something to watch.
--- orig/t_stub.c	2004-05-15 20:10:13
+++ t_stub.c	2004-07-24 17:00:35
@@ -28,6 +28,7 @@
 
 int modify_window = 0;
 int module_id = -1;
+char *partial_dir;
 struct exclude_list_struct server_exclude_list;
 
  void rprintf(UNUSED(enum logcode code), const char *format, ...)
--- orig/util.c	2004-06-09 21:54:47
+++ util.c	2004-07-23 21:43:44
@@ -31,6 +31,7 @@ extern int verbose;
 extern int dry_run;
 extern int module_id;
 extern int modify_window;
+extern char *partial_dir;
 extern struct exclude_list_struct server_exclude_list;
 
 int sanitize_paths = 0;
@@ -945,6 +946,74 @@ char *full_fname(const char *fn)
 	return result;
 }
 
+static char partial_fname[MAXPATHLEN];
+
+char *fname_in_partial_dir(const char *fname)
+{
+	char *t = partial_fname;
+	int sz = sizeof partial_fname;
+	const char *fn;
+
+	if ((fn = strrchr(fname, '/')) != NULL) {
+		fn++;
+		if (*partial_dir != '/') {
+			int len = fn - fname;
+			strncpy(t, fname, len); /* safe */
+			t += len;
+			sz -= len;
+		}
+	} else
+		fn = fname;
+	if ((int)pathjoin(t, sz, partial_dir, fn) >= sz) {
+		*partial_fname = '\0';
+		return NULL;
+	}
+
+	return partial_fname;
+}
+
+int handle_partial_dir(const char *fname, int create)
+{
+	char *fn, *dir = partial_fname;
+
+	if (fname != partial_fname)
+		return 1;
+	if (!create && *partial_dir == '/')
+		return 1;
+	if (!(fn = strrchr(partial_fname, '/')))
+		return 1;
+
+	*fn = '\0';
+	if (create) {
+		STRUCT_STAT st;
+#if SUPPORT_LINKS
+		int statret = do_lstat(dir, &st);
+#else
+		int statret = do_stat(dir, &st);
+#endif
+		if (statret == 0 && !S_ISDIR(st.st_mode)) {
+			if (do_unlink(dir) < 0)
+				return 0;
+			statret = -1;
+		}
+		if (statret < 0) {
+			if (do_mkdir(dir, 0700) < 0)
+				return 0;
+#if SUPPORT_LINKS
+			statret = do_lstat(dir, &st);
+#else
+			statret = do_stat(dir, &st);
+#endif
+			if (statret < 0 || !S_ISDIR(st.st_mode))
+				return 0;
+		}
+	} else
+		do_rmdir(dir);
+	*fn = '/';
+
+	return 1;
+}
+
 /** We need to supply our own strcmp function for file list comparisons
    to ensure that signed/unsigned usage is consistent between machines. */
 int u_strcmp(const char *cs1, const char *cs2)
