A minor tweak for the dry_run logic.
[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         int fd = -1, f_copy = -1;
244         STRUCT_STAT st, partial_st;
245         struct file_struct *back_file = NULL;
246         int statret, stat_errno;
247         char *fnamecmp, *partialptr, *backupptr = NULL;
248         char fnamecmpbuf[MAXPATHLEN];
249         uchar fnamecmp_type;
250
251         if (list_only)
252                 return;
253
254         if (verbose > 2) {
255                 rprintf(FINFO, "recv_generator(%s,%d)\n",
256                         safe_fname(fname), ndx);
257         }
258
259         if (server_filter_list.head
260             && check_filter(&server_filter_list, fname,
261                             S_ISDIR(file->mode)) < 0) {
262                 if (verbose) {
263                         rprintf(FINFO, "skipping server-excluded file \"%s\"\n",
264                                 safe_fname(fname));
265                 }
266                 return;
267         }
268
269         if (dry_run > 1) {
270                 statret = -1;
271                 stat_errno = ENOENT;
272         } else {
273                 statret = link_stat(fname, &st,
274                                     keep_dirlinks && S_ISDIR(file->mode));
275                 stat_errno = errno;
276         }
277
278         if (only_existing && statret == -1 && stat_errno == ENOENT) {
279                 /* we only want to update existing files */
280                 if (verbose > 1) {
281                         rprintf(FINFO, "not creating new file \"%s\"\n",
282                                 safe_fname(fname));
283                 }
284                 return;
285         }
286
287         if (statret == 0 && !preserve_perms
288             && S_ISDIR(st.st_mode) == S_ISDIR(file->mode)) {
289                 /* if the file exists already and we aren't perserving
290                  * permissions then act as though the remote end sent
291                  * us the file permissions we already have */
292                 file->mode = (file->mode & ~CHMOD_BITS)
293                            | (st.st_mode & CHMOD_BITS);
294         }
295
296         if (S_ISDIR(file->mode)) {
297                 /* The file to be received is a directory, so we need
298                  * to prepare appropriately.  If there is already a
299                  * file of that name and it is *not* a directory, then
300                  * we need to delete it.  If it doesn't exist, then
301                  * (perhaps recursively) create it. */
302                 if (statret == 0 && !S_ISDIR(st.st_mode)) {
303                         delete_file(fname, DEL_TERSE);
304                         statret = -1;
305                 }
306                 if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
307                         if (!relative_paths || errno != ENOENT
308                             || create_directory_path(fname, orig_umask) < 0
309                             || do_mkdir(fname, file->mode) < 0) {
310                                 rsyserr(FERROR, errno,
311                                         "recv_generator: mkdir %s failed",
312                                         full_fname(fname));
313                         }
314                 }
315                 if (set_perms(fname, file, statret ? NULL : &st, 0)
316                     && verbose && f_out != -1)
317                         rprintf(FINFO, "%s/\n", safe_fname(fname));
318                 if (delete_during && f_out != -1 && csum_length != SUM_LENGTH
319                     && (file->flags & FLAG_DEL_HERE))
320                         delete_in_dir(flist, fname, file);
321                 return;
322         } else if (max_size && file->length > max_size) {
323                 if (verbose > 1) {
324                         rprintf(FINFO, "%s is over max-size\n",
325                                 safe_fname(fname));
326                 }
327                 return;
328         }
329
330         if (preserve_links && S_ISLNK(file->mode)) {
331 #if SUPPORT_LINKS
332                 if (safe_symlinks && unsafe_symlink(file->u.link, fname)) {
333                         if (verbose) {
334                                 rprintf(FINFO,
335                                         "ignoring unsafe symlink %s -> \"%s\"\n",
336                                         full_fname(fname),
337                                         safe_fname(file->u.link));
338                         }
339                         return;
340                 }
341                 if (statret == 0) {
342                         int dflag = S_ISDIR(st.st_mode) ? DEL_DIR : 0;
343                         char lnk[MAXPATHLEN];
344                         int len;
345
346                         if (!dflag
347                             && (len = readlink(fname, lnk, MAXPATHLEN-1)) > 0) {
348                                 lnk[len] = 0;
349                                 /* A link already pointing to the
350                                  * right place -- no further action
351                                  * required. */
352                                 if (strcmp(lnk, file->u.link) == 0) {
353                                         set_perms(fname, file, &st,
354                                                   PERMS_REPORT);
355                                         return;
356                                 }
357                         }
358                         /* Not the right symlink (or not a symlink), so
359                          * delete it. */
360                         delete_file(fname, dflag | DEL_TERSE);
361                 }
362                 if (do_symlink(file->u.link,fname) != 0) {
363                         rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed",
364                                 full_fname(fname), safe_fname(file->u.link));
365                 } else {
366                         set_perms(fname,file,NULL,0);
367                         if (verbose) {
368                                 rprintf(FINFO, "%s -> %s\n", safe_fname(fname),
369                                         safe_fname(file->u.link));
370                         }
371                 }
372 #endif
373                 return;
374         }
375
376         if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
377                 if (statret != 0 ||
378                     st.st_mode != file->mode ||
379                     st.st_rdev != file->u.rdev) {
380                         int dflag = S_ISDIR(st.st_mode) ? DEL_DIR : 0;
381                         delete_file(fname, dflag | DEL_TERSE);
382                         if (verbose > 2) {
383                                 rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
384                                         safe_fname(fname),
385                                         (int)file->mode, (int)file->u.rdev);
386                         }
387                         if (do_mknod(fname,file->mode,file->u.rdev) != 0) {
388                                 rsyserr(FERROR, errno, "mknod %s failed",
389                                         full_fname(fname));
390                         } else {
391                                 set_perms(fname,file,NULL,0);
392                                 if (verbose) {
393                                         rprintf(FINFO, "%s\n",
394                                                 safe_fname(fname));
395                                 }
396                         }
397                 } else {
398                         set_perms(fname, file, &st, PERMS_REPORT);
399                 }
400                 return;
401         }
402
403         if (preserve_hard_links && hard_link_check(file, HL_CHECK_MASTER))
404                 return;
405
406         if (!S_ISREG(file->mode)) {
407                 rprintf(FINFO, "skipping non-regular file \"%s\"\n",
408                         safe_fname(fname));
409                 return;
410         }
411
412         fnamecmp = fname;
413         fnamecmp_type = FNAMECMP_FNAME;
414
415         if (statret == -1 && basis_dir[0] != NULL) {
416                 int fallback_match = -1;
417                 int match_level = 0;
418                 int i = 0;
419                 do {
420                         pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
421                                  basis_dir[i], fname);
422                         if (link_stat(fnamecmpbuf, &st, 0) == 0
423                             && S_ISREG(st.st_mode)) {
424                                 statret = 0;
425                                 if (link_dest) {
426                                         if (!match_level) {
427                                                 fallback_match = i;
428                                                 match_level = 1;
429                                         } else if (match_level == 2
430                                             && !unchanged_attrs(file, &st))
431                                                 continue;
432                                         if (!unchanged_file(fnamecmpbuf, file, &st))
433                                                 continue;
434                                         fallback_match = i;
435                                         match_level = 2;
436                                         if (!unchanged_attrs(file, &st))
437                                                 continue;
438                                 }
439                                 match_level = 3;
440                                 break;
441                         }
442                 } while (basis_dir[++i] != NULL);
443                 if (statret == 0) {
444                         if (match_level < 3) {
445                                 i = fallback_match;
446                                 pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
447                                          basis_dir[i], fname);
448                         }
449 #if HAVE_LINK
450                         if (link_dest && match_level == 3 && !dry_run) {
451                                 if (do_link(fnamecmpbuf, fname) < 0) {
452                                         if (verbose) {
453                                                 rsyserr(FINFO, errno,
454                                                         "link %s => %s",
455                                                         full_fname(fnamecmpbuf),
456                                                         safe_fname(fname));
457                                         }
458                                         fnamecmp = fnamecmpbuf;
459                                         fnamecmp_type = i;
460                                 }
461                         } else
462 #endif
463                         {
464                                 fnamecmp = fnamecmpbuf;
465                                 fnamecmp_type = i;
466                         }
467                 }
468         }
469
470         if (statret == 0 && !S_ISREG(st.st_mode)) {
471                 int dflag = S_ISDIR(st.st_mode) ? DEL_DIR : 0;
472                 if (delete_file(fname, dflag | DEL_TERSE) != 0)
473                         return;
474                 statret = -1;
475                 stat_errno = ENOENT;
476         }
477
478         if (partial_dir && (partialptr = partial_dir_fname(fname)) != NULL
479             && link_stat(partialptr, &partial_st, 0) == 0
480             && S_ISREG(partial_st.st_mode)) {
481                 if (statret == -1)
482                         goto prepare_to_open;
483         } else
484                 partialptr = NULL;
485
486         if (statret == -1) {
487                 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
488                         return;
489                 if (stat_errno == ENOENT)
490                         goto notify_others;
491                 if (verbose > 1) {
492                         rsyserr(FERROR, stat_errno,
493                                 "recv_generator: failed to stat %s",
494                                 full_fname(fname));
495                 }
496                 return;
497         }
498
499         if (opt_ignore_existing && fnamecmp_type == FNAMECMP_FNAME) {
500                 if (verbose > 1)
501                         rprintf(FINFO, "%s exists\n", safe_fname(fname));
502                 return;
503         }
504
505         if (update_only && fnamecmp_type == FNAMECMP_FNAME
506             && cmp_modtime(st.st_mtime, file->modtime) > 0) {
507                 if (verbose > 1)
508                         rprintf(FINFO, "%s is newer\n", safe_fname(fname));
509                 return;
510         }
511
512         if (!compare_dest && fnamecmp_type <= FNAMECMP_BASIS_DIR_HIGH)
513                 ;
514         else if (unchanged_file(fnamecmp, file, &st)) {
515                 if (fnamecmp_type == FNAMECMP_FNAME)
516                         set_perms(fname, file, &st, PERMS_REPORT);
517                 return;
518         }
519
520 prepare_to_open:
521         if (partialptr) {
522                 st = partial_st;
523                 fnamecmp = partialptr;
524                 fnamecmp_type = FNAMECMP_PARTIAL_DIR;
525                 statret = 0;
526         }
527
528         if (dry_run || read_batch)
529                 goto notify_others;
530         if (whole_file > 0) {
531                 statret = -1;
532                 goto notify_others;
533         }
534
535         /* open the file */
536         fd = do_open(fnamecmp, O_RDONLY, 0);
537
538         if (fd == -1) {
539                 rsyserr(FERROR, errno, "failed to open %s, continuing",
540                         full_fname(fnamecmp));
541             pretend_missing:
542                 /* pretend the file didn't exist */
543                 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
544                         return;
545                 statret = -1;
546                 goto notify_others;
547         }
548
549         if (inplace && make_backups) {
550                 if (!(backupptr = get_backup_name(fname))) {
551                         close(fd);
552                         return;
553                 }
554                 if (!(back_file = make_file(fname, NULL, NO_FILTERS))) {
555                         close(fd);
556                         goto pretend_missing;
557                 }
558                 if (robust_unlink(backupptr) && errno != ENOENT) {
559                         rsyserr(FERROR, errno, "unlink %s",
560                                 full_fname(backupptr));
561                         free(back_file);
562                         close(fd);
563                         return;
564                 }
565                 if ((f_copy = do_open(backupptr,
566                     O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) {
567                         rsyserr(FERROR, errno, "open %s",
568                                 full_fname(backupptr));
569                         free(back_file);
570                         close(fd);
571                         return;
572                 }
573                 fnamecmp_type = FNAMECMP_BACKUP;
574         }
575
576         if (verbose > 3) {
577                 rprintf(FINFO, "gen mapped %s of size %.0f\n",
578                         safe_fname(fnamecmp), (double)st.st_size);
579         }
580
581         if (verbose > 2)
582                 rprintf(FINFO, "generating and sending sums for %d\n", ndx);
583
584 notify_others:
585         write_int(f_out, ndx);
586         if (protocol_version >= 29 && inplace && !read_batch)
587                 write_byte(f_out, fnamecmp_type);
588         if (f_out_name >= 0)
589                 write_byte(f_out_name, fnamecmp_type);
590
591         if (dry_run || read_batch)
592                 return;
593
594         if (statret == 0) {
595                 generate_and_send_sums(fd, st.st_size, f_out, f_copy);
596
597                 if (f_copy >= 0) {
598                         close(f_copy);
599                         set_perms(backupptr, back_file, NULL, 0);
600                         if (verbose > 1) {
601                                 rprintf(FINFO, "backed up %s to %s\n",
602                                         safe_fname(fname), safe_fname(backupptr));
603                         }
604                         free(back_file);
605                 }
606
607                 close(fd);
608         } else
609                 write_sum_head(f_out, NULL);
610 }
611
612
613 void generate_files(int f_out, struct file_list *flist, char *local_name,
614                     int f_out_name)
615 {
616         int i;
617         int phase = 0;
618         char fbuf[MAXPATHLEN];
619         int need_retouch_dir_times = preserve_times && !omit_dir_times;
620         int need_retouch_dir_perms = 0;
621         int save_only_existing = only_existing;
622         int save_opt_ignore_existing = opt_ignore_existing;
623
624         if (verbose > 2) {
625                 rprintf(FINFO, "generator starting pid=%ld count=%d\n",
626                         (long)getpid(), flist->count);
627         }
628
629         if (verbose >= 2) {
630                 rprintf(FINFO,
631                         whole_file > 0
632                         ? "delta-transmission disabled for local transfer or --whole-file\n"
633                         : "delta transmission enabled\n");
634         }
635
636         /* We expect to just sit around now, so don't exit on a timeout.
637          * If we really get a timeout then the other process should exit. */
638         io_timeout = 0;
639
640         for (i = 0; i < flist->count; i++) {
641                 struct file_struct *file = flist->files[i];
642                 struct file_struct copy;
643
644                 if (!file->basename)
645                         continue;
646
647                 /* We need to ensure that any dirs we create have writeable
648                  * permissions during the time we are putting files within
649                  * them.  This is then fixed after the transfer is done. */
650                 if (!am_root && S_ISDIR(file->mode) && !(file->mode & S_IWUSR)) {
651                         copy = *file;
652                         copy.mode |= S_IWUSR; /* user write */
653                         file = &copy;
654                         need_retouch_dir_perms = 1;
655                 }
656
657                 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
658                                flist, file, i, f_out, f_out_name);
659         }
660         if (delete_during)
661                 delete_in_dir(NULL, NULL, NULL);
662
663         phase++;
664         csum_length = SUM_LENGTH;
665         only_existing = max_size = opt_ignore_existing = 0;
666         update_only = always_checksum = size_only = 0;
667         ignore_times = 1;
668
669         if (verbose > 2)
670                 rprintf(FINFO,"generate_files phase=%d\n",phase);
671
672         write_int(f_out, -1);
673
674         /* files can cycle through the system more than once
675          * to catch initial checksum errors */
676         while ((i = get_redo_num()) != -1) {
677                 struct file_struct *file = flist->files[i];
678                 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
679                                flist, file, i, f_out, f_out_name);
680         }
681
682         phase++;
683         only_existing = save_only_existing;
684         opt_ignore_existing = save_opt_ignore_existing;
685
686         if (verbose > 2)
687                 rprintf(FINFO,"generate_files phase=%d\n",phase);
688
689         write_int(f_out, -1);
690
691         /* Read post-redo-phase MSG_DONE and any prior messages. */
692         get_redo_num();
693
694         if (preserve_hard_links)
695                 do_hard_links();
696
697         if ((need_retouch_dir_perms || need_retouch_dir_times)
698             && !list_only && !local_name && !dry_run) {
699                 /* Now we need to fix any directory permissions that were
700                  * modified during the transfer and/or re-set any tweaked
701                  * modified-time values. */
702                 for (i = 0; i < flist->count; i++) {
703                         struct file_struct *file = flist->files[i];
704                         if (!file->basename || !S_ISDIR(file->mode))
705                                 continue;
706                         if (!need_retouch_dir_times && file->mode & S_IWUSR)
707                                 continue;
708                         recv_generator(local_name ? local_name : f_name(file),
709                                        flist, file, i, -1, -1);
710                 }
711         }
712
713         if (verbose > 2)
714                 rprintf(FINFO,"generate_files finished\n");
715 }