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;
287 if (preserve_hard_links)
288 init_hard_links(flist);
291 /* I moved this here from recv_files() to prevent a race condition */
292 if (recurse && delete_mode && !local_name && flist->count>0) {
297 if (fd_pair(recv_pipe) < 0) {
298 rprintf(FERROR,"pipe failed in do_recv\n");
299 exit_cleanup(RERR_SOCKETIO);
302 if (fd_pair(error_pipe) < 0) {
303 rprintf(FERROR,"error pipe failed in do_recv\n");
304 exit_cleanup(RERR_SOCKETIO);
309 if ((pid=do_fork()) == 0) {
311 close(error_pipe[0]);
312 if (f_in != f_out) close(f_out);
314 /* we can't let two processes write to the socket at one time */
315 io_multiplexing_close();
317 /* set place to send errors */
318 set_error_fd(error_pipe[1]);
320 recv_files(f_in,flist,local_name,recv_pipe[1]);
328 close(error_pipe[1]);
329 io_close_input(f_in);
330 if (f_in != f_out) close(f_in);
332 io_start_buffering(f_out);
334 io_set_error_fd(error_pipe[0]);
336 generate_files(f_out,flist,local_name,recv_pipe[0]);
339 wait_process(pid, &status);
344 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
347 struct file_list *flist;
348 char *local_name=NULL;
350 extern int delete_mode;
351 extern int delete_excluded;
352 extern int am_daemon;
353 extern int module_id;
354 extern int am_sender;
357 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
359 if (am_daemon && lp_read_only(module_id) && !am_sender) {
360 rprintf(FERROR,"ERROR: module is read only\n");
361 exit_cleanup(RERR_SYNTAX);
370 if (!am_daemon && !push_dir(dir, 0)) {
371 rprintf(FERROR,"push_dir %s : %s (4)\n",
372 dir,strerror(errno));
373 exit_cleanup(RERR_FILESELECT);
377 if (delete_mode && !delete_excluded)
378 recv_exclude_list(f_in);
380 flist = recv_file_list(f_in);
382 rprintf(FERROR,"server_recv: recv_file_list error\n");
383 exit_cleanup(RERR_FILESELECT);
387 if (strcmp(dir,".")) {
388 argv[0] += strlen(dir);
389 if (argv[0][0] == '/') argv[0]++;
391 local_name = get_local_name(flist,argv[0]);
394 status = do_recv(f_in,f_out,flist,local_name);
395 exit_cleanup(status);
399 void start_server(int f_in, int f_out, int argc, char *argv[])
401 extern int cvs_exclude;
402 extern int am_sender;
403 extern int remote_version;
405 setup_protocol(f_out, f_in);
407 if (remote_version >= 23)
408 io_start_multiplex_out(f_out);
411 recv_exclude_list(f_in);
414 do_server_sender(f_in, f_out, argc, argv);
416 do_server_recv(f_in, f_out, argc, argv);
421 int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
423 struct file_list *flist;
424 int status = 0, status2 = 0;
425 char *local_name = NULL;
426 extern int am_sender;
427 extern int list_only;
428 extern int remote_version;
430 setup_protocol(f_out,f_in);
432 if (remote_version >= 23)
433 io_start_multiplex_in(f_in);
436 extern int cvs_exclude;
437 extern int delete_mode;
438 extern int delete_excluded;
441 if (delete_mode && !delete_excluded)
442 send_exclude_list(f_out);
443 flist = send_file_list(f_out,argc,argv);
445 rprintf(FINFO,"file list sent\n");
447 send_files(flist,f_out,f_in);
450 rprintf(FINFO,"client_run waiting on %d\n",pid);
452 wait_process(pid, &status);
455 exit_cleanup(status);
458 if (argc == 0) list_only = 1;
460 send_exclude_list(f_out);
462 flist = recv_file_list(f_in);
463 if (!flist || flist->count == 0) {
464 rprintf(FINFO,"client: nothing to do\n");
468 local_name = get_local_name(flist,argv[0]);
470 status2 = do_recv(f_in,f_out,flist,local_name);
474 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
476 wait_process(pid, &status);
479 return status | status2;
482 static char *find_colon(char *s)
489 /* now check to see if there is a / in the string before the : - if there is then
490 discard the colon on the assumption that the : is part of a filename */
492 if (p2 && p2 < p) return NULL;
497 static int start_client(int argc, char *argv[])
500 char *shell_machine = NULL;
501 char *shell_path = NULL;
502 char *shell_user = NULL;
505 extern int local_server;
506 extern int am_sender;
507 extern char *shell_cmd;
508 extern int rsync_port;
510 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
513 host = argv[0] + strlen(URL_PREFIX);
514 p = strchr(host,'/');
521 p = strchr(host,':');
523 rsync_port = atoi(p+1);
526 return start_socket_client(host, path, argc-1, argv+1);
529 p = find_colon(argv[0]);
534 return start_socket_client(argv[0], p+2, argc-1, argv+1);
539 exit_cleanup(RERR_SYNTAX);
544 shell_machine = argv[0];
551 p = find_colon(argv[argc-1]);
554 } else if (p[1] == ':') {
556 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
561 exit_cleanup(RERR_SYNTAX);
565 shell_machine = NULL;
566 shell_path = argv[argc-1];
569 shell_machine = argv[argc-1];
576 p = strchr(shell_machine,'@');
579 shell_user = shell_machine;
585 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
586 shell_cmd?shell_cmd:"",
587 shell_machine?shell_machine:"",
588 shell_user?shell_user:"",
589 shell_path?shell_path:"");
592 if (!am_sender && argc > 1) {
594 exit_cleanup(RERR_SYNTAX);
597 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
599 ret = client_run(f_in, f_out, pid, argc, argv);
608 static RETSIGTYPE sigusr1_handler(int val) {
609 exit_cleanup(RERR_SIGNAL);
612 int main(int argc,char *argv[])
615 extern int orig_umask;
617 extern int am_daemon;
618 extern int am_server;
620 signal(SIGUSR1, sigusr1_handler);
622 starttime = time(NULL);
623 am_root = (getuid() == 0);
625 memset(&stats, 0, sizeof(stats));
629 exit_cleanup(RERR_SYNTAX);
632 /* we set a 0 umask so that correct file permissions can be
634 orig_umask = (int)umask(0);
636 if (!parse_arguments(argc, argv, 1)) {
637 exit_cleanup(RERR_SYNTAX);
644 signal(SIGCHLD,SIG_IGN);
645 signal(SIGINT,SIGNAL_CAST sig_int);
646 signal(SIGPIPE,SIGNAL_CAST sig_int);
647 signal(SIGHUP,SIGNAL_CAST sig_int);
648 signal(SIGTERM,SIGNAL_CAST sig_int);
650 /* Initialize push_dir here because on some old systems getcwd
651 (implemented by forking "pwd" and reading its output) doesn't
652 work when there are other child processes. Also, on all systems
653 that implement getcwd that way "pwd" can't be found after chroot. */
657 return daemon_main();
662 exit_cleanup(RERR_SYNTAX);
666 verbose = MAX(verbose,1);
668 #ifndef SUPPORT_LINKS
669 if (!am_server && preserve_links) {
670 rprintf(FERROR,"ERROR: symbolic links not supported\n");
671 exit_cleanup(RERR_UNSUPPORTED);
676 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
679 return start_client(argc, argv);