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 io_close_input(f_in);
360 if (f_in != f_out) close(f_in);
362 io_start_buffering(f_out);
364 io_set_error_fd(error_pipe[0]);
366 generate_files(f_out,flist,local_name,recv_pipe[0]);
368 read_int(recv_pipe[0]);
370 if (remote_version >= 24) {
371 /* send a final goodbye message */
372 write_int(f_out, -1);
377 wait_process(pid, &status);
382 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
385 struct file_list *flist;
386 char *local_name=NULL;
388 extern int delete_mode;
389 extern int delete_excluded;
390 extern int am_daemon;
391 extern int module_id;
392 extern int am_sender;
395 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
397 if (am_daemon && lp_read_only(module_id) && !am_sender) {
398 rprintf(FERROR,"ERROR: module is read only\n");
399 exit_cleanup(RERR_SYNTAX);
408 if (!am_daemon && !push_dir(dir, 0)) {
409 rprintf(FERROR,"push_dir %s : %s (4)\n",
410 dir,strerror(errno));
411 exit_cleanup(RERR_FILESELECT);
415 if (delete_mode && !delete_excluded)
416 recv_exclude_list(f_in);
418 flist = recv_file_list(f_in);
420 rprintf(FERROR,"server_recv: recv_file_list error\n");
421 exit_cleanup(RERR_FILESELECT);
425 if (strcmp(dir,".")) {
426 argv[0] += strlen(dir);
427 if (argv[0][0] == '/') argv[0]++;
429 local_name = get_local_name(flist,argv[0]);
432 status = do_recv(f_in,f_out,flist,local_name);
433 exit_cleanup(status);
437 void start_server(int f_in, int f_out, int argc, char *argv[])
439 extern int cvs_exclude;
440 extern int am_sender;
441 extern int remote_version;
443 setup_protocol(f_out, f_in);
445 set_nonblocking(f_in);
446 set_nonblocking(f_out);
448 if (remote_version >= 23)
449 io_start_multiplex_out(f_out);
452 recv_exclude_list(f_in);
455 do_server_sender(f_in, f_out, argc, argv);
457 do_server_recv(f_in, f_out, argc, argv);
462 int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
464 struct file_list *flist;
465 int status = 0, status2 = 0;
466 char *local_name = NULL;
467 extern int am_sender;
468 extern int list_only;
469 extern int remote_version;
471 set_nonblocking(f_in);
472 set_nonblocking(f_out);
474 setup_protocol(f_out,f_in);
476 if (remote_version >= 23)
477 io_start_multiplex_in(f_in);
480 extern int cvs_exclude;
481 extern int delete_mode;
482 extern int delete_excluded;
485 if (delete_mode && !delete_excluded)
486 send_exclude_list(f_out);
487 flist = send_file_list(f_out,argc,argv);
489 rprintf(FINFO,"file list sent\n");
491 send_files(flist,f_out,f_in);
494 rprintf(FINFO,"client_run waiting on %d\n",pid);
496 wait_process(pid, &status);
498 if (remote_version >= 24) {
499 /* final goodbye message */
503 exit_cleanup(status);
506 if (argc == 0) list_only = 1;
508 send_exclude_list(f_out);
510 flist = recv_file_list(f_in);
511 if (!flist || flist->count == 0) {
512 rprintf(FINFO,"client: nothing to do\n");
516 local_name = get_local_name(flist,argv[0]);
518 status2 = do_recv(f_in,f_out,flist,local_name);
522 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
524 wait_process(pid, &status);
527 return status | status2;
530 static char *find_colon(char *s)
537 /* now check to see if there is a / in the string before the : - if there is then
538 discard the colon on the assumption that the : is part of a filename */
540 if (p2 && p2 < p) return NULL;
545 static int start_client(int argc, char *argv[])
548 char *shell_machine = NULL;
549 char *shell_path = NULL;
550 char *shell_user = NULL;
553 extern int local_server;
554 extern int am_sender;
555 extern char *shell_cmd;
556 extern int rsync_port;
558 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
561 host = argv[0] + strlen(URL_PREFIX);
562 p = strchr(host,'/');
569 p = strchr(host,':');
571 rsync_port = atoi(p+1);
574 return start_socket_client(host, path, argc-1, argv+1);
577 p = find_colon(argv[0]);
582 return start_socket_client(argv[0], p+2, argc-1, argv+1);
587 exit_cleanup(RERR_SYNTAX);
592 shell_machine = argv[0];
599 p = find_colon(argv[argc-1]);
602 } else if (p[1] == ':') {
604 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
609 exit_cleanup(RERR_SYNTAX);
613 shell_machine = NULL;
614 shell_path = argv[argc-1];
617 shell_machine = argv[argc-1];
624 p = strchr(shell_machine,'@');
627 shell_user = shell_machine;
633 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
634 shell_cmd?shell_cmd:"",
635 shell_machine?shell_machine:"",
636 shell_user?shell_user:"",
637 shell_path?shell_path:"");
640 if (!am_sender && argc > 1) {
642 exit_cleanup(RERR_SYNTAX);
645 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
647 ret = client_run(f_in, f_out, pid, argc, argv);
656 static RETSIGTYPE sigusr1_handler(int val) {
657 exit_cleanup(RERR_SIGNAL);
660 static RETSIGTYPE sigusr2_handler(int val) {
664 int main(int argc,char *argv[])
667 extern int orig_umask;
669 extern int am_daemon;
670 extern int am_server;
672 signal(SIGUSR1, sigusr1_handler);
673 signal(SIGUSR2, sigusr2_handler);
675 starttime = time(NULL);
676 am_root = (getuid() == 0);
678 memset(&stats, 0, sizeof(stats));
682 exit_cleanup(RERR_SYNTAX);
685 /* we set a 0 umask so that correct file permissions can be
687 orig_umask = (int)umask(0);
689 if (!parse_arguments(argc, argv, 1)) {
690 exit_cleanup(RERR_SYNTAX);
697 signal(SIGCHLD,SIG_IGN);
698 signal(SIGINT,SIGNAL_CAST sig_int);
699 signal(SIGPIPE,SIGNAL_CAST sig_int);
700 signal(SIGHUP,SIGNAL_CAST sig_int);
701 signal(SIGTERM,SIGNAL_CAST sig_int);
703 /* Initialize push_dir here because on some old systems getcwd
704 (implemented by forking "pwd" and reading its output) doesn't
705 work when there are other child processes. Also, on all systems
706 that implement getcwd that way "pwd" can't be found after chroot. */
710 return daemon_main();
715 exit_cleanup(RERR_SYNTAX);
719 verbose = MAX(verbose,1);
721 #ifndef SUPPORT_LINKS
722 if (!am_server && preserve_links) {
723 rprintf(FERROR,"ERROR: symbolic links not supported\n");
724 exit_cleanup(RERR_UNSUPPORTED);
729 set_nonblocking(STDIN_FILENO);
730 set_nonblocking(STDOUT_FILENO);
731 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
734 return start_client(argc, argv);