4ea7d32f63cab1536c1c08a23e61cbe14f0b46a7
[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 update_only;
38 extern int opt_ignore_existing;
39 extern int csum_length;
40 extern int ignore_times;
41 extern int size_only;
42 extern int io_timeout;
43 extern int protocol_version;
44 extern int always_checksum;
45 extern char *compare_dest;
46 extern int link_dest;
47 extern int whole_file;
48 extern int local_server;
49 extern int list_only;
50 extern int read_batch;
51 extern int only_existing;
52 extern int orig_umask;
53 extern int safe_symlinks;
54 extern unsigned int block_size;
55 extern unsigned int max_map_size;
56
57 extern struct exclude_list_struct server_exclude_list;
58
59
60 /* choose whether to skip a particular file */
61 static int skip_file(char *fname, struct file_struct *file, STRUCT_STAT *st)
62 {
63         if (st->st_size != file->length)
64                 return 0;
65         if (link_dest) {
66                 if (preserve_perms
67                     && (st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS))
68                         return 0;
69
70                 if (am_root && preserve_uid && st->st_uid != file->uid)
71                         return 0;
72
73                 if (preserve_gid && file->gid != GID_NONE
74                     && st->st_gid != file->gid)
75                         return 0;
76         }
77
78         /* if always checksum is set then we use the checksum instead
79            of the file time to determine whether to sync */
80         if (always_checksum && S_ISREG(st->st_mode)) {
81                 char sum[MD4_SUM_LENGTH];
82                 char fnamecmpdest[MAXPATHLEN];
83
84                 if (compare_dest != NULL) {
85                         if (access(fname, 0) != 0) {
86                                 pathjoin(fnamecmpdest, sizeof fnamecmpdest,
87                                          compare_dest, fname);
88                                 fname = fnamecmpdest;
89                         }
90                 }
91                 file_checksum(fname,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  * NULL sum_struct means we have no checksums
108  */
109 void write_sum_head(int f, struct sum_struct *sum)
110 {
111         static struct sum_struct null_sum;
112
113         if (sum == NULL)
114                 sum = &null_sum;
115
116         write_int(f, sum->count);
117         write_int(f, sum->blength);
118         if (protocol_version >= 27)
119                 write_int(f, sum->s2length);
120         write_int(f, sum->remainder);
121 }
122
123 /*
124  * set (initialize) the size entries in the per-file sum_struct
125  * calculating dynamic block and checksum sizes.
126  *
127  * This is only called from generate_and_send_sums() but is a separate
128  * function to encapsulate the logic.
129  *
130  * The block size is a rounded square root of file length.
131  *
132  * The checksum size is determined according to:
133  *     blocksum_bits = BLOCKSUM_EXP + 2*log2(file_len) - log2(block_len)
134  * provided by Donovan Baarda which gives a probability of rsync
135  * algorithm corrupting data and falling back using the whole md4
136  * checksums.
137  *
138  * This might be made one of several selectable heuristics.
139  */
140
141 static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
142 {
143         unsigned int blength;
144         int s2length;
145         uint32 c;
146         uint64 l;
147
148         if (block_size) {
149                 blength = block_size;
150         } else if (len <= BLOCK_SIZE * BLOCK_SIZE) {
151                 blength = BLOCK_SIZE;
152         } else {
153                 l = len;
154                 c = 1;
155                 while (l >>= 2) {
156                         c <<= 1;
157                 }
158                 blength = 0;
159                 do {
160                         blength |= c;
161                         if (len < (uint64)blength * blength)
162                                 blength &= ~c;
163                         c >>= 1;
164                 } while (c >= 8);       /* round to multiple of 8 */
165                 blength = MAX(blength, BLOCK_SIZE);
166                 blength = MIN(blength, MAX_MAP_SIZE);
167         }
168         max_map_size = MAX(MAX_MAP_SIZE, blength * 32);
169
170         if (protocol_version < 27) {
171                 s2length = csum_length;
172         } else if (csum_length == SUM_LENGTH) {
173                 s2length = SUM_LENGTH;
174         } else {
175                 int b = BLOCKSUM_BIAS;
176                 l = len;
177                 while (l >>= 1) {
178                         b += 2;
179                 }
180                 c = blength;
181                 while (c >>= 1 && b) {
182                         b--;
183                 }
184                 s2length = (b + 1 - 32 + 7) / 8; /* add a bit,
185                                                   * subtract rollsum,
186                                                   * round up
187                                                   *    --optimize in compiler--
188                                                   */
189                 s2length = MAX(s2length, csum_length);
190                 s2length = MIN(s2length, SUM_LENGTH);
191         }
192
193         sum->flength    = len;
194         sum->blength    = blength;
195         sum->s2length   = s2length;
196         sum->count      = (len + (blength - 1)) / blength;
197         sum->remainder  = (len % blength);
198
199         if (sum->count && verbose > 2) {
200                 rprintf(FINFO, "count=%.0f rem=%u blength=%u s2length=%d flength=%.0f\n",
201                         (double)sum->count, sum->remainder, sum->blength,
202                         sum->s2length, (double)sum->flength);
203         }
204 }
205
206
207 /*
208  * Generate and send a stream of signatures/checksums that describe a buffer
209  *
210  * Generate approximately one checksum every block_len bytes.
211  */
212 static void generate_and_send_sums(struct map_struct *buf, OFF_T len, int f_out)
213 {
214         size_t i;
215         struct sum_struct sum;
216         OFF_T offset = 0;
217
218         sum_sizes_sqroot(&sum, len);
219
220         write_sum_head(f_out, &sum);
221
222         for (i = 0; i < sum.count; i++) {
223                 unsigned int n1 = MIN(len, sum.blength);
224                 char *map = map_ptr(buf, offset, n1);
225                 uint32 sum1 = get_checksum1(map, n1);
226                 char sum2[SUM_LENGTH];
227
228                 get_checksum2(map, n1, sum2);
229
230                 if (verbose > 3) {
231                         rprintf(FINFO,
232                                 "chunk[%.0f] offset=%.0f len=%u sum1=%08lx\n",
233                                 (double)i, (double)offset, n1,
234                                 (unsigned long)sum1);
235                 }
236                 write_int(f_out, sum1);
237                 write_buf(f_out, sum2, sum.s2length);
238                 len -= n1;
239                 offset += n1;
240         }
241 }
242
243
244
245 /*
246  * Acts on file number @p i from @p flist, whose name is @p fname.
247  *
248  * First fixes up permissions, then generates checksums for the file.
249  *
250  * @note This comment was added later by mbp who was trying to work it
251  * out.  It might be wrong.
252  */
253 static void recv_generator(char *fname, struct file_struct *file, int i,
254                            int f_out)
255 {
256         int fd;
257         STRUCT_STAT st;
258         struct map_struct *mapbuf;
259         int statret;
260         char *fnamecmp;
261         char fnamecmpbuf[MAXPATHLEN];
262
263         if (list_only)
264                 return;
265
266         if (verbose > 2)
267                 rprintf(FINFO,"recv_generator(%s,%d)\n",fname,i);
268
269         if (server_exclude_list.head
270             && check_exclude(&server_exclude_list, fname,
271                              S_ISDIR(file->mode)) < 0) {
272                 if (verbose) {
273                         rprintf(FINFO, "skipping server-excluded file \"%s\"\n",
274                                 fname);
275                 }
276                 return;
277         }
278
279         statret = link_stat(fname, &st, keep_dirlinks && S_ISDIR(file->mode));
280
281         if (only_existing && statret == -1 && errno == ENOENT) {
282                 /* we only want to update existing files */
283                 if (verbose > 1)
284                         rprintf(FINFO, "not creating new file \"%s\"\n", fname);
285                 return;
286         }
287
288         if (statret == 0 &&
289             !preserve_perms &&
290             (S_ISDIR(st.st_mode) == S_ISDIR(file->mode))) {
291                 /* if the file exists already and we aren't perserving
292                  * permissions then act as though the remote end sent
293                  * us the file permissions we already have */
294                 file->mode = (file->mode & ~CHMOD_BITS)
295                            | (st.st_mode & CHMOD_BITS);
296         }
297
298         if (S_ISDIR(file->mode)) {
299                 /* The file to be received is a directory, so we need
300                  * to prepare appropriately.  If there is already a
301                  * file of that name and it is *not* a directory, then
302                  * we need to delete it.  If it doesn't exist, then
303                  * recursively create it. */
304
305                 if (dry_run)
306                         return; /* TODO: causes inaccuracies -- fix */
307                 if (statret == 0 && !S_ISDIR(st.st_mode)) {
308                         if (robust_unlink(fname) != 0) {
309                                 rsyserr(FERROR, errno,
310                                         "recv_generator: unlink %s to make room for directory",
311                                         full_fname(fname));
312                                 return;
313                         }
314                         statret = -1;
315                 }
316                 if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
317                         if (!(relative_paths && errno == ENOENT
318                             && create_directory_path(fname, orig_umask) == 0
319                             && do_mkdir(fname, file->mode) == 0)) {
320                                 rsyserr(FERROR, errno,
321                                         "recv_generator: mkdir %s failed",
322                                         full_fname(fname));
323                         }
324                 }
325                 /* f_out is set to -1 when doing final directory-permission
326                  * and modification-time repair. */
327                 if (set_perms(fname, file, statret ? NULL : &st, 0)
328                     && verbose && f_out != -1)
329                         rprintf(FINFO,"%s/\n",fname);
330                 return;
331         }
332
333         if (read_batch)
334                 return;
335
336         if (preserve_links && S_ISLNK(file->mode)) {
337 #if SUPPORT_LINKS
338                 char lnk[MAXPATHLEN];
339                 int l;
340
341                 if (safe_symlinks && unsafe_symlink(file->u.link, fname)) {
342                         if (verbose) {
343                                 rprintf(FINFO, "ignoring unsafe symlink %s -> \"%s\"\n",
344                                         full_fname(fname), file->u.link);
345                         }
346                         return;
347                 }
348                 if (statret == 0) {
349                         l = readlink(fname,lnk,MAXPATHLEN-1);
350                         if (l > 0) {
351                                 lnk[l] = 0;
352                                 /* A link already pointing to the
353                                  * right place -- no further action
354                                  * required. */
355                                 if (strcmp(lnk,file->u.link) == 0) {
356                                         set_perms(fname, file, &st,
357                                                   PERMS_REPORT);
358                                         return;
359                                 }
360                         }
361                         /* Not a symlink, so delete whatever's
362                          * already there and put a new symlink
363                          * in place. */
364                         delete_file(fname);
365                 }
366                 if (do_symlink(file->u.link,fname) != 0) {
367                         rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed",
368                                 full_fname(fname), file->u.link);
369                 } else {
370                         set_perms(fname,file,NULL,0);
371                         if (verbose) {
372                                 rprintf(FINFO,"%s -> %s\n", fname,file->u.link);
373                         }
374                 }
375 #endif
376                 return;
377         }
378
379 #ifdef HAVE_MKNOD
380         if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
381                 if (statret != 0 ||
382                     st.st_mode != file->mode ||
383                     st.st_rdev != file->u.rdev) {
384                         delete_file(fname);
385                         if (verbose > 2) {
386                                 rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
387                                         fname,(int)file->mode,(int)file->u.rdev);
388                         }
389                         if (do_mknod(fname,file->mode,file->u.rdev) != 0) {
390                                 rsyserr(FERROR, errno, "mknod %s failed",
391                                         full_fname(fname));
392                         } else {
393                                 set_perms(fname,file,NULL,0);
394                                 if (verbose)
395                                         rprintf(FINFO,"%s\n",fname);
396                         }
397                 } else {
398                         set_perms(fname, file, &st, PERMS_REPORT);
399                 }
400                 return;
401         }
402 #endif
403
404         if (preserve_hard_links && hard_link_check(file, HL_CHECK_MASTER))
405                 return;
406
407         if (!S_ISREG(file->mode)) {
408                 rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname);
409                 return;
410         }
411
412         fnamecmp = fname;
413
414         if (statret == -1 && compare_dest != NULL) {
415                 /* try the file at compare_dest instead */
416                 int saveerrno = errno;
417                 pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, compare_dest, fname);
418                 statret = link_stat(fnamecmpbuf, &st, 0);
419                 if (!S_ISREG(st.st_mode))
420                         statret = -1;
421                 if (statret == -1)
422                         errno = saveerrno;
423 #if HAVE_LINK
424                 else if (link_dest && !dry_run) {
425                         if (do_link(fnamecmpbuf, fname) != 0) {
426                                 if (verbose > 0) {
427                                         rsyserr(FINFO, errno, "link %s => %s",
428                                                 fnamecmpbuf, fname);
429                                 }
430                         }
431                         fnamecmp = fnamecmpbuf;
432                 }
433 #endif
434                 else
435                         fnamecmp = fnamecmpbuf;
436         }
437
438         if (statret == -1) {
439                 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
440                         return;
441                 if (errno == ENOENT) {
442                         write_int(f_out,i);
443                         if (!dry_run)
444                                 write_sum_head(f_out, NULL);
445                 } else if (verbose > 1) {
446                         rsyserr(FERROR, errno,
447                                 "recv_generator: failed to open %s",
448                                 full_fname(fname));
449                 }
450                 return;
451         }
452
453         if (!S_ISREG(st.st_mode)) {
454                 if (delete_file(fname) != 0) {
455                         return;
456                 }
457
458                 /* now pretend the file didn't exist */
459                 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
460                         return;
461                 write_int(f_out,i);
462                 if (!dry_run)
463                         write_sum_head(f_out, NULL);
464                 return;
465         }
466
467         if (opt_ignore_existing && fnamecmp == fname) {
468                 if (verbose > 1)
469                         rprintf(FINFO,"%s exists\n",fname);
470                 return;
471         }
472
473         if (update_only && fnamecmp == fname
474             && cmp_modtime(st.st_mtime, file->modtime) > 0) {
475                 if (verbose > 1)
476                         rprintf(FINFO,"%s is newer\n",fname);
477                 return;
478         }
479
480         if (skip_file(fname, file, &st)) {
481                 if (fnamecmp == fname)
482                         set_perms(fname, file, &st, PERMS_REPORT);
483                 return;
484         }
485
486         if (dry_run) {
487                 write_int(f_out,i);
488                 return;
489         }
490
491         if (whole_file > 0) {
492                 write_int(f_out,i);
493                 write_sum_head(f_out, NULL);
494                 return;
495         }
496
497         /* open the file */
498         fd = do_open(fnamecmp, O_RDONLY, 0);
499
500         if (fd == -1) {
501                 rsyserr(FERROR, errno, "failed to open %s, continuing",
502                         full_fname(fnamecmp));
503                 /* pretend the file didn't exist */
504                 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
505                         return;
506                 write_int(f_out,i);
507                 write_sum_head(f_out, NULL);
508                 return;
509         }
510
511         if (st.st_size > 0)
512                 mapbuf = map_file(fd,st.st_size);
513         else
514                 mapbuf = NULL;
515
516         if (verbose > 3) {
517                 rprintf(FINFO,"gen mapped %s of size %.0f\n", fnamecmp,
518                         (double)st.st_size);
519         }
520
521         if (verbose > 2)
522                 rprintf(FINFO, "generating and sending sums for %d\n", i);
523
524         write_int(f_out,i);
525         generate_and_send_sums(mapbuf, st.st_size, f_out);
526
527         close(fd);
528         if (mapbuf)
529                 unmap_file(mapbuf);
530 }
531
532
533 void generate_files(int f_out, struct file_list *flist, char *local_name)
534 {
535         int i;
536         int phase = 0;
537         char fbuf[MAXPATHLEN];
538
539         if (verbose > 2) {
540                 rprintf(FINFO, "generator starting pid=%ld count=%d\n",
541                         (long)getpid(), flist->count);
542         }
543
544         if (verbose >= 2) {
545                 rprintf(FINFO,
546                         whole_file > 0
547                         ? "delta-transmission disabled for local transfer or --whole-file\n"
548                         : "delta transmission enabled\n");
549         }
550
551         /* we expect to just sit around now, so don't exit on a
552            timeout. If we really get a timeout then the other process should
553            exit */
554         io_timeout = 0;
555
556         for (i = 0; i < flist->count; i++) {
557                 struct file_struct *file = flist->files[i];
558                 struct file_struct copy;
559
560                 if (!file->basename)
561                         continue;
562                 /* we need to ensure that any directories we create have writeable
563                    permissions initially so that we can create the files within
564                    them. This is then fixed after the files are transferred */
565                 if (!am_root && S_ISDIR(file->mode) && !(file->mode & S_IWUSR)) {
566                         copy = *file;
567                         /* XXX: Could this be causing a problem on SCO?  Perhaps their
568                          * handling of permissions is strange? */
569                         copy.mode |= S_IWUSR; /* user write */
570                         file = &copy;
571                 }
572
573                 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
574                                file, i, f_out);
575         }
576
577         phase++;
578         csum_length = SUM_LENGTH;
579         ignore_times = 1;
580
581         if (verbose > 2)
582                 rprintf(FINFO,"generate_files phase=%d\n",phase);
583
584         write_int(f_out, -1);
585
586         /* files can cycle through the system more than once
587          * to catch initial checksum errors */
588         while ((i = get_redo_num()) != -1) {
589                 struct file_struct *file = flist->files[i];
590                 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
591                                file, i, f_out);
592         }
593
594         phase++;
595         if (verbose > 2)
596                 rprintf(FINFO,"generate_files phase=%d\n",phase);
597
598         write_int(f_out, -1);
599
600         if (preserve_hard_links)
601                 do_hard_links();
602
603         /* now we need to fix any directory permissions that were
604          * modified during the transfer */
605         for (i = 0; i < flist->count; i++) {
606                 struct file_struct *file = flist->files[i];
607                 if (!file->basename || !S_ISDIR(file->mode))
608                         continue;
609                 recv_generator(local_name ? local_name : f_name(file),
610                                file, i, -1);
611         }
612
613         if (verbose > 2)
614                 rprintf(FINFO,"generate_files finished\n");
615 }