Improved description of --whole-file option.
[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;
3ea9bbd6
WD
37extern int preserve_times;
38extern int omit_dir_times;
fa13f396 39extern int delete_during;
2f03f956 40extern int update_only;
3d6feada 41extern int opt_ignore_existing;
cd6aa5b5
WD
42extern int inplace;
43extern int make_backups;
2f03f956
AT
44extern int csum_length;
45extern int ignore_times;
f83f0548 46extern int size_only;
7d1bfaf7 47extern OFF_T max_size;
2f03f956 48extern int io_timeout;
d04e9c51 49extern int protocol_version;
8e85be0a 50extern int fuzzy_basis;
2f03f956 51extern int always_checksum;
a7260c40 52extern char *partial_dir;
b7e8628c 53extern char *basis_dir[];
2be2fb3e 54extern int compare_dest;
59c95e42 55extern int link_dest;
5774786f
WD
56extern int whole_file;
57extern int local_server;
5774786f 58extern int list_only;
b9f592fb 59extern int read_batch;
5774786f
WD
60extern int only_existing;
61extern int orig_umask;
62extern int safe_symlinks;
a255c592 63extern long block_size; /* "long" because popt can't set an int32. */
2f03f956 64
7842418b 65extern struct filter_list_struct server_filter_list;
97f9dcae 66
b7e8628c 67static int unchanged_attrs(struct file_struct *file, STRUCT_STAT *st)
2f03f956 68{
b7e8628c
WD
69 if (preserve_perms
70 && (st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS))
84acca07 71 return 0;
bb24028f 72
b7e8628c
WD
73 if (am_root && preserve_uid && st->st_uid != file->uid)
74 return 0;
bb24028f 75
b7e8628c
WD
76 if (preserve_gid && file->gid != GID_NONE && st->st_gid != file->gid)
77 return 0;
78
79 return 1;
80}
81
82/* Perform our quick-check heuristic for determining if a file is unchanged. */
83static int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
84{
85 if (st->st_size != file->length)
86 return 0;
59c95e42 87
2cda2560 88 /* if always checksum is set then we use the checksum instead
2f03f956
AT
89 of the file time to determine whether to sync */
90 if (always_checksum && S_ISREG(st->st_mode)) {
91 char sum[MD4_SUM_LENGTH];
b7e8628c 92 file_checksum(fn, sum, st->st_size);
728d0922 93 return memcmp(sum, file->u.sum, protocol_version < 21 ? 2
84acca07 94 : MD4_SUM_LENGTH) == 0;
2f03f956
AT
95 }
96
cc1e997d 97 if (size_only)
84acca07 98 return 1;
2f03f956 99
cc1e997d 100 if (ignore_times)
84acca07 101 return 0;
cc1e997d 102
84acca07 103 return cmp_modtime(st->st_mtime, file->modtime) == 0;
2f03f956
AT
104}
105
106
ec8290c8 107/*
195bd906 108 * set (initialize) the size entries in the per-file sum_struct
ec8290c8 109 * calculating dynamic block and checksum sizes.
195bd906 110 *
ec8290c8 111 * This is only called from generate_and_send_sums() but is a separate
195bd906
S
112 * function to encapsulate the logic.
113 *
114 * The block size is a rounded square root of file length.
115 *
116 * The checksum size is determined according to:
117 * blocksum_bits = BLOCKSUM_EXP + 2*log2(file_len) - log2(block_len)
118 * provided by Donovan Baarda which gives a probability of rsync
119 * algorithm corrupting data and falling back using the whole md4
120 * checksums.
121 *
122 * This might be made one of several selectable heuristics.
123 */
1490812a 124static void sum_sizes_sqroot(struct sum_struct *sum, int64 len)
195bd906 125{
a255c592 126 int32 blength;
da9d12f5 127 int s2length;
195bd906 128
a255c592 129 if (block_size)
195bd906 130 blength = block_size;
a255c592 131 else if (len <= BLOCK_SIZE * BLOCK_SIZE)
195bd906 132 blength = BLOCK_SIZE;
a255c592
WD
133 else {
134 int32 c;
1490812a 135 int64 l;
eae7165c
WD
136 int cnt;
137 for (c = 1, l = len, cnt = 0; l >>= 2; c <<= 1, cnt++) {}
138 if (cnt >= 31 || c >= MAX_BLOCK_SIZE)
139 blength = MAX_BLOCK_SIZE;
140 else {
141 blength = 0;
142 do {
143 blength |= c;
1490812a 144 if (len < (int64)blength * blength)
eae7165c
WD
145 blength &= ~c;
146 c >>= 1;
147 } while (c >= 8); /* round to multiple of 8 */
148 blength = MAX(blength, BLOCK_SIZE);
195bd906 149 }
195bd906
S
150 }
151
d04e9c51 152 if (protocol_version < 27) {
195bd906
S
153 s2length = csum_length;
154 } else if (csum_length == SUM_LENGTH) {
155 s2length = SUM_LENGTH;
156 } else {
a255c592 157 int32 c;
1490812a 158 int64 l;
da9d12f5 159 int b = BLOCKSUM_BIAS;
a255c592
WD
160 for (l = len; l >>= 1; b += 2) {}
161 for (c = blength; c >>= 1 && b; b--) {}
162 /* add a bit, subtract rollsum, round up. */
163 s2length = (b + 1 - 32 + 7) / 8; /* --optimize in compiler-- */
195bd906
S
164 s2length = MAX(s2length, csum_length);
165 s2length = MIN(s2length, SUM_LENGTH);
166 }
167
168 sum->flength = len;
169 sum->blength = blength;
170 sum->s2length = s2length;
171 sum->count = (len + (blength - 1)) / blength;
172 sum->remainder = (len % blength);
173
174 if (sum->count && verbose > 2) {
a255c592
WD
175 rprintf(FINFO,
176 "count=%.0f rem=%ld blength=%ld s2length=%d flength=%.0f\n",
177 (double)sum->count, (long)sum->remainder, (long)sum->blength,
da9d12f5 178 sum->s2length, (double)sum->flength);
195bd906
S
179 }
180}
80605142 181
bceec82f 182
80605142
WD
183/*
184 * Generate and send a stream of signatures/checksums that describe a buffer
e66dfd18 185 *
80605142
WD
186 * Generate approximately one checksum every block_len bytes.
187 */
cd6aa5b5 188static void generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy)
2f03f956 189{
80605142 190 size_t i;
6e45e1dd 191 struct map_struct *mapbuf;
80605142 192 struct sum_struct sum;
2f03f956
AT
193 OFF_T offset = 0;
194
423dba8e 195 sum_sizes_sqroot(&sum, len);
e66dfd18 196
6e45e1dd 197 if (len > 0)
96d910c7 198 mapbuf = map_file(fd, len, MAX_MAP_SIZE, sum.blength);
6e45e1dd
WD
199 else
200 mapbuf = NULL;
201
fc0257c9 202 write_sum_head(f_out, &sum);
2f03f956 203
80605142 204 for (i = 0; i < sum.count; i++) {
a255c592 205 int32 n1 = (int32)MIN(len, (OFF_T)sum.blength);
6e45e1dd 206 char *map = map_ptr(mapbuf, offset, n1);
80605142
WD
207 uint32 sum1 = get_checksum1(map, n1);
208 char sum2[SUM_LENGTH];
2f03f956 209
cd6aa5b5
WD
210 if (f_copy >= 0)
211 full_write(f_copy, map, n1);
212
80605142 213 get_checksum2(map, n1, sum2);
2f03f956 214
80605142 215 if (verbose > 3) {
e66dfd18 216 rprintf(FINFO,
a255c592
WD
217 "chunk[%.0f] offset=%.0f len=%ld sum1=%08lx\n",
218 (double)i, (double)offset, (long)n1,
0e36d9da 219 (unsigned long)sum1);
80605142
WD
220 }
221 write_int(f_out, sum1);
fc0257c9 222 write_buf(f_out, sum2, sum.s2length);
2f03f956
AT
223 len -= n1;
224 offset += n1;
225 }
6e45e1dd
WD
226
227 if (mapbuf)
228 unmap_file(mapbuf);
2f03f956
AT
229}
230
8e85be0a
WD
231/* Try to find a filename in the same dir as "fname" with a similar name. */
232static int find_fuzzy(struct file_struct *file, struct file_list *dirlist)
233{
234 int fname_len, fname_suf_len;
235 const char *fname_suf, *fname = file->basename;
236 uint32 lowest_dist = 0x7FFFFFFF;
237 int j, lowest_j = -1;
238
239 fname_len = strlen(fname);
240 fname_suf = find_filename_suffix(fname, fname_len, &fname_suf_len);
241
242 for (j = 0; j < dirlist->count; j++) {
243 struct file_struct *fp = dirlist->files[j];
244 const char *suf, *name;
245 int len, suf_len;
246 uint32 dist;
247
248 if (!S_ISREG(fp->mode) || !fp->length
249 || fp->flags & FLAG_NO_FUZZY)
250 continue;
251
252 name = fp->basename;
253
254 if (fp->length == file->length
255 && fp->modtime == file->modtime) {
256 if (verbose > 4) {
257 rprintf(FINFO,
258 "fuzzy size/modtime match for %s\n",
259 name);
260 }
261 return j;
262 }
263
264 len = strlen(name);
265 suf = find_filename_suffix(name, len, &suf_len);
266
267 dist = fuzzy_distance(name, len, fname, fname_len);
268 /* Add some extra weight to how well the suffixes match. */
269 dist += fuzzy_distance(suf, suf_len, fname_suf, fname_suf_len)
270 * 10;
271 if (verbose > 4) {
272 rprintf(FINFO, "fuzzy distance for %s = %d.%05d\n",
273 name, (int)(dist>>16), (int)(dist&0xFFFF));
274 }
275 if (dist <= lowest_dist) {
276 lowest_dist = dist;
277 lowest_j = j;
278 }
279 }
280
281 return lowest_j;
282}
283
2f03f956 284
0492fdfb
WD
285/* Acts on flist->file's ndx'th item, whose name is fname. If a directory,
286 * make sure it exists, and has the right permissions/timestamp info. For
287 * all other non-regular files (symlinks, etc.) we create them here. For
288 * regular files that have changed, we try to find a basis file and then
289 * start sending checksums.
ef1aa910 290 *
0492fdfb
WD
291 * Note that f_out is set to -1 when doing final directory-permission and
292 * modification-time repair. */
fa13f396 293static void recv_generator(char *fname, struct file_list *flist,
0492fdfb 294 struct file_struct *file, int ndx,
41cfde6b 295 int f_out, int f_out_name)
2cda2560 296{
df337831 297 static int missing_below = -1;
8e85be0a
WD
298 static char *fuzzy_dirname = NULL;
299 static struct file_list *fuzzy_dirlist = NULL;
300 struct file_struct *fuzzy_file = NULL;
41cfde6b 301 int fd = -1, f_copy = -1;
89f7eff3 302 STRUCT_STAT st, partial_st;
41cfde6b 303 struct file_struct *back_file = NULL;
e7d13fe5 304 int statret, stat_errno;
41cfde6b 305 char *fnamecmp, *partialptr, *backupptr = NULL;
375a4556 306 char fnamecmpbuf[MAXPATHLEN];
41cfde6b 307 uchar fnamecmp_type;
f7632fc6 308
dfd5ba6a
WD
309 if (list_only)
310 return;
2f03f956 311
8e85be0a
WD
312 if (!fname) {
313 if (fuzzy_dirlist) {
314 flist_free(fuzzy_dirlist);
315 fuzzy_dirlist = NULL;
316 fuzzy_dirname = NULL;
317 }
318 if (missing_below >= 0) {
319 dry_run--;
320 missing_below = -1;
321 }
322 return;
323 }
324
4875d6b6
WD
325 if (verbose > 2) {
326 rprintf(FINFO, "recv_generator(%s,%d)\n",
327 safe_fname(fname), ndx);
328 }
2f03f956 329
7842418b
WD
330 if (server_filter_list.head
331 && check_filter(&server_filter_list, fname,
332 S_ISDIR(file->mode)) < 0) {
3e35c34b
WD
333 if (verbose) {
334 rprintf(FINFO, "skipping server-excluded file \"%s\"\n",
ecc81fce 335 safe_fname(fname));
3e35c34b 336 }
97f9dcae 337 return;
3e35c34b 338 }
97f9dcae 339
8e85be0a 340 if (missing_below >= 0 && file->dir.depth <= missing_below) {
df337831
WD
341 dry_run--;
342 missing_below = -1;
343 }
73f7af0e
WD
344 if (dry_run > 1) {
345 statret = -1;
346 stat_errno = ENOENT;
347 } else {
8e85be0a
WD
348 if (fuzzy_basis && S_ISREG(file->mode)) {
349 char *dn = file->dirname ? file->dirname : ".";
350 /* Yes, identical dirnames are guaranteed to have
351 * identical pointers at this point. */
352 if (fuzzy_dirname != dn) {
353 if (fuzzy_dirlist)
354 flist_free(fuzzy_dirlist);
355 fuzzy_dirname = dn;
356 fuzzy_dirlist = get_dirlist(fuzzy_dirname, 1);
357 }
358 }
359
73f7af0e
WD
360 statret = link_stat(fname, &st,
361 keep_dirlinks && S_ISDIR(file->mode));
362 stat_errno = errno;
363 }
63787382 364
a7260c40 365 if (only_existing && statret == -1 && stat_errno == ENOENT) {
1347d512 366 /* we only want to update existing files */
ecc81fce
WD
367 if (verbose > 1) {
368 rprintf(FINFO, "not creating new file \"%s\"\n",
369 safe_fname(fname));
370 }
1347d512
AT
371 return;
372 }
373
d9b4d267
WD
374 if (statret == 0 && !preserve_perms
375 && S_ISDIR(st.st_mode) == S_ISDIR(file->mode)) {
4df9f368 376 /* if the file exists already and we aren't perserving
2cda2560
WD
377 * permissions then act as though the remote end sent
378 * us the file permissions we already have */
67e78a82
WD
379 file->mode = (file->mode & ~CHMOD_BITS)
380 | (st.st_mode & CHMOD_BITS);
4df9f368
AT
381 }
382
2f03f956 383 if (S_ISDIR(file->mode)) {
2cda2560
WD
384 /* The file to be received is a directory, so we need
385 * to prepare appropriately. If there is already a
386 * file of that name and it is *not* a directory, then
387 * we need to delete it. If it doesn't exist, then
027428eb 388 * (perhaps recursively) create it. */
2f03f956 389 if (statret == 0 && !S_ISDIR(st.st_mode)) {
7e38410e 390 delete_file(fname, DEL_TERSE);
2f03f956
AT
391 statret = -1;
392 }
df337831
WD
393 if (dry_run && statret != 0 && missing_below < 0) {
394 missing_below = file->dir.depth;
395 dry_run++;
396 }
2f03f956 397 if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
027428eb
WD
398 if (!relative_paths || errno != ENOENT
399 || create_directory_path(fname, orig_umask) < 0
400 || do_mkdir(fname, file->mode) < 0) {
d62bcc17
WD
401 rsyserr(FERROR, errno,
402 "recv_generator: mkdir %s failed",
403 full_fname(fname));
2f03f956
AT
404 }
405 }
716e73d4
WD
406 if (set_perms(fname, file, statret ? NULL : &st, 0)
407 && verbose && f_out != -1)
ecc81fce 408 rprintf(FINFO, "%s/\n", safe_fname(fname));
c93fad5e 409 if (delete_during && f_out != -1 && csum_length != SUM_LENGTH
31937d36
WD
410 && (file->flags & FLAG_DEL_HERE))
411 delete_in_dir(flist, fname, file);
2f03f956 412 return;
7d1bfaf7 413 } else if (max_size && file->length > max_size) {
4875d6b6
WD
414 if (verbose > 1) {
415 rprintf(FINFO, "%s is over max-size\n",
416 safe_fname(fname));
417 }
7d1bfaf7 418 return;
2f03f956
AT
419 }
420
421 if (preserve_links && S_ISLNK(file->mode)) {
4f5b0756 422#ifdef SUPPORT_LINKS
728d0922 423 if (safe_symlinks && unsafe_symlink(file->u.link, fname)) {
2f03f956 424 if (verbose) {
4875d6b6
WD
425 rprintf(FINFO,
426 "ignoring unsafe symlink %s -> \"%s\"\n",
427 full_fname(fname),
428 safe_fname(file->u.link));
2f03f956
AT
429 }
430 return;
431 }
432 if (statret == 0) {
7e38410e
WD
433 int dflag = S_ISDIR(st.st_mode) ? DEL_DIR : 0;
434 char lnk[MAXPATHLEN];
435 int len;
436
437 if (!dflag
438 && (len = readlink(fname, lnk, MAXPATHLEN-1)) > 0) {
439 lnk[len] = 0;
85d4d142
MP
440 /* A link already pointing to the
441 * right place -- no further action
442 * required. */
7e38410e 443 if (strcmp(lnk, file->u.link) == 0) {
c41b52c4
WD
444 set_perms(fname, file, &st,
445 PERMS_REPORT);
2f03f956
AT
446 return;
447 }
2cda2560 448 }
7e38410e
WD
449 /* Not the right symlink (or not a symlink), so
450 * delete it. */
451 delete_file(fname, dflag | DEL_TERSE);
2f03f956 452 }
728d0922 453 if (do_symlink(file->u.link,fname) != 0) {
d62bcc17 454 rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed",
ecc81fce 455 full_fname(fname), safe_fname(file->u.link));
2f03f956
AT
456 } else {
457 set_perms(fname,file,NULL,0);
458 if (verbose) {
ecc81fce
WD
459 rprintf(FINFO, "%s -> %s\n", safe_fname(fname),
460 safe_fname(file->u.link));
2f03f956
AT
461 }
462 }
463#endif
464 return;
465 }
466
2f03f956 467 if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
2cda2560 468 if (statret != 0 ||
2f03f956 469 st.st_mode != file->mode ||
3915fd75 470 st.st_rdev != file->u.rdev) {
7e38410e
WD
471 int dflag = S_ISDIR(st.st_mode) ? DEL_DIR : 0;
472 delete_file(fname, dflag | DEL_TERSE);
d62bcc17 473 if (verbose > 2) {
2f03f956 474 rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
ecc81fce
WD
475 safe_fname(fname),
476 (int)file->mode, (int)file->u.rdev);
d62bcc17 477 }
728d0922 478 if (do_mknod(fname,file->mode,file->u.rdev) != 0) {
d62bcc17
WD
479 rsyserr(FERROR, errno, "mknod %s failed",
480 full_fname(fname));
2f03f956
AT
481 } else {
482 set_perms(fname,file,NULL,0);
ecc81fce
WD
483 if (verbose) {
484 rprintf(FINFO, "%s\n",
485 safe_fname(fname));
486 }
2f03f956
AT
487 }
488 } else {
c41b52c4 489 set_perms(fname, file, &st, PERMS_REPORT);
2f03f956
AT
490 }
491 return;
492 }
2f03f956 493
6dff5992 494 if (preserve_hard_links && hard_link_check(file, HL_CHECK_MASTER))
2f03f956 495 return;
2f03f956
AT
496
497 if (!S_ISREG(file->mode)) {
ecc81fce
WD
498 rprintf(FINFO, "skipping non-regular file \"%s\"\n",
499 safe_fname(fname));
2f03f956
AT
500 return;
501 }
502
375a4556 503 fnamecmp = fname;
41cfde6b 504 fnamecmp_type = FNAMECMP_FNAME;
375a4556 505
b7e8628c
WD
506 if (statret == -1 && basis_dir[0] != NULL) {
507 int fallback_match = -1;
508 int match_level = 0;
509 int i = 0;
510 do {
511 pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
512 basis_dir[i], fname);
513 if (link_stat(fnamecmpbuf, &st, 0) == 0
514 && S_ISREG(st.st_mode)) {
515 statret = 0;
516 if (link_dest) {
517 if (!match_level) {
518 fallback_match = i;
519 match_level = 1;
520 } else if (match_level == 2
521 && !unchanged_attrs(file, &st))
522 continue;
523 if (!unchanged_file(fnamecmpbuf, file, &st))
524 continue;
525 fallback_match = i;
526 match_level = 2;
527 if (!unchanged_attrs(file, &st))
528 continue;
529 }
530 match_level = 3;
531 break;
532 }
533 } while (basis_dir[++i] != NULL);
534 if (statret == 0) {
535 if (match_level < 3) {
536 i = fallback_match;
537 pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
538 basis_dir[i], fname);
539 }
4f5b0756 540#ifdef HAVE_LINK
b7e8628c 541 if (link_dest && match_level == 3 && !dry_run) {
e7d13fe5
WD
542 if (do_link(fnamecmpbuf, fname) < 0) {
543 if (verbose) {
544 rsyserr(FINFO, errno,
545 "link %s => %s",
4875d6b6 546 full_fname(fnamecmpbuf),
e7d13fe5
WD
547 safe_fname(fname));
548 }
549 fnamecmp = fnamecmpbuf;
2be2fb3e 550 fnamecmp_type = i;
e7bc9b64 551 }
e7d13fe5 552 } else
59c95e42 553#endif
41cfde6b 554 {
e7d13fe5 555 fnamecmp = fnamecmpbuf;
2be2fb3e 556 fnamecmp_type = i;
41cfde6b 557 }
e7d13fe5
WD
558 }
559 }
560
561 if (statret == 0 && !S_ISREG(st.st_mode)) {
7e38410e
WD
562 int dflag = S_ISDIR(st.st_mode) ? DEL_DIR : 0;
563 if (delete_file(fname, dflag | DEL_TERSE) != 0)
e7d13fe5
WD
564 return;
565 statret = -1;
566 stat_errno = ENOENT;
375a4556
DD
567 }
568
9d954dca 569 if (partial_dir && (partialptr = partial_dir_fname(fname)) != NULL
72c19bb3
WD
570 && link_stat(partialptr, &partial_st, 0) == 0
571 && S_ISREG(partial_st.st_mode)) {
572 if (statret == -1)
573 goto prepare_to_open;
574 } else
575 partialptr = NULL;
89f7eff3 576
8e85be0a
WD
577 if (statret == -1 && fuzzy_basis && dry_run <= 1) {
578 int j = find_fuzzy(file, fuzzy_dirlist);
579 if (j >= 0) {
580 fuzzy_file = fuzzy_dirlist->files[j];
581 f_name_to(fuzzy_file, fnamecmpbuf);
582 if (verbose > 2) {
583 rprintf(FINFO, "fuzzy basis selected for %s: %s\n",
584 safe_fname(fname), safe_fname(fnamecmpbuf));
585 }
586 st.st_mode = fuzzy_file->mode;
587 st.st_size = fuzzy_file->length;
588 st.st_mtime = fuzzy_file->modtime;
589 statret = 0;
590 fnamecmp = fnamecmpbuf;
591 fnamecmp_type = FNAMECMP_FUZZY;
592 }
593 }
594
2f03f956 595 if (statret == -1) {
6dff5992
WD
596 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
597 return;
41cfde6b
WD
598 if (stat_errno == ENOENT)
599 goto notify_others;
600 if (verbose > 1) {
e7d13fe5
WD
601 rsyserr(FERROR, stat_errno,
602 "recv_generator: failed to stat %s",
d62bcc17 603 full_fname(fname));
2f03f956
AT
604 }
605 return;
606 }
607
41cfde6b 608 if (opt_ignore_existing && fnamecmp_type == FNAMECMP_FNAME) {
3d6feada 609 if (verbose > 1)
ecc81fce 610 rprintf(FINFO, "%s exists\n", safe_fname(fname));
3d6feada 611 return;
2cda2560 612 }
3d6feada 613
41cfde6b 614 if (update_only && fnamecmp_type == FNAMECMP_FNAME
d3a4375f 615 && cmp_modtime(st.st_mtime, file->modtime) > 0) {
2f03f956 616 if (verbose > 1)
ecc81fce 617 rprintf(FINFO, "%s is newer\n", safe_fname(fname));
2f03f956
AT
618 return;
619 }
620
2be2fb3e 621 if (!compare_dest && fnamecmp_type <= FNAMECMP_BASIS_DIR_HIGH)
b7e8628c 622 ;
8e85be0a
WD
623 else if (fnamecmp_type == FNAMECMP_FUZZY)
624 ;
b7e8628c 625 else if (unchanged_file(fnamecmp, file, &st)) {
41cfde6b 626 if (fnamecmp_type == FNAMECMP_FNAME)
c41b52c4 627 set_perms(fname, file, &st, PERMS_REPORT);
2f03f956
AT
628 return;
629 }
630
89f7eff3 631prepare_to_open:
9d954dca
WD
632 if (partialptr) {
633 st = partial_st;
634 fnamecmp = partialptr;
635 fnamecmp_type = FNAMECMP_PARTIAL_DIR;
636 statret = 0;
637 }
638
3841a04e
WD
639 if (dry_run || read_batch)
640 goto notify_others;
641 if (whole_file > 0) {
41cfde6b
WD
642 statret = -1;
643 goto notify_others;
2f03f956
AT
644 }
645
8e85be0a
WD
646 if (fuzzy_basis) {
647 int j = flist_find(fuzzy_dirlist, file);
648 if (j >= 0) /* don't use changing file as future fuzzy basis */
649 fuzzy_dirlist->files[j]->flags |= FLAG_NO_FUZZY;
650 }
651
2cda2560 652 /* open the file */
8c9fd200 653 fd = do_open(fnamecmp, O_RDONLY, 0);
2f03f956
AT
654
655 if (fd == -1) {
d62bcc17
WD
656 rsyserr(FERROR, errno, "failed to open %s, continuing",
657 full_fname(fnamecmp));
cd6aa5b5 658 pretend_missing:
60be6acf 659 /* pretend the file didn't exist */
6dff5992
WD
660 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
661 return;
41cfde6b
WD
662 statret = -1;
663 goto notify_others;
2f03f956
AT
664 }
665
cd6aa5b5
WD
666 if (inplace && make_backups) {
667 if (!(backupptr = get_backup_name(fname))) {
668 close(fd);
669 return;
670 }
7842418b 671 if (!(back_file = make_file(fname, NULL, NO_FILTERS))) {
cd6aa5b5
WD
672 close(fd);
673 goto pretend_missing;
674 }
675 if (robust_unlink(backupptr) && errno != ENOENT) {
676 rsyserr(FERROR, errno, "unlink %s",
677 full_fname(backupptr));
678 free(back_file);
679 close(fd);
680 return;
681 }
682 if ((f_copy = do_open(backupptr,
683 O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) {
684 rsyserr(FERROR, errno, "open %s",
685 full_fname(backupptr));
686 free(back_file);
687 close(fd);
688 return;
689 }
41cfde6b 690 fnamecmp_type = FNAMECMP_BACKUP;
cd6aa5b5
WD
691 }
692
dfd5ba6a 693 if (verbose > 3) {
ecc81fce
WD
694 rprintf(FINFO, "gen mapped %s of size %.0f\n",
695 safe_fname(fnamecmp), (double)st.st_size);
dfd5ba6a 696 }
2f03f956 697
2f03f956 698 if (verbose > 2)
0492fdfb 699 rprintf(FINFO, "generating and sending sums for %d\n", ndx);
2f03f956 700
41cfde6b 701notify_others:
0492fdfb 702 write_int(f_out, ndx);
17b5b32f
WD
703 if (protocol_version >= 29 && inplace && !read_batch)
704 write_byte(f_out, fnamecmp_type);
8e85be0a 705 if (f_out_name >= 0) {
41cfde6b 706 write_byte(f_out_name, fnamecmp_type);
8e85be0a
WD
707 if (fnamecmp_type == FNAMECMP_FUZZY) {
708 uchar lenbuf[3], *lb = lenbuf;
709 int len = strlen(fuzzy_file->basename);
710 if (len > 0x7F) {
711#if MAXPATHLEN > 0x7FFF
712 *lb++ = len / 0x10000 + 0x80;
713 *lb++ = len / 0x100;
714#else
715 *lb++ = len / 0x100 + 0x80;
716#endif
717 }
718 *lb = len;
719 write_buf(f_out_name, lenbuf, lb - lenbuf + 1);
720 write_buf(f_out_name, fuzzy_file->basename, len);
721 }
722 }
cd6aa5b5 723
41cfde6b
WD
724 if (dry_run || read_batch)
725 return;
726
727 if (statret == 0) {
728 generate_and_send_sums(fd, st.st_size, f_out, f_copy);
2f03f956 729
41cfde6b
WD
730 if (f_copy >= 0) {
731 close(f_copy);
732 set_perms(backupptr, back_file, NULL, 0);
733 if (verbose > 1) {
734 rprintf(FINFO, "backed up %s to %s\n",
4875d6b6 735 safe_fname(fname), safe_fname(backupptr));
41cfde6b
WD
736 }
737 free(back_file);
738 }
739
740 close(fd);
741 } else
742 write_sum_head(f_out, NULL);
2f03f956
AT
743}
744
745
41cfde6b
WD
746void generate_files(int f_out, struct file_list *flist, char *local_name,
747 int f_out_name)
2f03f956
AT
748{
749 int i;
e1f67417 750 int phase = 0;
968c8030 751 char fbuf[MAXPATHLEN];
3ea9bbd6
WD
752 int need_retouch_dir_times = preserve_times && !omit_dir_times;
753 int need_retouch_dir_perms = 0;
0492fdfb
WD
754 int save_only_existing = only_existing;
755 int save_opt_ignore_existing = opt_ignore_existing;
2f03f956 756
45e08edb
WD
757 if (verbose > 2) {
758 rprintf(FINFO, "generator starting pid=%ld count=%d\n",
759 (long)getpid(), flist->count);
760 }
2f03f956 761
3e7053ac
MP
762 if (verbose >= 2) {
763 rprintf(FINFO,
f38bd4a0 764 whole_file > 0
3e7053ac
MP
765 ? "delta-transmission disabled for local transfer or --whole-file\n"
766 : "delta transmission enabled\n");
767 }
2cda2560 768
0492fdfb
WD
769 /* We expect to just sit around now, so don't exit on a timeout.
770 * If we really get a timeout then the other process should exit. */
a57873b7
AT
771 io_timeout = 0;
772
2f03f956
AT
773 for (i = 0; i < flist->count; i++) {
774 struct file_struct *file = flist->files[i];
dfd5ba6a 775 struct file_struct copy;
2f03f956 776
dfd5ba6a
WD
777 if (!file->basename)
778 continue;
0492fdfb
WD
779
780 /* We need to ensure that any dirs we create have writeable
781 * permissions during the time we are putting files within
782 * them. This is then fixed after the transfer is done. */
dfd5ba6a
WD
783 if (!am_root && S_ISDIR(file->mode) && !(file->mode & S_IWUSR)) {
784 copy = *file;
dfd5ba6a
WD
785 copy.mode |= S_IWUSR; /* user write */
786 file = &copy;
3ea9bbd6 787 need_retouch_dir_perms = 1;
2f03f956
AT
788 }
789
3fef5364 790 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
fa13f396 791 flist, file, i, f_out, f_out_name);
2f03f956 792 }
8e85be0a 793 recv_generator(NULL, NULL, NULL, 0, -1, -1);
c93fad5e 794 if (delete_during)
31937d36 795 delete_in_dir(NULL, NULL, NULL);
2f03f956
AT
796
797 phase++;
798 csum_length = SUM_LENGTH;
0492fdfb
WD
799 only_existing = max_size = opt_ignore_existing = 0;
800 update_only = always_checksum = size_only = 0;
e1f67417 801 ignore_times = 1;
2f03f956
AT
802
803 if (verbose > 2)
804 rprintf(FINFO,"generate_files phase=%d\n",phase);
805
7daccb8e 806 write_int(f_out, -1);
2f03f956 807
bc63ae3f
S
808 /* files can cycle through the system more than once
809 * to catch initial checksum errors */
b9b15fb1 810 while ((i = get_redo_num()) != -1) {
bc63ae3f 811 struct file_struct *file = flist->files[i];
3fef5364 812 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
fa13f396 813 flist, file, i, f_out, f_out_name);
bc63ae3f 814 }
2f03f956 815
bc63ae3f 816 phase++;
0492fdfb
WD
817 only_existing = save_only_existing;
818 opt_ignore_existing = save_opt_ignore_existing;
819
bc63ae3f
S
820 if (verbose > 2)
821 rprintf(FINFO,"generate_files phase=%d\n",phase);
2f03f956 822
7daccb8e 823 write_int(f_out, -1);
6dff5992 824
b0da4b23
WD
825 /* Read post-redo-phase MSG_DONE and any prior messages. */
826 get_redo_num();
827
6dff5992
WD
828 if (preserve_hard_links)
829 do_hard_links();
830
0492fdfb
WD
831 if ((need_retouch_dir_perms || need_retouch_dir_times)
832 && !list_only && !local_name && !dry_run) {
3ea9bbd6
WD
833 /* Now we need to fix any directory permissions that were
834 * modified during the transfer and/or re-set any tweaked
835 * modified-time values. */
836 for (i = 0; i < flist->count; i++) {
837 struct file_struct *file = flist->files[i];
838 if (!file->basename || !S_ISDIR(file->mode))
839 continue;
840 if (!need_retouch_dir_times && file->mode & S_IWUSR)
841 continue;
842 recv_generator(local_name ? local_name : f_name(file),
843 flist, file, i, -1, -1);
844 }
6dff5992 845 }
8e85be0a 846 recv_generator(NULL, NULL, NULL, 0, -1, -1);
6dff5992
WD
847
848 if (verbose > 2)
849 rprintf(FINFO,"generate_files finished\n");
2f03f956 850}