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);
330 close(error_pipe[1]);
331 io_close_input(f_in);
332 if (f_in != f_out) close(f_in);
334 io_start_buffering(f_out);
336 io_set_error_fd(error_pipe[0]);
338 generate_files(f_out,flist,local_name,recv_pipe[0]);
340 read_int(recv_pipe[1]);
341 if (remote_version >= 24) {
342 /* send a final goodbye message */
343 write_int(f_out, -1);
347 wait_process(pid, &status);
352 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
355 struct file_list *flist;
356 char *local_name=NULL;
358 extern int delete_mode;
359 extern int delete_excluded;
360 extern int am_daemon;
361 extern int module_id;
362 extern int am_sender;
365 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
367 if (am_daemon && lp_read_only(module_id) && !am_sender) {
368 rprintf(FERROR,"ERROR: module is read only\n");
369 exit_cleanup(RERR_SYNTAX);
378 if (!am_daemon && !push_dir(dir, 0)) {
379 rprintf(FERROR,"push_dir %s : %s (4)\n",
380 dir,strerror(errno));
381 exit_cleanup(RERR_FILESELECT);
385 if (delete_mode && !delete_excluded)
386 recv_exclude_list(f_in);
388 flist = recv_file_list(f_in);
390 rprintf(FERROR,"server_recv: recv_file_list error\n");
391 exit_cleanup(RERR_FILESELECT);
395 if (strcmp(dir,".")) {
396 argv[0] += strlen(dir);
397 if (argv[0][0] == '/') argv[0]++;
399 local_name = get_local_name(flist,argv[0]);
402 status = do_recv(f_in,f_out,flist,local_name);
403 exit_cleanup(status);
407 void start_server(int f_in, int f_out, int argc, char *argv[])
409 extern int cvs_exclude;
410 extern int am_sender;
411 extern int remote_version;
413 setup_protocol(f_out, f_in);
415 if (remote_version >= 23)
416 io_start_multiplex_out(f_out);
419 recv_exclude_list(f_in);
422 do_server_sender(f_in, f_out, argc, argv);
424 do_server_recv(f_in, f_out, argc, argv);
429 int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
431 struct file_list *flist;
432 int status = 0, status2 = 0;
433 char *local_name = NULL;
434 extern int am_sender;
435 extern int list_only;
436 extern int remote_version;
438 setup_protocol(f_out,f_in);
440 if (remote_version >= 23)
441 io_start_multiplex_in(f_in);
444 extern int cvs_exclude;
445 extern int delete_mode;
446 extern int delete_excluded;
449 if (delete_mode && !delete_excluded)
450 send_exclude_list(f_out);
451 flist = send_file_list(f_out,argc,argv);
453 rprintf(FINFO,"file list sent\n");
455 send_files(flist,f_out,f_in);
458 rprintf(FINFO,"client_run waiting on %d\n",pid);
460 wait_process(pid, &status);
463 if (remote_version >= 24) {
464 /* final goodbye message */
467 exit_cleanup(status);
470 if (argc == 0) list_only = 1;
472 send_exclude_list(f_out);
474 flist = recv_file_list(f_in);
475 if (!flist || flist->count == 0) {
476 rprintf(FINFO,"client: nothing to do\n");
480 local_name = get_local_name(flist,argv[0]);
482 status2 = do_recv(f_in,f_out,flist,local_name);
486 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
488 wait_process(pid, &status);
491 return status | status2;
494 static char *find_colon(char *s)
501 /* now check to see if there is a / in the string before the : - if there is then
502 discard the colon on the assumption that the : is part of a filename */
504 if (p2 && p2 < p) return NULL;
509 static int start_client(int argc, char *argv[])
512 char *shell_machine = NULL;
513 char *shell_path = NULL;
514 char *shell_user = NULL;
517 extern int local_server;
518 extern int am_sender;
519 extern char *shell_cmd;
520 extern int rsync_port;
522 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
525 host = argv[0] + strlen(URL_PREFIX);
526 p = strchr(host,'/');
533 p = strchr(host,':');
535 rsync_port = atoi(p+1);
538 return start_socket_client(host, path, argc-1, argv+1);
541 p = find_colon(argv[0]);
546 return start_socket_client(argv[0], p+2, argc-1, argv+1);
551 exit_cleanup(RERR_SYNTAX);
556 shell_machine = argv[0];
563 p = find_colon(argv[argc-1]);
566 } else if (p[1] == ':') {
568 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
573 exit_cleanup(RERR_SYNTAX);
577 shell_machine = NULL;
578 shell_path = argv[argc-1];
581 shell_machine = argv[argc-1];
588 p = strchr(shell_machine,'@');
591 shell_user = shell_machine;
597 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
598 shell_cmd?shell_cmd:"",
599 shell_machine?shell_machine:"",
600 shell_user?shell_user:"",
601 shell_path?shell_path:"");
604 if (!am_sender && argc > 1) {
606 exit_cleanup(RERR_SYNTAX);
609 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
611 ret = client_run(f_in, f_out, pid, argc, argv);
620 static RETSIGTYPE sigusr1_handler(int val) {
621 exit_cleanup(RERR_SIGNAL);
624 int main(int argc,char *argv[])
627 extern int orig_umask;
629 extern int am_daemon;
630 extern int am_server;
632 signal(SIGUSR1, sigusr1_handler);
634 starttime = time(NULL);
635 am_root = (getuid() == 0);
637 memset(&stats, 0, sizeof(stats));
641 exit_cleanup(RERR_SYNTAX);
644 /* we set a 0 umask so that correct file permissions can be
646 orig_umask = (int)umask(0);
648 if (!parse_arguments(argc, argv, 1)) {
649 exit_cleanup(RERR_SYNTAX);
656 signal(SIGCHLD,SIG_IGN);
657 signal(SIGINT,SIGNAL_CAST sig_int);
658 signal(SIGPIPE,SIGNAL_CAST sig_int);
659 signal(SIGHUP,SIGNAL_CAST sig_int);
660 signal(SIGTERM,SIGNAL_CAST sig_int);
662 /* Initialize push_dir here because on some old systems getcwd
663 (implemented by forking "pwd" and reading its output) doesn't
664 work when there are other child processes. Also, on all systems
665 that implement getcwd that way "pwd" can't be found after chroot. */
669 return daemon_main();
674 exit_cleanup(RERR_SYNTAX);
678 verbose = MAX(verbose,1);
680 #ifndef SUPPORT_LINKS
681 if (!am_server && preserve_links) {
682 rprintf(FERROR,"ERROR: symbolic links not supported\n");
683 exit_cleanup(RERR_UNSUPPORTED);
688 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
691 return start_client(argc, argv);