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;
118 cmd = getenv(RSYNC_RSH_ENV);
125 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
130 /* remsh (on HPUX) takes the arguments the other way around */
131 args[argc++] = machine;
141 args[argc++] = machine;
144 args[argc++] = rsync_path;
146 server_options(args,&argc);
157 rprintf(FINFO,"cmd=");
159 rprintf(FINFO,"%s ",args[i]);
164 ret = local_child(argc, args, f_in, f_out);
166 ret = piped_child(args,f_in,f_out);
174 out_of_memory("do_cmd");
175 return 0; /* not reached */
181 static char *get_local_name(struct file_list *flist,char *name)
184 extern int orig_umask;
187 rprintf(FINFO,"get_local_name count=%d %s\n",
188 flist->count, NS(name));
193 if (do_stat(name,&st) == 0) {
194 if (S_ISDIR(st.st_mode)) {
195 if (!push_dir(name, 0)) {
196 rprintf(FERROR,"push_dir %s : %s (1)\n",
197 name,strerror(errno));
198 exit_cleanup(RERR_FILESELECT);
202 if (flist->count > 1) {
203 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
204 exit_cleanup(RERR_FILESELECT);
209 if (flist->count <= 1)
212 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
213 rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
214 exit_cleanup(RERR_FILEIO);
217 rprintf(FINFO,"created directory %s\n",name);
220 if (!push_dir(name, 0)) {
221 rprintf(FERROR,"push_dir %s : %s (2)\n",
222 name,strerror(errno));
223 exit_cleanup(RERR_FILESELECT);
232 static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
235 struct file_list *flist;
237 extern int relative_paths;
241 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
243 if (!relative_paths && !push_dir(dir, 0)) {
244 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
245 exit_cleanup(RERR_FILESELECT);
250 if (strcmp(dir,".")) {
252 if (strcmp(dir,"/") == 0)
258 if (argc == 0 && recurse) {
264 flist = send_file_list(f_out,argc,argv);
265 if (!flist || flist->count == 0) {
269 send_files(flist,f_out,f_in);
276 static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
282 extern int preserve_hard_links;
283 extern int delete_after;
285 extern int delete_mode;
286 extern int remote_version;
288 if (preserve_hard_links)
289 init_hard_links(flist);
292 /* I moved this here from recv_files() to prevent a race condition */
293 if (recurse && delete_mode && !local_name && flist->count>0) {
298 if (fd_pair(recv_pipe) < 0) {
299 rprintf(FERROR,"pipe failed in do_recv\n");
300 exit_cleanup(RERR_SOCKETIO);
303 if (fd_pair(error_pipe) < 0) {
304 rprintf(FERROR,"error pipe failed in do_recv\n");
305 exit_cleanup(RERR_SOCKETIO);
310 if ((pid=do_fork()) == 0) {
312 close(error_pipe[0]);
313 if (f_in != f_out) close(f_out);
315 /* we can't let two processes write to the socket at one time */
316 io_multiplexing_close();
318 /* set place to send errors */
319 set_error_fd(error_pipe[1]);
321 recv_files(f_in,flist,local_name,recv_pipe[1]);
324 write_int(recv_pipe[1],1);
327 /* finally we go to sleep until our parent kills us
328 with a USR2 signal. We sleepp for a short time as on
329 some OSes a signal won't interrupt a sleep! */
334 close(error_pipe[1]);
335 io_close_input(f_in);
336 if (f_in != f_out) close(f_in);
338 io_start_buffering(f_out);
340 io_set_error_fd(error_pipe[0]);
342 generate_files(f_out,flist,local_name,recv_pipe[0]);
344 read_int(recv_pipe[0]);
346 if (remote_version >= 24) {
347 /* send a final goodbye message */
348 write_int(f_out, -1);
353 wait_process(pid, &status);
358 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
361 struct file_list *flist;
362 char *local_name=NULL;
364 extern int delete_mode;
365 extern int delete_excluded;
366 extern int am_daemon;
367 extern int module_id;
368 extern int am_sender;
371 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
373 if (am_daemon && lp_read_only(module_id) && !am_sender) {
374 rprintf(FERROR,"ERROR: module is read only\n");
375 exit_cleanup(RERR_SYNTAX);
384 if (!am_daemon && !push_dir(dir, 0)) {
385 rprintf(FERROR,"push_dir %s : %s (4)\n",
386 dir,strerror(errno));
387 exit_cleanup(RERR_FILESELECT);
391 if (delete_mode && !delete_excluded)
392 recv_exclude_list(f_in);
394 flist = recv_file_list(f_in);
396 rprintf(FERROR,"server_recv: recv_file_list error\n");
397 exit_cleanup(RERR_FILESELECT);
401 if (strcmp(dir,".")) {
402 argv[0] += strlen(dir);
403 if (argv[0][0] == '/') argv[0]++;
405 local_name = get_local_name(flist,argv[0]);
408 status = do_recv(f_in,f_out,flist,local_name);
409 exit_cleanup(status);
413 void start_server(int f_in, int f_out, int argc, char *argv[])
415 extern int cvs_exclude;
416 extern int am_sender;
417 extern int remote_version;
419 setup_protocol(f_out, f_in);
421 set_nonblocking(f_in);
422 set_nonblocking(f_out);
424 if (remote_version >= 23)
425 io_start_multiplex_out(f_out);
428 recv_exclude_list(f_in);
431 do_server_sender(f_in, f_out, argc, argv);
433 do_server_recv(f_in, f_out, argc, argv);
438 int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
440 struct file_list *flist;
441 int status = 0, status2 = 0;
442 char *local_name = NULL;
443 extern int am_sender;
444 extern int list_only;
445 extern int remote_version;
447 set_nonblocking(f_in);
448 set_nonblocking(f_out);
450 setup_protocol(f_out,f_in);
452 if (remote_version >= 23)
453 io_start_multiplex_in(f_in);
456 extern int cvs_exclude;
457 extern int delete_mode;
458 extern int delete_excluded;
461 if (delete_mode && !delete_excluded)
462 send_exclude_list(f_out);
463 flist = send_file_list(f_out,argc,argv);
465 rprintf(FINFO,"file list sent\n");
467 send_files(flist,f_out,f_in);
470 rprintf(FINFO,"client_run waiting on %d\n",pid);
472 wait_process(pid, &status);
475 if (remote_version >= 24) {
476 /* final goodbye message */
479 exit_cleanup(status);
482 if (argc == 0) list_only = 1;
484 send_exclude_list(f_out);
486 flist = recv_file_list(f_in);
487 if (!flist || flist->count == 0) {
488 rprintf(FINFO,"client: nothing to do\n");
492 local_name = get_local_name(flist,argv[0]);
494 status2 = do_recv(f_in,f_out,flist,local_name);
498 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
500 wait_process(pid, &status);
503 return status | status2;
506 static char *find_colon(char *s)
513 /* now check to see if there is a / in the string before the : - if there is then
514 discard the colon on the assumption that the : is part of a filename */
516 if (p2 && p2 < p) return NULL;
521 static int start_client(int argc, char *argv[])
524 char *shell_machine = NULL;
525 char *shell_path = NULL;
526 char *shell_user = NULL;
529 extern int local_server;
530 extern int am_sender;
531 extern char *shell_cmd;
532 extern int rsync_port;
534 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
537 host = argv[0] + strlen(URL_PREFIX);
538 p = strchr(host,'/');
545 p = strchr(host,':');
547 rsync_port = atoi(p+1);
550 return start_socket_client(host, path, argc-1, argv+1);
553 p = find_colon(argv[0]);
558 return start_socket_client(argv[0], p+2, argc-1, argv+1);
563 exit_cleanup(RERR_SYNTAX);
568 shell_machine = argv[0];
575 p = find_colon(argv[argc-1]);
578 } else if (p[1] == ':') {
580 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
585 exit_cleanup(RERR_SYNTAX);
589 shell_machine = NULL;
590 shell_path = argv[argc-1];
593 shell_machine = argv[argc-1];
600 p = strchr(shell_machine,'@');
603 shell_user = shell_machine;
609 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
610 shell_cmd?shell_cmd:"",
611 shell_machine?shell_machine:"",
612 shell_user?shell_user:"",
613 shell_path?shell_path:"");
616 if (!am_sender && argc > 1) {
618 exit_cleanup(RERR_SYNTAX);
621 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
623 ret = client_run(f_in, f_out, pid, argc, argv);
632 static RETSIGTYPE sigusr1_handler(int val) {
633 exit_cleanup(RERR_SIGNAL);
636 static RETSIGTYPE sigusr2_handler(int val) {
640 int main(int argc,char *argv[])
643 extern int orig_umask;
645 extern int am_daemon;
646 extern int am_server;
648 signal(SIGUSR1, sigusr1_handler);
649 signal(SIGUSR2, sigusr2_handler);
651 starttime = time(NULL);
652 am_root = (getuid() == 0);
654 memset(&stats, 0, sizeof(stats));
658 exit_cleanup(RERR_SYNTAX);
661 /* we set a 0 umask so that correct file permissions can be
663 orig_umask = (int)umask(0);
665 if (!parse_arguments(argc, argv, 1)) {
666 exit_cleanup(RERR_SYNTAX);
673 signal(SIGCHLD,SIG_IGN);
674 signal(SIGINT,SIGNAL_CAST sig_int);
675 signal(SIGPIPE,SIGNAL_CAST sig_int);
676 signal(SIGHUP,SIGNAL_CAST sig_int);
677 signal(SIGTERM,SIGNAL_CAST sig_int);
679 /* Initialize push_dir here because on some old systems getcwd
680 (implemented by forking "pwd" and reading its output) doesn't
681 work when there are other child processes. Also, on all systems
682 that implement getcwd that way "pwd" can't be found after chroot. */
686 return daemon_main();
691 exit_cleanup(RERR_SYNTAX);
695 verbose = MAX(verbose,1);
697 #ifndef SUPPORT_LINKS
698 if (!am_server && preserve_links) {
699 rprintf(FERROR,"ERROR: symbolic links not supported\n");
700 exit_cleanup(RERR_UNSUPPORTED);
705 set_nonblocking(STDIN_FILENO);
706 set_nonblocking(STDOUT_FILENO);
707 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
710 return start_client(argc, argv);