*** empty log message ***
[rsync/rsync.git] / rsync.c
CommitLineData
c627d613
AT
1/*
2 Copyright (C) Andrew Tridgell 1996
3 Copyright (C) Paul Mackerras 1996
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20#include "rsync.h"
21
43a481dc
AT
22extern int csum_length;
23
c627d613
AT
24extern int verbose;
25extern int am_server;
26extern int always_checksum;
27extern time_t starttime;
28
29extern char *backup_suffix;
30
31extern int block_size;
32extern int update_only;
33extern int make_backups;
34extern int preserve_links;
35extern int preserve_perms;
36extern int preserve_devices;
37extern int preserve_uid;
38extern int preserve_gid;
39extern int preserve_times;
40extern int dry_run;
41extern int ignore_times;
42extern int recurse;
43extern int delete_mode;
44extern int cvs_exclude;
45
46/*
47 free a sums struct
48 */
49static void free_sums(struct sum_struct *s)
50{
51 if (s->sums) free(s->sums);
52 free(s);
53}
54
55
56
57/*
58 send a sums struct down a fd
59 */
60static void send_sums(struct sum_struct *s,int f_out)
61{
62 int i;
63
64 /* tell the other guy how many we are going to be doing and how many
65 bytes there are in the last chunk */
66 write_int(f_out,s?s->count:0);
67 write_int(f_out,s?s->n:block_size);
68 write_int(f_out,s?s->remainder:0);
69 if (s)
70 for (i=0;i<s->count;i++) {
71 write_int(f_out,s->sums[i].sum1);
43a481dc 72 write_buf(f_out,s->sums[i].sum2,csum_length);
c627d613
AT
73 }
74 write_flush(f_out);
75}
76
77
78/*
79 generate a stream of signatures/checksums that describe a buffer
80
81 generate approximately one checksum every n bytes
82 */
83static struct sum_struct *generate_sums(char *buf,off_t len,int n)
84{
85 int i;
86 struct sum_struct *s;
87 int count;
88 int block_len = n;
89 int remainder = (len%block_len);
90 off_t offset = 0;
91
92 count = (len+(block_len-1))/block_len;
93
94 s = (struct sum_struct *)malloc(sizeof(*s));
95 if (!s) out_of_memory("generate_sums");
96
97 s->count = count;
98 s->remainder = remainder;
99 s->n = n;
100 s->flength = len;
101
102 if (count==0) {
103 s->sums = NULL;
104 return s;
105 }
106
107 if (verbose > 3)
108 fprintf(stderr,"count=%d rem=%d n=%d flength=%d\n",
109 s->count,s->remainder,s->n,(int)s->flength);
110
111 s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
112 if (!s->sums) out_of_memory("generate_sums");
113
114 for (i=0;i<count;i++) {
115 int n1 = MIN(len,n);
d9bea2dd 116 char *map = map_ptr(buf,offset,n1);
c627d613 117
d9bea2dd
AT
118 s->sums[i].sum1 = get_checksum1(map,n1);
119 get_checksum2(map,n1,s->sums[i].sum2);
c627d613
AT
120
121 s->sums[i].offset = offset;
122 s->sums[i].len = n1;
123 s->sums[i].i = i;
124
125 if (verbose > 3)
126 fprintf(stderr,"chunk[%d] offset=%d len=%d sum1=%08x\n",
127 i,(int)s->sums[i].offset,s->sums[i].len,s->sums[i].sum1);
128
129 len -= n1;
c627d613
AT
130 offset += n1;
131 }
132
133 return s;
134}
135
136
137/*
138 receive the checksums for a buffer
139 */
140static struct sum_struct *receive_sums(int f)
141{
142 struct sum_struct *s;
143 int i;
144 off_t offset = 0;
145 int block_len;
146
147 s = (struct sum_struct *)malloc(sizeof(*s));
148 if (!s) out_of_memory("receive_sums");
149
150 s->count = read_int(f);
151 s->n = read_int(f);
152 s->remainder = read_int(f);
153 s->sums = NULL;
154
155 if (verbose > 3)
156 fprintf(stderr,"count=%d n=%d rem=%d\n",
157 s->count,s->n,s->remainder);
158
159 block_len = s->n;
160
161 if (s->count == 0)
162 return(s);
163
164 s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
165 if (!s->sums) out_of_memory("receive_sums");
166
167 for (i=0;i<s->count;i++) {
168 s->sums[i].sum1 = read_int(f);
43a481dc 169 read_buf(f,s->sums[i].sum2,csum_length);
c627d613
AT
170
171 s->sums[i].offset = offset;
172 s->sums[i].i = i;
173
174 if (i == s->count-1 && s->remainder != 0) {
175 s->sums[i].len = s->remainder;
176 } else {
177 s->sums[i].len = s->n;
178 }
179 offset += s->sums[i].len;
180
181 if (verbose > 3)
182 fprintf(stderr,"chunk[%d] len=%d offset=%d sum1=%08x\n",
183 i,s->sums[i].len,(int)s->sums[i].offset,s->sums[i].sum1);
184 }
185
186 s->flength = offset;
187
188 return s;
189}
190
191
192static void set_perms(char *fname,struct file_struct *file,struct stat *st,
193 int report)
194{
195 int updated = 0;
196 struct stat st2;
197
198 if (dry_run) return;
199
200 if (!st) {
201 if (stat(fname,&st2) != 0) {
202 fprintf(stderr,"stat %s : %s\n",fname,strerror(errno));
203 return;
204 }
205 st = &st2;
206 }
207
7bec6a5c
AT
208 if (preserve_times && !S_ISLNK(st->st_mode) &&
209 st->st_mtime != file->modtime) {
c627d613
AT
210 updated = 1;
211 if (set_modtime(fname,file->modtime) != 0) {
212 fprintf(stderr,"failed to set times on %s : %s\n",
213 fname,strerror(errno));
214 return;
215 }
216 }
217
218#ifdef HAVE_CHMOD
7bec6a5c
AT
219 if (preserve_perms && !S_ISLNK(st->st_mode) &&
220 st->st_mode != file->mode) {
c627d613
AT
221 updated = 1;
222 if (chmod(fname,file->mode) != 0) {
223 fprintf(stderr,"failed to set permissions on %s : %s\n",
224 fname,strerror(errno));
225 return;
226 }
227 }
228#endif
229
230 if ((preserve_uid && st->st_uid != file->uid) ||
231 (preserve_gid && st->st_gid != file->gid)) {
232 updated = 1;
233 if (chown(fname,
234 preserve_uid?file->uid:-1,
235 preserve_gid?file->gid:-1) != 0) {
236 if (verbose>1 || preserve_uid)
237 fprintf(stderr,"chown %s : %s\n",fname,strerror(errno));
238 return;
239 }
240 }
241
242 if (verbose > 1 && report) {
243 if (updated)
244 fprintf(am_server?stderr:stdout,"%s\n",fname);
245 else
246 fprintf(am_server?stderr:stdout,"%s is uptodate\n",fname);
247 }
248}
249
250
251void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
252{
253 int fd;
254 struct stat st;
255 char *buf;
256 struct sum_struct *s;
257 char sum[SUM_LENGTH];
258 int statret;
259
260 if (verbose > 2)
261 fprintf(stderr,"recv_generator(%s)\n",fname);
262
263 statret = lstat(fname,&st);
264
265#if SUPPORT_LINKS
266 if (preserve_links && S_ISLNK(flist->files[i].mode)) {
267 char lnk[MAXPATHLEN];
268 int l;
269 if (statret == 0) {
270 l = readlink(fname,lnk,MAXPATHLEN-1);
271 if (l > 0) {
272 lnk[l] = 0;
273 if (strcmp(lnk,flist->files[i].link) == 0) {
7bec6a5c 274 set_perms(fname,&flist->files[i],&st,1);
c627d613
AT
275 return;
276 }
277 }
278 }
279 if (!dry_run) unlink(fname);
280 if (!dry_run && symlink(flist->files[i].link,fname) != 0) {
281 fprintf(stderr,"link %s -> %s : %s\n",
282 fname,flist->files[i].link,strerror(errno));
283 } else {
7bec6a5c 284 set_perms(fname,&flist->files[i],NULL,0);
c627d613 285 if (verbose)
7bec6a5c
AT
286 fprintf(am_server?stderr:stdout,"%s -> %s\n",
287 fname,flist->files[i].link);
c627d613
AT
288 }
289 return;
290 }
291#endif
292
293#ifdef HAVE_MKNOD
182dca5c 294 if (preserve_devices && IS_DEVICE(flist->files[i].mode)) {
c627d613
AT
295 if (statret != 0 ||
296 st.st_mode != flist->files[i].mode ||
297 st.st_rdev != flist->files[i].dev) {
298 if (!dry_run) unlink(fname);
299 if (verbose > 2)
300 fprintf(stderr,"mknod(%s,0%o,0x%x)\n",
301 fname,(int)flist->files[i].mode,(int)flist->files[i].dev);
302 if (!dry_run &&
303 mknod(fname,flist->files[i].mode,flist->files[i].dev) != 0) {
304 fprintf(stderr,"mknod %s : %s\n",fname,strerror(errno));
305 } else {
306 set_perms(fname,&flist->files[i],NULL,0);
307 if (verbose)
308 fprintf(am_server?stderr:stdout,"%s\n",fname);
309 }
310 } else {
311 set_perms(fname,&flist->files[i],&st,1);
312 }
313 return;
314 }
315#endif
316
317 if (!S_ISREG(flist->files[i].mode)) {
318 fprintf(stderr,"skipping non-regular file %s\n",fname);
319 return;
320 }
321
322 if (statret == -1) {
323 if (errno == ENOENT) {
324 write_int(f_out,i);
325 if (!dry_run) send_sums(NULL,f_out);
326 } else {
327 if (verbose > 1)
328 fprintf(stderr,"recv_generator failed to open %s\n",fname);
329 }
330 return;
331 }
332
333 if (!S_ISREG(st.st_mode)) {
334 fprintf(stderr,"%s : not a regular file\n",fname);
335 return;
336 }
337
338 if (update_only && st.st_mtime >= flist->files[i].modtime) {
339 if (verbose > 1)
340 fprintf(stderr,"%s is newer\n",fname);
341 return;
342 }
343
344 if (always_checksum && S_ISREG(st.st_mode)) {
345 file_checksum(fname,sum,st.st_size);
346 }
347
348 if (st.st_size == flist->files[i].length &&
349 ((!ignore_times && st.st_mtime == flist->files[i].modtime) ||
350 (always_checksum && S_ISREG(st.st_mode) &&
43a481dc 351 memcmp(sum,flist->files[i].sum,csum_length) == 0))) {
c627d613
AT
352 set_perms(fname,&flist->files[i],&st,1);
353 return;
354 }
355
356 if (dry_run) {
357 write_int(f_out,i);
358 return;
359 }
360
361 /* open the file */
362 fd = open(fname,O_RDONLY);
363
364 if (fd == -1) {
365 fprintf(stderr,"failed to open %s : %s\n",fname,strerror(errno));
366 return;
367 }
368
369 if (st.st_size > 0) {
370 buf = map_file(fd,st.st_size);
c627d613
AT
371 } else {
372 buf = NULL;
373 }
374
375 if (verbose > 3)
376 fprintf(stderr,"mapped %s of size %d\n",fname,(int)st.st_size);
377
378 s = generate_sums(buf,st.st_size,block_size);
379
380 write_int(f_out,i);
381 send_sums(s,f_out);
382 write_flush(f_out);
383
384 close(fd);
385 unmap_file(buf,st.st_size);
386
387 free_sums(s);
388}
389
390
391
392static void receive_data(int f_in,char *buf,int fd,char *fname)
393{
394 int i,n,remainder,len,count;
395 off_t offset = 0;
396 off_t offset2;
397
398 count = read_int(f_in);
399 n = read_int(f_in);
400 remainder = read_int(f_in);
401
402 for (i=read_int(f_in); i != 0; i=read_int(f_in)) {
403 if (i > 0) {
404 if (verbose > 3)
405 fprintf(stderr,"data recv %d at %d\n",i,(int)offset);
406
407 if (read_write(f_in,fd,i) != i) {
408 fprintf(stderr,"write failed on %s : %s\n",fname,strerror(errno));
34ccb63e 409 exit_cleanup(1);
c627d613
AT
410 }
411 offset += i;
412 } else {
413 i = -(i+1);
414 offset2 = i*n;
415 len = n;
416 if (i == count-1 && remainder != 0)
417 len = remainder;
418
419 if (verbose > 3)
420 fprintf(stderr,"chunk[%d] of size %d at %d offset=%d\n",
421 i,len,(int)offset2,(int)offset);
422
7bec6a5c 423 if (write_sparse(fd,map_ptr(buf,offset2,len),len) != len) {
c627d613 424 fprintf(stderr,"write failed on %s : %s\n",fname,strerror(errno));
34ccb63e 425 exit_cleanup(1);
c627d613
AT
426 }
427 offset += len;
428 }
429 }
7bec6a5c
AT
430
431 if (offset > 0 && sparse_end(fd) != 0) {
432 fprintf(stderr,"write failed on %s : %s\n",fname,strerror(errno));
34ccb63e 433 exit_cleanup(1);
7bec6a5c 434 }
c627d613
AT
435}
436
437
438static void delete_one(struct file_struct *f)
439{
440 if (!S_ISDIR(f->mode)) {
441 if (!dry_run && unlink(f->name) != 0) {
442 fprintf(stderr,"unlink %s : %s\n",f->name,strerror(errno));
443 } else if (verbose) {
444 fprintf(stderr,"deleting %s\n",f->name);
445 }
446 } else {
447 if (!dry_run && rmdir(f->name) != 0) {
448 if (errno != ENOTEMPTY)
449 fprintf(stderr,"rmdir %s : %s\n",f->name,strerror(errno));
450 } else if (verbose) {
451 fprintf(stderr,"deleting directory %s\n",f->name);
452 }
453 }
454}
455
456
457static void delete_files(struct file_list *flist)
458{
459 struct file_list *local_file_list;
460 char *dot=".";
461 int i;
462
4fe159a8 463 if (cvs_exclude)
79fbb6f5 464 add_cvs_excludes();
4fe159a8 465
c627d613
AT
466 if (!(local_file_list = send_file_list(-1,recurse,1,&dot)))
467 return;
468
469 for (i=local_file_list->count;i>=0;i--) {
470 if (!local_file_list->files[i].name) continue;
471 if (-1 == flist_find(flist,&local_file_list->files[i])) {
472 delete_one(&local_file_list->files[i]);
473 }
474 }
475}
476
477static char *cleanup_fname = NULL;
478
34ccb63e 479void exit_cleanup(int code)
c627d613
AT
480{
481 if (cleanup_fname)
482 unlink(cleanup_fname);
34ccb63e
AT
483 exit(code);
484}
485
486void sig_int(void)
487{
488 exit_cleanup(1);
c627d613
AT
489}
490
491
492int recv_files(int f_in,struct file_list *flist,char *local_name)
493{
494 int fd1,fd2;
495 struct stat st;
496 char *fname;
497 char fnametmp[MAXPATHLEN];
498 char *buf;
499 int i;
500
981791bd 501 if (verbose > 2) {
c627d613 502 fprintf(stderr,"recv_files(%d) starting\n",flist->count);
981791bd 503 }
c627d613
AT
504
505 if (recurse && delete_mode && !local_name && flist->count>0) {
506 delete_files(flist);
507 }
508
509 while (1)
510 {
511 i = read_int(f_in);
512 if (i == -1) break;
513
514 fname = flist->files[i].name;
515
516 if (local_name)
517 fname = local_name;
518
519 if (dry_run) {
520 if (!am_server && verbose)
521 printf("%s\n",fname);
522 continue;
523 }
524
525 if (verbose > 2)
526 fprintf(stderr,"recv_files(%s)\n",fname);
527
528 /* open the file */
ac1eb754 529 fd1 = open(fname,O_RDONLY);
c627d613 530
ac1eb754 531 if (fd1 != -1 && fstat(fd1,&st) != 0) {
c627d613
AT
532 fprintf(stderr,"fstat %s : %s\n",fname,strerror(errno));
533 close(fd1);
534 return -1;
535 }
536
ac1eb754 537 if (fd1 != -1 && !S_ISREG(st.st_mode)) {
c627d613
AT
538 fprintf(stderr,"%s : not a regular file\n",fname);
539 close(fd1);
540 return -1;
541 }
542
ac1eb754 543 if (fd1 != -1 && st.st_size > 0) {
c627d613 544 buf = map_file(fd1,st.st_size);
c627d613
AT
545 } else {
546 buf = NULL;
547 }
548
549 if (verbose > 2)
550 fprintf(stderr,"mapped %s of size %d\n",fname,(int)st.st_size);
551
552 /* open tmp file */
553 sprintf(fnametmp,"%s.XXXXXX",fname);
554 if (NULL == mktemp(fnametmp)) {
555 fprintf(stderr,"mktemp %s failed\n",fnametmp);
556 return -1;
557 }
d9bea2dd 558 fd2 = open(fnametmp,O_WRONLY|O_CREAT,flist->files[i].mode);
c627d613
AT
559 if (fd2 == -1) {
560 fprintf(stderr,"open %s : %s\n",fnametmp,strerror(errno));
561 return -1;
562 }
563
564 cleanup_fname = fnametmp;
565
566 if (!am_server && verbose)
567 printf("%s\n",fname);
568
569 /* recv file data */
570 receive_data(f_in,buf,fd2,fname);
571
981791bd
AT
572 if (fd1 != -1) {
573 unmap_file(buf,st.st_size);
574 close(fd1);
575 }
c627d613
AT
576 close(fd2);
577
578 if (verbose > 2)
579 fprintf(stderr,"renaming %s to %s\n",fnametmp,fname);
580
581 if (make_backups) {
582 char fnamebak[MAXPATHLEN];
583 sprintf(fnamebak,"%s%s",fname,backup_suffix);
ac1eb754 584 if (rename(fname,fnamebak) != 0 && errno != ENOENT) {
c627d613 585 fprintf(stderr,"rename %s %s : %s\n",fname,fnamebak,strerror(errno));
34ccb63e 586 exit_cleanup(1);
c627d613
AT
587 }
588 }
589
590 /* move tmp file over real file */
591 if (rename(fnametmp,fname) != 0) {
592 fprintf(stderr,"rename %s -> %s : %s\n",
593 fnametmp,fname,strerror(errno));
594 }
595
596 cleanup_fname = NULL;
597
c627d613
AT
598 set_perms(fname,&flist->files[i],NULL,0);
599 }
600
601 if (verbose > 2)
602 fprintf(stderr,"recv_files finished\n");
603
604 return 0;
605}
606
607
608
609off_t send_files(struct file_list *flist,int f_out,int f_in)
610{
611 int fd;
612 struct sum_struct *s;
613 char *buf;
614 struct stat st;
615 char fname[MAXPATHLEN];
616 off_t total=0;
617 int i;
618
619 if (verbose > 2)
620 fprintf(stderr,"send_files starting\n");
621
720b47f2
AT
622 setup_nonblocking(f_in,f_out);
623
c627d613
AT
624 while (1)
625 {
626 i = read_int(f_in);
627 if (i == -1) break;
628
629 fname[0] = 0;
630 if (flist->files[i].dir) {
631 strcpy(fname,flist->files[i].dir);
632 strcat(fname,"/");
633 }
634 strcat(fname,flist->files[i].name);
635
636 if (verbose > 2)
637 fprintf(stderr,"send_files(%d,%s)\n",i,fname);
638
639 if (dry_run) {
640 if (!am_server && verbose)
641 printf("%s\n",fname);
642 write_int(f_out,i);
643 continue;
644 }
645
646 s = receive_sums(f_in);
647 if (!s) {
648 fprintf(stderr,"receive_sums failed\n");
649 return -1;
650 }
651
652 fd = open(fname,O_RDONLY);
653 if (fd == -1) {
654 fprintf(stderr,"send_files failed to open %s: %s\n",
655 fname,strerror(errno));
656 continue;
657 }
658
659 /* map the local file */
660 if (fstat(fd,&st) != 0) {
661 fprintf(stderr,"fstat failed : %s\n",strerror(errno));
662 return -1;
663 }
664
665 if (st.st_size > 0) {
666 buf = map_file(fd,st.st_size);
c627d613
AT
667 } else {
668 buf = NULL;
669 }
670
671 if (verbose > 2)
672 fprintf(stderr,"send_files mapped %s of size %d\n",
673 fname,(int)st.st_size);
674
675 write_int(f_out,i);
676
677 write_int(f_out,s->count);
678 write_int(f_out,s->n);
679 write_int(f_out,s->remainder);
680
681 if (verbose > 2)
682 fprintf(stderr,"calling match_sums %s\n",fname);
683
684 if (!am_server && verbose)
685 printf("%s\n",fname);
686
720b47f2 687 match_sums(f_out,s,buf,st.st_size);
c627d613
AT
688 write_flush(f_out);
689
690 unmap_file(buf,st.st_size);
691 close(fd);
692
693 free_sums(s);
694
695 if (verbose > 2)
696 fprintf(stderr,"sender finished %s\n",fname);
697
698 total += st.st_size;
699 }
700
701 match_report();
702
703 write_int(f_out,-1);
704 write_flush(f_out);
705
706 return total;
707}
708
709
710
711void generate_files(int f,struct file_list *flist,char *local_name)
712{
713 int i;
714
715 if (verbose > 2)
716 fprintf(stderr,"generator starting pid=%d count=%d\n",
717 (int)getpid(),flist->count);
718
719 for (i = 0; i < flist->count; i++) {
720 if (!flist->files[i].name) continue;
721 if (S_ISDIR(flist->files[i].mode)) {
722 if (dry_run) continue;
723 if (mkdir(flist->files[i].name,flist->files[i].mode) != 0 &&
724 errno != EEXIST) {
725 fprintf(stderr,"mkdir %s : %s\n",
726 flist->files[i].name,strerror(errno));
727 }
728 continue;
729 }
730 recv_generator(local_name?local_name:flist->files[i].name,
731 flist,i,f);
732 }
733 write_int(f,-1);
734 write_flush(f);
735 if (verbose > 2)
736 fprintf(stderr,"generator wrote %d\n",write_total());
737}