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 with
333 close(error_pipe[1]);
334 io_close_input(f_in);
335 if (f_in != f_out) close(f_in);
337 io_start_buffering(f_out);
339 io_set_error_fd(error_pipe[0]);
341 generate_files(f_out,flist,local_name,recv_pipe[0]);
343 read_int(recv_pipe[0]);
345 if (remote_version >= 24) {
346 /* send a final goodbye message */
347 write_int(f_out, -1);
352 wait_process(pid, &status);
357 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
360 struct file_list *flist;
361 char *local_name=NULL;
363 extern int delete_mode;
364 extern int delete_excluded;
365 extern int am_daemon;
366 extern int module_id;
367 extern int am_sender;
370 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
372 if (am_daemon && lp_read_only(module_id) && !am_sender) {
373 rprintf(FERROR,"ERROR: module is read only\n");
374 exit_cleanup(RERR_SYNTAX);
383 if (!am_daemon && !push_dir(dir, 0)) {
384 rprintf(FERROR,"push_dir %s : %s (4)\n",
385 dir,strerror(errno));
386 exit_cleanup(RERR_FILESELECT);
390 if (delete_mode && !delete_excluded)
391 recv_exclude_list(f_in);
393 flist = recv_file_list(f_in);
395 rprintf(FERROR,"server_recv: recv_file_list error\n");
396 exit_cleanup(RERR_FILESELECT);
400 if (strcmp(dir,".")) {
401 argv[0] += strlen(dir);
402 if (argv[0][0] == '/') argv[0]++;
404 local_name = get_local_name(flist,argv[0]);
407 status = do_recv(f_in,f_out,flist,local_name);
408 exit_cleanup(status);
412 void start_server(int f_in, int f_out, int argc, char *argv[])
414 extern int cvs_exclude;
415 extern int am_sender;
416 extern int remote_version;
418 setup_protocol(f_out, f_in);
420 if (remote_version >= 23)
421 io_start_multiplex_out(f_out);
424 recv_exclude_list(f_in);
427 do_server_sender(f_in, f_out, argc, argv);
429 do_server_recv(f_in, f_out, argc, argv);
434 int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
436 struct file_list *flist;
437 int status = 0, status2 = 0;
438 char *local_name = NULL;
439 extern int am_sender;
440 extern int list_only;
441 extern int remote_version;
443 setup_protocol(f_out,f_in);
445 if (remote_version >= 23)
446 io_start_multiplex_in(f_in);
449 extern int cvs_exclude;
450 extern int delete_mode;
451 extern int delete_excluded;
454 if (delete_mode && !delete_excluded)
455 send_exclude_list(f_out);
456 flist = send_file_list(f_out,argc,argv);
458 rprintf(FINFO,"file list sent\n");
460 send_files(flist,f_out,f_in);
463 rprintf(FINFO,"client_run waiting on %d\n",pid);
465 wait_process(pid, &status);
468 if (remote_version >= 24) {
469 /* final goodbye message */
472 exit_cleanup(status);
475 if (argc == 0) list_only = 1;
477 send_exclude_list(f_out);
479 flist = recv_file_list(f_in);
480 if (!flist || flist->count == 0) {
481 rprintf(FINFO,"client: nothing to do\n");
485 local_name = get_local_name(flist,argv[0]);
487 status2 = do_recv(f_in,f_out,flist,local_name);
491 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
493 wait_process(pid, &status);
496 return status | status2;
499 static char *find_colon(char *s)
506 /* now check to see if there is a / in the string before the : - if there is then
507 discard the colon on the assumption that the : is part of a filename */
509 if (p2 && p2 < p) return NULL;
514 static int start_client(int argc, char *argv[])
517 char *shell_machine = NULL;
518 char *shell_path = NULL;
519 char *shell_user = NULL;
522 extern int local_server;
523 extern int am_sender;
524 extern char *shell_cmd;
525 extern int rsync_port;
527 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
530 host = argv[0] + strlen(URL_PREFIX);
531 p = strchr(host,'/');
538 p = strchr(host,':');
540 rsync_port = atoi(p+1);
543 return start_socket_client(host, path, argc-1, argv+1);
546 p = find_colon(argv[0]);
551 return start_socket_client(argv[0], p+2, argc-1, argv+1);
556 exit_cleanup(RERR_SYNTAX);
561 shell_machine = argv[0];
568 p = find_colon(argv[argc-1]);
571 } else if (p[1] == ':') {
573 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
578 exit_cleanup(RERR_SYNTAX);
582 shell_machine = NULL;
583 shell_path = argv[argc-1];
586 shell_machine = argv[argc-1];
593 p = strchr(shell_machine,'@');
596 shell_user = shell_machine;
602 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
603 shell_cmd?shell_cmd:"",
604 shell_machine?shell_machine:"",
605 shell_user?shell_user:"",
606 shell_path?shell_path:"");
609 if (!am_sender && argc > 1) {
611 exit_cleanup(RERR_SYNTAX);
614 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
616 ret = client_run(f_in, f_out, pid, argc, argv);
625 static RETSIGTYPE sigusr1_handler(int val) {
626 exit_cleanup(RERR_SIGNAL);
629 static RETSIGTYPE sigusr2_handler(int val) {
633 int main(int argc,char *argv[])
636 extern int orig_umask;
638 extern int am_daemon;
639 extern int am_server;
641 signal(SIGUSR1, sigusr1_handler);
642 signal(SIGUSR2, sigusr2_handler);
644 starttime = time(NULL);
645 am_root = (getuid() == 0);
647 memset(&stats, 0, sizeof(stats));
651 exit_cleanup(RERR_SYNTAX);
654 /* we set a 0 umask so that correct file permissions can be
656 orig_umask = (int)umask(0);
658 if (!parse_arguments(argc, argv, 1)) {
659 exit_cleanup(RERR_SYNTAX);
666 signal(SIGCHLD,SIG_IGN);
667 signal(SIGINT,SIGNAL_CAST sig_int);
668 signal(SIGPIPE,SIGNAL_CAST sig_int);
669 signal(SIGHUP,SIGNAL_CAST sig_int);
670 signal(SIGTERM,SIGNAL_CAST sig_int);
672 /* Initialize push_dir here because on some old systems getcwd
673 (implemented by forking "pwd" and reading its output) doesn't
674 work when there are other child processes. Also, on all systems
675 that implement getcwd that way "pwd" can't be found after chroot. */
679 return daemon_main();
684 exit_cleanup(RERR_SYNTAX);
688 verbose = MAX(verbose,1);
690 #ifndef SUPPORT_LINKS
691 if (!am_server && preserve_links) {
692 rprintf(FERROR,"ERROR: symbolic links not supported\n");
693 exit_cleanup(RERR_UNSUPPORTED);
698 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
701 return start_client(argc, argv);