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.
26 extern int csum_length;
30 static void report(int f)
32 time_t t = time(NULL);
39 log_exit(0, __FILE__, __LINE__);
40 if (f == -1 || !am_sender) return;
45 if (am_server && !am_sender) return;
47 if (am_server && am_sender) {
48 write_longint(f,stats.total_read);
49 write_longint(f,stats.total_written);
50 write_longint(f,stats.total_size);
56 stats.total_written = read_longint(f);
58 stats.total_size = read_longint(f);
63 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
64 rprintf(FINFO,"Number of files transferred: %d\n",
65 stats.num_transferred_files);
66 rprintf(FINFO,"Total file size: %.0f bytes\n",
67 (double)stats.total_size);
68 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
69 (double)stats.total_transferred_size);
70 rprintf(FINFO,"Literal data: %.0f bytes\n",
71 (double)stats.literal_data);
72 rprintf(FINFO,"Matched data: %.0f bytes\n",
73 (double)stats.matched_data);
74 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
75 rprintf(FINFO,"Total bytes written: %.0f\n",
76 (double)stats.total_written);
77 rprintf(FINFO,"Total bytes read: %.0f\n\n",
78 (double)stats.total_read);
81 rprintf(FINFO,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
82 (double)stats.total_written,
83 (double)stats.total_read,
84 (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
85 rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
86 (double)stats.total_size,
87 (1.0*stats.total_size)/(stats.total_written+stats.total_read));
94 static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
99 extern int local_server;
100 extern char *rsync_path;
104 cmd = getenv(RSYNC_RSH_ENV);
111 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
116 /* remsh (on HPUX) takes the arguments the other way around */
117 args[argc++] = machine;
127 args[argc++] = machine;
130 args[argc++] = rsync_path;
132 server_options(args,&argc);
143 rprintf(FINFO,"cmd=");
145 rprintf(FINFO,"%s ",args[i]);
150 ret = local_child(argc, args, f_in, f_out);
152 ret = piped_child(args,f_in,f_out);
160 out_of_memory("do_cmd");
161 return 0; /* not reached */
167 static char *get_local_name(struct file_list *flist,char *name)
170 extern int orig_umask;
173 rprintf(FINFO,"get_local_name count=%d %s\n",
174 flist->count, NS(name));
179 if (do_stat(name,&st) == 0) {
180 if (S_ISDIR(st.st_mode)) {
181 if (!push_dir(name, 0)) {
182 rprintf(FERROR,"push_dir %s : %s (1)\n",
183 name,strerror(errno));
184 exit_cleanup(RERR_FILESELECT);
188 if (flist->count > 1) {
189 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
190 exit_cleanup(RERR_FILESELECT);
195 if (flist->count == 1)
198 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
199 rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
200 exit_cleanup(RERR_FILEIO);
203 rprintf(FINFO,"created directory %s\n",name);
206 if (!push_dir(name, 0)) {
207 rprintf(FERROR,"push_dir %s : %s (2)\n",
208 name,strerror(errno));
209 exit_cleanup(RERR_FILESELECT);
218 static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
221 struct file_list *flist;
223 extern int relative_paths;
227 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
229 if (!relative_paths && !push_dir(dir, 0)) {
230 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
231 exit_cleanup(RERR_FILESELECT);
236 if (strcmp(dir,".")) {
238 if (strcmp(dir,"/") == 0)
244 if (argc == 0 && recurse) {
250 set_nonblocking(f_out);
252 set_nonblocking(f_in);
254 flist = send_file_list(f_out,argc,argv);
255 if (!flist || flist->count == 0) {
259 send_files(flist,f_out,f_in);
266 static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
271 extern int preserve_hard_links;
273 if (preserve_hard_links)
274 init_hard_links(flist);
276 if (pipe(recv_pipe) < 0) {
277 rprintf(FERROR,"pipe failed in do_recv\n");
278 exit_cleanup(RERR_SOCKETIO);
283 if ((pid=do_fork()) == 0) {
285 if (f_in != f_out) close(f_out);
287 set_nonblocking(f_in);
288 set_nonblocking(recv_pipe[1]);
290 recv_files(f_in,flist,local_name,recv_pipe[1]);
298 io_close_input(f_in);
299 if (f_in != f_out) close(f_in);
301 set_nonblocking(f_out);
302 set_nonblocking(recv_pipe[0]);
304 io_start_buffering(f_out);
306 generate_files(f_out,flist,local_name,recv_pipe[0]);
309 waitpid(pid, &status, 0);
314 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
317 struct file_list *flist;
318 char *local_name=NULL;
320 extern int delete_mode;
321 extern int am_daemon;
324 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
330 if (!am_daemon && !push_dir(dir, 0)) {
331 rprintf(FERROR,"push_dir %s : %s (4)\n",
332 dir,strerror(errno));
333 exit_cleanup(RERR_FILESELECT);
338 recv_exclude_list(f_in);
340 flist = recv_file_list(f_in);
341 if (!flist || flist->count == 0) {
342 rprintf(FERROR,"server_recv: nothing to do\n");
343 exit_cleanup(RERR_FILESELECT);
347 if (strcmp(dir,".")) {
348 argv[0] += strlen(dir);
349 if (argv[0][0] == '/') argv[0]++;
351 local_name = get_local_name(flist,argv[0]);
354 status = do_recv(f_in,f_out,flist,local_name);
355 exit_cleanup(status);
359 void start_server(int f_in, int f_out, int argc, char *argv[])
361 extern int cvs_exclude;
362 extern int am_sender;
364 set_nonblocking(f_out);
366 set_nonblocking(f_in);
368 setup_protocol(f_out, f_in);
371 recv_exclude_list(f_in);
374 do_server_sender(f_in, f_out, argc, argv);
376 do_server_recv(f_in, f_out, argc, argv);
381 int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
383 struct file_list *flist;
384 int status = 0, status2 = 0;
385 char *local_name = NULL;
386 extern int am_sender;
387 extern int list_only;
389 setup_protocol(f_out,f_in);
392 extern int cvs_exclude;
393 extern int delete_mode;
397 send_exclude_list(f_out);
398 flist = send_file_list(f_out,argc,argv);
400 rprintf(FINFO,"file list sent\n");
402 set_nonblocking(f_out);
404 set_nonblocking(f_in);
406 send_files(flist,f_out,f_in);
409 rprintf(FINFO,"client_run waiting on %d\n",pid);
411 waitpid(pid, &status, 0);
414 exit_cleanup(status);
417 if (argc == 0) list_only = 1;
419 send_exclude_list(f_out);
421 flist = recv_file_list(f_in);
422 if (!flist || flist->count == 0) {
423 rprintf(FINFO,"client: nothing to do\n");
427 local_name = get_local_name(flist,argv[0]);
429 status2 = do_recv(f_in,f_out,flist,local_name);
433 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
435 waitpid(pid, &status, 0);
438 return status | status2;
441 static char *find_colon(char *s)
448 /* now check to see if there is a / in the string before the : - if there is then
449 discard the colon on the assumption that the : is part of a filename */
451 if (p2 && p2 < p) return NULL;
456 static int start_client(int argc, char *argv[])
459 char *shell_machine = NULL;
460 char *shell_path = NULL;
461 char *shell_user = NULL;
464 extern int local_server;
465 extern int am_sender;
466 extern char *shell_cmd;
467 extern int rsync_port;
469 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
472 host = argv[0] + strlen(URL_PREFIX);
473 p = strchr(host,'/');
480 p = strchr(host,':');
482 rsync_port = atoi(p+1);
485 return start_socket_client(host, path, argc-1, argv+1);
488 p = find_colon(argv[0]);
493 return start_socket_client(argv[0], p+2, argc-1, argv+1);
498 exit_cleanup(RERR_SYNTAX);
503 shell_machine = argv[0];
510 p = find_colon(argv[argc-1]);
513 } else if (p[1] == ':') {
515 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
520 exit_cleanup(RERR_SYNTAX);
524 shell_machine = NULL;
525 shell_path = argv[argc-1];
528 shell_machine = argv[argc-1];
535 p = strchr(shell_machine,'@');
538 shell_user = shell_machine;
544 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
545 shell_cmd?shell_cmd:"",
546 shell_machine?shell_machine:"",
547 shell_user?shell_user:"",
548 shell_path?shell_path:"");
551 if (!am_sender && argc > 1) {
553 exit_cleanup(RERR_SYNTAX);
556 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
558 ret = client_run(f_in, f_out, pid, argc, argv);
567 static RETSIGTYPE sigusr1_handler(int val) {
568 exit_cleanup(RERR_SIGNAL);
571 int main(int argc,char *argv[])
574 extern int orig_umask;
576 extern int am_daemon;
577 extern int am_server;
579 signal(SIGUSR1, sigusr1_handler);
581 starttime = time(NULL);
582 am_root = (getuid() == 0);
584 memset(&stats, 0, sizeof(stats));
588 exit_cleanup(RERR_SYNTAX);
591 /* we set a 0 umask so that correct file permissions can be
593 orig_umask = (int)umask(0);
595 if (!parse_arguments(argc, argv, 1)) {
596 exit_cleanup(RERR_SYNTAX);
603 signal(SIGCHLD,SIG_IGN);
604 signal(SIGINT,SIGNAL_CAST sig_int);
605 signal(SIGPIPE,SIGNAL_CAST sig_int);
606 signal(SIGHUP,SIGNAL_CAST sig_int);
607 signal(SIGTERM,SIGNAL_CAST sig_int);
609 /* Initialize push_dir here because on some old systems getcwd
610 (implemented by forking "pwd" and reading its output) doesn't
611 work when there are other child processes. Also, on all systems
612 that implement getcwd that way "pwd" can't be found after chroot. */
616 return daemon_main();
621 exit_cleanup(RERR_SYNTAX);
625 verbose = MAX(verbose,1);
627 #ifndef SUPPORT_LINKS
628 if (!am_server && preserve_links) {
629 rprintf(FERROR,"ERROR: symbolic links not supported\n");
630 exit_cleanup(RERR_UNSUPPORTED);
635 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
638 return start_client(argc, argv);