1 /* -*- c-file-style: "linux" -*-
3 Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
4 Copyright (C) Paul Mackerras 1996
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 /****************************************************************************
31 wait for a process to exit, calling io_flush while waiting
32 ****************************************************************************/
33 void wait_process(pid_t pid, int *status)
35 while (waitpid(pid, status, WNOHANG) == 0) {
40 /* TODO: If the child exited on a signal, then log an
41 * appropriate error message. Perhaps we should also accept a
42 * message describing the purpose of the child. Also indicate
43 * this to the caller so that thhey know something went
45 *status = WEXITSTATUS(*status);
48 static void report(int f)
50 time_t t = time(NULL);
55 extern int remote_version;
59 log_exit(0, __FILE__, __LINE__);
60 if (f == -1 || !am_sender) return;
63 send_stats = verbose || (remote_version >= 20);
65 if (am_sender && send_stats) {
67 /* store total_written in a temporary
68 because write_longint changes it */
69 w = stats.total_written;
70 write_longint(f,stats.total_read);
72 write_longint(f,stats.total_size);
77 /* this is the client */
79 if (!am_sender && send_stats) {
81 stats.total_written = read_longint(f);
82 /* store total_read in a temporary, read_longint changes it */
84 stats.total_size = read_longint(f);
89 if (!am_sender && !send_stats) {
90 /* missing the bytes written by the generator */
91 rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
92 rprintf(FINFO, "Use --stats -v to show stats\n");
95 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
96 rprintf(FINFO,"Number of files transferred: %d\n",
97 stats.num_transferred_files);
98 rprintf(FINFO,"Total file size: %.0f bytes\n",
99 (double)stats.total_size);
100 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
101 (double)stats.total_transferred_size);
102 rprintf(FINFO,"Literal data: %.0f bytes\n",
103 (double)stats.literal_data);
104 rprintf(FINFO,"Matched data: %.0f bytes\n",
105 (double)stats.matched_data);
106 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
107 rprintf(FINFO,"Total bytes written: %.0f\n",
108 (double)stats.total_written);
109 rprintf(FINFO,"Total bytes read: %.0f\n\n",
110 (double)stats.total_read);
113 if (verbose || do_stats) {
114 rprintf(FINFO,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
115 (double)stats.total_written,
116 (double)stats.total_read,
117 (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
118 rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
119 (double)stats.total_size,
120 (1.0*stats.total_size)/(stats.total_written+stats.total_read));
128 /* Start the remote shell. cmd may be NULL to use the default. */
129 static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
135 extern int local_server;
136 extern char *rsync_path;
137 extern int blocking_io;
138 extern int read_batch;
140 if (!read_batch && !local_server) { /* dw -- added read_batch */
142 cmd = getenv(RSYNC_RSH_ENV);
149 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
154 /* remsh (on HPUX) takes the arguments the other way around */
155 args[argc++] = machine;
165 args[argc++] = machine;
168 args[argc++] = rsync_path;
170 server_options(args,&argc);
173 if (strcmp(cmd, RSYNC_RSH) == 0) blocking_io = 1;
184 rprintf(FINFO,"cmd=");
186 rprintf(FINFO,"%s ",args[i]);
192 create_flist_from_batch();
193 ret = local_child(argc, args, f_in, f_out);
195 ret = piped_child(args,f_in,f_out);
203 out_of_memory("do_cmd");
204 return 0; /* not reached */
210 static char *get_local_name(struct file_list *flist,char *name)
213 extern int orig_umask;
216 rprintf(FINFO,"get_local_name count=%d %s\n",
217 flist->count, NS(name));
222 if (do_stat(name,&st) == 0) {
223 if (S_ISDIR(st.st_mode)) {
224 if (!push_dir(name, 0)) {
225 rprintf(FERROR,"push_dir %s : %s (1)\n",
226 name,strerror(errno));
227 exit_cleanup(RERR_FILESELECT);
231 if (flist->count > 1) {
232 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
233 exit_cleanup(RERR_FILESELECT);
238 if (flist->count <= 1)
241 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
242 rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
243 exit_cleanup(RERR_FILEIO);
246 rprintf(FINFO,"created directory %s\n",name);
249 if (!push_dir(name, 0)) {
250 rprintf(FERROR,"push_dir %s : %s (2)\n",
251 name,strerror(errno));
252 exit_cleanup(RERR_FILESELECT);
261 static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
264 struct file_list *flist;
266 extern int relative_paths;
268 extern int remote_version;
271 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
273 if (!relative_paths && !push_dir(dir, 0)) {
274 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
275 exit_cleanup(RERR_FILESELECT);
280 if (strcmp(dir,".")) {
282 if (strcmp(dir,"/") == 0)
288 if (argc == 0 && recurse) {
294 flist = send_file_list(f_out,argc,argv);
295 if (!flist || flist->count == 0) {
299 send_files(flist,f_out,f_in);
302 if (remote_version >= 24) {
303 /* final goodbye message */
311 static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
317 extern int preserve_hard_links;
318 extern int delete_after;
320 extern int delete_mode;
321 extern int remote_version;
323 if (preserve_hard_links)
324 init_hard_links(flist);
327 /* I moved this here from recv_files() to prevent a race condition */
328 if (recurse && delete_mode && !local_name && flist->count>0) {
333 if (fd_pair(recv_pipe) < 0) {
334 rprintf(FERROR,"pipe failed in do_recv\n");
335 exit_cleanup(RERR_SOCKETIO);
338 if (fd_pair(error_pipe) < 0) {
339 rprintf(FERROR,"error pipe failed in do_recv\n");
340 exit_cleanup(RERR_SOCKETIO);
345 if ((pid=do_fork()) == 0) {
347 close(error_pipe[0]);
348 if (f_in != f_out) close(f_out);
350 /* we can't let two processes write to the socket at one time */
351 io_multiplexing_close();
353 /* set place to send errors */
354 set_error_fd(error_pipe[1]);
356 recv_files(f_in,flist,local_name,recv_pipe[1]);
360 write_int(recv_pipe[1],1);
363 /* finally we go to sleep until our parent kills us
364 with a USR2 signal. We sleep for a short time as on
365 some OSes a signal won't interrupt a sleep! */
371 close(error_pipe[1]);
372 if (f_in != f_out) close(f_in);
374 io_start_buffering(f_out);
376 io_set_error_fd(error_pipe[0]);
378 generate_files(f_out,flist,local_name,recv_pipe[0]);
380 read_int(recv_pipe[0]);
382 if (remote_version >= 24) {
383 /* send a final goodbye message */
384 write_int(f_out, -1);
389 wait_process(pid, &status);
394 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
397 struct file_list *flist;
398 char *local_name=NULL;
400 extern int delete_mode;
401 extern int delete_excluded;
402 extern int am_daemon;
403 extern int module_id;
404 extern int am_sender;
405 extern int read_batch; /* dw */
406 extern struct file_list *batch_flist; /* dw */
409 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
411 if (am_daemon && lp_read_only(module_id) && !am_sender) {
412 rprintf(FERROR,"ERROR: module is read only\n");
413 exit_cleanup(RERR_SYNTAX);
422 if (!am_daemon && !push_dir(dir, 0)) {
423 rprintf(FERROR,"push_dir %s : %s (4)\n",
424 dir,strerror(errno));
425 exit_cleanup(RERR_FILESELECT);
429 if (delete_mode && !delete_excluded)
430 recv_exclude_list(f_in);
432 if (read_batch) /* dw */
435 flist = recv_file_list(f_in);
437 rprintf(FERROR,"server_recv: recv_file_list error\n");
438 exit_cleanup(RERR_FILESELECT);
442 if (strcmp(dir,".")) {
443 argv[0] += strlen(dir);
444 if (argv[0][0] == '/') argv[0]++;
446 local_name = get_local_name(flist,argv[0]);
449 status = do_recv(f_in,f_out,flist,local_name);
450 exit_cleanup(status);
454 void start_server(int f_in, int f_out, int argc, char *argv[])
456 extern int cvs_exclude;
457 extern int am_sender;
458 extern int remote_version;
459 extern int read_batch; /* dw */
461 setup_protocol(f_out, f_in);
463 set_nonblocking(f_in);
464 set_nonblocking(f_out);
466 if (remote_version >= 23)
467 io_start_multiplex_out(f_out);
470 if (!read_batch) { /* dw */
471 recv_exclude_list(f_in);
475 do_server_sender(f_in, f_out, argc, argv);
477 do_server_recv(f_in, f_out, argc, argv);
484 * This is called once the connection has been negotiated. It is used
485 * for rsyncd, remote-shell, and local connections.
487 int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
489 struct file_list *flist;
490 int status = 0, status2 = 0;
491 char *local_name = NULL;
492 extern int am_sender;
493 extern int remote_version;
494 extern pid_t cleanup_child_pid;
495 extern int write_batch; /* dw */
496 extern int read_batch; /* dw */
497 extern struct file_list *batch_flist; /* dw */
499 cleanup_child_pid = pid;
501 flist = batch_flist; /* dw */
503 set_nonblocking(f_in);
504 set_nonblocking(f_out);
506 setup_protocol(f_out,f_in);
508 if (remote_version >= 23)
509 io_start_multiplex_in(f_in);
512 extern int cvs_exclude;
513 extern int delete_mode;
514 extern int delete_excluded;
517 if (delete_mode && !delete_excluded)
518 send_exclude_list(f_out);
519 if (!read_batch) /* dw -- don't write to pipe */
520 flist = send_file_list(f_out,argc,argv);
522 rprintf(FINFO,"file list sent\n");
524 send_files(flist,f_out,f_in);
525 if (remote_version >= 24) {
526 /* final goodbye message */
531 rprintf(FINFO,"client_run waiting on %d\n",pid);
533 wait_process(pid, &status);
536 exit_cleanup(status);
540 extern int list_only;
544 if (!write_batch) /* dw */
545 send_exclude_list(f_out);
547 flist = recv_file_list(f_in);
548 if (!flist || flist->count == 0) {
549 rprintf(FINFO, "client: nothing to do: "
550 "perhaps you need to specify some filenames or "
551 "the --recursive option?\n");
555 local_name = get_local_name(flist,argv[0]);
557 status2 = do_recv(f_in,f_out,flist,local_name);
561 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
563 wait_process(pid, &status);
566 return MAX(status, status2);
569 static char *find_colon(char *s)
576 /* now check to see if there is a / in the string before the : - if there is then
577 discard the colon on the assumption that the : is part of a filename */
579 if (p2 && p2 < p) return NULL;
586 * Start a client for either type of remote connection. Work out
587 * whether the arguments request a remote shell or rsyncd connection,
588 * and call the appropriate connection function, then run_client.
590 static int start_client(int argc, char *argv[])
593 char *shell_machine = NULL;
594 char *shell_path = NULL;
595 char *shell_user = NULL;
599 extern int local_server;
600 extern int am_sender;
601 extern char *shell_cmd;
602 extern int rsync_port;
603 extern int whole_file;
604 char *argv0 = strdup(argv[0]);
605 extern int read_batch;
607 if (strncasecmp(URL_PREFIX, argv0, strlen(URL_PREFIX)) == 0) {
610 host = argv0 + strlen(URL_PREFIX);
611 p = strchr(host,'/');
618 p = strchr(host,':');
620 rsync_port = atoi(p+1);
623 return start_socket_client(host, path, argc-1, argv+1);
626 if (!read_batch) { /* dw */
627 p = find_colon(argv[0]);
632 return start_socket_client(argv0, p+2, argc-1, argv+1);
637 exit_cleanup(RERR_SYNTAX);
642 shell_machine = argv0;
649 p = find_colon(argv[argc-1]);
652 /* disable "rsync algorithm" when both sides local */
654 } else if (p[1] == ':') {
656 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
661 exit_cleanup(RERR_SYNTAX);
665 shell_machine = NULL;
666 shell_path = argv[argc-1];
669 shell_machine = argv[argc-1];
675 am_sender = 1; /* dw */
676 local_server = 1; /* dw */
677 shell_path = argv[argc-1]; /* dw */
681 p = strchr(shell_machine,'@');
684 shell_user = shell_machine;
690 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
691 shell_cmd?shell_cmd:"",
692 shell_machine?shell_machine:"",
693 shell_user?shell_user:"",
694 shell_path?shell_path:"");
697 if (!am_sender && argc > 1) {
699 exit_cleanup(RERR_SYNTAX);
702 if (argc == 0 && !am_sender) {
703 extern int list_only;
707 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
709 ret = client_run(f_in, f_out, pid, argc, argv);
718 static RETSIGTYPE sigusr1_handler(int val) {
719 exit_cleanup(RERR_SIGNAL);
722 static RETSIGTYPE sigusr2_handler(int val) {
723 extern int log_got_error;
724 if (log_got_error) _exit(RERR_PARTIAL);
728 static RETSIGTYPE sigchld_handler(int val) {
730 while (waitpid(-1, NULL, WNOHANG) > 0) ;
734 int main(int argc,char *argv[])
737 extern int orig_umask;
739 extern int am_daemon;
740 extern int am_server;
742 extern int read_batch; /* dw */
743 extern int write_batch; /* dw */
744 extern char *batch_ext; /* dw */
745 int orig_argc; /* dw */
747 orig_argc = argc; /* dw */
749 signal(SIGUSR1, sigusr1_handler);
750 signal(SIGUSR2, sigusr2_handler);
751 signal(SIGCHLD, sigchld_handler);
753 starttime = time(NULL);
754 am_root = (getuid() == 0);
756 memset(&stats, 0, sizeof(stats));
760 exit_cleanup(RERR_SYNTAX);
763 /* we set a 0 umask so that correct file permissions can be
765 orig_umask = (int)umask(0);
767 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
768 /* FIXME: We ought to call the same error-handling
769 * code here, rather than relying on getopt. */
771 exit_cleanup(RERR_SYNTAX);
774 signal(SIGINT,SIGNAL_CAST sig_int);
775 signal(SIGPIPE,SIGNAL_CAST sig_int);
776 signal(SIGHUP,SIGNAL_CAST sig_int);
777 signal(SIGTERM,SIGNAL_CAST sig_int);
779 /* Initialize push_dir here because on some old systems getcwd
780 (implemented by forking "pwd" and reading its output) doesn't
781 work when there are other child processes. Also, on all systems
782 that implement getcwd that way "pwd" can't be found after chroot. */
785 if (write_batch) { /* dw */
786 create_batch_file_ext();
787 write_batch_argvs_file(orig_argc, argc, argv);
790 if (read_batch) { /* dw */
791 set_batch_file_ext(batch_ext);
795 return daemon_main();
800 exit_cleanup(RERR_SYNTAX);
804 verbose = MAX(verbose,1);
806 #ifndef SUPPORT_LINKS
807 if (!am_server && preserve_links) {
808 rprintf(FERROR,"ERROR: symbolic links not supported\n");
809 exit_cleanup(RERR_UNSUPPORTED);
814 set_nonblocking(STDIN_FILENO);
815 set_nonblocking(STDOUT_FILENO);
816 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
819 ret = start_client(argc, argv);