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;
560 char *argv0 = strdup(argv[0]);
562 if (strncasecmp(URL_PREFIX, argv0, strlen(URL_PREFIX)) == 0) {
565 host = argv0 + strlen(URL_PREFIX);
566 p = strchr(host,'/');
573 p = strchr(host,':');
575 rsync_port = atoi(p+1);
578 return start_socket_client(host, path, argc-1, argv+1);
581 p = find_colon(argv0);
586 return start_socket_client(argv0, p+2, argc-1, argv+1);
591 exit_cleanup(RERR_SYNTAX);
596 shell_machine = argv[0];
603 p = find_colon(argv[argc-1]);
606 } else if (p[1] == ':') {
608 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
613 exit_cleanup(RERR_SYNTAX);
617 shell_machine = NULL;
618 shell_path = argv[argc-1];
621 shell_machine = argv[argc-1];
628 p = strchr(shell_machine,'@');
631 shell_user = shell_machine;
637 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
638 shell_cmd?shell_cmd:"",
639 shell_machine?shell_machine:"",
640 shell_user?shell_user:"",
641 shell_path?shell_path:"");
644 if (!am_sender && argc > 1) {
646 exit_cleanup(RERR_SYNTAX);
649 if (argc == 0 && !am_sender) {
650 extern int list_only;
654 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
656 ret = client_run(f_in, f_out, pid, argc, argv);
665 static RETSIGTYPE sigusr1_handler(int val) {
666 exit_cleanup(RERR_SIGNAL);
669 static RETSIGTYPE sigusr2_handler(int val) {
673 int main(int argc,char *argv[])
676 extern int orig_umask;
678 extern int am_daemon;
679 extern int am_server;
681 signal(SIGUSR1, sigusr1_handler);
682 signal(SIGUSR2, sigusr2_handler);
684 starttime = time(NULL);
685 am_root = (getuid() == 0);
687 memset(&stats, 0, sizeof(stats));
691 exit_cleanup(RERR_SYNTAX);
694 /* we set a 0 umask so that correct file permissions can be
696 orig_umask = (int)umask(0);
698 if (!parse_arguments(argc, argv, 1)) {
699 exit_cleanup(RERR_SYNTAX);
706 signal(SIGCHLD,SIG_IGN);
707 signal(SIGINT,SIGNAL_CAST sig_int);
708 signal(SIGPIPE,SIGNAL_CAST sig_int);
709 signal(SIGHUP,SIGNAL_CAST sig_int);
710 signal(SIGTERM,SIGNAL_CAST sig_int);
712 /* Initialize push_dir here because on some old systems getcwd
713 (implemented by forking "pwd" and reading its output) doesn't
714 work when there are other child processes. Also, on all systems
715 that implement getcwd that way "pwd" can't be found after chroot. */
719 return daemon_main();
724 exit_cleanup(RERR_SYNTAX);
728 verbose = MAX(verbose,1);
730 #ifndef SUPPORT_LINKS
731 if (!am_server && preserve_links) {
732 rprintf(FERROR,"ERROR: symbolic links not supported\n");
733 exit_cleanup(RERR_UNSUPPORTED);
738 set_nonblocking(STDIN_FILENO);
739 set_nonblocking(STDOUT_FILENO);
740 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
743 return start_client(argc, argv);