]>
git.ipfire.org Git - thirdparty/rsync.git/blob - main.c
2 Copyright (C) Andrew Tridgell 1996
3 Copyright (C) Paul Mackerras 1996
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.
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.
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.
23 int always_checksum
= 0;
26 int block_size
=BLOCK_SIZE
;
28 char *backup_suffix
= BACKUP_SUFFIX
;
31 static char *rsync_path
= RSYNC_NAME
;
36 int preserve_links
= 0;
37 int preserve_hard_links
= 0;
38 int preserve_perms
= 0;
39 int preserve_devices
= 0;
42 int preserve_times
= 0;
49 int one_file_system
=0;
63 static int port
= RSYNC_PORT
;
65 static char *shell_cmd
;
67 extern int csum_length
;
74 static void usage(int fd
);
76 static void report(int f
)
79 time_t t
= time(NULL
);
83 if (am_server
&& am_sender
) {
84 write_longint(f
,read_total());
85 write_longint(f
,write_total());
86 write_longint(f
,total_size
);
97 out
= read_longint(f
);
98 tsize
= read_longint(f
);
101 printf("wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
102 (double)out
,(double)in
,(in
+out
)/(0.5 + (t
-starttime
)));
103 printf("total size is %.0f speedup is %.2f\n",
104 (double)tsize
,(1.0*tsize
)/(in
+out
));
108 static void server_options(char **args
,int *argc
)
111 static char argstr
[50];
112 static char bsize
[30];
113 static char iotime
[30];
116 args
[ac
++] = "--server";
119 args
[ac
++] = "--sender";
123 for (i
=0;i
<verbose
;i
++)
137 if (preserve_hard_links
)
143 if (preserve_devices
)
167 if (x
!= 1) args
[ac
++] = argstr
;
169 if (block_size
!= BLOCK_SIZE
) {
170 sprintf(bsize
,"-B%d",block_size
);
175 sprintf(iotime
,"--timeout=%d",io_timeout
);
179 if (strcmp(backup_suffix
, BACKUP_SUFFIX
)) {
180 args
[ac
++] = "--suffix";
181 args
[ac
++] = backup_suffix
;
185 args
[ac
++] = "--delete";
188 args
[ac
++] = "--force";
191 args
[ac
++] = "--numeric-ids";
194 args
[ac
++] = "--temp-dir";
203 static int do_cmd(char *cmd
,char *machine
,char *user
,char *path
,int *f_in
,int *f_out
)
211 cmd
= getenv(RSYNC_RSH_ENV
);
218 for (tok
=strtok(cmd
," ");tok
;tok
=strtok(NULL
," ")) {
223 /* remsh (on HPUX) takes the arguments the other way around */
224 args
[argc
++] = machine
;
234 args
[argc
++] = machine
;
237 args
[argc
++] = rsync_path
;
239 server_options(args
,&argc
);
250 rprintf(FINFO
,"cmd=");
252 rprintf(FINFO
,"%s ",args
[i
]);
257 ret
= local_child(argc
, args
, f_in
, f_out
);
259 ret
= piped_child(args
,f_in
,f_out
);
267 out_of_memory("do_cmd");
268 return 0; /* not reached */
274 static char *get_local_name(struct file_list
*flist
,char *name
)
278 if (do_stat(name
,&st
) == 0) {
279 if (S_ISDIR(st
.st_mode
)) {
280 if (chdir(name
) != 0) {
281 rprintf(FERROR
,"chdir %s : %s (1)\n",name
,strerror(errno
));
286 if (flist
->count
> 1) {
287 rprintf(FERROR
,"ERROR: destination must be a directory when copying more than 1 file\n");
293 if (flist
->count
== 1)
299 if (do_mkdir(name
,0777 & ~orig_umask
) != 0) {
300 rprintf(FERROR
,"mkdir %s : %s (1)\n",name
,strerror(errno
));
303 rprintf(FINFO
,"created directory %s\n",name
);
306 if (chdir(name
) != 0) {
307 rprintf(FERROR
,"chdir %s : %s (2)\n",name
,strerror(errno
));
317 static void do_server_sender(int f_in
, int f_out
, int argc
,char *argv
[])
320 struct file_list
*flist
;
324 rprintf(FINFO
,"server_sender starting pid=%d\n",(int)getpid());
326 if (!relative_paths
&& chdir(dir
) != 0) {
327 rprintf(FERROR
,"chdir %s: %s (3)\n",dir
,strerror(errno
));
333 if (strcmp(dir
,".")) {
335 if (strcmp(dir
,"/") == 0)
342 char *name
= lp_name(module_id
);
343 int l
= strlen(name
);
344 for (i
=0;i
<argc
;i
++) {
345 if (strncmp(argv
[i
], name
, l
) == 0) {
347 if (!*argv
[i
]) argv
[i
] = ".";
352 if (argc
== 0 && recurse
) {
358 rprintf(FINFO
,"sending file list\n");
360 flist
= send_file_list(f_out
,argc
,argv
);
361 send_files(flist
,f_out
,f_in
);
367 static int do_recv(int f_in
,int f_out
,struct file_list
*flist
,char *local_name
)
373 if (preserve_hard_links
)
374 init_hard_links(flist
);
376 if (pipe(recv_pipe
) < 0) {
377 rprintf(FERROR
,"pipe failed in do_recv\n");
382 if ((pid
=do_fork()) == 0) {
383 recv_files(f_in
,flist
,local_name
,recv_pipe
[1]);
385 rprintf(FINFO
,"receiver read %ld\n",(long)read_total());
389 generate_files(f_out
,flist
,local_name
,recv_pipe
[0]);
391 waitpid(pid
, &status
, 0);
397 static void do_server_recv(int f_in
, int f_out
, int argc
,char *argv
[])
400 struct file_list
*flist
;
401 char *local_name
=NULL
;
405 rprintf(FINFO
,"server_recv(%d) starting pid=%d\n",argc
,(int)getpid());
408 char *name
= lp_name(module_id
);
409 int i
, l
= strlen(name
);
410 for (i
=0;i
<argc
;i
++) {
411 if (strncmp(argv
[i
], name
, l
) == 0) {
413 if (!*argv
[i
]) argv
[i
] = ".";
415 rprintf(FINFO
,"argv[%d]=%s\n", i
, argv
[i
]);
423 if (!am_daemon
&& chdir(dir
) != 0) {
424 rprintf(FERROR
,"chdir %s : %s (4)\n",
425 dir
,strerror(errno
));
431 recv_exclude_list(f_in
);
433 flist
= recv_file_list(f_in
);
434 if (!flist
|| flist
->count
== 0) {
435 rprintf(FERROR
,"nothing to do\n");
440 if (strcmp(dir
,".")) {
441 argv
[0] += strlen(dir
);
442 if (argv
[0][0] == '/') argv
[0]++;
444 local_name
= get_local_name(flist
,argv
[0]);
447 status
= do_recv(f_in
,f_out
,flist
,local_name
);
448 exit_cleanup(status
);
452 void start_server(int f_in
, int f_out
, int argc
, char *argv
[])
454 setup_protocol(f_out
, f_in
);
457 recv_exclude_list(f_in
);
460 do_server_sender(f_in
, f_out
, argc
, argv
);
462 do_server_recv(f_in
, f_out
, argc
, argv
);
467 static int client_run(int f_in
, int f_out
, int pid
, int argc
, char *argv
[])
469 struct file_list
*flist
;
470 int status
= 0, status2
= 0;
471 char *local_name
= NULL
;
473 setup_protocol(f_out
,f_in
);
479 send_exclude_list(f_out
);
480 flist
= send_file_list(f_out
,argc
,argv
);
482 rprintf(FINFO
,"file list sent\n");
483 send_files(flist
,f_out
,f_in
);
486 rprintf(FINFO
,"waiting on %d\n",pid
);
487 waitpid(pid
, &status
, 0);
490 exit_cleanup(status
);
493 send_exclude_list(f_out
);
495 flist
= recv_file_list(f_in
);
496 if (!flist
|| flist
->count
== 0) {
497 rprintf(FINFO
,"nothing to do\n");
501 local_name
= get_local_name(flist
,argv
[0]);
503 status2
= do_recv(f_in
,f_out
,flist
,local_name
);
508 waitpid(pid
, &status
, 0);
511 return status
| status2
;
515 int start_socket_client(char *host
, char *path
, int argc
, char *argv
[])
518 char *sargs
[MAX_ARGS
];
524 fd
= open_socket_out(host
, port
);
529 server_options(sargs
,&sargc
);
531 sargs
[sargc
++] = ".";
534 sargs
[sargc
++] = path
;
538 p
= strchr(path
,'/');
540 io_printf(fd
,"%s\n",path
);
543 if (!read_line(fd
, line
, sizeof(line
)-1)) {
547 if (sscanf(line
,"RSYNCD %d", &version
) != 1) {
552 if (!read_line(fd
, line
, sizeof(line
)-1)) {
555 if (strcmp(line
,"RSYNCD: OK") == 0) break;
556 rprintf(FINFO
,"%s\n", line
);
559 for (i
=0;i
<sargc
;i
++) {
560 io_printf(fd
,"%s\n", sargs
[i
]);
566 if (!read_line(fd
, line
, sizeof(line
)-1)) {
569 rprintf(FINFO
,"%s\n", line
);
573 return client_run(fd
, fd
, -1, argc
, argv
);
576 int start_client(int argc
, char *argv
[])
579 char *shell_machine
= NULL
;
580 char *shell_path
= NULL
;
581 char *shell_user
= NULL
;
585 p
= strchr(argv
[0],':');
590 return start_socket_client(argv
[0], p
+2, argc
-1, argv
+1);
594 shell_machine
= argv
[0];
601 p
= strchr(argv
[argc
-1],':');
604 } else if (p
[1] == ':') {
606 return start_socket_client(argv
[argc
-1], p
+2, argc
-1, argv
);
610 shell_machine
= NULL
;
611 shell_path
= argv
[argc
-1];
614 shell_machine
= argv
[argc
-1];
621 p
= strchr(shell_machine
,'@');
624 shell_user
= shell_machine
;
630 rprintf(FINFO
,"cmd=%s machine=%s user=%s path=%s\n",
631 shell_cmd
?shell_cmd
:"",
632 shell_machine
?shell_machine
:"",
633 shell_user
?shell_user
:"",
634 shell_path
?shell_path
:"");
637 if (!am_sender
&& argc
!= 1) {
642 pid
= do_cmd(shell_cmd
,shell_machine
,shell_user
,shell_path
,&f_in
,&f_out
);
649 return client_run(f_in
, f_out
, pid
, argc
, argv
);
653 static void usage(int F
)
655 rprintf(F
,"rsync version %s Copyright Andrew Tridgell and Paul Mackerras\n\n",
657 rprintf(F
,"Usage:\t%s [options] src user@host:dest\nOR",RSYNC_NAME
);
658 rprintf(F
,"\t%s [options] user@host:src dest\n\n",RSYNC_NAME
);
659 rprintf(F
,"Options:\n");
660 rprintf(F
,"-v, --verbose increase verbosity\n");
661 rprintf(F
,"-c, --checksum always checksum\n");
662 rprintf(F
,"-a, --archive archive mode (same as -rlptDog)\n");
663 rprintf(F
,"-r, --recursive recurse into directories\n");
664 rprintf(F
,"-R, --relative use relative path names\n");
665 rprintf(F
,"-b, --backup make backups (default ~ extension)\n");
666 rprintf(F
,"-u, --update update only (don't overwrite newer files)\n");
667 rprintf(F
,"-l, --links preserve soft links\n");
668 rprintf(F
,"-L, --copy-links treat soft links like regular files\n");
669 rprintf(F
,"-H, --hard-links preserve hard links\n");
670 rprintf(F
,"-p, --perms preserve permissions\n");
671 rprintf(F
,"-o, --owner preserve owner (root only)\n");
672 rprintf(F
,"-g, --group preserve group\n");
673 rprintf(F
,"-D, --devices preserve devices (root only)\n");
674 rprintf(F
,"-t, --times preserve times\n");
675 rprintf(F
,"-S, --sparse handle sparse files efficiently\n");
676 rprintf(F
,"-n, --dry-run show what would have been transferred\n");
677 rprintf(F
,"-W, --whole-file copy whole files, no incremental checks\n");
678 rprintf(F
,"-x, --one-file-system don't cross filesystem boundaries\n");
679 rprintf(F
,"-B, --block-size SIZE checksum blocking size\n");
680 rprintf(F
,"-e, --rsh COMMAND specify rsh replacement\n");
681 rprintf(F
," --rsync-path PATH specify path to rsync on the remote machine\n");
682 rprintf(F
,"-C, --cvs-exclude auto ignore files in the same way CVS does\n");
683 rprintf(F
," --delete delete files that don't exist on the sending side\n");
684 rprintf(F
," --force force deletion of directories even if not empty\n");
685 rprintf(F
," --numeric-ids don't map uid/gid values by user/group name\n");
686 rprintf(F
," --timeout TIME set IO timeout in seconds\n");
687 rprintf(F
,"-I, --ignore-times don't exclude files that match length and time\n");
688 rprintf(F
,"-T --temp-dir DIR create temporary files in directory DIR\n");
689 rprintf(F
,"-z, --compress compress file data\n");
690 rprintf(F
," --exclude FILE exclude file FILE\n");
691 rprintf(F
," --exclude-from FILE exclude files listed in FILE\n");
692 rprintf(F
," --suffix SUFFIX override backup suffix\n");
693 rprintf(F
," --version print version number\n");
696 rprintf(F
,"the backup suffix defaults to %s\n",BACKUP_SUFFIX
);
697 rprintf(F
,"the block size defaults to %d\n",BLOCK_SIZE
);
700 enum {OPT_VERSION
,OPT_SUFFIX
,OPT_SENDER
,OPT_SERVER
,OPT_EXCLUDE
,
701 OPT_EXCLUDE_FROM
,OPT_DELETE
,OPT_NUMERIC_IDS
,OPT_RSYNC_PATH
,
702 OPT_FORCE
,OPT_TIMEOUT
,OPT_DAEMON
};
704 static char *short_options
= "oblLWHpguDCtcahvrRIxnSe:B:T:z";
706 static struct option long_options
[] = {
707 {"version", 0, 0, OPT_VERSION
},
708 {"server", 0, 0, OPT_SERVER
},
709 {"sender", 0, 0, OPT_SENDER
},
710 {"delete", 0, 0, OPT_DELETE
},
711 {"force", 0, 0, OPT_FORCE
},
712 {"numeric-ids", 0, 0, OPT_NUMERIC_IDS
},
713 {"exclude", 1, 0, OPT_EXCLUDE
},
714 {"exclude-from",1, 0, OPT_EXCLUDE_FROM
},
715 {"rsync-path", 1, 0, OPT_RSYNC_PATH
},
716 {"one-file-system",0, 0, 'x'},
717 {"ignore-times",0, 0, 'I'},
719 {"dry-run", 0, 0, 'n'},
720 {"sparse", 0, 0, 'S'},
721 {"cvs-exclude", 0, 0, 'C'},
722 {"archive", 0, 0, 'a'},
723 {"checksum", 0, 0, 'c'},
724 {"backup", 0, 0, 'b'},
725 {"update", 0, 0, 'u'},
726 {"verbose", 0, 0, 'v'},
727 {"recursive", 0, 0, 'r'},
728 {"relative", 0, 0, 'R'},
729 {"devices", 0, 0, 'D'},
730 {"perms", 0, 0, 'p'},
731 {"links", 0, 0, 'l'},
732 {"copy-links", 0, 0, 'L'},
733 {"whole-file", 0, 0, 'W'},
734 {"hard-links", 0, 0, 'H'},
735 {"owner", 0, 0, 'o'},
736 {"group", 0, 0, 'g'},
737 {"times", 0, 0, 't'},
739 {"suffix", 1, 0, OPT_SUFFIX
},
740 {"block-size", 1, 0, 'B'},
741 {"timeout", 1, 0, OPT_TIMEOUT
},
742 {"temp-dir", 1, 0, 'T'},
743 {"compress", 0, 0, 'z'},
744 {"daemon", 0, 0, OPT_DAEMON
},
747 RETSIGTYPE
sigusr1_handler(int val
) {
752 static void parse_arguments(int argc
, char *argv
[])
757 while ((opt
= getopt_long(argc
, argv
,
758 short_options
, long_options
, &option_index
))
763 printf("rsync version %s protocol version %d\n",
764 VERSION
,PROTOCOL_VERSION
);
768 backup_suffix
= optarg
;
791 case OPT_NUMERIC_IDS
:
799 case OPT_EXCLUDE_FROM
:
800 add_exclude_file(optarg
,1);
840 #if SUPPORT_HARD_LINKS
841 preserve_hard_links
=1;
843 rprintf(FERROR
,"ERROR: hard links not supported on this platform\n");
915 block_size
= atoi(optarg
);
919 io_timeout
= atoi(optarg
);
935 /* rprintf(FERROR,"bad option -%c\n",opt); */
941 static int rsync_module(int fd
, int i
)
944 char *argv
[MAX_ARGS
];
953 rprintf(FERROR
,"rsyncd starting\n");
955 if (chroot(lp_path(i
))) {
956 io_printf(fd
,"ERROR: chroot failed\n");
961 io_printf(fd
,"ERROR: chdir failed\n");
965 if (setgid(lp_gid(i
))) {
966 io_printf(fd
,"ERROR: setgid failed\n");
970 if (setuid(lp_uid(i
))) {
971 io_printf(fd
,"ERROR: setuid failed\n");
975 io_printf(fd
,"RSYNCD: OK\n");
977 argv
[argc
++] = "rsyncd";
980 if (!read_line(fd
, line
, sizeof(line
)-1)) {
986 argv
[argc
] = strdup(line
);
992 if (argc
== MAX_ARGS
) {
997 parse_arguments(argc
, argv
);
999 /* don't allow the logs to be flooded too fast */
1000 if (verbose
> 1) verbose
= 1;
1003 argp
= argv
+ optind
;
1006 start_server(fd
, fd
, argc
, argp
);
1011 static void send_listing(int fd
)
1013 int n
= lp_numservices();
1018 io_printf(fd
, "%-15s\t%s\n", lp_name(i
), lp_comment(i
));
1021 /* this is called when a socket connection is established to a client
1022 and we want to start talking. The setup of the system is done from
1024 static int start_daemon(int fd
)
1029 set_socket_options(fd
,"SO_KEEPALIVE");
1031 io_printf(fd
,"RSYNCD %d\n", PROTOCOL_VERSION
);
1033 motd
= lp_motd_file();
1035 FILE *f
= fopen(motd
,"r");
1036 while (f
&& !feof(f
)) {
1037 int len
= fread(line
, 1, sizeof(line
)-1, f
);
1040 io_printf(fd
,"%s", line
);
1047 /* read a single line indicating the resource that is wanted */
1052 if (!read_line(fd
, line
, sizeof(line
)-1)) {
1056 if (!*line
|| strcmp(line
,"#list")==0) {
1062 /* it's some sort of command that I don't understand */
1063 io_printf(fd
,"ERROR: Unknown command '%s'\n", line
);
1067 i
= lp_number(line
);
1069 io_printf(fd
,"ERROR: Unknown module '%s'\n", line
);
1073 return rsync_module(fd
, i
);
1080 static int daemon_main(void)
1082 if (!lp_load(RSYNCD_CONF
)) {
1086 if (is_a_socket(STDIN_FILENO
)) {
1087 /* we are running via inetd */
1088 return start_daemon(STDIN_FILENO
);
1093 return start_accept_loop(port
, start_daemon
);
1096 int main(int argc
,char *argv
[])
1099 signal(SIGUSR1
, sigusr1_handler
);
1101 starttime
= time(NULL
);
1102 am_root
= (getuid() == 0);
1104 /* we set a 0 umask so that correct file permissions can be
1106 orig_umask
= (int)umask(0);
1108 parse_arguments(argc
, argv
);
1114 signal(SIGCHLD
,SIG_IGN
);
1115 signal(SIGINT
,SIGNAL_CAST sig_int
);
1116 signal(SIGPIPE
,SIGNAL_CAST sig_int
);
1117 signal(SIGHUP
,SIGNAL_CAST sig_int
);
1120 return daemon_main();
1124 verbose
= MAX(verbose
,1);
1126 #ifndef SUPPORT_LINKS
1127 if (!am_server
&& preserve_links
) {
1128 rprintf(FERROR
,"ERROR: symbolic links not supported\n");
1134 start_server(STDIN_FILENO
, STDOUT_FILENO
, argc
, argv
);
1142 return start_client(argc
, argv
);