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