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;
322 extern int write_batch; /* dw */
323 extern int read_batch; /* dw */
324 extern struct file_list *batch_flist; /* dw */
327 flist = batch_flist; /* dw */
329 if (preserve_hard_links)
330 init_hard_links(flist);
333 /* I moved this here from recv_files() to prevent a race condition */
334 if (recurse && delete_mode && !local_name && flist->count>0) {
339 if (fd_pair(recv_pipe) < 0) {
340 rprintf(FERROR,"pipe failed in do_recv\n");
341 exit_cleanup(RERR_SOCKETIO);
344 if (fd_pair(error_pipe) < 0) {
345 rprintf(FERROR,"error pipe failed in do_recv\n");
346 exit_cleanup(RERR_SOCKETIO);
351 if ((pid=do_fork()) == 0) {
353 close(error_pipe[0]);
354 if (f_in != f_out) close(f_out);
356 /* we can't let two processes write to the socket at one time */
357 io_multiplexing_close();
359 /* set place to send errors */
360 set_error_fd(error_pipe[1]);
362 recv_files(f_in,flist,local_name,recv_pipe[1]);
366 write_int(recv_pipe[1],1);
369 /* finally we go to sleep until our parent kills us
370 with a USR2 signal. We sleep for a short time as on
371 some OSes a signal won't interrupt a sleep! */
372 while (1) msleep(20);
376 close(error_pipe[1]);
377 if (f_in != f_out) close(f_in);
379 io_start_buffering(f_out);
381 io_set_error_fd(error_pipe[0]);
383 generate_files(f_out,flist,local_name,recv_pipe[0]);
385 read_int(recv_pipe[0]);
387 if (remote_version >= 24) {
388 /* send a final goodbye message */
389 write_int(f_out, -1);
394 wait_process(pid, &status);
399 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
402 struct file_list *flist;
403 char *local_name=NULL;
405 extern int delete_mode;
406 extern int delete_excluded;
407 extern int am_daemon;
408 extern int module_id;
409 extern int am_sender;
410 extern int read_batch; /* dw */
411 extern int write_batch; /* dw */
412 extern struct file_list *batch_flist; /* dw */
415 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
417 if (am_daemon && lp_read_only(module_id) && !am_sender) {
418 rprintf(FERROR,"ERROR: module is read only\n");
419 exit_cleanup(RERR_SYNTAX);
428 if (!am_daemon && !push_dir(dir, 0)) {
429 rprintf(FERROR,"push_dir %s : %s (4)\n",
430 dir,strerror(errno));
431 exit_cleanup(RERR_FILESELECT);
435 if (delete_mode && !delete_excluded)
436 recv_exclude_list(f_in);
438 if (read_batch) /* dw */
441 flist = recv_file_list(f_in);
443 rprintf(FERROR,"server_recv: recv_file_list error\n");
444 exit_cleanup(RERR_FILESELECT);
448 if (strcmp(dir,".")) {
449 argv[0] += strlen(dir);
450 if (argv[0][0] == '/') argv[0]++;
452 local_name = get_local_name(flist,argv[0]);
455 status = do_recv(f_in,f_out,flist,local_name);
456 exit_cleanup(status);
460 void start_server(int f_in, int f_out, int argc, char *argv[])
462 extern int cvs_exclude;
463 extern int am_sender;
464 extern int remote_version;
465 extern int read_batch; /* dw */
467 setup_protocol(f_out, f_in);
469 set_nonblocking(f_in);
470 set_nonblocking(f_out);
472 if (remote_version >= 23)
473 io_start_multiplex_out(f_out);
476 if (!read_batch) { /* dw */
477 recv_exclude_list(f_in);
481 do_server_sender(f_in, f_out, argc, argv);
483 do_server_recv(f_in, f_out, argc, argv);
490 * This is called once the connection has been negotiated. It is used
491 * for rsyncd, remote-shell, and local connections.
493 int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
495 struct file_list *flist;
496 int status = 0, status2 = 0;
497 char *local_name = NULL;
498 extern int am_sender;
499 extern int remote_version;
500 extern pid_t cleanup_child_pid;
501 extern int write_batch; /* dw */
502 extern int read_batch; /* dw */
503 extern struct file_list *batch_flist; /* dw */
506 flist = batch_flist; /* dw */
508 cleanup_child_pid = pid;
510 set_nonblocking(f_in);
511 set_nonblocking(f_out);
513 setup_protocol(f_out,f_in);
515 if (remote_version >= 23)
516 io_start_multiplex_in(f_in);
519 extern int cvs_exclude;
520 extern int delete_mode;
521 extern int delete_excluded;
524 if (delete_mode && !delete_excluded)
525 send_exclude_list(f_out);
526 if (!read_batch) /* dw -- don't write to pipe */
527 flist = send_file_list(f_out,argc,argv);
529 rprintf(FINFO,"file list sent\n");
531 send_files(flist,f_out,f_in);
532 if (remote_version >= 24) {
533 /* final goodbye message */
538 rprintf(FINFO,"client_run waiting on %d\n",pid);
540 wait_process(pid, &status);
543 exit_cleanup(status);
547 extern int list_only;
551 if (!write_batch) /* dw */
552 send_exclude_list(f_out);
554 flist = recv_file_list(f_in);
555 if (!flist || flist->count == 0) {
556 rprintf(FINFO, "client: nothing to do: "
557 "perhaps you need to specify some filenames or "
558 "the --recursive option?\n");
562 local_name = get_local_name(flist,argv[0]);
564 status2 = do_recv(f_in,f_out,flist,local_name);
568 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
570 wait_process(pid, &status);
573 return MAX(status, status2);
576 static char *find_colon(char *s)
583 /* now check to see if there is a / in the string before the : - if there is then
584 discard the colon on the assumption that the : is part of a filename */
586 if (p2 && p2 < p) return NULL;
593 * Start a client for either type of remote connection. Work out
594 * whether the arguments request a remote shell or rsyncd connection,
595 * and call the appropriate connection function, then run_client.
597 static int start_client(int argc, char *argv[])
600 char *shell_machine = NULL;
601 char *shell_path = NULL;
602 char *shell_user = NULL;
606 extern int local_server;
607 extern int am_sender;
608 extern char *shell_cmd;
609 extern int rsync_port;
610 extern int whole_file;
611 char *argv0 = strdup(argv[0]);
612 extern int read_batch;
614 if (strncasecmp(URL_PREFIX, argv0, strlen(URL_PREFIX)) == 0) {
617 host = argv0 + strlen(URL_PREFIX);
618 p = strchr(host,'/');
625 p = strchr(host,':');
627 rsync_port = atoi(p+1);
630 return start_socket_client(host, path, argc-1, argv+1);
634 p = find_colon(argv0);
639 return start_socket_client(argv0, p+2, argc-1, argv+1);
644 exit_cleanup(RERR_SYNTAX);
649 shell_machine = argv0;
656 p = find_colon(argv[argc-1]);
659 /* disable "rsync algorithm" when both sides local */
661 } else if (p[1] == ':') {
663 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
668 exit_cleanup(RERR_SYNTAX);
672 shell_machine = NULL;
673 shell_path = argv[argc-1];
676 shell_machine = argv[argc-1];
682 am_sender = 1; /* dw */
683 local_server = 1; /* dw */
684 shell_path = argv[argc-1]; /* dw */
688 p = strchr(shell_machine,'@');
691 shell_user = shell_machine;
697 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
698 shell_cmd?shell_cmd:"",
699 shell_machine?shell_machine:"",
700 shell_user?shell_user:"",
701 shell_path?shell_path:"");
704 if (!am_sender && argc > 1) {
706 exit_cleanup(RERR_SYNTAX);
709 if (argc == 0 && !am_sender) {
710 extern int list_only;
714 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
716 ret = client_run(f_in, f_out, pid, argc, argv);
725 static RETSIGTYPE sigusr1_handler(int val) {
726 exit_cleanup(RERR_SIGNAL);
729 static RETSIGTYPE sigusr2_handler(int val) {
730 extern int log_got_error;
731 if (log_got_error) _exit(RERR_PARTIAL);
735 static RETSIGTYPE sigchld_handler(int val) {
737 while (waitpid(-1, NULL, WNOHANG) > 0) ;
741 int main(int argc,char *argv[])
744 extern int orig_umask;
746 extern int am_daemon;
747 extern int am_server;
748 extern int read_batch;
749 extern int write_batch;
750 extern char *batch_ext;
757 signal(SIGUSR1, sigusr1_handler);
758 signal(SIGUSR2, sigusr2_handler);
759 signal(SIGCHLD, sigchld_handler);
761 starttime = time(NULL);
762 am_root = (getuid() == 0);
764 memset(&stats, 0, sizeof(stats));
768 exit_cleanup(RERR_SYNTAX);
771 /* we set a 0 umask so that correct file permissions can be
773 orig_umask = (int)umask(0);
775 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
776 /* FIXME: We ought to call the same error-handling
777 * code here, rather than relying on getopt. */
779 exit_cleanup(RERR_SYNTAX);
782 signal(SIGINT,SIGNAL_CAST sig_int);
783 signal(SIGPIPE,SIGNAL_CAST sig_int);
784 signal(SIGHUP,SIGNAL_CAST sig_int);
785 signal(SIGTERM,SIGNAL_CAST sig_int);
787 /* Initialize push_dir here because on some old systems getcwd
788 (implemented by forking "pwd" and reading its output) doesn't
789 work when there are other child processes. Also, on all systems
790 that implement getcwd that way "pwd" can't be found after chroot. */
794 create_batch_file_ext();
795 write_batch_argvs_file(orig_argc, argc, argv);
799 set_batch_file_ext(batch_ext);
803 return daemon_main();
808 exit_cleanup(RERR_SYNTAX);
812 verbose = MAX(verbose,1);
814 #ifndef SUPPORT_LINKS
815 if (!am_server && preserve_links) {
816 rprintf(FERROR,"ERROR: symbolic links not supported\n");
817 exit_cleanup(RERR_UNSUPPORTED);
822 set_nonblocking(STDIN_FILENO);
823 set_nonblocking(STDOUT_FILENO);
824 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
827 ret = start_client(argc, argv);