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