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