- check for setlinebuf() in autoconf. Apparently HPUX doesn't have it
[rsync/rsync.git] / main.c
diff --git a/main.c b/main.c
index 7cef434..d289a58 100644 (file)
--- a/main.c
+++ b/main.c
@@ -47,6 +47,9 @@ int one_file_system=0;
 int remote_version=0;
 int sparse_files=0;
 int do_compression=0;
+int am_root=0;
+int orig_umask=0;
+int relative_paths=0;
 
 extern int csum_length;
 
@@ -132,6 +135,8 @@ static void server_options(char **args,int *argc)
     argstr[x++] = 'C';
   if (ignore_times)
     argstr[x++] = 'I';
+  if (relative_paths)
+    argstr[x++] = 'R';
   if (one_file_system)
     argstr[x++] = 'x';
   if (sparse_files)
@@ -174,11 +179,20 @@ int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
       args[argc++] = tok;
     }
 
+#if HAVE_REMSH
+    /* remsh (on HPUX) takes the arguments the other way around */
+    args[argc++] = machine;
+    if (user) {
+      args[argc++] = "-l";
+      args[argc++] = user;
+    }
+#else
     if (user) {
       args[argc++] = "-l";
       args[argc++] = user;
     }
     args[argc++] = machine;
+#endif
   }
 
   args[argc++] = rsync_path;
@@ -188,9 +202,12 @@ int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
   if (path && *path) {
     char *dir = strdup(path);
     p = strrchr(dir,'/');
-    if (p) {
+    if (p && !relative_paths) {
       *p = 0;
-      args[argc++] = dir;
+      if (!dir[0])
+       args[argc++] = "/";
+      else
+       args[argc++] = dir;
       p++;
     } else {
       args[argc++] = ".";
@@ -226,7 +243,7 @@ static char *get_local_name(struct file_list *flist,char *name)
   if (stat(name,&st) == 0) {
     if (S_ISDIR(st.st_mode)) {
       if (chdir(name) != 0) {
-       fprintf(FERROR,"chdir %s : %s\n",name,strerror(errno));
+       fprintf(FERROR,"chdir %s : %s (1)\n",name,strerror(errno));
        exit_cleanup(1);
       }
       return NULL;
@@ -244,15 +261,15 @@ static char *get_local_name(struct file_list *flist,char *name)
   if (!name) 
     return NULL;
 
-  if (mkdir(name,0777) != 0) {
-    fprintf(FERROR,"mkdir %s : %s\n",name,strerror(errno));
+  if (mkdir(name,0777 & ~orig_umask) != 0) {
+    fprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
     exit_cleanup(1);
   } else {
     fprintf(FINFO,"created directory %s\n",name);
   }
 
   if (chdir(name) != 0) {
-    fprintf(FERROR,"chdir %s : %s\n",name,strerror(errno));
+    fprintf(FERROR,"chdir %s : %s (2)\n",name,strerror(errno));
     exit_cleanup(1);
   }
 
@@ -271,8 +288,8 @@ void do_server_sender(int argc,char *argv[])
   if (verbose > 2)
     fprintf(FERROR,"server_sender starting pid=%d\n",(int)getpid());
   
-  if (chdir(dir) != 0) {
-    fprintf(FERROR,"chdir %s: %s\n",dir,strerror(errno));
+  if (!relative_paths && chdir(dir) != 0) {
+    fprintf(FERROR,"chdir %s: %s (3)\n",dir,strerror(errno));
     exit_cleanup(1);
   }
   argc--;
@@ -280,6 +297,8 @@ void do_server_sender(int argc,char *argv[])
   
   if (strcmp(dir,".")) {
     int l = strlen(dir);
+    if (strcmp(dir,"/") == 0) 
+      l = 0;
     for (i=0;i<argc;i++)
       argv[i] += l+1;
   }
@@ -291,7 +310,7 @@ void do_server_sender(int argc,char *argv[])
   }
     
 
-  flist = send_file_list(STDOUT_FILENO,recurse,argc,argv);
+  flist = send_file_list(STDOUT_FILENO,argc,argv);
   send_files(flist,STDOUT_FILENO,STDIN_FILENO);
   report(STDOUT_FILENO);
   exit_cleanup(0);
@@ -315,8 +334,6 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
 
   if ((pid=fork()) == 0) {
     recv_files(f_in,flist,local_name,recv_pipe[1]);
-    if (preserve_hard_links)
-      do_hard_links(flist);
     if (verbose > 2)
       fprintf(FERROR,"receiver read %d\n",read_total());
     exit_cleanup(0);
@@ -345,7 +362,7 @@ void do_server_recv(int argc,char *argv[])
     argc--;
     argv++;
     if (chdir(dir) != 0) {
-      fprintf(FERROR,"chdir %s : %s\n",dir,strerror(errno));
+      fprintf(FERROR,"chdir %s : %s (4)\n",dir,strerror(errno));
       exit_cleanup(1);
     }    
   }
@@ -383,6 +400,7 @@ static void usage(FILE *f)
   fprintf(f,"-c, --checksum           always checksum\n");
   fprintf(f,"-a, --archive            archive mode (same as -rlptDog)\n");
   fprintf(f,"-r, --recursive          recurse into directories\n");
+  fprintf(f,"-R, --relative           use relative path names\n");
   fprintf(f,"-b, --backup             make backups (default ~ extension)\n");
   fprintf(f,"-u, --update             update only (don't overwrite newer files)\n");
   fprintf(f,"-l, --links              preserve soft links\n");
@@ -405,7 +423,6 @@ static void usage(FILE *f)
   fprintf(f,"    --exclude FILE       exclude file FILE\n");
   fprintf(f,"    --exclude-from FILE  exclude files listed in FILE\n");
   fprintf(f,"    --suffix SUFFIX      override backup suffix\n");  
-  fprintf(f,"    --csum-length LENGTH set the checksum length\n");  
   fprintf(f,"    --version            print version number\n");  
 
   fprintf(f,"\n");
@@ -416,7 +433,7 @@ static void usage(FILE *f)
 enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE,
       OPT_EXCLUDE_FROM,OPT_DELETE,OPT_RSYNC_PATH};
 
-static char *short_options = "oblHpguDCtcahvrIxnSe:B:z";
+static char *short_options = "oblHpguDCtcahvrRIxnSe:B:z";
 
 static struct option long_options[] = {
   {"version",     0,     0,    OPT_VERSION},
@@ -438,6 +455,7 @@ static struct option long_options[] = {
   {"update",      0,     0,    'u'},
   {"verbose",     0,     0,    'v'},
   {"recursive",   0,     0,    'r'},
+  {"relative",    0,     0,    'R'},
   {"devices",     0,     0,    'D'},
   {"perms",       0,     0,    'p'},
   {"links",       0,     0,    'l'},
@@ -453,7 +471,7 @@ static struct option long_options[] = {
 
 int main(int argc,char *argv[])
 {
-    int pid, status, status2;
+    int pid, status = 0, status2 = 0;
     int opt;
     int option_index;
     char *shell_cmd = NULL;
@@ -466,6 +484,11 @@ int main(int argc,char *argv[])
     char *local_name = NULL;
 
     starttime = time(NULL);
+    am_root = (getuid() == 0);
+
+    /* we set a 0 umask so that correct file permissions can be
+       carried across */
+    orig_umask = umask(0);
 
     while ((opt = getopt_long(argc, argv, 
                              short_options, long_options, &option_index)) 
@@ -546,12 +569,7 @@ int main(int argc,char *argv[])
          break;
 
        case 'o':
-         if (getuid() == 0) {
-           preserve_uid=1;
-         } else {
-           fprintf(FERROR,"-o only allowed for root\n");
-           exit_cleanup(1);
-         }
+         preserve_uid=1;
          break;
 
        case 'g':
@@ -559,12 +577,7 @@ int main(int argc,char *argv[])
          break;
 
        case 'D':
-         if (getuid() == 0) {
-           preserve_devices=1;
-         } else {
-           fprintf(FERROR,"-D only allowed for root\n");
-           exit_cleanup(1);
-         }
+         preserve_devices=1;
          break;
 
        case 't':
@@ -587,10 +600,10 @@ int main(int argc,char *argv[])
          preserve_perms=1;
          preserve_times=1;
          preserve_gid=1;
-         if (getuid() == 0) {
+         if (am_root) {
            preserve_devices=1;
            preserve_uid=1;
-         }         
+         }
          break;
 
        case OPT_SERVER:
@@ -609,6 +622,10 @@ int main(int argc,char *argv[])
          recurse = 1;
          break;
 
+       case 'R':
+         relative_paths = 1;
+         break;
+
        case 'e':
          shell_cmd = optarg;
          break;
@@ -713,6 +730,11 @@ int main(int argc,char *argv[])
 
     setup_protocol(f_out,f_in);
 
+#if HAVE_SETLINEBUF
+    setlinebuf(FINFO);
+    setlinebuf(FERROR);
+#endif
+
     if (verbose > 3) 
       fprintf(FERROR,"parent=%d child=%d sender=%d recurse=%d\n",
              (int)getpid(),pid,sender,recurse);
@@ -722,7 +744,7 @@ int main(int argc,char *argv[])
        add_cvs_excludes();
       if (delete_mode) 
        send_exclude_list(f_out);
-      flist = send_file_list(f_out,recurse,argc,argv);
+      flist = send_file_list(f_out,argc,argv);
       if (verbose > 3) 
        fprintf(FERROR,"file list sent\n");
       send_files(flist,f_out,f_in);