1 Added a pipe from the generator to the receiver that communicates
2 what basis file we used to generate the file data (if it was not
3 the default name). This optimizes away the basis-file search in
4 the receiver and makes future options that do more basis-file
5 searching more efficient (such as the --fuzzy option and the
6 support for multiple --compare-dest options).
8 You must run "make proto" before compiling.
10 --- orig/generator.c 2004-09-20 19:50:13
11 +++ generator.c 2004-09-20 19:57:58
12 @@ -254,14 +254,15 @@ static void generate_and_send_sums(int f
13 * out. It might be wrong.
15 static void recv_generator(char *fname, struct file_struct *file, int i,
17 + int f_out, int f_out_name)
20 + int fd = -1, f_copy;
21 STRUCT_STAT st, partial_st;
22 struct file_struct *back_file;
23 int statret, stat_errno;
24 char *fnamecmp, *partialptr, *backupptr;
25 char fnamecmpbuf[MAXPATHLEN];
26 + uchar fnamecmp_type;
30 @@ -423,6 +424,7 @@ static void recv_generator(char *fname,
34 + fnamecmp_type = G2R_FNAME;
36 if (statret == -1 && compare_dest != NULL) {
37 /* try the file at compare_dest instead */
38 @@ -439,10 +441,14 @@ static void recv_generator(char *fname,
41 fnamecmp = fnamecmpbuf;
47 fnamecmp = fnamecmpbuf;
53 @@ -465,11 +471,9 @@ static void recv_generator(char *fname,
55 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
57 - if (stat_errno == ENOENT) {
59 - if (!dry_run && !read_batch)
60 - write_sum_head(f_out, NULL);
61 - } else if (verbose > 1) {
62 + if (stat_errno == ENOENT)
65 rsyserr(FERROR, stat_errno,
66 "recv_generator: failed to stat %s",
68 @@ -477,13 +481,13 @@ static void recv_generator(char *fname,
72 - if (opt_ignore_existing && fnamecmp == fname) {
73 + if (opt_ignore_existing && fnamecmp_type == G2R_FNAME) {
75 rprintf(FINFO, "%s exists\n", safe_fname(fname));
79 - if (update_only && fnamecmp == fname
80 + if (update_only && fnamecmp_type == G2R_FNAME
81 && cmp_modtime(st.st_mtime, file->modtime) > 0) {
83 rprintf(FINFO, "%s is newer\n", safe_fname(fname));
84 @@ -491,26 +495,23 @@ static void recv_generator(char *fname,
87 if (skip_file(fnamecmp, file, &st)) {
88 - if (fnamecmp == fname)
89 + if (fnamecmp_type == G2R_FNAME)
90 set_perms(fname, file, &st, PERMS_REPORT);
95 - if (dry_run || read_batch) {
100 - if (whole_file > 0) {
101 - write_int(f_out,i);
102 - write_sum_head(f_out, NULL);
104 + if (dry_run || whole_file > 0) {
106 + goto notify_others;
109 + goto notify_others;
113 fnamecmp = partialptr;
114 + fnamecmp_type = G2R_PARTIAL_DIR;
118 @@ -523,9 +524,8 @@ prepare_to_open:
119 /* pretend the file didn't exist */
120 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
122 - write_int(f_out,i);
123 - write_sum_head(f_out, NULL);
126 + goto notify_others;
129 if (inplace && make_backups) {
130 @@ -552,6 +552,7 @@ prepare_to_open:
134 + fnamecmp_type = G2R_BACKUP;
138 @@ -566,22 +567,38 @@ prepare_to_open:
140 rprintf(FINFO, "generating and sending sums for %d\n", i);
142 - write_int(f_out,i);
143 - generate_and_send_sums(fd, st.st_size, f_out, f_copy);
147 - set_perms(backupptr, back_file, NULL, 0);
149 - rprintf(FINFO, "backed up %s to %s\n", fname, backupptr);
152 + if (f_out_name >= 0) {
153 + write_byte(f_out_name, fnamecmp_type);
154 + io_flush(NORMAL_FLUSH); /* XXX make this more efficient! */
158 + write_int(f_out, i);
160 + if (dry_run || read_batch)
163 + if (statret == 0) {
164 + generate_and_send_sums(fd, st.st_size, f_out, f_copy);
168 + set_perms(backupptr, back_file, NULL, 0);
170 + rprintf(FINFO, "backed up %s to %s\n",
178 + write_sum_head(f_out, NULL);
182 -void generate_files(int f_out, struct file_list *flist, char *local_name)
183 +void generate_files(int f_out, struct file_list *flist, char *local_name,
188 @@ -622,7 +639,7 @@ void generate_files(int f_out, struct fi
191 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
193 + file, i, f_out, f_out_name);
197 @@ -639,7 +656,7 @@ void generate_files(int f_out, struct fi
198 while ((i = get_redo_num()) != -1) {
199 struct file_struct *file = flist->files[i];
200 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
202 + file, i, f_out, f_out_name);
206 @@ -658,7 +675,7 @@ void generate_files(int f_out, struct fi
207 if (!file->basename || !S_ISDIR(file->mode))
209 recv_generator(local_name ? local_name : f_name(file),
215 --- orig/main.c 2004-09-18 01:49:33
216 +++ main.c 2004-07-22 00:10:43
217 @@ -59,6 +59,7 @@ extern int filesfrom_fd;
218 extern pid_t cleanup_child_pid;
219 extern char *files_from;
220 extern char *remote_filesfrom_file;
221 +extern char *compare_dest;
222 extern char *rsync_path;
223 extern char *shell_cmd;
224 extern char *batch_name;
225 @@ -461,7 +462,8 @@ static int do_recv(int f_in,int f_out,st
230 + int error_pipe[2], name_pipe[2];
231 + BOOL need_name_pipe = compare_dest && !dry_run;
233 /* The receiving side mustn't obey this, or an existing symlink that
234 * points to an identical file won't be replaced by the referent. */
235 @@ -476,8 +478,9 @@ static int do_recv(int f_in,int f_out,st
239 - if (fd_pair(error_pipe) < 0) {
240 - rprintf(FERROR,"error pipe failed in do_recv\n");
241 + if (fd_pair(error_pipe) < 0
242 + || (need_name_pipe && fd_pair(name_pipe) < 0)) {
243 + rprintf(FERROR, "fd_pair() failed in do_recv\n");
244 exit_cleanup(RERR_SOCKETIO);
247 @@ -485,6 +488,11 @@ static int do_recv(int f_in,int f_out,st
249 if ((pid = do_fork()) == 0) {
250 close(error_pipe[0]);
251 + if (need_name_pipe) {
252 + close(name_pipe[1]);
253 + set_blocking(name_pipe[0]);
259 @@ -494,7 +502,7 @@ static int do_recv(int f_in,int f_out,st
260 /* set place to send errors */
261 set_msg_fd_out(error_pipe[1]);
263 - recv_files(f_in,flist,local_name);
264 + recv_files(f_in, flist, local_name, name_pipe[0]);
265 io_flush(FULL_FLUSH);
268 @@ -513,6 +521,11 @@ static int do_recv(int f_in,int f_out,st
271 close(error_pipe[1]);
272 + if (need_name_pipe) {
273 + close(name_pipe[0]);
274 + set_nonblocking(name_pipe[1]);
280 @@ -520,7 +533,7 @@ static int do_recv(int f_in,int f_out,st
282 set_msg_fd_in(error_pipe[0]);
284 - generate_files(f_out, flist, local_name);
285 + generate_files(f_out, flist, local_name, name_pipe[1]);
287 get_redo_num(); /* Read final MSG_DONE and any prior messages. */
289 --- orig/receiver.c 2004-09-21 09:40:27
290 +++ receiver.c 2004-09-07 21:57:20
291 @@ -329,7 +329,8 @@ static void discard_receive_data(int f_i
292 * main routine for receiver process.
294 * Receiver process runs on the same host as the generator process. */
295 -int recv_files(int f_in, struct file_list *flist, char *local_name)
296 +int recv_files(int f_in, struct file_list *flist, char *local_name,
301 @@ -358,8 +359,13 @@ int recv_files(int f_in, struct file_lis
305 - if (next_gen_i != flist->count)
306 - while (read_int(batch_gen_fd) != -1) {}
307 + if (next_gen_i != flist->count) {
310 + && next_gen_i >= 0)
311 + read_byte(f_in_name);
312 + } while (read_int(batch_gen_fd) != -1);
317 @@ -407,6 +413,8 @@ int recv_files(int f_in, struct file_lis
320 while (i > next_gen_i) {
321 + if (f_in_name >= 0 && next_gen_i >= 0)
322 + read_byte(f_in_name);
323 next_gen_i = read_int(batch_gen_fd);
324 if (next_gen_i == -1)
325 next_gen_i = flist->count;
326 @@ -417,6 +425,7 @@ int recv_files(int f_in, struct file_lis
327 discard_receive_data(f_in, file->length);
333 if (server_exclude_list.head
334 @@ -426,35 +435,31 @@ int recv_files(int f_in, struct file_lis
335 exit_cleanup(RERR_PROTOCOL);
339 - if ((partialptr = partial_dir_fname(fname)) != NULL)
340 - fnamecmp = partialptr;
342 + partialptr = partial_dir ? partial_dir_fname(fname) : fname;
344 + if (f_in_name >= 0) {
345 + switch (read_byte(f_in_name)) {
349 + case G2R_PARTIAL_DIR:
350 + fnamecmp = partialptr ? partialptr : fname;
353 + fnamecmp = get_backup_name(fname);
356 + pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
357 + compare_dest, fname);
358 + fnamecmp = fnamecmpbuf;
362 - fnamecmp = partialptr = fname;
364 - if (inplace && make_backups) {
365 - if (!(fnamecmp = get_backup_name(fname)))
366 - fnamecmp = partialptr;
371 fd1 = do_open(fnamecmp, O_RDONLY, 0);
373 - if (fd1 == -1 && fnamecmp != fname) {
375 - fd1 = do_open(fnamecmp, O_RDONLY, 0);
378 - if (fd1 == -1 && compare_dest != NULL) {
379 - /* try the file at compare_dest instead */
380 - pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
381 - compare_dest, fname);
382 - fnamecmp = fnamecmpbuf;
383 - fd1 = do_open(fnamecmp, O_RDONLY, 0);
386 if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
387 rsyserr(FERROR, errno, "fstat %s failed",
388 full_fname(fnamecmp));
389 --- orig/rsync.h 2004-09-22 08:47:31
390 +++ rsync.h 2004-09-07 21:52:22
392 #define PDIR_CREATE 1
393 #define PDIR_DELETE 0
395 +#define G2R_FNAME 0x80
396 +#define G2R_PARTIAL_DIR 0x81
397 +#define G2R_BACKUP 0x82
400 /* Log-message categories. FLOG is only used on the daemon side to
401 * output messages to the log file. */