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