1 /* -*- c-file-style: "linux" -*-
3 Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
4 Copyright (C) Paul Mackerras 1996
5 Copyright (C) 2001 by Martin Pool <mbp@samba.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 /****************************************************************************
32 wait for a process to exit, calling io_flush while waiting
33 ****************************************************************************/
34 void wait_process(pid_t pid
, int *status
)
36 while (waitpid(pid
, status
, WNOHANG
) == 0) {
41 /* TODO: If the child exited on a signal, then log an
42 * appropriate error message. Perhaps we should also accept a
43 * message describing the purpose of the child. Also indicate
44 * this to the caller so that thhey know something went
46 *status
= WEXITSTATUS(*status
);
49 static void report(int f
)
51 time_t t
= time(NULL
);
56 extern int remote_version
;
60 log_exit(0, __FILE__
, __LINE__
);
61 if (f
== -1 || !am_sender
) return;
64 send_stats
= verbose
|| (remote_version
>= 20);
66 if (am_sender
&& send_stats
) {
68 /* store total_written in a temporary
69 because write_longint changes it */
70 w
= stats
.total_written
;
71 write_longint(f
,stats
.total_read
);
73 write_longint(f
,stats
.total_size
);
78 /* this is the client */
80 if (!am_sender
&& send_stats
) {
82 stats
.total_written
= read_longint(f
);
83 /* store total_read in a temporary, read_longint changes it */
85 stats
.total_size
= read_longint(f
);
90 if (!am_sender
&& !send_stats
) {
91 /* missing the bytes written by the generator */
92 rprintf(FINFO
, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
93 rprintf(FINFO
, "Use --stats -v to show stats\n");
96 rprintf(FINFO
,"\nNumber of files: %d\n", stats
.num_files
);
97 rprintf(FINFO
,"Number of files transferred: %d\n",
98 stats
.num_transferred_files
);
99 rprintf(FINFO
,"Total file size: %.0f bytes\n",
100 (double)stats
.total_size
);
101 rprintf(FINFO
,"Total transferred file size: %.0f bytes\n",
102 (double)stats
.total_transferred_size
);
103 rprintf(FINFO
,"Literal data: %.0f bytes\n",
104 (double)stats
.literal_data
);
105 rprintf(FINFO
,"Matched data: %.0f bytes\n",
106 (double)stats
.matched_data
);
107 rprintf(FINFO
,"File list size: %d\n", stats
.flist_size
);
108 rprintf(FINFO
,"Total bytes written: %.0f\n",
109 (double)stats
.total_written
);
110 rprintf(FINFO
,"Total bytes read: %.0f\n\n",
111 (double)stats
.total_read
);
114 if (verbose
|| do_stats
) {
115 rprintf(FINFO
,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
116 (double)stats
.total_written
,
117 (double)stats
.total_read
,
118 (stats
.total_written
+stats
.total_read
)/(0.5 + (t
-starttime
)));
119 rprintf(FINFO
,"total size is %.0f speedup is %.2f\n",
120 (double)stats
.total_size
,
121 (1.0*stats
.total_size
)/(stats
.total_written
+stats
.total_read
));
129 /* Start the remote shell. cmd may be NULL to use the default. */
130 static pid_t
do_cmd(char *cmd
,char *machine
,char *user
,char *path
,int *f_in
,int *f_out
)
136 extern int local_server
;
137 extern char *rsync_path
;
138 extern int blocking_io
;
139 extern int read_batch
;
141 if (!read_batch
&& !local_server
) { /* dw -- added read_batch */
143 cmd
= getenv(RSYNC_RSH_ENV
);
150 for (tok
=strtok(cmd
," ");tok
;tok
=strtok(NULL
," ")) {
155 /* remsh (on HPUX) takes the arguments the other way around */
156 args
[argc
++] = machine
;
166 args
[argc
++] = machine
;
169 args
[argc
++] = rsync_path
;
171 server_options(args
,&argc
);
174 if (strcmp(cmd
, RSYNC_RSH
) == 0) blocking_io
= 1;
185 rprintf(FINFO
,"cmd=");
187 rprintf(FINFO
,"%s ",args
[i
]);
193 create_flist_from_batch();
194 ret
= local_child(argc
, args
, f_in
, f_out
);
196 ret
= piped_child(args
,f_in
,f_out
);
204 out_of_memory("do_cmd");
205 return 0; /* not reached */
211 static char *get_local_name(struct file_list
*flist
,char *name
)
214 extern int orig_umask
;
217 rprintf(FINFO
,"get_local_name count=%d %s\n",
218 flist
->count
, NS(name
));
223 if (do_stat(name
,&st
) == 0) {
224 if (S_ISDIR(st
.st_mode
)) {
225 if (!push_dir(name
, 0)) {
226 rprintf(FERROR
,"push_dir %s : %s (1)\n",
227 name
,strerror(errno
));
228 exit_cleanup(RERR_FILESELECT
);
232 if (flist
->count
> 1) {
233 rprintf(FERROR
,"ERROR: destination must be a directory when copying more than 1 file\n");
234 exit_cleanup(RERR_FILESELECT
);
239 if (flist
->count
<= 1)
242 if (do_mkdir(name
,0777 & ~orig_umask
) != 0) {
243 rprintf(FERROR
,"mkdir %s : %s (1)\n",name
,strerror(errno
));
244 exit_cleanup(RERR_FILEIO
);
247 rprintf(FINFO
,"created directory %s\n",name
);
250 if (!push_dir(name
, 0)) {
251 rprintf(FERROR
,"push_dir %s : %s (2)\n",
252 name
,strerror(errno
));
253 exit_cleanup(RERR_FILESELECT
);
262 static void do_server_sender(int f_in
, int f_out
, int argc
,char *argv
[])
265 struct file_list
*flist
;
267 extern int relative_paths
;
269 extern int remote_version
;
272 rprintf(FINFO
,"server_sender starting pid=%d\n",(int)getpid());
274 if (!relative_paths
&& !push_dir(dir
, 0)) {
275 rprintf(FERROR
,"push_dir %s: %s (3)\n",dir
,strerror(errno
));
276 exit_cleanup(RERR_FILESELECT
);
281 if (strcmp(dir
,".")) {
283 if (strcmp(dir
,"/") == 0)
289 if (argc
== 0 && recurse
) {
295 flist
= send_file_list(f_out
,argc
,argv
);
296 if (!flist
|| flist
->count
== 0) {
300 send_files(flist
,f_out
,f_in
);
303 if (remote_version
>= 24) {
304 /* final goodbye message */
312 static int do_recv(int f_in
,int f_out
,struct file_list
*flist
,char *local_name
)
318 extern int preserve_hard_links
;
319 extern int delete_after
;
321 extern int delete_mode
;
322 extern int remote_version
;
324 if (preserve_hard_links
)
325 init_hard_links(flist
);
328 /* I moved this here from recv_files() to prevent a race condition */
329 if (recurse
&& delete_mode
&& !local_name
&& flist
->count
>0) {
334 if (fd_pair(recv_pipe
) < 0) {
335 rprintf(FERROR
,"pipe failed in do_recv\n");
336 exit_cleanup(RERR_SOCKETIO
);
339 if (fd_pair(error_pipe
) < 0) {
340 rprintf(FERROR
,"error pipe failed in do_recv\n");
341 exit_cleanup(RERR_SOCKETIO
);
346 if ((pid
=do_fork()) == 0) {
348 close(error_pipe
[0]);
349 if (f_in
!= f_out
) close(f_out
);
351 /* we can't let two processes write to the socket at one time */
352 io_multiplexing_close();
354 /* set place to send errors */
355 set_error_fd(error_pipe
[1]);
357 recv_files(f_in
,flist
,local_name
,recv_pipe
[1]);
361 write_int(recv_pipe
[1],1);
364 /* finally we go to sleep until our parent kills us
365 with a USR2 signal. We sleep for a short time as on
366 some OSes a signal won't interrupt a sleep! */
372 close(error_pipe
[1]);
373 if (f_in
!= f_out
) close(f_in
);
375 io_start_buffering(f_out
);
377 io_set_error_fd(error_pipe
[0]);
379 generate_files(f_out
,flist
,local_name
,recv_pipe
[0]);
381 read_int(recv_pipe
[0]);
383 if (remote_version
>= 24) {
384 /* send a final goodbye message */
385 write_int(f_out
, -1);
390 wait_process(pid
, &status
);
395 static void do_server_recv(int f_in
, int f_out
, int argc
,char *argv
[])
398 struct file_list
*flist
;
399 char *local_name
=NULL
;
401 extern int delete_mode
;
402 extern int delete_excluded
;
403 extern int am_daemon
;
404 extern int module_id
;
405 extern int am_sender
;
406 extern int read_batch
; /* dw */
407 extern struct file_list
*batch_flist
; /* dw */
410 rprintf(FINFO
,"server_recv(%d) starting pid=%d\n",argc
,(int)getpid());
412 if (am_daemon
&& lp_read_only(module_id
) && !am_sender
) {
413 rprintf(FERROR
,"ERROR: module is read only\n");
414 exit_cleanup(RERR_SYNTAX
);
423 if (!am_daemon
&& !push_dir(dir
, 0)) {
424 rprintf(FERROR
,"push_dir %s : %s (4)\n",
425 dir
,strerror(errno
));
426 exit_cleanup(RERR_FILESELECT
);
430 if (delete_mode
&& !delete_excluded
)
431 recv_exclude_list(f_in
);
433 if (read_batch
) /* dw */
436 flist
= recv_file_list(f_in
);
438 rprintf(FERROR
,"server_recv: recv_file_list error\n");
439 exit_cleanup(RERR_FILESELECT
);
443 if (strcmp(dir
,".")) {
444 argv
[0] += strlen(dir
);
445 if (argv
[0][0] == '/') argv
[0]++;
447 local_name
= get_local_name(flist
,argv
[0]);
450 status
= do_recv(f_in
,f_out
,flist
,local_name
);
451 exit_cleanup(status
);
455 void start_server(int f_in
, int f_out
, int argc
, char *argv
[])
457 extern int cvs_exclude
;
458 extern int am_sender
;
459 extern int remote_version
;
460 extern int read_batch
; /* dw */
462 setup_protocol(f_out
, f_in
);
464 set_nonblocking(f_in
);
465 set_nonblocking(f_out
);
467 if (remote_version
>= 23)
468 io_start_multiplex_out(f_out
);
471 if (!read_batch
) { /* dw */
472 recv_exclude_list(f_in
);
476 do_server_sender(f_in
, f_out
, argc
, argv
);
478 do_server_recv(f_in
, f_out
, argc
, argv
);
485 * This is called once the connection has been negotiated. It is used
486 * for rsyncd, remote-shell, and local connections.
488 int client_run(int f_in
, int f_out
, pid_t pid
, int argc
, char *argv
[])
490 struct file_list
*flist
;
491 int status
= 0, status2
= 0;
492 char *local_name
= NULL
;
493 extern int am_sender
;
494 extern int remote_version
;
495 extern pid_t cleanup_child_pid
;
496 extern int write_batch
; /* dw */
497 extern int read_batch
; /* dw */
498 extern struct file_list
*batch_flist
; /* dw */
500 cleanup_child_pid
= pid
;
502 flist
= batch_flist
; /* dw */
504 set_nonblocking(f_in
);
505 set_nonblocking(f_out
);
507 setup_protocol(f_out
,f_in
);
509 if (remote_version
>= 23)
510 io_start_multiplex_in(f_in
);
513 extern int cvs_exclude
;
514 extern int delete_mode
;
515 extern int delete_excluded
;
518 if (delete_mode
&& !delete_excluded
)
519 send_exclude_list(f_out
);
520 if (!read_batch
) /* dw -- don't write to pipe */
521 flist
= send_file_list(f_out
,argc
,argv
);
523 rprintf(FINFO
,"file list sent\n");
525 send_files(flist
,f_out
,f_in
);
526 if (remote_version
>= 24) {
527 /* final goodbye message */
532 rprintf(FINFO
,"client_run waiting on %d\n", (int) pid
);
534 wait_process(pid
, &status
);
537 exit_cleanup(status
);
541 extern int list_only
;
545 if (!write_batch
) /* dw */
546 send_exclude_list(f_out
);
548 flist
= recv_file_list(f_in
);
549 if (!flist
|| flist
->count
== 0) {
550 rprintf(FINFO
, "client: nothing to do: "
551 "perhaps you need to specify some filenames or "
552 "the --recursive option?\n");
556 local_name
= get_local_name(flist
,argv
[0]);
558 status2
= do_recv(f_in
,f_out
,flist
,local_name
);
562 rprintf(FINFO
,"client_run2 waiting on %d\n", (int) pid
);
564 wait_process(pid
, &status
);
567 return MAX(status
, status2
);
570 static char *find_colon(char *s
)
577 /* now check to see if there is a / in the string before the : - if there is then
578 discard the colon on the assumption that the : is part of a filename */
580 if (p2
&& p2
< p
) return NULL
;
586 static int copy_argv (char *argv
[])
590 for (i
= 0; argv
[i
]; i
++) {
591 if (!(argv
[i
] = strdup(argv
[i
]))) {
592 rprintf (FERROR
, "out of memory at %s(%d)\n",
603 * Start a client for either type of remote connection. Work out
604 * whether the arguments request a remote shell or rsyncd connection,
605 * and call the appropriate connection function, then run_client.
607 static int start_client(int argc
, char *argv
[])
610 char *shell_machine
= NULL
;
611 char *shell_path
= NULL
;
612 char *shell_user
= NULL
;
616 extern int local_server
;
617 extern int am_sender
;
618 extern char *shell_cmd
;
619 extern int rsync_port
;
620 extern int whole_file
;
621 extern int read_batch
;
624 /* Don't clobber argv[] so that ps(1) can still show the right
626 if ((rc
= copy_argv (argv
)))
629 if (strncasecmp(URL_PREFIX
, argv
[0], strlen(URL_PREFIX
)) == 0) {
632 host
= argv
[0] + strlen(URL_PREFIX
);
633 p
= strchr(host
,'/');
640 p
= strchr(host
,':');
642 rsync_port
= atoi(p
+1);
645 return start_socket_client(host
, path
, argc
-1, argv
+1);
648 if (!read_batch
) { /* dw */
649 p
= find_colon(argv
[0]);
654 return start_socket_client(argv
[0], p
+2, argc
-1, argv
+1);
659 exit_cleanup(RERR_SYNTAX
);
664 shell_machine
= argv
[0];
671 p
= find_colon(argv
[argc
-1]);
674 /* disable "rsync algorithm" when both sides local */
676 } else if (p
[1] == ':') {
678 return start_socket_client(argv
[argc
-1], p
+2, argc
-1, argv
);
683 exit_cleanup(RERR_SYNTAX
);
687 shell_machine
= NULL
;
688 shell_path
= argv
[argc
-1];
691 shell_machine
= argv
[argc
-1];
697 am_sender
= 1; /* dw */
698 local_server
= 1; /* dw */
699 shell_path
= argv
[argc
-1]; /* dw */
703 p
= strchr(shell_machine
,'@');
706 shell_user
= shell_machine
;
712 rprintf(FINFO
,"cmd=%s machine=%s user=%s path=%s\n",
713 shell_cmd
?shell_cmd
:"",
714 shell_machine
?shell_machine
:"",
715 shell_user
?shell_user
:"",
716 shell_path
?shell_path
:"");
719 if (!am_sender
&& argc
> 1) {
721 exit_cleanup(RERR_SYNTAX
);
724 if (argc
== 0 && !am_sender
) {
725 extern int list_only
;
729 pid
= do_cmd(shell_cmd
,shell_machine
,shell_user
,shell_path
,&f_in
,&f_out
);
731 ret
= client_run(f_in
, f_out
, pid
, argc
, argv
);
740 static RETSIGTYPE
sigusr1_handler(int val
) {
741 exit_cleanup(RERR_SIGNAL
);
744 static RETSIGTYPE
sigusr2_handler(int val
) {
745 extern int log_got_error
;
746 if (log_got_error
) _exit(RERR_PARTIAL
);
750 static RETSIGTYPE
sigchld_handler(int val
) {
752 while (waitpid(-1, NULL
, WNOHANG
) > 0) ;
756 int main(int argc
,char *argv
[])
759 extern int orig_umask
;
761 extern int am_daemon
;
762 extern int am_server
;
764 extern int read_batch
; /* dw */
765 extern int write_batch
; /* dw */
766 extern char *batch_ext
; /* dw */
767 int orig_argc
; /* dw */
769 orig_argc
= argc
; /* dw */
771 signal(SIGUSR1
, sigusr1_handler
);
772 signal(SIGUSR2
, sigusr2_handler
);
773 signal(SIGCHLD
, sigchld_handler
);
775 starttime
= time(NULL
);
776 am_root
= (getuid() == 0);
778 memset(&stats
, 0, sizeof(stats
));
782 exit_cleanup(RERR_SYNTAX
);
785 /* we set a 0 umask so that correct file permissions can be
787 orig_umask
= (int)umask(0);
789 if (!parse_arguments(&argc
, (const char ***) &argv
, 1)) {
790 /* FIXME: We ought to call the same error-handling
791 * code here, rather than relying on getopt. */
793 exit_cleanup(RERR_SYNTAX
);
796 signal(SIGINT
,SIGNAL_CAST sig_int
);
797 signal(SIGPIPE
,SIGNAL_CAST sig_int
);
798 signal(SIGHUP
,SIGNAL_CAST sig_int
);
799 signal(SIGTERM
,SIGNAL_CAST sig_int
);
801 /* Initialize push_dir here because on some old systems getcwd
802 (implemented by forking "pwd" and reading its output) doesn't
803 work when there are other child processes. Also, on all systems
804 that implement getcwd that way "pwd" can't be found after chroot. */
807 if (write_batch
) { /* dw */
808 create_batch_file_ext();
809 write_batch_argvs_file(orig_argc
, argc
, argv
);
812 if (read_batch
) { /* dw */
813 set_batch_file_ext(batch_ext
);
817 return daemon_main();
822 exit_cleanup(RERR_SYNTAX
);
826 verbose
= MAX(verbose
,1);
828 #ifndef SUPPORT_LINKS
829 if (!am_server
&& preserve_links
) {
830 rprintf(FERROR
,"ERROR: symbolic links not supported\n");
831 exit_cleanup(RERR_UNSUPPORTED
);
836 set_nonblocking(STDIN_FILENO
);
837 set_nonblocking(STDOUT_FILENO
);
838 start_server(STDIN_FILENO
, STDOUT_FILENO
, argc
, argv
);
841 ret
= start_client(argc
, argv
);