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;
44 if (verbose && am_sender) {
45 write_longint(f,stats.total_read);
46 write_longint(f,stats.total_written);
47 write_longint(f,stats.total_size);
52 /* this is the client */
54 if (!am_sender && verbose) {
55 /* note that if (!verbose && do_stats) then these values will
56 be taken from the receiver side's copy. The total size
57 is identical but the bytes read and written are slightly
58 different. It's done this way to avoid modifying the
59 protocol to support --stats without -v. */
60 stats.total_written = read_longint(f);
61 stats.total_read = read_longint(f);
62 stats.total_size = read_longint(f);
64 /* when the total_read was set above just now it would not
65 have included the last two longints, but the last
66 read_longint would have compensated for one of them.
67 Compensate for the other one too by adding 8. */
68 stats.total_read += sizeof(int64);
72 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
73 rprintf(FINFO,"Number of files transferred: %d\n",
74 stats.num_transferred_files);
75 rprintf(FINFO,"Total file size: %.0f bytes\n",
76 (double)stats.total_size);
77 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
78 (double)stats.total_transferred_size);
79 rprintf(FINFO,"Literal data: %.0f bytes\n",
80 (double)stats.literal_data);
81 rprintf(FINFO,"Matched data: %.0f bytes\n",
82 (double)stats.matched_data);
83 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
84 rprintf(FINFO,"Total bytes written: %.0f\n",
85 (double)stats.total_written);
86 rprintf(FINFO,"Total bytes read: %.0f\n\n",
87 (double)stats.total_read);
90 if (verbose || do_stats) {
91 rprintf(FINFO,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
92 (double)stats.total_written,
93 (double)stats.total_read,
94 (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
95 rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
96 (double)stats.total_size,
97 (1.0*stats.total_size)/(stats.total_written+stats.total_read));
105 static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
110 extern int local_server;
111 extern char *rsync_path;
115 cmd = getenv(RSYNC_RSH_ENV);
122 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
127 /* remsh (on HPUX) takes the arguments the other way around */
128 args[argc++] = machine;
138 args[argc++] = machine;
141 args[argc++] = rsync_path;
143 server_options(args,&argc);
154 rprintf(FINFO,"cmd=");
156 rprintf(FINFO,"%s ",args[i]);
161 ret = local_child(argc, args, f_in, f_out);
163 ret = piped_child(args,f_in,f_out);
171 out_of_memory("do_cmd");
172 return 0; /* not reached */
178 static char *get_local_name(struct file_list *flist,char *name)
181 extern int orig_umask;
184 rprintf(FINFO,"get_local_name count=%d %s\n",
185 flist->count, NS(name));
190 if (do_stat(name,&st) == 0) {
191 if (S_ISDIR(st.st_mode)) {
192 if (!push_dir(name, 0)) {
193 rprintf(FERROR,"push_dir %s : %s (1)\n",
194 name,strerror(errno));
195 exit_cleanup(RERR_FILESELECT);
199 if (flist->count > 1) {
200 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
201 exit_cleanup(RERR_FILESELECT);
206 if (flist->count == 1)
209 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
210 rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
211 exit_cleanup(RERR_FILEIO);
214 rprintf(FINFO,"created directory %s\n",name);
217 if (!push_dir(name, 0)) {
218 rprintf(FERROR,"push_dir %s : %s (2)\n",
219 name,strerror(errno));
220 exit_cleanup(RERR_FILESELECT);
229 static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
232 struct file_list *flist;
234 extern int relative_paths;
238 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
240 if (!relative_paths && !push_dir(dir, 0)) {
241 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
242 exit_cleanup(RERR_FILESELECT);
247 if (strcmp(dir,".")) {
249 if (strcmp(dir,"/") == 0)
255 if (argc == 0 && recurse) {
261 set_nonblocking(f_out);
263 set_nonblocking(f_in);
265 flist = send_file_list(f_out,argc,argv);
266 if (!flist || flist->count == 0) {
270 send_files(flist,f_out,f_in);
277 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);
294 if ((pid=do_fork()) == 0) {
296 if (f_in != f_out) close(f_out);
298 set_nonblocking(f_in);
299 set_nonblocking(recv_pipe[1]);
301 recv_files(f_in,flist,local_name,recv_pipe[1]);
309 io_close_input(f_in);
310 if (f_in != f_out) close(f_in);
312 set_nonblocking(f_out);
313 set_nonblocking(recv_pipe[0]);
315 io_start_buffering(f_out);
317 generate_files(f_out,flist,local_name,recv_pipe[0]);
320 waitpid(pid, &status, 0);
325 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
328 struct file_list *flist;
329 char *local_name=NULL;
331 extern int delete_mode;
332 extern int am_daemon;
335 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
341 if (!am_daemon && !push_dir(dir, 0)) {
342 rprintf(FERROR,"push_dir %s : %s (4)\n",
343 dir,strerror(errno));
344 exit_cleanup(RERR_FILESELECT);
349 recv_exclude_list(f_in);
351 flist = recv_file_list(f_in);
352 if (!flist || flist->count == 0) {
353 rprintf(FERROR,"server_recv: nothing to do\n");
354 exit_cleanup(RERR_FILESELECT);
358 if (strcmp(dir,".")) {
359 argv[0] += strlen(dir);
360 if (argv[0][0] == '/') argv[0]++;
362 local_name = get_local_name(flist,argv[0]);
365 status = do_recv(f_in,f_out,flist,local_name);
366 exit_cleanup(status);
370 void start_server(int f_in, int f_out, int argc, char *argv[])
372 extern int cvs_exclude;
373 extern int am_sender;
375 set_nonblocking(f_out);
377 set_nonblocking(f_in);
379 setup_protocol(f_out, f_in);
382 recv_exclude_list(f_in);
385 do_server_sender(f_in, f_out, argc, argv);
387 do_server_recv(f_in, f_out, argc, argv);
392 int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
394 struct file_list *flist;
395 int status = 0, status2 = 0;
396 char *local_name = NULL;
397 extern int am_sender;
398 extern int list_only;
400 setup_protocol(f_out,f_in);
403 extern int cvs_exclude;
404 extern int delete_mode;
408 send_exclude_list(f_out);
409 flist = send_file_list(f_out,argc,argv);
411 rprintf(FINFO,"file list sent\n");
413 set_nonblocking(f_out);
415 set_nonblocking(f_in);
417 send_files(flist,f_out,f_in);
420 rprintf(FINFO,"client_run waiting on %d\n",pid);
422 waitpid(pid, &status, 0);
425 exit_cleanup(status);
428 if (argc == 0) list_only = 1;
430 send_exclude_list(f_out);
432 flist = recv_file_list(f_in);
433 if (!flist || flist->count == 0) {
434 rprintf(FINFO,"client: nothing to do\n");
438 local_name = get_local_name(flist,argv[0]);
440 status2 = do_recv(f_in,f_out,flist,local_name);
444 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
446 waitpid(pid, &status, 0);
449 return status | status2;
452 static char *find_colon(char *s)
459 /* now check to see if there is a / in the string before the : - if there is then
460 discard the colon on the assumption that the : is part of a filename */
462 if (p2 && p2 < p) return NULL;
467 static int start_client(int argc, char *argv[])
470 char *shell_machine = NULL;
471 char *shell_path = NULL;
472 char *shell_user = NULL;
475 extern int local_server;
476 extern int am_sender;
477 extern char *shell_cmd;
478 extern int rsync_port;
480 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
483 host = argv[0] + strlen(URL_PREFIX);
484 p = strchr(host,'/');
491 p = strchr(host,':');
493 rsync_port = atoi(p+1);
496 return start_socket_client(host, path, argc-1, argv+1);
499 p = find_colon(argv[0]);
504 return start_socket_client(argv[0], p+2, argc-1, argv+1);
509 exit_cleanup(RERR_SYNTAX);
514 shell_machine = argv[0];
521 p = find_colon(argv[argc-1]);
524 } else if (p[1] == ':') {
526 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
531 exit_cleanup(RERR_SYNTAX);
535 shell_machine = NULL;
536 shell_path = argv[argc-1];
539 shell_machine = argv[argc-1];
546 p = strchr(shell_machine,'@');
549 shell_user = shell_machine;
555 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
556 shell_cmd?shell_cmd:"",
557 shell_machine?shell_machine:"",
558 shell_user?shell_user:"",
559 shell_path?shell_path:"");
562 if (!am_sender && argc > 1) {
564 exit_cleanup(RERR_SYNTAX);
567 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
569 ret = client_run(f_in, f_out, pid, argc, argv);
578 static RETSIGTYPE sigusr1_handler(int val) {
579 exit_cleanup(RERR_SIGNAL);
582 int main(int argc,char *argv[])
585 extern int orig_umask;
587 extern int am_daemon;
588 extern int am_server;
590 signal(SIGUSR1, sigusr1_handler);
592 starttime = time(NULL);
593 am_root = (getuid() == 0);
595 memset(&stats, 0, sizeof(stats));
599 exit_cleanup(RERR_SYNTAX);
602 /* we set a 0 umask so that correct file permissions can be
604 orig_umask = (int)umask(0);
606 if (!parse_arguments(argc, argv, 1)) {
607 exit_cleanup(RERR_SYNTAX);
614 signal(SIGCHLD,SIG_IGN);
615 signal(SIGINT,SIGNAL_CAST sig_int);
616 signal(SIGPIPE,SIGNAL_CAST sig_int);
617 signal(SIGHUP,SIGNAL_CAST sig_int);
618 signal(SIGTERM,SIGNAL_CAST sig_int);
620 /* Initialize push_dir here because on some old systems getcwd
621 (implemented by forking "pwd" and reading its output) doesn't
622 work when there are other child processes. Also, on all systems
623 that implement getcwd that way "pwd" can't be found after chroot. */
627 return daemon_main();
632 exit_cleanup(RERR_SYNTAX);
636 verbose = MAX(verbose,1);
638 #ifndef SUPPORT_LINKS
639 if (!am_server && preserve_links) {
640 rprintf(FERROR,"ERROR: symbolic links not supported\n");
641 exit_cleanup(RERR_UNSUPPORTED);
646 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
649 return start_client(argc, argv);