When --read-batch was specified, do not put the generator's output
[rsync/rsync-patches.git] / g2r-basis-filename.diff
CommitLineData
77945073
WD
1Added a pipe from the generator to the receiver that communicates
2what basis file we used to generate the file data (if it was not
3the default name). This optimizes away the basis-file search in
4the receiver and makes future options that do more basis-file
5searching more efficient (such as the --fuzzy option and the
6support for multiple --compare-dest options).
7
8You must run "make proto" before compiling.
9
2f5fa77e
WD
10--- orig/generator.c 2004-07-21 23:59:35
11+++ generator.c 2004-07-22 00:05:38
dc3ae351 12@@ -258,9 +258,9 @@ static void generate_and_send_sums(int f
77945073
WD
13 * out. It might be wrong.
14 */
15 static void recv_generator(char *fname, struct file_struct *file, int i,
16- int f_out)
17+ int f_out, int f_nameout)
18 {
0bd6d59f
WD
19- int fd;
20+ int fd = -1;
77945073 21 STRUCT_STAT st;
0bd6d59f
WD
22 int statret;
23 char *fnamecmp;
2f5fa77e 24@@ -421,8 +421,10 @@ static void recv_generator(char *fname,
77945073
WD
25 statret = link_stat(fnamecmpbuf, &st, 0);
26 if (!S_ISREG(st.st_mode))
27 statret = -1;
28- if (statret == -1)
0bd6d59f 29+ if (statret == -1) {
77945073
WD
30 errno = saveerrno;
31+ *fnamecmpbuf = '\0';
32+ }
33 #if HAVE_LINK
34 else if (link_dest && !dry_run) {
35 if (do_link(fnamecmpbuf, fname) != 0) {
2f5fa77e 36@@ -430,22 +432,22 @@ static void recv_generator(char *fname,
77945073
WD
37 rsyserr(FINFO, errno, "link %s => %s",
38 fnamecmpbuf, fname);
39 }
40- }
41- fnamecmp = fnamecmpbuf;
42+ fnamecmp = fnamecmpbuf;
43+ } else
44+ *fnamecmpbuf = '\0';
45 }
46 #endif
47 else
48 fnamecmp = fnamecmpbuf;
49- }
50+ } else
51+ *fnamecmpbuf = '\0';
52
53 if (statret == -1) {
54 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
55 return;
0bd6d59f
WD
56- if (errno == ENOENT) {
57- write_int(f_out,i);
2f5fa77e 58- if (!dry_run && !read_batch)
0bd6d59f
WD
59- write_sum_head(f_out, NULL);
60- } else if (verbose > 1) {
61+ if (errno == ENOENT)
d24c084d 62+ goto notify_others;
0bd6d59f
WD
63+ if (verbose > 1) {
64 rsyserr(FERROR, errno,
65 "recv_generator: failed to open %s",
66 full_fname(fname));
2f5fa77e 67@@ -454,26 +456,23 @@ static void recv_generator(char *fname,
0bd6d59f
WD
68 }
69
70 if (!S_ISREG(st.st_mode)) {
71- if (delete_file(fname) != 0) {
72+ if (delete_file(fname) != 0)
73 return;
74- }
75
77945073
WD
76 /* now pretend the file didn't exist */
77 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
78 return;
0bd6d59f 79- write_int(f_out,i);
2f5fa77e 80- if (!dry_run && !read_batch)
0bd6d59f
WD
81- write_sum_head(f_out, NULL);
82- return;
83+ statret = -1;
d24c084d 84+ goto notify_others;
77945073
WD
85 }
86
87- if (opt_ignore_existing && fnamecmp == fname) {
88+ if (opt_ignore_existing && !*fnamecmpbuf) {
89 if (verbose > 1)
90 rprintf(FINFO,"%s exists\n",fname);
91 return;
92 }
93
94- if (update_only && fnamecmp == fname
95+ if (update_only && !*fnamecmpbuf
96 && cmp_modtime(st.st_mtime, file->modtime) > 0) {
97 if (verbose > 1)
98 rprintf(FINFO,"%s is newer\n",fname);
2f5fa77e 99@@ -481,21 +480,17 @@ static void recv_generator(char *fname,
77945073
WD
100 }
101
102 if (skip_file(fname, file, &st)) {
103- if (fnamecmp == fname)
104+ if (!*fnamecmpbuf)
105 set_perms(fname, file, &st, PERMS_REPORT);
106 return;
107 }
108
2f5fa77e 109- if (dry_run || read_batch) {
0bd6d59f
WD
110- write_int(f_out,i);
111- return;
112- }
113-
114- if (whole_file > 0) {
115- write_int(f_out,i);
116- write_sum_head(f_out, NULL);
117- return;
118+ if (dry_run || whole_file) {
119+ statret = -1;
d24c084d 120+ goto notify_others;
77945073 121 }
0bd6d59f 122+ if (read_batch)
d24c084d 123+ goto notify_others;
77945073 124
0bd6d59f
WD
125 /* open the file */
126 fd = do_open(fnamecmp, O_RDONLY, 0);
2f5fa77e 127@@ -506,9 +501,8 @@ static void recv_generator(char *fname,
77945073
WD
128 /* pretend the file didn't exist */
129 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
130 return;
0bd6d59f
WD
131- write_int(f_out,i);
132- write_sum_head(f_out, NULL);
133- return;
134+ statret = -1;
d24c084d 135+ goto notify_others;
0bd6d59f
WD
136 }
137
0bd6d59f 138 if (verbose > 3) {
2f5fa77e 139@@ -519,14 +513,40 @@ static void recv_generator(char *fname,
77945073
WD
140 if (verbose > 2)
141 rprintf(FINFO, "generating and sending sums for %d\n", i);
142
0bd6d59f 143- write_int(f_out,i);
dc3ae351 144- generate_and_send_sums(fd, st.st_size, f_out);
d24c084d 145+notify_others:
0b32df42
WD
146+ if (f_nameout >= 0) {
147+ uchar lenbuf[3], *lb = lenbuf;
0bd6d59f 148+ int len = statret == -1 ? 0 : strlen(fnamecmpbuf);
0bd6d59f
WD
149+ if (len > 0x7F) {
150+#if MAXPATHLEN > 0x7FFF
151+ *lb++ = len / 0x10000 + 0x80;
152+ *lb++ = len / 0x100;
0b32df42 153+#else
0bd6d59f 154+ *lb++ = len / 0x100 + 0x80;
0b32df42
WD
155+#endif
156+ }
157+ *lb = len;
158+ write_buf(f_nameout, lenbuf, lb - lenbuf + 1);
0bd6d59f
WD
159+ if (len)
160+ write_buf(f_nameout, fnamecmpbuf, len);
0b32df42 161+ }
0bd6d59f
WD
162+
163+ write_int(f_out, i);
2f5fa77e
WD
164+
165+ if (read_batch)
166+ return;
167
168- close(fd);
0bd6d59f 169+ if (statret == 0) {
dc3ae351 170+ generate_and_send_sums(fd, st.st_size, f_out);
0bd6d59f
WD
171+
172+ close(fd);
0bd6d59f
WD
173+ } else if (!dry_run)
174+ write_sum_head(f_out, NULL);
77945073
WD
175 }
176
177
9be39c35
WD
178-void generate_files(int f_out, struct file_list *flist, char *local_name)
179+void generate_files(int f_out, struct file_list *flist, char *local_name,
77945073
WD
180+ int f_nameout)
181 {
182 int i;
8cec1ead 183 int phase = 0;
2f5fa77e 184@@ -567,7 +587,7 @@ void generate_files(int f_out, struct fi
77945073
WD
185 }
186
187 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
9be39c35
WD
188- file, i, f_out);
189+ file, i, f_out, f_nameout);
77945073
WD
190 }
191
192 phase++;
2f5fa77e 193@@ -584,7 +604,7 @@ void generate_files(int f_out, struct fi
77945073
WD
194 while ((i = get_redo_num()) != -1) {
195 struct file_struct *file = flist->files[i];
196 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
9be39c35
WD
197- file, i, f_out);
198+ file, i, f_out, f_nameout);
77945073
WD
199 }
200
201 phase++;
2f5fa77e 202@@ -603,7 +623,7 @@ void generate_files(int f_out, struct fi
77945073
WD
203 if (!file->basename || !S_ISDIR(file->mode))
204 continue;
205 recv_generator(local_name ? local_name : f_name(file),
206- file, i, -1);
207+ file, i, -1, -1);
208 }
209
210 if (verbose > 2)
2f5fa77e
WD
211--- orig/main.c 2004-07-21 23:59:35
212+++ main.c 2004-07-22 00:10:43
213@@ -58,6 +58,7 @@ extern int filesfrom_fd;
0bd6d59f
WD
214 extern pid_t cleanup_child_pid;
215 extern char *files_from;
216 extern char *remote_filesfrom_file;
217+extern char *compare_dest;
218 extern char *rsync_path;
219 extern char *shell_cmd;
220 extern char *batch_name;
2f5fa77e 221@@ -454,20 +455,21 @@ static int do_recv(int f_in,int f_out,st
77945073
WD
222 {
223 int pid;
8cec1ead 224 int status = 0;
77945073 225- int error_pipe[2];
77945073 226+ int error_pipe[2], name_pipe[2];
2f5fa77e 227+ int need_name_pipe = compare_dest;
77945073
WD
228
229 if (preserve_hard_links)
230 init_hard_links(flist);
d24c084d
WD
231
232 if (!delete_after) {
233 /* I moved this here from recv_files() to prevent a race condition */
234- if (recurse && delete_mode && !local_name && flist->count>0) {
235+ if (recurse && delete_mode && !local_name && flist->count > 0)
236 delete_files(flist);
237- }
77945073
WD
238 }
239
240- if (fd_pair(error_pipe) < 0) {
241- rprintf(FERROR,"error pipe failed in do_recv\n");
0bd6d59f
WD
242+ if (fd_pair(error_pipe) < 0
243+ || (need_name_pipe && fd_pair(name_pipe) < 0)) {
77945073
WD
244+ rprintf(FERROR, "fd_pair() failed in do_recv\n");
245 exit_cleanup(RERR_SOCKETIO);
246 }
247
2f5fa77e 248@@ -475,6 +477,11 @@ static int do_recv(int f_in,int f_out,st
77945073 249
8cec1ead 250 if ((pid = do_fork()) == 0) {
77945073 251 close(error_pipe[0]);
0bd6d59f
WD
252+ if (need_name_pipe) {
253+ close(name_pipe[1]);
254+ set_blocking(name_pipe[0]);
255+ } else
256+ name_pipe[0] = -1;
77945073
WD
257 if (f_in != f_out)
258 close(f_out);
77945073 259
2f5fa77e 260@@ -484,7 +491,7 @@ static int do_recv(int f_in,int f_out,st
77945073
WD
261 /* set place to send errors */
262 set_msg_fd_out(error_pipe[1]);
263
264- recv_files(f_in,flist,local_name);
265+ recv_files(f_in, flist, local_name, name_pipe[0]);
266 io_flush(FULL_FLUSH);
267 report(f_in);
268
2f5fa77e 269@@ -502,6 +509,11 @@ static int do_recv(int f_in,int f_out,st
9be39c35 270 stop_write_batch();
77945073
WD
271
272 close(error_pipe[1]);
0bd6d59f
WD
273+ if (need_name_pipe) {
274+ close(name_pipe[0]);
275+ set_nonblocking(name_pipe[1]);
276+ } else
277+ name_pipe[1] = -1;
77945073
WD
278 if (f_in != f_out)
279 close(f_in);
77945073 280
2f5fa77e 281@@ -509,7 +521,7 @@ static int do_recv(int f_in,int f_out,st
77945073
WD
282
283 set_msg_fd_in(error_pipe[0]);
284
285- generate_files(f_out, flist, local_name);
286+ generate_files(f_out, flist, local_name, name_pipe[1]);
287
288 get_redo_num(); /* Read final MSG_DONE and any prior messages. */
289 report(-1);
2f5fa77e
WD
290--- orig/receiver.c 2004-07-22 00:07:20
291+++ receiver.c 2004-07-22 00:20:50
292@@ -320,6 +320,30 @@ static int receive_data(int f_in, char *
0bd6d59f
WD
293 }
294
5823d322 295
0bd6d59f
WD
296+static char *read_gen_name(int fd, char *buf, char *realname)
297+{
298+ int len = read_byte(fd);
299+ if (len & 0x80) {
300+#if MAXPATHLEN > 32767
301+ uchar lenbuf[2];
302+ read_buf(fd, (char *)lenbuf, 2);
303+ len = (len & ~0x80) * 0x10000 + lenbuf[0] * 0x100 + lenbuf[1];
304+#else
305+ len = (len & ~0x80) * 0x100 + read_byte(fd);
306+#endif
307+ }
308+ if (len) {
309+ if (len >= MAXPATHLEN) {
310+ rprintf(FERROR, "bogus data on generator name pipe\n");
311+ exit_cleanup(RERR_PROTOCOL);
312+ }
313+ read_sbuf(fd, buf, len);
314+ return buf;
315+ }
316+ return realname;
317+}
318+
5823d322
WD
319+
320 static void discard_receive_data(int f_in, OFF_T length)
321 {
dc3ae351 322 receive_data(f_in, NULL, -1, 0, NULL, -1, length);
2f5fa77e 323@@ -330,7 +354,8 @@ static void discard_receive_data(int f_i
77945073
WD
324 * main routine for receiver process.
325 *
326 * Receiver process runs on the same host as the generator process. */
9be39c35 327-int recv_files(int f_in, struct file_list *flist, char *local_name)
77945073 328+int recv_files(int f_in, struct file_list *flist, char *local_name,
0bd6d59f 329+ int f_name_in)
77945073 330 {
2f5fa77e 331 int next_gen_i = -1;
77945073 332 int fd1,fd2;
2f5fa77e 333@@ -359,8 +384,15 @@ int recv_files(int f_in, struct file_lis
0bd6d59f
WD
334 i = read_int(f_in);
335 if (i == -1) {
2f5fa77e
WD
336 if (read_batch) {
337- if (next_gen_i != flist->count)
338- while (read_int(batch_gen_fd) != -1) {}
0bd6d59f 339+ while (next_gen_i < flist->count) {
2f5fa77e
WD
340+ if (f_name_in >= 0 && next_gen_i >= 0) {
341+ read_gen_name(f_name_in,
342+ fnamecmpbuf, NULL);
343+ }
0bd6d59f 344+ next_gen_i = read_int(f_name_in);
2f5fa77e
WD
345+ if (next_gen_i < 0)
346+ break;
0bd6d59f 347+ }
2f5fa77e
WD
348 next_gen_i = -1;
349 }
5823d322 350
2f5fa77e 351@@ -406,10 +438,12 @@ int recv_files(int f_in, struct file_lis
77945073
WD
352 if (verbose > 2)
353 rprintf(FINFO,"recv_files(%s)\n",fname);
354
355- fnamecmp = fname;
2f5fa77e
WD
356-
357 if (read_batch) {
358 while (i > next_gen_i) {
359+ if (f_name_in >= 0 && next_gen_i >= 0) {
360+ read_gen_name(f_name_in, fnamecmpbuf,
361+ NULL);
362+ }
363 next_gen_i = read_int(batch_gen_fd);
364 if (next_gen_i == -1)
365 next_gen_i = flist->count;
366@@ -420,8 +454,14 @@ int recv_files(int f_in, struct file_lis
367 discard_receive_data(f_in, file->length);
368 continue;
369 }
0bd6d59f 370+ next_gen_i = -1;
2f5fa77e
WD
371 }
372
0bd6d59f
WD
373+ if (f_name_in >= 0)
374+ fnamecmp = read_gen_name(f_name_in, fnamecmpbuf, fname);
375+ else
0b32df42 376+ fnamecmp = fname;
2f5fa77e 377+
5823d322
WD
378 if (server_exclude_list.head
379 && check_exclude(&server_exclude_list, fname,
2f5fa77e
WD
380 S_ISDIR(file->mode)) < 0) {
381@@ -437,14 +477,6 @@ int recv_files(int f_in, struct file_lis
77945073
WD
382 /* open the file */
383 fd1 = do_open(fnamecmp, O_RDONLY, 0);
384
385- if (fd1 == -1 && compare_dest != NULL) {
386- /* try the file at compare_dest instead */
387- pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
388- compare_dest, fname);
389- fnamecmp = fnamecmpbuf;
390- fd1 = do_open(fnamecmp, O_RDONLY, 0);
391- }
392-
393 if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
394 rsyserr(FERROR, errno, "fstat %s failed",
395 full_fname(fnamecmp));