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