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