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;
284 if (preserve_hard_links)
285 init_hard_links(flist);
287 if (pipe(recv_pipe) < 0) {
288 rprintf(FERROR,"pipe failed in do_recv\n");
289 exit_cleanup(RERR_SOCKETIO);
292 if (pipe(error_pipe) < 0) {
293 rprintf(FERROR,"error pipe failed in do_recv\n");
294 exit_cleanup(RERR_SOCKETIO);
299 if ((pid=do_fork()) == 0) {
301 close(error_pipe[0]);
302 if (f_in != f_out) close(f_out);
304 /* we can't let two processes write to the socket at one time */
305 io_multiplexing_close();
307 /* set place to send errors */
308 set_error_fd(error_pipe[1]);
310 recv_files(f_in,flist,local_name,recv_pipe[1]);
318 close(error_pipe[1]);
319 io_close_input(f_in);
320 if (f_in != f_out) close(f_in);
322 io_start_buffering(f_out);
324 io_set_error_fd(error_pipe[0]);
326 generate_files(f_out,flist,local_name,recv_pipe[0]);
329 wait_process(pid, &status);
334 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
337 struct file_list *flist;
338 char *local_name=NULL;
340 extern int delete_mode;
341 extern int delete_excluded;
342 extern int am_daemon;
345 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
351 if (!am_daemon && !push_dir(dir, 0)) {
352 rprintf(FERROR,"push_dir %s : %s (4)\n",
353 dir,strerror(errno));
354 exit_cleanup(RERR_FILESELECT);
358 if (delete_mode && !delete_excluded)
359 recv_exclude_list(f_in);
361 flist = recv_file_list(f_in);
363 rprintf(FERROR,"server_recv: recv_file_list error\n");
364 exit_cleanup(RERR_FILESELECT);
368 if (strcmp(dir,".")) {
369 argv[0] += strlen(dir);
370 if (argv[0][0] == '/') argv[0]++;
372 local_name = get_local_name(flist,argv[0]);
375 status = do_recv(f_in,f_out,flist,local_name);
376 exit_cleanup(status);
380 void start_server(int f_in, int f_out, int argc, char *argv[])
382 extern int cvs_exclude;
383 extern int am_sender;
385 setup_protocol(f_out, f_in);
388 recv_exclude_list(f_in);
391 do_server_sender(f_in, f_out, argc, argv);
393 do_server_recv(f_in, f_out, argc, argv);
398 int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
400 struct file_list *flist;
401 int status = 0, status2 = 0;
402 char *local_name = NULL;
403 extern int am_sender;
404 extern int list_only;
406 setup_protocol(f_out,f_in);
409 extern int cvs_exclude;
410 extern int delete_mode;
411 extern int delete_excluded;
414 if (delete_mode && !delete_excluded)
415 send_exclude_list(f_out);
416 flist = send_file_list(f_out,argc,argv);
418 rprintf(FINFO,"file list sent\n");
420 send_files(flist,f_out,f_in);
423 rprintf(FINFO,"client_run waiting on %d\n",pid);
425 wait_process(pid, &status);
428 exit_cleanup(status);
431 if (argc == 0) list_only = 1;
433 send_exclude_list(f_out);
435 flist = recv_file_list(f_in);
436 if (!flist || flist->count == 0) {
437 rprintf(FINFO,"client: nothing to do\n");
441 local_name = get_local_name(flist,argv[0]);
443 status2 = do_recv(f_in,f_out,flist,local_name);
447 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
449 wait_process(pid, &status);
452 return status | status2;
455 static char *find_colon(char *s)
462 /* now check to see if there is a / in the string before the : - if there is then
463 discard the colon on the assumption that the : is part of a filename */
465 if (p2 && p2 < p) return NULL;
470 static int start_client(int argc, char *argv[])
473 char *shell_machine = NULL;
474 char *shell_path = NULL;
475 char *shell_user = NULL;
478 extern int local_server;
479 extern int am_sender;
480 extern char *shell_cmd;
481 extern int rsync_port;
483 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
486 host = argv[0] + strlen(URL_PREFIX);
487 p = strchr(host,'/');
494 p = strchr(host,':');
496 rsync_port = atoi(p+1);
499 return start_socket_client(host, path, argc-1, argv+1);
502 p = find_colon(argv[0]);
507 return start_socket_client(argv[0], p+2, argc-1, argv+1);
512 exit_cleanup(RERR_SYNTAX);
517 shell_machine = argv[0];
524 p = find_colon(argv[argc-1]);
527 } else if (p[1] == ':') {
529 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
534 exit_cleanup(RERR_SYNTAX);
538 shell_machine = NULL;
539 shell_path = argv[argc-1];
542 shell_machine = argv[argc-1];
549 p = strchr(shell_machine,'@');
552 shell_user = shell_machine;
558 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
559 shell_cmd?shell_cmd:"",
560 shell_machine?shell_machine:"",
561 shell_user?shell_user:"",
562 shell_path?shell_path:"");
565 if (!am_sender && argc > 1) {
567 exit_cleanup(RERR_SYNTAX);
570 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
572 ret = client_run(f_in, f_out, pid, argc, argv);
581 static RETSIGTYPE sigusr1_handler(int val) {
582 exit_cleanup(RERR_SIGNAL);
585 int main(int argc,char *argv[])
588 extern int orig_umask;
590 extern int am_daemon;
591 extern int am_server;
593 signal(SIGUSR1, sigusr1_handler);
595 starttime = time(NULL);
596 am_root = (getuid() == 0);
598 memset(&stats, 0, sizeof(stats));
602 exit_cleanup(RERR_SYNTAX);
605 /* we set a 0 umask so that correct file permissions can be
607 orig_umask = (int)umask(0);
609 if (!parse_arguments(argc, argv, 1)) {
610 exit_cleanup(RERR_SYNTAX);
617 signal(SIGCHLD,SIG_IGN);
618 signal(SIGINT,SIGNAL_CAST sig_int);
619 signal(SIGPIPE,SIGNAL_CAST sig_int);
620 signal(SIGHUP,SIGNAL_CAST sig_int);
621 signal(SIGTERM,SIGNAL_CAST sig_int);
623 /* Initialize push_dir here because on some old systems getcwd
624 (implemented by forking "pwd" and reading its output) doesn't
625 work when there are other child processes. Also, on all systems
626 that implement getcwd that way "pwd" can't be found after chroot. */
630 return daemon_main();
635 exit_cleanup(RERR_SYNTAX);
639 verbose = MAX(verbose,1);
641 #ifndef SUPPORT_LINKS
642 if (!am_server && preserve_links) {
643 rprintf(FERROR,"ERROR: symbolic links not supported\n");
644 exit_cleanup(RERR_UNSUPPORTED);
649 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
652 return start_client(argc, argv);