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)
281 extern int preserve_hard_links;
283 if (preserve_hard_links)
284 init_hard_links(flist);
286 if (pipe(recv_pipe) < 0) {
287 rprintf(FERROR,"pipe failed in do_recv\n");
288 exit_cleanup(RERR_SOCKETIO);
293 if ((pid=do_fork()) == 0) {
295 if (f_in != f_out) close(f_out);
297 recv_files(f_in,flist,local_name,recv_pipe[1]);
305 io_close_input(f_in);
306 if (f_in != f_out) close(f_in);
308 io_start_buffering(f_out);
310 generate_files(f_out,flist,local_name,recv_pipe[0]);
313 wait_process(pid, &status);
318 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
321 struct file_list *flist;
322 char *local_name=NULL;
324 extern int delete_mode;
325 extern int delete_excluded;
326 extern int am_daemon;
329 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
335 if (!am_daemon && !push_dir(dir, 0)) {
336 rprintf(FERROR,"push_dir %s : %s (4)\n",
337 dir,strerror(errno));
338 exit_cleanup(RERR_FILESELECT);
342 if (delete_mode && !delete_excluded)
343 recv_exclude_list(f_in);
345 flist = recv_file_list(f_in);
347 rprintf(FERROR,"server_recv: recv_file_list error\n");
348 exit_cleanup(RERR_FILESELECT);
352 if (strcmp(dir,".")) {
353 argv[0] += strlen(dir);
354 if (argv[0][0] == '/') argv[0]++;
356 local_name = get_local_name(flist,argv[0]);
359 status = do_recv(f_in,f_out,flist,local_name);
360 exit_cleanup(status);
364 void start_server(int f_in, int f_out, int argc, char *argv[])
366 extern int cvs_exclude;
367 extern int am_sender;
369 setup_protocol(f_out, f_in);
372 recv_exclude_list(f_in);
375 do_server_sender(f_in, f_out, argc, argv);
377 do_server_recv(f_in, f_out, argc, argv);
382 int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
384 struct file_list *flist;
385 int status = 0, status2 = 0;
386 char *local_name = NULL;
387 extern int am_sender;
388 extern int list_only;
390 setup_protocol(f_out,f_in);
393 extern int cvs_exclude;
394 extern int delete_mode;
395 extern int delete_excluded;
398 if (delete_mode && !delete_excluded)
399 send_exclude_list(f_out);
400 flist = send_file_list(f_out,argc,argv);
402 rprintf(FINFO,"file list sent\n");
404 send_files(flist,f_out,f_in);
407 rprintf(FINFO,"client_run waiting on %d\n",pid);
409 wait_process(pid, &status);
412 exit_cleanup(status);
415 if (argc == 0) list_only = 1;
417 send_exclude_list(f_out);
419 flist = recv_file_list(f_in);
420 if (!flist || flist->count == 0) {
421 rprintf(FINFO,"client: nothing to do\n");
425 local_name = get_local_name(flist,argv[0]);
427 status2 = do_recv(f_in,f_out,flist,local_name);
431 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
433 wait_process(pid, &status);
436 return status | status2;
439 static char *find_colon(char *s)
446 /* now check to see if there is a / in the string before the : - if there is then
447 discard the colon on the assumption that the : is part of a filename */
449 if (p2 && p2 < p) return NULL;
454 static int start_client(int argc, char *argv[])
457 char *shell_machine = NULL;
458 char *shell_path = NULL;
459 char *shell_user = NULL;
462 extern int local_server;
463 extern int am_sender;
464 extern char *shell_cmd;
465 extern int rsync_port;
467 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
470 host = argv[0] + strlen(URL_PREFIX);
471 p = strchr(host,'/');
478 p = strchr(host,':');
480 rsync_port = atoi(p+1);
483 return start_socket_client(host, path, argc-1, argv+1);
486 p = find_colon(argv[0]);
491 return start_socket_client(argv[0], p+2, argc-1, argv+1);
496 exit_cleanup(RERR_SYNTAX);
501 shell_machine = argv[0];
508 p = find_colon(argv[argc-1]);
511 } else if (p[1] == ':') {
513 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
518 exit_cleanup(RERR_SYNTAX);
522 shell_machine = NULL;
523 shell_path = argv[argc-1];
526 shell_machine = argv[argc-1];
533 p = strchr(shell_machine,'@');
536 shell_user = shell_machine;
542 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
543 shell_cmd?shell_cmd:"",
544 shell_machine?shell_machine:"",
545 shell_user?shell_user:"",
546 shell_path?shell_path:"");
549 if (!am_sender && argc > 1) {
551 exit_cleanup(RERR_SYNTAX);
554 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
556 ret = client_run(f_in, f_out, pid, argc, argv);
565 static RETSIGTYPE sigusr1_handler(int val) {
566 exit_cleanup(RERR_SIGNAL);
569 int main(int argc,char *argv[])
572 extern int orig_umask;
574 extern int am_daemon;
575 extern int am_server;
577 signal(SIGUSR1, sigusr1_handler);
579 starttime = time(NULL);
580 am_root = (getuid() == 0);
582 memset(&stats, 0, sizeof(stats));
586 exit_cleanup(RERR_SYNTAX);
589 /* we set a 0 umask so that correct file permissions can be
591 orig_umask = (int)umask(0);
593 if (!parse_arguments(argc, argv, 1)) {
594 exit_cleanup(RERR_SYNTAX);
601 signal(SIGCHLD,SIG_IGN);
602 signal(SIGINT,SIGNAL_CAST sig_int);
603 signal(SIGPIPE,SIGNAL_CAST sig_int);
604 signal(SIGHUP,SIGNAL_CAST sig_int);
605 signal(SIGTERM,SIGNAL_CAST sig_int);
607 /* Initialize push_dir here because on some old systems getcwd
608 (implemented by forking "pwd" and reading its output) doesn't
609 work when there are other child processes. Also, on all systems
610 that implement getcwd that way "pwd" can't be found after chroot. */
614 return daemon_main();
619 exit_cleanup(RERR_SYNTAX);
623 verbose = MAX(verbose,1);
625 #ifndef SUPPORT_LINKS
626 if (!am_server && preserve_links) {
627 rprintf(FERROR,"ERROR: symbolic links not supported\n");
628 exit_cleanup(RERR_UNSUPPORTED);
633 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
636 return start_client(argc, argv);