replaced chdir and getcwd calls with push_dir/pop_dir functions. These
authorAndrew Tridgell <tridge@samba.org>
Fri, 29 May 1998 14:36:39 +0000 (14:36 +0000)
committerAndrew Tridgell <tridge@samba.org>
Fri, 29 May 1998 14:36:39 +0000 (14:36 +0000)
are faster and don't cause problems in a chrooted environment on any
systems.

clientserver.c
flist.c
main.c
options.c
rsync.yo
util.c

index 63ff4230a2ab1196443011a89f2e52774799a008..92d9b2c0cb86a8db7c490e72287d6e49862772d8 100644 (file)
@@ -362,6 +362,11 @@ int daemon_main(void)
 {
        extern char *config_file;
 
+       /* this ensures that we don't call getcwd after the chroot,
+           which doesn't work on platforms that use popen("pwd","r")
+           for getcwd */
+       push_dir("/", 0);
+
        if (is_a_socket(STDIN_FILENO)) {
                /* we are running via inetd */
                return start_daemon(STDIN_FILENO);
diff --git a/flist.c b/flist.c
index 179e7e7ecde080f6491eb6f7fe0525d8c24d2156..138894f775cb4fbbc3355e48917048d6c8915c3b 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -90,49 +90,6 @@ static void send_directory(int f,struct file_list *flist,char *dir);
 
 static char *flist_dir;
 
-static void clean_fname(char *name)
-{
-  char *p;
-  int l;
-  int modified = 1;
-
-  if (!name) return;
-
-  while (modified) {
-    modified = 0;
-
-    if ((p=strstr(name,"/./"))) {
-      modified = 1;
-      while (*p) {
-       p[0] = p[2];
-       p++;
-      }
-    }
-
-    if ((p=strstr(name,"//"))) {
-      modified = 1;
-      while (*p) {
-       p[0] = p[1];
-       p++;
-      }
-    }
-
-    if (strncmp(p=name,"./",2) == 0) {      
-      modified = 1;
-      do {
-       p[0] = p[2];
-      } while (*p++);
-    }
-
-    l = strlen(p=name);
-    if (l > 1 && p[l-1] == '/') {
-      modified = 1;
-      p[l-1] = 0;
-    }
-  }
-}
-
-
 
 void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
 {
@@ -566,7 +523,6 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
        int i,l;
        STRUCT_STAT st;
        char *p,*dir;
-       char dbuf[MAXPATHLEN];
        char lastpath[MAXPATHLEN]="";
        struct file_list *flist;
 
@@ -646,24 +602,23 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
                        fname = ".";
                
                if (dir && *dir) {
-                       if (getcwd(dbuf,MAXPATHLEN-1) == NULL) {
-                               rprintf(FERROR,"getwd : %s\n",strerror(errno));
-                               exit_cleanup(1);
-                       }
-                       if (chdir(dir) != 0) {
+                       char *olddir = push_dir(dir, 1);
+
+                       if (!olddir) {
                                io_error=1;
-                               rprintf(FERROR,"chdir %s : %s\n",
+                               rprintf(FERROR,"push_dir %s : %s\n",
                                        dir,strerror(errno));
                                continue;
                        }
+
                        flist_dir = dir;
                        if (one_file_system)
                                set_filesystem(fname);
                        send_file_name(f,flist,fname,recurse,FLAG_DELETE);
                        flist_dir = NULL;
-                       if (chdir(dbuf) != 0) {
-                               rprintf(FERROR,"chdir %s : %s\n",
-                                       dbuf,strerror(errno));
+                       if (pop_dir(olddir) != 0) {
+                               rprintf(FERROR,"pop_dir %s : %s\n",
+                                       dir,strerror(errno));
                                exit_cleanup(1);
                        }
                        continue;
diff --git a/main.c b/main.c
index 056863ff3694d28a6a5b20efa819a49d8a7e3589..fa4fe0f7d7d005fc4338af0e94986af8f65b51f8 100644 (file)
--- a/main.c
+++ b/main.c
@@ -149,8 +149,8 @@ static char *get_local_name(struct file_list *flist,char *name)
 
        if (do_stat(name,&st) == 0) {
                if (S_ISDIR(st.st_mode)) {
-                       if (chdir(name) != 0) {
-                               rprintf(FERROR,"chdir %s : %s (1)\n",
+                       if (!push_dir(name, 0)) {
+                               rprintf(FERROR,"push_dir %s : %s (1)\n",
                                        name,strerror(errno));
                                exit_cleanup(1);
                        }
@@ -176,8 +176,9 @@ static char *get_local_name(struct file_list *flist,char *name)
                rprintf(FINFO,"created directory %s\n",name);
        }
 
-       if (chdir(name) != 0) {
-               rprintf(FERROR,"chdir %s : %s (2)\n",name,strerror(errno));
+       if (!push_dir(name, 0)) {
+               rprintf(FERROR,"push_dir %s : %s (2)\n",
+                       name,strerror(errno));
                exit_cleanup(1);
        }
 
@@ -198,8 +199,8 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
        if (verbose > 2)
                rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
   
-       if (!relative_paths && chdir(dir) != 0) {
-               rprintf(FERROR,"chdir %s: %s (3)\n",dir,strerror(errno));
+       if (!relative_paths && !push_dir(dir, 0)) {
+               rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
                exit_cleanup(1);
        }
        argc--;
@@ -289,8 +290,8 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
                dir = argv[0];
                argc--;
                argv++;
-               if (!am_daemon && chdir(dir) != 0) {
-                       rprintf(FERROR,"chdir %s : %s (4)\n",
+               if (!am_daemon && !push_dir(dir, 0)) {
+                       rprintf(FERROR,"push_dir %s : %s (4)\n",
                                dir,strerror(errno));
                        exit_cleanup(1);
                }    
index 09363abf355ee3e1d2f2a76cd0ae67251543bf57..434defd0ae284970facdea5e1c2573d4521d96f2 100644 (file)
--- a/options.c
+++ b/options.c
@@ -79,7 +79,7 @@ void usage(int F)
   rprintf(F,"Options:\n");
   rprintf(F,"-v, --verbose            increase verbosity\n");
   rprintf(F,"-c, --checksum           always checksum\n");
-  rprintf(F,"-a, --archive            archive mode (same as -rlptDog)\n");
+  rprintf(F,"-a, --archive            archive mode\n");
   rprintf(F,"-r, --recursive          recurse into directories\n");
   rprintf(F,"-R, --relative           use relative path names\n");
   rprintf(F,"-b, --backup             make backups (default ~ extension)\n");
index e3f9c5c3014ccd680d438086ce041c721b26d6c0..8c2fae459c7c215d64304ed07f1f5e89c389b8f9 100644 (file)
--- a/rsync.yo
+++ b/rsync.yo
@@ -217,9 +217,12 @@ explicitly checked on the receiver and any files of the same name
 which already exist and have the same checksum and size on the
 receiver are skipped.  This option can be quite slow.
 
-dit(bf(-a, --archive)) This is equivalent to -rlptDog. It is a quick way
+dit(bf(-a, --archive)) This is equivalent to -rlptDg. It is a quick way
 of saying I want recursion and want to preserve everything.
 
+Note: if the user launching rsync is root then the -o option (preserve
+uid) is also implied.
+
 dit(bf(-r, --recursive)) This tells rsync to copy directories recursively
 
 dit(bf(-R, --relative)) Use relative paths. This means that the full path
diff --git a/util.c b/util.c
index 6470bf97e0887bfa4cde3ccad4c2bc6ae0c0f297..11e4a9d9b7c1012c79fd23880839f9c240e06046 100644 (file)
--- a/util.c
+++ b/util.c
@@ -559,3 +559,97 @@ void *Realloc(void *p, int size)
        if (!p) return (void *)malloc(size);
        return (void *)realloc(p, size);
 }
+
+
+void clean_fname(char *name)
+{
+       char *p;
+       int l;
+       int modified = 1;
+
+       if (!name) return;
+
+       while (modified) {
+               modified = 0;
+
+               if ((p=strstr(name,"/./"))) {
+                       modified = 1;
+                       while (*p) {
+                               p[0] = p[2];
+                               p++;
+                       }
+               }
+
+               if ((p=strstr(name,"//"))) {
+                       modified = 1;
+                       while (*p) {
+                               p[0] = p[1];
+                               p++;
+                       }
+               }
+
+               if (strncmp(p=name,"./",2) == 0) {      
+                       modified = 1;
+                       do {
+                               p[0] = p[2];
+                       } while (*p++);
+               }
+
+               l = strlen(p=name);
+               if (l > 1 && p[l-1] == '/') {
+                       modified = 1;
+                       p[l-1] = 0;
+               }
+       }
+}
+
+
+static char curr_dir[MAXPATHLEN];
+
+/* like chdir() but can be reversed with pop_dir() if save is set. It
+   is also much faster as it remembers where we have been */
+char *push_dir(char *dir, int save)
+{
+       char *ret = curr_dir;
+       static int initialised;
+
+       if (!initialised) {
+               initialised = 1;
+               getcwd(curr_dir, sizeof(curr_dir)-1);
+       }
+
+       if (chdir(dir)) return NULL;
+
+       if (save) {
+               ret = strdup(curr_dir);
+       }
+
+       if (*dir == '/') {
+               strlcpy(curr_dir, dir, sizeof(curr_dir)-1);
+       } else {
+               strlcat(curr_dir,"/", sizeof(curr_dir)-1);
+               strlcat(curr_dir,dir, sizeof(curr_dir)-1);
+       }
+
+       clean_fname(curr_dir);
+
+       return ret;
+}
+
+/* reverse a push_dir call */
+int pop_dir(char *dir)
+{
+       int ret;
+
+       ret = chdir(dir);
+       if (ret) {
+               free(dir);
+               return ret;
+       }
+
+       strlcpy(curr_dir, dir, sizeof(curr_dir)-1);
+
+       free(dir);
+
+       return 0;
+}