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 sleep for a short time as on
353 some OSes a signal won't interrupt a sleep! */
354 while (1) msleep(20);
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 remote_version;
469 set_nonblocking(f_in);
470 set_nonblocking(f_out);
472 setup_protocol(f_out,f_in);
474 if (remote_version >= 23)
475 io_start_multiplex_in(f_in);
478 extern int cvs_exclude;
479 extern int delete_mode;
480 extern int delete_excluded;
483 if (delete_mode && !delete_excluded)
484 send_exclude_list(f_out);
485 flist = send_file_list(f_out,argc,argv);
487 rprintf(FINFO,"file list sent\n");
489 send_files(flist,f_out,f_in);
492 rprintf(FINFO,"client_run waiting on %d\n",pid);
494 wait_process(pid, &status);
496 if (remote_version >= 24) {
497 /* final goodbye message */
501 exit_cleanup(status);
505 extern int list_only;
509 send_exclude_list(f_out);
511 flist = recv_file_list(f_in);
512 if (!flist || flist->count == 0) {
513 rprintf(FINFO, "client: nothing to do: "
514 "perhaps you need to specify some filenames or "
515 "the --recursive option?\n");
519 local_name = get_local_name(flist,argv[0]);
521 status2 = do_recv(f_in,f_out,flist,local_name);
525 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
527 wait_process(pid, &status);
530 return status | status2;
533 static char *find_colon(char *s)
540 /* now check to see if there is a / in the string before the : - if there is then
541 discard the colon on the assumption that the : is part of a filename */
543 if (p2 && p2 < p) return NULL;
548 static int start_client(int argc, char *argv[])
551 char *shell_machine = NULL;
552 char *shell_path = NULL;
553 char *shell_user = NULL;
556 extern int local_server;
557 extern int am_sender;
558 extern char *shell_cmd;
559 extern int rsync_port;
561 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
564 host = argv[0] + strlen(URL_PREFIX);
565 p = strchr(host,'/');
572 p = strchr(host,':');
574 rsync_port = atoi(p+1);
577 return start_socket_client(host, path, argc-1, argv+1);
580 p = find_colon(argv[0]);
585 return start_socket_client(argv[0], p+2, argc-1, argv+1);
590 exit_cleanup(RERR_SYNTAX);
595 shell_machine = argv[0];
602 p = find_colon(argv[argc-1]);
605 } else if (p[1] == ':') {
607 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
612 exit_cleanup(RERR_SYNTAX);
616 shell_machine = NULL;
617 shell_path = argv[argc-1];
620 shell_machine = argv[argc-1];
627 p = strchr(shell_machine,'@');
630 shell_user = shell_machine;
636 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
637 shell_cmd?shell_cmd:"",
638 shell_machine?shell_machine:"",
639 shell_user?shell_user:"",
640 shell_path?shell_path:"");
643 if (!am_sender && argc > 1) {
645 exit_cleanup(RERR_SYNTAX);
648 if (argc == 0 && !am_sender) {
649 extern int list_only;
653 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
655 ret = client_run(f_in, f_out, pid, argc, argv);
664 static RETSIGTYPE sigusr1_handler(int val) {
665 exit_cleanup(RERR_SIGNAL);
668 static RETSIGTYPE sigusr2_handler(int val) {
672 int main(int argc,char *argv[])
675 extern int orig_umask;
677 extern int am_daemon;
678 extern int am_server;
680 signal(SIGUSR1, sigusr1_handler);
681 signal(SIGUSR2, sigusr2_handler);
683 starttime = time(NULL);
684 am_root = (getuid() == 0);
686 memset(&stats, 0, sizeof(stats));
690 exit_cleanup(RERR_SYNTAX);
693 /* we set a 0 umask so that correct file permissions can be
695 orig_umask = (int)umask(0);
697 if (!parse_arguments(argc, argv, 1)) {
698 exit_cleanup(RERR_SYNTAX);
705 signal(SIGCHLD,SIG_IGN);
706 signal(SIGINT,SIGNAL_CAST sig_int);
707 signal(SIGPIPE,SIGNAL_CAST sig_int);
708 signal(SIGHUP,SIGNAL_CAST sig_int);
709 signal(SIGTERM,SIGNAL_CAST sig_int);
711 /* Initialize push_dir here because on some old systems getcwd
712 (implemented by forking "pwd" and reading its output) doesn't
713 work when there are other child processes. Also, on all systems
714 that implement getcwd that way "pwd" can't be found after chroot. */
718 return daemon_main();
723 exit_cleanup(RERR_SYNTAX);
727 verbose = MAX(verbose,1);
729 #ifndef SUPPORT_LINKS
730 if (!am_server && preserve_links) {
731 rprintf(FERROR,"ERROR: symbolic links not supported\n");
732 exit_cleanup(RERR_UNSUPPORTED);
737 set_nonblocking(STDIN_FILENO);
738 set_nonblocking(STDOUT_FILENO);
739 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
742 return start_client(argc, argv);