- Needed to move the partial-dir check in the generator.
[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-23 17:16:12
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_out_name)
18 {
19- int fd;
20+ int fd = -1;
21 STRUCT_STAT st;
22 int statret;
23 char *fnamecmp;
24@@ -420,8 +420,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@@ -429,22 +431,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@@ -453,26 +455,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@@ -480,21 +479,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@@ -505,9 +500,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@@ -518,14 +512,41 @@ 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_out_name >= 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_out_name, lenbuf, lb - lenbuf + 1);
159+ if (len)
160+ write_buf(f_out_name, fnamecmpbuf, len);
161+ io_flush(NORMAL_FLUSH); /* XXX make this more efficient! */
162+ }
163+
164+ write_int(f_out, i);
165+
166+ if (dry_run || read_batch)
167+ return;
168
169- close(fd);
170+ if (statret == 0) {
171+ generate_and_send_sums(fd, st.st_size, f_out);
172+
173+ close(fd);
174+ } else
175+ write_sum_head(f_out, NULL);
176 }
177
178
179-void generate_files(int f_out, struct file_list *flist, char *local_name)
180+void generate_files(int f_out, struct file_list *flist, char *local_name,
181+ int f_out_name)
182 {
183 int i;
184 int phase = 0;
185@@ -566,7 +587,7 @@ void generate_files(int f_out, struct fi
186 }
187
188 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
189- file, i, f_out);
190+ file, i, f_out, f_out_name);
191 }
192
193 phase++;
194@@ -583,7 +604,7 @@ void generate_files(int f_out, struct fi
195 while ((i = get_redo_num()) != -1) {
196 struct file_struct *file = flist->files[i];
197 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
198- file, i, f_out);
199+ file, i, f_out, f_out_name);
200 }
201
202 phase++;
203@@ -602,7 +623,7 @@ void generate_files(int f_out, struct fi
204 if (!file->basename || !S_ISDIR(file->mode))
205 continue;
206 recv_generator(local_name ? local_name : f_name(file),
207- file, i, -1);
208+ file, i, -1, -1);
209 }
210
211 if (verbose > 2)
212--- orig/main.c 2004-07-23 17:16:13
213+++ main.c 2004-07-22 00:10:43
214@@ -58,6 +58,7 @@ extern int filesfrom_fd;
215 extern pid_t cleanup_child_pid;
216 extern char *files_from;
217 extern char *remote_filesfrom_file;
218+extern char *compare_dest;
219 extern char *rsync_path;
220 extern char *shell_cmd;
221 extern char *batch_name;
222@@ -456,7 +457,8 @@ static int do_recv(int f_in,int f_out,st
223 {
224 int pid;
225 int status = 0;
226- int error_pipe[2];
227+ int error_pipe[2], name_pipe[2];
228+ BOOL need_name_pipe = compare_dest && !dry_run;
229
230 if (preserve_hard_links)
231 init_hard_links(flist);
232@@ -467,8 +469,9 @@ static int do_recv(int f_in,int f_out,st
233 delete_files(flist);
234 }
235
236- if (fd_pair(error_pipe) < 0) {
237- rprintf(FERROR,"error pipe failed in do_recv\n");
238+ if (fd_pair(error_pipe) < 0
239+ || (need_name_pipe && fd_pair(name_pipe) < 0)) {
240+ rprintf(FERROR, "fd_pair() failed in do_recv\n");
241 exit_cleanup(RERR_SOCKETIO);
242 }
243
244@@ -476,6 +479,11 @@ static int do_recv(int f_in,int f_out,st
245
246 if ((pid = do_fork()) == 0) {
247 close(error_pipe[0]);
248+ if (need_name_pipe) {
249+ close(name_pipe[1]);
250+ set_blocking(name_pipe[0]);
251+ } else
252+ name_pipe[0] = -1;
253 if (f_in != f_out)
254 close(f_out);
255
256@@ -485,7 +493,7 @@ static int do_recv(int f_in,int f_out,st
257 /* set place to send errors */
258 set_msg_fd_out(error_pipe[1]);
259
260- recv_files(f_in,flist,local_name);
261+ recv_files(f_in, flist, local_name, name_pipe[0]);
262 io_flush(FULL_FLUSH);
263 report(f_in);
264
265@@ -503,6 +511,11 @@ static int do_recv(int f_in,int f_out,st
266 stop_write_batch();
267
268 close(error_pipe[1]);
269+ if (need_name_pipe) {
270+ close(name_pipe[0]);
271+ set_nonblocking(name_pipe[1]);
272+ } else
273+ name_pipe[1] = -1;
274 if (f_in != f_out)
275 close(f_in);
276
277@@ -510,7 +523,7 @@ static int do_recv(int f_in,int f_out,st
278
279 set_msg_fd_in(error_pipe[0]);
280
281- generate_files(f_out, flist, local_name);
282+ generate_files(f_out, flist, local_name, name_pipe[1]);
283
284 get_redo_num(); /* Read final MSG_DONE and any prior messages. */
285 report(-1);
286--- orig/receiver.c 2004-07-23 17:16:13
287+++ receiver.c 2004-07-22 00:20:50
288@@ -320,6 +320,30 @@ static int receive_data(int f_in, char *
289 }
290
291
292+static char *read_gen_name(int fd, char *buf, char *realname)
293+{
294+ int len = read_byte(fd);
295+ if (len & 0x80) {
296+#if MAXPATHLEN > 32767
297+ uchar lenbuf[2];
298+ read_buf(fd, (char *)lenbuf, 2);
299+ len = (len & ~0x80) * 0x10000 + lenbuf[0] * 0x100 + lenbuf[1];
300+#else
301+ len = (len & ~0x80) * 0x100 + read_byte(fd);
302+#endif
303+ }
304+ if (len) {
305+ if (len >= MAXPATHLEN) {
306+ rprintf(FERROR, "bogus data on generator name pipe\n");
307+ exit_cleanup(RERR_PROTOCOL);
308+ }
309+ read_sbuf(fd, buf, len);
310+ return buf;
311+ }
312+ return realname;
313+}
314+
315+
316 static void discard_receive_data(int f_in, OFF_T length)
317 {
318 receive_data(f_in, NULL, -1, 0, NULL, -1, length);
319@@ -330,7 +354,8 @@ static void discard_receive_data(int f_i
320 * main routine for receiver process.
321 *
322 * Receiver process runs on the same host as the generator process. */
323-int recv_files(int f_in, struct file_list *flist, char *local_name)
324+int recv_files(int f_in, struct file_list *flist, char *local_name,
325+ int f_in_name)
326 {
327 int next_gen_i = -1;
328 int fd1,fd2;
329@@ -359,8 +384,15 @@ int recv_files(int f_in, struct file_lis
330 i = read_int(f_in);
331 if (i == -1) {
332 if (read_batch) {
333- if (next_gen_i != flist->count)
334- while (read_int(batch_gen_fd) != -1) {}
335+ while (next_gen_i < flist->count) {
336+ if (f_in_name >= 0 && next_gen_i >= 0) {
337+ read_gen_name(f_in_name,
338+ fnamecmpbuf, NULL);
339+ }
340+ next_gen_i = read_int(batch_gen_fd);
341+ if (next_gen_i < 0)
342+ break;
343+ }
344 next_gen_i = -1;
345 }
346
347@@ -406,10 +438,12 @@ int recv_files(int f_in, struct file_lis
348 if (verbose > 2)
349 rprintf(FINFO,"recv_files(%s)\n",fname);
350
351- fnamecmp = fname;
352-
353 if (read_batch) {
354 while (i > next_gen_i) {
355+ if (f_in_name >= 0 && next_gen_i >= 0) {
356+ read_gen_name(f_in_name, fnamecmpbuf,
357+ NULL);
358+ }
359 next_gen_i = read_int(batch_gen_fd);
360 if (next_gen_i == -1)
361 next_gen_i = flist->count;
362@@ -420,8 +454,14 @@ int recv_files(int f_in, struct file_lis
363 discard_receive_data(f_in, file->length);
364 continue;
365 }
366+ next_gen_i = -1;
367 }
368
369+ if (f_in_name >= 0)
370+ fnamecmp = read_gen_name(f_in_name, fnamecmpbuf, fname);
371+ else
372+ fnamecmp = fname;
373+
374 if (server_exclude_list.head
375 && check_exclude(&server_exclude_list, fname,
376 S_ISDIR(file->mode)) < 0) {
377@@ -437,14 +477,6 @@ int recv_files(int f_in, struct file_lis
378 /* open the file */
379 fd1 = do_open(fnamecmp, O_RDONLY, 0);
380
381- if (fd1 == -1 && compare_dest != NULL) {
382- /* try the file at compare_dest instead */
383- pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
384- compare_dest, fname);
385- fnamecmp = fnamecmpbuf;
386- fd1 = do_open(fnamecmp, O_RDONLY, 0);
387- }
388-
389 if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
390 rsyserr(FERROR, errno, "fstat %s failed",
391 full_fname(fnamecmp));