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);
280 static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
286 extern int preserve_hard_links;
287 extern int delete_after;
289 extern int delete_mode;
290 extern int remote_version;
292 if (preserve_hard_links)
293 init_hard_links(flist);
296 /* I moved this here from recv_files() to prevent a race condition */
297 if (recurse && delete_mode && !local_name && flist->count>0) {
302 if (fd_pair(recv_pipe) < 0) {
303 rprintf(FERROR,"pipe failed in do_recv\n");
304 exit_cleanup(RERR_SOCKETIO);
307 if (fd_pair(error_pipe) < 0) {
308 rprintf(FERROR,"error pipe failed in do_recv\n");
309 exit_cleanup(RERR_SOCKETIO);
314 if ((pid=do_fork()) == 0) {
316 close(error_pipe[0]);
317 if (f_in != f_out) close(f_out);
319 /* we can't let two processes write to the socket at one time */
320 io_multiplexing_close();
322 /* set place to send errors */
323 set_error_fd(error_pipe[1]);
325 recv_files(f_in,flist,local_name,recv_pipe[1]);
328 write_int(recv_pipe[1],1);
331 /* finally we go to sleep until our parent kills us
332 with a USR2 signal. We sleepp for a short time as on
333 some OSes a signal won't interrupt a sleep! */
338 close(error_pipe[1]);
339 io_close_input(f_in);
340 if (f_in != f_out) close(f_in);
342 io_start_buffering(f_out);
344 io_set_error_fd(error_pipe[0]);
346 generate_files(f_out,flist,local_name,recv_pipe[0]);
348 read_int(recv_pipe[0]);
350 if (remote_version >= 24) {
351 /* send a final goodbye message */
352 write_int(f_out, -1);
357 wait_process(pid, &status);
362 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
365 struct file_list *flist;
366 char *local_name=NULL;
368 extern int delete_mode;
369 extern int delete_excluded;
370 extern int am_daemon;
371 extern int module_id;
372 extern int am_sender;
375 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
377 if (am_daemon && lp_read_only(module_id) && !am_sender) {
378 rprintf(FERROR,"ERROR: module is read only\n");
379 exit_cleanup(RERR_SYNTAX);
388 if (!am_daemon && !push_dir(dir, 0)) {
389 rprintf(FERROR,"push_dir %s : %s (4)\n",
390 dir,strerror(errno));
391 exit_cleanup(RERR_FILESELECT);
395 if (delete_mode && !delete_excluded)
396 recv_exclude_list(f_in);
398 flist = recv_file_list(f_in);
400 rprintf(FERROR,"server_recv: recv_file_list error\n");
401 exit_cleanup(RERR_FILESELECT);
405 if (strcmp(dir,".")) {
406 argv[0] += strlen(dir);
407 if (argv[0][0] == '/') argv[0]++;
409 local_name = get_local_name(flist,argv[0]);
412 status = do_recv(f_in,f_out,flist,local_name);
413 exit_cleanup(status);
417 void start_server(int f_in, int f_out, int argc, char *argv[])
419 extern int cvs_exclude;
420 extern int am_sender;
421 extern int remote_version;
423 setup_protocol(f_out, f_in);
425 set_nonblocking(f_in);
426 set_nonblocking(f_out);
428 if (remote_version >= 23)
429 io_start_multiplex_out(f_out);
432 recv_exclude_list(f_in);
435 do_server_sender(f_in, f_out, argc, argv);
437 do_server_recv(f_in, f_out, argc, argv);
442 int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
444 struct file_list *flist;
445 int status = 0, status2 = 0;
446 char *local_name = NULL;
447 extern int am_sender;
448 extern int list_only;
449 extern int remote_version;
451 set_nonblocking(f_in);
452 set_nonblocking(f_out);
454 setup_protocol(f_out,f_in);
456 if (remote_version >= 23)
457 io_start_multiplex_in(f_in);
460 extern int cvs_exclude;
461 extern int delete_mode;
462 extern int delete_excluded;
465 if (delete_mode && !delete_excluded)
466 send_exclude_list(f_out);
467 flist = send_file_list(f_out,argc,argv);
469 rprintf(FINFO,"file list sent\n");
471 send_files(flist,f_out,f_in);
474 rprintf(FINFO,"client_run waiting on %d\n",pid);
476 wait_process(pid, &status);
479 if (remote_version >= 24) {
480 /* final goodbye message */
483 exit_cleanup(status);
486 if (argc == 0) list_only = 1;
488 send_exclude_list(f_out);
490 flist = recv_file_list(f_in);
491 if (!flist || flist->count == 0) {
492 rprintf(FINFO,"client: nothing to do\n");
496 local_name = get_local_name(flist,argv[0]);
498 status2 = do_recv(f_in,f_out,flist,local_name);
502 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
504 wait_process(pid, &status);
507 return status | status2;
510 static char *find_colon(char *s)
517 /* now check to see if there is a / in the string before the : - if there is then
518 discard the colon on the assumption that the : is part of a filename */
520 if (p2 && p2 < p) return NULL;
525 static int start_client(int argc, char *argv[])
528 char *shell_machine = NULL;
529 char *shell_path = NULL;
530 char *shell_user = NULL;
533 extern int local_server;
534 extern int am_sender;
535 extern char *shell_cmd;
536 extern int rsync_port;
538 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
541 host = argv[0] + strlen(URL_PREFIX);
542 p = strchr(host,'/');
549 p = strchr(host,':');
551 rsync_port = atoi(p+1);
554 return start_socket_client(host, path, argc-1, argv+1);
557 p = find_colon(argv[0]);
562 return start_socket_client(argv[0], p+2, argc-1, argv+1);
567 exit_cleanup(RERR_SYNTAX);
572 shell_machine = argv[0];
579 p = find_colon(argv[argc-1]);
582 } else if (p[1] == ':') {
584 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
589 exit_cleanup(RERR_SYNTAX);
593 shell_machine = NULL;
594 shell_path = argv[argc-1];
597 shell_machine = argv[argc-1];
604 p = strchr(shell_machine,'@');
607 shell_user = shell_machine;
613 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
614 shell_cmd?shell_cmd:"",
615 shell_machine?shell_machine:"",
616 shell_user?shell_user:"",
617 shell_path?shell_path:"");
620 if (!am_sender && argc > 1) {
622 exit_cleanup(RERR_SYNTAX);
625 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
627 ret = client_run(f_in, f_out, pid, argc, argv);
636 static RETSIGTYPE sigusr1_handler(int val) {
637 exit_cleanup(RERR_SIGNAL);
640 static RETSIGTYPE sigusr2_handler(int val) {
644 int main(int argc,char *argv[])
647 extern int orig_umask;
649 extern int am_daemon;
650 extern int am_server;
652 signal(SIGUSR1, sigusr1_handler);
653 signal(SIGUSR2, sigusr2_handler);
655 starttime = time(NULL);
656 am_root = (getuid() == 0);
658 memset(&stats, 0, sizeof(stats));
662 exit_cleanup(RERR_SYNTAX);
665 /* we set a 0 umask so that correct file permissions can be
667 orig_umask = (int)umask(0);
669 if (!parse_arguments(argc, argv, 1)) {
670 exit_cleanup(RERR_SYNTAX);
677 signal(SIGCHLD,SIG_IGN);
678 signal(SIGINT,SIGNAL_CAST sig_int);
679 signal(SIGPIPE,SIGNAL_CAST sig_int);
680 signal(SIGHUP,SIGNAL_CAST sig_int);
681 signal(SIGTERM,SIGNAL_CAST sig_int);
683 /* Initialize push_dir here because on some old systems getcwd
684 (implemented by forking "pwd" and reading its output) doesn't
685 work when there are other child processes. Also, on all systems
686 that implement getcwd that way "pwd" can't be found after chroot. */
690 return daemon_main();
695 exit_cleanup(RERR_SYNTAX);
699 verbose = MAX(verbose,1);
701 #ifndef SUPPORT_LINKS
702 if (!am_server && preserve_links) {
703 rprintf(FERROR,"ERROR: symbolic links not supported\n");
704 exit_cleanup(RERR_UNSUPPORTED);
709 set_nonblocking(STDIN_FILENO);
710 set_nonblocking(STDOUT_FILENO);
711 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
714 return start_client(argc, argv);