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