1 You must run "make proto" after applying this patch.
3 --- orig/cleanup.c 2004-07-20 21:36:07
4 +++ cleanup.c 2004-07-23 19:19:47
7 extern int keep_partial;
8 extern int log_got_error;
9 +extern char *partial_dir;
12 * Close all open sockets and files, allowing a (somewhat) graceful
13 @@ -113,6 +114,8 @@ void _exit_cleanup(int code, const char
15 if (cleanup_got_literal && cleanup_fname && keep_partial) {
16 char *fname = cleanup_fname;
18 + handle_partial_dir(cleanup_new_fname, 1);
20 if (cleanup_fd_r != -1)
22 --- orig/generator.c 2004-07-23 17:16:12
23 +++ generator.c 2004-07-23 19:19:47
24 @@ -42,6 +42,7 @@ extern int size_only;
25 extern int io_timeout;
26 extern int protocol_version;
27 extern int always_checksum;
28 +extern char *partial_dir;
29 extern char *compare_dest;
31 extern int whole_file;
32 @@ -411,7 +412,18 @@ static void recv_generator(char *fname,
39 + if (!(fnamecmp = fname_in_partial_dir(fname)))
41 + else if (link_stat(fnamecmp, &st2, 0) == 0
42 + && S_ISREG(st2.st_mode)) {
50 if (statret == -1 && compare_dest != NULL) {
51 /* try the file at compare_dest instead */
52 --- orig/options.c 2004-07-23 17:16:13
53 +++ options.c 2004-07-23 19:19:48
54 @@ -118,6 +118,7 @@ unsigned int backup_dir_remainder;
56 char *backup_suffix = NULL;
58 +char *partial_dir = NULL;
59 char *compare_dest = NULL;
60 char *config_file = NULL;
61 char *shell_cmd = NULL;
62 @@ -268,6 +269,7 @@ void usage(enum logcode F)
63 rprintf(F," --ignore-errors delete even if there are I/O errors\n");
64 rprintf(F," --max-delete=NUM don't delete more than NUM files\n");
65 rprintf(F," --partial keep partially transferred files\n");
66 + rprintf(F," --partial-dir=DIR put a partially transferred file into DIR\n");
67 rprintf(F," --force force deletion of directories even if not empty\n");
68 rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
69 rprintf(F," --timeout=TIME set I/O timeout in seconds\n");
70 @@ -383,6 +385,7 @@ static struct poptOption long_options[]
71 {"stats", 0, POPT_ARG_NONE, &do_stats, 0, 0, 0 },
72 {"progress", 0, POPT_ARG_NONE, &do_progress, 0, 0, 0 },
73 {"partial", 0, POPT_ARG_NONE, &keep_partial, 0, 0, 0 },
74 + {"partial-dir", 0, POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
75 {"ignore-errors", 0, POPT_ARG_NONE, &ignore_errors, 0, 0, 0 },
76 {"blocking-io", 0, POPT_ARG_VAL, &blocking_io, 1, 0, 0 },
77 {"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 },
78 @@ -718,6 +721,8 @@ int parse_arguments(int *argc, const cha
79 (*argv)[i] = alloc_sanitize_path((*argv)[i], NULL);
81 tmpdir = alloc_sanitize_path(tmpdir, curr_dir);
83 + partial_dir = alloc_sanitize_path(partial_dir, curr_dir);
85 compare_dest = alloc_sanitize_path(compare_dest, curr_dir);
87 @@ -770,6 +775,11 @@ int parse_arguments(int *argc, const cha
92 + snprintf(err_buf, sizeof err_buf,
93 + "--inplace cannot be used with --partial-dir\n");
98 snprintf(err_buf, sizeof err_buf,
99 @@ -777,7 +787,8 @@ int parse_arguments(int *argc, const cha
100 am_server ? "server" : "client");
104 + } else if (partial_dir)
109 @@ -969,7 +980,10 @@ void server_options(char **args,int *arg
115 + args[ac++] = "--partial-dir";
116 + args[ac++] = partial_dir;
117 + } else if (keep_partial)
118 args[ac++] = "--partial";
121 --- orig/receiver.c 2004-07-23 17:16:13
122 +++ receiver.c 2004-07-23 19:19:48
123 @@ -38,6 +38,7 @@ extern int preserve_perms;
124 extern int cvs_exclude;
127 +extern char *partial_dir;
128 extern char *compare_dest;
129 extern int make_backups;
130 extern int do_progress;
131 @@ -338,7 +339,7 @@ int recv_files(int f_in, struct file_lis
132 char *fname, fbuf[MAXPATHLEN];
133 char template[MAXPATHLEN];
134 char fnametmp[MAXPATHLEN];
136 + char *fnamecmp, *partialptr;
137 char fnamecmpbuf[MAXPATHLEN];
138 struct file_struct *file;
139 struct stats initial_stats;
140 @@ -406,8 +407,6 @@ int recv_files(int f_in, struct file_lis
142 rprintf(FINFO,"recv_files(%s)\n",fname);
147 while (i > next_gen_i) {
148 next_gen_i = read_int(batch_gen_fd);
149 @@ -434,9 +433,22 @@ int recv_files(int f_in, struct file_lis
154 + if ((partialptr = fname_in_partial_dir(fname)) != NULL)
155 + fnamecmp = partialptr;
159 + fnamecmp = partialptr = fname;
162 fd1 = do_open(fnamecmp, O_RDONLY, 0);
164 + if (fd1 == -1 && fnamecmp != fname) {
166 + fd1 = do_open(fnamecmp, O_RDONLY, 0);
169 if (fd1 == -1 && compare_dest != NULL) {
170 /* try the file at compare_dest instead */
171 pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
172 @@ -524,7 +536,8 @@ int recv_files(int f_in, struct file_lis
176 - cleanup_set(fnametmp, fname, file, fd1, fd2);
178 + cleanup_set(fnametmp, partialptr, file, fd1, fd2);
181 if (!am_server && verbose)
182 @@ -544,11 +557,16 @@ int recv_files(int f_in, struct file_lis
183 exit_cleanup(RERR_FILEIO);
186 - if (recv_ok || keep_partial || inplace)
187 + if (recv_ok || (keep_partial && partialptr) || inplace)
188 finish_transfer(fname, fnametmp, file, recv_ok);
192 + if (partialptr != fname && fnamecmp == partialptr) {
193 + do_unlink(partialptr);
194 + handle_partial_dir(partialptr, 0);
200 --- orig/rsync.yo 2004-07-23 17:16:13
201 +++ rsync.yo 2004-07-23 19:36:41
202 @@ -317,6 +317,7 @@ verb(
203 --ignore-errors delete even if there are I/O errors
204 --max-delete=NUM don't delete more than NUM files
205 --partial keep partially transferred files
206 + --partial-dir=DIR put a partially transferred file into DIR
207 --force force deletion of dirs even if not empty
208 --numeric-ids don't map uid/gid values by user/group name
209 --timeout=TIME set I/O timeout in seconds
210 @@ -865,6 +866,21 @@ it is more desirable to keep partially t
211 --partial option tells rsync to keep the partial file which should
212 make a subsequent transfer of the rest of the file much faster.
214 +dit(bf(--partial-dir=DIR)) Turns on --partial mode, but tells rsync to
215 +put a partially transferred file into DIR instead of writing out the
216 +file to the destination dir. Rsync will also use a file found in this
217 +dir as data to speed up a subsequent transfer.
219 +Rsync will create the dir if it is missing, so feel free to use a
220 +relative path (such as quote(--partial-dir=.rsync-partial)) if you
221 +want the file put into a directory relative to the current directory
222 +in the tree (rsync will also try to remove the DIR if a partial file
223 +was found and the DIR was specified as a relative path).
225 +If you want to delete files on the destination, be sure to use
226 +--delete-after instead of --delete or the partial file may be deleted
227 +before it can be used.
229 dit(bf(--progress)) This option tells rsync to print information
230 showing the progress of the transfer. This gives a bored user
232 --- orig/util.c 2004-06-09 21:54:47
233 +++ util.c 2004-07-23 21:43:44
234 @@ -31,6 +31,7 @@ extern int verbose;
236 extern int module_id;
237 extern int modify_window;
238 +extern char *partial_dir;
239 extern struct exclude_list_struct server_exclude_list;
241 int sanitize_paths = 0;
242 @@ -945,6 +946,51 @@ char *full_fname(const char *fn)
246 +static char partialbuf[MAXPATHLEN];
248 +char *fname_in_partial_dir(const char *fname)
250 + char *t = partialbuf;
251 + int sz = sizeof partialbuf;
254 + if ((fn = strrchr(fname, '/')) != NULL) {
256 + if (*partial_dir != '/') {
257 + int len = fn - fname;
258 + strncpy(t, fname, len); /* safe */
264 + if ((int)pathjoin(t, sz, partial_dir, fn) >= sz) {
265 + *partialbuf = '\0';
272 +void handle_partial_dir(const char *fname, int create)
276 + if (fname != partialbuf)
278 + if (!create && *partial_dir == '/')
280 + if (!(fn = strrchr(partialbuf, '/')))
285 + do_mkdir(partialbuf, 0700);
287 + do_rmdir(partialbuf);
291 /** We need to supply our own strcmp function for file list comparisons
292 to ensure that signed/unsigned usage is consistent between machines. */
293 int u_strcmp(const char *cs1, const char *cs2)