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.
28 static void report(int f)
30 time_t t = time(NULL);
35 extern int remote_version;
39 log_exit(0, __FILE__, __LINE__);
40 if (f == -1 || !am_sender) return;
43 send_stats = verbose || (remote_version >= 20);
45 if (am_sender && send_stats) {
47 /* store total_written in a temporary
48 because write_longint changes it */
49 w = stats.total_written;
50 write_longint(f,stats.total_read);
52 write_longint(f,stats.total_size);
57 /* this is the client */
59 if (!am_sender && send_stats) {
61 stats.total_written = read_longint(f);
62 /* store total_read in a temporary, read_longint changes it */
64 stats.total_size = read_longint(f);
69 if (!am_sender && !send_stats) {
70 /* missing the bytes written by the generator */
71 rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
72 rprintf(FINFO, "Use --stats -v to show stats\n");
75 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
76 rprintf(FINFO,"Number of files transferred: %d\n",
77 stats.num_transferred_files);
78 rprintf(FINFO,"Total file size: %.0f bytes\n",
79 (double)stats.total_size);
80 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
81 (double)stats.total_transferred_size);
82 rprintf(FINFO,"Literal data: %.0f bytes\n",
83 (double)stats.literal_data);
84 rprintf(FINFO,"Matched data: %.0f bytes\n",
85 (double)stats.matched_data);
86 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
87 rprintf(FINFO,"Total bytes written: %.0f\n",
88 (double)stats.total_written);
89 rprintf(FINFO,"Total bytes read: %.0f\n\n",
90 (double)stats.total_read);
93 if (verbose || do_stats) {
94 rprintf(FINFO,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
95 (double)stats.total_written,
96 (double)stats.total_read,
97 (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
98 rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
99 (double)stats.total_size,
100 (1.0*stats.total_size)/(stats.total_written+stats.total_read));
108 static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
113 extern int local_server;
114 extern char *rsync_path;
115 extern int blocking_io;
119 cmd = getenv(RSYNC_RSH_ENV);
126 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
131 /* remsh (on HPUX) takes the arguments the other way around */
132 args[argc++] = machine;
142 args[argc++] = machine;
145 args[argc++] = rsync_path;
147 server_options(args,&argc);
150 if (strcmp(cmd, RSYNC_RSH) == 0) blocking_io = 1;
161 rprintf(FINFO,"cmd=");
163 rprintf(FINFO,"%s ",args[i]);
168 ret = local_child(argc, args, f_in, f_out);
170 ret = piped_child(args,f_in,f_out);
178 out_of_memory("do_cmd");
179 return 0; /* not reached */
185 static char *get_local_name(struct file_list *flist,char *name)
188 extern int orig_umask;
191 rprintf(FINFO,"get_local_name count=%d %s\n",
192 flist->count, NS(name));
197 if (do_stat(name,&st) == 0) {
198 if (S_ISDIR(st.st_mode)) {
199 if (!push_dir(name, 0)) {
200 rprintf(FERROR,"push_dir %s : %s (1)\n",
201 name,strerror(errno));
202 exit_cleanup(RERR_FILESELECT);
206 if (flist->count > 1) {
207 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
208 exit_cleanup(RERR_FILESELECT);
213 if (flist->count <= 1)
216 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
217 rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
218 exit_cleanup(RERR_FILEIO);
221 rprintf(FINFO,"created directory %s\n",name);
224 if (!push_dir(name, 0)) {
225 rprintf(FERROR,"push_dir %s : %s (2)\n",
226 name,strerror(errno));
227 exit_cleanup(RERR_FILESELECT);
236 static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
239 struct file_list *flist;
241 extern int relative_paths;
245 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
247 if (!relative_paths && !push_dir(dir, 0)) {
248 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
249 exit_cleanup(RERR_FILESELECT);
254 if (strcmp(dir,".")) {
256 if (strcmp(dir,"/") == 0)
262 if (argc == 0 && recurse) {
268 flist = send_file_list(f_out,argc,argv);
269 if (!flist || flist->count == 0) {
273 send_files(flist,f_out,f_in);
281 static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
287 extern int preserve_hard_links;
288 extern int delete_after;
290 extern int delete_mode;
291 extern int remote_version;
293 if (preserve_hard_links)
294 init_hard_links(flist);
297 /* I moved this here from recv_files() to prevent a race condition */
298 if (recurse && delete_mode && !local_name && flist->count>0) {
303 if (fd_pair(recv_pipe) < 0) {
304 rprintf(FERROR,"pipe failed in do_recv\n");
305 exit_cleanup(RERR_SOCKETIO);
308 if (fd_pair(error_pipe) < 0) {
309 rprintf(FERROR,"error pipe failed in do_recv\n");
310 exit_cleanup(RERR_SOCKETIO);
315 if ((pid=do_fork()) == 0) {
317 close(error_pipe[0]);
318 if (f_in != f_out) close(f_out);
320 /* we can't let two processes write to the socket at one time */
321 io_multiplexing_close();
323 /* set place to send errors */
324 set_error_fd(error_pipe[1]);
326 recv_files(f_in,flist,local_name,recv_pipe[1]);
330 write_int(recv_pipe[1],1);
333 /* finally we go to sleep until our parent kills us
334 with a USR2 signal. We sleepp for a short time as on
335 some OSes a signal won't interrupt a sleep! */
340 close(error_pipe[1]);
341 io_close_input(f_in);
342 if (f_in != f_out) close(f_in);
344 io_start_buffering(f_out);
346 io_set_error_fd(error_pipe[0]);
348 generate_files(f_out,flist,local_name,recv_pipe[0]);
350 read_int(recv_pipe[0]);
352 if (remote_version >= 24) {
353 /* send a final goodbye message */
354 write_int(f_out, -1);
359 wait_process(pid, &status);
364 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
367 struct file_list *flist;
368 char *local_name=NULL;
370 extern int delete_mode;
371 extern int delete_excluded;
372 extern int am_daemon;
373 extern int module_id;
374 extern int am_sender;
377 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
379 if (am_daemon && lp_read_only(module_id) && !am_sender) {
380 rprintf(FERROR,"ERROR: module is read only\n");
381 exit_cleanup(RERR_SYNTAX);
390 if (!am_daemon && !push_dir(dir, 0)) {
391 rprintf(FERROR,"push_dir %s : %s (4)\n",
392 dir,strerror(errno));
393 exit_cleanup(RERR_FILESELECT);
397 if (delete_mode && !delete_excluded)
398 recv_exclude_list(f_in);
400 flist = recv_file_list(f_in);
402 rprintf(FERROR,"server_recv: recv_file_list error\n");
403 exit_cleanup(RERR_FILESELECT);
407 if (strcmp(dir,".")) {
408 argv[0] += strlen(dir);
409 if (argv[0][0] == '/') argv[0]++;
411 local_name = get_local_name(flist,argv[0]);
414 status = do_recv(f_in,f_out,flist,local_name);
415 exit_cleanup(status);
419 void start_server(int f_in, int f_out, int argc, char *argv[])
421 extern int cvs_exclude;
422 extern int am_sender;
423 extern int remote_version;
425 setup_protocol(f_out, f_in);
427 set_nonblocking(f_in);
428 set_nonblocking(f_out);
430 if (remote_version >= 23)
431 io_start_multiplex_out(f_out);
434 recv_exclude_list(f_in);
437 do_server_sender(f_in, f_out, argc, argv);
439 do_server_recv(f_in, f_out, argc, argv);
444 int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
446 struct file_list *flist;
447 int status = 0, status2 = 0;
448 char *local_name = NULL;
449 extern int am_sender;
450 extern int list_only;
451 extern int remote_version;
453 set_nonblocking(f_in);
454 set_nonblocking(f_out);
456 setup_protocol(f_out,f_in);
458 if (remote_version >= 23)
459 io_start_multiplex_in(f_in);
462 extern int cvs_exclude;
463 extern int delete_mode;
464 extern int delete_excluded;
467 if (delete_mode && !delete_excluded)
468 send_exclude_list(f_out);
469 flist = send_file_list(f_out,argc,argv);
471 rprintf(FINFO,"file list sent\n");
473 send_files(flist,f_out,f_in);
476 rprintf(FINFO,"client_run waiting on %d\n",pid);
478 wait_process(pid, &status);
480 if (remote_version >= 24) {
481 /* final goodbye message */
485 exit_cleanup(status);
488 if (argc == 0) list_only = 1;
490 send_exclude_list(f_out);
492 flist = recv_file_list(f_in);
493 if (!flist || flist->count == 0) {
494 rprintf(FINFO,"client: nothing to do\n");
498 local_name = get_local_name(flist,argv[0]);
500 status2 = do_recv(f_in,f_out,flist,local_name);
504 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
506 wait_process(pid, &status);
509 return status | status2;
512 static char *find_colon(char *s)
519 /* now check to see if there is a / in the string before the : - if there is then
520 discard the colon on the assumption that the : is part of a filename */
522 if (p2 && p2 < p) return NULL;
527 static int start_client(int argc, char *argv[])
530 char *shell_machine = NULL;
531 char *shell_path = NULL;
532 char *shell_user = NULL;
535 extern int local_server;
536 extern int am_sender;
537 extern char *shell_cmd;
538 extern int rsync_port;
540 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
543 host = argv[0] + strlen(URL_PREFIX);
544 p = strchr(host,'/');
551 p = strchr(host,':');
553 rsync_port = atoi(p+1);
556 return start_socket_client(host, path, argc-1, argv+1);
559 p = find_colon(argv[0]);
564 return start_socket_client(argv[0], p+2, argc-1, argv+1);
569 exit_cleanup(RERR_SYNTAX);
574 shell_machine = argv[0];
581 p = find_colon(argv[argc-1]);
584 } else if (p[1] == ':') {
586 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
591 exit_cleanup(RERR_SYNTAX);
595 shell_machine = NULL;
596 shell_path = argv[argc-1];
599 shell_machine = argv[argc-1];
606 p = strchr(shell_machine,'@');
609 shell_user = shell_machine;
615 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
616 shell_cmd?shell_cmd:"",
617 shell_machine?shell_machine:"",
618 shell_user?shell_user:"",
619 shell_path?shell_path:"");
622 if (!am_sender && argc > 1) {
624 exit_cleanup(RERR_SYNTAX);
627 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
629 ret = client_run(f_in, f_out, pid, argc, argv);
638 static RETSIGTYPE sigusr1_handler(int val) {
639 exit_cleanup(RERR_SIGNAL);
642 static RETSIGTYPE sigusr2_handler(int val) {
646 int main(int argc,char *argv[])
649 extern int orig_umask;
651 extern int am_daemon;
652 extern int am_server;
654 signal(SIGUSR1, sigusr1_handler);
655 signal(SIGUSR2, sigusr2_handler);
657 starttime = time(NULL);
658 am_root = (getuid() == 0);
660 memset(&stats, 0, sizeof(stats));
664 exit_cleanup(RERR_SYNTAX);
667 /* we set a 0 umask so that correct file permissions can be
669 orig_umask = (int)umask(0);
671 if (!parse_arguments(argc, argv, 1)) {
672 exit_cleanup(RERR_SYNTAX);
679 signal(SIGCHLD,SIG_IGN);
680 signal(SIGINT,SIGNAL_CAST sig_int);
681 signal(SIGPIPE,SIGNAL_CAST sig_int);
682 signal(SIGHUP,SIGNAL_CAST sig_int);
683 signal(SIGTERM,SIGNAL_CAST sig_int);
685 /* Initialize push_dir here because on some old systems getcwd
686 (implemented by forking "pwd" and reading its output) doesn't
687 work when there are other child processes. Also, on all systems
688 that implement getcwd that way "pwd" can't be found after chroot. */
692 return daemon_main();
697 exit_cleanup(RERR_SYNTAX);
701 verbose = MAX(verbose,1);
703 #ifndef SUPPORT_LINKS
704 if (!am_server && preserve_links) {
705 rprintf(FERROR,"ERROR: symbolic links not supported\n");
706 exit_cleanup(RERR_UNSUPPORTED);
711 set_nonblocking(STDIN_FILENO);
712 set_nonblocking(STDOUT_FILENO);
713 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
716 return start_client(argc, argv);