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