1 /* -*- c-file-style: "linux" -*-
3 Copyright (C) 1996-2000 by Andrew Tridgell
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) {
39 *status = WEXITSTATUS(*status);
42 static void report(int f)
44 time_t t = time(NULL);
49 extern int remote_version;
53 log_exit(0, __FILE__, __LINE__);
54 if (f == -1 || !am_sender) return;
57 send_stats = verbose || (remote_version >= 20);
59 if (am_sender && send_stats) {
61 /* store total_written in a temporary
62 because write_longint changes it */
63 w = stats.total_written;
64 write_longint(f,stats.total_read);
66 write_longint(f,stats.total_size);
71 /* this is the client */
73 if (!am_sender && send_stats) {
75 stats.total_written = read_longint(f);
76 /* store total_read in a temporary, read_longint changes it */
78 stats.total_size = read_longint(f);
83 if (!am_sender && !send_stats) {
84 /* missing the bytes written by the generator */
85 rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
86 rprintf(FINFO, "Use --stats -v to show stats\n");
89 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
90 rprintf(FINFO,"Number of files transferred: %d\n",
91 stats.num_transferred_files);
92 rprintf(FINFO,"Total file size: %.0f bytes\n",
93 (double)stats.total_size);
94 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
95 (double)stats.total_transferred_size);
96 rprintf(FINFO,"Literal data: %.0f bytes\n",
97 (double)stats.literal_data);
98 rprintf(FINFO,"Matched data: %.0f bytes\n",
99 (double)stats.matched_data);
100 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
101 rprintf(FINFO,"Total bytes written: %.0f\n",
102 (double)stats.total_written);
103 rprintf(FINFO,"Total bytes read: %.0f\n\n",
104 (double)stats.total_read);
107 if (verbose || do_stats) {
108 rprintf(FINFO,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
109 (double)stats.total_written,
110 (double)stats.total_read,
111 (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
112 rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
113 (double)stats.total_size,
114 (1.0*stats.total_size)/(stats.total_written+stats.total_read));
122 static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
127 extern int local_server;
128 extern char *rsync_path;
129 extern int blocking_io;
133 cmd = getenv(RSYNC_RSH_ENV);
140 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
145 /* remsh (on HPUX) takes the arguments the other way around */
146 args[argc++] = machine;
156 args[argc++] = machine;
159 args[argc++] = rsync_path;
161 server_options(args,&argc);
164 if (strcmp(cmd, RSYNC_RSH) == 0) blocking_io = 1;
175 rprintf(FINFO,"cmd=");
177 rprintf(FINFO,"%s ",args[i]);
182 ret = local_child(argc, args, f_in, f_out);
184 ret = piped_child(args,f_in,f_out);
192 out_of_memory("do_cmd");
193 return 0; /* not reached */
199 static char *get_local_name(struct file_list *flist,char *name)
202 extern int orig_umask;
205 rprintf(FINFO,"get_local_name count=%d %s\n",
206 flist->count, NS(name));
211 if (do_stat(name,&st) == 0) {
212 if (S_ISDIR(st.st_mode)) {
213 if (!push_dir(name, 0)) {
214 rprintf(FERROR,"push_dir %s : %s (1)\n",
215 name,strerror(errno));
216 exit_cleanup(RERR_FILESELECT);
220 if (flist->count > 1) {
221 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
222 exit_cleanup(RERR_FILESELECT);
227 if (flist->count <= 1)
230 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
231 rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
232 exit_cleanup(RERR_FILEIO);
235 rprintf(FINFO,"created directory %s\n",name);
238 if (!push_dir(name, 0)) {
239 rprintf(FERROR,"push_dir %s : %s (2)\n",
240 name,strerror(errno));
241 exit_cleanup(RERR_FILESELECT);
250 static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
253 struct file_list *flist;
255 extern int relative_paths;
257 extern int remote_version;
260 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
262 if (!relative_paths && !push_dir(dir, 0)) {
263 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
264 exit_cleanup(RERR_FILESELECT);
269 if (strcmp(dir,".")) {
271 if (strcmp(dir,"/") == 0)
277 if (argc == 0 && recurse) {
283 flist = send_file_list(f_out,argc,argv);
284 if (!flist || flist->count == 0) {
288 send_files(flist,f_out,f_in);
291 if (remote_version >= 24) {
292 /* final goodbye message */
300 static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
306 extern int preserve_hard_links;
307 extern int delete_after;
309 extern int delete_mode;
310 extern int remote_version;
312 if (preserve_hard_links)
313 init_hard_links(flist);
316 /* I moved this here from recv_files() to prevent a race condition */
317 if (recurse && delete_mode && !local_name && flist->count>0) {
322 if (fd_pair(recv_pipe) < 0) {
323 rprintf(FERROR,"pipe failed in do_recv\n");
324 exit_cleanup(RERR_SOCKETIO);
327 if (fd_pair(error_pipe) < 0) {
328 rprintf(FERROR,"error pipe failed in do_recv\n");
329 exit_cleanup(RERR_SOCKETIO);
334 if ((pid=do_fork()) == 0) {
336 close(error_pipe[0]);
337 if (f_in != f_out) close(f_out);
339 /* we can't let two processes write to the socket at one time */
340 io_multiplexing_close();
342 /* set place to send errors */
343 set_error_fd(error_pipe[1]);
345 recv_files(f_in,flist,local_name,recv_pipe[1]);
349 write_int(recv_pipe[1],1);
352 /* finally we go to sleep until our parent kills us
353 with a USR2 signal. We sleep for a short time as on
354 some OSes a signal won't interrupt a sleep! */
355 while (1) msleep(20);
359 close(error_pipe[1]);
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);
464 * This is called once the connection has been negotiated. It is used
465 * for rsyncd, remote-shell, and local connections.
467 int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
469 struct file_list *flist;
470 int status = 0, status2 = 0;
471 char *local_name = NULL;
472 extern int am_sender;
473 extern int remote_version;
475 set_nonblocking(f_in);
476 set_nonblocking(f_out);
478 setup_protocol(f_out,f_in);
480 if (remote_version >= 23)
481 io_start_multiplex_in(f_in);
484 extern int cvs_exclude;
485 extern int delete_mode;
486 extern int delete_excluded;
489 if (delete_mode && !delete_excluded)
490 send_exclude_list(f_out);
491 flist = send_file_list(f_out,argc,argv);
493 rprintf(FINFO,"file list sent\n");
495 send_files(flist,f_out,f_in);
498 rprintf(FINFO,"client_run waiting on %d\n",pid);
500 wait_process(pid, &status);
502 if (remote_version >= 24) {
503 /* final goodbye message */
507 exit_cleanup(status);
511 extern int list_only;
515 send_exclude_list(f_out);
517 flist = recv_file_list(f_in);
518 if (!flist || flist->count == 0) {
519 rprintf(FINFO, "client: nothing to do: "
520 "perhaps you need to specify some filenames or "
521 "the --recursive option?\n");
525 local_name = get_local_name(flist,argv[0]);
527 status2 = do_recv(f_in,f_out,flist,local_name);
531 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
533 wait_process(pid, &status);
536 return status | status2;
539 static char *find_colon(char *s)
546 /* now check to see if there is a / in the string before the : - if there is then
547 discard the colon on the assumption that the : is part of a filename */
549 if (p2 && p2 < p) return NULL;
556 * Start a client for either type of remote connection. Work out
557 * whether the arguments request a remote shell or rsyncd connection,
558 * and call the appropriate connection function, then run_client.
560 static int start_client(int argc, char *argv[])
563 char *shell_machine = NULL;
564 char *shell_path = NULL;
565 char *shell_user = NULL;
568 extern int local_server;
569 extern int am_sender;
570 extern char *shell_cmd;
571 extern int rsync_port;
572 char *argv0 = strdup(argv[0]);
574 if (strncasecmp(URL_PREFIX, argv0, strlen(URL_PREFIX)) == 0) {
577 host = argv0 + strlen(URL_PREFIX);
578 p = strchr(host,'/');
585 p = strchr(host,':');
587 rsync_port = atoi(p+1);
590 return start_socket_client(host, path, argc-1, argv+1);
593 p = find_colon(argv0);
598 return start_socket_client(argv0, p+2, argc-1, argv+1);
603 exit_cleanup(RERR_SYNTAX);
608 shell_machine = argv0;
615 p = find_colon(argv[argc-1]);
618 } else if (p[1] == ':') {
620 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
625 exit_cleanup(RERR_SYNTAX);
629 shell_machine = NULL;
630 shell_path = argv[argc-1];
633 shell_machine = argv[argc-1];
640 p = strchr(shell_machine,'@');
643 shell_user = shell_machine;
649 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
650 shell_cmd?shell_cmd:"",
651 shell_machine?shell_machine:"",
652 shell_user?shell_user:"",
653 shell_path?shell_path:"");
656 if (!am_sender && argc > 1) {
658 exit_cleanup(RERR_SYNTAX);
661 if (argc == 0 && !am_sender) {
662 extern int list_only;
666 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
668 ret = client_run(f_in, f_out, pid, argc, argv);
677 static RETSIGTYPE sigusr1_handler(int val) {
678 exit_cleanup(RERR_SIGNAL);
681 static RETSIGTYPE sigusr2_handler(int val) {
685 int main(int argc,char *argv[])
688 extern int orig_umask;
690 extern int am_daemon;
691 extern int am_server;
693 signal(SIGUSR1, sigusr1_handler);
694 signal(SIGUSR2, sigusr2_handler);
696 starttime = time(NULL);
697 am_root = (getuid() == 0);
699 memset(&stats, 0, sizeof(stats));
703 exit_cleanup(RERR_SYNTAX);
706 /* we set a 0 umask so that correct file permissions can be
708 orig_umask = (int)umask(0);
710 if (!parse_arguments(argc, argv, 1)) {
711 exit_cleanup(RERR_SYNTAX);
718 signal(SIGCHLD,SIG_IGN);
719 signal(SIGINT,SIGNAL_CAST sig_int);
720 signal(SIGPIPE,SIGNAL_CAST sig_int);
721 signal(SIGHUP,SIGNAL_CAST sig_int);
722 signal(SIGTERM,SIGNAL_CAST sig_int);
724 /* Initialize push_dir here because on some old systems getcwd
725 (implemented by forking "pwd" and reading its output) doesn't
726 work when there are other child processes. Also, on all systems
727 that implement getcwd that way "pwd" can't be found after chroot. */
731 return daemon_main();
736 exit_cleanup(RERR_SYNTAX);
740 verbose = MAX(verbose,1);
742 #ifndef SUPPORT_LINKS
743 if (!am_server && preserve_links) {
744 rprintf(FERROR,"ERROR: symbolic links not supported\n");
745 exit_cleanup(RERR_UNSUPPORTED);
750 set_nonblocking(STDIN_FILENO);
751 set_nonblocking(STDOUT_FILENO);
752 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
755 return start_client(argc, argv);