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