When --read-batch was specified, do not put the generator's output
[rsync/rsync-patches.git] / g2r-basis-filename.diff
... / ...
CommitLineData
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
10--- orig/generator.c 2004-07-21 23:59:35
11+++ generator.c 2004-07-22 00:05:38
12@@ -258,9 +258,9 @@ static void generate_and_send_sums(int f
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 {
19- int fd;
20+ int fd = -1;
21 STRUCT_STAT st;
22 int statret;
23 char *fnamecmp;
24@@ -421,8 +421,10 @@ static void recv_generator(char *fname,
25 statret = link_stat(fnamecmpbuf, &st, 0);
26 if (!S_ISREG(st.st_mode))
27 statret = -1;
28- if (statret == -1)
29+ if (statret == -1) {
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) {
36@@ -430,22 +432,22 @@ static void recv_generator(char *fname,
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;
56- if (errno == ENOENT) {
57- write_int(f_out,i);
58- if (!dry_run && !read_batch)
59- write_sum_head(f_out, NULL);
60- } else if (verbose > 1) {
61+ if (errno == ENOENT)
62+ goto notify_others;
63+ if (verbose > 1) {
64 rsyserr(FERROR, errno,
65 "recv_generator: failed to open %s",
66 full_fname(fname));
67@@ -454,26 +456,23 @@ static void recv_generator(char *fname,
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
76 /* now pretend the file didn't exist */
77 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
78 return;
79- write_int(f_out,i);
80- if (!dry_run && !read_batch)
81- write_sum_head(f_out, NULL);
82- return;
83+ statret = -1;
84+ goto notify_others;
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);
99@@ -481,21 +480,17 @@ static void recv_generator(char *fname,
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
109- if (dry_run || read_batch) {
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;
120+ goto notify_others;
121 }
122+ if (read_batch)
123+ goto notify_others;
124
125 /* open the file */
126 fd = do_open(fnamecmp, O_RDONLY, 0);
127@@ -506,9 +501,8 @@ static void recv_generator(char *fname,
128 /* pretend the file didn't exist */
129 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
130 return;
131- write_int(f_out,i);
132- write_sum_head(f_out, NULL);
133- return;
134+ statret = -1;
135+ goto notify_others;
136 }
137
138 if (verbose > 3) {
139@@ -519,14 +513,40 @@ static void recv_generator(char *fname,
140 if (verbose > 2)
141 rprintf(FINFO, "generating and sending sums for %d\n", i);
142
143- write_int(f_out,i);
144- generate_and_send_sums(fd, st.st_size, f_out);
145+notify_others:
146+ if (f_nameout >= 0) {
147+ uchar lenbuf[3], *lb = lenbuf;
148+ int len = statret == -1 ? 0 : strlen(fnamecmpbuf);
149+ if (len > 0x7F) {
150+#if MAXPATHLEN > 0x7FFF
151+ *lb++ = len / 0x10000 + 0x80;
152+ *lb++ = len / 0x100;
153+#else
154+ *lb++ = len / 0x100 + 0x80;
155+#endif
156+ }
157+ *lb = len;
158+ write_buf(f_nameout, lenbuf, lb - lenbuf + 1);
159+ if (len)
160+ write_buf(f_nameout, fnamecmpbuf, len);
161+ }
162+
163+ write_int(f_out, i);
164+
165+ if (read_batch)
166+ return;
167
168- close(fd);
169+ if (statret == 0) {
170+ generate_and_send_sums(fd, st.st_size, f_out);
171+
172+ close(fd);
173+ } else if (!dry_run)
174+ write_sum_head(f_out, NULL);
175 }
176
177
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,
180+ int f_nameout)
181 {
182 int i;
183 int phase = 0;
184@@ -567,7 +587,7 @@ void generate_files(int f_out, struct fi
185 }
186
187 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
188- file, i, f_out);
189+ file, i, f_out, f_nameout);
190 }
191
192 phase++;
193@@ -584,7 +604,7 @@ void generate_files(int f_out, struct fi
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),
197- file, i, f_out);
198+ file, i, f_out, f_nameout);
199 }
200
201 phase++;
202@@ -603,7 +623,7 @@ void generate_files(int f_out, struct fi
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)
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;
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;
221@@ -454,20 +455,21 @@ static int do_recv(int f_in,int f_out,st
222 {
223 int pid;
224 int status = 0;
225- int error_pipe[2];
226+ int error_pipe[2], name_pipe[2];
227+ int need_name_pipe = compare_dest;
228
229 if (preserve_hard_links)
230 init_hard_links(flist);
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- }
238 }
239
240- if (fd_pair(error_pipe) < 0) {
241- rprintf(FERROR,"error pipe failed in do_recv\n");
242+ if (fd_pair(error_pipe) < 0
243+ || (need_name_pipe && fd_pair(name_pipe) < 0)) {
244+ rprintf(FERROR, "fd_pair() failed in do_recv\n");
245 exit_cleanup(RERR_SOCKETIO);
246 }
247
248@@ -475,6 +477,11 @@ static int do_recv(int f_in,int f_out,st
249
250 if ((pid = do_fork()) == 0) {
251 close(error_pipe[0]);
252+ if (need_name_pipe) {
253+ close(name_pipe[1]);
254+ set_blocking(name_pipe[0]);
255+ } else
256+ name_pipe[0] = -1;
257 if (f_in != f_out)
258 close(f_out);
259
260@@ -484,7 +491,7 @@ static int do_recv(int f_in,int f_out,st
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
269@@ -502,6 +509,11 @@ static int do_recv(int f_in,int f_out,st
270 stop_write_batch();
271
272 close(error_pipe[1]);
273+ if (need_name_pipe) {
274+ close(name_pipe[0]);
275+ set_nonblocking(name_pipe[1]);
276+ } else
277+ name_pipe[1] = -1;
278 if (f_in != f_out)
279 close(f_in);
280
281@@ -509,7 +521,7 @@ static int do_recv(int f_in,int f_out,st
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);
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 *
293 }
294
295
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+
319+
320 static void discard_receive_data(int f_in, OFF_T length)
321 {
322 receive_data(f_in, NULL, -1, 0, NULL, -1, length);
323@@ -330,7 +354,8 @@ static void discard_receive_data(int f_i
324 * main routine for receiver process.
325 *
326 * Receiver process runs on the same host as the generator process. */
327-int recv_files(int f_in, struct file_list *flist, char *local_name)
328+int recv_files(int f_in, struct file_list *flist, char *local_name,
329+ int f_name_in)
330 {
331 int next_gen_i = -1;
332 int fd1,fd2;
333@@ -359,8 +384,15 @@ int recv_files(int f_in, struct file_lis
334 i = read_int(f_in);
335 if (i == -1) {
336 if (read_batch) {
337- if (next_gen_i != flist->count)
338- while (read_int(batch_gen_fd) != -1) {}
339+ while (next_gen_i < flist->count) {
340+ if (f_name_in >= 0 && next_gen_i >= 0) {
341+ read_gen_name(f_name_in,
342+ fnamecmpbuf, NULL);
343+ }
344+ next_gen_i = read_int(f_name_in);
345+ if (next_gen_i < 0)
346+ break;
347+ }
348 next_gen_i = -1;
349 }
350
351@@ -406,10 +438,12 @@ int recv_files(int f_in, struct file_lis
352 if (verbose > 2)
353 rprintf(FINFO,"recv_files(%s)\n",fname);
354
355- fnamecmp = fname;
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 }
370+ next_gen_i = -1;
371 }
372
373+ if (f_name_in >= 0)
374+ fnamecmp = read_gen_name(f_name_in, fnamecmpbuf, fname);
375+ else
376+ fnamecmp = fname;
377+
378 if (server_exclude_list.head
379 && check_exclude(&server_exclude_list, fname,
380 S_ISDIR(file->mode)) < 0) {
381@@ -437,14 +477,6 @@ int recv_files(int f_in, struct file_lis
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));