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