don't use stderr after we become a daemon
[rsync/rsync.git] / main.c
CommitLineData
c627d613
AT
1/*
2 Copyright (C) Andrew Tridgell 1996
3 Copyright (C) Paul Mackerras 1996
4
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.
9
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.
14
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.
18*/
19
20#include "rsync.h"
21
f0fca04e 22time_t starttime = 0;
a800434a
AT
23
24struct stats stats;
5d6bcd44 25
7a6421fa 26extern int verbose;
c627d613
AT
27
28static void report(int f)
29{
7a6421fa
AT
30 time_t t = time(NULL);
31 extern int am_server;
32 extern int am_sender;
248fbb8c 33 extern int am_daemon;
a800434a 34 extern int do_stats;
17d31b38
DD
35 extern int remote_version;
36 int send_stats;
7a6421fa 37
248fbb8c 38 if (am_daemon) {
a9766ef1 39 log_exit(0, __FILE__, __LINE__);
7b372642 40 if (f == -1 || !am_sender) return;
248fbb8c
AT
41 }
42
ebb00c8e 43 send_stats = verbose || (remote_version >= 20);
e19452a9 44 if (am_server) {
17d31b38 45 if (am_sender && send_stats) {
23c5aef1
DD
46 int64 w;
47 /* store total_written in a temporary
48 because write_longint changes it */
49 w = stats.total_written;
e19452a9 50 write_longint(f,stats.total_read);
23c5aef1 51 write_longint(f,w);
e19452a9
DD
52 write_longint(f,stats.total_size);
53 }
7a6421fa
AT
54 return;
55 }
e19452a9
DD
56
57 /* this is the client */
58
17d31b38 59 if (!am_sender && send_stats) {
23c5aef1 60 int64 r;
a800434a 61 stats.total_written = read_longint(f);
23c5aef1
DD
62 /* store total_read in a temporary, read_longint changes it */
63 r = read_longint(f);
a800434a 64 stats.total_size = read_longint(f);
23c5aef1 65 stats.total_read = r;
a800434a
AT
66 }
67
68 if (do_stats) {
17d31b38
DD
69 if (!am_sender && !send_stats) {
70 /* missing the bytes written by the generator */
ebb00c8e 71 rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
17d31b38
DD
72 rprintf(FINFO, "Use --stats -v to show stats\n");
73 return;
74 }
1f658d42
AT
75 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
76 rprintf(FINFO,"Number of files transferred: %d\n",
a800434a 77 stats.num_transferred_files);
1f658d42 78 rprintf(FINFO,"Total file size: %.0f bytes\n",
a800434a 79 (double)stats.total_size);
1f658d42 80 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
a800434a 81 (double)stats.total_transferred_size);
1f658d42 82 rprintf(FINFO,"Literal data: %.0f bytes\n",
a800434a 83 (double)stats.literal_data);
1f658d42 84 rprintf(FINFO,"Matched data: %.0f bytes\n",
a800434a 85 (double)stats.matched_data);
1f658d42
AT
86 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
87 rprintf(FINFO,"Total bytes written: %.0f\n",
a800434a 88 (double)stats.total_written);
1f658d42 89 rprintf(FINFO,"Total bytes read: %.0f\n\n",
a800434a 90 (double)stats.total_read);
7a6421fa
AT
91 }
92
e19452a9
DD
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));
101 }
fc8a6b97
AT
102
103 fflush(stdout);
104 fflush(stderr);
c627d613
AT
105}
106
107
e3cd198f 108static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
c627d613 109{
366345fe
AT
110 char *args[100];
111 int i,argc=0, ret;
112 char *tok,*dir=NULL;
7a6421fa
AT
113 extern int local_server;
114 extern char *rsync_path;
366345fe
AT
115
116 if (!local_server) {
117 if (!cmd)
118 cmd = getenv(RSYNC_RSH_ENV);
119 if (!cmd)
120 cmd = RSYNC_RSH;
121 cmd = strdup(cmd);
122 if (!cmd)
123 goto oom;
124
125 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
126 args[argc++] = tok;
127 }
c627d613 128
7b8356d0 129#if HAVE_REMSH
366345fe
AT
130 /* remsh (on HPUX) takes the arguments the other way around */
131 args[argc++] = machine;
132 if (user) {
133 args[argc++] = "-l";
134 args[argc++] = user;
135 }
7b8356d0 136#else
366345fe
AT
137 if (user) {
138 args[argc++] = "-l";
139 args[argc++] = user;
140 }
141 args[argc++] = machine;
7b8356d0 142#endif
c627d613 143
366345fe 144 args[argc++] = rsync_path;
c627d613 145
366345fe
AT
146 server_options(args,&argc);
147 }
c627d613 148
366345fe 149 args[argc++] = ".";
76076c4b 150
366345fe
AT
151 if (path && *path)
152 args[argc++] = path;
c627d613 153
366345fe 154 args[argc] = NULL;
c627d613 155
366345fe 156 if (verbose > 3) {
9486289c 157 rprintf(FINFO,"cmd=");
366345fe 158 for (i=0;i<argc;i++)
9486289c
AT
159 rprintf(FINFO,"%s ",args[i]);
160 rprintf(FINFO,"\n");
366345fe
AT
161 }
162
163 if (local_server) {
164 ret = local_child(argc, args, f_in, f_out);
165 } else {
166 ret = piped_child(args,f_in,f_out);
167 }
c627d613 168
366345fe 169 if (dir) free(dir);
82306bf6 170
366345fe 171 return ret;
c627d613
AT
172
173oom:
366345fe
AT
174 out_of_memory("do_cmd");
175 return 0; /* not reached */
c627d613
AT
176}
177
178
179
180
181static char *get_local_name(struct file_list *flist,char *name)
182{
7a6421fa
AT
183 STRUCT_STAT st;
184 extern int orig_umask;
c627d613 185
c95da96a
AT
186 if (verbose > 2)
187 rprintf(FINFO,"get_local_name count=%d %s\n",
1f0610ef
DD
188 flist->count, NS(name));
189
190 if (!name)
191 return NULL;
c95da96a 192
1ff5450d
AT
193 if (do_stat(name,&st) == 0) {
194 if (S_ISDIR(st.st_mode)) {
5243c216
AT
195 if (!push_dir(name, 0)) {
196 rprintf(FERROR,"push_dir %s : %s (1)\n",
1ff5450d 197 name,strerror(errno));
65417579 198 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
199 }
200 return NULL;
201 }
202 if (flist->count > 1) {
203 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
65417579 204 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
205 }
206 return name;
207 }
208
cec8aa77 209 if (flist->count <= 1)
1ff5450d
AT
210 return name;
211
1ff5450d
AT
212 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
213 rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
65417579 214 exit_cleanup(RERR_FILEIO);
1ff5450d 215 } else {
b536f47e
AT
216 if (verbose > 0)
217 rprintf(FINFO,"created directory %s\n",name);
1ff5450d
AT
218 }
219
5243c216
AT
220 if (!push_dir(name, 0)) {
221 rprintf(FERROR,"push_dir %s : %s (2)\n",
222 name,strerror(errno));
65417579 223 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
224 }
225
226 return NULL;
c627d613
AT
227}
228
229
230
231
9486289c 232static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
c627d613 233{
7a6421fa
AT
234 int i;
235 struct file_list *flist;
236 char *dir = argv[0];
237 extern int relative_paths;
7a6421fa 238 extern int recurse;
c627d613 239
7a6421fa
AT
240 if (verbose > 2)
241 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
c627d613 242
5243c216
AT
243 if (!relative_paths && !push_dir(dir, 0)) {
244 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
65417579 245 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
246 }
247 argc--;
248 argv++;
c627d613 249
7a6421fa
AT
250 if (strcmp(dir,".")) {
251 int l = strlen(dir);
252 if (strcmp(dir,"/") == 0)
253 l = 0;
254 for (i=0;i<argc;i++)
255 argv[i] += l+1;
256 }
c627d613 257
7a6421fa
AT
258 if (argc == 0 && recurse) {
259 argc=1;
260 argv--;
261 argv[0] = ".";
262 }
263
7a6421fa 264 flist = send_file_list(f_out,argc,argv);
8d9dc9f9
AT
265 if (!flist || flist->count == 0) {
266 exit_cleanup(0);
267 }
268
7a6421fa
AT
269 send_files(flist,f_out,f_in);
270 report(f_out);
8d9dc9f9 271 io_flush();
7a6421fa 272 exit_cleanup(0);
c627d613
AT
273}
274
275
dc5ddbcc
AT
276static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
277{
d186eb1a
AT
278 int pid;
279 int status=0;
280 int recv_pipe[2];
554e0a8d 281 int error_pipe[2];
d186eb1a 282 extern int preserve_hard_links;
dc5ddbcc 283
d186eb1a
AT
284 if (preserve_hard_links)
285 init_hard_links(flist);
dc5ddbcc 286
d186eb1a
AT
287 if (pipe(recv_pipe) < 0) {
288 rprintf(FERROR,"pipe failed in do_recv\n");
65417579 289 exit_cleanup(RERR_SOCKETIO);
d186eb1a 290 }
554e0a8d
AT
291
292 if (pipe(error_pipe) < 0) {
293 rprintf(FERROR,"error pipe failed in do_recv\n");
294 exit_cleanup(RERR_SOCKETIO);
295 }
c6e7fcb4 296
8d9dc9f9 297 io_flush();
c6e7fcb4 298
d186eb1a 299 if ((pid=do_fork()) == 0) {
e08c9610 300 close(recv_pipe[0]);
554e0a8d 301 close(error_pipe[0]);
e08c9610
AT
302 if (f_in != f_out) close(f_out);
303
554e0a8d
AT
304 /* we can't let two processes write to the socket at one time */
305 io_multiplexing_close();
306
307 /* set place to send errors */
308 set_error_fd(error_pipe[1]);
309
e08c9610 310 recv_files(f_in,flist,local_name,recv_pipe[1]);
ba5e128d 311 report(f_in);
e08c9610 312
8d9dc9f9
AT
313 io_flush();
314 _exit(0);
d186eb1a 315 }
dc5ddbcc 316
e08c9610 317 close(recv_pipe[1]);
554e0a8d 318 close(error_pipe[1]);
e08c9610
AT
319 io_close_input(f_in);
320 if (f_in != f_out) close(f_in);
e1b3d5c4 321
b3e10ed7
AT
322 io_start_buffering(f_out);
323
554e0a8d
AT
324 io_set_error_fd(error_pipe[0]);
325
e08c9610 326 generate_files(f_out,flist,local_name,recv_pipe[0]);
8d9dc9f9
AT
327
328 io_flush();
d79d1c69 329 wait_process(pid, &status);
d186eb1a 330 return status;
dc5ddbcc
AT
331}
332
c627d613 333
9486289c 334static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
c627d613 335{
7a6421fa
AT
336 int status;
337 struct file_list *flist;
338 char *local_name=NULL;
339 char *dir = NULL;
340 extern int delete_mode;
b33b791e 341 extern int delete_excluded;
7a6421fa 342 extern int am_daemon;
f0fca04e 343
7a6421fa
AT
344 if (verbose > 2)
345 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
346
7a6421fa
AT
347 if (argc > 0) {
348 dir = argv[0];
349 argc--;
350 argv++;
5243c216
AT
351 if (!am_daemon && !push_dir(dir, 0)) {
352 rprintf(FERROR,"push_dir %s : %s (4)\n",
7a6421fa 353 dir,strerror(errno));
65417579 354 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
355 }
356 }
c627d613 357
b33b791e 358 if (delete_mode && !delete_excluded)
7a6421fa 359 recv_exclude_list(f_in);
c627d613 360
7a6421fa 361 flist = recv_file_list(f_in);
4c36a13e
AT
362 if (!flist) {
363 rprintf(FERROR,"server_recv: recv_file_list error\n");
65417579 364 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
365 }
366
367 if (argc > 0) {
368 if (strcmp(dir,".")) {
369 argv[0] += strlen(dir);
370 if (argv[0][0] == '/') argv[0]++;
371 }
372 local_name = get_local_name(flist,argv[0]);
373 }
c627d613 374
7a6421fa
AT
375 status = do_recv(f_in,f_out,flist,local_name);
376 exit_cleanup(status);
c627d613
AT
377}
378
379
9486289c 380void start_server(int f_in, int f_out, int argc, char *argv[])
366345fe 381{
7a6421fa
AT
382 extern int cvs_exclude;
383 extern int am_sender;
384
385 setup_protocol(f_out, f_in);
3eb38818 386
7a6421fa
AT
387 if (am_sender) {
388 recv_exclude_list(f_in);
389 if (cvs_exclude)
390 add_cvs_excludes();
391 do_server_sender(f_in, f_out, argc, argv);
392 } else {
393 do_server_recv(f_in, f_out, argc, argv);
394 }
395 exit_cleanup(0);
366345fe
AT
396}
397
3591c066 398int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
9486289c
AT
399{
400 struct file_list *flist;
401 int status = 0, status2 = 0;
402 char *local_name = NULL;
7a6421fa 403 extern int am_sender;
f7632fc6 404 extern int list_only;
9486289c
AT
405
406 setup_protocol(f_out,f_in);
407
408 if (am_sender) {
7a6421fa
AT
409 extern int cvs_exclude;
410 extern int delete_mode;
b33b791e 411 extern int delete_excluded;
9486289c
AT
412 if (cvs_exclude)
413 add_cvs_excludes();
b33b791e 414 if (delete_mode && !delete_excluded)
9486289c
AT
415 send_exclude_list(f_out);
416 flist = send_file_list(f_out,argc,argv);
417 if (verbose > 3)
418 rprintf(FINFO,"file list sent\n");
e1b3d5c4 419
9486289c
AT
420 send_files(flist,f_out,f_in);
421 if (pid != -1) {
422 if (verbose > 3)
8d9dc9f9
AT
423 rprintf(FINFO,"client_run waiting on %d\n",pid);
424 io_flush();
d79d1c69 425 wait_process(pid, &status);
9486289c
AT
426 }
427 report(-1);
428 exit_cleanup(status);
429 }
f7632fc6
AT
430
431 if (argc == 0) list_only = 1;
9486289c
AT
432
433 send_exclude_list(f_out);
434
435 flist = recv_file_list(f_in);
436 if (!flist || flist->count == 0) {
8d9dc9f9 437 rprintf(FINFO,"client: nothing to do\n");
9486289c
AT
438 exit_cleanup(0);
439 }
440
441 local_name = get_local_name(flist,argv[0]);
442
443 status2 = do_recv(f_in,f_out,flist,local_name);
444
9486289c 445 if (pid != -1) {
8d9dc9f9
AT
446 if (verbose > 3)
447 rprintf(FINFO,"client_run2 waiting on %d\n",pid);
448 io_flush();
d79d1c69 449 wait_process(pid, &status);
9486289c
AT
450 }
451
452 return status | status2;
453}
454
ca6c93f8
AT
455static char *find_colon(char *s)
456{
457 char *p, *p2;
458
459 p = strchr(s,':');
460 if (!p) return NULL;
461
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 */
464 p2 = strchr(s,'/');
465 if (p2 && p2 < p) return NULL;
466
467 return p;
468}
9486289c 469
fc8a6b97 470static int start_client(int argc, char *argv[])
5d6bcd44
AT
471{
472 char *p;
473 char *shell_machine = NULL;
474 char *shell_path = NULL;
475 char *shell_user = NULL;
fc8a6b97 476 int pid, ret;
5d6bcd44 477 int f_in,f_out;
7a6421fa
AT
478 extern int local_server;
479 extern int am_sender;
480 extern char *shell_cmd;
2acf81eb 481 extern int rsync_port;
5d6bcd44 482
f7632fc6
AT
483 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
484 char *host, *path;
485
486 host = argv[0] + strlen(URL_PREFIX);
487 p = strchr(host,'/');
488 if (p) {
489 *p = 0;
490 path = p+1;
491 } else {
492 path="";
493 }
2acf81eb
DD
494 p = strchr(host,':');
495 if (p) {
496 rsync_port = atoi(p+1);
497 *p = 0;
498 }
f7632fc6
AT
499 return start_socket_client(host, path, argc-1, argv+1);
500 }
501
ca6c93f8 502 p = find_colon(argv[0]);
5d6bcd44
AT
503
504 if (p) {
9486289c
AT
505 if (p[1] == ':') {
506 *p = 0;
507 return start_socket_client(argv[0], p+2, argc-1, argv+1);
508 }
3591c066 509
f7632fc6 510 if (argc < 1) {
3591c066 511 usage(FERROR);
65417579 512 exit_cleanup(RERR_SYNTAX);
3591c066
AT
513 }
514
5d6bcd44
AT
515 am_sender = 0;
516 *p = 0;
517 shell_machine = argv[0];
518 shell_path = p+1;
519 argc--;
520 argv++;
521 } else {
522 am_sender = 1;
9486289c 523
ca6c93f8 524 p = find_colon(argv[argc-1]);
5d6bcd44
AT
525 if (!p) {
526 local_server = 1;
9486289c
AT
527 } else if (p[1] == ':') {
528 *p = 0;
529 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
5d6bcd44 530 }
3591c066
AT
531
532 if (argc < 2) {
533 usage(FERROR);
65417579 534 exit_cleanup(RERR_SYNTAX);
3591c066 535 }
9486289c 536
5d6bcd44
AT
537 if (local_server) {
538 shell_machine = NULL;
539 shell_path = argv[argc-1];
540 } else {
541 *p = 0;
542 shell_machine = argv[argc-1];
543 shell_path = p+1;
544 }
545 argc--;
546 }
547
548 if (shell_machine) {
549 p = strchr(shell_machine,'@');
550 if (p) {
551 *p = 0;
552 shell_user = shell_machine;
553 shell_machine = p+1;
554 }
555 }
556
557 if (verbose > 3) {
9486289c 558 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
5d6bcd44
AT
559 shell_cmd?shell_cmd:"",
560 shell_machine?shell_machine:"",
561 shell_user?shell_user:"",
562 shell_path?shell_path:"");
563 }
564
f7632fc6 565 if (!am_sender && argc > 1) {
5d6bcd44 566 usage(FERROR);
65417579 567 exit_cleanup(RERR_SYNTAX);
5d6bcd44
AT
568 }
569
570 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
571
fc8a6b97
AT
572 ret = client_run(f_in, f_out, pid, argc, argv);
573
574 fflush(stdout);
575 fflush(stderr);
576
577 return ret;
5d6bcd44
AT
578}
579
366345fe 580
6e4fb64e 581static RETSIGTYPE sigusr1_handler(int val) {
65417579 582 exit_cleanup(RERR_SIGNAL);
82306bf6
AT
583}
584
5d6bcd44 585int main(int argc,char *argv[])
7a6421fa
AT
586{
587 extern int am_root;
588 extern int orig_umask;
589 extern int dry_run;
590 extern int am_daemon;
591 extern int am_server;
5d6bcd44 592
7a6421fa 593 signal(SIGUSR1, sigusr1_handler);
5d6bcd44 594
7a6421fa
AT
595 starttime = time(NULL);
596 am_root = (getuid() == 0);
c627d613 597
a800434a
AT
598 memset(&stats, 0, sizeof(stats));
599
df5e03da
AT
600 if (argc < 2) {
601 usage(FERROR);
65417579 602 exit_cleanup(RERR_SYNTAX);
df5e03da
AT
603 }
604
7a6421fa
AT
605 /* we set a 0 umask so that correct file permissions can be
606 carried across */
607 orig_umask = (int)umask(0);
5d6bcd44 608
b86f0cef 609 if (!parse_arguments(argc, argv, 1)) {
65417579 610 exit_cleanup(RERR_SYNTAX);
b11ed3b1 611 }
5d6bcd44 612
7a6421fa
AT
613 argc -= optind;
614 argv += optind;
615 optind = 0;
c627d613 616
7a6421fa
AT
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);
8638dd48 621 signal(SIGTERM,SIGNAL_CAST sig_int);
6b83141d 622
c226b7c2
DD
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. */
627 push_dir(NULL,0);
628
7a6421fa
AT
629 if (am_daemon) {
630 return daemon_main();
631 }
f0fca04e 632
08ac228f
AT
633 if (argc < 1) {
634 usage(FERROR);
65417579 635 exit_cleanup(RERR_SYNTAX);
08ac228f
AT
636 }
637
7a6421fa
AT
638 if (dry_run)
639 verbose = MAX(verbose,1);
c627d613 640
cbbe4892 641#ifndef SUPPORT_LINKS
7a6421fa
AT
642 if (!am_server && preserve_links) {
643 rprintf(FERROR,"ERROR: symbolic links not supported\n");
65417579 644 exit_cleanup(RERR_UNSUPPORTED);
7a6421fa 645 }
cbbe4892
AT
646#endif
647
7a6421fa
AT
648 if (am_server) {
649 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
650 }
c627d613 651
7a6421fa 652 return start_client(argc, argv);
c627d613 653}
82306bf6 654