- Simplified the whole-file option handling.
[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 preserve_links;
30 extern int am_root;
31 extern int preserve_devices;
32 extern int preserve_hard_links;
33 extern int update_only;
34 extern int opt_ignore_existing;
35 extern int block_size;
36 extern int csum_length;
37 extern int ignore_times;
38 extern int size_only;
39 extern int io_timeout;
40 extern int remote_version;
41 extern int always_checksum;
42 extern int modify_window;
43 extern char *compare_dest;
44 extern int link_dest;
45
46
47 /* choose whether to skip a particular file */
48 static int skip_file(char *fname,
49                      struct file_struct *file, STRUCT_STAT *st)
50 {
51         if (st->st_size != file->length) {
52                 return 0;
53         }
54         if (link_dest) {
55                 if((st->st_mode & ~_S_IFMT) !=  (file->mode & ~_S_IFMT)) {
56                         return 0;
57                 }
58                 if (st->st_uid != file->uid || st->st_gid != file->gid) {
59                         return 0;
60                 }
61         }
62
63         /* if always checksum is set then we use the checksum instead
64            of the file time to determine whether to sync */
65         if (always_checksum && S_ISREG(st->st_mode)) {
66                 char sum[MD4_SUM_LENGTH];
67                 char fnamecmpdest[MAXPATHLEN];
68
69                 if (compare_dest != NULL) {
70                         if (access(fname, 0) != 0) {
71                                 snprintf(fnamecmpdest,MAXPATHLEN,"%s/%s",
72                                          compare_dest,fname);
73                                 fname = fnamecmpdest;
74                         }
75                 }
76                 file_checksum(fname,sum,st->st_size);
77                 if (remote_version < 21) {
78                         return (memcmp(sum,file->sum,2) == 0);
79                 } else {
80                         return (memcmp(sum,file->sum,MD4_SUM_LENGTH) == 0);
81                 }
82         }
83
84         if (size_only) {
85                 return 1;
86         }
87
88         if (ignore_times) {
89                 return 0;
90         }
91
92         return (cmp_modtime(st->st_mtime,file->modtime) == 0);
93 }
94
95
96 /* use a larger block size for really big files */
97 static int adapt_block_size(struct file_struct *file, int bsize)
98 {
99         int ret;
100
101         if (bsize != BLOCK_SIZE) return bsize;
102
103         ret = file->length / (10000); /* rough heuristic */
104         ret = ret & ~15; /* multiple of 16 */
105         if (ret < bsize) ret = bsize;
106         if (ret > CHUNK_SIZE/2) ret = CHUNK_SIZE/2;
107         return ret;
108 }
109
110
111 /*
112   send a header that says "we have no checksums" down the f_out fd
113   */
114 static void send_null_sums(int f_out)
115 {
116         write_int(f_out, 0);
117         write_int(f_out, block_size);
118         write_int(f_out, 0);
119 }
120
121
122
123 /**
124  * Perhaps we want to just send an empty checksum set for this file,
125  * which will force the whole thing to be literally transferred.
126  *
127  * When do we do this?  If the user's explicitly said they
128  * want the whole thing, or if { they haven't explicitly
129  * requested a delta, and it's local but not batch mode.}
130  *
131  * Whew. */
132 static BOOL disable_deltas_p(void)
133 {
134         extern int whole_file;
135         extern int local_server;
136         extern int write_batch;
137
138         if (whole_file > 0)
139                 return True;
140         if (whole_file == 0 || write_batch)
141                 return False;
142         return local_server;
143 }
144
145
146 /*
147  * Generate and send a stream of signatures/checksums that describe a buffer
148  *
149  * Generate approximately one checksum every block_len bytes.
150  */
151 static void generate_and_send_sums(struct map_struct *buf, OFF_T len,
152                                    int block_len, int f_out)
153 {
154         size_t i;
155         struct sum_struct sum;
156         OFF_T offset = 0;
157
158         sum.count = (len + (block_len - 1)) / block_len;
159         sum.remainder = (len % block_len);
160         sum.n = block_len;
161         sum.flength = len;
162         /* not needed here  sum.sums = NULL; */
163
164         if (sum.count && verbose > 3) {
165                 rprintf(FINFO, "count=%ld rem=%ld n=%ld flength=%.0f\n",
166                         (long) sum.count, (long) sum.remainder,
167                         (long) sum.n, (double) sum.flength);
168         }
169
170         write_int(f_out, sum.count);
171         write_int(f_out, sum.n);
172         write_int(f_out, sum.remainder);
173
174         for (i = 0; i < sum.count; i++) {
175                 int n1 = MIN(len, block_len);
176                 char *map = map_ptr(buf, offset, n1);
177                 uint32 sum1 = get_checksum1(map, n1);
178                 char sum2[SUM_LENGTH];
179
180                 get_checksum2(map, n1, sum2);
181
182                 if (verbose > 3) {
183                         rprintf(FINFO,
184                                 "chunk[%d] offset=%.0f len=%d sum1=%08lx\n",
185                                 i, (double) offset, n1, (unsigned long) sum1);
186                 }
187                 write_int(f_out, sum1);
188                 write_buf(f_out, sum2, csum_length);
189                 len -= n1;
190                 offset += n1;
191         }
192 }
193
194
195
196 /**
197  * Acts on file number @p i from @p flist, whose name is @p fname.
198  *
199  * First fixes up permissions, then generates checksums for the file.
200  *
201  * @note This comment was added later by mbp who was trying to work it
202  * out.  It might be wrong.
203  **/
204 void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
205 {
206         int fd;
207         STRUCT_STAT st;
208         struct map_struct *buf;
209         int statret;
210         struct file_struct *file = flist->files[i];
211         char *fnamecmp;
212         char fnamecmpbuf[MAXPATHLEN];
213         extern char *compare_dest;
214         extern int list_only;
215         extern int preserve_perms;
216         extern int only_existing;
217         extern int orig_umask;
218
219         if (list_only) return;
220
221         if (verbose > 2)
222                 rprintf(FINFO,"recv_generator(%s,%d)\n",fname,i);
223
224         statret = link_stat(fname,&st);
225
226         if (only_existing && statret == -1 && errno == ENOENT) {
227                 /* we only want to update existing files */
228                 if (verbose > 1) rprintf(FINFO, "not creating new file \"%s\"\n",fname);
229                 return;
230         }
231
232         if (statret == 0 &&
233             !preserve_perms &&
234             (S_ISDIR(st.st_mode) == S_ISDIR(file->mode))) {
235                 /* if the file exists already and we aren't perserving
236                  * permissions then act as though the remote end sent
237                  * us the file permissions we already have */
238                 file->mode = (file->mode & _S_IFMT) | (st.st_mode & ~_S_IFMT);
239         }
240
241         if (S_ISDIR(file->mode)) {
242                 /* The file to be received is a directory, so we need
243                  * to prepare appropriately.  If there is already a
244                  * file of that name and it is *not* a directory, then
245                  * we need to delete it.  If it doesn't exist, then
246                  * recursively create it. */
247
248                 if (dry_run) return; /* XXXX -- might cause inaccuracies?? -- mbp */
249                 if (statret == 0 && !S_ISDIR(st.st_mode)) {
250                         if (robust_unlink(fname) != 0) {
251                                 rprintf(FERROR, RSYNC_NAME
252                                         ": recv_generator: unlink \"%s\" to make room for directory: %s\n",
253                                         fname,strerror(errno));
254                                 return;
255                         }
256                         statret = -1;
257                 }
258                 if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
259                         if (!(relative_paths && errno==ENOENT &&
260                               create_directory_path(fname, orig_umask)==0 &&
261                               do_mkdir(fname,file->mode)==0)) {
262                                 rprintf(FERROR, RSYNC_NAME ": recv_generator: mkdir \"%s\": %s (2)\n",
263                                         fname,strerror(errno));
264                         }
265                 }
266                 /* f_out is set to -1 when doing final directory
267                    permission and modification time repair */
268                 if (set_perms(fname,file,NULL,0) && verbose && (f_out != -1))
269                         rprintf(FINFO,"%s/\n",fname);
270                 return;
271         }
272
273         if (preserve_links && S_ISLNK(file->mode)) {
274 #if SUPPORT_LINKS
275                 char lnk[MAXPATHLEN];
276                 int l;
277                 extern int safe_symlinks;
278
279                 if (safe_symlinks && unsafe_symlink(file->link, fname)) {
280                         if (verbose) {
281                                 rprintf(FINFO,"ignoring unsafe symlink \"%s\" -> \"%s\"\n",
282                                         fname,file->link);
283                         }
284                         return;
285                 }
286                 if (statret == 0) {
287                         l = readlink(fname,lnk,MAXPATHLEN-1);
288                         if (l > 0) {
289                                 lnk[l] = 0;
290                                 /* A link already pointing to the
291                                  * right place -- no further action
292                                  * required. */
293                                 if (strcmp(lnk,file->link) == 0) {
294                                         set_perms(fname,file,&st,1);
295                                         return;
296                                 }
297                         }
298                         /* Not a symlink, so delete whatever's
299                          * already there and put a new symlink
300                          * in place. */
301                         delete_file(fname);
302                 }
303                 if (do_symlink(file->link,fname) != 0) {
304                         rprintf(FERROR,RSYNC_NAME": symlink \"%s\" -> \"%s\": %s\n",
305                                 fname,file->link,strerror(errno));
306                 } else {
307                         set_perms(fname,file,NULL,0);
308                         if (verbose) {
309                                 rprintf(FINFO,"%s -> %s\n", fname,file->link);
310                         }
311                 }
312 #endif
313                 return;
314         }
315
316 #ifdef HAVE_MKNOD
317         if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
318                 if (statret != 0 ||
319                     st.st_mode != file->mode ||
320                     st.st_rdev != file->rdev) {
321                         delete_file(fname);
322                         if (verbose > 2)
323                                 rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
324                                         fname,(int)file->mode,(int)file->rdev);
325                         if (do_mknod(fname,file->mode,file->rdev) != 0) {
326                                 rprintf(FERROR,"mknod %s : %s\n",fname,strerror(errno));
327                         } else {
328                                 set_perms(fname,file,NULL,0);
329                                 if (verbose)
330                                         rprintf(FINFO,"%s\n",fname);
331                         }
332                 } else {
333                         set_perms(fname,file,&st,1);
334                 }
335                 return;
336         }
337 #endif
338
339         if (preserve_hard_links && check_hard_link(file)) {
340                 if (verbose > 1)
341                         rprintf(FINFO, "recv_generator: \"%s\" is a hard link\n",f_name(file));
342                 return;
343         }
344
345         if (!S_ISREG(file->mode)) {
346                 rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname);
347                 return;
348         }
349
350         fnamecmp = fname;
351
352         if ((statret == -1) && (compare_dest != NULL)) {
353                 /* try the file at compare_dest instead */
354                 int saveerrno = errno;
355                 snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",compare_dest,fname);
356                 statret = link_stat(fnamecmpbuf,&st);
357                 if (!S_ISREG(st.st_mode))
358                         statret = -1;
359                 if (statret == -1)
360                         errno = saveerrno;
361 #if HAVE_LINK
362                 else if (link_dest && !dry_run) {
363                         if (do_link(fnamecmpbuf, fname) != 0) {
364                                 if (verbose > 0)
365                                         rprintf(FINFO,"link %s => %s : %s\n",
366                                                 fnamecmpbuf,
367                                                 fname,
368                                                 strerror(errno));
369                         }
370                         fnamecmp = fnamecmpbuf;
371                 }
372 #endif
373                 else
374                         fnamecmp = fnamecmpbuf;
375         }
376
377         if (statret == -1) {
378                 if (errno == ENOENT) {
379                         write_int(f_out,i);
380                         if (!dry_run) send_null_sums(f_out);
381                 } else {
382                         if (verbose > 1)
383                                 rprintf(FERROR, RSYNC_NAME
384                                         ": recv_generator failed to open \"%s\": %s\n",
385                                         fname, strerror(errno));
386                 }
387                 return;
388         }
389
390         if (!S_ISREG(st.st_mode)) {
391                 if (delete_file(fname) != 0) {
392                         return;
393                 }
394
395                 /* now pretend the file didn't exist */
396                 write_int(f_out,i);
397                 if (!dry_run) send_null_sums(f_out);
398                 return;
399         }
400
401         if (opt_ignore_existing && fnamecmp == fname) {
402                 if (verbose > 1)
403                         rprintf(FINFO,"%s exists\n",fname);
404                 return;
405         }
406
407         if (update_only && cmp_modtime(st.st_mtime,file->modtime)>0 && fnamecmp == fname) {
408                 if (verbose > 1)
409                         rprintf(FINFO,"%s is newer\n",fname);
410                 return;
411         }
412
413         if (skip_file(fname, file, &st)) {
414                 if (fnamecmp == fname)
415                         set_perms(fname,file,&st,1);
416                 return;
417         }
418
419         if (dry_run) {
420                 write_int(f_out,i);
421                 return;
422         }
423
424         if (disable_deltas_p()) {
425                 write_int(f_out,i);
426                 send_null_sums(f_out);
427                 return;
428         }
429
430         /* open the file */
431         fd = do_open(fnamecmp, O_RDONLY, 0);
432
433         if (fd == -1) {
434                 rprintf(FERROR,RSYNC_NAME": failed to open \"%s\", continuing : %s\n",fnamecmp,strerror(errno));
435                 /* pretend the file didn't exist */
436                 write_int(f_out,i);
437                 send_null_sums(f_out);
438                 return;
439         }
440
441         if (st.st_size > 0) {
442                 buf = map_file(fd,st.st_size);
443         } else {
444                 buf = NULL;
445         }
446
447         if (verbose > 3)
448                 rprintf(FINFO,"gen mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
449
450         if (verbose > 2)
451                 rprintf(FINFO, "generating and sending sums for %d\n", i);
452
453         write_int(f_out,i);
454         generate_and_send_sums(buf, st.st_size,
455                                adapt_block_size(file, block_size), f_out);
456
457         close(fd);
458         if (buf) unmap_file(buf);
459 }
460
461
462
463 void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
464 {
465         int i;
466         int phase=0;
467
468         if (verbose > 2)
469                 rprintf(FINFO,"generator starting pid=%d count=%d\n",
470                         (int)getpid(),flist->count);
471
472         if (verbose >= 2) {
473                 rprintf(FINFO,
474                         disable_deltas_p()
475                         ? "delta-transmission disabled for local transfer or --whole-file\n"
476                         : "delta transmission enabled\n");
477         }
478
479         /* we expect to just sit around now, so don't exit on a
480            timeout. If we really get a timeout then the other process should
481            exit */
482         io_timeout = 0;
483
484         for (i = 0; i < flist->count; i++) {
485                 struct file_struct *file = flist->files[i];
486                 mode_t saved_mode = file->mode;
487                 if (!file->basename) continue;
488
489                 /* we need to ensure that any directories we create have writeable
490                    permissions initially so that we can create the files within
491                    them. This is then fixed after the files are transferred */
492                 if (!am_root && S_ISDIR(file->mode)) {
493                         file->mode |= S_IWUSR; /* user write */
494                         /* XXX: Could this be causing a problem on SCO?  Perhaps their
495                          * handling of permissions is strange? */
496                 }
497
498                 recv_generator(local_name?local_name:f_name(file), flist,i,f);
499
500                 file->mode = saved_mode;
501         }
502
503         phase++;
504         csum_length = SUM_LENGTH;
505         ignore_times=1;
506
507         if (verbose > 2)
508                 rprintf(FINFO,"generate_files phase=%d\n",phase);
509
510         write_int(f,-1);
511
512         if (remote_version >= 13) {
513                 /* in newer versions of the protocol the files can cycle through
514                    the system more than once to catch initial checksum errors */
515                 for (i=read_int(f_recv); i != -1; i=read_int(f_recv)) {
516                         struct file_struct *file = flist->files[i];
517                         recv_generator(local_name?local_name:f_name(file),
518                                        flist,i,f);
519                 }
520
521                 phase++;
522                 if (verbose > 2)
523                         rprintf(FINFO,"generate_files phase=%d\n",phase);
524
525                 write_int(f,-1);
526         }
527 }