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\n");
517 local_name = get_local_name(flist,argv[0]);
519 status2 = do_recv(f_in,f_out,flist,local_name);
523 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
525 wait_process(pid, &status);
528 return status | status2;
531 static char *find_colon(char *s)
538 /* now check to see if there is a / in the string before the : - if there is then
539 discard the colon on the assumption that the : is part of a filename */
541 if (p2 && p2 < p) return NULL;
546 static int start_client(int argc, char *argv[])
549 char *shell_machine = NULL;
550 char *shell_path = NULL;
551 char *shell_user = NULL;
554 extern int local_server;
555 extern int am_sender;
556 extern char *shell_cmd;
557 extern int rsync_port;
559 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
562 host = argv[0] + strlen(URL_PREFIX);
563 p = strchr(host,'/');
570 p = strchr(host,':');
572 rsync_port = atoi(p+1);
575 return start_socket_client(host, path, argc-1, argv+1);
578 p = find_colon(argv[0]);
583 return start_socket_client(argv[0], p+2, argc-1, argv+1);
588 exit_cleanup(RERR_SYNTAX);
593 shell_machine = argv[0];
600 p = find_colon(argv[argc-1]);
603 } else if (p[1] == ':') {
605 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
610 exit_cleanup(RERR_SYNTAX);
614 shell_machine = NULL;
615 shell_path = argv[argc-1];
618 shell_machine = argv[argc-1];
625 p = strchr(shell_machine,'@');
628 shell_user = shell_machine;
634 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
635 shell_cmd?shell_cmd:"",
636 shell_machine?shell_machine:"",
637 shell_user?shell_user:"",
638 shell_path?shell_path:"");
641 if (!am_sender && argc > 1) {
643 exit_cleanup(RERR_SYNTAX);
646 if (argc == 0 && !am_sender) {
647 extern int list_only;
651 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
653 ret = client_run(f_in, f_out, pid, argc, argv);
662 static RETSIGTYPE sigusr1_handler(int val) {
663 exit_cleanup(RERR_SIGNAL);
666 static RETSIGTYPE sigusr2_handler(int val) {
670 int main(int argc,char *argv[])
673 extern int orig_umask;
675 extern int am_daemon;
676 extern int am_server;
678 signal(SIGUSR1, sigusr1_handler);
679 signal(SIGUSR2, sigusr2_handler);
681 starttime = time(NULL);
682 am_root = (getuid() == 0);
684 memset(&stats, 0, sizeof(stats));
688 exit_cleanup(RERR_SYNTAX);
691 /* we set a 0 umask so that correct file permissions can be
693 orig_umask = (int)umask(0);
695 if (!parse_arguments(argc, argv, 1)) {
696 exit_cleanup(RERR_SYNTAX);
703 signal(SIGCHLD,SIG_IGN);
704 signal(SIGINT,SIGNAL_CAST sig_int);
705 signal(SIGPIPE,SIGNAL_CAST sig_int);
706 signal(SIGHUP,SIGNAL_CAST sig_int);
707 signal(SIGTERM,SIGNAL_CAST sig_int);
709 /* Initialize push_dir here because on some old systems getcwd
710 (implemented by forking "pwd" and reading its output) doesn't
711 work when there are other child processes. Also, on all systems
712 that implement getcwd that way "pwd" can't be found after chroot. */
716 return daemon_main();
721 exit_cleanup(RERR_SYNTAX);
725 verbose = MAX(verbose,1);
727 #ifndef SUPPORT_LINKS
728 if (!am_server && preserve_links) {
729 rprintf(FERROR,"ERROR: symbolic links not supported\n");
730 exit_cleanup(RERR_UNSUPPORTED);
735 set_nonblocking(STDIN_FILENO);
736 set_nonblocking(STDOUT_FILENO);
737 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
740 return start_client(argc, argv);