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 63ff423..92d9b2c 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 179e7e7..138894f 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 056863f..fa4fe0f 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 09363ab..434defd 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 e3f9c5c..8c2fae4 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 6470bf9..11e4a9d 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;
+}