1 /* -*- c-file-style: "linux" -*-
3 Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
4 Copyright (C) Paul Mackerras 1996
5 Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 static void show_malloc_stats(void);
32 /****************************************************************************
33 wait for a process to exit, calling io_flush while waiting
34 ****************************************************************************/
35 void wait_process(pid_t pid, int *status)
37 while (waitpid(pid, status, WNOHANG) == 0) {
42 /* TODO: If the child exited on a signal, then log an
43 * appropriate error message. Perhaps we should also accept a
44 * message describing the purpose of the child. Also indicate
45 * this to the caller so that thhey know something went
47 *status = WEXITSTATUS(*status);
50 static void report(int f)
52 time_t t = time(NULL);
57 extern int remote_version;
61 log_exit(0, __FILE__, __LINE__);
62 if (f == -1 || !am_sender) return;
65 send_stats = verbose || (remote_version >= 20);
67 if (am_sender && send_stats) {
69 /* store total_written in a temporary
70 because write_longint changes it */
71 w = stats.total_written;
72 write_longint(f,stats.total_read);
74 write_longint(f,stats.total_size);
79 /* this is the client */
81 if (!am_sender && send_stats) {
83 stats.total_written = read_longint(f);
84 /* store total_read in a temporary, read_longint changes it */
86 stats.total_size = read_longint(f);
91 if (!am_sender && !send_stats) {
92 /* missing the bytes written by the generator */
93 rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
94 rprintf(FINFO, "Use --stats -v to show stats\n");
97 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
98 rprintf(FINFO,"Number of files transferred: %d\n",
99 stats.num_transferred_files);
100 rprintf(FINFO,"Total file size: %.0f bytes\n",
101 (double)stats.total_size);
102 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
103 (double)stats.total_transferred_size);
104 rprintf(FINFO,"Literal data: %.0f bytes\n",
105 (double)stats.literal_data);
106 rprintf(FINFO,"Matched data: %.0f bytes\n",
107 (double)stats.matched_data);
108 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
109 rprintf(FINFO,"Total bytes written: %.0f\n",
110 (double)stats.total_written);
111 rprintf(FINFO,"Total bytes read: %.0f\n\n",
112 (double)stats.total_read);
115 if (verbose || do_stats) {
116 rprintf(FINFO,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
117 (double)stats.total_written,
118 (double)stats.total_read,
119 (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
120 rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
121 (double)stats.total_size,
122 (1.0*stats.total_size)/(stats.total_written+stats.total_read));
132 * If our C library can get malloc statistics, then show them to FINFO
134 static void show_malloc_stats(void)
141 rprintf(FINFO, RSYNC_NAME " heap statistics:\n");
142 rprintf(FINFO, " arena: %10d (bytes from sbrk)\n", mi.arena);
143 rprintf(FINFO, " ordblks: %10d (chunks not in use)\n", mi.ordblks);
144 rprintf(FINFO, " smblks: %10d\n", mi.smblks);
145 rprintf(FINFO, " hblks: %10d (chunks from mmap)\n", mi.hblks);
146 rprintf(FINFO, " hblkhd: %10d (bytes from mmap)\n", mi.hblkhd);
147 rprintf(FINFO, " usmblks: %10d\n", mi.usmblks);
148 rprintf(FINFO, " fsmblks: %10d\n", mi.fsmblks);
149 rprintf(FINFO, " uordblks: %10d (bytes used)\n", mi.uordblks);
150 rprintf(FINFO, " fordblks: %10d (bytes free)\n", mi.fordblks);
151 rprintf(FINFO, " keepcost: %10d (bytes in releasable chunk)\n", mi.keepcost);
152 #endif /* HAVE_MALLINFO */
156 /* Start the remote shell. cmd may be NULL to use the default. */
157 static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
163 extern int local_server;
164 extern char *rsync_path;
165 extern int blocking_io;
166 extern int read_batch;
168 if (!read_batch && !local_server) { /* dw -- added read_batch */
170 cmd = getenv(RSYNC_RSH_ENV);
177 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
182 /* remsh (on HPUX) takes the arguments the other way around */
183 args[argc++] = machine;
193 args[argc++] = machine;
196 args[argc++] = rsync_path;
198 server_options(args,&argc);
201 if (strcmp(cmd, RSYNC_RSH) == 0) blocking_io = 1;
212 rprintf(FINFO,"cmd=");
214 rprintf(FINFO,"%s ",args[i]);
220 create_flist_from_batch();
221 ret = local_child(argc, args, f_in, f_out);
223 ret = piped_child(args,f_in,f_out);
231 out_of_memory("do_cmd");
232 return 0; /* not reached */
238 static char *get_local_name(struct file_list *flist,char *name)
241 extern int orig_umask;
244 rprintf(FINFO,"get_local_name count=%d %s\n",
245 flist->count, NS(name));
250 if (do_stat(name,&st) == 0) {
251 if (S_ISDIR(st.st_mode)) {
252 if (!push_dir(name, 0)) {
253 rprintf(FERROR,"push_dir %s : %s (1)\n",
254 name,strerror(errno));
255 exit_cleanup(RERR_FILESELECT);
259 if (flist->count > 1) {
260 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
261 exit_cleanup(RERR_FILESELECT);
266 if (flist->count <= 1)
269 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
270 rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
271 exit_cleanup(RERR_FILEIO);
274 rprintf(FINFO,"created directory %s\n",name);
277 if (!push_dir(name, 0)) {
278 rprintf(FERROR,"push_dir %s : %s (2)\n",
279 name,strerror(errno));
280 exit_cleanup(RERR_FILESELECT);
289 static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
292 struct file_list *flist;
294 extern int relative_paths;
296 extern int remote_version;
299 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
301 if (!relative_paths && !push_dir(dir, 0)) {
302 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
303 exit_cleanup(RERR_FILESELECT);
308 if (strcmp(dir,".")) {
310 if (strcmp(dir,"/") == 0)
316 if (argc == 0 && recurse) {
322 flist = send_file_list(f_out,argc,argv);
323 if (!flist || flist->count == 0) {
327 send_files(flist,f_out,f_in);
330 if (remote_version >= 24) {
331 /* final goodbye message */
339 static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
345 extern int preserve_hard_links;
346 extern int delete_after;
348 extern int delete_mode;
349 extern int remote_version;
351 if (preserve_hard_links)
352 init_hard_links(flist);
355 /* I moved this here from recv_files() to prevent a race condition */
356 if (recurse && delete_mode && !local_name && flist->count>0) {
361 if (fd_pair(recv_pipe) < 0) {
362 rprintf(FERROR,"pipe failed in do_recv\n");
363 exit_cleanup(RERR_SOCKETIO);
366 if (fd_pair(error_pipe) < 0) {
367 rprintf(FERROR,"error pipe failed in do_recv\n");
368 exit_cleanup(RERR_SOCKETIO);
373 if ((pid=do_fork()) == 0) {
375 close(error_pipe[0]);
376 if (f_in != f_out) close(f_out);
378 /* we can't let two processes write to the socket at one time */
379 io_multiplexing_close();
381 /* set place to send errors */
382 set_error_fd(error_pipe[1]);
384 recv_files(f_in,flist,local_name,recv_pipe[1]);
388 write_int(recv_pipe[1],1);
391 /* finally we go to sleep until our parent kills us
392 with a USR2 signal. We sleep for a short time as on
393 some OSes a signal won't interrupt a sleep! */
399 close(error_pipe[1]);
400 if (f_in != f_out) close(f_in);
402 io_start_buffering(f_out);
404 io_set_error_fd(error_pipe[0]);
406 generate_files(f_out,flist,local_name,recv_pipe[0]);
408 read_int(recv_pipe[0]);
410 if (remote_version >= 24) {
411 /* send a final goodbye message */
412 write_int(f_out, -1);
417 wait_process(pid, &status);
422 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
425 struct file_list *flist;
426 char *local_name=NULL;
428 extern int delete_mode;
429 extern int delete_excluded;
430 extern int am_daemon;
431 extern int module_id;
432 extern int am_sender;
433 extern int read_batch; /* dw */
434 extern struct file_list *batch_flist; /* dw */
437 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
439 if (am_daemon && lp_read_only(module_id) && !am_sender) {
440 rprintf(FERROR,"ERROR: module is read only\n");
441 exit_cleanup(RERR_SYNTAX);
450 if (!am_daemon && !push_dir(dir, 0)) {
451 rprintf(FERROR,"push_dir %s : %s (4)\n",
452 dir,strerror(errno));
453 exit_cleanup(RERR_FILESELECT);
457 if (delete_mode && !delete_excluded)
458 recv_exclude_list(f_in);
460 if (read_batch) /* dw */
463 flist = recv_file_list(f_in);
465 rprintf(FERROR,"server_recv: recv_file_list error\n");
466 exit_cleanup(RERR_FILESELECT);
470 if (strcmp(dir,".")) {
471 argv[0] += strlen(dir);
472 if (argv[0][0] == '/') argv[0]++;
474 local_name = get_local_name(flist,argv[0]);
477 status = do_recv(f_in,f_out,flist,local_name);
478 exit_cleanup(status);
482 void start_server(int f_in, int f_out, int argc, char *argv[])
484 extern int cvs_exclude;
485 extern int am_sender;
486 extern int remote_version;
487 extern int read_batch; /* dw */
489 setup_protocol(f_out, f_in);
491 set_nonblocking(f_in);
492 set_nonblocking(f_out);
494 if (remote_version >= 23)
495 io_start_multiplex_out(f_out);
498 if (!read_batch) { /* dw */
499 recv_exclude_list(f_in);
503 do_server_sender(f_in, f_out, argc, argv);
505 do_server_recv(f_in, f_out, argc, argv);
512 * This is called once the connection has been negotiated. It is used
513 * for rsyncd, remote-shell, and local connections.
515 int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
517 struct file_list *flist;
518 int status = 0, status2 = 0;
519 char *local_name = NULL;
520 extern int am_sender;
521 extern int remote_version;
522 extern pid_t cleanup_child_pid;
523 extern int write_batch; /* dw */
524 extern int read_batch; /* dw */
525 extern struct file_list *batch_flist; /* dw */
527 cleanup_child_pid = pid;
529 flist = batch_flist; /* dw */
531 set_nonblocking(f_in);
532 set_nonblocking(f_out);
534 setup_protocol(f_out,f_in);
536 if (remote_version >= 23)
537 io_start_multiplex_in(f_in);
540 extern int cvs_exclude;
541 extern int delete_mode;
542 extern int delete_excluded;
545 if (delete_mode && !delete_excluded)
546 send_exclude_list(f_out);
547 if (!read_batch) /* dw -- don't write to pipe */
548 flist = send_file_list(f_out,argc,argv);
550 rprintf(FINFO,"file list sent\n");
552 send_files(flist,f_out,f_in);
553 if (remote_version >= 24) {
554 /* final goodbye message */
559 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
561 wait_process(pid, &status);
564 exit_cleanup(status);
568 extern int list_only;
572 if (!write_batch) /* dw */
573 send_exclude_list(f_out);
575 flist = recv_file_list(f_in);
576 if (!flist || flist->count == 0) {
577 rprintf(FINFO, "client: nothing to do: "
578 "perhaps you need to specify some filenames or "
579 "the --recursive option?\n");
583 local_name = get_local_name(flist,argv[0]);
585 status2 = do_recv(f_in,f_out,flist,local_name);
589 rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
591 wait_process(pid, &status);
594 return MAX(status, status2);
597 static char *find_colon(char *s)
604 /* now check to see if there is a / in the string before the : - if there is then
605 discard the colon on the assumption that the : is part of a filename */
607 if (p2 && p2 < p) return NULL;
613 static int copy_argv (char *argv[])
617 for (i = 0; argv[i]; i++) {
618 if (!(argv[i] = strdup(argv[i]))) {
619 rprintf (FERROR, "out of memory at %s(%d)\n",
630 * Start a client for either type of remote connection. Work out
631 * whether the arguments request a remote shell or rsyncd connection,
632 * and call the appropriate connection function, then run_client.
634 static int start_client(int argc, char *argv[])
637 char *shell_machine = NULL;
638 char *shell_path = NULL;
639 char *shell_user = NULL;
643 extern int local_server;
644 extern int am_sender;
645 extern char *shell_cmd;
646 extern int rsync_port;
647 extern int whole_file;
648 extern int read_batch;
651 /* Don't clobber argv[] so that ps(1) can still show the right
653 if ((rc = copy_argv (argv)))
656 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
659 host = argv[0] + strlen(URL_PREFIX);
660 p = strchr(host,'/');
667 p = strchr(host,':');
669 rsync_port = atoi(p+1);
672 return start_socket_client(host, path, argc-1, argv+1);
675 if (!read_batch) { /* dw */
676 p = find_colon(argv[0]);
681 return start_socket_client(argv[0], p+2, argc-1, argv+1);
686 exit_cleanup(RERR_SYNTAX);
691 shell_machine = argv[0];
698 p = find_colon(argv[argc-1]);
701 /* disable "rsync algorithm" when both sides local */
703 } else if (p[1] == ':') {
705 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
710 exit_cleanup(RERR_SYNTAX);
714 shell_machine = NULL;
715 shell_path = argv[argc-1];
718 shell_machine = argv[argc-1];
724 am_sender = 1; /* dw */
725 local_server = 1; /* dw */
726 shell_path = argv[argc-1]; /* dw */
730 p = strchr(shell_machine,'@');
733 shell_user = shell_machine;
739 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
740 shell_cmd?shell_cmd:"",
741 shell_machine?shell_machine:"",
742 shell_user?shell_user:"",
743 shell_path?shell_path:"");
746 if (!am_sender && argc > 1) {
748 exit_cleanup(RERR_SYNTAX);
751 if (argc == 0 && !am_sender) {
752 extern int list_only;
756 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
758 ret = client_run(f_in, f_out, pid, argc, argv);
767 static RETSIGTYPE sigusr1_handler(int val) {
768 exit_cleanup(RERR_SIGNAL);
771 static RETSIGTYPE sigusr2_handler(int val) {
772 extern int log_got_error;
773 if (log_got_error) _exit(RERR_PARTIAL);
777 static RETSIGTYPE sigchld_handler(int val) {
779 while (waitpid(-1, NULL, WNOHANG) > 0) ;
783 int main(int argc,char *argv[])
786 extern int orig_umask;
788 extern int am_daemon;
789 extern int am_server;
791 extern int read_batch; /* dw */
792 extern int write_batch; /* dw */
793 extern char *batch_ext; /* dw */
794 int orig_argc; /* dw */
796 orig_argc = argc; /* dw */
798 signal(SIGUSR1, sigusr1_handler);
799 signal(SIGUSR2, sigusr2_handler);
800 signal(SIGCHLD, sigchld_handler);
802 starttime = time(NULL);
803 am_root = (getuid() == 0);
805 memset(&stats, 0, sizeof(stats));
809 exit_cleanup(RERR_SYNTAX);
812 /* we set a 0 umask so that correct file permissions can be
814 orig_umask = (int)umask(0);
816 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
817 /* FIXME: We ought to call the same error-handling
818 * code here, rather than relying on getopt. */
820 exit_cleanup(RERR_SYNTAX);
823 signal(SIGINT,SIGNAL_CAST sig_int);
824 signal(SIGPIPE,SIGNAL_CAST sig_int);
825 signal(SIGHUP,SIGNAL_CAST sig_int);
826 signal(SIGTERM,SIGNAL_CAST sig_int);
828 /* Initialize push_dir here because on some old systems getcwd
829 (implemented by forking "pwd" and reading its output) doesn't
830 work when there are other child processes. Also, on all systems
831 that implement getcwd that way "pwd" can't be found after chroot. */
834 if (write_batch) { /* dw */
835 create_batch_file_ext();
836 write_batch_argvs_file(orig_argc, argc, argv);
839 if (read_batch) { /* dw */
840 set_batch_file_ext(batch_ext);
844 return daemon_main();
849 exit_cleanup(RERR_SYNTAX);
853 verbose = MAX(verbose,1);
855 #ifndef SUPPORT_LINKS
856 if (!am_server && preserve_links) {
857 rprintf(FERROR,"ERROR: symbolic links not supported\n");
858 exit_cleanup(RERR_UNSUPPORTED);
863 set_nonblocking(STDIN_FILENO);
864 set_nonblocking(STDOUT_FILENO);
865 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
868 ret = start_client(argc, argv);