fixed bug in replacement inet_aton()
[rsync/rsync.git] / main.c
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
22 time_t starttime = 0;
23
24 struct stats stats;
25
26 extern int verbose;
27
28 static void report(int f)
29 {
30         time_t t = time(NULL);
31         extern int am_server;
32         extern int am_sender;
33         extern int am_daemon;
34         extern int do_stats;
35         extern int remote_version;
36         int send_stats;
37
38         if (am_daemon) {
39                 log_exit(0, __FILE__, __LINE__);
40                 if (f == -1 || !am_sender) return;
41         }
42
43         send_stats = verbose || (remote_version >= 20);
44         if (am_server) {
45                 if (am_sender && send_stats) {
46                         int64 w;
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);
51                         write_longint(f,w);
52                         write_longint(f,stats.total_size);
53                 }
54                 return;
55         }
56
57         /* this is the client */
58             
59         if (!am_sender && send_stats) {
60                 int64 r;
61                 stats.total_written = read_longint(f);
62                 /* store total_read in a temporary, read_longint changes it */
63                 r = read_longint(f);
64                 stats.total_size = read_longint(f);
65                 stats.total_read = r;
66         }
67
68         if (do_stats) {
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");
73                     return;
74                 }
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);
91         }
92         
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         }
102
103         fflush(stdout);
104         fflush(stderr);
105 }
106
107
108 static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
109 {
110         char *args[100];
111         int i,argc=0, ret;
112         char *tok,*dir=NULL;
113         extern int local_server;
114         extern char *rsync_path;
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                 }
128
129 #if HAVE_REMSH
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                 }
136 #else
137                 if (user) {
138                         args[argc++] = "-l";
139                         args[argc++] = user;
140                 }
141                 args[argc++] = machine;
142 #endif
143
144                 args[argc++] = rsync_path;
145
146                 server_options(args,&argc);
147         }
148
149         args[argc++] = ".";
150
151         if (path && *path) 
152                 args[argc++] = path;
153
154         args[argc] = NULL;
155
156         if (verbose > 3) {
157                 rprintf(FINFO,"cmd=");
158                 for (i=0;i<argc;i++)
159                         rprintf(FINFO,"%s ",args[i]);
160                 rprintf(FINFO,"\n");
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         }
168
169         if (dir) free(dir);
170
171         return ret;
172
173 oom:
174         out_of_memory("do_cmd");
175         return 0; /* not reached */
176 }
177
178
179
180
181 static char *get_local_name(struct file_list *flist,char *name)
182 {
183         STRUCT_STAT st;
184         extern int orig_umask;
185
186         if (verbose > 2)
187                 rprintf(FINFO,"get_local_name count=%d %s\n", 
188                         flist->count, NS(name));
189
190         if (!name) 
191                 return NULL;
192
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);
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");
204                         exit_cleanup(RERR_FILESELECT);
205                 }
206                 return name;
207         }
208
209         if (flist->count <= 1)
210                 return name;
211
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);
215         } else {
216                 if (verbose > 0)
217                         rprintf(FINFO,"created directory %s\n",name);
218         }
219
220         if (!push_dir(name, 0)) {
221                 rprintf(FERROR,"push_dir %s : %s (2)\n",
222                         name,strerror(errno));
223                 exit_cleanup(RERR_FILESELECT);
224         }
225
226         return NULL;
227 }
228
229
230
231
232 static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
233 {
234         int i;
235         struct file_list *flist;
236         char *dir = argv[0];
237         extern int relative_paths;
238         extern int recurse;
239
240         if (verbose > 2)
241                 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
242   
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);
246         }
247         argc--;
248         argv++;
249   
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         }
257
258         if (argc == 0 && recurse) {
259                 argc=1;
260                 argv--;
261                 argv[0] = ".";
262         }
263         
264         flist = send_file_list(f_out,argc,argv);
265         if (!flist || flist->count == 0) {
266                 exit_cleanup(0);
267         }
268
269         send_files(flist,f_out,f_in);
270         report(f_out);
271         io_flush();
272         exit_cleanup(0);
273 }
274
275
276 static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
277 {
278         int pid;
279         int status=0;
280         int recv_pipe[2];
281         int error_pipe[2];
282         extern int preserve_hard_links;
283         extern int delete_after;
284         extern int recurse;
285         extern int delete_mode;
286         extern int remote_version;
287
288         if (preserve_hard_links)
289                 init_hard_links(flist);
290
291         if (!delete_after) {
292                 /* I moved this here from recv_files() to prevent a race condition */
293                 if (recurse && delete_mode && !local_name && flist->count>0) {
294                         delete_files(flist);
295                 }
296         }
297
298         if (fd_pair(recv_pipe) < 0) {
299                 rprintf(FERROR,"pipe failed in do_recv\n");
300                 exit_cleanup(RERR_SOCKETIO);
301         }
302
303         if (fd_pair(error_pipe) < 0) {
304                 rprintf(FERROR,"error pipe failed in do_recv\n");
305                 exit_cleanup(RERR_SOCKETIO);
306         }
307   
308         io_flush();
309
310         if ((pid=do_fork()) == 0) {
311                 close(recv_pipe[0]);
312                 close(error_pipe[0]);
313                 if (f_in != f_out) close(f_out);
314
315                 /* we can't let two processes write to the socket at one time */
316                 io_multiplexing_close();
317
318                 /* set place to send errors */
319                 set_error_fd(error_pipe[1]);
320
321                 recv_files(f_in,flist,local_name,recv_pipe[1]);
322                 report(f_in);
323
324                 write_int(recv_pipe[1],1);
325                 close(recv_pipe[1]);
326                 io_flush();
327                 /* finally we go to sleep until our parent kills us
328                    with a USR2 signal. We sleepp for a short time as on
329                    some OSes a signal won't interrupt a sleep! */
330                 while (1) sleep(1);
331         }
332
333         close(recv_pipe[1]);
334         close(error_pipe[1]);
335         io_close_input(f_in);
336         if (f_in != f_out) close(f_in);
337
338         io_start_buffering(f_out);
339
340         io_set_error_fd(error_pipe[0]);
341
342         generate_files(f_out,flist,local_name,recv_pipe[0]);
343
344         read_int(recv_pipe[0]);
345         close(recv_pipe[0]);
346         if (remote_version >= 24) {
347                 /* send a final goodbye message */
348                 write_int(f_out, -1);
349         }
350         io_flush();
351
352         kill(pid, SIGUSR2);
353         wait_process(pid, &status);
354         return status;
355 }
356
357
358 static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
359 {
360         int status;
361         struct file_list *flist;
362         char *local_name=NULL;
363         char *dir = NULL;
364         extern int delete_mode;
365         extern int delete_excluded;
366         extern int am_daemon;
367         extern int module_id;
368         extern int am_sender;
369
370         if (verbose > 2)
371                 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
372
373         if (am_daemon && lp_read_only(module_id) && !am_sender) {
374                 rprintf(FERROR,"ERROR: module is read only\n");
375                 exit_cleanup(RERR_SYNTAX);
376                 return;
377         }
378
379         
380         if (argc > 0) {
381                 dir = argv[0];
382                 argc--;
383                 argv++;
384                 if (!am_daemon && !push_dir(dir, 0)) {
385                         rprintf(FERROR,"push_dir %s : %s (4)\n",
386                                 dir,strerror(errno));
387                         exit_cleanup(RERR_FILESELECT);
388                 }    
389         }
390
391         if (delete_mode && !delete_excluded)
392                 recv_exclude_list(f_in);
393
394         flist = recv_file_list(f_in);
395         if (!flist) {
396                 rprintf(FERROR,"server_recv: recv_file_list error\n");
397                 exit_cleanup(RERR_FILESELECT);
398         }
399         
400         if (argc > 0) {    
401                 if (strcmp(dir,".")) {
402                         argv[0] += strlen(dir);
403                         if (argv[0][0] == '/') argv[0]++;
404                 }
405                 local_name = get_local_name(flist,argv[0]);
406         }
407
408         status = do_recv(f_in,f_out,flist,local_name);
409         exit_cleanup(status);
410 }
411
412
413 void start_server(int f_in, int f_out, int argc, char *argv[])
414 {
415         extern int cvs_exclude;
416         extern int am_sender;
417         extern int remote_version;
418
419         setup_protocol(f_out, f_in);
420
421         set_nonblocking(f_in);
422         set_nonblocking(f_out);
423
424         if (remote_version >= 23)
425                 io_start_multiplex_out(f_out);
426
427         if (am_sender) {
428                 recv_exclude_list(f_in);
429                 if (cvs_exclude)
430                         add_cvs_excludes();
431                 do_server_sender(f_in, f_out, argc, argv);
432         } else {
433                 do_server_recv(f_in, f_out, argc, argv);
434         }
435         exit_cleanup(0);
436 }
437
438 int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
439 {
440         struct file_list *flist;
441         int status = 0, status2 = 0;
442         char *local_name = NULL;
443         extern int am_sender;
444         extern int list_only;
445         extern int remote_version;
446
447         set_nonblocking(f_in);
448         set_nonblocking(f_out);
449
450         setup_protocol(f_out,f_in);
451
452         if (remote_version >= 23)
453                 io_start_multiplex_in(f_in);
454         
455         if (am_sender) {
456                 extern int cvs_exclude;
457                 extern int delete_mode;
458                 extern int delete_excluded;
459                 if (cvs_exclude)
460                         add_cvs_excludes();
461                 if (delete_mode && !delete_excluded) 
462                         send_exclude_list(f_out);
463                 flist = send_file_list(f_out,argc,argv);
464                 if (verbose > 3) 
465                         rprintf(FINFO,"file list sent\n");
466
467                 send_files(flist,f_out,f_in);
468                 if (pid != -1) {
469                         if (verbose > 3)
470                                 rprintf(FINFO,"client_run waiting on %d\n",pid);
471                         io_flush();
472                         wait_process(pid, &status);
473                 }
474                 report(-1);
475                 if (remote_version >= 24) {
476                         /* final goodbye message */             
477                         read_int(f_in);
478                 }
479                 exit_cleanup(status);
480         }
481
482         if (argc == 0) list_only = 1;
483         
484         send_exclude_list(f_out);
485         
486         flist = recv_file_list(f_in);
487         if (!flist || flist->count == 0) {
488                 rprintf(FINFO,"client: nothing to do\n");
489                 exit_cleanup(0);
490         }
491         
492         local_name = get_local_name(flist,argv[0]);
493         
494         status2 = do_recv(f_in,f_out,flist,local_name);
495         
496         if (pid != -1) {
497                 if (verbose > 3)
498                         rprintf(FINFO,"client_run2 waiting on %d\n",pid);
499                 io_flush();
500                 wait_process(pid, &status);
501         }
502         
503         return status | status2;
504 }
505
506 static char *find_colon(char *s)
507 {
508         char *p, *p2;
509
510         p = strchr(s,':');
511         if (!p) return NULL;
512         
513         /* now check to see if there is a / in the string before the : - if there is then
514            discard the colon on the assumption that the : is part of a filename */
515         p2 = strchr(s,'/');
516         if (p2 && p2 < p) return NULL;
517
518         return p;
519 }
520
521 static int start_client(int argc, char *argv[])
522 {
523         char *p;
524         char *shell_machine = NULL;
525         char *shell_path = NULL;
526         char *shell_user = NULL;
527         int pid, ret;
528         int f_in,f_out;
529         extern int local_server;
530         extern int am_sender;
531         extern char *shell_cmd;
532         extern int rsync_port;
533
534         if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
535                 char *host, *path;
536
537                 host = argv[0] + strlen(URL_PREFIX);
538                 p = strchr(host,'/');
539                 if (p) {
540                         *p = 0;
541                         path = p+1;
542                 } else {
543                         path="";
544                 }
545                 p = strchr(host,':');
546                 if (p) {
547                         rsync_port = atoi(p+1);
548                         *p = 0;
549                 }
550                 return start_socket_client(host, path, argc-1, argv+1);
551         }
552
553         p = find_colon(argv[0]);
554
555         if (p) {
556                 if (p[1] == ':') {
557                         *p = 0;
558                         return start_socket_client(argv[0], p+2, argc-1, argv+1);
559                 }
560
561                 if (argc < 1) {
562                         usage(FERROR);
563                         exit_cleanup(RERR_SYNTAX);
564                 }
565
566                 am_sender = 0;
567                 *p = 0;
568                 shell_machine = argv[0];
569                 shell_path = p+1;
570                 argc--;
571                 argv++;
572         } else {
573                 am_sender = 1;
574
575                 p = find_colon(argv[argc-1]);
576                 if (!p) {
577                         local_server = 1;
578                 } else if (p[1] == ':') {
579                         *p = 0;
580                         return start_socket_client(argv[argc-1], p+2, argc-1, argv);
581                 }
582
583                 if (argc < 2) {
584                         usage(FERROR);
585                         exit_cleanup(RERR_SYNTAX);
586                 }
587                 
588                 if (local_server) {
589                         shell_machine = NULL;
590                         shell_path = argv[argc-1];
591                 } else {
592                         *p = 0;
593                         shell_machine = argv[argc-1];
594                         shell_path = p+1;
595                 }
596                 argc--;
597         }
598         
599         if (shell_machine) {
600                 p = strchr(shell_machine,'@');
601                 if (p) {
602                         *p = 0;
603                         shell_user = shell_machine;
604                         shell_machine = p+1;
605                 }
606         }
607
608         if (verbose > 3) {
609                 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
610                         shell_cmd?shell_cmd:"",
611                         shell_machine?shell_machine:"",
612                         shell_user?shell_user:"",
613                         shell_path?shell_path:"");
614         }
615         
616         if (!am_sender && argc > 1) {
617                 usage(FERROR);
618                 exit_cleanup(RERR_SYNTAX);
619         }
620         
621         pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
622         
623         ret = client_run(f_in, f_out, pid, argc, argv);
624
625         fflush(stdout);
626         fflush(stderr);
627
628         return ret;
629 }
630
631
632 static RETSIGTYPE sigusr1_handler(int val) {
633         exit_cleanup(RERR_SIGNAL);
634 }
635
636 static RETSIGTYPE sigusr2_handler(int val) {
637         _exit(0);
638 }
639
640 int main(int argc,char *argv[])
641 {       
642         extern int am_root;
643         extern int orig_umask;
644         extern int dry_run;
645         extern int am_daemon;
646         extern int am_server;
647
648         signal(SIGUSR1, sigusr1_handler);
649         signal(SIGUSR2, sigusr2_handler);
650
651         starttime = time(NULL);
652         am_root = (getuid() == 0);
653
654         memset(&stats, 0, sizeof(stats));
655
656         if (argc < 2) {
657                 usage(FERROR);
658                 exit_cleanup(RERR_SYNTAX);
659         }
660
661         /* we set a 0 umask so that correct file permissions can be
662            carried across */
663         orig_umask = (int)umask(0);
664
665         if (!parse_arguments(argc, argv, 1)) {
666                 exit_cleanup(RERR_SYNTAX);
667         }
668
669         argc -= optind;
670         argv += optind;
671         optind = 0;
672
673         signal(SIGCHLD,SIG_IGN);
674         signal(SIGINT,SIGNAL_CAST sig_int);
675         signal(SIGPIPE,SIGNAL_CAST sig_int);
676         signal(SIGHUP,SIGNAL_CAST sig_int);
677         signal(SIGTERM,SIGNAL_CAST sig_int);
678
679         /* Initialize push_dir here because on some old systems getcwd
680            (implemented by forking "pwd" and reading its output) doesn't
681            work when there are other child processes.  Also, on all systems
682            that implement getcwd that way "pwd" can't be found after chroot. */
683         push_dir(NULL,0);
684
685         if (am_daemon) {
686                 return daemon_main();
687         }
688
689         if (argc < 1) {
690                 usage(FERROR);
691                 exit_cleanup(RERR_SYNTAX);
692         }
693
694         if (dry_run)
695                 verbose = MAX(verbose,1);
696
697 #ifndef SUPPORT_LINKS
698         if (!am_server && preserve_links) {
699                 rprintf(FERROR,"ERROR: symbolic links not supported\n");
700                 exit_cleanup(RERR_UNSUPPORTED);
701         }
702 #endif
703
704         if (am_server) {
705                 set_nonblocking(STDIN_FILENO);
706                 set_nonblocking(STDOUT_FILENO);
707                 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
708         }
709
710         return start_client(argc, argv);
711 }
712