Implemented the --what-has-changed functionality.
[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;
06a1dbad 28extern int what_has_changed;
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)
85#define SC_SYMLINK_CHANGED (1<<1)
86#define SC_SENDING_FILE (1<<2)
87#define SC_NO_BASIS (1<<3)
88#define SC_NO_NL (1<<4)
89
90static void showchg(const char *fname, struct file_struct *file, int statret,
91 STRUCT_STAT *st, int flags)
92{
93 static char ch[] = "*XcstpogDL";
94 int keep_time;
95 char *s;
96
97 ch[0] = flags & SC_SENDING_FILE ? '*' : ' ';
98 ch[1] = S_ISDIR(file->mode) ? 'd' : IS_DEVICE(file->mode) ? 'D'
99 : S_ISLNK(file->mode) ? 'L' : 'f';
100
101 if (statret < 0) {
102 for (s = ch + 2; *s; ) *s++ = '+';
103 goto print_it;
104 }
105
106 keep_time = !preserve_times ? 0
107 : S_ISDIR(file->mode) ? !omit_dir_times : !S_ISLNK(file->mode);
108
109 ch[2] = !(flags & SC_CHECKSUM_CHANGED) ? '-' : 'c';
110 ch[3] = !S_ISREG(file->mode) || file->length == st->st_size ? '-' : 's';
111 ch[4] = flags & SC_SENDING_FILE && !keep_time ? 'T'
112 : !keep_time || file->modtime == st->st_mtime ? '-' : 't';
113 ch[5] = !preserve_perms || file->mode == st->st_mode ? '-' : 'p';
114 ch[6] = !am_root || !preserve_uid || file->uid == st->st_uid ? '-' : 'o';
115 ch[7] = preserve_gid && file->gid != GID_NONE && st->st_gid != file->gid ? 'g' : '-';
116 ch[8] = IS_DEVICE(file->mode) && file->u.rdev != st->st_rdev ? 'D' : '-';
117 ch[9] = flags & SC_SYMLINK_CHANGED ? 'L' : '-';
118
119 if (flags & SC_NO_BASIS)
120 ch[4] = ch[5] = ch[6] = ch[7] = '-';
121
122 s = ch + 2;
123 if (!(flags & SC_SENDING_FILE))
124 while (*s == '-') s++;
125 if (*s) {
126 print_it:
127 rprintf(FINFO, "%s %s%s%s", ch, fname,
128 ch[1] == 'd' ? "/" : "",
129 flags & SC_NO_NL ? "" : "\n");
130 }
131}
132
133
b7e8628c
WD
134/* Perform our quick-check heuristic for determining if a file is unchanged. */
135static int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
136{
137 if (st->st_size != file->length)
138 return 0;
59c95e42 139
2cda2560 140 /* if always checksum is set then we use the checksum instead
2f03f956
AT
141 of the file time to determine whether to sync */
142 if (always_checksum && S_ISREG(st->st_mode)) {
143 char sum[MD4_SUM_LENGTH];
b7e8628c 144 file_checksum(fn, sum, st->st_size);
728d0922 145 return memcmp(sum, file->u.sum, protocol_version < 21 ? 2
84acca07 146 : MD4_SUM_LENGTH) == 0;
2f03f956
AT
147 }
148
cc1e997d 149 if (size_only)
84acca07 150 return 1;
2f03f956 151
cc1e997d 152 if (ignore_times)
84acca07 153 return 0;
cc1e997d 154
84acca07 155 return cmp_modtime(st->st_mtime, file->modtime) == 0;
2f03f956
AT
156}
157
158
ec8290c8 159/*
195bd906 160 * set (initialize) the size entries in the per-file sum_struct
ec8290c8 161 * calculating dynamic block and checksum sizes.
195bd906 162 *
ec8290c8 163 * This is only called from generate_and_send_sums() but is a separate
195bd906
S
164 * function to encapsulate the logic.
165 *
166 * The block size is a rounded square root of file length.
167 *
168 * The checksum size is determined according to:
169 * blocksum_bits = BLOCKSUM_EXP + 2*log2(file_len) - log2(block_len)
170 * provided by Donovan Baarda which gives a probability of rsync
171 * algorithm corrupting data and falling back using the whole md4
172 * checksums.
173 *
174 * This might be made one of several selectable heuristics.
175 */
1490812a 176static void sum_sizes_sqroot(struct sum_struct *sum, int64 len)
195bd906 177{
a255c592 178 int32 blength;
da9d12f5 179 int s2length;
195bd906 180
a255c592 181 if (block_size)
195bd906 182 blength = block_size;
a255c592 183 else if (len <= BLOCK_SIZE * BLOCK_SIZE)
195bd906 184 blength = BLOCK_SIZE;
a255c592
WD
185 else {
186 int32 c;
1490812a 187 int64 l;
eae7165c
WD
188 int cnt;
189 for (c = 1, l = len, cnt = 0; l >>= 2; c <<= 1, cnt++) {}
190 if (cnt >= 31 || c >= MAX_BLOCK_SIZE)
191 blength = MAX_BLOCK_SIZE;
192 else {
193 blength = 0;
194 do {
195 blength |= c;
1490812a 196 if (len < (int64)blength * blength)
eae7165c
WD
197 blength &= ~c;
198 c >>= 1;
199 } while (c >= 8); /* round to multiple of 8 */
200 blength = MAX(blength, BLOCK_SIZE);
195bd906 201 }
195bd906
S
202 }
203
d04e9c51 204 if (protocol_version < 27) {
195bd906
S
205 s2length = csum_length;
206 } else if (csum_length == SUM_LENGTH) {
207 s2length = SUM_LENGTH;
208 } else {
a255c592 209 int32 c;
1490812a 210 int64 l;
da9d12f5 211 int b = BLOCKSUM_BIAS;
a255c592
WD
212 for (l = len; l >>= 1; b += 2) {}
213 for (c = blength; c >>= 1 && b; b--) {}
214 /* add a bit, subtract rollsum, round up. */
215 s2length = (b + 1 - 32 + 7) / 8; /* --optimize in compiler-- */
195bd906
S
216 s2length = MAX(s2length, csum_length);
217 s2length = MIN(s2length, SUM_LENGTH);
218 }
219
220 sum->flength = len;
221 sum->blength = blength;
222 sum->s2length = s2length;
223 sum->count = (len + (blength - 1)) / blength;
224 sum->remainder = (len % blength);
225
226 if (sum->count && verbose > 2) {
a255c592
WD
227 rprintf(FINFO,
228 "count=%.0f rem=%ld blength=%ld s2length=%d flength=%.0f\n",
229 (double)sum->count, (long)sum->remainder, (long)sum->blength,
da9d12f5 230 sum->s2length, (double)sum->flength);
195bd906
S
231 }
232}
80605142 233
bceec82f 234
80605142
WD
235/*
236 * Generate and send a stream of signatures/checksums that describe a buffer
e66dfd18 237 *
80605142
WD
238 * Generate approximately one checksum every block_len bytes.
239 */
cd6aa5b5 240static void generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy)
2f03f956 241{
a1cbe76e 242 int32 i;
6e45e1dd 243 struct map_struct *mapbuf;
80605142 244 struct sum_struct sum;
2f03f956
AT
245 OFF_T offset = 0;
246
423dba8e 247 sum_sizes_sqroot(&sum, len);
e66dfd18 248
6e45e1dd 249 if (len > 0)
96d910c7 250 mapbuf = map_file(fd, len, MAX_MAP_SIZE, sum.blength);
6e45e1dd
WD
251 else
252 mapbuf = NULL;
253
fc0257c9 254 write_sum_head(f_out, &sum);
2f03f956 255
80605142 256 for (i = 0; i < sum.count; i++) {
a255c592 257 int32 n1 = (int32)MIN(len, (OFF_T)sum.blength);
6e45e1dd 258 char *map = map_ptr(mapbuf, offset, n1);
80605142
WD
259 uint32 sum1 = get_checksum1(map, n1);
260 char sum2[SUM_LENGTH];
2f03f956 261
cd6aa5b5
WD
262 if (f_copy >= 0)
263 full_write(f_copy, map, n1);
264
80605142 265 get_checksum2(map, n1, sum2);
2f03f956 266
80605142 267 if (verbose > 3) {
e66dfd18 268 rprintf(FINFO,
a255c592
WD
269 "chunk[%.0f] offset=%.0f len=%ld sum1=%08lx\n",
270 (double)i, (double)offset, (long)n1,
0e36d9da 271 (unsigned long)sum1);
80605142
WD
272 }
273 write_int(f_out, sum1);
fc0257c9 274 write_buf(f_out, sum2, sum.s2length);
2f03f956
AT
275 len -= n1;
276 offset += n1;
277 }
6e45e1dd
WD
278
279 if (mapbuf)
280 unmap_file(mapbuf);
2f03f956
AT
281}
282
06a1dbad 283
8e85be0a
WD
284/* Try to find a filename in the same dir as "fname" with a similar name. */
285static int find_fuzzy(struct file_struct *file, struct file_list *dirlist)
286{
287 int fname_len, fname_suf_len;
288 const char *fname_suf, *fname = file->basename;
289 uint32 lowest_dist = 0x7FFFFFFF;
290 int j, lowest_j = -1;
291
292 fname_len = strlen(fname);
293 fname_suf = find_filename_suffix(fname, fname_len, &fname_suf_len);
294
295 for (j = 0; j < dirlist->count; j++) {
296 struct file_struct *fp = dirlist->files[j];
297 const char *suf, *name;
298 int len, suf_len;
299 uint32 dist;
300
301 if (!S_ISREG(fp->mode) || !fp->length
302 || fp->flags & FLAG_NO_FUZZY)
303 continue;
304
305 name = fp->basename;
306
307 if (fp->length == file->length
308 && fp->modtime == file->modtime) {
309 if (verbose > 4) {
310 rprintf(FINFO,
311 "fuzzy size/modtime match for %s\n",
312 name);
313 }
314 return j;
315 }
316
317 len = strlen(name);
318 suf = find_filename_suffix(name, len, &suf_len);
319
320 dist = fuzzy_distance(name, len, fname, fname_len);
321 /* Add some extra weight to how well the suffixes match. */
322 dist += fuzzy_distance(suf, suf_len, fname_suf, fname_suf_len)
323 * 10;
324 if (verbose > 4) {
325 rprintf(FINFO, "fuzzy distance for %s = %d.%05d\n",
326 name, (int)(dist>>16), (int)(dist&0xFFFF));
327 }
328 if (dist <= lowest_dist) {
329 lowest_dist = dist;
330 lowest_j = j;
331 }
332 }
333
334 return lowest_j;
335}
336
2f03f956 337
0492fdfb
WD
338/* Acts on flist->file's ndx'th item, whose name is fname. If a directory,
339 * make sure it exists, and has the right permissions/timestamp info. For
340 * all other non-regular files (symlinks, etc.) we create them here. For
341 * regular files that have changed, we try to find a basis file and then
342 * start sending checksums.
ef1aa910 343 *
0492fdfb
WD
344 * Note that f_out is set to -1 when doing final directory-permission and
345 * modification-time repair. */
fa13f396 346static void recv_generator(char *fname, struct file_list *flist,
0492fdfb 347 struct file_struct *file, int ndx,
41cfde6b 348 int f_out, int f_out_name)
2cda2560 349{
df337831 350 static int missing_below = -1;
8e85be0a
WD
351 static char *fuzzy_dirname = NULL;
352 static struct file_list *fuzzy_dirlist = NULL;
353 struct file_struct *fuzzy_file = NULL;
41cfde6b 354 int fd = -1, f_copy = -1;
89f7eff3 355 STRUCT_STAT st, partial_st;
41cfde6b 356 struct file_struct *back_file = NULL;
e7d13fe5 357 int statret, stat_errno;
41cfde6b 358 char *fnamecmp, *partialptr, *backupptr = NULL;
375a4556 359 char fnamecmpbuf[MAXPATHLEN];
41cfde6b 360 uchar fnamecmp_type;
f7632fc6 361
dfd5ba6a
WD
362 if (list_only)
363 return;
2f03f956 364
8e85be0a
WD
365 if (!fname) {
366 if (fuzzy_dirlist) {
367 flist_free(fuzzy_dirlist);
368 fuzzy_dirlist = NULL;
369 fuzzy_dirname = NULL;
370 }
371 if (missing_below >= 0) {
372 dry_run--;
373 missing_below = -1;
374 }
375 return;
376 }
377
4875d6b6
WD
378 if (verbose > 2) {
379 rprintf(FINFO, "recv_generator(%s,%d)\n",
380 safe_fname(fname), ndx);
381 }
2f03f956 382
7842418b
WD
383 if (server_filter_list.head
384 && check_filter(&server_filter_list, fname,
385 S_ISDIR(file->mode)) < 0) {
3e35c34b
WD
386 if (verbose) {
387 rprintf(FINFO, "skipping server-excluded file \"%s\"\n",
ecc81fce 388 safe_fname(fname));
3e35c34b 389 }
97f9dcae 390 return;
3e35c34b 391 }
97f9dcae 392
8e85be0a 393 if (missing_below >= 0 && file->dir.depth <= missing_below) {
df337831
WD
394 dry_run--;
395 missing_below = -1;
396 }
73f7af0e
WD
397 if (dry_run > 1) {
398 statret = -1;
399 stat_errno = ENOENT;
400 } else {
8e85be0a
WD
401 if (fuzzy_basis && S_ISREG(file->mode)) {
402 char *dn = file->dirname ? file->dirname : ".";
403 /* Yes, identical dirnames are guaranteed to have
404 * identical pointers at this point. */
405 if (fuzzy_dirname != dn) {
406 if (fuzzy_dirlist)
407 flist_free(fuzzy_dirlist);
408 fuzzy_dirname = dn;
409 fuzzy_dirlist = get_dirlist(fuzzy_dirname, 1);
410 }
411 }
412
73f7af0e
WD
413 statret = link_stat(fname, &st,
414 keep_dirlinks && S_ISDIR(file->mode));
415 stat_errno = errno;
416 }
63787382 417
a7260c40 418 if (only_existing && statret == -1 && stat_errno == ENOENT) {
1347d512 419 /* we only want to update existing files */
ecc81fce
WD
420 if (verbose > 1) {
421 rprintf(FINFO, "not creating new file \"%s\"\n",
422 safe_fname(fname));
423 }
1347d512
AT
424 return;
425 }
426
d9b4d267
WD
427 if (statret == 0 && !preserve_perms
428 && S_ISDIR(st.st_mode) == S_ISDIR(file->mode)) {
4df9f368 429 /* if the file exists already and we aren't perserving
2cda2560
WD
430 * permissions then act as though the remote end sent
431 * us the file permissions we already have */
67e78a82
WD
432 file->mode = (file->mode & ~CHMOD_BITS)
433 | (st.st_mode & CHMOD_BITS);
4df9f368
AT
434 }
435
2f03f956 436 if (S_ISDIR(file->mode)) {
2cda2560
WD
437 /* The file to be received is a directory, so we need
438 * to prepare appropriately. If there is already a
439 * file of that name and it is *not* a directory, then
440 * we need to delete it. If it doesn't exist, then
027428eb 441 * (perhaps recursively) create it. */
2f03f956 442 if (statret == 0 && !S_ISDIR(st.st_mode)) {
7e38410e 443 delete_file(fname, DEL_TERSE);
2f03f956
AT
444 statret = -1;
445 }
df337831
WD
446 if (dry_run && statret != 0 && missing_below < 0) {
447 missing_below = file->dir.depth;
448 dry_run++;
449 }
06a1dbad
WD
450 if (what_has_changed && f_out != -1)
451 showchg(fname, file, statret, &st, 0);
2f03f956 452 if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
027428eb
WD
453 if (!relative_paths || errno != ENOENT
454 || create_directory_path(fname, orig_umask) < 0
455 || do_mkdir(fname, file->mode) < 0) {
d62bcc17
WD
456 rsyserr(FERROR, errno,
457 "recv_generator: mkdir %s failed",
458 full_fname(fname));
2f03f956
AT
459 }
460 }
716e73d4 461 if (set_perms(fname, file, statret ? NULL : &st, 0)
06a1dbad 462 && verbose && f_out != -1 && !what_has_changed)
ecc81fce 463 rprintf(FINFO, "%s/\n", safe_fname(fname));
c93fad5e 464 if (delete_during && f_out != -1 && csum_length != SUM_LENGTH
31937d36
WD
465 && (file->flags & FLAG_DEL_HERE))
466 delete_in_dir(flist, fname, file);
2f03f956 467 return;
06a1dbad
WD
468 }
469
470 if (max_size && file->length > max_size) {
4875d6b6
WD
471 if (verbose > 1) {
472 rprintf(FINFO, "%s is over max-size\n",
473 safe_fname(fname));
474 }
7d1bfaf7 475 return;
2f03f956
AT
476 }
477
478 if (preserve_links && S_ISLNK(file->mode)) {
4f5b0756 479#ifdef SUPPORT_LINKS
728d0922 480 if (safe_symlinks && unsafe_symlink(file->u.link, fname)) {
2f03f956 481 if (verbose) {
4875d6b6
WD
482 rprintf(FINFO,
483 "ignoring unsafe symlink %s -> \"%s\"\n",
484 full_fname(fname),
485 safe_fname(file->u.link));
2f03f956
AT
486 }
487 return;
488 }
489 if (statret == 0) {
7e38410e
WD
490 int dflag = S_ISDIR(st.st_mode) ? DEL_DIR : 0;
491 char lnk[MAXPATHLEN];
492 int len;
493
494 if (!dflag
495 && (len = readlink(fname, lnk, MAXPATHLEN-1)) > 0) {
496 lnk[len] = 0;
85d4d142
MP
497 /* A link already pointing to the
498 * right place -- no further action
499 * required. */
7e38410e 500 if (strcmp(lnk, file->u.link) == 0) {
06a1dbad
WD
501 if (what_has_changed)
502 showchg(fname, file, 0, &st, 0);
c41b52c4
WD
503 set_perms(fname, file, &st,
504 PERMS_REPORT);
2f03f956
AT
505 return;
506 }
2cda2560 507 }
7e38410e
WD
508 /* Not the right symlink (or not a symlink), so
509 * delete it. */
510 delete_file(fname, dflag | DEL_TERSE);
2f03f956 511 }
728d0922 512 if (do_symlink(file->u.link,fname) != 0) {
d62bcc17 513 rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed",
ecc81fce 514 full_fname(fname), safe_fname(file->u.link));
2f03f956
AT
515 } else {
516 set_perms(fname,file,NULL,0);
06a1dbad
WD
517 if (what_has_changed) {
518 showchg(fname, file, statret, &st,
519 SC_SYMLINK_CHANGED
520 | (verbose ? SC_NO_NL : 0));
521 }
2f03f956 522 if (verbose) {
06a1dbad
WD
523 rprintf(FINFO, "%s -> %s\n",
524 what_has_changed ? "" : safe_fname(fname),
525 safe_fname(file->u.link));
2f03f956
AT
526 }
527 }
528#endif
529 return;
530 }
531
2f03f956 532 if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
06a1dbad
WD
533 if (what_has_changed)
534 showchg(fname, file, statret, &st, 0);
2cda2560 535 if (statret != 0 ||
2f03f956 536 st.st_mode != file->mode ||
3915fd75 537 st.st_rdev != file->u.rdev) {
7e38410e
WD
538 int dflag = S_ISDIR(st.st_mode) ? DEL_DIR : 0;
539 delete_file(fname, dflag | DEL_TERSE);
d62bcc17 540 if (verbose > 2) {
2f03f956 541 rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
ecc81fce
WD
542 safe_fname(fname),
543 (int)file->mode, (int)file->u.rdev);
d62bcc17 544 }
728d0922 545 if (do_mknod(fname,file->mode,file->u.rdev) != 0) {
d62bcc17
WD
546 rsyserr(FERROR, errno, "mknod %s failed",
547 full_fname(fname));
2f03f956
AT
548 } else {
549 set_perms(fname,file,NULL,0);
06a1dbad 550 if (verbose && !what_has_changed) {
ecc81fce
WD
551 rprintf(FINFO, "%s\n",
552 safe_fname(fname));
553 }
2f03f956
AT
554 }
555 } else {
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)) {
06a1dbad
WD
693 if (what_has_changed) {
694 showchg(fname, file, statret, &st,
695 fnamecmp_type == FNAMECMP_FNAME ? 0
696 : SC_NO_BASIS);
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 }
06a1dbad
WD
796 if (what_has_changed) {
797 showchg(fname, file, statret, &st,
798 (always_checksum ? SC_CHECKSUM_CHANGED : 0)
799 | SC_SENDING_FILE);
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}