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.
29 /****************************************************************************
30 wait for a process to exit, calling io_flush while waiting
31 ****************************************************************************/
32 void wait_process(pid_t pid, int *status)
34 while (waitpid(pid, status, WNOHANG) == 0) {
38 *status = WEXITSTATUS(*status);
41 static void report(int f)
43 time_t t = time(NULL);
48 extern int remote_version;
52 log_exit(0, __FILE__, __LINE__);
53 if (f == -1 || !am_sender) return;
56 send_stats = verbose || (remote_version >= 20);
58 if (am_sender && send_stats) {
60 /* store total_written in a temporary
61 because write_longint changes it */
62 w = stats.total_written;
63 write_longint(f,stats.total_read);
65 write_longint(f,stats.total_size);
70 /* this is the client */
72 if (!am_sender && send_stats) {
74 stats.total_written = read_longint(f);
75 /* store total_read in a temporary, read_longint changes it */
77 stats.total_size = read_longint(f);
82 if (!am_sender && !send_stats) {
83 /* missing the bytes written by the generator */
84 rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
85 rprintf(FINFO, "Use --stats -v to show stats\n");
88 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
89 rprintf(FINFO,"Number of files transferred: %d\n",
90 stats.num_transferred_files);
91 rprintf(FINFO,"Total file size: %.0f bytes\n",
92 (double)stats.total_size);
93 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
94 (double)stats.total_transferred_size);
95 rprintf(FINFO,"Literal data: %.0f bytes\n",
96 (double)stats.literal_data);
97 rprintf(FINFO,"Matched data: %.0f bytes\n",
98 (double)stats.matched_data);
99 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
100 rprintf(FINFO,"Total bytes written: %.0f\n",
101 (double)stats.total_written);
102 rprintf(FINFO,"Total bytes read: %.0f\n\n",
103 (double)stats.total_read);
106 if (verbose || do_stats) {
107 rprintf(FINFO,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
108 (double)stats.total_written,
109 (double)stats.total_read,
110 (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
111 rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
112 (double)stats.total_size,
113 (1.0*stats.total_size)/(stats.total_written+stats.total_read));
121 static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
126 extern int local_server;
127 extern char *rsync_path;
128 extern int blocking_io;
132 cmd = getenv(RSYNC_RSH_ENV);
139 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
144 /* remsh (on HPUX) takes the arguments the other way around */
145 args[argc++] = machine;
155 args[argc++] = machine;
158 args[argc++] = rsync_path;
160 server_options(args,&argc);
163 if (strcmp(cmd, RSYNC_RSH) == 0) blocking_io = 1;
174 rprintf(FINFO,"cmd=");
176 rprintf(FINFO,"%s ",args[i]);
181 ret = local_child(argc, args, f_in, f_out);
183 ret = piped_child(args,f_in,f_out);
191 out_of_memory("do_cmd");
192 return 0; /* not reached */
198 static char *get_local_name(struct file_list *flist,char *name)
201 extern int orig_umask;
204 rprintf(FINFO,"get_local_name count=%d %s\n",
205 flist->count, NS(name));
210 if (do_stat(name,&st) == 0) {
211 if (S_ISDIR(st.st_mode)) {
212 if (!push_dir(name, 0)) {
213 rprintf(FERROR,"push_dir %s : %s (1)\n",
214 name,strerror(errno));
215 exit_cleanup(RERR_FILESELECT);
219 if (flist->count > 1) {
220 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
221 exit_cleanup(RERR_FILESELECT);
226 if (flist->count <= 1)
229 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
230 rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
231 exit_cleanup(RERR_FILEIO);
234 rprintf(FINFO,"created directory %s\n",name);
237 if (!push_dir(name, 0)) {
238 rprintf(FERROR,"push_dir %s : %s (2)\n",
239 name,strerror(errno));
240 exit_cleanup(RERR_FILESELECT);
249 static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
252 struct file_list *flist;
254 extern int relative_paths;
256 extern int remote_version;
259 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
261 if (!relative_paths && !push_dir(dir, 0)) {
262 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
263 exit_cleanup(RERR_FILESELECT);
268 if (strcmp(dir,".")) {
270 if (strcmp(dir,"/") == 0)
276 if (argc == 0 && recurse) {
282 flist = send_file_list(f_out,argc,argv);
283 if (!flist || flist->count == 0) {
287 send_files(flist,f_out,f_in);
290 if (remote_version >= 24) {
291 /* final goodbye message */
299 static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
305 extern int preserve_hard_links;
306 extern int delete_after;
308 extern int delete_mode;
309 extern int remote_version;
311 if (preserve_hard_links)
312 init_hard_links(flist);
315 /* I moved this here from recv_files() to prevent a race condition */
316 if (recurse && delete_mode && !local_name && flist->count>0) {
321 if (fd_pair(recv_pipe) < 0) {
322 rprintf(FERROR,"pipe failed in do_recv\n");
323 exit_cleanup(RERR_SOCKETIO);
326 if (fd_pair(error_pipe) < 0) {
327 rprintf(FERROR,"error pipe failed in do_recv\n");
328 exit_cleanup(RERR_SOCKETIO);
333 if ((pid=do_fork()) == 0) {
335 close(error_pipe[0]);
336 if (f_in != f_out) close(f_out);
338 /* we can't let two processes write to the socket at one time */
339 io_multiplexing_close();
341 /* set place to send errors */
342 set_error_fd(error_pipe[1]);
344 recv_files(f_in,flist,local_name,recv_pipe[1]);
348 write_int(recv_pipe[1],1);
351 /* finally we go to sleep until our parent kills us
352 with a USR2 signal. We sleepp for a short time as on
353 some OSes a signal won't interrupt a sleep! */
358 close(error_pipe[1]);
359 if (f_in != f_out) close(f_in);
361 io_start_buffering(f_out);
363 io_set_error_fd(error_pipe[0]);
365 generate_files(f_out,flist,local_name,recv_pipe[0]);
367 read_int(recv_pipe[0]);
369 if (remote_version >= 24) {
370 /* send a final goodbye message */
371 write_int(f_out, -1);
376 wait_process(pid, &status);
381 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
384 struct file_list *flist;
385 char *local_name=NULL;
387 extern int delete_mode;
388 extern int delete_excluded;
389 extern int am_daemon;
390 extern int module_id;
391 extern int am_sender;
394 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
396 if (am_daemon && lp_read_only(module_id) && !am_sender) {
397 rprintf(FERROR,"ERROR: module is read only\n");
398 exit_cleanup(RERR_SYNTAX);
407 if (!am_daemon && !push_dir(dir, 0)) {
408 rprintf(FERROR,"push_dir %s : %s (4)\n",
409 dir,strerror(errno));
410 exit_cleanup(RERR_FILESELECT);
414 if (delete_mode && !delete_excluded)
415 recv_exclude_list(f_in);
417 flist = recv_file_list(f_in);
419 rprintf(FERROR,"server_recv: recv_file_list error\n");
420 exit_cleanup(RERR_FILESELECT);
424 if (strcmp(dir,".")) {
425 argv[0] += strlen(dir);
426 if (argv[0][0] == '/') argv[0]++;
428 local_name = get_local_name(flist,argv[0]);
431 status = do_recv(f_in,f_out,flist,local_name);
432 exit_cleanup(status);
436 void start_server(int f_in, int f_out, int argc, char *argv[])
438 extern int cvs_exclude;
439 extern int am_sender;
440 extern int remote_version;
442 setup_protocol(f_out, f_in);
444 set_nonblocking(f_in);
445 set_nonblocking(f_out);
447 if (remote_version >= 23)
448 io_start_multiplex_out(f_out);
451 recv_exclude_list(f_in);
454 do_server_sender(f_in, f_out, argc, argv);
456 do_server_recv(f_in, f_out, argc, argv);
461 int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
463 struct file_list *flist;
464 int status = 0, status2 = 0;
465 char *local_name = NULL;
466 extern int am_sender;
467 extern int list_only;
468 extern int remote_version;
470 set_nonblocking(f_in);
471 set_nonblocking(f_out);
473 setup_protocol(f_out,f_in);
475 if (remote_version >= 23)
476 io_start_multiplex_in(f_in);
479 extern int cvs_exclude;
480 extern int delete_mode;
481 extern int delete_excluded;
484 if (delete_mode && !delete_excluded)
485 send_exclude_list(f_out);
486 flist = send_file_list(f_out,argc,argv);
488 rprintf(FINFO,"file list sent\n");
490 send_files(flist,f_out,f_in);
493 rprintf(FINFO,"client_run waiting on %d\n",pid);
495 wait_process(pid, &status);
497 if (remote_version >= 24) {
498 /* final goodbye message */
502 exit_cleanup(status);
505 if (argc == 0) list_only = 1;
507 send_exclude_list(f_out);
509 flist = recv_file_list(f_in);
510 if (!flist || flist->count == 0) {
511 rprintf(FINFO,"client: nothing to do\n");
515 local_name = get_local_name(flist,argv[0]);
517 status2 = do_recv(f_in,f_out,flist,local_name);
521 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
523 wait_process(pid, &status);
526 return status | status2;
529 static char *find_colon(char *s)
536 /* now check to see if there is a / in the string before the : - if there is then
537 discard the colon on the assumption that the : is part of a filename */
539 if (p2 && p2 < p) return NULL;
544 static int start_client(int argc, char *argv[])
547 char *shell_machine = NULL;
548 char *shell_path = NULL;
549 char *shell_user = NULL;
552 extern int local_server;
553 extern int am_sender;
554 extern char *shell_cmd;
555 extern int rsync_port;
557 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
560 host = argv[0] + strlen(URL_PREFIX);
561 p = strchr(host,'/');
568 p = strchr(host,':');
570 rsync_port = atoi(p+1);
573 return start_socket_client(host, path, argc-1, argv+1);
576 p = find_colon(argv[0]);
581 return start_socket_client(argv[0], p+2, argc-1, argv+1);
586 exit_cleanup(RERR_SYNTAX);
591 shell_machine = argv[0];
598 p = find_colon(argv[argc-1]);
601 } else if (p[1] == ':') {
603 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
608 exit_cleanup(RERR_SYNTAX);
612 shell_machine = NULL;
613 shell_path = argv[argc-1];
616 shell_machine = argv[argc-1];
623 p = strchr(shell_machine,'@');
626 shell_user = shell_machine;
632 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
633 shell_cmd?shell_cmd:"",
634 shell_machine?shell_machine:"",
635 shell_user?shell_user:"",
636 shell_path?shell_path:"");
639 if (!am_sender && argc > 1) {
641 exit_cleanup(RERR_SYNTAX);
644 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
646 ret = client_run(f_in, f_out, pid, argc, argv);
655 static RETSIGTYPE sigusr1_handler(int val) {
656 exit_cleanup(RERR_SIGNAL);
659 static RETSIGTYPE sigusr2_handler(int val) {
663 int main(int argc,char *argv[])
666 extern int orig_umask;
668 extern int am_daemon;
669 extern int am_server;
671 signal(SIGUSR1, sigusr1_handler);
672 signal(SIGUSR2, sigusr2_handler);
674 starttime = time(NULL);
675 am_root = (getuid() == 0);
677 memset(&stats, 0, sizeof(stats));
681 exit_cleanup(RERR_SYNTAX);
684 /* we set a 0 umask so that correct file permissions can be
686 orig_umask = (int)umask(0);
688 if (!parse_arguments(argc, argv, 1)) {
689 exit_cleanup(RERR_SYNTAX);
696 signal(SIGCHLD,SIG_IGN);
697 signal(SIGINT,SIGNAL_CAST sig_int);
698 signal(SIGPIPE,SIGNAL_CAST sig_int);
699 signal(SIGHUP,SIGNAL_CAST sig_int);
700 signal(SIGTERM,SIGNAL_CAST sig_int);
702 /* Initialize push_dir here because on some old systems getcwd
703 (implemented by forking "pwd" and reading its output) doesn't
704 work when there are other child processes. Also, on all systems
705 that implement getcwd that way "pwd" can't be found after chroot. */
709 return daemon_main();
714 exit_cleanup(RERR_SYNTAX);
718 verbose = MAX(verbose,1);
720 #ifndef SUPPORT_LINKS
721 if (!am_server && preserve_links) {
722 rprintf(FERROR,"ERROR: symbolic links not supported\n");
723 exit_cleanup(RERR_UNSUPPORTED);
728 set_nonblocking(STDIN_FILENO);
729 set_nonblocking(STDOUT_FILENO);
730 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
733 return start_client(argc, argv);