*** empty log message ***
[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 int verbose = 0;
23 int always_checksum = 0;
24 time_t starttime;
25 off_t total_size = 0;
26 int block_size=BLOCK_SIZE;
27
28 char *backup_suffix = BACKUP_SUFFIX;
29
30 static char *rsync_path = RSYNC_NAME;
31
32 int make_backups = 0;
33 int whole_file = 0;
34 int copy_links = 0;
35 int preserve_links = 0;
36 int preserve_hard_links = 0;
37 int preserve_perms = 0;
38 int preserve_devices = 0;
39 int preserve_uid = 0;
40 int preserve_gid = 0;
41 int preserve_times = 0;
42 int update_only = 0;
43 int cvs_exclude = 0;
44 int dry_run=0;
45 int local_server=0;
46 int ignore_times=0;
47 int delete_mode=0;
48 int one_file_system=0;
49 int remote_version=0;
50 int sparse_files=0;
51 int do_compression=0;
52 int am_root=0;
53 int orig_umask=0;
54 int relative_paths=0;
55 int numeric_ids = 0;
56
57 extern int csum_length;
58
59 int am_server = 0;
60 static int sender = 0;
61 int recurse = 0;
62
63 static void usage(FILE *f);
64
65 static void report(int f)
66 {
67   int in,out,tsize;
68   time_t t = time(NULL);
69   
70   if (!verbose) return;
71
72   if (am_server && sender) {
73     write_int(f,read_total());
74     write_int(f,write_total());
75     write_int(f,total_size);
76     write_flush(f);
77     return;
78   }
79     
80   if (sender) {
81     in = read_total();
82     out = write_total();
83     tsize = (int)total_size;
84   } else {
85     in = read_int(f);
86     out = read_int(f);
87     tsize = read_int(f);
88   }
89
90   printf("wrote %d bytes  read %d bytes  %g bytes/sec\n",
91          out,in,(in+out)/(0.5 + (t-starttime)));        
92   printf("total size is %d  speedup is %g\n",
93          tsize,(1.0*tsize)/(in+out));
94 }
95
96
97 static void server_options(char **args,int *argc)
98 {
99   int ac = *argc;
100   static char argstr[50];
101   static char bsize[30];
102   int i, x;
103
104   args[ac++] = "--server";
105
106   if (!sender)
107     args[ac++] = "--sender";
108
109   x = 1;
110   argstr[0] = '-';
111   for (i=0;i<verbose;i++)
112     argstr[x++] = 'v';
113   if (make_backups)
114     argstr[x++] = 'b';
115   if (update_only)
116     argstr[x++] = 'u';
117   if (dry_run)
118     argstr[x++] = 'n';
119   if (preserve_links)
120     argstr[x++] = 'l';
121   if (copy_links)
122     argstr[x++] = 'L';
123   if (whole_file)
124     argstr[x++] = 'W';
125   if (preserve_hard_links)
126     argstr[x++] = 'H';
127   if (preserve_uid)
128     argstr[x++] = 'o';
129   if (preserve_gid)
130     argstr[x++] = 'g';
131   if (preserve_devices)
132     argstr[x++] = 'D';
133   if (preserve_times)
134     argstr[x++] = 't';
135   if (preserve_perms)
136     argstr[x++] = 'p';
137   if (recurse)
138     argstr[x++] = 'r';
139   if (always_checksum)
140     argstr[x++] = 'c';
141   if (cvs_exclude)
142     argstr[x++] = 'C';
143   if (ignore_times)
144     argstr[x++] = 'I';
145   if (relative_paths)
146     argstr[x++] = 'R';
147   if (one_file_system)
148     argstr[x++] = 'x';
149   if (sparse_files)
150     argstr[x++] = 'S';
151   if (do_compression)
152     argstr[x++] = 'z';
153   argstr[x] = 0;
154
155   if (x != 1) args[ac++] = argstr;
156
157   if (block_size != BLOCK_SIZE) {
158     sprintf(bsize,"-B%d",block_size);
159     args[ac++] = bsize;
160   }    
161
162   if (strcmp(backup_suffix, BACKUP_SUFFIX)) {
163           args[ac++] = "--suffix";
164           args[ac++] = backup_suffix;
165   }
166
167   if (delete_mode)
168     args[ac++] = "--delete";
169
170   if (numeric_ids)
171     args[ac++] = "--numeric-ids";
172
173   *argc = ac;
174 }
175
176
177
178 static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
179 {
180   char *args[100];
181   int i,argc=0, ret;
182   char *tok,*p,*dir=NULL;
183
184   if (!local_server) {
185     if (!cmd)
186       cmd = getenv(RSYNC_RSH_ENV);
187     if (!cmd)
188       cmd = RSYNC_RSH;
189     cmd = strdup(cmd);
190     if (!cmd) 
191       goto oom;
192
193     for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
194       args[argc++] = tok;
195     }
196
197 #if HAVE_REMSH
198     /* remsh (on HPUX) takes the arguments the other way around */
199     args[argc++] = machine;
200     if (user) {
201       args[argc++] = "-l";
202       args[argc++] = user;
203     }
204 #else
205     if (user) {
206       args[argc++] = "-l";
207       args[argc++] = user;
208     }
209     args[argc++] = machine;
210 #endif
211   }
212
213   args[argc++] = rsync_path;
214
215   server_options(args,&argc);
216
217   if (path && *path) {
218     dir = strdup(path);
219     p = strrchr(dir,'/');
220     if (p && !relative_paths) {
221       *p = 0;
222       if (!dir[0])
223         args[argc++] = "/";
224       else
225         args[argc++] = dir;
226       p++;
227     } else {
228       args[argc++] = ".";
229       p = dir;
230     }
231     if (p[0])
232       args[argc++] = path;
233   }
234
235   args[argc] = NULL;
236
237   if (verbose > 3) {
238     fprintf(FERROR,"cmd=");
239     for (i=0;i<argc;i++)
240       fprintf(FERROR,"%s ",args[i]);
241     fprintf(FERROR,"\n");
242   }
243
244   ret = piped_child(args,f_in,f_out);
245   if (dir) free(dir);
246
247   return ret;
248
249 oom:
250   out_of_memory("do_cmd");
251   return 0; /* not reached */
252 }
253
254
255
256
257 static char *get_local_name(struct file_list *flist,char *name)
258 {
259   struct stat st;
260
261   if (stat(name,&st) == 0) {
262     if (S_ISDIR(st.st_mode)) {
263       if (chdir(name) != 0) {
264         fprintf(FERROR,"chdir %s : %s (1)\n",name,strerror(errno));
265         exit_cleanup(1);
266       }
267       return NULL;
268     }
269     if (flist->count > 1) {
270       fprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
271       exit_cleanup(1);
272     }
273     return name;
274   }
275
276   if (flist->count == 1)
277     return name;
278
279   if (!name) 
280     return NULL;
281
282   if (mkdir(name,0777 & ~orig_umask) != 0) {
283     fprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
284     exit_cleanup(1);
285   } else {
286     fprintf(FINFO,"created directory %s\n",name);
287   }
288
289   if (chdir(name) != 0) {
290     fprintf(FERROR,"chdir %s : %s (2)\n",name,strerror(errno));
291     exit_cleanup(1);
292   }
293
294   return NULL;
295 }
296
297
298
299
300 void do_server_sender(int argc,char *argv[])
301 {
302   int i;
303   char *dir = argv[0];
304   struct file_list *flist;
305
306   if (verbose > 2)
307     fprintf(FERROR,"server_sender starting pid=%d\n",(int)getpid());
308   
309   if (!relative_paths && chdir(dir) != 0) {
310     fprintf(FERROR,"chdir %s: %s (3)\n",dir,strerror(errno));
311     exit_cleanup(1);
312   }
313   argc--;
314   argv++;
315   
316   if (strcmp(dir,".")) {
317     int l = strlen(dir);
318     if (strcmp(dir,"/") == 0) 
319       l = 0;
320     for (i=0;i<argc;i++)
321       argv[i] += l+1;
322   }
323
324   if (argc == 0 && recurse) {
325     argc=1;
326     argv--;
327     argv[0] = ".";
328   }
329     
330
331   flist = send_file_list(STDOUT_FILENO,argc,argv);
332   send_files(flist,STDOUT_FILENO,STDIN_FILENO);
333   report(STDOUT_FILENO);
334   exit_cleanup(0);
335 }
336
337
338 static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
339 {
340   int pid;
341   int status=0;
342   int recv_pipe[2];
343
344   if (preserve_hard_links)
345     init_hard_links(flist);
346
347   if (pipe(recv_pipe) < 0) {
348     fprintf(FERROR,"pipe failed in do_recv\n");
349     exit(1);
350   }
351   
352
353   if ((pid=fork()) == 0) {
354     recv_files(f_in,flist,local_name,recv_pipe[1]);
355     if (verbose > 2)
356       fprintf(FERROR,"receiver read %d\n",read_total());
357     exit_cleanup(0);
358   }
359
360   generate_files(f_out,flist,local_name,recv_pipe[0]);
361
362   waitpid(pid, &status, 0);
363
364   return status;
365 }
366
367
368 void do_server_recv(int argc,char *argv[])
369 {
370   int status;
371   char *dir = NULL;
372   struct file_list *flist;
373   char *local_name=NULL;
374   
375   if (verbose > 2)
376     fprintf(FERROR,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
377
378   if (argc > 0) {
379     dir = argv[0];
380     argc--;
381     argv++;
382     if (chdir(dir) != 0) {
383       fprintf(FERROR,"chdir %s : %s (4)\n",dir,strerror(errno));
384       exit_cleanup(1);
385     }    
386   }
387
388   if (delete_mode)
389     recv_exclude_list(STDIN_FILENO);
390
391   flist = recv_file_list(STDIN_FILENO);
392   if (!flist || flist->count == 0) {
393     fprintf(FERROR,"nothing to do\n");
394     exit_cleanup(1);
395   }
396
397   if (argc > 0) {    
398     if (strcmp(dir,".")) {
399       argv[0] += strlen(dir);
400       if (argv[0][0] == '/') argv[0]++;
401     }
402     local_name = get_local_name(flist,argv[0]);
403   }
404
405   status = do_recv(STDIN_FILENO,STDOUT_FILENO,flist,local_name);
406   exit_cleanup(status);
407 }
408
409
410 static void usage(FILE *f)
411 {
412   fprintf(f,"rsync version %s Copyright Andrew Tridgell and Paul Mackerras\n\n",
413           VERSION);
414   fprintf(f,"Usage:\t%s [options] src user@host:dest\nOR",RSYNC_NAME);
415   fprintf(f,"\t%s [options] user@host:src dest\n\n",RSYNC_NAME);
416   fprintf(f,"Options:\n");
417   fprintf(f,"-v, --verbose            increase verbosity\n");
418   fprintf(f,"-c, --checksum           always checksum\n");
419   fprintf(f,"-a, --archive            archive mode (same as -rlptDog)\n");
420   fprintf(f,"-r, --recursive          recurse into directories\n");
421   fprintf(f,"-R, --relative           use relative path names\n");
422   fprintf(f,"-b, --backup             make backups (default ~ extension)\n");
423   fprintf(f,"-u, --update             update only (don't overwrite newer files)\n");
424   fprintf(f,"-l, --links              preserve soft links\n");
425   fprintf(f,"-L, --copy-links         treat soft links like regular files\n");
426   fprintf(f,"-H, --hard-links         preserve hard links\n");
427   fprintf(f,"-p, --perms              preserve permissions\n");
428   fprintf(f,"-o, --owner              preserve owner (root only)\n");
429   fprintf(f,"-g, --group              preserve group\n");
430   fprintf(f,"-D, --devices            preserve devices (root only)\n");
431   fprintf(f,"-t, --times              preserve times\n");  
432   fprintf(f,"-S, --sparse             handle sparse files efficiently\n");
433   fprintf(f,"-n, --dry-run            show what would have been transferred\n");
434   fprintf(f,"-W, --whole-file         copy whole files, no incremental checks\n");
435   fprintf(f,"-x, --one-file-system    don't cross filesystem boundaries\n");
436   fprintf(f,"-B, --block-size SIZE    checksum blocking size\n");  
437   fprintf(f,"-e, --rsh COMMAND        specify rsh replacement\n");
438   fprintf(f,"    --rsync-path PATH    specify path to rsync on the remote machine\n");
439   fprintf(f,"-C, --cvs-exclude        auto ignore files in the same way CVS does\n");
440   fprintf(f,"    --delete             delete files that don't exist on the sending side\n");
441   fprintf(f,"    --numeric-ids        don't map uid/gid values by user/group name\n");
442   fprintf(f,"-I, --ignore-times       don't exclude files that match length and time\n");
443   fprintf(f,"-z, --compress           compress file data\n");
444   fprintf(f,"    --exclude FILE       exclude file FILE\n");
445   fprintf(f,"    --exclude-from FILE  exclude files listed in FILE\n");
446   fprintf(f,"    --suffix SUFFIX      override backup suffix\n");  
447   fprintf(f,"    --version            print version number\n");  
448
449   fprintf(f,"\n");
450   fprintf(f,"the backup suffix defaults to %s\n",BACKUP_SUFFIX);
451   fprintf(f,"the block size defaults to %d\n",BLOCK_SIZE);  
452 }
453
454 enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE,
455       OPT_EXCLUDE_FROM,OPT_DELETE,OPT_NUMERIC_IDS,OPT_RSYNC_PATH};
456
457 static char *short_options = "oblLWHpguDCtcahvrRIxnSe:B:z";
458
459 static struct option long_options[] = {
460   {"version",     0,     0,    OPT_VERSION},
461   {"server",      0,     0,    OPT_SERVER},
462   {"sender",      0,     0,    OPT_SENDER},
463   {"delete",      0,     0,    OPT_DELETE},
464   {"numeric-ids", 0,     0,    OPT_NUMERIC_IDS},
465   {"exclude",     1,     0,    OPT_EXCLUDE},
466   {"exclude-from",1,     0,    OPT_EXCLUDE_FROM},
467   {"rsync-path",  1,     0,    OPT_RSYNC_PATH},
468   {"one-file-system",0,  0,    'x'},
469   {"ignore-times",0,     0,    'I'},
470   {"help",        0,     0,    'h'},
471   {"dry-run",     0,     0,    'n'},
472   {"sparse",      0,     0,    'S'},
473   {"cvs-exclude", 0,     0,    'C'},
474   {"archive",     0,     0,    'a'},
475   {"checksum",    0,     0,    'c'},
476   {"backup",      0,     0,    'b'},
477   {"update",      0,     0,    'u'},
478   {"verbose",     0,     0,    'v'},
479   {"recursive",   0,     0,    'r'},
480   {"relative",    0,     0,    'R'},
481   {"devices",     0,     0,    'D'},
482   {"perms",       0,     0,    'p'},
483   {"links",       0,     0,    'l'},
484   {"copy-links",  0,     0,    'L'},
485   {"whole-file",  0,     0,    'W'},
486   {"hard-links",  0,     0,    'H'},
487   {"owner",       0,     0,    'o'},
488   {"group",       0,     0,    'g'},
489   {"times",       0,     0,    't'},
490   {"rsh",         1,     0,    'e'},
491   {"suffix",      1,     0,    OPT_SUFFIX},
492   {"block-size",  1,     0,    'B'},
493   {"compress",    0,     0,    'z'},
494   {0,0,0,0}};
495
496 RETSIGTYPE sigusr1_handler(int val) {
497         exit_cleanup(1);
498 }
499
500 int main(int argc,char *argv[])
501 {
502     int pid, status = 0, status2 = 0;
503     int opt;
504     int option_index;
505     char *shell_cmd = NULL;
506     char *shell_machine = NULL;
507     char *shell_path = NULL;
508     char *shell_user = NULL;
509     char *p;
510     int f_in,f_out;
511     struct file_list *flist;
512     char *local_name = NULL;
513
514 #ifdef SETPGRP_VOID
515     setpgrp();
516 #else
517     setpgrp(0,0);
518 #endif
519     signal(SIGUSR1, sigusr1_handler);
520
521     starttime = time(NULL);
522     am_root = (getuid() == 0);
523
524     /* we set a 0 umask so that correct file permissions can be
525        carried across */
526     orig_umask = umask(0);
527
528     while ((opt = getopt_long(argc, argv, 
529                               short_options, long_options, &option_index)) 
530            != -1) {
531       switch (opt) 
532         {
533         case OPT_VERSION:
534           printf("rsync version %s  protocol version %d\n",
535                  VERSION,PROTOCOL_VERSION);
536           exit_cleanup(0);
537
538         case OPT_SUFFIX:
539           backup_suffix = optarg;
540           break;
541
542         case OPT_RSYNC_PATH:
543           rsync_path = optarg;
544           break;
545
546         case 'I':
547           ignore_times = 1;
548           break;
549
550         case 'x':
551           one_file_system=1;
552           break;
553
554         case OPT_DELETE:
555           delete_mode = 1;
556           break;
557
558         case OPT_NUMERIC_IDS:
559           numeric_ids = 1;
560           break;
561
562         case OPT_EXCLUDE:
563           add_exclude(optarg);
564           break;
565
566         case OPT_EXCLUDE_FROM:
567           add_exclude_file(optarg,1);
568           break;
569
570         case 'h':
571           usage(FINFO);
572           exit_cleanup(0);
573
574         case 'b':
575           make_backups=1;
576           break;
577
578         case 'n':
579           dry_run=1;
580           break;
581
582         case 'S':
583           sparse_files=1;
584           break;
585
586         case 'C':
587           cvs_exclude=1;
588           break;
589
590         case 'u':
591           update_only=1;
592           break;
593
594         case 'l':
595           preserve_links=1;
596           break;
597
598         case 'L':
599           copy_links=1;
600           break;
601
602         case 'W':
603           whole_file=1;
604           break;
605
606         case 'H':
607 #if SUPPORT_HARD_LINKS
608           preserve_hard_links=1;
609 #else 
610           fprintf(FERROR,"ERROR: hard links not supported on this platform\n");
611           exit_cleanup(1);
612 #endif
613           break;
614
615         case 'p':
616           preserve_perms=1;
617           break;
618
619         case 'o':
620           preserve_uid=1;
621           break;
622
623         case 'g':
624           preserve_gid=1;
625           break;
626
627         case 'D':
628           preserve_devices=1;
629           break;
630
631         case 't':
632           preserve_times=1;
633           break;
634
635         case 'c':
636           always_checksum=1;
637           break;
638
639         case 'v':
640           verbose++;
641           break;
642
643         case 'a':
644           recurse=1;
645 #if SUPPORT_LINKS
646           preserve_links=1;
647 #endif
648           preserve_perms=1;
649           preserve_times=1;
650           preserve_gid=1;
651           if (am_root) {
652             preserve_devices=1;
653             preserve_uid=1;
654           }
655           break;
656
657         case OPT_SERVER:
658           am_server = 1;
659           break;
660
661         case OPT_SENDER:
662           if (!am_server) {
663             usage(FERROR);
664             exit_cleanup(1);
665           }
666           sender = 1;
667           break;
668
669         case 'r':
670           recurse = 1;
671           break;
672
673         case 'R':
674           relative_paths = 1;
675           break;
676
677         case 'e':
678           shell_cmd = optarg;
679           break;
680
681         case 'B':
682           block_size = atoi(optarg);
683           break;
684
685         case 'z':
686           do_compression = 1;
687           break;
688
689         default:
690           /* fprintf(FERROR,"bad option -%c\n",opt); */
691           exit_cleanup(1);
692         }
693     }
694
695     while (optind--) {
696       argc--;
697       argv++;
698     }
699
700     signal(SIGCHLD,SIG_IGN);
701     signal(SIGINT,SIGNAL_CAST sig_int);
702     signal(SIGPIPE,SIGNAL_CAST sig_int);
703     signal(SIGHUP,SIGNAL_CAST sig_int);
704
705     if (dry_run)
706       verbose = MAX(verbose,1);
707
708 #ifndef SUPPORT_LINKS
709     if (!am_server && preserve_links) {
710             fprintf(FERROR,"ERROR: symbolic links not supported\n");
711             exit_cleanup(1);
712     }
713 #endif
714
715     if (am_server) {
716       setup_protocol(STDOUT_FILENO,STDIN_FILENO);
717         
718       if (sender) {
719         recv_exclude_list(STDIN_FILENO);
720         if (cvs_exclude)
721           add_cvs_excludes();
722         do_server_sender(argc,argv);
723       } else {
724         do_server_recv(argc,argv);
725       }
726       exit_cleanup(0);
727     }
728
729     if (argc < 2) {
730       usage(FERROR);
731       exit_cleanup(1);
732     }
733
734     p = strchr(argv[0],':');
735
736     if (p) {
737       sender = 0;
738       *p = 0;
739       shell_machine = argv[0];
740       shell_path = p+1;
741       argc--;
742       argv++;
743     } else {
744       sender = 1;
745
746       p = strchr(argv[argc-1],':');
747       if (!p) {
748         local_server = 1;
749       }
750
751       if (local_server) {
752         shell_machine = NULL;
753         shell_path = argv[argc-1];
754       } else {
755         *p = 0;
756         shell_machine = argv[argc-1];
757         shell_path = p+1;
758       }
759       argc--;
760     }
761
762     if (shell_machine) {
763       p = strchr(shell_machine,'@');
764       if (p) {
765         *p = 0;
766         shell_user = shell_machine;
767         shell_machine = p+1;
768       }
769     }
770
771     if (verbose > 3) {
772       fprintf(FERROR,"cmd=%s machine=%s user=%s path=%s\n",
773               shell_cmd?shell_cmd:"",
774               shell_machine?shell_machine:"",
775               shell_user?shell_user:"",
776               shell_path?shell_path:"");
777     }
778     
779     if (!sender && argc != 1) {
780       usage(FERROR);
781       exit_cleanup(1);
782     }
783
784     pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
785
786     setup_protocol(f_out,f_in);
787
788 #if HAVE_SETLINEBUF
789     setlinebuf(FINFO);
790     setlinebuf(FERROR);
791 #endif
792
793     if (verbose > 3) 
794       fprintf(FERROR,"parent=%d child=%d sender=%d recurse=%d\n",
795               (int)getpid(),pid,sender,recurse);
796
797     if (sender) {
798       if (cvs_exclude)
799         add_cvs_excludes();
800       if (delete_mode) 
801         send_exclude_list(f_out);
802       flist = send_file_list(f_out,argc,argv);
803       if (verbose > 3) 
804         fprintf(FERROR,"file list sent\n");
805       send_files(flist,f_out,f_in);
806       if (verbose > 3)
807         fprintf(FERROR,"waiting on %d\n",pid);
808       waitpid(pid, &status, 0);
809       report(-1);
810       exit_cleanup(status);
811     }
812
813     send_exclude_list(f_out);
814
815     flist = recv_file_list(f_in);
816     if (!flist || flist->count == 0) {
817       fprintf(FERROR,"nothing to do\n");
818       exit_cleanup(0);
819     }
820
821     local_name = get_local_name(flist,argv[0]);
822
823     status2 = do_recv(f_in,f_out,flist,local_name);
824
825     report(f_in);
826
827     waitpid(pid, &status, 0);
828
829     return status | status2;
830 }
831