Document the latest changes.
[rsync/rsync.git] / generator.c
... / ...
CommitLineData
1/* -*- c-file-style: "linux" -*-
2
3 rsync -- fast file replication program
4
5 Copyright (C) 1996-2000 by Andrew Tridgell
6 Copyright (C) Paul Mackerras 1996
7 Copyright (C) 2002 by Martin Pool <mbp@samba.org>
8
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.
13
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.
18
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.
22*/
23
24#include "rsync.h"
25
26extern int verbose;
27extern int dry_run;
28extern int relative_paths;
29extern int preserve_links;
30extern int am_root;
31extern int preserve_devices;
32extern int preserve_hard_links;
33extern int preserve_perms;
34extern int preserve_uid;
35extern int preserve_gid;
36extern int update_only;
37extern int opt_ignore_existing;
38extern int csum_length;
39extern int ignore_times;
40extern int size_only;
41extern int io_timeout;
42extern int protocol_version;
43extern int always_checksum;
44extern char *compare_dest;
45extern int link_dest;
46extern int whole_file;
47extern int local_server;
48extern int read_batch;
49extern int write_batch;
50extern int list_only;
51extern int only_existing;
52extern int orig_umask;
53extern int safe_symlinks;
54
55extern struct exclude_list_struct server_exclude_list;
56
57
58/* choose whether to skip a particular file */
59static int skip_file(char *fname, struct file_struct *file, STRUCT_STAT *st)
60{
61 if (st->st_size != file->length) {
62 return 0;
63 }
64 if (link_dest) {
65 if (preserve_perms
66 && (st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS))
67 return 0;
68
69 if (am_root && preserve_uid && st->st_uid != file->uid)
70 return 0;
71
72 if (preserve_gid && file->gid != GID_NONE
73 && st->st_gid != file->gid)
74 return 0;
75 }
76
77 /* if always checksum is set then we use the checksum instead
78 of the file time to determine whether to sync */
79 if (always_checksum && S_ISREG(st->st_mode)) {
80 char sum[MD4_SUM_LENGTH];
81 char fnamecmpdest[MAXPATHLEN];
82
83 if (compare_dest != NULL) {
84 if (access(fname, 0) != 0) {
85 pathjoin(fnamecmpdest, sizeof fnamecmpdest,
86 compare_dest, fname);
87 fname = fnamecmpdest;
88 }
89 }
90 file_checksum(fname,sum,st->st_size);
91 return memcmp(sum, file->u.sum, protocol_version < 21 ? 2
92 : MD4_SUM_LENGTH) == 0;
93 }
94
95 if (size_only) {
96 return 1;
97 }
98
99 if (ignore_times) {
100 return 0;
101 }
102
103 return (cmp_modtime(st->st_mtime,file->modtime) == 0);
104}
105
106
107/*
108 * NULL sum_struct means we have no checksums
109 */
110void write_sum_head(int f, struct sum_struct *sum)
111{
112 static struct sum_struct null_sum;
113
114 if (sum == NULL)
115 sum = &null_sum;
116
117 write_int(f, sum->count);
118 write_int(f, sum->blength);
119 if (protocol_version >= 27)
120 write_int(f, sum->s2length);
121 write_int(f, sum->remainder);
122}
123
124/*
125 * set (initialize) the size entries in the per-file sum_struct
126 * calulating dynamic block ans checksum sizes.
127 *
128 * This is only called from generate_and_send_sums() but is a seperate
129 * function to encapsulate the logic.
130 *
131 * The block size is a rounded square root of file length.
132 *
133 * The checksum size is determined according to:
134 * blocksum_bits = BLOCKSUM_EXP + 2*log2(file_len) - log2(block_len)
135 * provided by Donovan Baarda which gives a probability of rsync
136 * algorithm corrupting data and falling back using the whole md4
137 * checksums.
138 *
139 * This might be made one of several selectable heuristics.
140 */
141
142static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
143{
144 extern unsigned int block_size;
145 unsigned int blength;
146 int s2length;
147 uint32 c;
148 uint64 l;
149
150 if (block_size) {
151 blength = block_size;
152 } else if (len <= BLOCK_SIZE * BLOCK_SIZE) {
153 blength = BLOCK_SIZE;
154 } else {
155 l = len;
156 c = 1;
157 while (l >>= 2) {
158 c <<= 1;
159 }
160 blength = 0;
161 do {
162 blength |= c;
163 if (len < (uint64)blength * blength)
164 blength &= ~c;
165 c >>= 1;
166 } while (c >= 8); /* round to multiple of 8 */
167 blength = MAX(blength, BLOCK_SIZE);
168 }
169
170 if (protocol_version < 27) {
171 s2length = csum_length;
172 } else if (csum_length == SUM_LENGTH) {
173 s2length = SUM_LENGTH;
174 } else {
175 int b = BLOCKSUM_BIAS;
176 l = len;
177 while (l >>= 1) {
178 b += 2;
179 }
180 c = blength;
181 while (c >>= 1 && b) {
182 b--;
183 }
184 s2length = (b + 1 - 32 + 7) / 8; /* add a bit,
185 * subtract rollsum,
186 * round up
187 * --optimize in compiler--
188 */
189 s2length = MAX(s2length, csum_length);
190 s2length = MIN(s2length, SUM_LENGTH);
191 }
192
193 sum->flength = len;
194 sum->blength = blength;
195 sum->s2length = s2length;
196 sum->count = (len + (blength - 1)) / blength;
197 sum->remainder = (len % blength);
198
199 if (sum->count && verbose > 2) {
200 rprintf(FINFO, "count=%.0f rem=%u blength=%u s2length=%d flength=%.0f\n",
201 (double)sum->count, sum->remainder, sum->blength,
202 sum->s2length, (double)sum->flength);
203 }
204}
205
206/**
207 * Perhaps we want to just send an empty checksum set for this file,
208 * which will force the whole thing to be literally transferred.
209 *
210 * When do we do this? If the user's explicitly said they
211 * want the whole thing, or if { they haven't explicitly
212 * requested a delta, and it's local but not batch mode.}
213 *
214 * Whew. */
215static BOOL disable_deltas_p(void)
216{
217 if (whole_file > 0)
218 return True;
219 if (whole_file == 0 || write_batch || read_batch)
220 return False;
221 return local_server;
222}
223
224
225/*
226 * Generate and send a stream of signatures/checksums that describe a buffer
227 *
228 * Generate approximately one checksum every block_len bytes.
229 */
230static void generate_and_send_sums(struct map_struct *buf, size_t len, int f_out)
231{
232 size_t i;
233 struct sum_struct sum;
234 OFF_T offset = 0;
235
236 sum_sizes_sqroot(&sum, len);
237
238 write_sum_head(f_out, &sum);
239
240 for (i = 0; i < sum.count; i++) {
241 unsigned int n1 = MIN(len, sum.blength);
242 char *map = map_ptr(buf, offset, n1);
243 uint32 sum1 = get_checksum1(map, n1);
244 char sum2[SUM_LENGTH];
245
246 get_checksum2(map, n1, sum2);
247
248 if (verbose > 3) {
249 rprintf(FINFO,
250 "chunk[%.0f] offset=%.0f len=%u sum1=%08lx\n",
251 (double)i, (double)offset, n1,
252 (unsigned long)sum1);
253 }
254 write_int(f_out, sum1);
255 write_buf(f_out, sum2, sum.s2length);
256 len -= n1;
257 offset += n1;
258 }
259}
260
261
262
263/**
264 * Acts on file number @p i from @p flist, whose name is @p fname.
265 *
266 * First fixes up permissions, then generates checksums for the file.
267 *
268 * @note This comment was added later by mbp who was trying to work it
269 * out. It might be wrong.
270 **/
271void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
272{
273 int fd;
274 STRUCT_STAT st;
275 struct map_struct *mapbuf;
276 int statret;
277 char *fnamecmp;
278 char fnamecmpbuf[MAXPATHLEN];
279
280 if (list_only)
281 return;
282
283 if (verbose > 2)
284 rprintf(FINFO,"recv_generator(%s,%d)\n",fname,i);
285
286 if (server_exclude_list.head
287 && check_exclude(&server_exclude_list, fname,
288 S_ISDIR(file->mode)) < 0)
289 return;
290
291 statret = link_stat(fname,&st);
292
293 if (only_existing && statret == -1 && errno == ENOENT) {
294 /* we only want to update existing files */
295 if (verbose > 1) rprintf(FINFO, "not creating new file \"%s\"\n",fname);
296 return;
297 }
298
299 if (statret == 0 &&
300 !preserve_perms &&
301 (S_ISDIR(st.st_mode) == S_ISDIR(file->mode))) {
302 /* if the file exists already and we aren't perserving
303 * permissions then act as though the remote end sent
304 * us the file permissions we already have */
305 file->mode = (file->mode & ~CHMOD_BITS)
306 | (st.st_mode & CHMOD_BITS);
307 }
308
309 if (S_ISDIR(file->mode)) {
310 /* The file to be received is a directory, so we need
311 * to prepare appropriately. If there is already a
312 * file of that name and it is *not* a directory, then
313 * we need to delete it. If it doesn't exist, then
314 * recursively create it. */
315
316 if (dry_run) return; /* XXXX -- might cause inaccuracies?? -- mbp */
317 if (statret == 0 && !S_ISDIR(st.st_mode)) {
318 if (robust_unlink(fname) != 0) {
319 rsyserr(FERROR, errno,
320 "recv_generator: unlink %s to make room for directory",
321 full_fname(fname));
322 return;
323 }
324 statret = -1;
325 }
326 if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
327 if (!(relative_paths && errno == ENOENT
328 && create_directory_path(fname, orig_umask) == 0
329 && do_mkdir(fname, file->mode) == 0)) {
330 rsyserr(FERROR, errno,
331 "recv_generator: mkdir %s failed",
332 full_fname(fname));
333 }
334 }
335 /* f_out is set to -1 when doing final directory
336 permission and modification time repair */
337 if (set_perms(fname,file,NULL,0) && verbose && (f_out != -1))
338 rprintf(FINFO,"%s/\n",fname);
339 return;
340 }
341
342 if (preserve_links && S_ISLNK(file->mode)) {
343#if SUPPORT_LINKS
344 char lnk[MAXPATHLEN];
345 int l;
346
347 if (safe_symlinks && unsafe_symlink(file->u.link, fname)) {
348 if (verbose) {
349 rprintf(FINFO, "ignoring unsafe symlink %s -> \"%s\"\n",
350 full_fname(fname), file->u.link);
351 }
352 return;
353 }
354 if (statret == 0) {
355 l = readlink(fname,lnk,MAXPATHLEN-1);
356 if (l > 0) {
357 lnk[l] = 0;
358 /* A link already pointing to the
359 * right place -- no further action
360 * required. */
361 if (strcmp(lnk,file->u.link) == 0) {
362 set_perms(fname, file, &st,
363 PERMS_REPORT);
364 return;
365 }
366 }
367 /* Not a symlink, so delete whatever's
368 * already there and put a new symlink
369 * in place. */
370 delete_file(fname);
371 }
372 if (do_symlink(file->u.link,fname) != 0) {
373 rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed",
374 full_fname(fname), file->u.link);
375 } else {
376 set_perms(fname,file,NULL,0);
377 if (verbose) {
378 rprintf(FINFO,"%s -> %s\n", fname,file->u.link);
379 }
380 }
381#endif
382 return;
383 }
384
385#ifdef HAVE_MKNOD
386 if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
387 if (statret != 0 ||
388 st.st_mode != file->mode ||
389 st.st_rdev != file->u.rdev) {
390 delete_file(fname);
391 if (verbose > 2) {
392 rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
393 fname,(int)file->mode,(int)file->u.rdev);
394 }
395 if (do_mknod(fname,file->mode,file->u.rdev) != 0) {
396 rsyserr(FERROR, errno, "mknod %s failed",
397 full_fname(fname));
398 } else {
399 set_perms(fname,file,NULL,0);
400 if (verbose)
401 rprintf(FINFO,"%s\n",fname);
402 }
403 } else {
404 set_perms(fname, file, &st, PERMS_REPORT);
405 }
406 return;
407 }
408#endif
409
410 if (preserve_hard_links && hard_link_check(file, HL_CHECK_MASTER))
411 return;
412
413 if (!S_ISREG(file->mode)) {
414 rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname);
415 return;
416 }
417
418 fnamecmp = fname;
419
420 if (statret == -1 && compare_dest != NULL) {
421 /* try the file at compare_dest instead */
422 int saveerrno = errno;
423 pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, compare_dest, fname);
424 statret = link_stat(fnamecmpbuf,&st);
425 if (!S_ISREG(st.st_mode))
426 statret = -1;
427 if (statret == -1)
428 errno = saveerrno;
429#if HAVE_LINK
430 else if (link_dest && !dry_run) {
431 if (do_link(fnamecmpbuf, fname) != 0) {
432 if (verbose > 0) {
433 rsyserr(FINFO, errno, "link %s => %s",
434 fnamecmpbuf, fname);
435 }
436 }
437 fnamecmp = fnamecmpbuf;
438 }
439#endif
440 else
441 fnamecmp = fnamecmpbuf;
442 }
443
444 if (statret == -1) {
445 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
446 return;
447 if (errno == ENOENT) {
448 write_int(f_out,i);
449 if (!dry_run) write_sum_head(f_out, NULL);
450 } else if (verbose > 1) {
451 rsyserr(FERROR, errno,
452 "recv_generator: failed to open %s",
453 full_fname(fname));
454 }
455 return;
456 }
457
458 if (!S_ISREG(st.st_mode)) {
459 if (delete_file(fname) != 0) {
460 return;
461 }
462
463 /* now pretend the file didn't exist */
464 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
465 return;
466 write_int(f_out,i);
467 if (!dry_run) write_sum_head(f_out, NULL);
468 return;
469 }
470
471 if (opt_ignore_existing && fnamecmp == fname) {
472 if (verbose > 1)
473 rprintf(FINFO,"%s exists\n",fname);
474 return;
475 }
476
477 if (update_only && cmp_modtime(st.st_mtime,file->modtime)>0 && fnamecmp == fname) {
478 if (verbose > 1)
479 rprintf(FINFO,"%s is newer\n",fname);
480 return;
481 }
482
483 if (skip_file(fname, file, &st)) {
484 if (fnamecmp == fname)
485 set_perms(fname, file, &st, PERMS_REPORT);
486 return;
487 }
488
489 if (dry_run) {
490 write_int(f_out,i);
491 return;
492 }
493
494 if (disable_deltas_p()) {
495 write_int(f_out,i);
496 write_sum_head(f_out, NULL);
497 return;
498 }
499
500 /* open the file */
501 fd = do_open(fnamecmp, O_RDONLY, 0);
502
503 if (fd == -1) {
504 rsyserr(FERROR, errno, "failed to open %s, continuing",
505 full_fname(fnamecmp));
506 /* pretend the file didn't exist */
507 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
508 return;
509 write_int(f_out,i);
510 write_sum_head(f_out, NULL);
511 return;
512 }
513
514 if (st.st_size > 0)
515 mapbuf = map_file(fd,st.st_size);
516 else
517 mapbuf = NULL;
518
519 if (verbose > 3) {
520 rprintf(FINFO,"gen mapped %s of size %.0f\n", fnamecmp,
521 (double)st.st_size);
522 }
523
524 if (verbose > 2)
525 rprintf(FINFO, "generating and sending sums for %d\n", i);
526
527 write_int(f_out,i);
528 generate_and_send_sums(mapbuf, st.st_size, f_out);
529
530 close(fd);
531 if (mapbuf) unmap_file(mapbuf);
532}
533
534
535void generate_files(int f, struct file_list *flist, char *local_name)
536{
537 int i;
538 int phase=0;
539 char fbuf[MAXPATHLEN];
540
541 if (verbose > 2) {
542 rprintf(FINFO, "generator starting pid=%ld count=%d\n",
543 (long)getpid(), flist->count);
544 }
545
546 if (verbose >= 2) {
547 rprintf(FINFO,
548 disable_deltas_p()
549 ? "delta-transmission disabled for local transfer or --whole-file\n"
550 : "delta transmission enabled\n");
551 }
552
553 /* we expect to just sit around now, so don't exit on a
554 timeout. If we really get a timeout then the other process should
555 exit */
556 io_timeout = 0;
557
558 for (i = 0; i < flist->count; i++) {
559 struct file_struct *file = flist->files[i];
560 struct file_struct copy;
561
562 if (!file->basename)
563 continue;
564 /* we need to ensure that any directories we create have writeable
565 permissions initially so that we can create the files within
566 them. This is then fixed after the files are transferred */
567 if (!am_root && S_ISDIR(file->mode) && !(file->mode & S_IWUSR)) {
568 copy = *file;
569 /* XXX: Could this be causing a problem on SCO? Perhaps their
570 * handling of permissions is strange? */
571 copy.mode |= S_IWUSR; /* user write */
572 file = &copy;
573 }
574
575 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
576 file, i, f);
577 }
578
579 phase++;
580 csum_length = SUM_LENGTH;
581 ignore_times=1;
582
583 if (verbose > 2)
584 rprintf(FINFO,"generate_files phase=%d\n",phase);
585
586 write_int(f,-1);
587
588 /* files can cycle through the system more than once
589 * to catch initial checksum errors */
590 while ((i = get_redo_num()) != -1) {
591 struct file_struct *file = flist->files[i];
592 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
593 file, i, f);
594 }
595
596 phase++;
597 if (verbose > 2)
598 rprintf(FINFO,"generate_files phase=%d\n",phase);
599
600 write_int(f,-1);
601
602 if (preserve_hard_links)
603 do_hard_links();
604
605 /* now we need to fix any directory permissions that were
606 * modified during the transfer */
607 for (i = 0; i < flist->count; i++) {
608 struct file_struct *file = flist->files[i];
609 if (!file->basename || !S_ISDIR(file->mode)) continue;
610 recv_generator(local_name ? local_name : f_name(file),
611 file, i, -1);
612 }
613
614 if (verbose > 2)
615 rprintf(FINFO,"generate_files finished\n");
616}