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