Stefan Nehlsen's fix of a timeout problem on large files.
[rsync.git] / generator.c
blobdd3eef66250799c591df2783e872533b2ef8fa50
1 /* -*- c-file-style: "linux" -*-
3 rsync -- fast file replication program
5 Copyright (C) 1996-2000 by Andrew Tridgell
6 Copyright (C) Paul Mackerras 1996
7 Copyright (C) 2002 by Martin Pool <mbp@samba.org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "rsync.h"
26 extern int verbose;
27 extern int dry_run;
28 extern int relative_paths;
29 extern int preserve_links;
30 extern int am_root;
31 extern int preserve_devices;
32 extern int preserve_hard_links;
33 extern int update_only;
34 extern int opt_ignore_existing;
35 extern int block_size;
36 extern int csum_length;
37 extern int ignore_times;
38 extern int size_only;
39 extern int io_timeout;
40 extern int remote_version;
41 extern int always_checksum;
42 extern int modify_window;
43 extern char *compare_dest;
46 /* choose whether to skip a particular file */
47 static int skip_file(char *fname,
48 struct file_struct *file, STRUCT_STAT *st)
50 if (st->st_size != file->length) {
51 return 0;
54 /* if always checksum is set then we use the checksum instead
55 of the file time to determine whether to sync */
56 if (always_checksum && S_ISREG(st->st_mode)) {
57 char sum[MD4_SUM_LENGTH];
58 char fnamecmpdest[MAXPATHLEN];
60 if (compare_dest != NULL) {
61 if (access(fname, 0) != 0) {
62 snprintf(fnamecmpdest,MAXPATHLEN,"%s/%s",
63 compare_dest,fname);
64 fname = fnamecmpdest;
67 file_checksum(fname,sum,st->st_size);
68 if (remote_version < 21) {
69 return (memcmp(sum,file->sum,2) == 0);
70 } else {
71 return (memcmp(sum,file->sum,MD4_SUM_LENGTH) == 0);
75 if (size_only) {
76 return 1;
79 if (ignore_times) {
80 return 0;
83 return (cmp_modtime(st->st_mtime,file->modtime) == 0);
87 /* use a larger block size for really big files */
88 static int adapt_block_size(struct file_struct *file, int bsize)
90 int ret;
92 if (bsize != BLOCK_SIZE) return bsize;
94 ret = file->length / (10000); /* rough heuristic */
95 ret = ret & ~15; /* multiple of 16 */
96 if (ret < bsize) ret = bsize;
97 if (ret > CHUNK_SIZE/2) ret = CHUNK_SIZE/2;
98 return ret;
103 send a header that says "we have no checksums" down the f_out fd
105 static void send_null_sums(int f_out)
107 write_int(f_out, 0);
108 write_int(f_out, block_size);
109 write_int(f_out, 0);
115 * Perhaps we want to just send an empty checksum set for this file,
116 * which will force the whole thing to be literally transferred.
118 * When do we do this? If the user's explicitly said they
119 * want the whole thing, or if { they haven't explicitly
120 * requested a delta, and it's local but not batch mode.}
122 * Whew. */
123 static BOOL disable_deltas_p(void)
125 extern int whole_file, no_whole_file;
126 extern int local_server;
127 extern int write_batch;
129 assert(whole_file == 0 || whole_file == 1);
131 /* whole_file and no_whole_file are never both on at the same time */
133 if (whole_file)
134 return True;
135 else if (no_whole_file)
136 return False;
137 else if (write_batch)
138 return False;
139 else
140 return local_server;
145 * Generate and send a stream of signatures/checksums that describe a buffer
147 * Generate approximately one checksum every block_len bytes.
149 static void generate_and_send_sums(struct map_struct *buf, OFF_T len,
150 int block_len, int f_out)
152 size_t i;
153 struct sum_struct sum;
154 OFF_T offset = 0;
156 sum.count = (len + (block_len - 1)) / block_len;
157 sum.remainder = (len % block_len);
158 sum.n = block_len;
159 sum.flength = len;
160 /* not needed here sum.sums = NULL; */
162 if (sum.count && verbose > 3) {
163 rprintf(FINFO, "count=%ld rem=%ld n=%ld flength=%.0f\n",
164 (long) sum.count, (long) sum.remainder,
165 (long) sum.n, (double) sum.flength);
168 write_int(f_out, sum.count);
169 write_int(f_out, sum.n);
170 write_int(f_out, sum.remainder);
172 for (i = 0; i < sum.count; i++) {
173 int n1 = MIN(len, block_len);
174 char *map = map_ptr(buf, offset, n1);
175 uint32 sum1 = get_checksum1(map, n1);
176 char sum2[SUM_LENGTH];
178 get_checksum2(map, n1, sum2);
180 if (verbose > 3) {
181 rprintf(FINFO,
182 "chunk[%d] offset=%.0f len=%d sum1=%08lx\n",
183 i, (double) offset, n1, (unsigned long) sum1);
185 write_int(f_out, sum1);
186 write_buf(f_out, sum2, csum_length);
187 len -= n1;
188 offset += n1;
195 * Acts on file number @p i from @p flist, whose name is @p fname.
197 * First fixes up permissions, then generates checksums for the file.
199 * @note This comment was added later by mbp who was trying to work it
200 * out. It might be wrong.
201 **/
202 void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
204 int fd;
205 STRUCT_STAT st;
206 struct map_struct *buf;
207 int statret;
208 struct file_struct *file = flist->files[i];
209 char *fnamecmp;
210 char fnamecmpbuf[MAXPATHLEN];
211 extern char *compare_dest;
212 extern int list_only;
213 extern int preserve_perms;
214 extern int only_existing;
215 extern int orig_umask;
217 if (list_only) return;
219 if (verbose > 2)
220 rprintf(FINFO,"recv_generator(%s,%d)\n",fname,i);
222 statret = link_stat(fname,&st);
224 if (only_existing && statret == -1 && errno == ENOENT) {
225 /* we only want to update existing files */
226 if (verbose > 1) rprintf(FINFO, "not creating new file \"%s\"\n",fname);
227 return;
230 if (statret == 0 &&
231 !preserve_perms &&
232 (S_ISDIR(st.st_mode) == S_ISDIR(file->mode))) {
233 /* if the file exists already and we aren't perserving
234 presmissions then act as though the remote end sent
235 us the file permissions we already have */
236 file->mode = (file->mode & _S_IFMT) | (st.st_mode & ~_S_IFMT);
239 if (S_ISDIR(file->mode)) {
240 /* The file to be received is a directory, so we need
241 * to prepare appropriately. If there is already a
242 * file of that name and it is *not* a directory, then
243 * we need to delete it. If it doesn't exist, then
244 * recursively create it. */
246 if (dry_run) return; /* XXXX -- might cause inaccuracies?? -- mbp */
247 if (statret == 0 && !S_ISDIR(st.st_mode)) {
248 if (robust_unlink(fname) != 0) {
249 rprintf(FERROR, RSYNC_NAME
250 ": recv_generator: unlink \"%s\" to make room for directory: %s\n",
251 fname,strerror(errno));
252 return;
254 statret = -1;
256 if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
257 if (!(relative_paths && errno==ENOENT &&
258 create_directory_path(fname, orig_umask)==0 &&
259 do_mkdir(fname,file->mode)==0)) {
260 rprintf(FERROR, RSYNC_NAME ": recv_generator: mkdir \"%s\": %s (2)\n",
261 fname,strerror(errno));
264 /* f_out is set to -1 when doing final directory
265 permission and modification time repair */
266 if (set_perms(fname,file,NULL,0) && verbose && (f_out != -1))
267 rprintf(FINFO,"%s/\n",fname);
268 return;
271 if (preserve_links && S_ISLNK(file->mode)) {
272 #if SUPPORT_LINKS
273 char lnk[MAXPATHLEN];
274 int l;
275 extern int safe_symlinks;
277 if (safe_symlinks && unsafe_symlink(file->link, fname)) {
278 if (verbose) {
279 rprintf(FINFO,"ignoring unsafe symlink \"%s\" -> \"%s\"\n",
280 fname,file->link);
282 return;
284 if (statret == 0) {
285 l = readlink(fname,lnk,MAXPATHLEN-1);
286 if (l > 0) {
287 lnk[l] = 0;
288 /* A link already pointing to the
289 * right place -- no further action
290 * required. */
291 if (strcmp(lnk,file->link) == 0) {
292 set_perms(fname,file,&st,1);
293 return;
296 /* Not a symlink, so delete whatever's
297 * already there and put a new symlink
298 * in place. */
299 delete_file(fname);
301 if (do_symlink(file->link,fname) != 0) {
302 rprintf(FERROR,RSYNC_NAME": symlink \"%s\" -> \"%s\": %s\n",
303 fname,file->link,strerror(errno));
304 } else {
305 set_perms(fname,file,NULL,0);
306 if (verbose) {
307 rprintf(FINFO,"%s -> %s\n", fname,file->link);
310 #endif
311 return;
314 #ifdef HAVE_MKNOD
315 if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
316 if (statret != 0 ||
317 st.st_mode != file->mode ||
318 st.st_rdev != file->rdev) {
319 delete_file(fname);
320 if (verbose > 2)
321 rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
322 fname,(int)file->mode,(int)file->rdev);
323 if (do_mknod(fname,file->mode,file->rdev) != 0) {
324 rprintf(FERROR,"mknod %s : %s\n",fname,strerror(errno));
325 } else {
326 set_perms(fname,file,NULL,0);
327 if (verbose)
328 rprintf(FINFO,"%s\n",fname);
330 } else {
331 set_perms(fname,file,&st,1);
333 return;
335 #endif
337 if (preserve_hard_links && check_hard_link(file)) {
338 if (verbose > 1)
339 rprintf(FINFO, "recv_generator: \"%s\" is a hard link\n",f_name(file));
340 return;
343 if (!S_ISREG(file->mode)) {
344 rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname);
345 return;
348 fnamecmp = fname;
350 if ((statret == -1) && (compare_dest != NULL)) {
351 /* try the file at compare_dest instead */
352 int saveerrno = errno;
353 snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",compare_dest,fname);
354 statret = link_stat(fnamecmpbuf,&st);
355 if (!S_ISREG(st.st_mode))
356 statret = -1;
357 if (statret == -1)
358 errno = saveerrno;
359 else
360 fnamecmp = fnamecmpbuf;
363 if (statret == -1) {
364 if (errno == ENOENT) {
365 write_int(f_out,i);
366 if (!dry_run) send_null_sums(f_out);
367 } else {
368 if (verbose > 1)
369 rprintf(FERROR, RSYNC_NAME
370 ": recv_generator failed to open \"%s\": %s\n",
371 fname, strerror(errno));
373 return;
376 if (!S_ISREG(st.st_mode)) {
377 if (delete_file(fname) != 0) {
378 return;
381 /* now pretend the file didn't exist */
382 write_int(f_out,i);
383 if (!dry_run) send_null_sums(f_out);
384 return;
387 if (opt_ignore_existing && fnamecmp == fname) {
388 if (verbose > 1)
389 rprintf(FINFO,"%s exists\n",fname);
390 return;
393 if (update_only && cmp_modtime(st.st_mtime,file->modtime)>0 && fnamecmp == fname) {
394 if (verbose > 1)
395 rprintf(FINFO,"%s is newer\n",fname);
396 return;
399 if (skip_file(fname, file, &st)) {
400 if (fnamecmp == fname)
401 set_perms(fname,file,&st,1);
402 return;
405 if (dry_run) {
406 write_int(f_out,i);
407 return;
410 if (disable_deltas_p()) {
411 write_int(f_out,i);
412 send_null_sums(f_out);
413 return;
416 /* open the file */
417 fd = do_open(fnamecmp, O_RDONLY, 0);
419 if (fd == -1) {
420 rprintf(FERROR,RSYNC_NAME": failed to open \"%s\", continuing : %s\n",fnamecmp,strerror(errno));
421 /* pretend the file didn't exist */
422 write_int(f_out,i);
423 send_null_sums(f_out);
424 return;
427 if (st.st_size > 0) {
428 buf = map_file(fd,st.st_size);
429 } else {
430 buf = NULL;
433 if (verbose > 3)
434 rprintf(FINFO,"gen mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
436 if (verbose > 2)
437 rprintf(FINFO, "generating and sending sums for %d\n", i);
439 write_int(f_out,i);
440 generate_and_send_sums(buf, st.st_size,
441 adapt_block_size(file, block_size), f_out);
443 close(fd);
444 if (buf) unmap_file(buf);
449 void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
451 int i;
452 int phase=0;
454 if (verbose > 2)
455 rprintf(FINFO,"generator starting pid=%d count=%d\n",
456 (int)getpid(),flist->count);
458 if (verbose >= 2) {
459 rprintf(FINFO,
460 disable_deltas_p()
461 ? "delta-transmission disabled for local transfer or --whole-file\n"
462 : "delta transmission enabled\n");
465 /* we expect to just sit around now, so don't exit on a
466 timeout. If we really get a timeout then the other process should
467 exit */
468 io_timeout = 0;
470 for (i = 0; i < flist->count; i++) {
471 struct file_struct *file = flist->files[i];
472 mode_t saved_mode = file->mode;
473 if (!file->basename) continue;
475 /* we need to ensure that any directories we create have writeable
476 permissions initially so that we can create the files within
477 them. This is then fixed after the files are transferred */
478 if (!am_root && S_ISDIR(file->mode)) {
479 file->mode |= S_IWUSR; /* user write */
480 /* XXX: Could this be causing a problem on SCO? Perhaps their
481 * handling of permissions is strange? */
484 recv_generator(local_name?local_name:f_name(file),
485 flist,i,f);
487 file->mode = saved_mode;
490 phase++;
491 csum_length = SUM_LENGTH;
492 ignore_times=1;
494 if (verbose > 2)
495 rprintf(FINFO,"generate_files phase=%d\n",phase);
497 write_int(f,-1);
499 if (remote_version >= 13) {
500 /* in newer versions of the protocol the files can cycle through
501 the system more than once to catch initial checksum errors */
502 for (i=read_int(f_recv); i != -1; i=read_int(f_recv)) {
503 struct file_struct *file = flist->files[i];
504 recv_generator(local_name?local_name:f_name(file),
505 flist,i,f);
508 phase++;
509 if (verbose > 2)
510 rprintf(FINFO,"generate_files phase=%d\n",phase);
512 write_int(f,-1);